Version 2.3.2-dev.0.1

Merge commit '55d3bbf13f81552c33fe0dc6a9557233b85b8f97' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4de047e..4221276 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,70 @@
+## 2.3.2-dev.0.1
+(Add new changes here, and they will be copied to the change section for the
+ next dev version)
+
+### Language
+
+*   **Breaking change:** Covariance of type variables used in super-interfaces
+    is now enforced (issue [35097][]).  For example, the following code was
+    previously accepted and will now be rejected:
+
+```dart
+class A<X> {};
+class B<X> extends A<void Function(X)> {};
+```
+
+* The identifier `async` can now be used in asynchronous and generator
+  functions.
+
+[35097]: https://github.com/dart-lang/sdk/issues/35097
+
+### Core libraries
+
+#### `dart:developer`
+* Exposed `result`, `errorCode` and `errorDetail` getters in
+  `ServiceExtensionResponse` to allow for better debugging of VM service
+  extension RPC results.
+
+#### `dart:io`
+
+* Fixed `Cookie` class interoperability with certain websites by allowing the
+  cookie values to be the empty string (Issue [35804][]) and not stripping
+  double quotes from the value (Issue [33327][]) in accordance with RFC 6265.
+
+  [33327]: https://github.com/dart-lang/sdk/issues/33327
+  [35804]: https://github.com/dart-lang/sdk/issues/35804
+
+* The `HttpClientResponse` interface has been extended with the addition of a
+  new `compressionState` getter, which specifies whether the body of a
+  response was compressed when it was received and whether it has been
+  automatically uncompressed via `HttpClient.autoUncompress` (Issue [36971][]).
+
+  As part of this change, a corresponding new enum was added to `dart:io`:
+  `HttpClientResponseCompressionState`.
+
+  [36971]: https://github.com/dart-lang/sdk/issues/36971
+
+  * **Breaking change**: For those implementing the `HttpClientResponse`
+    interface, this is a breaking change, as implementing classes will need to
+    implement the new getter.
+
+### Dart VM
+
+### Tools
+
+#### Linter
+
+The Linter was updated to `0.1.90`, which includes the following changes:
+
+* fixed null-reference in `unrelated_type_equality_checks`
+* new lint: `unsafe_html`
+
+#### Pub
+
+* `pub publish` will no longer warn about missing dependencies for import
+   statements in `example/`.
+* OAuth2 authentication will explicitely ask for the `openid` scope.
+
 ## 2.3.2-dev.0.0
 
 ### Tools
@@ -285,7 +352,7 @@
   `.g.dart`, etc.).
 *   Fixed false positives in `unnecessary_parenthesis`.
 
-#### Pub client
+#### Pub
 
 *   Added a CHANGELOG validator that complains if you `pub publish` without
     mentioning the current version.
diff --git a/DEPS b/DEPS
index e9f2353..efa5353 100644
--- a/DEPS
+++ b/DEPS
@@ -96,7 +96,7 @@
   "intl_tag": "0.15.7",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "2.0.9",
-  "linter_tag": "0.1.89",
+  "linter_tag": "0.1.90",
   "logging_tag": "0.11.3+2",
   "markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
   "markdown_tag": "2.0.3",
@@ -113,7 +113,7 @@
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_tag": "1.3.6",
   "protobuf_rev": "7d34c9e4e552a4f66acce32e4344ae27756a1949",
-  "pub_rev": "8c363fe26f059c3063f1129adbb3c4e22a8ce954",
+  "pub_rev": "ecd5b413271f2699f8cd9e23aa4eebb5030c964f",
   "pub_semver_tag": "1.4.2",
   "quiver-dart_tag": "2.0.0+1",
   "resource_rev": "2.1.5",
@@ -133,7 +133,7 @@
   "test_process_tag": "1.0.3",
   "term_glyph_tag": "1.0.1",
   "test_reflective_loader_tag": "0.1.8",
-  "test_tag": "test-v1.6.1",
+  "test_tag": "test-v1.6.4",
   "typed_data_tag": "1.1.6",
   "unittest_rev": "2b8375bc98bb9dc81c539c91aaea6adce12e1072",
   "usage_tag": "3.4.0",
@@ -168,7 +168,6 @@
       }],
       "dep_type": "cipd",
   },
-
   Var("dart_root") + "/tests/co19_2/src": {
       "packages": [{
           "package": "dart/third_party/co19",
@@ -176,11 +175,16 @@
       }],
       "dep_type": "cipd",
   },
-
   Var("dart_root") + "/third_party/markupsafe":
       Var("chromium_git") + "/chromium/src/third_party/markupsafe.git" +
       "@" + Var("markupsafe_rev"),
-
+  Var("dart_root") + "/third_party/babel": {
+      "packages": [{
+          "package": "dart/third_party/babel",
+          "version": "version:7.4.5",
+      }],
+      "dep_type": "cipd",
+  },
   Var("dart_root") + "/third_party/zlib":
       Var("chromium_git") + "/chromium/src/third_party/zlib.git" +
       "@" + Var("zlib_rev"),
diff --git a/README.md b/README.md
index 51f129a..195667d 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,43 @@
 # Dart
 
-[Dart][website] is an open-source, scalable programming language, with robust
-libraries and runtimes, for building web, server, and mobile apps.
+## A client-optimized language for fast apps on any platform
+
+Dart is:
+
+  * **Optimized for UI**:
+  Develop with a programming language specialized around the needs of user interface creation
+  
+  * **Productive**:
+  Make changes iteratively: use hot reload to see the result instantly in your running app
+  
+  * **Fast on all platforms**:
+  Compile to ARM & x64 machine code for mobile,  desktop, and backend. Or compile to JavaScript for the web
+
+Dart has flexible compiler technology lets you run Dart code in different ways,
+depending on your target platform and goals:
+
+  * **Dart Native**: For programs targeting devices (mobile, desktop, server, and more),
+  Dart Native includes both a Dart VM with JIT (just-in-time) compilation and an
+  AOT (ahead-of-time) compiler for producing machine code.
+  
+  * **Dart Web**: For programs targeting the web, Dart Web includes both a development time
+  compiler (dartdevc) and a production time compiler (dart2js).  
+
+![Dart platforms illustration](https://dart.dev/assets/platforms-7f4d540acf9fe801b456ad74f9f855230a385014d05d9f5997c878b889a67a0f.svg)
+
+## License & patents
+
+Dart is free and open source.
+
+See [LICENSE][license] and [PATENTS][patents].
 
 ## Using Dart
 
-Visit the [dartlang.org][website] to learn more about the
+Visit the [dart.dev][website] to learn more about the
 [language][lang], [tools][tools],
 [getting started][codelab], and more.
 
-Browse [pub.dartlang.org][pubsite] for more packages and libraries contributed
+Browse [pub.dev][pubsite] for more packages and libraries contributed
 by the community and the Dart team.
 
 ## Building Dart
@@ -26,11 +54,7 @@
 
 You can also contribute patches, as described in [Contributing][contrib].
 
-## License & patents
-
-See [LICENSE][license] and [PATENTS][patents].
-
-[website]: https://www.dartlang.org
+[website]: https://dart.dev
 [license]: https://github.com/dart-lang/sdk/blob/master/LICENSE
 [repo]: https://github.com/dart-lang/sdk
 [lang]: https://www.dartlang.org/docs/dart-up-and-running/ch02.html
@@ -38,6 +62,5 @@
 [codelab]: https://www.dartlang.org/codelabs/darrrt/
 [dartbug]: http://dartbug.com
 [contrib]: https://github.com/dart-lang/sdk/wiki/Contributing
-[pubsite]: https://pub.dartlang.org
+[pubsite]: https://pub.dev
 [patents]: https://github.com/dart-lang/sdk/blob/master/PATENTS
-
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index baa7bc3..f073da1 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -433,8 +433,10 @@
     ]
   }
 
-  # Android standard library setup.
-  if (is_android) {
+  if (is_linux) {
+    libs += [ "dl" ]
+  } else if (is_android) {
+    # Android standard library setup.
     if (is_clang) {
       # Work around incompatibilities between bionic and clang headers.
       defines += [ "__compiler_offsetof=__builtin_offsetof" ]
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 918ff0b..9a5386a 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -109,7 +109,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  1.26.1
+  1.27.0
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -1455,6 +1455,7 @@
   
   
   
+  
 <h3>Requests</h3><dl><dt class="request"><a name="request_completion.getSuggestions">completion.getSuggestions</a></dt><dd><div class="box"><pre>request: {
   "id": String
   "method": "completion.getSuggestions"
@@ -1612,6 +1613,7 @@
     "<b>replacementLength</b>": int
     "<b>results</b>": List&lt;<a href="#type_CompletionSuggestion">CompletionSuggestion</a>&gt;
     "<b>isLast</b>": bool
+    "<b>libraryFile</b>": <span style="color:#999999">optional</span> <a href="#type_FilePath">FilePath</a>
     "<b>includedSuggestionSets</b>": <span style="color:#999999">optional</span> List&lt;<a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a>&gt;
     "<b>includedElementKinds</b>": <span style="color:#999999">optional</span> List&lt;<a href="#type_ElementKind">ElementKind</a>&gt;
     "<b>includedSuggestionRelevanceTags</b>": <span style="color:#999999">optional</span> List&lt;<a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a>&gt;
@@ -1663,6 +1665,16 @@
           True if this is that last set of results that will be
           returned for the indicated completion.
         </p>
+      </dd><dt class="field"><b>libraryFile: <a href="#type_FilePath">FilePath</a><span style="color:#999999"> (optional)</span></b></dt><dd>
+        
+        <p>
+          The library file that contains the file where completion was
+          requested. The client might use it for example together with the
+          <tt>existingImports</tt> notification to filter out available
+          suggestions. If there were changes to existing imports in the library,
+          the corresponding <tt>existingImports</tt> notification will be sent
+          before the completion notification.
+        </p>
       </dd><dt class="field"><b>includedSuggestionSets: List&lt;<a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a>&gt;<span style="color:#999999"> (optional)</span></b></dt><dd>
         
         <p>
@@ -1720,6 +1732,29 @@
         <p>
           A list of library ids that no longer apply.
         </p>
+      </dd></dl></dd><dt class="notification"><a name="notification_completion.existingImports">completion.existingImports</a></dt><dd><div class="box"><pre>notification: {
+  "event": "completion.existingImports"
+  "params": {
+    "<b>file</b>": <a href="#type_FilePath">FilePath</a>
+    "<b>imports</b>": <a href="#type_ExistingImports">ExistingImports</a>
+  }
+}</pre></div>
+    <p>
+      Reports existing imports in a library. This notification may be sent
+      multiple times for a library. When a notification is processed, clients
+      should replace any previous information for the library.
+    </p>
+    
+  <h4>parameters:</h4><dl><dt class="field"><b>file: <a href="#type_FilePath">FilePath</a></b></dt><dd>
+        
+        <p>
+          The defining file of the library.
+        </p>
+      </dd><dt class="field"><b>imports: <a href="#type_ExistingImports">ExistingImports</a></b></dt><dd>
+        
+        <p>
+          The existing imports in the library.
+        </p>
       </dd></dl></dd></dl>
 <h2 class="domain"><a name="domain_search">search domain</a></h2>
   <p>
@@ -2833,6 +2868,9 @@
   
   
   
+  
+  
+  
 <dl><dt class="typeDefinition"><a name="type_AddContentOverlay">AddContentOverlay: object</a></dt><dd>
     <p>
       A directive to begin overlaying the contents of a file. The supplied
@@ -3182,11 +3220,15 @@
   <dl><dt class="value">AVAILABLE_SUGGESTION_SETS</dt><dd>
         
         <p>
-          The client will receive notifications once subscribed with completion suggestion sets from
-          the libraries of interest. The client should keep an up-to-date record of these in
+          The client will receive <tt>availableSuggestions</tt> notifications
+          once subscribed with completion suggestion sets from the libraries of
+          interest. The client should keep an up-to-date record of these in
           memory so that it will be able to union these candidates with other
           completion suggestions when applicable at completion time.
         </p>
+        <p>
+          The client will also receive <tt>existingImports</tt> notifications.
+        </p>
       </dd></dl></dd><dt class="typeDefinition"><a name="type_CompletionSuggestion">CompletionSuggestion: object</a></dt><dd>
     <p>
       A suggestion for how to complete partially entered text. Many of the
@@ -3602,7 +3644,40 @@
       domain.
     </p>
     
-  <dl><dt class="value">LAUNCH_DATA</dt></dl></dd><dt class="typeDefinition"><a name="type_FileKind">FileKind: String</a></dt><dd>
+  <dl><dt class="value">LAUNCH_DATA</dt></dl></dd><dt class="typeDefinition"><a name="type_ExistingImport">ExistingImport: object</a></dt><dd>
+    <p>
+      Information about an existing import, with elements that it provides.
+    </p>
+    
+  <dl><dt class="field"><b>uri: int</b></dt><dd>
+        
+        <p>
+          The URI of the imported library.
+          It is an index in the <tt>strings</tt> field, in the enclosing
+          <tt>ExistingImports</tt> and its <tt>ImportedElementSet</tt> object.
+        </p>
+      </dd><dt class="field"><b>elements: List&lt;int&gt;</b></dt><dd>
+        
+        <p>
+          The list of indexes of elements, in the enclosing
+          <tt>ExistingImports</tt> object.
+        </p>
+      </dd></dl></dd><dt class="typeDefinition"><a name="type_ExistingImports">ExistingImports: object</a></dt><dd>
+    <p>
+      Information about all existing imports in a library.
+    </p>
+    
+  <dl><dt class="field"><b>elements: <a href="#type_ImportedElementSet">ImportedElementSet</a></b></dt><dd>
+        
+        <p>
+          The set of all unique imported elements for all imports.
+        </p>
+      </dd><dt class="field"><b>imports: List&lt;<a href="#type_ExistingImport">ExistingImport</a>&gt;</b></dt><dd>
+        
+        <p>
+          The list of imports in the library.
+        </p>
+      </dd></dl></dd><dt class="typeDefinition"><a name="type_FileKind">FileKind: String</a></dt><dd>
     <p>
       An enumeration of the kinds of files.
     </p>
@@ -3851,10 +3926,10 @@
       </dd><dt class="field"><b>containingLibraryName: String<span style="color:#999999"> (optional)</span></b></dt><dd>
         
         <p>
-          The name of the library in which the referenced element is
-          declared. This data is omitted if there is no referenced
-          element, or if the element is declared inside an HTML
-          file.
+          The URI of the containing library, examples here include
+          "dart:core", "package:.." and file uris represented by the
+          path on disk, "/..". The data is omitted if the element is
+          declared inside an HTML file.
         </p>
       </dd><dt class="field"><b>containingClassDescription: String<span style="color:#999999"> (optional)</span></b></dt><dd>
         
@@ -3945,6 +4020,30 @@
         <p>
           The length of the name of the implemented member.
         </p>
+      </dd></dl></dd><dt class="typeDefinition"><a name="type_ImportedElementSet">ImportedElementSet: object</a></dt><dd>
+    <p>
+      The set of top-level elements encoded as pairs of the defining library
+      URI and the name, and stored in the parallel lists <tt>elementUris</tt>
+      and <tt>elementNames</tt>.
+    </p>
+    
+  <dl><dt class="field"><b>strings: List&lt;String&gt;</b></dt><dd>
+        
+        <p>
+          The list of unique strings in this object.
+        </p>
+      </dd><dt class="field"><b>uris: List&lt;int&gt;</b></dt><dd>
+        
+        <p>
+          The library URI part of the element.
+          It is an index in the <tt>strings</tt> field.
+        </p>
+      </dd><dt class="field"><b>names: List&lt;int&gt;</b></dt><dd>
+        
+        <p>
+          The name part of a the element.
+          It is an index in the <tt>strings</tt> field.
+        </p>
       </dd></dl></dd><dt class="typeDefinition"><a name="type_ImportedElements">ImportedElements: object</a></dt><dd>
     <p>
       A description of the elements that are referenced in a region of a file
@@ -5430,7 +5529,7 @@
   TODO: TBD
 </p>
 <h2 class="domain"><a name="index">Index</a></h2>
-<h3>Domains</h3><h4>server (<a href="#domain_server">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_server.getVersion">getVersion</a></li><li><a href="#request_server.shutdown">shutdown</a></li><li><a href="#request_server.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_server.connected">connected</a></li><li><a href="#notification_server.error">error</a></li><li><a href="#notification_server.status">status</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getErrors">getErrors</a></li><li><a href="#request_analysis.getHover">getHover</a></li><li><a href="#request_analysis.getLibraryDependencies">getLibraryDependencies</a></li><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.getReachableSources">getReachableSources</a></li><li><a href="#request_analysis.reanalyze">reanalyze</a></li><li><a href="#request_analysis.setAnalysisRoots">setAnalysisRoots</a></li><li><a href="#request_analysis.setGeneralSubscriptions">setGeneralSubscriptions</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li><li><a href="#request_analysis.updateOptions">updateOptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.analyzedFiles">analyzedFiles</a></li><li><a href="#notification_analysis.closingLabels">closingLabels</a></li><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.flushResults">flushResults</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.implemented">implemented</a></li><li><a href="#notification_analysis.invalidate">invalidate</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li><li><a href="#notification_analysis.overrides">overrides</a></li></ul></div></div><h4>completion (<a href="#domain_completion">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li><li><a href="#request_completion.setSubscriptions">setSubscriptions</a></li><li><a href="#request_completion.registerLibraryPaths">registerLibraryPaths</a></li><li><a href="#request_completion.getSuggestionDetails">getSuggestionDetails</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</a></li><li><a href="#notification_completion.availableSuggestions">availableSuggestions</a></li></ul></div></div><h4>search (<a href="#domain_search">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_search.findElementReferences">findElementReferences</a></li><li><a href="#request_search.findMemberDeclarations">findMemberDeclarations</a></li><li><a href="#request_search.findMemberReferences">findMemberReferences</a></li><li><a href="#request_search.findTopLevelDeclarations">findTopLevelDeclarations</a></li><li><a href="#request_search.getTypeHierarchy">getTypeHierarchy</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_search.results">results</a></li></ul></div></div><h4>edit (<a href="#domain_edit">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.format">format</a></li><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getAvailableRefactorings">getAvailableRefactorings</a></li><li><a href="#request_edit.getFixes">getFixes</a></li><li><a href="#request_edit.getRefactoring">getRefactoring</a></li><li><a href="#request_edit.sortMembers">sortMembers</a></li><li><a href="#request_edit.organizeDirectives">organizeDirectives</a></li></ul></div><h4>execution (<a href="#domain_execution">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_execution.createContext">createContext</a></li><li><a href="#request_execution.deleteContext">deleteContext</a></li><li><a href="#request_execution.getSuggestions">getSuggestions</a></li><li><a href="#request_execution.mapUri">mapUri</a></li><li><a href="#request_execution.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_execution.launchData">launchData</a></li></ul></div></div><h4>diagnostic (<a href="#domain_diagnostic">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_diagnostic.getDiagnostics">getDiagnostics</a></li><li><a href="#request_diagnostic.getServerPort">getServerPort</a></li></ul></div><h3>Types (<a href="#types">↑</a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisOptions">AnalysisOptions</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_AnalysisStatus">AnalysisStatus</a></li><li><a href="#type_AvailableSuggestion">AvailableSuggestion</a></li><li><a href="#type_AvailableSuggestionRelevanceTag">AvailableSuggestionRelevanceTag</a></li><li><a href="#type_AvailableSuggestionSet">AvailableSuggestionSet</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</a></li><li><a href="#type_CompletionService">CompletionService</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextData">ContextData</a></li><li><a href="#type_DiagnosticMessage">DiagnosticMessage</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementDeclaration">ElementDeclaration</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_ExecutableFile">ExecutableFile</a></li><li><a href="#type_ExecutableKind">ExecutableKind</a></li><li><a href="#type_ExecutionContextId">ExecutionContextId</a></li><li><a href="#type_ExecutionService">ExecutionService</a></li><li><a href="#type_FileKind">FileKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_GeneralAnalysisService">GeneralAnalysisService</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_HoverInformation">HoverInformation</a></li><li><a href="#type_ImplementedClass">ImplementedClass</a></li><li><a href="#type_ImplementedMember">ImplementedMember</a></li><li><a href="#type_ImportedElements">ImportedElements</a></li><li><a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a></li><li><a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a></li><li><a href="#type_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</a></li><li><a href="#type_LibraryPathSet">LibraryPathSet</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_OverriddenMember">OverriddenMember</a></li><li><a href="#type_Override">Override</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PostfixTemplateDescriptor">PostfixTemplateDescriptor</a></li><li><a href="#type_PubStatus">PubStatus</a></li><li><a href="#type_RefactoringFeedback">RefactoringFeedback</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringOptions">RefactoringOptions</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_RuntimeCompletionExpression">RuntimeCompletionExpression</a></li><li><a href="#type_RuntimeCompletionExpressionType">RuntimeCompletionExpressionType</a></li><li><a href="#type_RuntimeCompletionExpressionTypeKind">RuntimeCompletionExpressionTypeKind</a></li><li><a href="#type_RuntimeCompletionVariable">RuntimeCompletionVariable</a></li><li><a href="#type_SearchId">SearchId</a></li><li><a href="#type_SearchResult">SearchResult</a></li><li><a href="#type_SearchResultKind">SearchResultKind</a></li><li><a href="#type_ServerService">ServerService</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_TypeHierarchyItem">TypeHierarchyItem</a></li></ul></div><h3>Refactorings (<a href="#refactorings">↑</a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_EXTRACT_WIDGET">EXTRACT_WIDGET</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
+<h3>Domains</h3><h4>server (<a href="#domain_server">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_server.getVersion">getVersion</a></li><li><a href="#request_server.shutdown">shutdown</a></li><li><a href="#request_server.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_server.connected">connected</a></li><li><a href="#notification_server.error">error</a></li><li><a href="#notification_server.status">status</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getErrors">getErrors</a></li><li><a href="#request_analysis.getHover">getHover</a></li><li><a href="#request_analysis.getLibraryDependencies">getLibraryDependencies</a></li><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.getReachableSources">getReachableSources</a></li><li><a href="#request_analysis.reanalyze">reanalyze</a></li><li><a href="#request_analysis.setAnalysisRoots">setAnalysisRoots</a></li><li><a href="#request_analysis.setGeneralSubscriptions">setGeneralSubscriptions</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li><li><a href="#request_analysis.updateOptions">updateOptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.analyzedFiles">analyzedFiles</a></li><li><a href="#notification_analysis.closingLabels">closingLabels</a></li><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.flushResults">flushResults</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.implemented">implemented</a></li><li><a href="#notification_analysis.invalidate">invalidate</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li><li><a href="#notification_analysis.overrides">overrides</a></li></ul></div></div><h4>completion (<a href="#domain_completion">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li><li><a href="#request_completion.setSubscriptions">setSubscriptions</a></li><li><a href="#request_completion.registerLibraryPaths">registerLibraryPaths</a></li><li><a href="#request_completion.getSuggestionDetails">getSuggestionDetails</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</a></li><li><a href="#notification_completion.availableSuggestions">availableSuggestions</a></li><li><a href="#notification_completion.existingImports">existingImports</a></li></ul></div></div><h4>search (<a href="#domain_search">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_search.findElementReferences">findElementReferences</a></li><li><a href="#request_search.findMemberDeclarations">findMemberDeclarations</a></li><li><a href="#request_search.findMemberReferences">findMemberReferences</a></li><li><a href="#request_search.findTopLevelDeclarations">findTopLevelDeclarations</a></li><li><a href="#request_search.getTypeHierarchy">getTypeHierarchy</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_search.results">results</a></li></ul></div></div><h4>edit (<a href="#domain_edit">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.format">format</a></li><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getAvailableRefactorings">getAvailableRefactorings</a></li><li><a href="#request_edit.getFixes">getFixes</a></li><li><a href="#request_edit.getRefactoring">getRefactoring</a></li><li><a href="#request_edit.sortMembers">sortMembers</a></li><li><a href="#request_edit.organizeDirectives">organizeDirectives</a></li></ul></div><h4>execution (<a href="#domain_execution">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_execution.createContext">createContext</a></li><li><a href="#request_execution.deleteContext">deleteContext</a></li><li><a href="#request_execution.getSuggestions">getSuggestions</a></li><li><a href="#request_execution.mapUri">mapUri</a></li><li><a href="#request_execution.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_execution.launchData">launchData</a></li></ul></div></div><h4>diagnostic (<a href="#domain_diagnostic">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_diagnostic.getDiagnostics">getDiagnostics</a></li><li><a href="#request_diagnostic.getServerPort">getServerPort</a></li></ul></div><h3>Types (<a href="#types">↑</a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisOptions">AnalysisOptions</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_AnalysisStatus">AnalysisStatus</a></li><li><a href="#type_AvailableSuggestion">AvailableSuggestion</a></li><li><a href="#type_AvailableSuggestionRelevanceTag">AvailableSuggestionRelevanceTag</a></li><li><a href="#type_AvailableSuggestionSet">AvailableSuggestionSet</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</a></li><li><a href="#type_CompletionService">CompletionService</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextData">ContextData</a></li><li><a href="#type_DiagnosticMessage">DiagnosticMessage</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementDeclaration">ElementDeclaration</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_ExecutableFile">ExecutableFile</a></li><li><a href="#type_ExecutableKind">ExecutableKind</a></li><li><a href="#type_ExecutionContextId">ExecutionContextId</a></li><li><a href="#type_ExecutionService">ExecutionService</a></li><li><a href="#type_ExistingImport">ExistingImport</a></li><li><a href="#type_ExistingImports">ExistingImports</a></li><li><a href="#type_FileKind">FileKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_GeneralAnalysisService">GeneralAnalysisService</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_HoverInformation">HoverInformation</a></li><li><a href="#type_ImplementedClass">ImplementedClass</a></li><li><a href="#type_ImplementedMember">ImplementedMember</a></li><li><a href="#type_ImportedElementSet">ImportedElementSet</a></li><li><a href="#type_ImportedElements">ImportedElements</a></li><li><a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a></li><li><a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a></li><li><a href="#type_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</a></li><li><a href="#type_LibraryPathSet">LibraryPathSet</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_OverriddenMember">OverriddenMember</a></li><li><a href="#type_Override">Override</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PostfixTemplateDescriptor">PostfixTemplateDescriptor</a></li><li><a href="#type_PubStatus">PubStatus</a></li><li><a href="#type_RefactoringFeedback">RefactoringFeedback</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringOptions">RefactoringOptions</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_RuntimeCompletionExpression">RuntimeCompletionExpression</a></li><li><a href="#type_RuntimeCompletionExpressionType">RuntimeCompletionExpressionType</a></li><li><a href="#type_RuntimeCompletionExpressionTypeKind">RuntimeCompletionExpressionTypeKind</a></li><li><a href="#type_RuntimeCompletionVariable">RuntimeCompletionVariable</a></li><li><a href="#type_SearchId">SearchId</a></li><li><a href="#type_SearchResult">SearchResult</a></li><li><a href="#type_SearchResultKind">SearchResultKind</a></li><li><a href="#type_ServerService">ServerService</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_TypeHierarchyItem">TypeHierarchyItem</a></li></ul></div><h3>Refactorings (<a href="#refactorings">↑</a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_EXTRACT_WIDGET">EXTRACT_WIDGET</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
 
 
 </body></html>
\ No newline at end of file
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
index 8ae18ae..de7720a2 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
@@ -8415,7 +8415,9 @@
   }
   static TextDocumentChangeRegistrationOptions fromJson(
       Map<String, dynamic> json) {
-    final syncKind = json['syncKind'];
+    final syncKind = json['syncKind'] != null
+        ? TextDocumentSyncKind.fromJson(json['syncKind'])
+        : null;
     final documentSelector = json['documentSelector']
         ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
         ?.cast<DocumentFilter>()
@@ -8430,7 +8432,7 @@
 
   /// How documents are synced to the server. See TextDocumentSyncKind.Full and
   /// TextDocumentSyncKind.Incremental.
-  final num syncKind;
+  final TextDocumentSyncKind syncKind;
 
   Map<String, dynamic> toJson() {
     Map<String, dynamic> __result = {};
@@ -8443,7 +8445,7 @@
   static bool canParse(Object obj) {
     return obj is Map<String, dynamic> &&
         obj.containsKey('syncKind') &&
-        obj['syncKind'] is num &&
+        TextDocumentSyncKind.canParse(obj['syncKind']) &&
         obj.containsKey('documentSelector') &&
         (obj['documentSelector'] == null ||
             (obj['documentSelector'] is List &&
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart
index 7093987..ca304eb 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart
@@ -8,6 +8,17 @@
 
 const jsonRpcVersion = '2.0';
 
+const NullJsonHandler = const LspJsonHandler<Null>(_alwaysTrue, _alwaysNull);
+
+ErrorOr<R> cancelled<R>([R t]) =>
+    error(ErrorCodes.RequestCancelled, 'Request was cancelled', null);
+
+ErrorOr<R> error<R>(ErrorCodes code, String message, [String data]) =>
+    new ErrorOr<R>.error(new ResponseError(code, message, data));
+
+ErrorOr<R> failure<R>(ErrorOr<dynamic> error) =>
+    new ErrorOr<R>.error(error.error);
+
 Object specToJson(Object obj) {
   if (obj is ToJsonable) {
     return obj.toJson();
@@ -16,6 +27,12 @@
   }
 }
 
+ErrorOr<R> success<R>([R t]) => new ErrorOr<R>.success(t);
+
+Null _alwaysNull(_) => null;
+
+bool _alwaysTrue(_) => true;
+
 class Either2<T1, T2> {
   final int _which;
   final T1 _t1;
@@ -39,6 +56,9 @@
 
   Object toJson() => map(specToJson, specToJson);
 
+  @override
+  String toString() => map((t) => t.toString(), (t) => t.toString());
+
   /// Checks whether the value of the union equals the supplied value.
   bool valueEquals(o) => map((t) => t == o, (t) => t == o);
 }
@@ -83,6 +103,13 @@
 
   Object toJson() => map(specToJson, specToJson, specToJson);
 
+  @override
+  String toString() => map(
+        (t) => t.toString(),
+        (t) => t.toString(),
+        (t) => t.toString(),
+      );
+
   /// Checks whether the value of the union equals the supplied value.
   bool valueEquals(o) => map((t) => t == o, (t) => t == o, (t) => t == o);
 }
@@ -144,6 +171,14 @@
 
   Object toJson() => map(specToJson, specToJson, specToJson, specToJson);
 
+  @override
+  String toString() => map(
+        (t) => t.toString(),
+        (t) => t.toString(),
+        (t) => t.toString(),
+        (t) => t.toString(),
+      );
+
   /// Checks whether the value of the union equals the supplied value.
   bool valueEquals(o) =>
       map((t) => t == o, (t) => t == o, (t) => t == o, (t) => t == o);
@@ -198,10 +233,6 @@
   const LspJsonHandler(this.validateParams, this.convertParams);
 }
 
-bool _alwaysTrue(_) => true;
-Null _alwaysNull(_) => null;
-const NullJsonHandler = const LspJsonHandler<Null>(_alwaysTrue, _alwaysNull);
-
 abstract class ToJsonable {
   Object toJson();
 }
diff --git a/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart b/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
index fb3c5ec..499c925 100644
--- a/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
+++ b/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
 
@@ -21,4 +22,10 @@
    * The workspace in which the fix contributor operates.
    */
   ChangeWorkspace get workspace;
+
+  /**
+   * Return top-level declarations with the [name] in libraries that are
+   * available to this context.
+   */
+  List<TopLevelDeclaration> getTopLevelDeclarations(String name);
 }
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index af958c9..b944f0f 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.26.1';
+const String PROTOCOL_VERSION = '1.27.0';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -116,6 +116,10 @@
     'changedLibraries';
 const String COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS_REMOVED_LIBRARIES =
     'removedLibraries';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS =
+    'completion.existingImports';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_FILE = 'file';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_IMPORTS = 'imports';
 const String COMPLETION_NOTIFICATION_RESULTS = 'completion.results';
 const String COMPLETION_NOTIFICATION_RESULTS_ID = 'id';
 const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_ELEMENT_KINDS =
@@ -126,6 +130,7 @@
 const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_SUGGESTION_SETS =
     'includedSuggestionSets';
 const String COMPLETION_NOTIFICATION_RESULTS_IS_LAST = 'isLast';
+const String COMPLETION_NOTIFICATION_RESULTS_LIBRARY_FILE = 'libraryFile';
 const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_LENGTH =
     'replacementLength';
 const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_OFFSET =
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 6e7da59..fbaaf97 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -5803,6 +5803,116 @@
 }
 
 /**
+ * completion.existingImports params
+ *
+ * {
+ *   "file": FilePath
+ *   "imports": ExistingImports
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionExistingImportsParams implements HasToJson {
+  String _file;
+
+  ExistingImports _imports;
+
+  /**
+   * The defining file of the library.
+   */
+  String get file => _file;
+
+  /**
+   * The defining file of the library.
+   */
+  void set file(String value) {
+    assert(value != null);
+    this._file = value;
+  }
+
+  /**
+   * The existing imports in the library.
+   */
+  ExistingImports get imports => _imports;
+
+  /**
+   * The existing imports in the library.
+   */
+  void set imports(ExistingImports value) {
+    assert(value != null);
+    this._imports = value;
+  }
+
+  CompletionExistingImportsParams(String file, ExistingImports imports) {
+    this.file = file;
+    this.imports = imports;
+  }
+
+  factory CompletionExistingImportsParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String file;
+      if (json.containsKey("file")) {
+        file = jsonDecoder.decodeString(jsonPath + ".file", json["file"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "file");
+      }
+      ExistingImports imports;
+      if (json.containsKey("imports")) {
+        imports = new ExistingImports.fromJson(
+            jsonDecoder, jsonPath + ".imports", json["imports"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "imports");
+      }
+      return new CompletionExistingImportsParams(file, imports);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.existingImports params", json);
+    }
+  }
+
+  factory CompletionExistingImportsParams.fromNotification(
+      Notification notification) {
+    return new CompletionExistingImportsParams.fromJson(
+        new ResponseDecoder(null), "params", notification.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["file"] = file;
+    result["imports"] = imports.toJson();
+    return result;
+  }
+
+  Notification toNotification() {
+    return new Notification("completion.existingImports", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionExistingImportsParams) {
+      return file == other.file && imports == other.imports;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, file.hashCode);
+    hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * completion.getSuggestionDetails params
  *
  * {
@@ -6593,6 +6703,7 @@
  *   "replacementLength": int
  *   "results": List<CompletionSuggestion>
  *   "isLast": bool
+ *   "libraryFile": optional FilePath
  *   "includedSuggestionSets": optional List<IncludedSuggestionSet>
  *   "includedElementKinds": optional List<ElementKind>
  *   "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
@@ -6611,6 +6722,8 @@
 
   bool _isLast;
 
+  String _libraryFile;
+
   List<IncludedSuggestionSet> _includedSuggestionSets;
 
   List<ElementKind> _includedElementKinds;
@@ -6703,6 +6816,26 @@
   }
 
   /**
+   * The library file that contains the file where completion was requested.
+   * The client might use it for example together with the existingImports
+   * notification to filter out available suggestions. If there were changes to
+   * existing imports in the library, the corresponding existingImports
+   * notification will be sent before the completion notification.
+   */
+  String get libraryFile => _libraryFile;
+
+  /**
+   * The library file that contains the file where completion was requested.
+   * The client might use it for example together with the existingImports
+   * notification to filter out available suggestions. If there were changes to
+   * existing imports in the library, the corresponding existingImports
+   * notification will be sent before the completion notification.
+   */
+  void set libraryFile(String value) {
+    this._libraryFile = value;
+  }
+
+  /**
    * References to AvailableSuggestionSet objects previously sent to the
    * client. The client can include applicable names from the referenced
    * library in code completion suggestions.
@@ -6765,7 +6898,8 @@
 
   CompletionResultsParams(String id, int replacementOffset,
       int replacementLength, List<CompletionSuggestion> results, bool isLast,
-      {List<IncludedSuggestionSet> includedSuggestionSets,
+      {String libraryFile,
+      List<IncludedSuggestionSet> includedSuggestionSets,
       List<ElementKind> includedElementKinds,
       List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags}) {
     this.id = id;
@@ -6773,6 +6907,7 @@
     this.replacementLength = replacementLength;
     this.results = results;
     this.isLast = isLast;
+    this.libraryFile = libraryFile;
     this.includedSuggestionSets = includedSuggestionSets;
     this.includedElementKinds = includedElementKinds;
     this.includedSuggestionRelevanceTags = includedSuggestionRelevanceTags;
@@ -6820,6 +6955,11 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "isLast");
       }
+      String libraryFile;
+      if (json.containsKey("libraryFile")) {
+        libraryFile = jsonDecoder.decodeString(
+            jsonPath + ".libraryFile", json["libraryFile"]);
+      }
       List<IncludedSuggestionSet> includedSuggestionSets;
       if (json.containsKey("includedSuggestionSets")) {
         includedSuggestionSets = jsonDecoder.decodeList(
@@ -6848,6 +6988,7 @@
       }
       return new CompletionResultsParams(
           id, replacementOffset, replacementLength, results, isLast,
+          libraryFile: libraryFile,
           includedSuggestionSets: includedSuggestionSets,
           includedElementKinds: includedElementKinds,
           includedSuggestionRelevanceTags: includedSuggestionRelevanceTags);
@@ -6870,6 +7011,9 @@
     result["results"] =
         results.map((CompletionSuggestion value) => value.toJson()).toList();
     result["isLast"] = isLast;
+    if (libraryFile != null) {
+      result["libraryFile"] = libraryFile;
+    }
     if (includedSuggestionSets != null) {
       result["includedSuggestionSets"] = includedSuggestionSets
           .map((IncludedSuggestionSet value) => value.toJson())
@@ -6905,6 +7049,7 @@
           listEqual(results, other.results,
               (CompletionSuggestion a, CompletionSuggestion b) => a == b) &&
           isLast == other.isLast &&
+          libraryFile == other.libraryFile &&
           listEqual(includedSuggestionSets, other.includedSuggestionSets,
               (IncludedSuggestionSet a, IncludedSuggestionSet b) => a == b) &&
           listEqual(includedElementKinds, other.includedElementKinds,
@@ -6927,6 +7072,7 @@
     hash = JenkinsSmiHash.combine(hash, replacementLength.hashCode);
     hash = JenkinsSmiHash.combine(hash, results.hashCode);
     hash = JenkinsSmiHash.combine(hash, isLast.hashCode);
+    hash = JenkinsSmiHash.combine(hash, libraryFile.hashCode);
     hash = JenkinsSmiHash.combine(hash, includedSuggestionSets.hashCode);
     hash = JenkinsSmiHash.combine(hash, includedElementKinds.hashCode);
     hash =
@@ -6946,11 +7092,13 @@
  */
 class CompletionService implements Enum {
   /**
-   * The client will receive notifications once subscribed with completion
-   * suggestion sets from the libraries of interest. The client should keep an
-   * up-to-date record of these in memory so that it will be able to union
-   * these candidates with other completion suggestions when applicable at
-   * completion time.
+   * The client will receive availableSuggestions notifications once subscribed
+   * with completion suggestion sets from the libraries of interest. The client
+   * should keep an up-to-date record of these in memory so that it will be
+   * able to union these candidates with other completion suggestions when
+   * applicable at completion time.
+   *
+   * The client will also receive existingImports notifications.
    */
   static const CompletionService AVAILABLE_SUGGESTION_SETS =
       const CompletionService._("AVAILABLE_SUGGESTION_SETS");
@@ -13011,6 +13159,214 @@
 }
 
 /**
+ * ExistingImport
+ *
+ * {
+ *   "uri": int
+ *   "elements": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImport implements HasToJson {
+  int _uri;
+
+  List<int> _elements;
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in
+   * the enclosing ExistingImports and its ImportedElementSet object.
+   */
+  int get uri => _uri;
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in
+   * the enclosing ExistingImports and its ImportedElementSet object.
+   */
+  void set uri(int value) {
+    assert(value != null);
+    this._uri = value;
+  }
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  List<int> get elements => _elements;
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  void set elements(List<int> value) {
+    assert(value != null);
+    this._elements = value;
+  }
+
+  ExistingImport(int uri, List<int> elements) {
+    this.uri = uri;
+    this.elements = elements;
+  }
+
+  factory ExistingImport.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      int uri;
+      if (json.containsKey("uri")) {
+        uri = jsonDecoder.decodeInt(jsonPath + ".uri", json["uri"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "uri");
+      }
+      List<int> elements;
+      if (json.containsKey("elements")) {
+        elements = jsonDecoder.decodeList(
+            jsonPath + ".elements", json["elements"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "elements");
+      }
+      return new ExistingImport(uri, elements);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ExistingImport", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["uri"] = uri;
+    result["elements"] = elements;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ExistingImport) {
+      return uri == other.uri &&
+          listEqual(elements, other.elements, (int a, int b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+    hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * ExistingImports
+ *
+ * {
+ *   "elements": ImportedElementSet
+ *   "imports": List<ExistingImport>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImports implements HasToJson {
+  ImportedElementSet _elements;
+
+  List<ExistingImport> _imports;
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  ImportedElementSet get elements => _elements;
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  void set elements(ImportedElementSet value) {
+    assert(value != null);
+    this._elements = value;
+  }
+
+  /**
+   * The list of imports in the library.
+   */
+  List<ExistingImport> get imports => _imports;
+
+  /**
+   * The list of imports in the library.
+   */
+  void set imports(List<ExistingImport> value) {
+    assert(value != null);
+    this._imports = value;
+  }
+
+  ExistingImports(ImportedElementSet elements, List<ExistingImport> imports) {
+    this.elements = elements;
+    this.imports = imports;
+  }
+
+  factory ExistingImports.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      ImportedElementSet elements;
+      if (json.containsKey("elements")) {
+        elements = new ImportedElementSet.fromJson(
+            jsonDecoder, jsonPath + ".elements", json["elements"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "elements");
+      }
+      List<ExistingImport> imports;
+      if (json.containsKey("imports")) {
+        imports = jsonDecoder.decodeList(
+            jsonPath + ".imports",
+            json["imports"],
+            (String jsonPath, Object json) =>
+                new ExistingImport.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "imports");
+      }
+      return new ExistingImports(elements, imports);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ExistingImports", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["elements"] = elements.toJson();
+    result["imports"] =
+        imports.map((ExistingImport value) => value.toJson()).toList();
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ExistingImports) {
+      return elements == other.elements &&
+          listEqual(imports, other.imports,
+              (ExistingImport a, ExistingImport b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+    hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * extractLocalVariable feedback
  *
  * {
@@ -15586,16 +15942,16 @@
   }
 
   /**
-   * The name of the library in which the referenced element is declared. This
-   * data is omitted if there is no referenced element, or if the element is
-   * declared inside an HTML file.
+   * The URI of the containing library, examples here include "dart:core",
+   * "package:.." and file uris represented by the path on disk, "/..". The
+   * data is omitted if the element is declared inside an HTML file.
    */
   String get containingLibraryName => _containingLibraryName;
 
   /**
-   * The name of the library in which the referenced element is declared. This
-   * data is omitted if there is no referenced element, or if the element is
-   * declared inside an HTML file.
+   * The URI of the containing library, examples here include "dart:core",
+   * "package:.." and file uris represented by the path on disk, "/..". The
+   * data is omitted if the element is declared inside an HTML file.
    */
   void set containingLibraryName(String value) {
     this._containingLibraryName = value;
@@ -16109,6 +16465,135 @@
 }
 
 /**
+ * ImportedElementSet
+ *
+ * {
+ *   "strings": List<String>
+ *   "uris": List<int>
+ *   "names": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ImportedElementSet implements HasToJson {
+  List<String> _strings;
+
+  List<int> _uris;
+
+  List<int> _names;
+
+  /**
+   * The list of unique strings in this object.
+   */
+  List<String> get strings => _strings;
+
+  /**
+   * The list of unique strings in this object.
+   */
+  void set strings(List<String> value) {
+    assert(value != null);
+    this._strings = value;
+  }
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  List<int> get uris => _uris;
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  void set uris(List<int> value) {
+    assert(value != null);
+    this._uris = value;
+  }
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  List<int> get names => _names;
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  void set names(List<int> value) {
+    assert(value != null);
+    this._names = value;
+  }
+
+  ImportedElementSet(List<String> strings, List<int> uris, List<int> names) {
+    this.strings = strings;
+    this.uris = uris;
+    this.names = names;
+  }
+
+  factory ImportedElementSet.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      List<String> strings;
+      if (json.containsKey("strings")) {
+        strings = jsonDecoder.decodeList(
+            jsonPath + ".strings", json["strings"], jsonDecoder.decodeString);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "strings");
+      }
+      List<int> uris;
+      if (json.containsKey("uris")) {
+        uris = jsonDecoder.decodeList(
+            jsonPath + ".uris", json["uris"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "uris");
+      }
+      List<int> names;
+      if (json.containsKey("names")) {
+        names = jsonDecoder.decodeList(
+            jsonPath + ".names", json["names"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "names");
+      }
+      return new ImportedElementSet(strings, uris, names);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ImportedElementSet", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["strings"] = strings;
+    result["uris"] = uris;
+    result["names"] = names;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ImportedElementSet) {
+      return listEqual(
+              strings, other.strings, (String a, String b) => a == b) &&
+          listEqual(uris, other.uris, (int a, int b) => a == b) &&
+          listEqual(names, other.names, (int a, int b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, strings.hashCode);
+    hash = JenkinsSmiHash.combine(hash, uris.hashCode);
+    hash = JenkinsSmiHash.combine(hash, names.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * ImportedElements
  *
  * {
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index ca242a8..587adc4 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -42,6 +42,7 @@
 import 'package:analysis_server/src/search/search_domain.dart';
 import 'package:analysis_server/src/server/detachable_filesystem_manager.dart';
 import 'package:analysis_server/src/server/diagnostic_server.dart';
+import 'package:analysis_server/src/server/features.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analysis_server/src/services/search/search_engine_internal.dart';
 import 'package:analysis_server/src/utilities/null_string_sink.dart';
@@ -206,10 +207,12 @@
     analysisDriverScheduler.status.listen(sendStatusNotificationNew);
     analysisDriverScheduler.start();
 
-    declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
-    declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
-    analysisDriverScheduler.outOfBandWorker =
-        CompletionLibrariesWorker(declarationsTracker);
+    if (options.featureSet.completion) {
+      declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
+      declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
+      analysisDriverScheduler.outOfBandWorker =
+          CompletionLibrariesWorker(declarationsTracker);
+    }
 
     contextManager = new ContextManagerImpl(
         resourceProvider,
@@ -485,7 +488,7 @@
   /// projects/contexts support.
   void setAnalysisRoots(String requestId, List<String> includedPaths,
       List<String> excludedPaths, Map<String, String> packageRoots) {
-    declarationsTracker.discardContexts();
+    declarationsTracker?.discardContexts();
     if (notificationManager != null) {
       notificationManager.setAnalysisRoots(includedPaths, excludedPaths);
     }
@@ -739,6 +742,9 @@
 
   /// Whether to enable parsing via the Fasta parser.
   bool useFastaParser = true;
+
+  /// The set of enabled features.
+  FeatureSet featureSet = FeatureSet();
 }
 
 class ServerContextManagerCallbacks extends ContextManagerCallbacks {
@@ -886,6 +892,11 @@
   }
 
   @override
+  void analysisOptionsUpdated(nd.AnalysisDriver driver) {
+    analysisServer.updateContextInDeclarationsTracker(driver);
+  }
+
+  @override
   void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) {
     nd.AnalysisDriver analysisDriver = analysisServer.driverMap[contextFolder];
     if (analysisDriver != null) {
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index c56a762..d1aa497d 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -136,7 +136,7 @@
 
   void addContextsToDeclarationsTracker() {
     for (var driver in driverMap.values) {
-      declarationsTracker.addContext(driver.analysisContext);
+      declarationsTracker?.addContext(driver.analysisContext);
       driver.resetUriResolution();
     }
   }
@@ -189,7 +189,7 @@
 
   DartdocDirectiveInfo getDartdocDirectiveInfoFor(ResolvedUnitResult result) {
     return declarationsTracker
-            .getContext(result.session.analysisContext)
+            ?.getContext(result.session.analysisContext)
             ?.dartdocDirectiveInfo ??
         new DartdocDirectiveInfo();
   }
@@ -288,7 +288,12 @@
   /// Notify the declarations tracker that the file with the given [path] was
   /// changed - added, updated, or removed.  Schedule processing of the file.
   void notifyDeclarationsTracker(String path) {
-    declarationsTracker.changeFile(path);
+    declarationsTracker?.changeFile(path);
     analysisDriverScheduler.notify(null);
   }
+
+  void updateContextInDeclarationsTracker(nd.AnalysisDriver driver) {
+    declarationsTracker?.discardContext(driver.analysisContext);
+    declarationsTracker?.addContext(driver.analysisContext);
+  }
 }
diff --git a/pkg/analysis_server/lib/src/computer/computer_hover.dart b/pkg/analysis_server/lib/src/computer/computer_hover.dart
index 1dd0b83..c4e1f34 100644
--- a/pkg/analysis_server/lib/src/computer/computer_hover.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart
@@ -72,7 +72,15 @@
           // containing library
           LibraryElement library = element.library;
           if (library != null) {
-            hover.containingLibraryName = library.name;
+            Uri uri = library.source.uri;
+            if (uri.scheme != '' && uri.scheme == 'file') {
+              // for 'file:' URIs, use the path (contents after 'file:///')
+              hover.containingLibraryName = _unit
+                  .declaredElement.session.resourceProvider.pathContext
+                  .fromUri(uri);
+            } else {
+              hover.containingLibraryName = uri.toString();
+            }
             hover.containingLibraryPath = library.source.fullName;
           }
         }
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index fa1d36f..dfb5db4 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -355,6 +355,11 @@
   void afterWatchEvent(WatchEvent event);
 
   /**
+   * Called when analysis options or URI resolution in the [driver] are changed.
+   */
+  void analysisOptionsUpdated(AnalysisDriver driver);
+
+  /**
    * Called when the set of files associated with a context have changed (or
    * some of those files have been modified).  [changeSet] is the set of
    * changes that need to be applied to the context.
@@ -1630,6 +1635,7 @@
         contextRoot: driver.contextRoot);
     SourceFactory factory = builder.createSourceFactory(contextRoot, options);
     driver.configure(analysisOptions: options, sourceFactory: factory);
+    callbacks.analysisOptionsUpdated(driver);
   }
 
   void _updateContextPackageUriResolver(Folder contextFolder) {
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 26461fc..4f91833 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -264,6 +264,14 @@
 
   @override
   Response handleRequest(Request request) {
+    if (!server.options.featureSet.completion) {
+      return Response.invalidParameter(
+        request,
+        'request',
+        'The completion feature is not enabled',
+      );
+    }
+
     return runZoned(() {
       String requestName = request.method;
 
@@ -335,8 +343,6 @@
    * Process a `completion.getSuggestions` request.
    */
   Future<void> processRequest(Request request) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     performance = new CompletionPerformance();
 
     // extract and validate params
@@ -389,8 +395,13 @@
       includedElementKinds,
       includedSuggestionRelevanceTags,
     ).then((CompletionResult result) {
+      String libraryFile;
       List<IncludedSuggestionSet> includedSuggestionSets;
       if (includedElementKinds != null && resolvedUnit != null) {
+        libraryFile = resolvedUnit.libraryElement.source.fullName;
+        server.sendNotification(
+          createExistingImportsNotification(resolvedUnit),
+        );
         includedSuggestionSets = computeIncludedSetList(
           server.declarationsTracker,
           resolvedUnit,
@@ -406,6 +417,7 @@
         result.replacementOffset,
         result.replacementLength,
         result.suggestions,
+        libraryFile,
         includedSuggestionSets,
         includedElementKinds?.toList(),
         includedSuggestionRelevanceTags,
@@ -444,6 +456,7 @@
     int replacementOffset,
     int replacementLength,
     Iterable<CompletionSuggestion> results,
+    String libraryFile,
     List<IncludedSuggestionSet> includedSuggestionSets,
     List<ElementKind> includedElementKinds,
     List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags,
@@ -455,6 +468,7 @@
         replacementLength,
         results,
         true,
+        libraryFile: libraryFile,
         includedSuggestionSets: includedSuggestionSets,
         includedElementKinds: includedElementKinds,
         includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
diff --git a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
index ce8b297..305907c 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -4,7 +4,9 @@
 
 import 'package:analysis_server/src/protocol_server.dart' as protocol;
 import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/generated/utilities_general.dart';
 import 'package:analyzer/src/services/available_declarations.dart';
 
 /// Compute which suggestion sets should be included into completion inside
@@ -79,6 +81,81 @@
   ).toNotification();
 }
 
+/// Compute existing imports and elements that they provide.
+protocol.Notification createExistingImportsNotification(
+  ResolvedUnitResult resolvedUnit,
+) {
+  var uniqueStrings = _UniqueImportedStrings();
+  var uniqueElements = _UniqueImportedElements();
+  var existingImports = <protocol.ExistingImport>[];
+
+  var importElementList = resolvedUnit.libraryElement.imports;
+  for (var import in importElementList) {
+    var importedLibrary = import.importedLibrary;
+    if (importedLibrary == null) continue;
+
+    var importedUriStr = '${importedLibrary.librarySource.uri}';
+
+    var existingImportElements = <int>[];
+    for (var element in import.namespace.definedNames.values) {
+      if (element.librarySource != null) {
+        var index = uniqueElements.indexOf(uniqueStrings, element);
+        existingImportElements.add(index);
+      }
+    }
+
+    existingImports.add(protocol.ExistingImport(
+      uniqueStrings.indexOf(importedUriStr),
+      existingImportElements,
+    ));
+  }
+
+  return protocol.CompletionExistingImportsParams(
+    resolvedUnit.libraryElement.source.fullName,
+    protocol.ExistingImports(
+      protocol.ImportedElementSet(
+        uniqueStrings.values,
+        uniqueElements.uriList,
+        uniqueElements.nameList,
+      ),
+      existingImports,
+    ),
+  ).toNotification();
+}
+
+/// TODO(dantup): We need to expose this because the Declarations code currently
+/// returns declarations with DeclarationKinds but the DartCompletionManager
+/// gives us a list of "included ElementKinds". Maybe it would be better to expose
+/// includedDeclarationKinds and then just map that list to ElementKinds once in
+/// domain_completion for the original protocol?
+protocol.ElementKind protocolElementKind(DeclarationKind kind) {
+  switch (kind) {
+    case DeclarationKind.CLASS:
+      return protocol.ElementKind.CLASS;
+    case DeclarationKind.CLASS_TYPE_ALIAS:
+      return protocol.ElementKind.CLASS_TYPE_ALIAS;
+    case DeclarationKind.CONSTRUCTOR:
+      return protocol.ElementKind.CONSTRUCTOR;
+    case DeclarationKind.ENUM:
+      return protocol.ElementKind.ENUM;
+    case DeclarationKind.ENUM_CONSTANT:
+      return protocol.ElementKind.ENUM_CONSTANT;
+    case DeclarationKind.FUNCTION:
+      return protocol.ElementKind.FUNCTION;
+    case DeclarationKind.FUNCTION_TYPE_ALIAS:
+      return protocol.ElementKind.FUNCTION_TYPE_ALIAS;
+    case DeclarationKind.GETTER:
+      return protocol.ElementKind.GETTER;
+    case DeclarationKind.MIXIN:
+      return protocol.ElementKind.MIXIN;
+    case DeclarationKind.SETTER:
+      return protocol.ElementKind.SETTER;
+    case DeclarationKind.VARIABLE:
+      return protocol.ElementKind.TOP_LEVEL_VARIABLE;
+  }
+  return protocol.ElementKind.UNKNOWN;
+}
+
 /// Computes the best URI to import [what] into the [unit] library.
 String _getRelativeFileUri(ResolvedUnitResult unit, Uri what) {
   if (what.scheme == 'file') {
@@ -173,39 +250,6 @@
   );
 }
 
-// TODO(dantup): We need to expose this because the Declarations code currently
-// returns declarations with DeclarationKinds but the DartCompletionManager
-// gives us a list of "included ElementKinds". Maybe it would be better to expose
-// includedDeclarationKinds and then just map that list to ElementKinds once in
-// domain_completion for the original protocol?
-protocol.ElementKind protocolElementKind(DeclarationKind kind) {
-  switch (kind) {
-    case DeclarationKind.CLASS:
-      return protocol.ElementKind.CLASS;
-    case DeclarationKind.CLASS_TYPE_ALIAS:
-      return protocol.ElementKind.CLASS_TYPE_ALIAS;
-    case DeclarationKind.CONSTRUCTOR:
-      return protocol.ElementKind.CONSTRUCTOR;
-    case DeclarationKind.ENUM:
-      return protocol.ElementKind.ENUM;
-    case DeclarationKind.ENUM_CONSTANT:
-      return protocol.ElementKind.ENUM_CONSTANT;
-    case DeclarationKind.FUNCTION:
-      return protocol.ElementKind.FUNCTION;
-    case DeclarationKind.FUNCTION_TYPE_ALIAS:
-      return protocol.ElementKind.FUNCTION_TYPE_ALIAS;
-    case DeclarationKind.GETTER:
-      return protocol.ElementKind.GETTER;
-    case DeclarationKind.MIXIN:
-      return protocol.ElementKind.MIXIN;
-    case DeclarationKind.SETTER:
-      return protocol.ElementKind.SETTER;
-    case DeclarationKind.VARIABLE:
-      return protocol.ElementKind.TOP_LEVEL_VARIABLE;
-  }
-  return protocol.ElementKind.UNKNOWN;
-}
-
 class CompletionLibrariesWorker implements SchedulerWorker {
   final DeclarationsTracker tracker;
 
@@ -277,3 +321,56 @@
     _listener = null;
   }
 }
+
+class _ImportedElement {
+  final int uri;
+  final int name;
+
+  @override
+  final int hashCode;
+
+  _ImportedElement(this.uri, this.name)
+      : hashCode = JenkinsSmiHash.hash2(uri, name);
+
+  @override
+  bool operator ==(other) {
+    return other is _ImportedElement && other.uri == uri && other.name == name;
+  }
+}
+
+class _UniqueImportedElements {
+  final map = <_ImportedElement, int>{};
+
+  List<int> get nameList => map.keys.map((e) => e.name).toList();
+
+  List<int> get uriList => map.keys.map((e) => e.uri).toList();
+
+  int indexOf(_UniqueImportedStrings strings, Element element) {
+    var uriStr = '${element.librarySource.uri}';
+    var wrapper = _ImportedElement(
+      strings.indexOf(uriStr),
+      strings.indexOf(element.name),
+    );
+    var index = map[wrapper];
+    if (index == null) {
+      index = map.length;
+      map[wrapper] = index;
+    }
+    return index;
+  }
+}
+
+class _UniqueImportedStrings {
+  final map = <String, int>{};
+
+  List<String> get values => map.keys.toList();
+
+  int indexOf(String str) {
+    var index = map[str];
+    if (index == null) {
+      index = map.length;
+      map[str] = index;
+    }
+    return index;
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 99a39bd..5941656 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -23,6 +23,7 @@
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analysis_server/src/services/correction/fix/analysis_options/fix_generator.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/fix/manifest/fix_generator.dart';
 import 'package:analysis_server/src/services/correction/fix/pubspec/fix_generator.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
@@ -634,7 +635,16 @@
         int errorLine = lineInfo.getLocation(error.offset).lineNumber;
         if (errorLine == requestLine) {
           var workspace = DartChangeWorkspace(server.currentSessions);
-          var context = new DartFixContextImpl(workspace, result, error);
+          var context =
+              new DartFixContextImpl(workspace, result, error, (name) {
+            var tracker = server.declarationsTracker;
+            var provider = TopLevelDeclarationsProvider(tracker);
+            return provider.get(
+              result.session.analysisContext,
+              result.path,
+              name,
+            );
+          });
           List<Fix> fixes =
               await new DartFixContributor().computeFixes(context);
           if (fixes.isNotEmpty) {
diff --git a/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart b/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart
index e71fd1d..378b3b1 100644
--- a/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart
@@ -28,7 +28,12 @@
 
   Future<void> fixError(ResolvedUnitResult result, AnalysisError error) async {
     final workspace = DartChangeWorkspace(listener.server.currentSessions);
-    final dartContext = new DartFixContextImpl(workspace, result, error);
+    final dartContext = new DartFixContextImpl(
+      workspace,
+      result,
+      error,
+      (name) => [],
+    );
     final processor = new FixProcessor(dartContext);
     Fix fix = await processor.computeFix();
     final location = listener.locationFor(result, error.offset, error.length);
diff --git a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
index 61d3984..62161e4 100644
--- a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
@@ -105,6 +105,7 @@
             content = '''
 
     - non-nullable''';
+            return null;
           },
         );
       }
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
index 277658d..6330e82 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
@@ -63,7 +63,20 @@
     var flutterDartOutline = _convert(dartOutline);
 
     // Create outlines for widgets.
-    resolvedUnit.unit.accept(new _FlutterOutlineBuilder(this));
+    var visitor = new _FlutterOutlineBuilder(this);
+    resolvedUnit.unit.accept(visitor);
+
+    // Associate Flutter outlines with Dart outlines.
+    for (var outline in visitor.outlines) {
+      for (var parent in _depthFirstOrder) {
+        if (parent.offset < outline.offset &&
+            outline.offset + outline.length < parent.offset + parent.length) {
+          parent.children ??= <protocol.FlutterOutline>[];
+          parent.children.add(outline);
+          break;
+        }
+      }
+    }
 
     // Compute instrumented code.
     if (widgets.values.any((w) => w.hasDesignTimeConstructor)) {
@@ -224,8 +237,14 @@
             }
           }
         } else {
-          ParameterElement parameter = argument.staticParameterElement;
-          _addAttribute(attributes, argument, parameter);
+          var visitor = _FlutterOutlineBuilder(this);
+          argument.accept(visitor);
+          if (visitor.outlines.isNotEmpty) {
+            children.addAll(visitor.outlines);
+          } else {
+            ParameterElement parameter = argument.staticParameterElement;
+            _addAttribute(attributes, argument, parameter);
+          }
         }
       }
 
@@ -385,6 +404,7 @@
 
 class _FlutterOutlineBuilder extends GeneralizingAstVisitor<void> {
   final FlutterOutlineComputer computer;
+  final List<protocol.FlutterOutline> outlines = [];
 
   _FlutterOutlineBuilder(this.computer);
 
@@ -392,14 +412,7 @@
   void visitExpression(Expression node) {
     var outline = computer._createOutline(node, false);
     if (outline != null) {
-      for (var parent in computer._depthFirstOrder) {
-        if (parent.offset < outline.offset &&
-            outline.offset + outline.length < parent.offset + parent.length) {
-          parent.children ??= <protocol.FlutterOutline>[];
-          parent.children.add(outline);
-          return;
-        }
-      }
+      outlines.add(outline);
     } else {
       super.visitExpression(node);
     }
diff --git a/pkg/analysis_server/lib/src/lsp/constants.dart b/pkg/analysis_server/lib/src/lsp/constants.dart
index 904feeb..54b1805 100644
--- a/pkg/analysis_server/lib/src/lsp/constants.dart
+++ b/pkg/analysis_server/lib/src/lsp/constants.dart
@@ -4,6 +4,36 @@
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 
+/// Set the characters that will cause the editor to automatically
+/// trigger completion.
+/// TODO(dantup): There are several characters that we want to conditionally
+/// allow to trigger completion, but they can only be added when the completion
+/// provider is able to handle them in context:
+///
+///    {   trigger if being typed in a string immediately after a $
+///    '   trigger if the opening quote for an import/export
+///    "   trigger if the opening quote for an import/export
+///    /   trigger if as part of a path in an import/export
+///    \   trigger if as part of a path in an import/export
+///    :   don't trigger when typing case expressions (`case x:`)
+///
+/// Additionally, we need to prefix `filterText` on completion items
+/// with spaces for those that can follow whitespace (eg. `foo` in
+/// `myArg: foo`) to ensure they're not filtered away when the user
+/// types space.
+///
+/// See https://github.com/Dart-Code/Dart-Code/blob/68d1cd271e88a785570257d487adbdec17abd6a3/src/providers/dart_completion_item_provider.ts#L36-L64
+/// for the VS Code implementation of this.
+const dartCompletionTriggerCharacters = ['.', '=', '(', r'$'];
+
+/// TODO(dantup): Signature help triggering is even more sensitive to
+/// bad chars, so we'll need to implement the logic described here:
+/// https://github.com/dart-lang/sdk/issues/34241
+const dartSignatureHelpTriggerCharacters = <String>[];
+
+/// Characters to trigger formatting when format-on-type is enabled.
+const dartTypeFormattingCharacters = ['}', ';'];
+
 /// Constants for command IDs that are exchanged between LSP client/server.
 abstract class Commands {
   /// A list of all commands IDs that can be sent to the client to inform which
@@ -19,6 +49,11 @@
   static const sendWorkspaceEdit = 'edit.sendWorkspaceEdit';
 }
 
+abstract class CustomMethods {
+  static const DiagnosticServer = const Method('dart/diagnosticServer');
+  static const AnalyzerStatus = const Method(r'$/analyzerStatus');
+}
+
 /// CodeActionKinds supported by the server that are not declared in the LSP spec.
 abstract class DartCodeActionKind {
   /// A list of all supported CodeAction kinds, supplied to the client during
@@ -61,8 +96,3 @@
   ///   if it crashes 5 times in the last 180 seconds."
   static const ClientServerInconsistentState = const ErrorCodes(-32010);
 }
-
-abstract class CustomMethods {
-  static const DiagnosticServer = const Method('dart/diagnosticServer');
-  static const AnalyzerStatus = const Method(r'$/analyzerStatus');
-}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
index 5d75dde..e4f255e 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
@@ -20,7 +20,8 @@
   LspJsonHandler<void> get jsonHandler => NullJsonHandler;
 
   @override
-  Future<ErrorOr<DartDiagnosticServer>> handle(void _) async {
+  Future<ErrorOr<DartDiagnosticServer>> handle(
+      void _, CancellationToken token) async {
     final port = await server.diagnosticServer.getServerPort();
     return success(new DartDiagnosticServer(port));
   }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_cancel_request.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_cancel_request.dart
new file mode 100644
index 0000000..c21782c
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_cancel_request.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2019, 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+
+class CancelRequestHandler extends MessageHandler<CancelParams, void> {
+  Map<String, CancelableToken> _tokens = {};
+
+  CancelRequestHandler(LspAnalysisServer server) : super(server);
+
+  Method get handlesMessage => Method.cancelRequest;
+
+  @override
+  LspJsonHandler<CancelParams> get jsonHandler => CancelParams.jsonHandler;
+
+  void clearToken(RequestMessage message) {
+    _tokens.remove(message.id.toString());
+  }
+
+  CancelableToken createToken(RequestMessage message) {
+    final token = new CancelableToken();
+    _tokens[message.id.toString()] = token;
+    return token;
+  }
+
+  ErrorOr<void> handle(CancelParams params, CancellationToken token) {
+    // Don't assume this is in the map as it's possible the client sent a
+    // cancellation that we processed after already starting to send the response
+    // and cleared the token.
+    _tokens[params.id.toString()]?.cancel();
+    return success();
+  }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
index c43057f..c518c93 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
@@ -21,7 +21,8 @@
   LspJsonHandler<DidChangeWorkspaceFoldersParams> get jsonHandler =>
       DidChangeWorkspaceFoldersParams.jsonHandler;
 
-  ErrorOr<void> handle(DidChangeWorkspaceFoldersParams params) {
+  ErrorOr<void> handle(
+      DidChangeWorkspaceFoldersParams params, CancellationToken token) {
     // Don't do anything if our analysis roots are not based on open workspaces.
     if (!updateAnalysisRoots) {
       return success();
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
index b7b5f72..326b25a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
@@ -17,6 +17,7 @@
 import 'package:analysis_server/src/services/correction/assist_internal.dart';
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart'
@@ -33,13 +34,16 @@
       CodeActionParams.jsonHandler;
 
   Future<ErrorOr<List<Either2<Command, CodeAction>>>> handle(
-      CodeActionParams params) async {
+      CodeActionParams params, CancellationToken token) async {
     if (!isDartDocument(params.textDocument)) {
       return success(const []);
     }
 
     final capabilities = server?.clientCapabilities?.textDocument?.codeAction;
 
+    final clientSupportsWorkspaceApplyEdit =
+        server?.clientCapabilities?.workspace?.applyEdit == true;
+
     final clientSupportsLiteralCodeActions =
         capabilities?.codeActionLiteralSupport != null;
 
@@ -59,6 +63,7 @@
           return _getCodeActions(
               clientSupportedCodeActionKinds,
               clientSupportsLiteralCodeActions,
+              clientSupportsWorkspaceApplyEdit,
               path.result,
               params.range,
               offset,
@@ -148,6 +153,7 @@
   Future<ErrorOr<List<Either2<Command, CodeAction>>>> _getCodeActions(
     HashSet<CodeActionKind> kinds,
     bool supportsLiterals,
+    bool supportsWorkspaceApplyEdit,
     String path,
     Range range,
     int offset,
@@ -155,7 +161,8 @@
     ResolvedUnitResult unit,
   ) async {
     final results = await Future.wait([
-      _getSourceActions(kinds, supportsLiterals, path),
+      _getSourceActions(
+          kinds, supportsLiterals, supportsWorkspaceApplyEdit, path),
       _getAssistActions(kinds, supportsLiterals, offset, length, unit),
       _getRefactorActions(kinds, supportsLiterals, path, range, unit),
       _getFixActions(kinds, supportsLiterals, range, unit),
@@ -186,7 +193,14 @@
         int errorLine = lineInfo.getLocation(error.offset).lineNumber - 1;
         if (errorLine >= range.start.line && errorLine <= range.end.line) {
           var workspace = DartChangeWorkspace(server.currentSessions);
-          var context = new DartFixContextImpl(workspace, unit, error);
+          var context = new DartFixContextImpl(workspace, unit, error, (name) {
+            var tracker = server.declarationsTracker;
+            return TopLevelDeclarationsProvider(tracker).get(
+              unit.session.analysisContext,
+              unit.path,
+              name,
+            );
+          });
           final fixes = await fixContributor.computeFixes(context);
           if (fixes.isNotEmpty) {
             fixes.sort(Fix.SORT_BY_RELEVANCE);
@@ -236,18 +250,25 @@
   Future<List<Either2<Command, CodeAction>>> _getSourceActions(
     HashSet<CodeActionKind> clientSupportedCodeActionKinds,
     bool clientSupportsLiteralCodeActions,
+    bool clientSupportsWorkspaceApplyEdit,
     String path,
   ) async {
     // The source actions supported are only valid for Dart files.
     if (!AnalysisEngine.isDartFileName(path)) {
-      return [];
+      return const [];
     }
 
     // If the client told us what kinds they support but it does not include
     // Source then don't return any.
     if (clientSupportsLiteralCodeActions &&
         !clientSupportedCodeActionKinds.contains(CodeActionKind.Source)) {
-      return [];
+      return const [];
+    }
+
+    // If the client does not support workspace/applyEdit, we won't be able to
+    // run any of these.
+    if (!clientSupportsWorkspaceApplyEdit) {
+      return const [];
     }
 
     return [
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index ea2b0a2..0602df0 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -55,7 +55,8 @@
   LspJsonHandler<CompletionParams> get jsonHandler =>
       CompletionParams.jsonHandler;
 
-  Future<ErrorOr<List<CompletionItem>>> handle(CompletionParams params) async {
+  Future<ErrorOr<List<CompletionItem>>> handle(
+      CompletionParams params, CancellationToken token) async {
     if (!isDartDocument(params.textDocument)) {
       return success(const []);
     }
@@ -82,6 +83,7 @@
           includeSuggestionSets,
           unit.result,
           offset,
+          token,
         ));
   }
 
@@ -91,6 +93,7 @@
     bool includeSuggestionSets,
     ResolvedUnitResult unit,
     int offset,
+    CancellationToken token,
   ) async {
     final performance = new CompletionPerformance();
     performance.path = unit.path;
@@ -114,6 +117,11 @@
       );
       final suggestions =
           await contributor.computeSuggestions(completionRequest);
+
+      if (token.isCancellationRequested) {
+        return cancelled();
+      }
+
       final results = suggestions
           .map((item) => toCompletionItem(
                 completionCapabilities,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
index df26ab8..c4b764c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
@@ -29,7 +29,8 @@
   @override
   LspJsonHandler<CompletionItem> get jsonHandler => CompletionItem.jsonHandler;
 
-  Future<ErrorOr<CompletionItem>> handle(CompletionItem item) async {
+  Future<ErrorOr<CompletionItem>> handle(
+      CompletionItem item, CancellationToken token) async {
     // If this isn't an item with resolution data, return the same item back.
     if (item.data == null) {
       return success(item);
@@ -80,6 +81,10 @@
 
         var resolvedLibrary = await session.getResolvedLibrary(libraryPath);
 
+        if (token.isCancellationRequested) {
+          return cancelled();
+        }
+
         analyzer.LibraryElement requestedLibraryElement;
         try {
           requestedLibraryElement = await session.getLibraryByUri(
@@ -93,6 +98,10 @@
           );
         }
 
+        if (token.isCancellationRequested) {
+          return cancelled();
+        }
+
         var requestedElement =
             requestedLibraryElement.exportNamespace.get(requestedName);
         if (requestedElement == null) {
@@ -118,6 +127,10 @@
           }
         });
 
+        if (token.isCancellationRequested) {
+          return cancelled();
+        }
+
         final changes = builder.sourceChange;
         final thisFilesChanges =
             changes.edits.where((e) => e.file == data.file).toList();
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
index ead355a..c6df90c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
@@ -23,7 +23,7 @@
       TextDocumentPositionParams.jsonHandler;
 
   Future<ErrorOr<List<Location>>> handle(
-      TextDocumentPositionParams params) async {
+      TextDocumentPositionParams params, CancellationToken token) async {
     if (!isDartDocument(params.textDocument)) {
       return success(const []);
     }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
index 5be52b6..6a59beb 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
@@ -22,7 +22,7 @@
       TextDocumentPositionParams.jsonHandler;
 
   Future<ErrorOr<List<DocumentHighlight>>> handle(
-      TextDocumentPositionParams params) async {
+      TextDocumentPositionParams params, CancellationToken token) async {
     if (!isDartDocument(params.textDocument)) {
       return success(const []);
     }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart
index a4c623b..3de909c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart
@@ -48,7 +48,7 @@
       DocumentSymbolParams.jsonHandler;
 
   Future<ErrorOr<Either2<List<DocumentSymbol>, List<SymbolInformation>>>>
-      handle(DocumentSymbolParams params) async {
+      handle(DocumentSymbolParams params, CancellationToken token) async {
     if (!isDartDocument(params.textDocument)) {
       return success(
         Either2<List<DocumentSymbol>, List<SymbolInformation>>.t2([]),
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
index c440afe..f552cf6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
@@ -33,7 +33,8 @@
   LspJsonHandler<ExecuteCommandParams> get jsonHandler =>
       ExecuteCommandParams.jsonHandler;
 
-  Future<ErrorOr<Object>> handle(ExecuteCommandParams params) async {
+  Future<ErrorOr<Object>> handle(
+      ExecuteCommandParams params, CancellationToken token) async {
     final handler = commandHandlers[params.command];
     if (handler == null) {
       return error(ServerErrorCodes.UnknownCommand,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart
index c301118..699931d 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart
@@ -24,7 +24,7 @@
   LspJsonHandler<void> get jsonHandler => NullJsonHandler;
 
   @override
-  Future<ErrorOr<void>> handle(void _) async {
+  Future<ErrorOr<void>> handle(void _, CancellationToken token) async {
     // Set a flag that the server shutdown is being controlled here to ensure
     // that the normal code that shuts down the server when the channel closes
     // does not fire.
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart
index 7ad848d..bfea14c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart
@@ -20,7 +20,8 @@
   LspJsonHandler<FoldingRangeParams> get jsonHandler =>
       FoldingRangeParams.jsonHandler;
 
-  Future<ErrorOr<List<FoldingRange>>> handle(FoldingRangeParams params) async {
+  Future<ErrorOr<List<FoldingRange>>> handle(
+      FoldingRangeParams params, CancellationToken token) async {
     if (!isDartDocument(params.textDocument)) {
       return success(const []);
     }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
index 7426410..2760984 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
@@ -32,7 +32,7 @@
   }
 
   Future<ErrorOr<List<TextEdit>>> handle(
-      DocumentOnTypeFormattingParams params) async {
+      DocumentOnTypeFormattingParams params, CancellationToken token) async {
     final path = pathOfDoc(params.textDocument);
     return path.mapResult((path) => formatFile(path));
   }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
index effe549..a0587b7 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
@@ -32,7 +32,7 @@
   }
 
   Future<ErrorOr<List<TextEdit>>> handle(
-      DocumentFormattingParams params) async {
+      DocumentFormattingParams params, CancellationToken token) async {
     final path = pathOfDoc(params.textDocument);
     return path.mapResult((path) => formatFile(path));
   }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
index bd70948..b724b1a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
@@ -23,7 +23,8 @@
   LspJsonHandler<TextDocumentPositionParams> get jsonHandler =>
       TextDocumentPositionParams.jsonHandler;
 
-  Future<ErrorOr<Hover>> handle(TextDocumentPositionParams params) async {
+  Future<ErrorOr<Hover>> handle(
+      TextDocumentPositionParams params, CancellationToken token) async {
     if (!isDartDocument(params.textDocument)) {
       return success(null);
     }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart
index e131307..d6e7643 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart
@@ -23,7 +23,7 @@
 
   @override
   Future<ErrorOr<List<Location>>> handle(
-      TextDocumentPositionParams params) async {
+      TextDocumentPositionParams params, CancellationToken token) async {
     if (!isDartDocument(params.textDocument)) {
       return success(const []);
     }
@@ -33,13 +33,16 @@
     final unit = await path.mapResult(requireResolvedUnit);
     final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));
     return offset
-        .mapResult((offset) => _getImplementations(path.result, offset));
+        .mapResult((offset) => _getImplementations(path.result, offset, token));
   }
 
   Future<ErrorOr<List<Location>>> _getImplementations(
-      String file, int offset) async {
+      String file, int offset, CancelableToken token) async {
     final element = await server.getElementAtOffset(file, offset);
     final computer = new TypeHierarchyComputer(server.searchEngine, element);
+    if (token.isCancellationRequested) {
+      return cancelled();
+    }
     final items = await computer.compute();
 
     if (items == null || items.isEmpty) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
index ea1ed19..5b104b8 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
@@ -19,7 +19,8 @@
   LspJsonHandler<InitializeParams> get jsonHandler =>
       InitializeParams.jsonHandler;
 
-  ErrorOr<InitializeResult> handle(InitializeParams params) {
+  ErrorOr<InitializeResult> handle(
+      InitializeParams params, CancellationToken token) {
     final openWorkspacePaths = <String>[];
 
     // The onlyAnalyzeProjectsWithOpenFiles flag allows opening huge folders
@@ -69,6 +70,12 @@
     final renameOptionsSupport =
         params.capabilities.textDocument?.rename?.prepareSupport ?? false;
 
+    // When adding new capabilities to the server that may apply to specific file
+    // types, it's important to update
+    // [IntializedMessageHandler._performDynamicRegistration()] to notify
+    // supporting clients of this. This avoids clients needing to hard-code the
+    // list of what files types we support (and allows them to avoid sending
+    // requests where we have only partial support for some types).
     server.capabilities = new ServerCapabilities(
         Either2<TextDocumentSyncOptions, num>.t1(new TextDocumentSyncOptions(
           true,
@@ -80,33 +87,10 @@
         true, // hoverProvider
         new CompletionOptions(
           true, // resolveProvider
-          // Set the characters that will cause the editor to automatically
-          // trigger completion.
-          // TODO(dantup): There are several characters that we want to conditionally
-          // allow to trigger completion, but they can only be added when the completion
-          // provider is able to handle them in context:
-          //
-          //    {   trigger if being typed in a string immediately after a $
-          //    '   trigger if the opening quote for an import/export
-          //    "   trigger if the opening quote for an import/export
-          //    /   trigger if as part of a path in an import/export
-          //    \   trigger if as part of a path in an import/export
-          //    :   don't trigger when typing case expressions (`case x:`)
-          //
-          // Additionally, we need to prefix `filterText` on completion items
-          // with spaces for those that can follow whitespace (eg. `foo` in
-          // `myArg: foo`) to ensure they're not filtered away when the user
-          // types space.
-          //
-          // See https://github.com/Dart-Code/Dart-Code/blob/68d1cd271e88a785570257d487adbdec17abd6a3/src/providers/dart_completion_item_provider.ts#L36-L64
-          // for the VS Code implementation of this.
-          r'''.=($'''.split(''),
+          dartCompletionTriggerCharacters,
         ),
         new SignatureHelpOptions(
-          // TODO(dantup): Signature help triggering is even more sensitive to
-          // bad chars, so we'll need to implement the logic described here:
-          // https://github.com/dart-lang/sdk/issues/34241
-          [],
+          dartSignatureHelpTriggerCharacters,
         ),
         true, // definitionProvider
         null,
@@ -125,7 +109,8 @@
         null,
         true, // documentFormattingProvider
         false, // documentRangeFormattingProvider
-        new DocumentOnTypeFormattingOptions('}', [';']),
+        new DocumentOnTypeFormattingOptions(dartTypeFormattingCharacters.first,
+            dartTypeFormattingCharacters.skip(1).toList()),
         renameOptionsSupport
             ? Either2<bool, RenameOptions>.t2(new RenameOptions(true))
             : Either2<bool, RenameOptions>.t1(true),
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
index ea74fc5..27cf61a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
@@ -4,6 +4,7 @@
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_states.dart';
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
@@ -23,17 +24,161 @@
   LspJsonHandler<InitializedParams> get jsonHandler =>
       InitializedParams.jsonHandler;
 
-  ErrorOr<void> handle(InitializedParams params) {
+  ErrorOr<void> handle(InitializedParams params, CancellationToken token) {
     server.messageHandler = new InitializedStateMessageHandler(
       server,
       onlyAnalyzeProjectsWithOpenFiles,
       suggestFromUnimportedLibraries,
     );
 
+    _performDynamicRegistration();
+
     if (!onlyAnalyzeProjectsWithOpenFiles) {
       server.setAnalysisRoots(openWorkspacePaths);
     }
 
     return success();
   }
+
+  /// If the client supports dynamic registrations we can tell it what methods
+  /// we support for which documents. For example, this allows us to ask for
+  /// file edits for .dart as well as pubspec.yaml but only get hover/completion
+  /// calls for .dart. This functionality may not be supported by the client, in
+  /// which case they will use the ServerCapabilities to know which methods we
+  /// support and it will be up to them to decide which file types they will
+  /// send requests for.
+  Future<void> _performDynamicRegistration() async {
+    final dartFiles = DocumentFilter('dart', 'file', null);
+    final pubspecFile = DocumentFilter('yaml', 'file', '**/pubspec.yaml');
+    final analysisOptionsFile =
+        DocumentFilter('yaml', 'file', '**/analysis_options.yaml');
+    final allTypes = [dartFiles, pubspecFile, analysisOptionsFile];
+
+    // TODO(dantup): When we support plugins, we will need to collect their
+    // requirements too. For example, the Angular plugin might wish to add HTML
+    // `DocumentFilter('html', 'file', null)` to many of these requests.
+
+    int _lastRegistrationId = 1;
+    final registrations = <Registration>[];
+
+    /// Helper for creating registrations with IDs.
+    void register(bool condition, Method method, [ToJsonable options]) {
+      if (condition == true) {
+        registrations.add(Registration(
+            (_lastRegistrationId++).toString(), method.toJson(), options));
+      }
+    }
+
+    final textCapabilities = server.clientCapabilities?.textDocument;
+
+    register(
+      textCapabilities?.synchronization?.dynamicRegistration,
+      Method.textDocument_didOpen,
+      TextDocumentRegistrationOptions(allTypes),
+    );
+    register(
+      textCapabilities?.synchronization?.dynamicRegistration,
+      Method.textDocument_didClose,
+      TextDocumentRegistrationOptions(allTypes),
+    );
+    register(
+      textCapabilities?.synchronization?.dynamicRegistration,
+      Method.textDocument_didChange,
+      TextDocumentChangeRegistrationOptions(
+          TextDocumentSyncKind.Incremental, allTypes),
+    );
+    register(
+      server.clientCapabilities?.textDocument?.completion?.dynamicRegistration,
+      Method.textDocument_completion,
+      CompletionRegistrationOptions(
+        dartCompletionTriggerCharacters,
+        null,
+        true,
+        [dartFiles],
+      ),
+    );
+    register(
+      textCapabilities?.hover?.dynamicRegistration,
+      Method.textDocument_hover,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+    register(
+      textCapabilities?.signatureHelp?.dynamicRegistration,
+      Method.textDocument_signatureHelp,
+      SignatureHelpRegistrationOptions(
+          dartSignatureHelpTriggerCharacters, [dartFiles]),
+    );
+    register(
+      server.clientCapabilities?.textDocument?.references?.dynamicRegistration,
+      Method.textDocument_references,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+    register(
+      textCapabilities?.documentHighlight?.dynamicRegistration,
+      Method.textDocument_documentHighlight,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+    register(
+      textCapabilities?.documentSymbol?.dynamicRegistration,
+      Method.textDocument_documentSymbol,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+    register(
+      server.clientCapabilities?.textDocument?.formatting?.dynamicRegistration,
+      Method.textDocument_formatting,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+    register(
+      textCapabilities?.onTypeFormatting?.dynamicRegistration,
+      Method.textDocument_onTypeFormatting,
+      DocumentOnTypeFormattingRegistrationOptions(
+        dartTypeFormattingCharacters.first,
+        dartTypeFormattingCharacters.skip(1).toList(),
+        [dartFiles],
+      ),
+    );
+    register(
+      server.clientCapabilities?.textDocument?.definition?.dynamicRegistration,
+      Method.textDocument_definition,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+    register(
+      textCapabilities?.implementation?.dynamicRegistration,
+      Method.textDocument_implementation,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+    register(
+      server.clientCapabilities?.textDocument?.codeAction?.dynamicRegistration,
+      Method.textDocument_codeAction,
+      CodeActionRegistrationOptions(
+          [dartFiles], DartCodeActionKind.serverSupportedKinds),
+    );
+    register(
+      textCapabilities?.rename?.dynamicRegistration,
+      Method.textDocument_rename,
+      RenameRegistrationOptions(true, [dartFiles]),
+    );
+    register(
+      textCapabilities?.foldingRange?.dynamicRegistration,
+      Method.textDocument_foldingRange,
+      TextDocumentRegistrationOptions([dartFiles]),
+    );
+
+    // Only send the registration request if we have at least one (since
+    // otherwise we don't know that the client supports registerCapability).
+    if (registrations.isNotEmpty) {
+      final registrationResponse = await server.sendRequest(
+        Method.client_registerCapability,
+        RegistrationParams(registrations),
+      );
+
+      if (registrationResponse.error != null) {
+        server.logErrorToClient(
+          'Failed to register capabilities with client: '
+          '(${registrationResponse.error.code}) '
+          '${registrationResponse.error.message}',
+        );
+      }
+    }
+  }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
index f410e9f..c6660f4 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
@@ -28,7 +28,8 @@
       ReferenceParams.jsonHandler;
 
   @override
-  Future<ErrorOr<List<Location>>> handle(ReferenceParams params) async {
+  Future<ErrorOr<List<Location>>> handle(
+      ReferenceParams params, CancellationToken token) async {
     if (!isDartDocument(params.textDocument)) {
       return success(const []);
     }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart
index b006c00..37c7916 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart
@@ -21,7 +21,7 @@
   LspJsonHandler<void> get jsonHandler => NullJsonHandler;
 
   @override
-  ErrorOr<void> handle(void _) {
+  ErrorOr<void> handle(void _, CancellationToken token) {
     return error(errorCode, errorMessage, null);
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
index d997719..799eab6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
@@ -21,7 +21,7 @@
 
   @override
   Future<ErrorOr<RangeAndPlaceholder>> handle(
-      TextDocumentPositionParams params) async {
+      TextDocumentPositionParams params, CancellationToken token) async {
     final pos = params.position;
     final path = pathOfDoc(params.textDocument);
     final unit = await path.mapResult(requireResolvedUnit);
@@ -71,7 +71,8 @@
   LspJsonHandler<RenameParams> get jsonHandler => RenameParams.jsonHandler;
 
   @override
-  Future<ErrorOr<WorkspaceEdit>> handle(RenameParams params) async {
+  Future<ErrorOr<WorkspaceEdit>> handle(
+      RenameParams params, CancellationToken token) async {
     final pos = params.position;
     final path = pathOfDoc(params.textDocument);
     // If the client provided us a version doc identifier, we'll use it to ensure
@@ -106,6 +107,9 @@
 
       // Check the rename is valid here.
       final initStatus = await refactoring.checkInitialConditions();
+      if (token.isCancellationRequested) {
+        return cancelled();
+      }
       if (initStatus.hasError) {
         return error(
             ServerErrorCodes.RenameNotValid, initStatus.problem.message, null);
@@ -121,6 +125,9 @@
 
       // Final validation.
       final finalStatus = await refactoring.checkFinalConditions();
+      if (token.isCancellationRequested) {
+        return cancelled();
+      }
       if (finalStatus.hasError) {
         return error(
             ServerErrorCodes.RenameNotValid, finalStatus.problem.message, null);
@@ -128,6 +135,9 @@
 
       // Compute the actual change.
       final change = await refactoring.createChange();
+      if (token.isCancellationRequested) {
+        return cancelled();
+      }
 
       // Before we send anything back, ensure the original file didn't change
       // while we were computing changes.
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart
index c16a394..9349240 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart
@@ -16,7 +16,7 @@
   LspJsonHandler<void> get jsonHandler => NullJsonHandler;
 
   @override
-  ErrorOr<void> handle(void _) {
+  ErrorOr<void> handle(void _, CancellationToken token) {
     // Move to the Shutting Down state so we won't process any more
     // requests and the Exit notification will know it was a clean shutdown.
     server.messageHandler = new ShuttingDownStateMessageHandler(server);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
index cde88c9..642e77f 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
@@ -21,7 +21,7 @@
       TextDocumentPositionParams.jsonHandler;
 
   Future<ErrorOr<SignatureHelp>> handle(
-      TextDocumentPositionParams params) async {
+      TextDocumentPositionParams params, CancellationToken token) async {
     if (!isDartDocument(params.textDocument)) {
       return success(null);
     }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
index 60b6f53..3bcf9fd 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
@@ -41,7 +41,7 @@
 
   @override
   FutureOr<ErrorOr<Object>> handleUnknownMessage(IncomingMessage message) {
-    return failure(
+    return error(
         ErrorCodes.InternalError,
         'An unrecoverable error occurred and the server cannot process messages',
         null);
@@ -117,7 +117,7 @@
     if (message is! RequestMessage) {
       return success();
     }
-    return failure(
+    return error(
         ErrorCodes.ServerNotInitialized,
         'Unable to handle ${message.method} before the server is initialized '
         'and the client has sent the initialized notification');
@@ -137,7 +137,7 @@
     if (message is! RequestMessage) {
       return success();
     }
-    return failure(ErrorCodes.ServerNotInitialized,
+    return error(ErrorCodes.ServerNotInitialized,
         'Unable to handle ${message.method} before client has sent initialize request');
   }
 }
@@ -154,7 +154,7 @@
     if (message is! RequestMessage) {
       return success();
     }
-    return failure(ErrorCodes.InvalidRequest,
+    return error(ErrorCodes.InvalidRequest,
         'Unable to handle ${message.method} after shutdown request');
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
index e083f5d..46ab686 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
@@ -23,7 +23,8 @@
   LspJsonHandler<DidChangeTextDocumentParams> get jsonHandler =>
       DidChangeTextDocumentParams.jsonHandler;
 
-  ErrorOr<void> handle(DidChangeTextDocumentParams params) {
+  ErrorOr<void> handle(
+      DidChangeTextDocumentParams params, CancellationToken token) {
     final path = pathOfDoc(params.textDocument);
     return path.mapResult((path) => _changeFile(path, params));
   }
@@ -66,7 +67,8 @@
   LspJsonHandler<DidCloseTextDocumentParams> get jsonHandler =>
       DidCloseTextDocumentParams.jsonHandler;
 
-  ErrorOr<void> handle(DidCloseTextDocumentParams params) {
+  ErrorOr<void> handle(
+      DidCloseTextDocumentParams params, CancellationToken token) {
     final path = pathOfDoc(params.textDocument);
     return path.mapResult((path) {
       server.removePriorityFile(path);
@@ -111,7 +113,8 @@
   LspJsonHandler<DidOpenTextDocumentParams> get jsonHandler =>
       DidOpenTextDocumentParams.jsonHandler;
 
-  ErrorOr<void> handle(DidOpenTextDocumentParams params) {
+  ErrorOr<void> handle(
+      DidOpenTextDocumentParams params, CancellationToken token) {
     final doc = params.textDocument;
     final path = pathOfDocItem(doc);
     return path.mapResult((path) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart
index 0f748d5..c53327a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart
@@ -24,7 +24,7 @@
       WorkspaceSymbolParams.jsonHandler;
 
   Future<ErrorOr<List<SymbolInformation>>> handle(
-      WorkspaceSymbolParams params) async {
+      WorkspaceSymbolParams params, CancellationToken token) async {
     // Respond to empty queries with an empty list. The spec says this should
     // be non-empty, however VS Code's client sends empty requests (but then
     // appears to not render the results we supply anyway).
@@ -55,6 +55,9 @@
     for (var driver in server.driverMap.values) {
       final driverResults = await driver.search
           .declarations(regex, remainingResults, filePathsHashSet);
+      if (token.isCancellationRequested) {
+        return cancelled();
+      }
       declarations.addAll(driverResults);
       remainingResults -= driverResults.length;
     }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
index 29d6800..89a8c1b 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
@@ -7,6 +7,7 @@
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:analysis_server/src/lsp/handlers/handler_cancel_request.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_reject.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 import 'package:analyzer/dart/analysis/results.dart';
@@ -19,6 +20,22 @@
   return items.map(converter).where((item) => item != null);
 }
 
+class CancelableToken extends CancellationToken {
+  bool _isCancelled = false;
+
+  @override
+  bool get isCancellationRequested => _isCancelled;
+
+  void cancel() => _isCancelled = true;
+}
+
+/// A token used to signal cancellation of an operation. This allows computation
+/// to be skipped when a caller is no longer interested in the result, for example
+/// when a $/cancel request is recieved for an in-progress request.
+abstract class CancellationToken {
+  bool get isCancellationRequested;
+}
+
 abstract class CommandHandler<P, R> with Handler<P, R> {
   CommandHandler(LspAnalysisServer server) {
     this.server = server;
@@ -30,12 +47,6 @@
 mixin Handler<P, R> {
   LspAnalysisServer server;
 
-  ErrorOr<R> error<R>(ErrorCodes code, String message, String data) =>
-      new ErrorOr<R>.error(new ResponseError(code, message, data));
-
-  ErrorOr<R> failure<R>(ErrorOr<dynamic> error) =>
-      new ErrorOr<R>.error(error.error);
-
   Future<ErrorOr<ResolvedUnitResult>> requireResolvedUnit(String path) async {
     final result = await server.getResolvedUnit(path);
     if (result?.state != ResultState.VALID) {
@@ -51,8 +62,6 @@
     }
     return success(result);
   }
-
-  ErrorOr<R> success<R>([R t]) => new ErrorOr<R>.success(t);
 }
 
 /// An object that can handle messages and produce responses for requests.
@@ -69,41 +78,69 @@
   /// A handler that can parse and validate JSON params.
   LspJsonHandler<P> get jsonHandler;
 
-  FutureOr<ErrorOr<R>> handle(P params);
+  FutureOr<ErrorOr<R>> handle(P params, CancellationToken token);
 
   /// Handle the given [message]. If the [message] is a [RequestMessage], then the
   /// return value will be sent back in a [ResponseMessage].
   /// [NotificationMessage]s are not expected to return results.
-  FutureOr<ErrorOr<R>> handleMessage(IncomingMessage message) {
+  FutureOr<ErrorOr<R>> handleMessage(
+      IncomingMessage message, CancellationToken token) {
     if (!jsonHandler.validateParams(message.params)) {
       return error(ErrorCodes.InvalidParams,
           'Invalid params for ${message.method}', null);
     }
 
     final params = jsonHandler.convertParams(message.params);
-    return handle(params);
+    return handle(params, token);
   }
 }
 
+class NotCancelableToken extends CancellationToken {
+  @override
+  bool get isCancellationRequested => false;
+}
+
 /// A message handler that handles all messages for a given server state.
 abstract class ServerStateMessageHandler {
   final LspAnalysisServer server;
   final Map<Method, MessageHandler> _messageHandlers = {};
+  final CancelRequestHandler _cancelHandler;
+  final NotCancelableToken _notCancelableToken = NotCancelableToken();
 
-  ServerStateMessageHandler(this.server);
-
-  ErrorOr<Object> failure<Object>(ErrorCodes code, String message,
-          [String data]) =>
-      new ErrorOr<Object>.error(new ResponseError(code, message, data));
+  ServerStateMessageHandler(this.server)
+      : _cancelHandler = CancelRequestHandler(server) {
+    registerHandler(_cancelHandler);
+  }
 
   /// Handle the given [message]. If the [message] is a [RequestMessage], then the
   /// return value will be sent back in a [ResponseMessage].
   /// [NotificationMessage]s are not expected to return results.
   FutureOr<ErrorOr<Object>> handleMessage(IncomingMessage message) async {
     final handler = _messageHandlers[message.method];
-    return handler != null
-        ? handler.handleMessage(message)
-        : handleUnknownMessage(message);
+    if (handler == null) {
+      return handleUnknownMessage(message);
+    }
+
+    if (message is! RequestMessage) {
+      return handler.handleMessage(message, _notCancelableToken);
+    }
+
+    // Create a cancellation token that will allow us to cancel this request if
+    // requested to save processing (the handler will need to specifically
+    // check the token after `await` points).
+    final token = _cancelHandler.createToken(message);
+    try {
+      final result = await handler.handleMessage(message, token);
+      // Do a final check before returning the result, because if the request was
+      // cancelled we can save the overhead of serialising everything to JSON
+      // and the client to deserialising the same in order to read the ID to see
+      // that it was a request it didn't need (in the case of completions this
+      // can be quite large).
+      await Future.delayed(Duration.zero);
+      return token.isCancellationRequested ? cancelled() : result;
+    } finally {
+      _cancelHandler.clearToken(message);
+    }
   }
 
   FutureOr<ErrorOr<Object>> handleUnknownMessage(IncomingMessage message) {
@@ -112,8 +149,7 @@
     // to so they don't leave open requests on the client.
     return _isOptionalNotification(message)
         ? success()
-        : failure(
-            ErrorCodes.MethodNotFound, 'Unknown method ${message.method}');
+        : error(ErrorCodes.MethodNotFound, 'Unknown method ${message.method}');
   }
 
   registerHandler(MessageHandler handler) {
@@ -129,8 +165,6 @@
     registerHandler(new RejectMessageHandler(server, method, code, message));
   }
 
-  ErrorOr<Object> success<Object>([Object t]) => new ErrorOr<Object>.success(t);
-
   bool _isOptionalNotification(IncomingMessage message) {
     // Not a notification.
     if (message is! NotificationMessage) {
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index e8f5112..7fff986 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -88,9 +88,6 @@
    */
   RefactoringWorkspace _refactoringWorkspace;
 
-  RefactoringWorkspace get refactoringWorkspace => _refactoringWorkspace ??=
-      new RefactoringWorkspace(driverMap.values, searchEngine);
-
   /**
    * The versions of each document known to the server (keyed by path), used to
    * send back to the client for server-initiated edits so that the client can
@@ -172,10 +169,12 @@
     analysisDriverScheduler.status.listen(sendStatusNotification);
     analysisDriverScheduler.start();
 
-    declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
-    declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
-    analysisDriverScheduler.outOfBandWorker =
-        CompletionLibrariesWorker(declarationsTracker);
+    if (options.featureSet.completion) {
+      declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
+      declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
+      analysisDriverScheduler.outOfBandWorker =
+          CompletionLibrariesWorker(declarationsTracker);
+    }
 
     contextManager = new ContextManagerImpl(
         resourceProvider,
@@ -197,6 +196,9 @@
 
   Future<void> get exited => channel.closed;
 
+  RefactoringWorkspace get refactoringWorkspace => _refactoringWorkspace ??=
+      new RefactoringWorkspace(driverMap.values, searchEngine);
+
   addPriorityFile(String path) {
     final didAdd = priorityFiles.add(path);
     assert(didAdd);
@@ -326,6 +328,28 @@
     ));
   }
 
+  /// Logs an exception by sending it to the client (window/logMessage) and
+  /// recording it in a buffer on the server for diagnostics.
+  void logException(String message, exception, stackTrace) {
+    if (exception is CaughtException) {
+      stackTrace ??= exception.stackTrace;
+    }
+
+    final fullError = stackTrace == null ? message : '$message\n$stackTrace';
+
+    // Log the full message since showMessage above may be truncated or formatted
+    // badly (eg. VS Code takes the newlines out).
+    logErrorToClient(fullError);
+
+    // remember the last few exceptions
+    exceptions.add(new ServerException(
+      message,
+      exception,
+      stackTrace is StackTrace ? stackTrace : null,
+      false,
+    ));
+  }
+
   void publishDiagnostics(String path, List<Diagnostic> errors) {
     final params =
         new PublishDiagnosticsParams(Uri.file(path).toString(), errors);
@@ -414,28 +438,6 @@
     logException(message, exception, stackTrace);
   }
 
-  /// Logs an exception by sending it to the client (window/logMessage) and
-  /// recording it in a buffer on the server for diagnostics.
-  void logException(String message, exception, stackTrace) {
-    if (exception is CaughtException) {
-      stackTrace ??= exception.stackTrace;
-    }
-
-    final fullError = stackTrace == null ? message : '$message\n$stackTrace';
-
-    // Log the full message since showMessage above may be truncated or formatted
-    // badly (eg. VS Code takes the newlines out).
-    logErrorToClient(fullError);
-
-    // remember the last few exceptions
-    exceptions.add(new ServerException(
-      message,
-      exception,
-      stackTrace is StackTrace ? stackTrace : null,
-      false,
-    ));
-  }
-
   /// Send status notification to the client. The state of analysis is given by
   /// the [status] information.
   void sendStatusNotification(nd.AnalysisStatus status) {
@@ -447,7 +449,7 @@
   }
 
   void setAnalysisRoots(List<String> includedPaths) {
-    declarationsTracker.discardContexts();
+    declarationsTracker?.discardContexts();
     final uniquePaths = HashSet<String>.of(includedPaths ?? const []);
     contextManager.setRoots(uniquePaths.toList(), [], {});
     addContextsToDeclarationsTracker();
@@ -574,6 +576,11 @@
   }
 
   @override
+  void analysisOptionsUpdated(nd.AnalysisDriver driver) {
+    // TODO: implement analysisOptionsUpdated
+  }
+
+  @override
   void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) {
     nd.AnalysisDriver analysisDriver = analysisServer.driverMap[contextFolder];
     if (analysisDriver != null) {
diff --git a/pkg/analysis_server/lib/src/nullability/decorated_type.dart b/pkg/analysis_server/lib/src/nullability/decorated_type.dart
index 81abe99..0dbc5ac 100644
--- a/pkg/analysis_server/lib/src/nullability/decorated_type.dart
+++ b/pkg/analysis_server/lib/src/nullability/decorated_type.dart
@@ -35,29 +35,26 @@
   /// TODO(paulberry): how should we handle generic typedefs?
   final List<DecoratedType> typeArguments;
 
-  DecoratedType(this.type, this.node, NullabilityGraph graph,
+  DecoratedType(this.type, this.node,
       {this.returnType,
       this.positionalParameters = const [],
       this.namedParameters = const {},
       this.typeArguments = const []}) {
     assert(node != null);
     // The type system doesn't have a non-nullable version of `dynamic`.  So if
-    // the type is `dynamic`, verify that the node is directly downstream from
-    // Nullability.always.
-    assert(!type.isDynamic ||
-        graph
-            .getUnconditionalUpstreamNodes(node)
-            .contains(NullabilityNode.always));
+    // the type is `dynamic`, verify that the node was initially placed into a
+    // nullable state.
+    assert(!type.isDynamic || node.isNullable);
   }
 
   /// Creates a [DecoratedType] corresponding to the given [element], which is
   /// presumed to have come from code that is already migrated.
-  factory DecoratedType.forElement(Element element, NullabilityGraph graph) {
+  factory DecoratedType.forElement(Element element) {
     DecoratedType decorate(DartType type) {
       assert((type as TypeImpl).nullabilitySuffix ==
           NullabilitySuffix.star); // TODO(paulberry)
       if (type is FunctionType) {
-        var decoratedType = DecoratedType(type, NullabilityNode.never, graph,
+        var decoratedType = DecoratedType(type, NullabilityNode.never,
             returnType: decorate(type.returnType), positionalParameters: []);
         for (var parameter in type.parameters) {
           assert(parameter.isPositional); // TODO(paulberry)
@@ -66,7 +63,7 @@
         return decoratedType;
       } else if (type is InterfaceType) {
         assert(type.typeParameters.isEmpty); // TODO(paulberry)
-        return DecoratedType(type, NullabilityNode.never, graph);
+        return DecoratedType(type, NullabilityNode.never);
       } else {
         throw type.runtimeType; // TODO(paulberry)
       }
@@ -75,6 +72,8 @@
     DecoratedType decoratedType;
     if (element is MethodElement) {
       decoratedType = decorate(element.type);
+    } else if (element is PropertyAccessorElement) {
+      decoratedType = decorate(element.type);
     } else {
       throw element.runtimeType; // TODO(paulberry)
     }
@@ -86,11 +85,10 @@
   /// [undecoratedResult] is the result of the substitution, as determined by
   /// the normal type system.
   DecoratedType substitute(
-      NullabilityGraph graph,
       Map<TypeParameterElement, DecoratedType> substitution,
       DartType undecoratedResult) {
     if (substitution.isEmpty) return this;
-    return _substitute(graph, substitution, undecoratedResult);
+    return _substitute(substitution, undecoratedResult);
   }
 
   @override
@@ -121,7 +119,6 @@
 
   /// Internal implementation of [_substitute], used as a recursion target.
   DecoratedType _substitute(
-      NullabilityGraph graph,
       Map<TypeParameterElement, DecoratedType> substitution,
       DartType undecoratedResult) {
     var type = this.type;
@@ -136,16 +133,16 @@
             : undecoratedResult
                 .optionalParameterTypes[i - numRequiredParameters];
         newPositionalParameters.add(positionalParameters[i]
-            ._substitute(graph, substitution, undecoratedParameterType));
+            ._substitute(substitution, undecoratedParameterType));
       }
-      return DecoratedType(undecoratedResult, node, graph,
+      return DecoratedType(undecoratedResult, node,
           returnType: returnType._substitute(
-              graph, substitution, undecoratedResult.returnType),
+              substitution, undecoratedResult.returnType),
           positionalParameters: newPositionalParameters);
     } else if (type is TypeParameterType) {
       var inner = substitution[type.element];
       return DecoratedType(undecoratedResult,
-          NullabilityNode.forSubstitution(inner?.node, node), graph);
+          NullabilityNode.forSubstitution(inner?.node, node));
     } else if (type is VoidType) {
       return this;
     }
@@ -162,10 +159,10 @@
     implements PotentialModification {
   final int _offset;
 
-  DecoratedTypeAnnotation(DartType type, NullabilityNode nullabilityNode,
-      this._offset, NullabilityGraph graph,
+  DecoratedTypeAnnotation(
+      DartType type, NullabilityNode nullabilityNode, this._offset,
       {List<DecoratedType> typeArguments = const []})
-      : super(type, nullabilityNode, graph, typeArguments: typeArguments);
+      : super(type, nullabilityNode, typeArguments: typeArguments);
 
   @override
   bool get isEmpty => !node.isNullable;
diff --git a/pkg/analysis_server/lib/src/nullability/decorated_type_operations.dart b/pkg/analysis_server/lib/src/nullability/decorated_type_operations.dart
index 59164ce..0788209 100644
--- a/pkg/analysis_server/lib/src/nullability/decorated_type_operations.dart
+++ b/pkg/analysis_server/lib/src/nullability/decorated_type_operations.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.
 
-import 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
 import 'package:analysis_server/src/nullability/decorated_type.dart';
+import 'package:analysis_server/src/nullability/node_builder.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis.dart';
diff --git a/pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart b/pkg/analysis_server/lib/src/nullability/graph_builder.dart
similarity index 85%
rename from pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart
rename to pkg/analysis_server/lib/src/nullability/graph_builder.dart
index 20532c1..c2f4bfa 100644
--- a/pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart
+++ b/pkg/analysis_server/lib/src/nullability/graph_builder.dart
@@ -3,11 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/nullability/conditional_discard.dart';
-import 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
 import 'package:analysis_server/src/nullability/decorated_type.dart';
 import 'package:analysis_server/src/nullability/expression_checks.dart';
+import 'package:analysis_server/src/nullability/node_builder.dart';
 import 'package:analysis_server/src/nullability/nullability_node.dart';
-import 'package:analysis_server/src/nullability/transitional_api.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -18,22 +17,20 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:meta/meta.dart';
 
-/// Visitor that gathers nullability migration constraints from code to be
+/// Visitor that builds nullability graph edges by examining code to be
 /// migrated.
 ///
 /// The return type of each `visit...` method is a [DecoratedType] indicating
 /// the static type of the visited expression, along with the constraint
 /// variables that will determine its nullability.  For `visit...` methods that
 /// don't visit expressions, `null` will be returned.
-class ConstraintGatherer extends GeneralizingAstVisitor<DecoratedType> {
+class GraphBuilder extends GeneralizingAstVisitor<DecoratedType> {
   /// The repository of constraint variables and decorated types (from a
   /// previous pass over the source code).
   final VariableRepository _variables;
 
   final bool _permissive;
 
-  final NullabilityMigrationAssumptions assumptions;
-
   final NullabilityGraph _graph;
 
   /// The file being analyzed.
@@ -76,16 +73,16 @@
   /// or expression.
   bool _inConditionalControlFlow = false;
 
-  ConstraintGatherer(TypeProvider typeProvider, this._variables, this._graph,
-      this._source, this._permissive, this.assumptions)
-      : _notNullType = DecoratedType(
-            typeProvider.objectType, NullabilityNode.never, _graph),
+  GraphBuilder(TypeProvider typeProvider, this._variables, this._graph,
+      this._source, this._permissive)
+      : _notNullType =
+            DecoratedType(typeProvider.objectType, NullabilityNode.never),
         _nonNullableBoolType =
-            DecoratedType(typeProvider.boolType, NullabilityNode.never, _graph),
+            DecoratedType(typeProvider.boolType, NullabilityNode.never),
         _nonNullableTypeType =
-            DecoratedType(typeProvider.typeType, NullabilityNode.never, _graph),
-        _nullType = DecoratedType(
-            typeProvider.nullType, NullabilityNode.always, _graph);
+            DecoratedType(typeProvider.typeType, NullabilityNode.never),
+        _nullType =
+            DecoratedType(typeProvider.nullType, NullabilityNode.always);
 
   /// Gets the decorated type of [element] from [_variables], performing any
   /// necessary substitutions.
@@ -121,7 +118,7 @@
       } else {
         throw element.runtimeType; // TODO(paulberry)
       }
-      return decoratedBaseType.substitute(_graph, substitution, elementType);
+      return decoratedBaseType.substitute(substitution, elementType);
     } else {
       return decoratedBaseType;
     }
@@ -184,7 +181,7 @@
 
   @override
   DecoratedType visitBooleanLiteral(BooleanLiteral node) {
-    return DecoratedType(node.staticType, NullabilityNode.never, _graph);
+    return DecoratedType(node.staticType, NullabilityNode.never);
   }
 
   @override
@@ -201,10 +198,8 @@
     assert(_isSimple(thenType)); // TODO(paulberry)
     var elseType = node.elseExpression.accept(this);
     assert(_isSimple(elseType)); // TODO(paulberry)
-    var overallType = DecoratedType(
-        node.staticType,
-        NullabilityNode.forLUB(node, thenType.node, elseType.node, _graph),
-        _graph);
+    var overallType = DecoratedType(node.staticType,
+        NullabilityNode.forLUB(node, thenType.node, elseType.node, _graph));
     _variables.recordDecoratedExpressionType(node, overallType);
     return overallType;
   }
@@ -216,18 +211,10 @@
       if (node.declaredElement.hasRequired) {
         // Nothing to do; the implicit default value of `null` will never be
         // reached.
-      } else if (node.declaredElement.isOptionalPositional ||
-          assumptions.namedNoDefaultParameterHeuristic ==
-              NamedNoDefaultParameterHeuristic.assumeNullable) {
-        NullabilityNode.recordAssignment(
-            NullabilityNode.always,
-            getOrComputeElementType(node.declaredElement).node,
-            _guards,
-            _graph,
-            false);
       } else {
-        assert(assumptions.namedNoDefaultParameterHeuristic ==
-            NamedNoDefaultParameterHeuristic.assumeRequired);
+        NullabilityNode.recordAssignment(NullabilityNode.always,
+            getOrComputeElementType(node.declaredElement).node, _guards, _graph,
+            hard: false);
       }
     } else {
       _handleAssignment(
@@ -297,12 +284,12 @@
 
   @override
   DecoratedType visitIntegerLiteral(IntegerLiteral node) {
-    return DecoratedType(node.staticType, NullabilityNode.never, _graph);
+    return DecoratedType(node.staticType, NullabilityNode.never);
   }
 
   @override
   DecoratedType visitMethodDeclaration(MethodDeclaration node) {
-    node.parameters.accept(this);
+    node.parameters?.accept(this);
     assert(_currentFunctionType == null);
     _currentFunctionType =
         _variables.decoratedElementType(node.declaredElement);
@@ -319,12 +306,16 @@
   DecoratedType visitMethodInvocation(MethodInvocation node) {
     DecoratedType targetType;
     if (node.target != null) {
-      assert(node.operator.type == TokenType.PERIOD);
+      if (node.operator.type != TokenType.PERIOD) {
+        throw new UnimplementedError('TODO(paulberry)');
+      }
       _checkNonObjectMember(node.methodName.name); // TODO(paulberry)
       targetType = _handleAssignment(_notNullType, node.target);
     }
     var callee = node.methodName.staticElement;
-    assert(callee != null); // TODO(paulberry)
+    if (callee == null) {
+      throw new UnimplementedError('TODO(paulberry)');
+    }
     var calleeType = getOrComputeElementType(callee, targetType: targetType);
     // TODO(paulberry): substitute if necessary
     var arguments = node.argumentList.arguments;
@@ -374,6 +365,20 @@
   }
 
   @override
+  DecoratedType visitPrefixedIdentifier(PrefixedIdentifier node) {
+    if (node.prefix.staticElement is ImportElement) {
+      throw new UnimplementedError('TODO(paulberry)');
+    } else {
+      return _handlePropertyAccess(node.prefix, node.period, node.identifier);
+    }
+  }
+
+  @override
+  DecoratedType visitPropertyAccess(PropertyAccess node) {
+    return _handlePropertyAccess(node.target, node.operator, node.propertyName);
+  }
+
+  @override
   DecoratedType visitReturnStatement(ReturnStatement node) {
     if (node.expression == null) {
       _checkAssignment(_currentFunctionType.returnType, _nullType, null);
@@ -398,19 +403,19 @@
 
   @override
   DecoratedType visitStringLiteral(StringLiteral node) {
-    return DecoratedType(node.staticType, NullabilityNode.never, _graph);
+    return DecoratedType(node.staticType, NullabilityNode.never);
   }
 
   @override
   DecoratedType visitThisExpression(ThisExpression node) {
-    return DecoratedType(node.staticType, NullabilityNode.never, _graph);
+    return DecoratedType(node.staticType, NullabilityNode.never);
   }
 
   @override
   DecoratedType visitThrowExpression(ThrowExpression node) {
     node.expression.accept(this);
     // TODO(paulberry): do we need to check the expression type?  I think not.
-    return DecoratedType(node.staticType, NullabilityNode.never, _graph);
+    return DecoratedType(node.staticType, NullabilityNode.never);
   }
 
   @override
@@ -426,13 +431,12 @@
         } else {
           throw new UnimplementedError('TODO(paulberry)');
         }
-        _checkAssignment(
-            bound,
-            _variables.decoratedTypeAnnotation(_source, typeArguments[i]),
-            null);
+        _checkAssignment(bound,
+            _variables.decoratedTypeAnnotation(_source, typeArguments[i]), null,
+            hard: true);
       }
     }
-    return DecoratedType(typeName.type, NullabilityNode.never, _graph);
+    return DecoratedType(typeName.type, NullabilityNode.never);
   }
 
   /// Creates the necessary constraint(s) for an assignment from [sourceType] to
@@ -440,7 +444,8 @@
   /// [sourceType]; it is the expression we will have to null-check in the case
   /// where a nullable source is assigned to a non-nullable destination.
   void _checkAssignment(DecoratedType destinationType, DecoratedType sourceType,
-      Expression expression) {
+      Expression expression,
+      {bool hard}) {
     if (expression != null) {
       _variables.recordExpressionChecks(
           _source,
@@ -448,8 +453,11 @@
           ExpressionChecks(
               expression.end, sourceType.node, destinationType.node, _guards));
     }
-    NullabilityNode.recordAssignment(sourceType.node, destinationType.node,
-        _guards, _graph, _inConditionalControlFlow);
+    NullabilityNode.recordAssignment(
+        sourceType.node, destinationType.node, _guards, _graph,
+        hard: hard ??
+            (_isVariableOrParameterReference(expression) &&
+                !_inConditionalControlFlow));
     // TODO(paulberry): it's a cheat to pass in expression=null for the
     // recursive checks.  Really we want to unify all the checks in a single
     // ExpressionChecks object.
@@ -497,6 +505,22 @@
     return sourceType;
   }
 
+  DecoratedType _handlePropertyAccess(
+      Expression target, Token operator, SimpleIdentifier propertyName) {
+    if (operator.type != TokenType.PERIOD) {
+      throw new UnimplementedError('TODO(paulberry)');
+    }
+    _checkNonObjectMember(propertyName.name); // TODO(paulberry)
+    var targetType = _handleAssignment(_notNullType, target);
+    var callee = propertyName.staticElement;
+    if (callee == null) {
+      throw new UnimplementedError('TODO(paulberry)');
+    }
+    var calleeType = getOrComputeElementType(callee, targetType: targetType);
+    // TODO(paulberry): substitute if necessary
+    return calleeType.returnType;
+  }
+
   /// Double checks that [type] is sufficiently simple for this naive prototype
   /// implementation.
   ///
@@ -509,6 +533,15 @@
     if ((type.type as InterfaceType).typeParameters.isNotEmpty) return false;
     return true;
   }
+
+  bool _isVariableOrParameterReference(Expression expression) {
+    if (expression is SimpleIdentifier) {
+      var element = expression.staticElement;
+      if (element is LocalVariableElement) return true;
+      if (element is ParameterElement) return true;
+    }
+    return false;
+  }
 }
 
 /// Information about a binary expression whose boolean value could possibly
diff --git a/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart b/pkg/analysis_server/lib/src/nullability/node_builder.dart
similarity index 89%
rename from pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart
rename to pkg/analysis_server/lib/src/nullability/node_builder.dart
index fbabd5a..b85765b 100644
--- a/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart
+++ b/pkg/analysis_server/lib/src/nullability/node_builder.dart
@@ -6,7 +6,6 @@
 import 'package:analysis_server/src/nullability/decorated_type.dart';
 import 'package:analysis_server/src/nullability/expression_checks.dart';
 import 'package:analysis_server/src/nullability/nullability_node.dart';
-import 'package:analysis_server/src/nullability/transitional_api.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -15,14 +14,13 @@
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
 
-/// Visitor that gathers constraint variables for nullability migration from
-/// code to be migrated.
+/// Visitor that builds nullability nodes based on visiting code to be migrated.
 ///
 /// The return type of each `visit...` method is a [DecoratedType] indicating
 /// the static type of the element declared by the visited node, along with the
 /// constraint variables that will determine its nullability.  For `visit...`
 /// methods that don't visit declarations, `null` will be returned.
-class ConstraintVariableGatherer extends GeneralizingAstVisitor<DecoratedType> {
+class NodeBuilder extends GeneralizingAstVisitor<DecoratedType> {
   /// Constraint variables and decorated types are stored here.
   final VariableRecorder _variables;
 
@@ -39,14 +37,12 @@
 
   final bool _permissive;
 
-  final NullabilityMigrationAssumptions assumptions;
-
   final NullabilityGraph _graph;
 
   final TypeProvider _typeProvider;
 
-  ConstraintVariableGatherer(this._variables, this._source, this._permissive,
-      this.assumptions, this._graph, this._typeProvider);
+  NodeBuilder(this._variables, this._source, this._permissive, this._graph,
+      this._typeProvider);
 
   /// Creates and stores a [DecoratedType] object corresponding to the given
   /// [type] AST, and returns it.
@@ -58,8 +54,7 @@
         ? new DecoratedType(
             DynamicTypeImpl.instance,
             NullabilityNode.forInferredDynamicType(
-                _graph, enclosingNode.offset),
-            _graph)
+                _graph, enclosingNode.offset))
         : type.accept(this);
   }
 
@@ -132,8 +127,8 @@
     assert(node is NamedType); // TODO(paulberry)
     var type = node.type;
     if (type.isVoid) {
-      return DecoratedType(type,
-          NullabilityNode.forTypeAnnotation(node.end, always: true), _graph);
+      return DecoratedType(
+          type, NullabilityNode.forTypeAnnotation(node.end, always: true));
     }
     assert(
         type is InterfaceType || type is TypeParameterType); // TODO(paulberry)
@@ -152,7 +147,6 @@
         NullabilityNode.forTypeAnnotation(node.end,
             always: node.question != null),
         node.end,
-        _graph,
         typeArguments: typeArguments);
     _variables.recordDecoratedTypeAnnotation(_source, node, decoratedType);
     return decoratedType;
@@ -165,10 +159,8 @@
   DecoratedType visitTypeParameter(TypeParameter node) {
     var element = node.declaredElement;
     var decoratedBound = node.bound?.accept(this) ??
-        DecoratedType(
-            element.bound ?? _typeProvider.objectType,
-            NullabilityNode.forInferredDynamicType(_graph, node.offset),
-            _graph);
+        DecoratedType(element.bound ?? _typeProvider.objectType,
+            NullabilityNode.forInferredDynamicType(_graph, node.offset));
     _variables.recordDecoratedElementType(element, decoratedBound);
     return null;
   }
@@ -184,13 +176,13 @@
     // TODO(paulberry): test that it's correct to use `null` for the nullability
     // of the function type
     var functionType = DecoratedType(
-        declaredElement.type, NullabilityNode.never, _graph,
+        declaredElement.type, NullabilityNode.never,
         returnType: decoratedReturnType,
         positionalParameters: [],
         namedParameters: {});
     _currentFunctionType = functionType;
     try {
-      parameters.accept(this);
+      parameters?.accept(this);
     } finally {
       _currentFunctionType = previousFunctionType;
     }
@@ -202,7 +194,7 @@
 /// code being migrated.
 ///
 /// This data structure records the results of the first pass of migration
-/// ([ConstraintVariableGatherer], which finds all the variables that need to be
+/// ([NodeBuilder], which finds all the variables that need to be
 /// constrained).
 abstract class VariableRecorder {
   /// Associates decorated type information with the given [element].
@@ -224,7 +216,7 @@
 ///
 /// This data structure allows the second pass of migration
 /// ([ConstraintGatherer], which builds all the constraints) to access the
-/// results of the first ([ConstraintVariableGatherer], which finds all the
+/// results of the first ([NodeBuilder], which finds all the
 /// variables that need to be constrained).
 abstract class VariableRepository {
   /// Retrieves the [DecoratedType] associated with the static type of the given
diff --git a/pkg/analysis_server/lib/src/nullability/nullability_node.dart b/pkg/analysis_server/lib/src/nullability/nullability_node.dart
index ebd221c..453887d 100644
--- a/pkg/analysis_server/lib/src/nullability/nullability_node.dart
+++ b/pkg/analysis_server/lib/src/nullability/nullability_node.dart
@@ -5,28 +5,60 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:meta/meta.dart';
 
+/// Data structure to keep track of the relationship from one [NullabilityNode]
+/// object to another [NullabilityNode] that is "downstream" from it (meaning
+/// that if the former node is nullable, then the latter node will either have
+/// to be nullable, or null checks will have to be added).
+class NullabilityEdge {
+  /// The node that is downstream.
+  final NullabilityNode destinationNode;
+
+  /// A set of source nodes.  By convention, the first node is the primary
+  /// source and the other nodes are "guards".  The destination node will only
+  /// need to be made nullable if all the source nodes are nullable.
+  final List<NullabilityNode> sources;
+
+  final bool hard;
+
+  NullabilityEdge(this.destinationNode, this.sources, this.hard);
+
+  Iterable<NullabilityNode> get guards => sources.skip(1);
+
+  NullabilityNode get primarySource => sources.first;
+}
+
 /// Data structure to keep track of the relationship between [NullabilityNode]
 /// objects.
 class NullabilityGraph {
+  /// Set this const to `true` to dump the nullability graph just before
+  /// propagation.
+  static const _debugBeforePropagation = false;
+
   /// Set containing all [NullabilityNode]s that have been passed as the
   /// `sourceNode` argument to [connect].
   final _allSourceNodes = Set<NullabilityNode>.identity();
 
-  /// List of [_NullabilityEdge] objects that are downstream from
+  /// List of [NullabilityEdge] objects that are downstream from
   /// [NullabilityNode.always].  (They can't be stored in
   /// [NullabilityNode.always] directly because it is immutable).
-  final _downstreamFromAlways = <_NullabilityEdge>[];
+  final _downstreamFromAlways = <NullabilityEdge>[];
 
-  /// List of [NullabilityNodes] that are "upstream" from
+  /// List of [NullabilityEdge] objects that are upstream from
   /// [NullabilityNode.never] due to unconditional control flow.  (They can't be
   /// stored in [NullabilityNode.never] directly because it is immutable).
-  final _unconditionalUpstreamFromNever = <NullabilityNode>[];
+  final _upstreamFromNever = <NullabilityEdge>[];
+
+  /// List of [NullabilityNodeMutable] objects that were set into the nullable
+  /// state by a process other than nullability propagation.  The next time
+  /// nullability is propagated, the propagation algorithm will ensure that
+  /// edges originating at these nodes are examined.
+  final _pendingDownstreamNodes = <NullabilityNodeMutable>[];
 
   /// Records that [sourceNode] is immediately upstream from [destinationNode].
   void connect(NullabilityNode sourceNode, NullabilityNode destinationNode,
-      {bool unconditional: false, List<NullabilityNode> guards: const []}) {
+      {bool hard: false, List<NullabilityNode> guards: const []}) {
     var sources = [sourceNode]..addAll(guards);
-    var edge = _NullabilityEdge(destinationNode, sources);
+    var edge = NullabilityEdge(destinationNode, sources, hard);
     for (var source in sources) {
       _allSourceNodes.add(source);
       if (source is NullabilityNodeMutable) {
@@ -39,16 +71,14 @@
         assert(source == NullabilityNode.never);
       }
     }
-    if (unconditional) {
-      if (destinationNode is NullabilityNodeMutable) {
-        destinationNode._unconditionalUpstreamNodes.add(sourceNode);
-      } else if (destinationNode == NullabilityNode.never) {
-        _unconditionalUpstreamFromNever.add(sourceNode);
-      } else {
-        // We don't need to track nodes that are upstream from `always` because
-        // `always` will never have non-null intent.
-        assert(destinationNode == NullabilityNode.always);
-      }
+    if (destinationNode is NullabilityNodeMutable) {
+      destinationNode._upstreamEdges.add(edge);
+    } else if (destinationNode == NullabilityNode.never) {
+      _upstreamFromNever.add(edge);
+    } else {
+      // We don't need to track nodes that are upstream from `always` because
+      // `always` will never have non-null intent.
+      assert(destinationNode == NullabilityNode.always);
     }
   }
 
@@ -58,46 +88,27 @@
       var destinations =
           edges.where((edge) => edge.primarySource == source).map((edge) {
         var suffixes = <Object>[];
-        if (getUnconditionalUpstreamNodes(edge.destinationNode)
-            .contains(source)) {
-          suffixes.add('unconditional');
+        if (edge.hard) {
+          suffixes.add('hard');
         }
         suffixes.addAll(edge.guards);
         var suffix = suffixes.isNotEmpty ? ' (${suffixes.join(', ')})' : '';
         return '${edge.destinationNode}$suffix';
       });
-      var suffixes = <String>[];
-      if (source.isNullable) {
-        suffixes.add('nullable');
-      }
-      if (source.hasNonNullIntent) {
-        suffixes.add('non-null intent');
-      }
-      var suffix = suffixes.isNotEmpty ? ' (${suffixes.join(', ')})' : '';
-      print('$source$suffix -> ${destinations.join(', ')}');
+      var state = source._state;
+      print('$source ($state) -> ${destinations.join(', ')}');
     }
   }
 
-  /// Iterates through all nodes that are "downstream" of [node] (i.e. if
-  /// [node] is nullable, then all the iterated nodes will either have to be
-  /// nullable, or null checks will have to be added).
-  ///
-  /// There is no guarantee of uniqueness of the iterated nodes.
-  Iterable<NullabilityNode> getDownstreamNodes(NullabilityNode node) =>
-      _getDownstreamEdges(node)
-          .where((edge) => edge.primarySource == node)
-          .map((edge) => edge.destinationNode);
-
   /// Iterates through all nodes that are "upstream" of [node] due to
   /// unconditional control flow.
   ///
   /// There is no guarantee of uniqueness of the iterated nodes.
-  Iterable<NullabilityNode> getUnconditionalUpstreamNodes(
-      NullabilityNode node) {
+  Iterable<NullabilityEdge> getUpstreamEdges(NullabilityNode node) {
     if (node is NullabilityNodeMutable) {
-      return node._unconditionalUpstreamNodes;
+      return node._upstreamEdges;
     } else if (node == NullabilityNode.never) {
-      return _unconditionalUpstreamFromNever;
+      return _upstreamFromNever;
     } else {
       // No nodes are upstream from `always`.
       assert(node == NullabilityNode.always);
@@ -128,11 +139,12 @@
   /// Determines the nullability of each node in the graph by propagating
   /// nullability information from one node to another.
   void propagate() {
+    if (_debugBeforePropagation) debugDump();
     _propagateUpstream();
     _propagateDownstream();
   }
 
-  Iterable<_NullabilityEdge> _getDownstreamEdges(NullabilityNode node) {
+  Iterable<NullabilityEdge> _getDownstreamEdges(NullabilityNode node) {
     if (node is NullabilityNodeMutable) {
       return node._downstreamEdges;
     } else if (node == NullabilityNode.always) {
@@ -146,15 +158,19 @@
 
   /// Propagates nullability downstream.
   void _propagateDownstream() {
-    var pendingEdges = <_NullabilityEdge>[]..addAll(_downstreamFromAlways);
+    var pendingEdges = <NullabilityEdge>[]..addAll(_downstreamFromAlways);
+    for (var node in _pendingDownstreamNodes) {
+      pendingEdges.addAll(node._downstreamEdges);
+    }
+    _pendingDownstreamNodes.clear();
     var pendingSubstitutions = <NullabilityNodeForSubstitution>[];
     while (true) {
       nextEdge:
       while (pendingEdges.isNotEmpty) {
         var edge = pendingEdges.removeLast();
         var node = edge.destinationNode;
-        if (node.hasNonNullIntent) {
-          // Non-null intent nodes are never made nullable; a null check will need
+        if (node._state == _NullabilityState.nonNullable) {
+          // Non-nullable nodes are never made nullable; a null check will need
           // to be added instead.
           continue;
         }
@@ -164,7 +180,8 @@
             continue nextEdge;
           }
         }
-        if (node is NullabilityNodeMutable && node._becomeNullable()) {
+        if (node is NullabilityNodeMutable && !node.isNullable) {
+          node._state = _NullabilityState.ordinaryNullable;
           // Was not previously nullable, so we need to propagate.
           pendingEdges.addAll(node._downstreamEdges);
           if (node is NullabilityNodeForSubstitution) {
@@ -181,25 +198,24 @@
       }
       // Heuristically choose to propagate to the inner node since this seems
       // to lead to better quality migrations.
-      pendingEdges.add(_NullabilityEdge(node.innerNode, const []));
+      pendingEdges.add(NullabilityEdge(node.innerNode, const [], false));
     }
   }
 
   /// Propagates non-null intent upstream along unconditional control flow
   /// lines.
   void _propagateUpstream() {
-    var pendingNodes = <NullabilityNode>[]
-      ..addAll(_unconditionalUpstreamFromNever);
-    while (pendingNodes.isNotEmpty) {
-      var node = pendingNodes.removeLast();
-      if (node == NullabilityNode.always) {
-        // The "always" node cannot have non-null intent.
-        continue;
-      }
-      if (node is NullabilityNodeMutable && node._setNonNullIntent()) {
+    var pendingEdges = <NullabilityEdge>[]..addAll(_upstreamFromNever);
+    while (pendingEdges.isNotEmpty) {
+      var edge = pendingEdges.removeLast();
+      if (!edge.hard) continue;
+      var node = edge.primarySource;
+      if (node is NullabilityNodeMutable &&
+          node._state == _NullabilityState.undetermined) {
+        node._state = _NullabilityState.nonNullable;
         // Was not previously in the set of non-null intent nodes, so we need to
         // propagate.
-        pendingNodes.addAll(node._unconditionalUpstreamNodes);
+        pendingEdges.addAll(node._upstreamEdges);
       }
     }
   }
@@ -235,8 +251,9 @@
   /// inferred type rather than assuming `dynamic`.
   factory NullabilityNode.forInferredDynamicType(
       NullabilityGraph graph, int offset) {
-    var node = _NullabilityNodeSimple('inferredDynamic($offset)');
-    graph.connect(NullabilityNode.always, node, unconditional: true);
+    var node = _NullabilityNodeSimple('inferredDynamic($offset)',
+        initialState: _NullabilityState.ordinaryNullable);
+    graph._pendingDownstreamNodes.add(node);
     return node;
   }
 
@@ -281,8 +298,6 @@
   String get debugSuffix =>
       this == always ? '?' : this == never ? '' : '?($this)';
 
-  bool get hasNonNullIntent;
-
   /// After nullability propagation, this getter can be used to query whether
   /// the type associated with this node should be considered nullable.
   bool get isNullable;
@@ -293,6 +308,8 @@
 
   String get _debugPrefix;
 
+  _NullabilityState get _state;
+
   /// Records the fact that an invocation was made to a function with named
   /// parameters, and the named parameter associated with this node was not
   /// supplied.
@@ -305,7 +322,7 @@
 
   void recordNonNullIntent(
       List<NullabilityNode> guards, NullabilityGraph graph) {
-    graph.connect(this, NullabilityNode.never, unconditional: true);
+    graph.connect(this, NullabilityNode.never, hard: true);
   }
 
   String toString() {
@@ -348,9 +365,8 @@
       NullabilityNode destinationNode,
       List<NullabilityNode> guards,
       NullabilityGraph graph,
-      bool inConditionalControlFlow) {
-    graph.connect(sourceNode, destinationNode,
-        guards: guards, unconditional: !inConditionalControlFlow);
+      {@required bool hard}) {
+    graph.connect(sourceNode, destinationNode, guards: guards, hard: hard);
   }
 }
 
@@ -400,70 +416,27 @@
 /// Nearly all nullability nodes derive from this class; the only exceptions are
 /// the fixed nodes [NullabilityNode.always] and [NullabilityNode.never].
 abstract class NullabilityNodeMutable extends NullabilityNode {
-  bool _isNullable = false;
+  _NullabilityState _state;
 
-  bool _hasNonNullIntent = false;
-
-  /// List of [_NullabilityEdge] objects describing this node's relationship to
+  /// List of [NullabilityEdge] objects describing this node's relationship to
   /// other nodes that are "downstream" from it (meaning that if a key node is
   /// nullable, then all the nodes in the corresponding value will either have
   /// to be nullable, or null checks will have to be added).
-  final _downstreamEdges = <_NullabilityEdge>[];
+  final _downstreamEdges = <NullabilityEdge>[];
 
   /// List of nodes that are "upstream" from this node via unconditional control
   /// flow (meaning that if a node in the list is nullable, then there exists
   /// code that is unguarded by an "if" statement that indicates that this node
   /// will have to be nullable, or null checks will have to be added).
-  final _unconditionalUpstreamNodes = <NullabilityNode>[];
+  final _upstreamEdges = <NullabilityEdge>[];
 
-  NullabilityNodeMutable._() : super._();
+  NullabilityNodeMutable._(
+      {_NullabilityState initialState: _NullabilityState.undetermined})
+      : _state = initialState,
+        super._();
 
   @override
-  bool get hasNonNullIntent => _hasNonNullIntent;
-
-  @override
-  bool get isNullable => _isNullable;
-
-  /// During nullability propagation, this method marks the type as nullable, or
-  /// does nothing if the type was already nullable.
-  ///
-  /// Return value indicates whether a change was made.
-  bool _becomeNullable() {
-    if (_isNullable) return false;
-    _isNullable = true;
-    return true;
-  }
-
-  /// During nullability propagation, this method marks the type as having
-  /// non-null intent, or does nothing if the type was already marked as having
-  /// non-null intent.
-  ///
-  /// Return value indicates whether a change was made.
-  bool _setNonNullIntent() {
-    if (_hasNonNullIntent) return false;
-    _hasNonNullIntent = true;
-    return true;
-  }
-}
-
-/// Data structure to keep track of the relationship from one [NullabilityNode]
-/// object to another [NullabilityNode] that is "downstream" from it (meaning
-/// that if the former node is nullable, then the latter node will either have
-/// to be nullable, or null checks will have to be added).
-class _NullabilityEdge {
-  /// The node that is downstream.
-  final NullabilityNode destinationNode;
-
-  /// A set of source nodes.  By convention, the first node is the primary
-  /// source and the other nodes are "guards".  The destination node will only
-  /// need to be made nullable if all the source nodes are nullable.
-  final List<NullabilityNode> sources;
-
-  _NullabilityEdge(this.destinationNode, this.sources);
-
-  Iterable<NullabilityNode> get guards => sources.skip(1);
-
-  NullabilityNode get primarySource => sources.first;
+  bool get isNullable => _state.isNullable;
 }
 
 class _NullabilityNodeImmutable extends NullabilityNode {
@@ -476,12 +449,50 @@
   _NullabilityNodeImmutable(this._debugPrefix, this.isNullable) : super._();
 
   @override
-  bool get hasNonNullIntent => !isNullable;
+  _NullabilityState get _state => isNullable
+      ? _NullabilityState.ordinaryNullable
+      : _NullabilityState.nonNullable;
 }
 
 class _NullabilityNodeSimple extends NullabilityNodeMutable {
   @override
   final String _debugPrefix;
 
-  _NullabilityNodeSimple(this._debugPrefix) : super._();
+  _NullabilityNodeSimple(this._debugPrefix,
+      {_NullabilityState initialState: _NullabilityState.undetermined})
+      : super._(initialState: initialState);
+}
+
+/// State of a nullability node.
+class _NullabilityState {
+  /// State of a nullability node whose nullability hasn't been decided yet.
+  static const undetermined = _NullabilityState._('undetermined', false);
+
+  /// State of a nullability node that has been determined to be non-nullable
+  /// by propagating upstream.
+  static const nonNullable = _NullabilityState._('non-nullable', false);
+
+  /// State of a nullability node that has been determined to be nullable by
+  /// propagating downstream.
+  static const ordinaryNullable =
+      _NullabilityState._('ordinary nullable', true);
+
+  /// State of a nullability node that has been determined to be nullable by
+  /// propagating upstream from a contravariant use of a generic.
+  static const exactNullable = _NullabilityState._('exact nullable', true);
+
+  /// Name of the state (for use in debugging).
+  final String name;
+
+  /// Indicates whether the given state should be considered nullable.
+  ///
+  /// After propagation, any nodes that remain in the undetermined state are
+  /// considered to be non-nullable, so this field is returns `false` for nodes
+  /// in that state.
+  final bool isNullable;
+
+  const _NullabilityState._(this.name, this.isNullable);
+
+  @override
+  String toString() => name;
 }
diff --git a/pkg/analysis_server/lib/src/nullability/provisional_api.dart b/pkg/analysis_server/lib/src/nullability/provisional_api.dart
index 36b741b..02b8921 100644
--- a/pkg/analysis_server/lib/src/nullability/provisional_api.dart
+++ b/pkg/analysis_server/lib/src/nullability/provisional_api.dart
@@ -13,9 +13,6 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:meta/meta.dart';
 
-export 'package:analysis_server/src/nullability/transitional_api.dart'
-    show NamedNoDefaultParameterHeuristic, NullabilityMigrationAssumptions;
-
 /// Kinds of fixes that might be performed by nullability migration.
 class NullabilityFixKind {
   /// An import needs to be added.
@@ -73,12 +70,9 @@
   /// as far as possible even though the migration algorithm is not yet
   /// complete.  TODO(paulberry): remove this mode once the migration algorithm
   /// is fully implemented.
-  NullabilityMigration(this.listener,
-      {bool permissive: false,
-      analyzer.NullabilityMigrationAssumptions assumptions:
-          const analyzer.NullabilityMigrationAssumptions()})
-      : _analyzerMigration = analyzer.NullabilityMigration(
-            permissive: permissive, assumptions: assumptions);
+  NullabilityMigration(this.listener, {bool permissive: false})
+      : _analyzerMigration =
+            analyzer.NullabilityMigration(permissive: permissive);
 
   void finish() {
     for (var entry in _analyzerMigration.finish().entries) {
diff --git a/pkg/analysis_server/lib/src/nullability/transitional_api.dart b/pkg/analysis_server/lib/src/nullability/transitional_api.dart
index f49c106..69b4d89 100644
--- a/pkg/analysis_server/lib/src/nullability/transitional_api.dart
+++ b/pkg/analysis_server/lib/src/nullability/transitional_api.dart
@@ -3,10 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/nullability/conditional_discard.dart';
-import 'package:analysis_server/src/nullability/constraint_gatherer.dart';
-import 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
 import 'package:analysis_server/src/nullability/decorated_type.dart';
 import 'package:analysis_server/src/nullability/expression_checks.dart';
+import 'package:analysis_server/src/nullability/graph_builder.dart';
+import 'package:analysis_server/src/nullability/node_builder.dart';
 import 'package:analysis_server/src/nullability/nullability_node.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -89,38 +89,6 @@
   }
 }
 
-/// Enum encapsulating the various options proposed at
-/// https://github.com/dart-lang/language/issues/156#issuecomment-460525075
-enum DefaultParameterHandling {
-  /// Option 2: Add required named parameters
-  ///
-  /// - `{int x}` implicitly means `x` is required
-  ///   - required-ness goes into the function type:
-  ///     `int Function({required int x})`
-  /// - `{required int? x}` is allowed
-  ///   - means that something must be passed
-  ///   - passing null is allowed
-  /// - `{int x = 3}` is allowed
-  ///   - `x` is optional
-  ///   - passing null to it is an error
-  ///   - passing nothing to it results in it getting the default value
-  /// - `[int x]` is an error
-  /// - `[int x = 3]` is allowed
-  option2_addRequiredNamedParameters,
-}
-
-/// Enum representing the possible heuristics for handling named parameters with
-/// no default value.
-enum NamedNoDefaultParameterHeuristic {
-  /// Assume that the parameter should be considered nullable, unless the user
-  /// has explicitly marked it as `@required`.
-  assumeNullable,
-
-  /// Assume that the parameter should be considered required, unless the user
-  /// has explicitly marked it as nullable.
-  assumeRequired,
-}
-
 /// Transitional migration API.
 ///
 /// Usage: pass each input source file to [prepareInput].  Then pass each input
@@ -132,8 +100,6 @@
 class NullabilityMigration {
   final bool _permissive;
 
-  final NullabilityMigrationAssumptions assumptions;
-
   final Variables _variables;
 
   final NullabilityGraph _graph;
@@ -144,13 +110,10 @@
   /// as far as possible even though the migration algorithm is not yet
   /// complete.  TODO(paulberry): remove this mode once the migration algorithm
   /// is fully implemented.
-  NullabilityMigration(
-      {bool permissive: false,
-      NullabilityMigrationAssumptions assumptions:
-          const NullabilityMigrationAssumptions()})
-      : this._(permissive, assumptions, NullabilityGraph());
+  NullabilityMigration({bool permissive: false})
+      : this._(permissive, NullabilityGraph());
 
-  NullabilityMigration._(this._permissive, this.assumptions, this._graph)
+  NullabilityMigration._(this._permissive, this._graph)
       : _variables = Variables(_graph);
 
   Map<Source, List<PotentialModification>> finish() {
@@ -159,42 +122,16 @@
   }
 
   void prepareInput(CompilationUnit unit, TypeProvider typeProvider) {
-    unit.accept(ConstraintVariableGatherer(
-        _variables,
-        unit.declaredElement.source,
-        _permissive,
-        assumptions,
-        _graph,
-        typeProvider));
+    unit.accept(NodeBuilder(_variables, unit.declaredElement.source,
+        _permissive, _graph, typeProvider));
   }
 
   void processInput(CompilationUnit unit, TypeProvider typeProvider) {
-    unit.accept(ConstraintGatherer(typeProvider, _variables, _graph,
-        unit.declaredElement.source, _permissive, assumptions));
+    unit.accept(GraphBuilder(typeProvider, _variables, _graph,
+        unit.declaredElement.source, _permissive));
   }
 }
 
-/// Assumptions affecting the behavior of the nullability migration tool.
-///
-/// These options generally reflect design decisions that have not yet been
-/// made.  They don't reflect behavioral differences we would want to expose to
-/// the user.
-///
-/// TODO(paulberry): hardcode these assumptions once decisions have been made.
-class NullabilityMigrationAssumptions {
-  /// Handling of default parameters.
-  final DefaultParameterHandling defaultParameterHandling;
-
-  /// Heuristic for handling named parameters with no default value.
-  final NamedNoDefaultParameterHeuristic namedNoDefaultParameterHeuristic;
-
-  const NullabilityMigrationAssumptions(
-      {this.defaultParameterHandling:
-          DefaultParameterHandling.option2_addRequiredNamedParameters,
-      this.namedNoDefaultParameterHeuristic:
-          NamedNoDefaultParameterHeuristic.assumeNullable});
-}
-
 /// Records information about the possible addition of an import
 /// to the source code.
 class PotentiallyAddImport extends PotentialModification {
@@ -274,7 +211,7 @@
   @override
   DecoratedType decoratedElementType(Element element, {bool create: false}) =>
       _decoratedElementTypes[element] ??= create
-          ? DecoratedType.forElement(element, _graph)
+          ? DecoratedType.forElement(element)
           : throw StateError('No element found');
 
   @override
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 2937dee..4aad023 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -14,6 +14,7 @@
 import 'package:analysis_server/src/server/detachable_filesystem_manager.dart';
 import 'package:analysis_server/src/server/dev_server.dart';
 import 'package:analysis_server/src/server/diagnostic_server.dart';
+import 'package:analysis_server/src/server/features.dart';
 import 'package:analysis_server/src/server/http_server.dart';
 import 'package:analysis_server/src/server/lsp_stdio_server.dart';
 import 'package:analysis_server/src/server/stdio_server.dart';
@@ -29,6 +30,7 @@
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:args/args.dart';
+import 'package:front_end/src/fasta/compiler_context.dart';
 import 'package:linter/src/rules.dart' as linter;
 import 'package:telemetry/crash_reporting.dart';
 import 'package:telemetry/telemetry.dart' as telemetry;
@@ -195,6 +197,18 @@
   static const String DARTPAD_OPTION = "dartpad";
 
   /**
+   * The name of the option to disable the completion feature.
+   */
+  static const String DISABLE_SERVER_FEATURE_COMPLETION =
+      "disable-server-feature-completion";
+
+  /**
+   * The name of the option to disable the search feature.
+   */
+  static const String DISABLE_SERVER_FEATURE_SEARCH =
+      "disable-server-feature-search";
+
+  /**
    * The name of the option used to enable instrumentation.
    */
   static const String ENABLE_INSTRUMENTATION_OPTION = "enable-instrumentation";
@@ -354,6 +368,17 @@
       UriContributor.suggestFilePaths = false;
     }
 
+    {
+      bool disableCompletion = results[DISABLE_SERVER_FEATURE_COMPLETION];
+      bool disableSearch = results[DISABLE_SERVER_FEATURE_SEARCH];
+      if (disableCompletion || disableSearch) {
+        analysisServerOptions.featureSet = FeatureSet(
+          completion: !disableCompletion,
+          search: !disableSearch,
+        );
+      }
+    }
+
     if (results[HELP_OPTION]) {
       _printUsage(parser.parser, analytics, fromHelp: true);
       return null;
@@ -404,19 +429,21 @@
       }
     }
 
-    if (analysisServerOptions.useLanguageServerProtocol) {
-      startLspServer(results, analysisServerOptions, dartSdkManager,
-          instrumentationService, diagnosticServerPort);
-    } else {
-      startAnalysisServer(
-          results,
-          analysisServerOptions,
-          parser,
-          dartSdkManager,
-          instrumentationService,
-          analytics,
-          diagnosticServerPort);
-    }
+    CompilerContext.runWithDefaultOptions((_) async {
+      if (analysisServerOptions.useLanguageServerProtocol) {
+        startLspServer(results, analysisServerOptions, dartSdkManager,
+            instrumentationService, diagnosticServerPort);
+      } else {
+        startAnalysisServer(
+            results,
+            analysisServerOptions,
+            parser,
+            dartSdkManager,
+            instrumentationService,
+            analytics,
+            diagnosticServerPort);
+      }
+    });
   }
 
   void startAnalysisServer(
@@ -632,6 +659,10 @@
         help: 'enable DartPad specific functionality',
         defaultsTo: false,
         hide: true);
+    parser.addFlag(DISABLE_SERVER_FEATURE_COMPLETION,
+        help: 'disable all completion features', defaultsTo: false, hide: true);
+    parser.addFlag(DISABLE_SERVER_FEATURE_SEARCH,
+        help: 'disable all search features', defaultsTo: false, hide: true);
     parser.addFlag(ENABLE_INSTRUMENTATION_OPTION,
         help: "enable sending instrumentation information to a server",
         defaultsTo: false,
diff --git a/pkg/analysis_server/lib/src/server/features.dart b/pkg/analysis_server/lib/src/server/features.dart
new file mode 100644
index 0000000..fd02aa1
--- /dev/null
+++ b/pkg/analysis_server/lib/src/server/features.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// The set of features enabled in a server session.
+///
+/// When some features are not enabled, the server might avoid doing work
+/// that is only required for these features.
+class FeatureSet {
+  final bool completion;
+  final bool search;
+
+  FeatureSet({
+    this.completion = true,
+    this.search = true,
+  });
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
index 82555b4..1d86d94 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
@@ -11,6 +11,7 @@
     show DartCompletionRequestImpl;
 import 'package:analysis_server/src/services/correction/name_suggestion.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
 import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
 
 /**
@@ -59,17 +60,25 @@
       // Resolution not needed for this completion
 
       AstNode node = request.target.containingNode;
+      int offset = request.target.offset;
+
+      // Use the refined node.
+      if (node is FormalParameterList) {
+        node = CompletionTarget.findFormalParameter(node, offset);
+      }
 
       String strName = null;
       if (node is ExpressionStatement) {
-        if (node.expression is Identifier) {
-          strName = _getStringName(node.expression as Identifier);
+        var expression = node.expression;
+        if (expression is Identifier) {
+          strName = _getStringName(expression);
         }
+      } else if (node is SimpleFormalParameter) {
+        var identifier = _formalParameterTypeIdentifier(node);
+        strName = _getStringName(identifier);
       } else if (node is VariableDeclarationList) {
-        TypeAnnotation typeAnnotation = node.type;
-        if (typeAnnotation is TypeName) {
-          strName = _getStringName(typeAnnotation.name);
-        }
+        var identifier = _typeAnnotationIdentifier(node.type);
+        strName = _getStringName(identifier);
       } else if (node is TopLevelVariableDeclaration) {
         // The parser parses 'Foo ' and 'Foo ;' differently, resulting in the
         // following.
@@ -79,9 +88,8 @@
         VariableDeclarationList varDeclarationList = node.variables;
         TypeAnnotation typeAnnotation = varDeclarationList.type;
         if (typeAnnotation != null) {
-          if (typeAnnotation is TypeName) {
-            strName = _getStringName(typeAnnotation.name);
-          }
+          var identifier = _typeAnnotationIdentifier(typeAnnotation);
+          strName = _getStringName(identifier);
         } else {
           NodeList<VariableDeclaration> varDeclarations =
               varDeclarationList.variables;
@@ -95,9 +103,8 @@
         return const <CompletionSuggestion>[];
       }
 
-      var doIncludePrivateVersion = !optype.inMethodBody &&
-          !optype.inFunctionBody &&
-          !optype.inConstructorBody;
+      var doIncludePrivateVersion =
+          optype.inFieldDeclaration || optype.inTopLevelVariableDeclaration;
 
       List<String> variableNameSuggestions = getCamelWordCombinations(strName);
       variableNameSuggestions.remove(strName);
@@ -119,4 +126,22 @@
     }
     return const <CompletionSuggestion>[];
   }
+
+  static Identifier _formalParameterTypeIdentifier(FormalParameter node) {
+    if (node is SimpleFormalParameter) {
+      var type = node.type;
+      if (type != null) {
+        return _typeAnnotationIdentifier(type);
+      }
+      return node.identifier;
+    }
+    return null;
+  }
+
+  static Identifier _typeAnnotationIdentifier(TypeAnnotation type) {
+    if (type is TypeName) {
+      return type.name;
+    }
+    return null;
+  }
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index d24108b..e46f525 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -205,6 +205,13 @@
       'dart.assist.convert.ifElseToConditional',
       30,
       "Replace 'if-else' with conditional ('c ? x : y')");
+  static const SORT_CHILD_PROPERTY_LAST = const AssistKind(
+      'dart.assist.sort.child.properties.last',
+      30,
+      "Move child property to end of arguments",
+      associatedErrorCodes: <String>[
+        'sort_child_properties_last',
+      ]);
   static const SPLIT_AND_CONDITION = const AssistKind(
       'dart.assist.splitIfConjunction', 30, "Split && condition");
   static const SPLIT_VARIABLE_DECLARATION = const AssistKind(
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index b420fd0..b465c69 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -145,6 +145,7 @@
     await _addProposal_reparentFlutterList();
     await _addProposal_replaceConditionalWithIfElse();
     await _addProposal_replaceIfElseWithConditional();
+    await _addProposal_sortChildPropertyLast();
     await _addProposal_splitAndCondition();
     await _addProposal_splitVariableDeclaration();
     await _addProposal_surroundWith();
@@ -3547,6 +3548,47 @@
     }
   }
 
+  Future<void> _addProposal_sortChildPropertyLast() async {
+    NamedExpression childProp = flutter.findNamedExpression(node, 'child');
+    if (childProp == null) {
+      childProp = flutter.findNamedExpression(node, 'children');
+    }
+    if (childProp == null) {
+      return;
+    }
+
+    var parent = childProp.parent?.parent;
+    if (parent is! InstanceCreationExpression ||
+        !flutter.isWidgetCreation(parent)) {
+      return;
+    }
+
+    InstanceCreationExpression creationExpression = parent;
+    var args = creationExpression.argumentList;
+
+    var last = args.arguments.last;
+    if (last == childProp) {
+      // Already sorted.
+      return;
+    }
+
+    var changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      var start = childProp.beginToken.previous.end;
+      var end = childProp.endToken.next.end;
+      var childRange = range.startOffsetEndOffset(start, end);
+
+      var childText = utils.getRangeText(childRange);
+      builder.addSimpleReplacement(childRange, '');
+      builder.addSimpleInsertion(last.end + 1, childText);
+
+      changeBuilder.setSelection(new Position(file, last.end + 1));
+    });
+
+    _addAssistFromBuilder(
+        changeBuilder, DartAssistKind.SORT_CHILD_PROPERTY_LAST);
+  }
+
   Future<void> _addProposal_splitAndCondition() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 7ca77e9..adfc446 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/plugin/edit/fix/fix_dart.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/error/error.dart';
@@ -119,7 +120,16 @@
   @override
   final AnalysisError error;
 
-  DartFixContextImpl(this.workspace, this.resolveResult, this.error);
+  final List<TopLevelDeclaration> Function(String name)
+      getTopLevelDeclarationsFunction;
+
+  DartFixContextImpl(this.workspace, this.resolveResult, this.error,
+      this.getTopLevelDeclarationsFunction);
+
+  @override
+  List<TopLevelDeclaration> getTopLevelDeclarations(String name) {
+    return getTopLevelDeclarationsFunction(name);
+  }
 }
 
 /// An enumeration of quick fix kinds found in a Dart file.
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/dart/top_level_declarations.dart b/pkg/analysis_server/lib/src/services/correction/fix/dart/top_level_declarations.dart
new file mode 100644
index 0000000..ef4b987
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/fix/dart/top_level_declarations.dart
@@ -0,0 +1,107 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/analysis/analysis_context.dart';
+import 'package:analyzer/src/services/available_declarations.dart';
+
+/// Information about a single top-level declaration.
+class TopLevelDeclaration {
+  /// The path of the library that exports this declaration.
+  final String path;
+
+  /// The URI of the library that exports this declaration.
+  final Uri uri;
+
+  final TopLevelDeclarationKind kind;
+
+  final String name;
+
+  /// Is `true` if the declaration is exported, not declared in the [path].
+  final bool isExported;
+
+  TopLevelDeclaration(
+    this.path,
+    this.uri,
+    this.kind,
+    this.name,
+    this.isExported,
+  );
+
+  @override
+  String toString() => '($path, $uri, $kind, $name, $isExported)';
+}
+
+/// Kind of a top-level declaration.
+///
+/// We don't need it to be precise, just enough to support quick fixes.
+enum TopLevelDeclarationKind { type, function, variable }
+
+class TopLevelDeclarationsProvider {
+  final DeclarationsTracker tracker;
+
+  TopLevelDeclarationsProvider(this.tracker);
+
+  void doTrackerWork() {
+    while (tracker.hasWork) {
+      tracker.doWork();
+    }
+  }
+
+  List<TopLevelDeclaration> get(
+    AnalysisContext analysisContext,
+    String path,
+    String name,
+  ) {
+    var declarations = <TopLevelDeclaration>[];
+
+    void addDeclarations(Library library) {
+      for (var declaration in library.declarations) {
+        if (declaration.name != name) continue;
+
+        var kind = _getTopKind(declaration.kind);
+        if (kind == null) continue;
+
+        declarations.add(
+          TopLevelDeclaration(
+            library.path,
+            library.uri,
+            kind,
+            name,
+            declaration.locationLibraryUri != library.uri,
+          ),
+        );
+      }
+    }
+
+    var declarationsContext = tracker.getContext(analysisContext);
+    var libraries = declarationsContext.getLibraries(path);
+    libraries.context.forEach(addDeclarations);
+    libraries.dependencies.forEach(addDeclarations);
+    libraries.sdk.forEach(addDeclarations);
+
+    return declarations;
+  }
+
+  TopLevelDeclarationKind _getTopKind(DeclarationKind kind) {
+    switch (kind) {
+      case DeclarationKind.CLASS:
+      case DeclarationKind.CLASS_TYPE_ALIAS:
+      case DeclarationKind.ENUM:
+      case DeclarationKind.FUNCTION_TYPE_ALIAS:
+      case DeclarationKind.MIXIN:
+        return TopLevelDeclarationKind.type;
+        break;
+      case DeclarationKind.FUNCTION:
+        return TopLevelDeclarationKind.function;
+        break;
+      case DeclarationKind.GETTER:
+      case DeclarationKind.SETTER:
+      case DeclarationKind.VARIABLE:
+        return TopLevelDeclarationKind.variable;
+        break;
+      default:
+        return null;
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index dc43fd4..4cd9e33 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -10,6 +10,7 @@
 import 'package:analysis_server/plugin/edit/fix/fix_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/levenshtein.dart';
 import 'package:analysis_server/src/services/correction/namespace.dart';
 import 'package:analysis_server/src/services/correction/strings.dart';
@@ -26,7 +27,6 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/session_helper.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
@@ -105,7 +105,11 @@
     // For each fix, put the fix into the HashMap.
     for (int i = 0; i < allAnalysisErrors.length; i++) {
       final FixContext fixContextI = new DartFixContextImpl(
-          context.workspace, context.resolveResult, allAnalysisErrors[i]);
+        context.workspace,
+        context.resolveResult,
+        allAnalysisErrors[i],
+        (name) => [],
+      );
       final FixProcessor processorI = new FixProcessor(fixContextI);
       final List<Fix> fixesListI = await processorI.compute();
       for (Fix f in fixesListI) {
@@ -2412,7 +2416,7 @@
     }
     // may be there is an existing import,
     // but it is with prefix and we don't use this prefix
-    Set<Source> alreadyImportedWithPrefix = new Set<Source>();
+    var alreadyImportedWithPrefix = new Set<String>();
     for (ImportElement imp in unitLibraryElement.imports) {
       // prepare element
       LibraryElement libraryElement = imp.importedLibrary;
@@ -2454,7 +2458,7 @@
           libraryName = libraryElement.source.shortName;
         }
         // don't add this library again
-        alreadyImportedWithPrefix.add(libraryElement.source);
+        alreadyImportedWithPrefix.add(libraryElement.source.fullName);
         // update library
         String newShowCode = 'show ${showNames.join(', ')}';
         int offset = showCombinator.offset;
@@ -2473,25 +2477,21 @@
     }
     // Find new top-level declarations.
     {
-      var declarations = await session.getTopLevelDeclarations(name);
-      for (TopLevelDeclarationInSource declaration in declarations) {
+      var declarations = await context.getTopLevelDeclarations(name);
+      for (var declaration in declarations) {
         // Check the kind.
-        if (!kinds2.contains(declaration.declaration.kind)) {
+        if (!kinds2.contains(declaration.kind)) {
           continue;
         }
         // Check the source.
-        Source librarySource = declaration.source;
-        if (alreadyImportedWithPrefix.contains(librarySource)) {
-          continue;
-        }
-        if (!_isSourceVisibleToLibrary(librarySource)) {
+        if (alreadyImportedWithPrefix.contains(declaration.path)) {
           continue;
         }
         // Compute the fix kind.
         FixKind fixKind;
-        if (librarySource.isInSystemLibrary) {
+        if (declaration.uri.isScheme('dart')) {
           fixKind = DartFixKind.IMPORT_LIBRARY_SDK;
-        } else if (_isLibSrcPath(librarySource.fullName)) {
+        } else if (_isLibSrcPath(declaration.path)) {
           // Bad: non-API.
           fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT3;
         } else if (declaration.isExported) {
@@ -2503,8 +2503,8 @@
         }
         // Add the fix.
         var relativeURI =
-            _getRelativeURIFromLibrary(unitLibraryElement, librarySource);
-        await _addFix_importLibrary(fixKind, librarySource.uri, relativeURI);
+            _getRelativeURIFromLibrary(unitLibraryElement, declaration.path);
+        await _addFix_importLibrary(fixKind, declaration.uri, relativeURI);
       }
     }
   }
@@ -4246,21 +4246,20 @@
   }
 
   /**
-   * Return the relative uri from the passed [library] to the passed
-   * [source]. If the [source] is not in the LibraryElement, `null` is returned.
+   * Return the relative uri from the passed [library] to the given [path].
+   * If the [path] is not in the LibraryElement, `null` is returned.
    */
-  String _getRelativeURIFromLibrary(LibraryElement library, Source source) {
+  String _getRelativeURIFromLibrary(LibraryElement library, String path) {
     var librarySource = library?.librarySource;
     if (librarySource == null) {
       return null;
     }
     var pathCtx = resourceProvider.pathContext;
     var libraryDirectory = pathCtx.dirname(librarySource.fullName);
-    var sourceDirectory = pathCtx.dirname(source.fullName);
-    if (pathCtx.isWithin(libraryDirectory, source.fullName) ||
+    var sourceDirectory = pathCtx.dirname(path);
+    if (pathCtx.isWithin(libraryDirectory, path) ||
         pathCtx.isWithin(sourceDirectory, libraryDirectory)) {
-      String relativeFile =
-          pathCtx.relative(source.fullName, from: libraryDirectory);
+      String relativeFile = pathCtx.relative(path, from: libraryDirectory);
       return pathCtx.split(relativeFile).join('/');
     }
     return null;
@@ -4469,30 +4468,6 @@
     return false;
   }
 
-  /**
-   * Return `true` if the [source] can be imported into current library.
-   */
-  bool _isSourceVisibleToLibrary(Source source) {
-    String path = source.fullName;
-
-    var contextRoot = context.resolveResult.session.analysisContext.contextRoot;
-    if (contextRoot == null) {
-      return true;
-    }
-
-    // We don't want to use private libraries of other packages.
-    if (source.uri.isScheme('package') && _isLibSrcPath(path)) {
-      return contextRoot.root.contains(path);
-    }
-
-    // We cannot use relative URIs to reference files outside of our package.
-    if (source.uri.isScheme('file')) {
-      return contextRoot.root.contains(path);
-    }
-
-    return true;
-  }
-
   bool _isToListMethodElement(MethodElement method) {
     if (method.name != 'toList') {
       return false;
diff --git a/pkg/analysis_server/lib/src/utilities/flutter.dart b/pkg/analysis_server/lib/src/utilities/flutter.dart
index b803440..867a30b 100644
--- a/pkg/analysis_server/lib/src/utilities/flutter.dart
+++ b/pkg/analysis_server/lib/src/utilities/flutter.dart
@@ -284,6 +284,7 @@
       if (isWidgetExpression(node)) {
         var parent = node.parent;
         if (parent is ArgumentList ||
+            parent is ExpressionFunctionBody && parent.expression == node ||
             parent is ListLiteral ||
             parent is NamedExpression && parent.expression == node ||
             parent is Statement) {
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index 7dc1119..be52e27 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -3,9 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:io';
 
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:path/path.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -20,6 +22,9 @@
 
 @reflectiveTest
 class AnalysisHoverTest extends AbstractAnalysisTest {
+  /// If windows, return 'C:', otherwise return the empty string
+  String get windowsCColon => Platform.isWindows ? 'C:' : '';
+
   Future<HoverInformation> prepareHover(String search) {
     int offset = findOffset(search);
     return prepareHoverAt(offset);
@@ -87,7 +92,7 @@
       expect(hover.length, 'new A.named()'.length);
       // element
       expect(hover.dartdoc, 'my doc');
-      expect(hover.elementDescription, 'A.named() → A');
+      expect(hover.elementDescription, 'A A.named()');
       expect(hover.elementKind, 'constructor');
     }
 
@@ -116,10 +121,11 @@
     expect(hover.offset, findOffset('A(0)'));
     expect(hover.length, 'A(0)'.length);
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName,
+        normalize('$windowsCColon/project/bin/test.dart'));
     expect(hover.containingLibraryPath, testFile);
     expect(hover.dartdoc, isNull);
-    expect(hover.elementDescription, '(const) A(int i) → A');
+    expect(hover.elementDescription, '(const) A A(int i)');
     expect(hover.elementKind, 'constructor');
     // types
     expect(hover.staticType, isNull);
@@ -141,10 +147,11 @@
     expect(hover.offset, findOffset('A()'));
     expect(hover.length, 'A()'.length);
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName,
+        normalize('$windowsCColon/project/bin/test.dart'));
     expect(hover.containingLibraryPath, testFile);
     expect(hover.dartdoc, isNull);
-    expect(hover.elementDescription, '(new) A() → A');
+    expect(hover.elementDescription, '(new) A A()');
     expect(hover.elementKind, 'constructor');
     // types
     expect(hover.staticType, isNull);
@@ -167,10 +174,11 @@
     expect(hover.offset, findOffset('new A'));
     expect(hover.length, 'new A()'.length);
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName,
+        normalize('$windowsCColon/project/bin/test.dart'));
     expect(hover.containingLibraryPath, testFile);
     expect(hover.dartdoc, isNull);
-    expect(hover.elementDescription, 'A() → A');
+    expect(hover.elementDescription, 'A A()');
     expect(hover.elementKind, 'constructor');
     // types
     expect(hover.staticType, isNull);
@@ -192,10 +200,11 @@
       expect(hover.offset, findOffset('new A<String>'));
       expect(hover.length, 'new A<String>()'.length);
       // element
-      expect(hover.containingLibraryName, 'my.library');
+      expect(hover.containingLibraryName,
+          normalize('$windowsCColon/project/bin/test.dart'));
       expect(hover.containingLibraryPath, testFile);
       expect(hover.dartdoc, isNull);
-      expect(hover.elementDescription, 'A() → A<String>');
+      expect(hover.elementDescription, 'A<String> A()');
       expect(hover.elementKind, 'constructor');
       // types
       expect(hover.staticType, isNull);
@@ -214,6 +223,7 @@
     }
     {
       HoverInformation hover = await prepareHover('String>');
+      expect(hover.containingLibraryName, 'dart:core');
       expect(hover.offset, findOffset('String>'));
       expect(hover.length, 'String'.length);
       expect(hover.elementKind, 'class');
@@ -329,11 +339,12 @@
 ''');
     HoverInformation hover = await prepareHover('fff(int a');
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName,
+        normalize('$windowsCColon/project/bin/test.dart'));
     expect(hover.containingLibraryPath, testFile);
     expect(hover.containingClassDescription, isNull);
     expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
-    expect(hover.elementDescription, 'fff(int a, String b) → List<String>');
+    expect(hover.elementDescription, 'List<String> fff(int a, String b)');
     expect(hover.elementKind, 'function');
     // types
     expect(hover.staticType, isNull);
@@ -356,7 +367,8 @@
 ''');
     HoverInformation hover = await prepareHover('fff);');
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName,
+        normalize('$windowsCColon/project/bin/test.dart'));
     expect(hover.containingLibraryPath, testFile);
     expect(hover.containingClassDescription, 'A');
     expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
@@ -494,11 +506,12 @@
 ''');
     HoverInformation hover = await prepareHover('mmm(int a');
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName,
+        normalize('$windowsCColon/project/bin/test.dart'));
     expect(hover.containingLibraryPath, testFile);
     expect(hover.containingClassDescription, 'A');
     expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
-    expect(hover.elementDescription, 'mmm(int a, String b) → List<String>');
+    expect(hover.elementDescription, 'List<String> mmm(int a, String b)');
     expect(hover.elementKind, 'method');
     // types
     expect(hover.staticType, isNull);
@@ -523,13 +536,14 @@
     expect(hover.offset, findOffset('mmm(42, '));
     expect(hover.length, 'mmm'.length);
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName,
+        normalize('$windowsCColon/project/bin/test.dart'));
     expect(hover.containingLibraryPath, testFile);
-    expect(hover.elementDescription, 'mmm(int a, String b) → List<String>');
+    expect(hover.elementDescription, 'List<String> mmm(int a, String b)');
     expect(hover.elementKind, 'method');
     expect(hover.isDeprecated, isFalse);
     // types
-    expect(hover.staticType, '(int, String) → List<String>');
+    expect(hover.staticType, 'List<String> Function(int, String)');
     expect(hover.propagatedType, isNull);
     // no parameter
     expect(hover.parameter, isNull);
@@ -548,7 +562,7 @@
     HoverInformation hover = await prepareHover('test();');
     // element
     expect(hover.containingLibraryPath, testFile);
-    expect(hover.elementDescription, 'test() → void');
+    expect(hover.elementDescription, 'void test()');
     expect(hover.elementKind, 'method');
     expect(hover.isDeprecated, isTrue);
   }
@@ -571,15 +585,16 @@
     expect(hover.offset, findOffset('transform(n'));
     expect(hover.length, 'transform'.length);
     // element
-    expect(hover.containingLibraryName, 'my.library');
+    expect(hover.containingLibraryName,
+        normalize('$windowsCColon/project/bin/test.dart'));
     expect(hover.containingLibraryPath, testFile);
     expect(hover.elementDescription,
-        'Stream.transform<S>(StreamTransformer<int, S> streamTransformer) → Stream<S>');
+        'Stream<S> Stream.transform<S>(StreamTransformer<int, S> streamTransformer)');
     expect(hover.elementKind, 'method');
     expect(hover.isDeprecated, isFalse);
     // types
     expect(hover.staticType,
-        '(StreamTransformer<int, dynamic>) → Stream<dynamic>');
+        'Stream<dynamic> Function(StreamTransformer<int, dynamic>)');
     expect(hover.propagatedType, isNull);
     // no parameter
     expect(hover.parameter, isNull);
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index f4593b4..22715a4 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -135,6 +135,12 @@
     handleSuccessfulRequest(request, handler: analysisHandler);
   }
 
+  void doAllDeclarationsTrackerWork() {
+    while (server.declarationsTracker.hasWork) {
+      server.declarationsTracker.doWork();
+    }
+  }
+
   /**
    * Returns the offset of [search] in [testCode].
    * Fails if not found.
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index f30a1c3..228ec3f 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -2519,6 +2519,9 @@
   void afterWatchEvent(WatchEvent event) {}
 
   @override
+  void analysisOptionsUpdated(AnalysisDriver driver) {}
+
+  @override
   void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) {
     AnalysisDriver driver = driverMap[contextFolder.path];
     if (driver != null) {
diff --git a/pkg/analysis_server/test/edit/fixes_test.dart b/pkg/analysis_server/test/edit/fixes_test.dart
index 2fa8a24..22a7245 100644
--- a/pkg/analysis_server/test/edit/fixes_test.dart
+++ b/pkg/analysis_server/test/edit/fixes_test.dart
@@ -40,6 +40,7 @@
 }
 ''');
     await waitForTasksFinished();
+    doAllDeclarationsTrackerWork();
     List<AnalysisErrorFixes> errorFixes =
         await _getFixesAt('Completer<String>');
     expect(errorFixes, hasLength(1));
@@ -133,17 +134,20 @@
   }
 
   test_suggestImportFromDifferentAnalysisRoot() async {
-    String asFileUri(String input) =>
-        new Uri.file(convertPath(input)).toString();
     newFolder('/aaa');
     newFile('/aaa/.packages', content: '''
-aaa:${asFileUri('/aaa/lib')}
-bbb:${asFileUri('/bbb/lib')}
+aaa:${toUri('/aaa/lib')}
+bbb:${toUri('/bbb/lib')}
 ''');
-    // Ensure that the target is analyzed as an implicit source.
-    newFile('/aaa/lib/foo.dart', content: 'import "package:bbb/target.dart";');
+    newFile('/aaa/pubspec.yaml', content: r'''
+dependencies:
+  bbb: any
+''');
 
     newFolder('/bbb');
+    newFile('/bbb/.packages', content: '''
+bbb:${toUri('/bbb/lib')}
+''');
     newFile('/bbb/lib/target.dart', content: 'class Foo() {}');
 
     handleSuccessfulRequest(
@@ -157,6 +161,7 @@
     _addOverlay(testFile, testCode);
 
     await waitForTasksFinished();
+    doAllDeclarationsTrackerWork();
 
     List<String> fixes = (await _getFixesAt('Foo()'))
         .single
diff --git a/pkg/analysis_server/test/integration/analysis/error_test.dart b/pkg/analysis_server/test/integration/analysis/error_test.dart
index 0a7948b..7d5cd76 100644
--- a/pkg/analysis_server/test/integration/analysis/error_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/error_test.dart
@@ -18,6 +18,24 @@
 @reflectiveTest
 class AnalysisErrorIntegrationTest
     extends AbstractAnalysisServerIntegrationTest {
+  test_analysisRootDoesNotExist() async {
+    String packagePath = sourcePath('package');
+    String filePath = sourcePath('package/lib/test.dart');
+    String content = '''
+main() {
+  print(null) // parse error: missing ';'
+}''';
+    await sendServerSetSubscriptions([ServerService.STATUS]);
+    await sendAnalysisUpdateContent({filePath: AddContentOverlay(content)});
+    await sendAnalysisSetAnalysisRoots([packagePath], []);
+    await analysisFinished;
+
+    expect(currentAnalysisErrors[filePath], isList);
+    List<AnalysisError> errors = currentAnalysisErrors[filePath];
+    expect(errors, hasLength(1));
+    expect(errors[0].location.file, equals(filePath));
+  }
+
   test_detect_simple_error() {
     String pathname = sourcePath('test.dart');
     writeFile(pathname, '''
diff --git a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
index e2f25af..ae7e4db 100644
--- a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
@@ -81,13 +81,13 @@
       expect(info.length, equals(length));
       if (isCore) {
         expect(path.basename(info.containingLibraryPath), equals('core.dart'));
-        expect(info.containingLibraryName, equals('dart.core'));
+        expect(info.containingLibraryName, equals('dart:core'));
       } else if (isLocal || isLiteral) {
         expect(info.containingLibraryPath, isNull);
         expect(info.containingLibraryName, isNull);
       } else {
         expect(info.containingLibraryPath, equals(pathname));
-        expect(info.containingLibraryName, equals('lib.test'));
+        expect(info.containingLibraryName, isNotNull);
       }
       if (docRegexp == null) {
         expect(info.dartdoc, isNull);
diff --git a/pkg/analysis_server/test/integration/coverage.md b/pkg/analysis_server/test/integration/coverage.md
index 6331b59..6df0629 100644
--- a/pkg/analysis_server/test/integration/coverage.md
+++ b/pkg/analysis_server/test/integration/coverage.md
@@ -31,6 +31,7 @@
 
 ## completion domain
 - [ ] completion.availableSuggestions
+- [ ] completion.existingImports
 - [ ] completion.getSuggestionDetails
 - [x] completion.getSuggestions
 - [x] completion.listTokenDetails
diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
index fe67037..65c2ca5 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -1219,6 +1219,14 @@
    *   True if this is that last set of results that will be returned for the
    *   indicated completion.
    *
+   * libraryFile: FilePath (optional)
+   *
+   *   The library file that contains the file where completion was requested.
+   *   The client might use it for example together with the existingImports
+   *   notification to filter out available suggestions. If there were changes
+   *   to existing imports in the library, the corresponding existingImports
+   *   notification will be sent before the completion notification.
+   *
    * includedSuggestionSets: List<IncludedSuggestionSet> (optional)
    *
    *   References to AvailableSuggestionSet objects previously sent to the
@@ -1279,6 +1287,29 @@
       _onCompletionAvailableSuggestions;
 
   /**
+   * Reports existing imports in a library. This notification may be sent
+   * multiple times for a library. When a notification is processed, clients
+   * should replace any previous information for the library.
+   *
+   * Parameters
+   *
+   * file: FilePath
+   *
+   *   The defining file of the library.
+   *
+   * imports: ExistingImports
+   *
+   *   The existing imports in the library.
+   */
+  Stream<CompletionExistingImportsParams> onCompletionExistingImports;
+
+  /**
+   * Stream controller for [onCompletionExistingImports].
+   */
+  StreamController<CompletionExistingImportsParams>
+      _onCompletionExistingImports;
+
+  /**
    * Perform a search for references to the element defined or referenced at
    * the given offset in the given file.
    *
@@ -2702,6 +2733,10 @@
         new StreamController<CompletionAvailableSuggestionsParams>(sync: true);
     onCompletionAvailableSuggestions =
         _onCompletionAvailableSuggestions.stream.asBroadcastStream();
+    _onCompletionExistingImports =
+        new StreamController<CompletionExistingImportsParams>(sync: true);
+    onCompletionExistingImports =
+        _onCompletionExistingImports.stream.asBroadcastStream();
     _onSearchResults = new StreamController<SearchResultsParams>(sync: true);
     onSearchResults = _onSearchResults.stream.asBroadcastStream();
     _onExecutionLaunchData =
@@ -2804,6 +2839,12 @@
             new CompletionAvailableSuggestionsParams.fromJson(
                 decoder, 'params', params));
         break;
+      case "completion.existingImports":
+        outOfTestExpect(params, isCompletionExistingImportsParams);
+        _onCompletionExistingImports.add(
+            new CompletionExistingImportsParams.fromJson(
+                decoder, 'params', params));
+        break;
       case "search.results":
         outOfTestExpect(params, isSearchResultsParams);
         _onSearchResults
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 23e34a7..70dc041 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -560,6 +560,29 @@
     new MatchesEnum("ExecutionService", ["LAUNCH_DATA"]);
 
 /**
+ * ExistingImport
+ *
+ * {
+ *   "uri": int
+ *   "elements": List<int>
+ * }
+ */
+final Matcher isExistingImport = new LazyMatcher(() => new MatchesJsonObject(
+    "ExistingImport", {"uri": isInt, "elements": isListOf(isInt)}));
+
+/**
+ * ExistingImports
+ *
+ * {
+ *   "elements": ImportedElementSet
+ *   "imports": List<ExistingImport>
+ * }
+ */
+final Matcher isExistingImports = new LazyMatcher(() => new MatchesJsonObject(
+    "ExistingImports",
+    {"elements": isImportedElementSet, "imports": isListOf(isExistingImport)}));
+
+/**
  * FileKind
  *
  * enum {
@@ -948,6 +971,22 @@
     "ImplementedMember", {"offset": isInt, "length": isInt}));
 
 /**
+ * ImportedElementSet
+ *
+ * {
+ *   "strings": List<String>
+ *   "uris": List<int>
+ *   "names": List<int>
+ * }
+ */
+final Matcher isImportedElementSet = new LazyMatcher(() =>
+    new MatchesJsonObject("ImportedElementSet", {
+      "strings": isListOf(isString),
+      "uris": isListOf(isInt),
+      "names": isListOf(isInt)
+    }));
+
+/**
  * ImportedElements
  *
  * {
@@ -2192,6 +2231,18 @@
         }));
 
 /**
+ * completion.existingImports params
+ *
+ * {
+ *   "file": FilePath
+ *   "imports": ExistingImports
+ * }
+ */
+final Matcher isCompletionExistingImportsParams = new LazyMatcher(() =>
+    new MatchesJsonObject("completion.existingImports params",
+        {"file": isFilePath, "imports": isExistingImports}));
+
+/**
  * completion.getSuggestionDetails params
  *
  * {
@@ -2288,6 +2339,7 @@
  *   "replacementLength": int
  *   "results": List<CompletionSuggestion>
  *   "isLast": bool
+ *   "libraryFile": optional FilePath
  *   "includedSuggestionSets": optional List<IncludedSuggestionSet>
  *   "includedElementKinds": optional List<ElementKind>
  *   "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
@@ -2301,6 +2353,7 @@
           "results": isListOf(isCompletionSuggestion),
           "isLast": isBool
         }, optionalFields: {
+          "libraryFile": isFilePath,
           "includedSuggestionSets": isListOf(isIncludedSuggestionSet),
           "includedElementKinds": isListOf(isElementKind),
           "includedSuggestionRelevanceTags":
diff --git a/pkg/analysis_server/test/lsp/cancel_request_test.dart b/pkg/analysis_server/test/lsp/cancel_request_test.dart
new file mode 100644
index 0000000..033f671
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/cancel_request_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2019, 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../tool/lsp_spec/matchers.dart';
+import 'server_abstract.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(CancelRequestTest);
+  });
+}
+
+@reflectiveTest
+class CancelRequestTest extends AbstractLspAnalysisServerTest {
+  test_cancel() async {
+    final content = '''
+main() {
+  InOtherF^
+}
+    ''';
+
+    final initialAnalysis = waitForAnalysisComplete();
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    await initialAnalysis;
+
+    // Create a completion request that we'll cancel.
+    final completionRequest = makeRequest(
+      Method.textDocument_completion,
+      new CompletionParams(
+        null,
+        new TextDocumentIdentifier(mainFileUri.toString()),
+        positionFromMarker(content),
+      ),
+    );
+    // And a request to cancel it.
+    final cancelNotification = makeNotification(
+        Method.cancelRequest, new CancelParams(completionRequest.id));
+
+    // Send both (without waiting for the results of the first).
+    final completionRequestFuture = sendRequestToServer(completionRequest);
+    await sendNotificationToServer(cancelNotification);
+
+    final result = await completionRequestFuture;
+    expect(result.result, isNull);
+    expect(result.error, isNotNull);
+    expect(result.error, isResponseError(ErrorCodes.RequestCancelled));
+  }
+}
diff --git a/pkg/analysis_server/test/lsp/code_actions_source_test.dart b/pkg/analysis_server/test/lsp/code_actions_source_test.dart
index 22c11ab..fb1daa5 100644
--- a/pkg/analysis_server/test/lsp/code_actions_source_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_source_test.dart
@@ -37,8 +37,8 @@
     ''';
     await newFile(mainFilePath, content: content);
     await initialize(
-        workspaceCapabilities:
-            withDocumentChangesSupport(emptyWorkspaceClientCapabilities));
+        workspaceCapabilities: withApplyEditSupport(
+            withDocumentChangesSupport(emptyWorkspaceClientCapabilities)));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -95,7 +95,9 @@
 int minified(int x, int y) => min(x, y);
     ''';
     await newFile(mainFilePath, content: content);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -138,9 +140,10 @@
   test_availableAsCodeActionLiteral() async {
     await newFile(mainFilePath);
     await initialize(
-      textDocumentCapabilities: withCodeActionKinds(
-          emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
-    );
+        textDocumentCapabilities: withCodeActionKinds(
+            emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     await checkCodeActionAvailable(
       mainFileUri,
@@ -152,7 +155,9 @@
 
   test_availableAsCommand() async {
     await newFile(mainFilePath);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     await checkCodeActionAvailable(
       mainFileUri,
@@ -165,7 +170,9 @@
   test_failsIfFileHasErrors() async {
     final content = 'invalid dart code';
     await newFile(mainFilePath, content: content);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -191,7 +198,9 @@
 int minified(int x, int y) => min(x, y);
     ''';
     await newFile(mainFilePath, content: content);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -212,9 +221,19 @@
   test_unavailableWhenNotRequested() async {
     await newFile(mainFilePath);
     await initialize(
-      textDocumentCapabilities: withCodeActionKinds(
-          emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
-    );
+        textDocumentCapabilities: withCodeActionKinds(
+            emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
+
+    final codeActions = await getCodeActions(mainFileUri.toString());
+    final codeAction = findCommand(codeActions, Commands.organizeImports);
+    expect(codeAction, isNull);
+  }
+
+  test_unavailableWithoutApplyEditSupport() async {
+    await newFile(mainFilePath);
+    await initialize();
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -235,8 +254,8 @@
     ''';
     await newFile(mainFilePath, content: content);
     await initialize(
-        workspaceCapabilities:
-            withDocumentChangesSupport(emptyWorkspaceClientCapabilities));
+        workspaceCapabilities: withApplyEditSupport(
+            withDocumentChangesSupport(emptyWorkspaceClientCapabilities)));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.sortMembers);
@@ -286,7 +305,9 @@
     String b;
     ''';
     await newFile(mainFilePath, content: content);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.sortMembers);
@@ -329,9 +350,10 @@
   test_availableAsCodeActionLiteral() async {
     await newFile(mainFilePath);
     await initialize(
-      textDocumentCapabilities: withCodeActionKinds(
-          emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
-    );
+        textDocumentCapabilities: withCodeActionKinds(
+            emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     await checkCodeActionAvailable(
       mainFileUri,
@@ -343,7 +365,9 @@
 
   test_availableAsCommand() async {
     await newFile(mainFilePath);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     await checkCodeActionAvailable(
       mainFileUri,
@@ -359,7 +383,9 @@
     String a;
     ''';
     await newFile(mainFilePath, content: content);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.sortMembers);
@@ -390,7 +416,9 @@
   test_failsIfFileHasErrors() async {
     final content = 'invalid dart code';
     await newFile(mainFilePath, content: content);
-    await initialize();
+    await initialize(
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.sortMembers);
@@ -410,9 +438,10 @@
   test_nonDartFile() async {
     await newFile(pubspecFilePath, content: simplePubspecContent);
     await initialize(
-      textDocumentCapabilities: withCodeActionKinds(
-          emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
-    );
+        textDocumentCapabilities: withCodeActionKinds(
+            emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
 
     final codeActions =
         await getCodeActions(pubspecFileUri.toString(), range: startOfDocRange);
@@ -422,9 +451,19 @@
   test_unavailableWhenNotRequested() async {
     await newFile(mainFilePath);
     await initialize(
-      textDocumentCapabilities: withCodeActionKinds(
-          emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
-    );
+        textDocumentCapabilities: withCodeActionKinds(
+            emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+        workspaceCapabilities:
+            withApplyEditSupport(emptyWorkspaceClientCapabilities));
+
+    final codeActions = await getCodeActions(mainFileUri.toString());
+    final codeAction = findCommand(codeActions, Commands.sortMembers);
+    expect(codeAction, isNull);
+  }
+
+  test_unavailableWithoutApplyEditSupport() async {
+    await newFile(mainFilePath);
+    await initialize();
 
     final codeActions = await getCodeActions(mainFileUri.toString());
     final codeAction = findCommand(codeActions, Commands.sortMembers);
diff --git a/pkg/analysis_server/test/lsp/hover_test.dart b/pkg/analysis_server/test/lsp/hover_test.dart
index 6b9be51..7f06e69 100644
--- a/pkg/analysis_server/test/lsp/hover_test.dart
+++ b/pkg/analysis_server/test/lsp/hover_test.dart
@@ -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.
 
+import 'dart:io';
+
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -18,6 +21,9 @@
 
 @reflectiveTest
 class HoverTest extends AbstractLspAnalysisServerTest {
+  /// If windows, return 'C:/', otherwise return the empty string
+  String get windowsCColon => Platform.isWindows ? 'C:/' : '';
+
   test_dartDoc_macros() async {
     final content = '''
     /// {@template template_name}
@@ -63,10 +69,15 @@
     String [[a^bc]];
     ''';
 
+    final containingLibraryName =
+        path.normalize("$windowsCColon/project/lib/main.dart");
+
     final expectedHoverContent = '''
 ```dart
 String abc
 ```
+*$containingLibraryName*
+
 ---
 This is a string.
 
@@ -161,10 +172,14 @@
     String [[a^bc]];
     ''';
 
+    final containingLibraryName =
+        path.normalize("$windowsCColon/project/lib/main.dart");
+
     final expectedHoverContent = '''
 ```dart
 String abc
 ```
+*$containingLibraryName*
     '''
         .trim();
 
diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart
index aa19b1d..7b147df 100644
--- a/pkg/analysis_server/test/lsp/initialization_test.dart
+++ b/pkg/analysis_server/test/lsp/initialization_test.dart
@@ -170,6 +170,7 @@
       const Duration(seconds: 1),
       onTimeout: () {
         didTimeout = true;
+        return null;
       },
     );
 
@@ -185,4 +186,94 @@
     expect(response.error, isNotNull);
     expect(response.error.code, ErrorCodes.ServerNotInitialized);
   }
+
+  test_dynamicRegistration_notSupportedByClient() async {
+    // If the client doesn't send any dynamicRegistration settings then there
+    // should be no `client/registerCapability` calls.
+
+    // Set a flag if any registerCapability request comes through.
+    bool didGetRegisterCapabilityRequest = false;
+    requestsFromServer
+        .firstWhere((n) => n.method == Method.client_registerCapability)
+        .then((params) {
+      didGetRegisterCapabilityRequest = true;
+    });
+
+    // Initialize with no dynamic registrations advertised.
+    await initialize();
+    await pumpEventQueue();
+
+    expect(didGetRegisterCapabilityRequest, isFalse);
+  }
+
+  test_dynamicRegistration_onlyForClientSupportedMethods() async {
+    // Check that when the server calls client/registerCapability it only includes
+    // the items we advertised dynamic registration support for.
+    List<Registration> registrations;
+    await handleExpectedRequest<void, RegistrationParams, void>(
+      Method.client_registerCapability,
+      () => initialize(
+          textDocumentCapabilities: withHoverDynamicRegistration(
+              emptyTextDocumentClientCapabilities)),
+      handler: (registrationParams) =>
+          registrations = registrationParams.registrations,
+    );
+
+    expect(registrations, hasLength(1));
+    expect(registrations.single.method,
+        equals(Method.textDocument_hover.toJson()));
+  }
+
+  test_dynamicRegistration_containsAppropriateSettings() async {
+    // Basic check that the server responds with the capabilities we'd expect,
+    // for ex including analysis_options.yaml in text synchronization but not
+    // for hovers.
+    List<Registration> registrations;
+    await handleExpectedRequest<void, RegistrationParams, void>(
+      Method.client_registerCapability,
+      () => initialize(
+          // Support dynamic registration for both text sync + hovers.
+          textDocumentCapabilities: withTextSyncDynamicRegistration(
+              withHoverDynamicRegistration(
+                  emptyTextDocumentClientCapabilities))),
+      handler: (registrationParams) =>
+          registrations = registrationParams.registrations,
+    );
+
+    // Should container Hover, DidOpen, DidClose, DidChange.
+    expect(registrations, hasLength(4));
+    final hover =
+        registrationOptionsFor(registrations, Method.textDocument_hover);
+    final change =
+        registrationOptionsFor(registrations, Method.textDocument_didChange);
+    expect(registrationOptionsFor(registrations, Method.textDocument_didOpen),
+        isNotNull);
+    expect(registrationOptionsFor(registrations, Method.textDocument_didClose),
+        isNotNull);
+
+    // The hover capability should only specific Dart.
+    expect(hover, isNotNull);
+    expect(hover.documentSelector, hasLength(1));
+    expect(hover.documentSelector.single.language, equals('dart'));
+
+    // didChange should also include pubspec + analysis_options.
+    expect(change, isNotNull);
+    expect(change.documentSelector, hasLength(greaterThanOrEqualTo(3)));
+    expect(change.documentSelector.any((ds) => ds.language == 'dart'), isTrue);
+    expect(change.documentSelector.any((ds) => ds.pattern == '**/pubspec.yaml'),
+        isTrue);
+    expect(
+        change.documentSelector
+            .any((ds) => ds.pattern == '**/analysis_options.yaml'),
+        isTrue);
+  }
+
+  TextDocumentRegistrationOptions registrationOptionsFor(
+    List<Registration> registrations,
+    Method method,
+  ) {
+    return registrations
+        .singleWhere((r) => r.method == method.toJson(), orElse: () => null)
+        ?.registerOptions;
+  }
 }
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index 9c15da4..d2e229f 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:convert';
 
 import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
@@ -193,7 +194,7 @@
         changes,
       ),
     );
-    sendNotificationToServer(notification);
+    await sendNotificationToServer(notification);
   }
 
   Future changeWorkspaceFolders({List<Uri> add, List<Uri> remove}) async {
@@ -206,7 +207,7 @@
         ),
       ),
     );
-    sendNotificationToServer(notification);
+    await sendNotificationToServer(notification);
   }
 
   Future closeFile(Uri uri) async {
@@ -215,7 +216,7 @@
       new DidCloseTextDocumentParams(
           new TextDocumentIdentifier(uri.toString())),
     );
-    sendNotificationToServer(notification);
+    await sendNotificationToServer(notification);
   }
 
   Future<Object> executeCommand(Command command) async {
@@ -567,7 +568,7 @@
     if (response.error == null) {
       final notification =
           makeNotification(Method.initialized, new InitializedParams());
-      sendNotificationToServer(notification);
+      await sendNotificationToServer(notification);
       await pumpEventQueue();
     } else if (throwOnFailure) {
       throw 'Error during initialize request: '
@@ -604,7 +605,7 @@
       new DidOpenTextDocumentParams(new TextDocumentItem(
           uri.toString(), dartLanguageId, version, content)),
     );
-    sendNotificationToServer(notification);
+    await sendNotificationToServer(notification);
     await pumpEventQueue();
   }
 
@@ -886,7 +887,12 @@
     TextDocumentClientCapabilities source,
     Map<String, dynamic> textDocumentCapabilities,
   ) {
-    final json = source.toJson();
+    // TODO(dantup): Figure out why we need to do this to get a map...
+    // source.toJson() doesn't recursively called toJson() so we end up with
+    // objects (instead of maps) in child properties, which means multiple
+    // calls to this function do not work correctly. For now, calling jsonEncode
+    // then jsonDecode will force recursive serialisation.
+    final json = jsonDecode(jsonEncode(source));
     if (textDocumentCapabilities != null) {
       textDocumentCapabilities.keys.forEach((key) {
         json[key] = textDocumentCapabilities[key];
@@ -899,7 +905,9 @@
     WorkspaceClientCapabilities source,
     Map<String, dynamic> workspaceCapabilities,
   ) {
-    final json = source.toJson();
+    // TODO(dantup): As above - it seems like this round trip should be
+    // unnecessary.
+    final json = jsonDecode(jsonEncode(source));
     if (workspaceCapabilities != null) {
       workspaceCapabilities.keys.forEach((key) {
         json[key] = workspaceCapabilities[key];
@@ -963,6 +971,14 @@
     });
   }
 
+  TextDocumentClientCapabilities withHoverDynamicRegistration(
+    TextDocumentClientCapabilities source,
+  ) {
+    return extendTextDocumentCapabilities(source, {
+      'hover': {'dynamicRegistration': true}
+    });
+  }
+
   TextDocumentClientCapabilities withSignatureHelpContentFormat(
     TextDocumentClientCapabilities source,
     List<MarkupKind> formats,
@@ -976,6 +992,14 @@
     });
   }
 
+  TextDocumentClientCapabilities withTextSyncDynamicRegistration(
+    TextDocumentClientCapabilities source,
+  ) {
+    return extendTextDocumentCapabilities(source, {
+      'synchronization': {'dynamicRegistration': true}
+    });
+  }
+
   TextDocumentClientCapabilities withHierarchicalDocumentSymbolSupport(
     TextDocumentClientCapabilities source,
   ) {
diff --git a/pkg/analysis_server/test/lsp/server_test.dart b/pkg/analysis_server/test/lsp/server_test.dart
index eb79236..17cea13 100644
--- a/pkg/analysis_server/test/lsp/server_test.dart
+++ b/pkg/analysis_server/test/lsp/server_test.dart
@@ -75,6 +75,7 @@
       const Duration(seconds: 1),
       onTimeout: () {
         didTimeout = true;
+        return null;
       },
     );
 
diff --git a/pkg/analysis_server/test/lsp/test_all.dart b/pkg/analysis_server/test/lsp/test_all.dart
index 54c5d7d..7973bac 100644
--- a/pkg/analysis_server/test/lsp/test_all.dart
+++ b/pkg/analysis_server/test/lsp/test_all.dart
@@ -6,6 +6,7 @@
 
 import '../src/lsp/lsp_packet_transformer_test.dart' as lsp_packet_transformer;
 import 'analyzer_status_test.dart' as analyzer_status;
+import 'cancel_request_test.dart' as cancel_request;
 import 'change_workspace_folders_test.dart' as change_workspace_folders;
 import 'code_actions_assists_test.dart' as code_actions_assists;
 import 'code_actions_fixes_test.dart' as code_actions_fixes;
@@ -32,6 +33,7 @@
 main() {
   defineReflectiveSuite(() {
     analyzer_status.main();
+    cancel_request.main();
     change_workspace_folders.main();
     code_actions_assists.main();
     code_actions_fixes.main();
diff --git a/pkg/analysis_server/test/lsp/workspace_symbols_test.dart b/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
index 72cad45..8bf1e30 100644
--- a/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
+++ b/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -10,7 +11,9 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(WorkspaceSymbolsTest);
+    if (!AnalysisDriver.useSummary2) {
+      defineReflectiveTests(WorkspaceSymbolsTest);
+    }
   });
 }
 
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index 367e52e..6daf2ec 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -107,7 +107,8 @@
 
     notification = _convertJson(notification, lsp.NotificationMessage.fromJson);
 
-    _clientToServer.add(notification);
+    // Wrap send request in future to simulate WebSocket.
+    new Future(() => _clientToServer.add(notification));
   }
 
   @override
diff --git a/pkg/analysis_server/test/search/declarations_test.dart b/pkg/analysis_server/test/search/declarations_test.dart
index 000ba70..3d505be 100644
--- a/pkg/analysis_server/test/search/declarations_test.dart
+++ b/pkg/analysis_server/test/search/declarations_test.dart
@@ -6,6 +6,7 @@
 
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -14,7 +15,9 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(DeclarationsTest);
+    if (!AnalysisDriver.useSummary2) {
+      defineReflectiveTests(DeclarationsTest);
+    }
   });
 }
 
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
index 9d9a40d..dd6b22f 100644
--- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -582,16 +582,20 @@
     //
     addTestSource('main() { int.parse("16", ^);}');
     await computeSuggestions();
-    assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'radix': 'int',
+      'onError': 'int Function(String)'
+    });
   }
 
   test_ArgumentList_imported_function_named_param1() async {
     //
     addTestSource('main() { int.parse("16", r^);}');
     await computeSuggestions();
-    assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'radix': 'int',
+      'onError': 'int Function(String)'
+    });
   }
 
   test_ArgumentList_imported_function_named_param2() async {
@@ -599,7 +603,7 @@
     addTestSource('main() { int.parse("16", radix: 7, ^);}');
     await computeSuggestions();
     assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'onError': '(String) → int'});
+        namedArgumentsWithTypes: {'onError': 'int Function(String)'});
   }
 
   test_ArgumentList_imported_function_named_param2a() async {
@@ -613,9 +617,10 @@
     //
     addTestSource('main() { int.parse("16", r^: 16);}');
     await computeSuggestions();
-    assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'},
-        includeColon: false);
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'radix': 'int',
+      'onError': 'int Function(String)'
+    }, includeColon: false);
   }
 
   test_ArgumentList_imported_function_named_param_label2() async {
@@ -629,8 +634,10 @@
     //
     addTestSource('main() { int.parse("16", ^: 16);}');
     await computeSuggestions();
-    assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'radix': 'int',
+      'onError': 'int Function(String)'
+    });
   }
 
   test_ArgumentList_local_constructor_named_fieldFormal_documentation() async {
@@ -886,8 +893,10 @@
 f(v,{int radix, int onError(String s)}){}
 main() { f("16", ^);}''');
     await computeSuggestions();
-    assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'radix': 'int',
+      'onError': 'int Function(String)'
+    });
   }
 
   test_ArgumentList_local_function_named_param1() async {
@@ -896,8 +905,10 @@
 f(v,{int radix, int onError(String s)}){}
 main() { f("16", r^);}''');
     await computeSuggestions();
-    assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'radix': 'int',
+      'onError': 'int Function(String)'
+    });
   }
 
   test_ArgumentList_local_function_named_param2() async {
@@ -907,7 +918,7 @@
 main() { f("16", radix: 7, ^);}''');
     await computeSuggestions();
     assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'onError': '(String) → int'});
+        namedArgumentsWithTypes: {'onError': 'int Function(String)'});
   }
 
   test_ArgumentList_local_function_named_param2a() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
index ed57fbe..49a2d65 100644
--- a/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
@@ -269,6 +269,30 @@
     assertNotSuggested('_name');
   }
 
+  test_SimpleFormalParameter_FormalParameterList() async {
+    addTestSource('''
+f(A ^) {}
+''');
+    await computeSuggestions();
+    expect(replacementOffset, 4);
+    expect(replacementLength, 0);
+    assertSuggestName('a');
+    // private version
+    assertNotSuggested('_a');
+  }
+
+  test_SimpleFormalParameter_itself() async {
+    addTestSource('''
+f(A n^) {}
+''');
+    await computeSuggestions();
+    expect(replacementOffset, 4);
+    expect(replacementLength, 1);
+    assertSuggestName('a');
+    // private version
+    assertNotSuggested('_a');
+  }
+
   test_TopLevelVariableDeclaration_dont_suggest_type() async {
     addTestSource('''
     a ^
diff --git a/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart b/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
index 97064f5..469ba02 100644
--- a/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
+++ b/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
@@ -21,6 +21,7 @@
   final Map<int, AvailableSuggestionSet> idToSetMap = {};
   final Map<String, AvailableSuggestionSet> uriToSetMap = {};
   final Map<String, CompletionResultsParams> idToSuggestions = {};
+  final Map<String, ExistingImports> fileToExistingImports = {};
 
   void assertJsonText(Object object, String expected) {
     expected = expected.trimRight();
@@ -56,6 +57,13 @@
     } else if (notification.event == COMPLETION_RESULTS) {
       var params = CompletionResultsParams.fromNotification(notification);
       idToSuggestions[params.id] = params;
+    } else if (notification.event == COMPLETION_NOTIFICATION_EXISTING_IMPORTS) {
+      var params = CompletionExistingImportsParams.fromNotification(
+        notification,
+      );
+      fileToExistingImports[params.file] = params.imports;
+    } else if (notification.event == SERVER_NOTIFICATION_ERROR) {
+      fail('${notification.toJson()}');
     }
   }
 
diff --git a/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart b/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
index 600a33a..47c59ec 100644
--- a/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
@@ -10,12 +10,50 @@
 
 main() {
   defineReflectiveSuite(() {
+    defineReflectiveTests(ExistingImportsNotification);
     defineReflectiveTests(GetSuggestionAvailableTest);
   });
 }
 
 @reflectiveTest
-class GetSuggestionAvailableTest extends AvailableSuggestionsBase {
+class ExistingImportsNotification extends GetSuggestionsBase {
+  test_dart() async {
+    addTestFile(r'''
+import 'dart:math';
+''');
+    await _getSuggestions(testFile, 0);
+    _assertHasImport('dart:math', 'dart:math', 'Random');
+  }
+
+  test_invalidUri() async {
+    addTestFile(r'''
+import 'ht:';
+''');
+    await _getSuggestions(testFile, 0);
+    // We should not get 'server.error' notification.
+  }
+
+  void _assertHasImport(String exportingUri, String declaringUri, String name) {
+    var existingImports = fileToExistingImports[testFile];
+    expect(existingImports, isNotNull);
+
+    var existingImport = existingImports.imports.singleWhere((import) =>
+        existingImports.elements.strings[import.uri] == exportingUri);
+
+    var elements = existingImport.elements.map((index) {
+      var uriIndex = existingImports.elements.uris[index];
+      var nameIndex = existingImports.elements.names[index];
+      var uri = existingImports.elements.strings[uriIndex];
+      var name = existingImports.elements.strings[nameIndex];
+      return '$uri::$name';
+    }).toList();
+
+    expect(elements, contains('$declaringUri::$name'));
+  }
+}
+
+@reflectiveTest
+class GetSuggestionAvailableTest extends GetSuggestionsBase {
   test_dart() async {
     addTestFile('');
     var mathSet = await waitForSetWithUri('dart:math');
@@ -284,7 +322,9 @@
 ]
 ''');
   }
+}
 
+abstract class GetSuggestionsBase extends AvailableSuggestionsBase {
   Future<CompletionResultsParams> _getSuggestions(
     String path,
     int offset,
diff --git a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
index fe6ebd6..2ab09bd 100644
--- a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
@@ -205,6 +205,73 @@
     }
   }
 
+  test_children_closure_blockBody() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+import 'package:flutter/widgets.dart';
+
+class WidgetA extends StatelessWidget {
+  final Widget Function(bool) factory;
+
+  WidgetA(this.factory);
+}
+''');
+    FlutterOutline unitOutline = await _computeOutline('''
+import 'package:flutter/widgets.dart';
+import 'a.dart';
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new WidgetA((b) {
+      if (b) {
+        return const Text('aaa'),
+      } else {
+        return const Container(),
+      }
+    }); // WidgetA
+  }
+}
+''');
+    expect(_toText(unitOutline), r'''
+(D) MyWidget
+  (D) build
+    WidgetA
+      Text
+      Container
+''');
+  }
+
+  test_children_closure_expressionBody() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+import 'package:flutter/widgets.dart';
+
+class WidgetA extends StatelessWidget {
+  final Widget Function() factory;
+
+  WidgetA(this.factory);
+}
+''');
+    FlutterOutline unitOutline = await _computeOutline('''
+import 'package:flutter/widgets.dart';
+import 'a.dart';
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new WidgetA(
+      () => const Text('aaa'),
+    ); // WidgetA
+  }
+}
+''');
+    expect(_toText(unitOutline), r'''
+(D) MyWidget
+  (D) build
+    WidgetA
+      Text
+''');
+  }
+
   test_children_withCollectionElements() async {
     FlutterOutline unitOutline = await _computeOutline('''
 import 'package:flutter/widgets.dart';
diff --git a/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart b/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
index b143f73..357b500 100644
--- a/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
+++ b/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
@@ -3,16 +3,17 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/nullability/conditional_discard.dart';
-import 'package:analysis_server/src/nullability/constraint_gatherer.dart';
-import 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
 import 'package:analysis_server/src/nullability/decorated_type.dart';
 import 'package:analysis_server/src/nullability/expression_checks.dart';
+import 'package:analysis_server/src/nullability/graph_builder.dart';
+import 'package:analysis_server/src/nullability/node_builder.dart';
 import 'package:analysis_server/src/nullability/nullability_node.dart';
 import 'package:analysis_server/src/nullability/transitional_api.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/test_utilities/find_node.dart';
+import 'package:meta/meta.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -20,13 +21,23 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(ConstraintGathererTest);
-    defineReflectiveTests(ConstraintVariableGathererTest);
+    defineReflectiveTests(GraphBuilderTest);
+    defineReflectiveTests(NodeBuilderTest);
   });
 }
 
 @reflectiveTest
-class ConstraintGathererTest extends ConstraintsTestBase {
+class GraphBuilderTest extends MigrationVisitorTestBase {
+  /// Analyzes the given source code, producing constraint variables and
+  /// constraints for it.
+  @override
+  Future<CompilationUnit> analyze(String code) async {
+    var unit = await super.analyze(code);
+    unit.accept(
+        GraphBuilder(typeProvider, _variables, graph, testSource, false));
+    return unit;
+  }
+
   void assertConditional(
       NullabilityNode node, NullabilityNode left, NullabilityNode right) {
     var conditionalNode = node as NullabilityNodeForLUB;
@@ -34,23 +45,6 @@
     expect(conditionalNode.right, same(right));
   }
 
-  /// Checks that there is a connection from [sourceNode] to [destinationNode].
-  void assertConnection(
-      NullabilityNode sourceNode, NullabilityNode destinationNode) {
-    expect(graph.getDownstreamNodes(sourceNode).toList(),
-        contains(destinationNode));
-  }
-
-  void assertNonNullIntent(NullabilityNode node, bool expected) {
-    if (expected) {
-      expect(graph.getUnconditionalUpstreamNodes(NullabilityNode.never),
-          contains(node));
-    } else {
-      expect(graph.getUnconditionalUpstreamNodes(NullabilityNode.never),
-          isNot(contains(node)));
-    }
-  }
-
   /// Checks that there are no nullability nodes upstream from [node] that could
   /// cause it to become nullable.
   void assertNoUpstreamNullability(NullabilityNode node) {
@@ -112,7 +106,7 @@
 }
 ''');
 
-    assertNonNullIntent(decoratedTypeAnnotation('int i').node, true);
+    assertEdge(decoratedTypeAnnotation('int i').node, never, hard: true);
   }
 
   test_binaryExpression_add_left_check() async {
@@ -301,55 +295,25 @@
 void f({int i = null}) {}
 ''');
 
-    assertConnection(
-        NullabilityNode.always, decoratedTypeAnnotation('int').node);
+    assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+        hard: false);
   }
 
-  test_functionDeclaration_parameter_named_no_default_assume_nullable() async {
+  test_functionDeclaration_parameter_named_no_default() async {
     await analyze('''
 void f({int i}) {}
-''',
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
+''');
 
-    assertConnection(
-        NullabilityNode.always, decoratedTypeAnnotation('int').node);
+    assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+        hard: false);
   }
 
-  test_functionDeclaration_parameter_named_no_default_assume_required() async {
-    await analyze('''
-void f({int i}) {}
-''',
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-
-    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
-  }
-
-  test_functionDeclaration_parameter_named_no_default_required_assume_nullable() async {
+  test_functionDeclaration_parameter_named_no_default_required() async {
     addMetaPackage();
     await analyze('''
 import 'package:meta/meta.dart';
 void f({@required int i}) {}
-''',
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
-
-    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
-  }
-
-  test_functionDeclaration_parameter_named_no_default_required_assume_required() async {
-    addMetaPackage();
-    await analyze('''
-import 'package:meta/meta.dart';
-void f({@required int i}) {}
-''',
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
+''');
 
     assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
   }
@@ -367,8 +331,8 @@
 void f([int i = null]) {}
 ''');
 
-    assertConnection(
-        NullabilityNode.always, decoratedTypeAnnotation('int').node);
+    assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+        hard: false);
   }
 
   test_functionDeclaration_parameter_positionalOptional_no_default() async {
@@ -376,22 +340,8 @@
 void f([int i]) {}
 ''');
 
-    assertConnection(
-        NullabilityNode.always, decoratedTypeAnnotation('int').node);
-  }
-
-  test_functionDeclaration_parameter_positionalOptional_no_default_assume_required() async {
-    // Note: the `assumeRequired` behavior shouldn't affect the behavior here
-    // because it only affects named parameters.
-    await analyze('''
-void f([int i]) {}
-''',
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-
-    assertConnection(
-        NullabilityNode.always, decoratedTypeAnnotation('int').node);
+    assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+        hard: false);
   }
 
   test_functionDeclaration_resets_unconditional_control_flow() async {
@@ -405,9 +355,9 @@
   assert(k != null);
 }
 ''');
-    assertNonNullIntent(decoratedTypeAnnotation('int i').node, true);
-    assertNonNullIntent(decoratedTypeAnnotation('int j').node, false);
-    assertNonNullIntent(decoratedTypeAnnotation('int k').node, true);
+    assertEdge(decoratedTypeAnnotation('int i').node, never, hard: true);
+    assertNoEdge(always, decoratedTypeAnnotation('int j').node);
+    assertEdge(decoratedTypeAnnotation('int k').node, never, hard: true);
   }
 
   test_functionInvocation_parameter_fromLocalParameter() async {
@@ -422,8 +372,7 @@
     var int_2 = decoratedTypeAnnotation('int/*2*/');
     var i_3 = checkExpression('i/*3*/');
     assertNullCheck(i_3, int_2.node, contextNode: int_1.node);
-    expect(
-        graph.getUnconditionalUpstreamNodes(int_1.node), contains(int_2.node));
+    assertEdge(int_2.node, int_1.node, hard: true);
   }
 
   test_functionInvocation_parameter_named() async {
@@ -447,7 +396,7 @@
 }
 ''');
     var optional_i = possiblyOptionalParameter('int i');
-    assertConnection(NullabilityNode.always, optional_i);
+    expect(getEdges(NullabilityNode.always, optional_i), isNotEmpty);
   }
 
   test_functionInvocation_parameter_named_missing_required() async {
@@ -513,7 +462,7 @@
 }
 ''');
 
-    assertNonNullIntent(decoratedTypeAnnotation('int i').node, false);
+    assertNoEdge(always, decoratedTypeAnnotation('int i').node);
   }
 
   test_if_conditional_control_flow_within() async {
@@ -528,7 +477,7 @@
 }
 ''');
 
-    assertNonNullIntent(decoratedTypeAnnotation('int i').node, false);
+    assertNoEdge(always, decoratedTypeAnnotation('int i').node);
   }
 
   test_if_guard_equals_null() async {
@@ -613,9 +562,9 @@
   }
 }
 ''');
-    assertNonNullIntent(decoratedTypeAnnotation('int i').node, true);
-    assertNonNullIntent(decoratedTypeAnnotation('int j').node, false);
-    assertNonNullIntent(decoratedTypeAnnotation('int k').node, true);
+    assertEdge(decoratedTypeAnnotation('int i').node, never, hard: true);
+    assertNoEdge(always, decoratedTypeAnnotation('int j').node);
+    assertEdge(decoratedTypeAnnotation('int k').node, never, hard: true);
   }
 
   test_methodInvocation_parameter_contravariant() async {
@@ -649,8 +598,9 @@
 }
 ''');
 
-    assertConnection(decoratedTypeAnnotation('int/*3*/').node,
-        decoratedTypeAnnotation('int/*1*/').node);
+    assertEdge(decoratedTypeAnnotation('int/*3*/').node,
+        decoratedTypeAnnotation('int/*1*/').node,
+        hard: false);
     assertNullCheck(checkExpression('c/*check*/'),
         decoratedTypeAnnotation('C<int/*3*/>/*4*/').node,
         contextNode: decoratedTypeAnnotation('C<int/*1*/>/*2*/').node);
@@ -671,6 +621,18 @@
         contextNode: nullable_i);
   }
 
+  test_methodInvocation_return_type() async {
+    await analyze('''
+class C {
+  bool m() => true;
+}
+bool f(C c) => c.m();
+''');
+    assertEdge(decoratedTypeAnnotation('bool m').node,
+        decoratedTypeAnnotation('bool f').node,
+        hard: false);
+  }
+
   test_methodInvocation_target_check() async {
     await analyze('''
 class C {
@@ -695,7 +657,7 @@
 }
 ''');
 
-    assertNonNullIntent(decoratedTypeAnnotation('C c').node, true);
+    assertEdge(decoratedTypeAnnotation('C c').node, never, hard: true);
   }
 
   test_never() async {
@@ -715,6 +677,71 @@
         contextNode: decoratedTypeAnnotation('int').node);
   }
 
+  test_prefixedIdentifier_return_type() async {
+    await analyze('''
+class C {
+  bool get b => true;
+}
+bool f(C c) => c.b;
+''');
+    assertEdge(decoratedTypeAnnotation('bool get').node,
+        decoratedTypeAnnotation('bool f').node,
+        hard: false);
+  }
+
+  test_prefixedIdentifier_target_check() async {
+    await analyze('''
+class C {
+  int get x => 1;
+}
+void test(C c) {
+  c.x;
+}
+''');
+
+    assertNullCheck(
+        checkExpression('c.x'), decoratedTypeAnnotation('C c').node);
+  }
+
+  test_prefixedIdentifier_target_demonstrates_non_null_intent() async {
+    await analyze('''
+class C {
+  int get x => 1;
+}
+void test(C c) {
+  c.x;
+}
+''');
+
+    assertEdge(decoratedTypeAnnotation('C c').node, never, hard: true);
+  }
+
+  test_propertyAccess_return_type() async {
+    await analyze('''
+class C {
+  bool get b => true;
+}
+bool f(C c) => (c).b;
+''');
+    assertEdge(decoratedTypeAnnotation('bool get').node,
+        decoratedTypeAnnotation('bool f').node,
+        hard: false);
+  }
+
+  test_propertyAccess_target_check() async {
+    await analyze('''
+class C {
+  int get x => 1;
+}
+void test(C c) {
+  (c).x;
+}
+''');
+
+    assertNullCheck(
+        checkExpression('c).x'), decoratedTypeAnnotation('C c').node);
+  }
+
   test_return_implicit_null() async {
     verifyNoTestUnitErrors = false;
     await analyze('''
@@ -723,8 +750,8 @@
 }
 ''');
 
-    assertConnection(
-        NullabilityNode.always, decoratedTypeAnnotation('int').node);
+    assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+        hard: false);
   }
 
   test_return_null() async {
@@ -738,6 +765,15 @@
         contextNode: decoratedTypeAnnotation('int').node);
   }
 
+  test_soft_edge_for_non_variable_reference() async {
+    // Edges originating in things other than variable references should be
+    // soft.
+    await analyze('''
+int f() => null;
+''');
+    assertEdge(always, decoratedTypeAnnotation('int').node, hard: false);
+  }
+
   test_stringLiteral() async {
     // TODO(paulberry): also test string interpolations
     await analyze('''
@@ -772,8 +808,9 @@
 class C<T extends Object> {}
 void f(C<int> c) {}
 ''');
-    assertConnection(decoratedTypeAnnotation('int>').node,
-        decoratedTypeAnnotation('Object>').node);
+    assertEdge(decoratedTypeAnnotation('int>').node,
+        decoratedTypeAnnotation('Object>').node,
+        hard: true);
   }
 
   test_typeName() async {
@@ -786,22 +823,79 @@
   }
 }
 
-abstract class ConstraintsTestBase extends MigrationVisitorTestBase {
-  /// Analyzes the given source code, producing constraint variables and
-  /// constraints for it.
-  @override
-  Future<CompilationUnit> analyze(String code,
-      {NullabilityMigrationAssumptions assumptions:
-          const NullabilityMigrationAssumptions()}) async {
-    var unit = await super.analyze(code);
-    unit.accept(ConstraintGatherer(
-        typeProvider, _variables, graph, testSource, false, assumptions));
-    return unit;
+class MigrationVisitorTestBase extends AbstractSingleUnitTest {
+  final _Variables _variables;
+
+  FindNode findNode;
+
+  final NullabilityGraph graph;
+
+  MigrationVisitorTestBase() : this._(NullabilityGraph());
+
+  MigrationVisitorTestBase._(this.graph) : _variables = _Variables(graph);
+
+  NullabilityNode get always => NullabilityNode.always;
+
+  NullabilityNode get never => NullabilityNode.never;
+
+  TypeProvider get typeProvider => testAnalysisResult.typeProvider;
+
+  Future<CompilationUnit> analyze(String code) async {
+    await resolveTestUnit(code);
+    testUnit.accept(
+        NodeBuilder(_variables, testSource, false, graph, typeProvider));
+    findNode = FindNode(code, testUnit);
+    return testUnit;
+  }
+
+  void assertEdge(NullabilityNode source, NullabilityNode destination,
+      {@required bool hard}) {
+    var edges = getEdges(source, destination);
+    if (edges.length == 0) {
+      fail('Expected edge $source -> $destination, found none');
+    } else if (edges.length != 1) {
+      fail('Found multiple edges $source -> $destination');
+    } else {
+      var edge = edges[0];
+      expect(edge.hard, hard);
+    }
+  }
+
+  void assertNoEdge(NullabilityNode source, NullabilityNode destination) {
+    var edges = getEdges(source, destination);
+    if (edges.isNotEmpty) {
+      fail('Expected no edge $source -> $destination, found ${edges.length}');
+    }
+  }
+
+  /// Gets the [DecoratedType] associated with the type annotation whose text
+  /// is [text].
+  DecoratedType decoratedTypeAnnotation(String text) {
+    return _variables.decoratedTypeAnnotation(
+        testSource, findNode.typeAnnotation(text));
+  }
+
+  List<NullabilityEdge> getEdges(
+          NullabilityNode source, NullabilityNode destination) =>
+      graph
+          .getUpstreamEdges(destination)
+          .where((e) => e.primarySource == source)
+          .toList();
+
+  NullabilityNode possiblyOptionalParameter(String text) {
+    return _variables
+        .possiblyOptionalParameter(findNode.defaultParameter(text));
+  }
+
+  /// Gets the [ConditionalDiscard] information associated with the statement
+  /// whose text is [text].
+  ConditionalDiscard statementDiscard(String text) {
+    return _variables.conditionalDiscard(findNode.statement(text));
   }
 }
 
 @reflectiveTest
-class ConstraintVariableGathererTest extends MigrationVisitorTestBase {
+class NodeBuilderTest extends MigrationVisitorTestBase {
   /// Gets the [DecoratedType] associated with the function declaration whose
   /// name matches [search].
   DecoratedType decoratedFunctionType(String search) =>
@@ -835,8 +929,7 @@
     expect(decoratedFunctionType('f').positionalParameters[0],
         same(decoratedType));
     expect(decoratedType.type.isDynamic, isTrue);
-    expect(graph.getUpstreamNodesForTesting(decoratedType.node),
-        contains(NullabilityNode.always));
+    expect(decoratedType.node.isNullable, isTrue);
   }
 
   test_topLevelFunction_parameterType_named_no_default() async {
@@ -907,8 +1000,7 @@
 ''');
     var decoratedType = decoratedFunctionType('f').returnType;
     expect(decoratedType.type.isDynamic, isTrue);
-    expect(graph.getUpstreamNodesForTesting(decoratedType.node),
-        contains(NullabilityNode.always));
+    expect(decoratedType.node.isNullable, isTrue);
   }
 
   test_topLevelFunction_returnType_simple() async {
@@ -939,54 +1031,11 @@
 class C<T> {}
 ''');
     var bound = decoratedTypeParameterBound('T');
-    expect(graph.getUnconditionalUpstreamNodes(bound.node),
-        contains(NullabilityNode.always));
+    expect(bound.node.isNullable, isTrue);
     expect(bound.type, same(typeProvider.objectType));
   }
 }
 
-class MigrationVisitorTestBase extends AbstractSingleUnitTest {
-  final _Variables _variables;
-
-  FindNode findNode;
-
-  final NullabilityGraph graph;
-
-  MigrationVisitorTestBase() : this._(NullabilityGraph());
-
-  MigrationVisitorTestBase._(this.graph) : _variables = _Variables(graph);
-
-  TypeProvider get typeProvider => testAnalysisResult.typeProvider;
-
-  Future<CompilationUnit> analyze(String code,
-      {NullabilityMigrationAssumptions assumptions:
-          const NullabilityMigrationAssumptions()}) async {
-    await resolveTestUnit(code);
-    testUnit.accept(ConstraintVariableGatherer(
-        _variables, testSource, false, assumptions, graph, typeProvider));
-    findNode = FindNode(code, testUnit);
-    return testUnit;
-  }
-
-  /// Gets the [DecoratedType] associated with the type annotation whose text
-  /// is [text].
-  DecoratedType decoratedTypeAnnotation(String text) {
-    return _variables.decoratedTypeAnnotation(
-        testSource, findNode.typeAnnotation(text));
-  }
-
-  NullabilityNode possiblyOptionalParameter(String text) {
-    return _variables
-        .possiblyOptionalParameter(findNode.defaultParameter(text));
-  }
-
-  /// Gets the [ConditionalDiscard] information associated with the statement
-  /// whose text is [text].
-  ConditionalDiscard statementDiscard(String text) {
-    return _variables.conditionalDiscard(findNode.statement(text));
-  }
-}
-
 /// Mock representation of constraint variables.
 class _Variables extends Variables {
   final _conditionalDiscard = <AstNode, ConditionalDiscard>{};
diff --git a/pkg/analysis_server/test/src/nullability/provisional_api_test.dart b/pkg/analysis_server/test/src/nullability/provisional_api_test.dart
index 8a4bb19..f6ba883 100644
--- a/pkg/analysis_server/test/src/nullability/provisional_api_test.dart
+++ b/pkg/analysis_server/test/src/nullability/provisional_api_test.dart
@@ -36,15 +36,13 @@
   /// Verifies that migration of the files in [input] produces the output in
   /// [expectedOutput].
   Future<void> _checkMultipleFileChanges(
-      Map<String, String> input, Map<String, String> expectedOutput,
-      {NullabilityMigrationAssumptions assumptions:
-          const NullabilityMigrationAssumptions()}) async {
+      Map<String, String> input, Map<String, String> expectedOutput) async {
     for (var path in input.keys) {
       newFile(path, content: input[path]);
     }
     var listener = new _TestMigrationListener();
-    var migration = NullabilityMigration(listener,
-        permissive: _usePermissiveMode, assumptions: assumptions);
+    var migration =
+        NullabilityMigration(listener, permissive: _usePermissiveMode);
     for (var path in input.keys) {
       migration.prepareInput(await session.getResolvedUnit(path));
     }
@@ -69,13 +67,10 @@
 
   /// Verifies that migraiton of the single file with the given [content]
   /// produces the [expected] output.
-  Future<void> _checkSingleFileChanges(String content, String expected,
-      {NullabilityMigrationAssumptions assumptions:
-          const NullabilityMigrationAssumptions()}) async {
+  Future<void> _checkSingleFileChanges(String content, String expected) async {
     var sourcePath = convertPath('/home/test/lib/test.dart');
     await _checkMultipleFileChanges(
-        {sourcePath: content}, {sourcePath: expected},
-        assumptions: assumptions);
+        {sourcePath: content}, {sourcePath: expected});
   }
 }
 
@@ -318,7 +313,7 @@
     await _checkSingleFileChanges(content, expected);
   }
 
-  test_named_parameter_no_default_unused_option2_assume_nullable() async {
+  test_named_parameter_no_default_unused() async {
     var content = '''
 void f({String s}) {}
 main() {
@@ -331,13 +326,10 @@
   f();
 }
 ''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
+    await _checkSingleFileChanges(content, expected);
   }
 
-  test_named_parameter_no_default_unused_option2_assume_nullable_propagate() async {
+  test_named_parameter_no_default_unused_propagate() async {
     var content = '''
 void f(String s) {}
 void g({String s}) {
@@ -356,57 +348,10 @@
   g();
 }
 ''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
+    await _checkSingleFileChanges(content, expected);
   }
 
-  test_named_parameter_no_default_unused_option2_assume_required() async {
-    var content = '''
-void f({String s}) {}
-main() {
-  f();
-}
-''';
-    var expected = '''
-void f({String? s}) {}
-main() {
-  f();
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-  }
-
-  test_named_parameter_no_default_unused_option2_assume_required_propagate() async {
-    var content = '''
-void f(String s) {}
-void g({String s}) {
-  f(s);
-}
-main() {
-  g();
-}
-''';
-    var expected = '''
-void f(String? s) {}
-void g({String? s}) {
-  f(s);
-}
-main() {
-  g();
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-  }
-
-  test_named_parameter_no_default_unused_required_option2_assume_nullable() async {
+  test_named_parameter_no_default_unused_required() async {
     // The `@required` annotation overrides the assumption of nullability.
     // The call at `f()` is presumed to be in error.
     addMetaPackage();
@@ -424,38 +369,10 @@
   f();
 }
 ''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
+    await _checkSingleFileChanges(content, expected);
   }
 
-  test_named_parameter_no_default_unused_required_option2_assume_required() async {
-    // Since the `@required` annotation is already present, it is not added
-    // again.
-    // The call at `f()` is presumed to be in error.
-    addMetaPackage();
-    var content = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f();
-}
-''';
-    var expected = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f();
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-  }
-
-  test_named_parameter_no_default_used_non_null_option2_assume_nullable() async {
+  test_named_parameter_no_default_used_non_null() async {
     var content = '''
 void f({String s}) {}
 main() {
@@ -468,13 +385,10 @@
   f(s: 'x');
 }
 ''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
+    await _checkSingleFileChanges(content, expected);
   }
 
-  test_named_parameter_no_default_used_non_null_option2_assume_nullable_propagate() async {
+  test_named_parameter_no_default_used_non_null_propagate() async {
     var content = '''
 void f(String s) {}
 void g({String s}) {
@@ -493,80 +407,7 @@
   g(s: 'x');
 }
 ''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
-  }
-
-  test_named_parameter_no_default_used_non_null_option2_assume_required() async {
-    var content = '''
-void f({String s}) {}
-main() {
-  f(s: 'x');
-}
-''';
-    var expected = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f(s: 'x');
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-  }
-
-  test_named_parameter_no_default_used_non_null_option2_assume_required_propagate() async {
-    var content = '''
-void f(String s) {}
-void g({String s}) {
-  f(s);
-}
-main() {
-  g(s: 'x');
-}
-''';
-    var expected = '''
-import 'package:meta/meta.dart';
-void f(String s) {}
-void g({@required String s}) {
-  f(s);
-}
-main() {
-  g(s: 'x');
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
-  }
-
-  test_named_parameter_no_default_used_non_null_required_option2_assume_required() async {
-    // Even if we are using the "assumeRequired" heuristic, we should not add a
-    // duplicate `@required` annotation.
-    addMetaPackage();
-    var content = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f(s: 'x');
-}
-''';
-    var expected = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f(s: 'x');
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
+    await _checkSingleFileChanges(content, expected);
   }
 
   test_named_parameter_no_default_used_null_option2() async {
@@ -585,7 +426,7 @@
     await _checkSingleFileChanges(content, expected);
   }
 
-  test_named_parameter_no_default_used_null_required_option2_assume_nullable() async {
+  test_named_parameter_no_default_used_null_required() async {
     // Explicitly passing `null` forces the parameter to be nullable even though
     // it is required.
     addMetaPackage();
@@ -603,34 +444,7 @@
   f(s: null);
 }
 ''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeNullable));
-  }
-
-  test_named_parameter_no_default_used_null_required_option2_assume_required() async {
-    // Explicitly passing `null` forces the parameter to be nullable even though
-    // it is required.
-    addMetaPackage();
-    var content = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
-  f(s: null);
-}
-''';
-    var expected = '''
-import 'package:meta/meta.dart';
-void f({@required String? s}) {}
-main() {
-  f(s: null);
-}
-''';
-    await _checkSingleFileChanges(content, expected,
-        assumptions: NullabilityMigrationAssumptions(
-            namedNoDefaultParameterHeuristic:
-                NamedNoDefaultParameterHeuristic.assumeRequired));
+    await _checkSingleFileChanges(content, expected);
   }
 
   test_named_parameter_with_non_null_default_unused_option2() async {
@@ -816,7 +630,7 @@
     await _checkSingleFileChanges(content, expected);
   }
 
-  test_unconditional_dereference_implies_non_null_intent() async {
+  test_unconditional_method_call_implies_non_null_intent() async {
     var content = '''
 void f(int i) {
   i.abs();
@@ -868,6 +682,32 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  test_unconditional_property_access_implies_non_null_intent() async {
+    var content = '''
+void f(int i) {
+  i.isEven;
+}
+void g(bool b, int i) {
+  if (b) f(i);
+}
+main() {
+  g(false, null);
+}
+''';
+    var expected = '''
+void f(int i) {
+  i.isEven;
+}
+void g(bool b, int? i) {
+  if (b) f(i!);
+}
+main() {
+  g(false, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   test_unconditional_usage_propagates_non_null_intent() async {
     var content = '''
 void f(int i) {
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart
index f51ffa7..4e1af86 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart
@@ -81,4 +81,20 @@
 }
 ''');
   }
+
+  test_expressionFunctionBody() async {
+    addFlutterPackage();
+    await resolveTestUnit('''
+import 'package:flutter/widgets.dart';
+class FakeFlutter {
+  main() => /*caret*/Container();
+}
+''');
+    await assertHasAssist('''
+import 'package:flutter/widgets.dart';
+class FakeFlutter {
+  main() => Center(child: Container());
+}
+''');
+  }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/assist/sort_child_property_last_test.dart b/pkg/analysis_server/test/src/services/correction/assist/sort_child_property_last_test.dart
new file mode 100644
index 0000000..4cc5973
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/sort_child_property_last_test.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2019, 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:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SortChildPropertyLastTest);
+  });
+}
+
+@reflectiveTest
+class SortChildPropertyLastTest extends AssistProcessorTest {
+  @override
+  AssistKind get kind => DartAssistKind.SORT_CHILD_PROPERTY_LAST;
+
+  test_already_sorted() async {
+    addFlutterPackage();
+    await resolveTestUnit('''
+import 'package:flutter/material.dart';
+main() {
+  Column(
+    crossAxisAlignment: CrossAxisAlignment.center,
+    children: <Widget>[
+      Text('aaa'),
+      Text('bbbbbb'),
+      Text('ccccccccc'),
+    ],
+  );
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_already_sorted_one_prop() async {
+    addFlutterPackage();
+    await resolveTestUnit('''
+import 'package:flutter/material.dart';
+main() {
+  Column(
+    children: <Widget>[
+      Text('aaa'),
+      Text('bbbbbb'),
+      Text('ccccccccc'),
+    ],
+  );
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_no_children() async {
+    addFlutterPackage();
+    await resolveTestUnit('''
+import 'package:flutter/material.dart';
+main() {
+  Column(
+    crossAxisAlignment: CrossAxisAlignment.center,
+  );
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_sort() async {
+    addFlutterPackage();
+    await resolveTestUnit('''
+import 'package:flutter/material.dart';
+main() {
+  Column(
+    /*caret*/children: <Widget>[
+      Text('aaa'),
+      Text('bbbbbb'),
+      Text('ccccccccc'),
+    ],
+    crossAxisAlignment: CrossAxisAlignment.center,
+  );
+}
+''');
+    await assertHasAssist('''
+import 'package:flutter/material.dart';
+main() {
+  Column(
+    crossAxisAlignment: CrossAxisAlignment.center,
+    children: <Widget>[
+      Text('aaa'),
+      Text('bbbbbb'),
+      Text('ccccccccc'),
+    ],
+  );
+}
+''');
+    assertExitPosition(after: "],");
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
index d76f97b..7a7f079 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
@@ -67,6 +67,7 @@
     as replace_conditional_with_if_else;
 import 'replace_if_else_with_conditional_test.dart'
     as replace_if_else_with_conditional;
+import 'sort_child_property_last_test.dart' as sort_child_property_last;
 import 'split_and_condition_test.dart' as split_and_condition;
 import 'split_variable_declaration_test.dart' as split_variable_declaration;
 import 'surround_with_block_test.dart' as surround_with_block;
@@ -135,6 +136,7 @@
     remove_type_annotation.main();
     replace_conditional_with_if_else.main();
     replace_if_else_with_conditional.main();
+    sort_child_property_last.main();
     split_and_condition.main();
     split_variable_declaration.main();
     surround_with_block.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
index beb7025..4dbfa14 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
@@ -7,9 +7,12 @@
 import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/error/lint_codes.dart';
+import 'package:analyzer/src/services/available_declarations.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     hide AnalysisError;
 import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
@@ -250,7 +253,19 @@
 
   /// Computes fixes for the given [error] in [testUnit].
   Future<List<Fix>> _computeFixes(AnalysisError error) async {
-    var context = new DartFixContextImpl(workspace, testAnalysisResult, error);
+    var tracker = DeclarationsTracker(MemoryByteStore(), resourceProvider);
+    tracker.addContext(driver.analysisContext);
+
+    var context = new DartFixContextImpl(
+      workspace,
+      testAnalysisResult,
+      error,
+      (name) {
+        var provider = TopLevelDeclarationsProvider(tracker);
+        provider.doTrackerWork();
+        return provider.get(driver.analysisContext, testFile, name);
+      },
+    );
     return await new DartFixContributor().computeFixes(context);
   }
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
index f1d1710..6c11ac8 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
@@ -18,8 +18,7 @@
 }
 
 @reflectiveTest
-class ImportLibraryProject1Test extends FixProcessorTest
-    with ImportLibraryTestMixin {
+class ImportLibraryProject1Test extends FixProcessorTest {
   @override
   FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT1;
 
@@ -39,6 +38,45 @@
     await assertNoFix();
   }
 
+  test_lib() async {
+    addPackageFile('my_pkg', 'a.dart', 'class Test {}');
+    newFile('/home/test/pubspec.yaml', content: r'''
+dependencies:
+  my_pkg: any
+''');
+
+    await resolveTestUnit('''
+main() {
+  Test test = null;
+  print(test);
+}
+''');
+
+    await assertHasFix('''
+import 'package:my_pkg/a.dart';
+
+main() {
+  Test test = null;
+  print(test);
+}
+''', expectedNumberOfFixesForKind: 1);
+  }
+
+  test_lib_src() async {
+    addPackageFile('my_pkg', 'src/a.dart', 'class Test {}');
+    newFile('/home/test/pubspec.yaml', content: r'''
+dependencies:
+  my_pkg: any
+''');
+    await resolveTestUnit('''
+main() {
+  Test test = null;
+  print(test);
+}
+''');
+    await assertNoFix();
+  }
+
   test_notInLib() async {
     addSource('/home/other/test/lib.dart', 'class Test {}');
     await resolveTestUnit('''
@@ -50,66 +88,40 @@
     await assertNoFix();
   }
 
-  test_preferDirectOverExport() async {
-    _configureMyPkg({'b.dart': 'class Test {}', 'a.dart': "export 'b.dart';"});
-    await resolveTestUnit('''
-main() {
-  Test test = null;
-  print(test);
-}
-''');
-    await assertHasFix('''
-import 'package:my_pkg/b.dart';
-
-main() {
-  Test test = null;
-  print(test);
-}
-''', expectedNumberOfFixesForKind: 1);
-  }
-
-  test_preferDirectOverExport_src() async {
-    _configureMyPkg({'b.dart': 'class Test {}', 'a.dart': "export 'b.dart';"});
-    await resolveTestUnit('''
-main() {
-  Test test = null;
-  print(test);
-}
-''');
-    await assertHasFix('''
-import 'package:my_pkg/b.dart';
-
-main() {
-  Test test = null;
-  print(test);
-}
-''', expectedNumberOfFixesForKind: 1);
-  }
-
   test_relativeDirective() async {
     addSource('/home/test/lib/a.dart', '''
-import "b.dart";
-''');
-    addSource('/home/test/lib/b.dart', '''
 class Foo {}
 ''');
     await resolveTestUnit('''
 main() { new Foo(); }
 ''');
     await assertHasFix('''
-import 'b.dart';
+import 'a.dart';
 
 main() { new Foo(); }
 ''',
         expectedNumberOfFixesForKind: 2,
-        matchFixMessage: "Import library 'b.dart'");
+        matchFixMessage: "Import library 'a.dart'");
+  }
+
+  test_relativeDirective_downOneDirectory() async {
+    addSource('/home/test/lib/dir/a.dart', '''
+class Foo {}
+''');
+    await resolveTestUnit('''
+main() { new Foo(); }
+''');
+    await assertHasFix('''
+import 'dir/a.dart';
+
+main() { new Foo(); }
+''',
+        expectedNumberOfFixesForKind: 2,
+        matchFixMessage: "Import library 'dir/a.dart'");
   }
 
   test_relativeDirective_upOneDirectory() async {
     addSource('/home/test/lib/a.dart', '''
-import "b.dart";
-''');
-    addSource('/home/test/lib/b.dart', '''
 class Foo {}
 ''');
     testFile = convertPath('/home/test/lib/dir/test.dart');
@@ -117,31 +129,12 @@
 main() { new Foo(); }
 ''');
     await assertHasFix('''
-import '../b.dart';
+import '../a.dart';
 
 main() { new Foo(); }
 ''',
         expectedNumberOfFixesForKind: 2,
-        matchFixMessage: "Import library '../b.dart'");
-  }
-
-  test_relativeDirective_downOneDirectory() async {
-    addSource('/home/test/lib/dir/a.dart', '''
-import "b.dart";
-''');
-    addSource('/home/test/lib/dir/b.dart', '''
-class Foo {}
-''');
-    await resolveTestUnit('''
-main() { new Foo(); }
-''');
-    await assertHasFix('''
-import 'dir/b.dart';
-
-main() { new Foo(); }
-''',
-        expectedNumberOfFixesForKind: 2,
-        matchFixMessage: "Import library 'dir/b.dart'");
+        matchFixMessage: "Import library '../a.dart'");
   }
 
   test_withClass_annotation() async {
@@ -395,7 +388,6 @@
 
   @failingTest
   test_withFunction_nonFunctionType() async {
-    // TODO Remove preferFunctionOverTopLevelVariable test once this is passing
     addSource('/home/test/lib/lib.dart', 'int zero = 0;');
     await resolveTestUnit('''
 main() {
@@ -405,25 +397,6 @@
     await assertNoFix();
   }
 
-  test_withFunction_preferFunctionOverTopLevelVariable() async {
-    _configureMyPkg({
-      'b.dart': 'var myFunction = () {};',
-      'a.dart': 'myFunction() {}',
-    });
-    await resolveTestUnit('''
-main() {
-  myFunction();
-}
-''');
-    await assertHasFix('''
-import 'package:my_pkg/a.dart';
-
-main() {
-  myFunction();
-}
-''');
-  }
-
   test_withFunction_unresolvedMethod() async {
     addSource('/home/test/lib/lib.dart', '''
 library lib;
@@ -505,16 +478,17 @@
 }
 
 @reflectiveTest
-class ImportLibraryProject2Test extends FixProcessorTest
-    with ImportLibraryTestMixin {
+class ImportLibraryProject2Test extends FixProcessorTest {
   @override
   FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT2;
 
-  test_preferDirectOverExport() async {
-    _configureMyPkg({
-      'b.dart': 'class Test {}',
-      'a.dart': "export 'b.dart';",
-    });
+  test_lib() async {
+    addPackageFile('my_pkg', 'a.dart', "export 'b.dart';");
+    addPackageFile('my_pkg', 'b.dart', 'class Test {}');
+    newFile('/home/test/pubspec.yaml', content: r'''
+dependencies:
+  my_pkg: any
+''');
     await resolveTestUnit('''
 main() {
   Test test = null;
@@ -531,11 +505,13 @@
 ''');
   }
 
-  test_preferDirectOverExport_src() async {
-    _configureMyPkg({
-      'b.dart': 'class Test {}',
-      'a.dart': "export 'b.dart';",
-    });
+  test_lib_src() async {
+    addPackageFile('my_pkg', 'a.dart', "export 'src/b.dart';");
+    addPackageFile('my_pkg', 'src/b.dart', 'class Test {}');
+    newFile('/home/test/pubspec.yaml', content: r'''
+dependencies:
+  my_pkg: any
+''');
     await resolveTestUnit('''
 main() {
   Test test = null;
@@ -593,15 +569,3 @@
 ''');
   }
 }
-
-mixin ImportLibraryTestMixin on FixProcessorTest {
-  /// Configures the source factory to have a package named 'my_pkg' and for
-  /// the package to contain all of the files described by the [pathToCode] map.
-  /// The keys in the map are paths relative to the root of the package, and the
-  /// values are the contents of the files at those paths.
-  void _configureMyPkg(Map<String, String> pathToCode) {
-    pathToCode.forEach((path, code) {
-      addPackageFile('my_pkg', path, code);
-    });
-  }
-}
diff --git a/pkg/analysis_server/test/src/utilities/flutter_test.dart b/pkg/analysis_server/test/src/utilities/flutter_test.dart
index 6bb17e3..5a558ac 100644
--- a/pkg/analysis_server/test/src/utilities/flutter_test.dart
+++ b/pkg/analysis_server/test/src/utilities/flutter_test.dart
@@ -279,6 +279,16 @@
     expect(flutter.identifyWidgetExpression(expression), expression);
   }
 
+  test_identifyWidgetExpression_parent_expressionFunctionBody() async {
+    await resolveTestUnit('''
+import 'package:flutter/widgets.dart';
+
+main(Widget widget) => widget; // ref
+''');
+    Expression expression = findNodeAtString("widget; // ref");
+    expect(flutter.identifyWidgetExpression(expression), expression);
+  }
+
   test_identifyWidgetExpression_parent_expressionStatement() async {
     await resolveTestUnit('''
 import 'package:flutter/widgets.dart';
diff --git a/pkg/analysis_server/tool/lsp_spec/README.md b/pkg/analysis_server/tool/lsp_spec/README.md
index 5cfc02b..f44d5ea 100644
--- a/pkg/analysis_server/tool/lsp_spec/README.md
+++ b/pkg/analysis_server/tool/lsp_spec/README.md
@@ -36,14 +36,14 @@
 | initialize | ✅ | ✅ | ✅ | ✅ | trace and other options NYI
 | initialized | ✅ | ✅ | ✅ | ✅ |
 | shutdown | ✅ | ✅ | ✅ | ✅ | supported but does nothing |
-| exit | | | | | |
-| $/cancelRequest | | | | | ignored (unsupported) |
+| exit | ✅ | ✅ | ✅ | ✅ |
+| $/cancelRequest | ✅ | ✅ | ✅ | ✅ |
 | window/showMessage | ✅ | | | |
 | window/showMessageRequest | | | | |
 | window/logMessage | ✅ | | | |
 | telemetry/event | | | | |
-| client/registerCapability | | | | | unused, but should be used for DocumentSelector at least
-| client/unregisterCapability | | | | |
+| client/registerCapability | ✅ | ✅ | ✅ | ✅ |
+| client/unregisterCapability | | | | | (unused, capabilities don't change currently)
 | workspace/workspaceFolders | | | | |
 | workspace/didChangeWorkspaceFolders | ✅ | ✅ | ✅ | ✅ |
 | workspace/configuration | | | | |
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript.dart b/pkg/analysis_server/tool/lsp_spec/typescript.dart
index 130cbe2..f80733d 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript.dart
@@ -50,6 +50,9 @@
     "TextDocumentSyncOptions": {
       "change": "TextDocumentSyncKind",
     },
+    "TextDocumentChangeRegistrationOptions": {
+      "syncKind": "TextDocumentSyncKind",
+    },
     "FileSystemWatcher": {
       "kind": "WatchKind",
     },
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java
index 5007ebd..8de0a91 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java
@@ -16,10 +16,12 @@
 public class CompletionService {
 
   /**
-   * The client will receive notifications once subscribed with completion suggestion sets from the
-   * libraries of interest. The client should keep an up-to-date record of these in memory so that it
-   * will be able to union these candidates with other completion suggestions when applicable at
-   * completion time.
+   * The client will receive availableSuggestions notifications once subscribed with completion
+   * suggestion sets from the libraries of interest. The client should keep an up-to-date record of
+   * these in memory so that it will be able to union these candidates with other completion
+   * suggestions when applicable at completion time.
+   *
+   * The client will also receive existingImports notifications.
    */
   public static final String AVAILABLE_SUGGESTION_SETS = "AVAILABLE_SUGGESTION_SETS";
 
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExistingImport.java b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImport.java
new file mode 100644
index 0000000..a9055d0
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImport.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ *
+ * This file has been automatically generated. Please do not edit it manually.
+ * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
+ */
+package org.dartlang.analysis.server.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Information about an existing import, with elements that it provides.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ExistingImport {
+
+  public static final ExistingImport[] EMPTY_ARRAY = new ExistingImport[0];
+
+  public static final List<ExistingImport> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in the enclosing
+   * ExistingImports and its ImportedElementSet object.
+   */
+  private final int uri;
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  private final int[] elements;
+
+  /**
+   * Constructor for {@link ExistingImport}.
+   */
+  public ExistingImport(int uri, int[] elements) {
+    this.uri = uri;
+    this.elements = elements;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ExistingImport) {
+      ExistingImport other = (ExistingImport) obj;
+      return
+        other.uri == uri &&
+        Arrays.equals(other.elements, elements);
+    }
+    return false;
+  }
+
+  public static ExistingImport fromJson(JsonObject jsonObject) {
+    int uri = jsonObject.get("uri").getAsInt();
+    int[] elements = JsonUtilities.decodeIntArray(jsonObject.get("elements").getAsJsonArray());
+    return new ExistingImport(uri, elements);
+  }
+
+  public static List<ExistingImport> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<ExistingImport> list = new ArrayList<ExistingImport>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  public int[] getElements() {
+    return elements;
+  }
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in the enclosing
+   * ExistingImports and its ImportedElementSet object.
+   */
+  public int getUri() {
+    return uri;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(uri);
+    builder.append(elements);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("uri", uri);
+    JsonArray jsonArrayElements = new JsonArray();
+    for (int elt : elements) {
+      jsonArrayElements.add(new JsonPrimitive(elt));
+    }
+    jsonObject.add("elements", jsonArrayElements);
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("uri=");
+    builder.append(uri + ", ");
+    builder.append("elements=");
+    builder.append(StringUtils.join(elements, ", "));
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExistingImports.java b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImports.java
new file mode 100644
index 0000000..7473d829
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImports.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ *
+ * This file has been automatically generated. Please do not edit it manually.
+ * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
+ */
+package org.dartlang.analysis.server.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Information about all existing imports in a library.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ExistingImports {
+
+  public static final ExistingImports[] EMPTY_ARRAY = new ExistingImports[0];
+
+  public static final List<ExistingImports> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  private final ImportedElementSet elements;
+
+  /**
+   * The list of imports in the library.
+   */
+  private final List<ExistingImport> imports;
+
+  /**
+   * Constructor for {@link ExistingImports}.
+   */
+  public ExistingImports(ImportedElementSet elements, List<ExistingImport> imports) {
+    this.elements = elements;
+    this.imports = imports;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ExistingImports) {
+      ExistingImports other = (ExistingImports) obj;
+      return
+        ObjectUtilities.equals(other.elements, elements) &&
+        ObjectUtilities.equals(other.imports, imports);
+    }
+    return false;
+  }
+
+  public static ExistingImports fromJson(JsonObject jsonObject) {
+    ImportedElementSet elements = ImportedElementSet.fromJson(jsonObject.get("elements").getAsJsonObject());
+    List<ExistingImport> imports = ExistingImport.fromJsonArray(jsonObject.get("imports").getAsJsonArray());
+    return new ExistingImports(elements, imports);
+  }
+
+  public static List<ExistingImports> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<ExistingImports> list = new ArrayList<ExistingImports>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  public ImportedElementSet getElements() {
+    return elements;
+  }
+
+  /**
+   * The list of imports in the library.
+   */
+  public List<ExistingImport> getImports() {
+    return imports;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(elements);
+    builder.append(imports);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.add("elements", elements.toJson());
+    JsonArray jsonArrayImports = new JsonArray();
+    for (ExistingImport elt : imports) {
+      jsonArrayImports.add(elt.toJson());
+    }
+    jsonObject.add("imports", jsonArrayImports);
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("elements=");
+    builder.append(elements + ", ");
+    builder.append("imports=");
+    builder.append(StringUtils.join(imports, ", "));
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java b/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java
index 463b420..88e6f0b 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java
@@ -55,8 +55,9 @@
   private final String containingLibraryPath;
 
   /**
-   * The name of the library in which the referenced element is declared. This data is omitted if
-   * there is no referenced element, or if the element is declared inside an HTML file.
+   * The URI of the containing library, examples here include "dart:core", "package:.." and file uris
+   * represented by the path on disk, "/..". The data is omitted if the element is declared inside an
+   * HTML file.
    */
   private final String containingLibraryName;
 
@@ -185,8 +186,9 @@
   }
 
   /**
-   * The name of the library in which the referenced element is declared. This data is omitted if
-   * there is no referenced element, or if the element is declared inside an HTML file.
+   * The URI of the containing library, examples here include "dart:core", "package:.." and file uris
+   * represented by the path on disk, "/..". The data is omitted if the element is declared inside an
+   * HTML file.
    */
   public String getContainingLibraryName() {
     return containingLibraryName;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ImportedElementSet.java b/pkg/analysis_server/tool/spec/generated/java/types/ImportedElementSet.java
new file mode 100644
index 0000000..50ca031
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ImportedElementSet.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ *
+ * This file has been automatically generated. Please do not edit it manually.
+ * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
+ */
+package org.dartlang.analysis.server.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * The set of top-level elements encoded as pairs of the defining library URI and the name, and
+ * stored in the parallel lists elementUris and elementNames.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ImportedElementSet {
+
+  public static final ImportedElementSet[] EMPTY_ARRAY = new ImportedElementSet[0];
+
+  public static final List<ImportedElementSet> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The list of unique strings in this object.
+   */
+  private final List<String> strings;
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  private final int[] uris;
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  private final int[] names;
+
+  /**
+   * Constructor for {@link ImportedElementSet}.
+   */
+  public ImportedElementSet(List<String> strings, int[] uris, int[] names) {
+    this.strings = strings;
+    this.uris = uris;
+    this.names = names;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ImportedElementSet) {
+      ImportedElementSet other = (ImportedElementSet) obj;
+      return
+        ObjectUtilities.equals(other.strings, strings) &&
+        Arrays.equals(other.uris, uris) &&
+        Arrays.equals(other.names, names);
+    }
+    return false;
+  }
+
+  public static ImportedElementSet fromJson(JsonObject jsonObject) {
+    List<String> strings = JsonUtilities.decodeStringList(jsonObject.get("strings").getAsJsonArray());
+    int[] uris = JsonUtilities.decodeIntArray(jsonObject.get("uris").getAsJsonArray());
+    int[] names = JsonUtilities.decodeIntArray(jsonObject.get("names").getAsJsonArray());
+    return new ImportedElementSet(strings, uris, names);
+  }
+
+  public static List<ImportedElementSet> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<ImportedElementSet> list = new ArrayList<ImportedElementSet>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  public int[] getNames() {
+    return names;
+  }
+
+  /**
+   * The list of unique strings in this object.
+   */
+  public List<String> getStrings() {
+    return strings;
+  }
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  public int[] getUris() {
+    return uris;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(strings);
+    builder.append(uris);
+    builder.append(names);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    JsonArray jsonArrayStrings = new JsonArray();
+    for (String elt : strings) {
+      jsonArrayStrings.add(new JsonPrimitive(elt));
+    }
+    jsonObject.add("strings", jsonArrayStrings);
+    JsonArray jsonArrayUris = new JsonArray();
+    for (int elt : uris) {
+      jsonArrayUris.add(new JsonPrimitive(elt));
+    }
+    jsonObject.add("uris", jsonArrayUris);
+    JsonArray jsonArrayNames = new JsonArray();
+    for (int elt : names) {
+      jsonArrayNames.add(new JsonPrimitive(elt));
+    }
+    jsonObject.add("names", jsonArrayNames);
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("strings=");
+    builder.append(StringUtils.join(strings, ", ") + ", ");
+    builder.append("uris=");
+    builder.append(StringUtils.join(uris, ", ") + ", ");
+    builder.append("names=");
+    builder.append(StringUtils.join(names, ", "));
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 362a389..e49442e 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -7,7 +7,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  <version>1.26.1</version>
+  <version>1.27.0</version>
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -1588,6 +1588,17 @@
           returned for the indicated completion.
         </p>
       </field>
+      <field name="libraryFile" optional="true">
+        <ref>FilePath</ref>
+        <p>
+          The library file that contains the file where completion was
+          requested. The client might use it for example together with the
+          <tt>existingImports</tt> notification to filter out available
+          suggestions. If there were changes to existing imports in the library,
+          the corresponding <tt>existingImports</tt> notification will be sent
+          before the completion notification.
+        </p>
+      </field>
       <field name="includedSuggestionSets" optional="true">
         <list>
           <ref>IncludedSuggestionSet</ref>
@@ -1658,6 +1669,27 @@
       </field>
     </params>
   </notification>
+  <notification event="existingImports">
+    <p>
+      Reports existing imports in a library. This notification may be sent
+      multiple times for a library. When a notification is processed, clients
+      should replace any previous information for the library.
+    </p>
+    <params>
+      <field name="file">
+        <ref>FilePath</ref>
+        <p>
+          The defining file of the library.
+        </p>
+      </field>
+      <field name="imports">
+        <ref>ExistingImports</ref>
+        <p>
+          The existing imports in the library.
+        </p>
+      </field>
+    </params>
+  </notification>
 </domain>
 <domain name="search">
   <p>
@@ -3669,6 +3701,86 @@
       </field>
     </object>
   </type>
+  <type name="ExistingImport">
+    <p>
+      Information about an existing import, with elements that it provides.
+    </p>
+    <object>
+      <field name="uri">
+        <ref>int</ref>
+        <p>
+          The URI of the imported library.
+          It is an index in the <tt>strings</tt> field, in the enclosing
+          <tt>ExistingImports</tt> and its <tt>ImportedElementSet</tt> object.
+        </p>
+      </field>
+      <field name="elements">
+        <list>
+          <ref>int</ref>
+        </list>
+        <p>
+          The list of indexes of elements, in the enclosing
+          <tt>ExistingImports</tt> object.
+        </p>
+      </field>
+    </object>
+  </type>
+  <type name="ExistingImports">
+    <p>
+      Information about all existing imports in a library.
+    </p>
+    <object>
+      <field name="elements">
+        <ref>ImportedElementSet</ref>
+        <p>
+          The set of all unique imported elements for all imports.
+        </p>
+      </field>
+      <field name="imports">
+        <list>
+          <ref>ExistingImport</ref>
+        </list>
+        <p>
+          The list of imports in the library.
+        </p>
+      </field>
+    </object>
+  </type>
+  <type name="ImportedElementSet">
+    <p>
+      The set of top-level elements encoded as pairs of the defining library
+      URI and the name, and stored in the parallel lists <tt>elementUris</tt>
+      and <tt>elementNames</tt>.
+    </p>
+    <object>
+      <field name="strings">
+        <list>
+          <ref>String</ref>
+        </list>
+        <p>
+          The list of unique strings in this object.
+        </p>
+      </field>
+      <field name="uris">
+        <list>
+          <ref>int</ref>
+        </list>
+        <p>
+          The library URI part of the element.
+          It is an index in the <tt>strings</tt> field.
+        </p>
+      </field>
+      <field name="names">
+        <list>
+          <ref>int</ref>
+        </list>
+        <p>
+          The name part of a the element.
+          It is an index in the <tt>strings</tt> field.
+        </p>
+      </field>
+    </object>
+  </type>
   <type name="IncludedSuggestionSet">
     <p>
       A reference to an <tt>AvailableSuggestionSet</tt> noting
@@ -3737,11 +3849,15 @@
       <value>
         <code>AVAILABLE_SUGGESTION_SETS</code>
         <p>
-          The client will receive notifications once subscribed with completion suggestion sets from
-          the libraries of interest. The client should keep an up-to-date record of these in
+          The client will receive <tt>availableSuggestions</tt> notifications
+          once subscribed with completion suggestion sets from the libraries of
+          interest. The client should keep an up-to-date record of these in
           memory so that it will be able to union these candidates with other
           completion suggestions when applicable at completion time.
         </p>
+        <p>
+          The client will also receive <tt>existingImports</tt> notifications.
+        </p>
       </value>
     </enum>
   </type>
@@ -4212,10 +4328,10 @@
       <field name="containingLibraryName" optional="true">
         <ref>String</ref>
         <p>
-          The name of the library in which the referenced element is
-          declared. This data is omitted if there is no referenced
-          element, or if the element is declared inside an HTML
-          file.
+          The URI of the containing library, examples here include
+          "dart:core", "package:.." and file uris represented by the
+          path on disk, "/..". The data is omitted if the element is
+          declared inside an HTML file.
         </p>
       </field>
       <field name="containingClassDescription" optional="true">
diff --git a/pkg/analysis_server_client/lib/handler/notification_handler.dart b/pkg/analysis_server_client/lib/handler/notification_handler.dart
index 97ec840..b85aa31 100644
--- a/pkg/analysis_server_client/lib/handler/notification_handler.dart
+++ b/pkg/analysis_server_client/lib/handler/notification_handler.dart
@@ -72,6 +72,11 @@
             new CompletionAvailableSuggestionsParams.fromJson(
                 decoder, 'params', params));
         break;
+      case COMPLETION_NOTIFICATION_EXISTING_IMPORTS:
+        onCompletionExistingImports(
+            new CompletionExistingImportsParams.fromJson(
+                decoder, 'params', params));
+        break;
       case COMPLETION_NOTIFICATION_RESULTS:
         onCompletionResults(
             new CompletionResultsParams.fromJson(decoder, 'params', params));
@@ -221,6 +226,11 @@
   void onCompletionAvailableSuggestions(
       CompletionAvailableSuggestionsParams params) {}
 
+  /// Reports existing imports in a library. This notification may be sent
+  /// multiple times for a library. When a notification is processed, clients
+  /// should replace any previous information for the library.
+  void onCompletionExistingImports(CompletionExistingImportsParams params) {}
+
   /// Reports the completion suggestions that should be presented
   /// to the user. The set of suggestions included in the
   /// notification is always a complete list that supersedes any
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index af958c9..b944f0f 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.26.1';
+const String PROTOCOL_VERSION = '1.27.0';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -116,6 +116,10 @@
     'changedLibraries';
 const String COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS_REMOVED_LIBRARIES =
     'removedLibraries';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS =
+    'completion.existingImports';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_FILE = 'file';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_IMPORTS = 'imports';
 const String COMPLETION_NOTIFICATION_RESULTS = 'completion.results';
 const String COMPLETION_NOTIFICATION_RESULTS_ID = 'id';
 const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_ELEMENT_KINDS =
@@ -126,6 +130,7 @@
 const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_SUGGESTION_SETS =
     'includedSuggestionSets';
 const String COMPLETION_NOTIFICATION_RESULTS_IS_LAST = 'isLast';
+const String COMPLETION_NOTIFICATION_RESULTS_LIBRARY_FILE = 'libraryFile';
 const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_LENGTH =
     'replacementLength';
 const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_OFFSET =
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
index 5d1b076..44ef533e 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -5803,6 +5803,116 @@
 }
 
 /**
+ * completion.existingImports params
+ *
+ * {
+ *   "file": FilePath
+ *   "imports": ExistingImports
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionExistingImportsParams implements HasToJson {
+  String _file;
+
+  ExistingImports _imports;
+
+  /**
+   * The defining file of the library.
+   */
+  String get file => _file;
+
+  /**
+   * The defining file of the library.
+   */
+  void set file(String value) {
+    assert(value != null);
+    this._file = value;
+  }
+
+  /**
+   * The existing imports in the library.
+   */
+  ExistingImports get imports => _imports;
+
+  /**
+   * The existing imports in the library.
+   */
+  void set imports(ExistingImports value) {
+    assert(value != null);
+    this._imports = value;
+  }
+
+  CompletionExistingImportsParams(String file, ExistingImports imports) {
+    this.file = file;
+    this.imports = imports;
+  }
+
+  factory CompletionExistingImportsParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String file;
+      if (json.containsKey("file")) {
+        file = jsonDecoder.decodeString(jsonPath + ".file", json["file"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "file");
+      }
+      ExistingImports imports;
+      if (json.containsKey("imports")) {
+        imports = new ExistingImports.fromJson(
+            jsonDecoder, jsonPath + ".imports", json["imports"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "imports");
+      }
+      return new CompletionExistingImportsParams(file, imports);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.existingImports params", json);
+    }
+  }
+
+  factory CompletionExistingImportsParams.fromNotification(
+      Notification notification) {
+    return new CompletionExistingImportsParams.fromJson(
+        new ResponseDecoder(null), "params", notification.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["file"] = file;
+    result["imports"] = imports.toJson();
+    return result;
+  }
+
+  Notification toNotification() {
+    return new Notification("completion.existingImports", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionExistingImportsParams) {
+      return file == other.file && imports == other.imports;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, file.hashCode);
+    hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * completion.getSuggestionDetails params
  *
  * {
@@ -6593,6 +6703,7 @@
  *   "replacementLength": int
  *   "results": List<CompletionSuggestion>
  *   "isLast": bool
+ *   "libraryFile": optional FilePath
  *   "includedSuggestionSets": optional List<IncludedSuggestionSet>
  *   "includedElementKinds": optional List<ElementKind>
  *   "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
@@ -6611,6 +6722,8 @@
 
   bool _isLast;
 
+  String _libraryFile;
+
   List<IncludedSuggestionSet> _includedSuggestionSets;
 
   List<ElementKind> _includedElementKinds;
@@ -6703,6 +6816,26 @@
   }
 
   /**
+   * The library file that contains the file where completion was requested.
+   * The client might use it for example together with the existingImports
+   * notification to filter out available suggestions. If there were changes to
+   * existing imports in the library, the corresponding existingImports
+   * notification will be sent before the completion notification.
+   */
+  String get libraryFile => _libraryFile;
+
+  /**
+   * The library file that contains the file where completion was requested.
+   * The client might use it for example together with the existingImports
+   * notification to filter out available suggestions. If there were changes to
+   * existing imports in the library, the corresponding existingImports
+   * notification will be sent before the completion notification.
+   */
+  void set libraryFile(String value) {
+    this._libraryFile = value;
+  }
+
+  /**
    * References to AvailableSuggestionSet objects previously sent to the
    * client. The client can include applicable names from the referenced
    * library in code completion suggestions.
@@ -6765,7 +6898,8 @@
 
   CompletionResultsParams(String id, int replacementOffset,
       int replacementLength, List<CompletionSuggestion> results, bool isLast,
-      {List<IncludedSuggestionSet> includedSuggestionSets,
+      {String libraryFile,
+      List<IncludedSuggestionSet> includedSuggestionSets,
       List<ElementKind> includedElementKinds,
       List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags}) {
     this.id = id;
@@ -6773,6 +6907,7 @@
     this.replacementLength = replacementLength;
     this.results = results;
     this.isLast = isLast;
+    this.libraryFile = libraryFile;
     this.includedSuggestionSets = includedSuggestionSets;
     this.includedElementKinds = includedElementKinds;
     this.includedSuggestionRelevanceTags = includedSuggestionRelevanceTags;
@@ -6820,6 +6955,11 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "isLast");
       }
+      String libraryFile;
+      if (json.containsKey("libraryFile")) {
+        libraryFile = jsonDecoder.decodeString(
+            jsonPath + ".libraryFile", json["libraryFile"]);
+      }
       List<IncludedSuggestionSet> includedSuggestionSets;
       if (json.containsKey("includedSuggestionSets")) {
         includedSuggestionSets = jsonDecoder.decodeList(
@@ -6848,6 +6988,7 @@
       }
       return new CompletionResultsParams(
           id, replacementOffset, replacementLength, results, isLast,
+          libraryFile: libraryFile,
           includedSuggestionSets: includedSuggestionSets,
           includedElementKinds: includedElementKinds,
           includedSuggestionRelevanceTags: includedSuggestionRelevanceTags);
@@ -6870,6 +7011,9 @@
     result["results"] =
         results.map((CompletionSuggestion value) => value.toJson()).toList();
     result["isLast"] = isLast;
+    if (libraryFile != null) {
+      result["libraryFile"] = libraryFile;
+    }
     if (includedSuggestionSets != null) {
       result["includedSuggestionSets"] = includedSuggestionSets
           .map((IncludedSuggestionSet value) => value.toJson())
@@ -6905,6 +7049,7 @@
           listEqual(results, other.results,
               (CompletionSuggestion a, CompletionSuggestion b) => a == b) &&
           isLast == other.isLast &&
+          libraryFile == other.libraryFile &&
           listEqual(includedSuggestionSets, other.includedSuggestionSets,
               (IncludedSuggestionSet a, IncludedSuggestionSet b) => a == b) &&
           listEqual(includedElementKinds, other.includedElementKinds,
@@ -6927,6 +7072,7 @@
     hash = JenkinsSmiHash.combine(hash, replacementLength.hashCode);
     hash = JenkinsSmiHash.combine(hash, results.hashCode);
     hash = JenkinsSmiHash.combine(hash, isLast.hashCode);
+    hash = JenkinsSmiHash.combine(hash, libraryFile.hashCode);
     hash = JenkinsSmiHash.combine(hash, includedSuggestionSets.hashCode);
     hash = JenkinsSmiHash.combine(hash, includedElementKinds.hashCode);
     hash =
@@ -6946,11 +7092,13 @@
  */
 class CompletionService implements Enum {
   /**
-   * The client will receive notifications once subscribed with completion
-   * suggestion sets from the libraries of interest. The client should keep an
-   * up-to-date record of these in memory so that it will be able to union
-   * these candidates with other completion suggestions when applicable at
-   * completion time.
+   * The client will receive availableSuggestions notifications once subscribed
+   * with completion suggestion sets from the libraries of interest. The client
+   * should keep an up-to-date record of these in memory so that it will be
+   * able to union these candidates with other completion suggestions when
+   * applicable at completion time.
+   *
+   * The client will also receive existingImports notifications.
    */
   static const CompletionService AVAILABLE_SUGGESTION_SETS =
       const CompletionService._("AVAILABLE_SUGGESTION_SETS");
@@ -13011,6 +13159,214 @@
 }
 
 /**
+ * ExistingImport
+ *
+ * {
+ *   "uri": int
+ *   "elements": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImport implements HasToJson {
+  int _uri;
+
+  List<int> _elements;
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in
+   * the enclosing ExistingImports and its ImportedElementSet object.
+   */
+  int get uri => _uri;
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in
+   * the enclosing ExistingImports and its ImportedElementSet object.
+   */
+  void set uri(int value) {
+    assert(value != null);
+    this._uri = value;
+  }
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  List<int> get elements => _elements;
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  void set elements(List<int> value) {
+    assert(value != null);
+    this._elements = value;
+  }
+
+  ExistingImport(int uri, List<int> elements) {
+    this.uri = uri;
+    this.elements = elements;
+  }
+
+  factory ExistingImport.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      int uri;
+      if (json.containsKey("uri")) {
+        uri = jsonDecoder.decodeInt(jsonPath + ".uri", json["uri"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "uri");
+      }
+      List<int> elements;
+      if (json.containsKey("elements")) {
+        elements = jsonDecoder.decodeList(
+            jsonPath + ".elements", json["elements"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "elements");
+      }
+      return new ExistingImport(uri, elements);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ExistingImport", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["uri"] = uri;
+    result["elements"] = elements;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ExistingImport) {
+      return uri == other.uri &&
+          listEqual(elements, other.elements, (int a, int b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+    hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * ExistingImports
+ *
+ * {
+ *   "elements": ImportedElementSet
+ *   "imports": List<ExistingImport>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImports implements HasToJson {
+  ImportedElementSet _elements;
+
+  List<ExistingImport> _imports;
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  ImportedElementSet get elements => _elements;
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  void set elements(ImportedElementSet value) {
+    assert(value != null);
+    this._elements = value;
+  }
+
+  /**
+   * The list of imports in the library.
+   */
+  List<ExistingImport> get imports => _imports;
+
+  /**
+   * The list of imports in the library.
+   */
+  void set imports(List<ExistingImport> value) {
+    assert(value != null);
+    this._imports = value;
+  }
+
+  ExistingImports(ImportedElementSet elements, List<ExistingImport> imports) {
+    this.elements = elements;
+    this.imports = imports;
+  }
+
+  factory ExistingImports.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      ImportedElementSet elements;
+      if (json.containsKey("elements")) {
+        elements = new ImportedElementSet.fromJson(
+            jsonDecoder, jsonPath + ".elements", json["elements"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "elements");
+      }
+      List<ExistingImport> imports;
+      if (json.containsKey("imports")) {
+        imports = jsonDecoder.decodeList(
+            jsonPath + ".imports",
+            json["imports"],
+            (String jsonPath, Object json) =>
+                new ExistingImport.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "imports");
+      }
+      return new ExistingImports(elements, imports);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ExistingImports", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["elements"] = elements.toJson();
+    result["imports"] =
+        imports.map((ExistingImport value) => value.toJson()).toList();
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ExistingImports) {
+      return elements == other.elements &&
+          listEqual(imports, other.imports,
+              (ExistingImport a, ExistingImport b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+    hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * extractLocalVariable feedback
  *
  * {
@@ -15586,16 +15942,16 @@
   }
 
   /**
-   * The name of the library in which the referenced element is declared. This
-   * data is omitted if there is no referenced element, or if the element is
-   * declared inside an HTML file.
+   * The URI of the containing library, examples here include "dart:core",
+   * "package:.." and file uris represented by the path on disk, "/..". The
+   * data is omitted if the element is declared inside an HTML file.
    */
   String get containingLibraryName => _containingLibraryName;
 
   /**
-   * The name of the library in which the referenced element is declared. This
-   * data is omitted if there is no referenced element, or if the element is
-   * declared inside an HTML file.
+   * The URI of the containing library, examples here include "dart:core",
+   * "package:.." and file uris represented by the path on disk, "/..". The
+   * data is omitted if the element is declared inside an HTML file.
    */
   void set containingLibraryName(String value) {
     this._containingLibraryName = value;
@@ -16109,6 +16465,135 @@
 }
 
 /**
+ * ImportedElementSet
+ *
+ * {
+ *   "strings": List<String>
+ *   "uris": List<int>
+ *   "names": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ImportedElementSet implements HasToJson {
+  List<String> _strings;
+
+  List<int> _uris;
+
+  List<int> _names;
+
+  /**
+   * The list of unique strings in this object.
+   */
+  List<String> get strings => _strings;
+
+  /**
+   * The list of unique strings in this object.
+   */
+  void set strings(List<String> value) {
+    assert(value != null);
+    this._strings = value;
+  }
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  List<int> get uris => _uris;
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  void set uris(List<int> value) {
+    assert(value != null);
+    this._uris = value;
+  }
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  List<int> get names => _names;
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  void set names(List<int> value) {
+    assert(value != null);
+    this._names = value;
+  }
+
+  ImportedElementSet(List<String> strings, List<int> uris, List<int> names) {
+    this.strings = strings;
+    this.uris = uris;
+    this.names = names;
+  }
+
+  factory ImportedElementSet.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      List<String> strings;
+      if (json.containsKey("strings")) {
+        strings = jsonDecoder.decodeList(
+            jsonPath + ".strings", json["strings"], jsonDecoder.decodeString);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "strings");
+      }
+      List<int> uris;
+      if (json.containsKey("uris")) {
+        uris = jsonDecoder.decodeList(
+            jsonPath + ".uris", json["uris"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "uris");
+      }
+      List<int> names;
+      if (json.containsKey("names")) {
+        names = jsonDecoder.decodeList(
+            jsonPath + ".names", json["names"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "names");
+      }
+      return new ImportedElementSet(strings, uris, names);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ImportedElementSet", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["strings"] = strings;
+    result["uris"] = uris;
+    result["names"] = names;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ImportedElementSet) {
+      return listEqual(
+              strings, other.strings, (String a, String b) => a == b) &&
+          listEqual(uris, other.uris, (int a, int b) => a == b) &&
+          listEqual(names, other.names, (int a, int b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, strings.hashCode);
+    hash = JenkinsSmiHash.combine(hash, uris.hashCode);
+    hash = JenkinsSmiHash.combine(hash, names.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * ImportedElements
  *
  * {
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index e305a68..37ac0ad 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -4,6 +4,15 @@
   `featureSet` parameter.
 * Refined the return type of the getter `TypeParameter.declaredElement`.  It is
   always guaranteed to return a `TypeParameterElement`.
+* Deprecated the `abstract` setter in `ClassElementImpl`, `EnumElementImpl`,
+  `MethodElementImpl`, and `PropertyAccessorElementImpl`.  `isAbstract` should
+  be used instead.
+* Changed the way function types are displayed from e.g. `(int) -> void` to
+  `void Function(int)`. This is more consistent with the syntax of Dart, and it
+  will avoid ambiguities when nullability is added to the type system. This
+  impacts to value returned by `FunctionType.displayName` and
+  `FunctionType.toString` and `ExecutableElement.toString`. Client code might be
+  broken if it depends on the content of the returned value.
 
 ## 0.36.3
 * Deprecated `AstFactory.compilationUnit`.  In a future analyzer release, this
diff --git a/pkg/analyzer/doc/tutorial/analysis.md b/pkg/analyzer/doc/tutorial/analysis.md
index a44d6a5..e71d245 100644
--- a/pkg/analyzer/doc/tutorial/analysis.md
+++ b/pkg/analyzer/doc/tutorial/analysis.md
@@ -24,9 +24,14 @@
 main() {
   List<String> includedPaths = <String>[/* ... */];
   AnalysisContextCollection collection =
-      new AnalysisContextCollection(includedPaths);
+      new AnalysisContextCollection(includedPaths: includedPaths);
   analyzeSomeFiles(collection, includedPaths);
 }
+
+analyzeSomeFiles(
+    AnalysisContextCollection collection, List<String> includedPaths) {
+  // See below.
+}
 ```
 
 The collection will create one or more analysis contexts that can be used to
@@ -52,6 +57,10 @@
     analyzeSingleFile(context, path);
   }
 }
+
+analyzeSingleFile(AnalysisContext context, String path) {
+  // See below.
+}
 ```
 
 ## Analyzing Multiple Files
@@ -68,6 +77,10 @@
     }
   }
 }
+
+analyzeSingleFile(AnalysisContext context, String path) {
+  // See below.
+}
 ```
 
 The files returned this way will include _all_ of the files in all of the
diff --git a/pkg/analyzer/doc/tutorial/ast.md b/pkg/analyzer/doc/tutorial/ast.md
index fd41d31..57af577 100644
--- a/pkg/analyzer/doc/tutorial/ast.md
+++ b/pkg/analyzer/doc/tutorial/ast.md
@@ -50,21 +50,12 @@
 to get the compilation unit for a file at a known `path`, then you can ask the
 analysis session for an AST.
 
-If you need an unresolved AST, then you can use either a synchronous or
-asynchronous method to access the AST:
+If you need an unresolved AST, then you can use the following method to access
+the AST:
 
 ```dart
-main() async {
-  ParseResult result = await session.getParsedAst(path);
-  CompilationUnit unit = result.unit;
-}
-```
-
-or
-
-```dart
-main() {
-  ParseResult result = session.getParsedAstSync(path);
+processFile(AnalysisSession session, String path) {
+  ParsedUnitResult result = session.getParsedUnit(path);
   CompilationUnit unit = result.unit;
 }
 ```
@@ -73,8 +64,8 @@
 method to access it:
 
 ```dart
-main() async {
-  ResolveResult result = await session.getResolvedAst(path);
+processFile(AnalysisSession session, String path) async {
+  ResolvedUnitResult result = await session.getResolvedUnit(path);
   CompilationUnit unit = result.unit;
 }
 ```
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index 6f31a7b..542661b 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -11,7 +11,6 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
 
@@ -122,11 +121,6 @@
   /// complete with [SourceKind.UNKNOWN].
   Future<SourceKind> getSourceKind(String path);
 
-  /// Return a future that will complete with a list of the top-level
-  /// declarations with the given [name] in all known libraries.
-  Future<List<TopLevelDeclarationInSource>> getTopLevelDeclarations(
-      String name);
-
   /// Return a future that will complete with information about the results of
   /// building the element model for the file with the given absolute,
   /// normalized[path].
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 008e727..a34b97c 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -500,6 +500,8 @@
 
   R visitExtendsClause(ExtendsClause node);
 
+  R visitExtensionDeclaration(ExtensionDeclaration node);
+
   R visitFieldDeclaration(FieldDeclaration node);
 
   R visitFieldFormalParameter(FieldFormalParameter node);
@@ -2108,6 +2110,37 @@
   void set superclass(TypeName name);
 }
 
+/// The declaration of an extension of a type.
+///
+///    extension ::=
+///        'extension' [SimpleIdentifier] [TypeParameterList]?
+///        'on' [TypeAnnotation] '{' [ClassMember]* '}'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ExtensionDeclaration implements NamedCompilationUnitMember {
+  /// Return the type that is being extended.
+  TypeAnnotation get extendedType;
+
+  /// Return the token representing the 'extension' keyword.
+  Token get extensionKeyword;
+
+  /// Return the left curly bracket.
+  Token get leftBracket;
+
+  /// Return the members being added to the extended class.
+  NodeList<ClassMember> get members;
+
+  /// Return the token representing the 'on' keyword.
+  Token get onKeyword;
+
+  /// Return the right curly bracket.
+  Token get rightBracket;
+
+  /// Return the type parameters for the extension, or `null` if the extension
+  /// does not have any type parameters.
+  TypeParameterList get typeParameters;
+}
+
 /// The declaration of one or more fields of the same type.
 ///
 ///    fieldDeclaration ::=
@@ -2777,7 +2810,8 @@
 /// A function-typed formal parameter.
 ///
 ///    functionSignature ::=
-///        [TypeAnnotation]? [SimpleIdentifier] [TypeParameterList]? [FormalParameterList]
+///        [TypeAnnotation]? [SimpleIdentifier] [TypeParameterList]?
+///        [FormalParameterList] '?'?
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class FunctionTypedFormalParameter implements NormalFormalParameter {
@@ -2788,6 +2822,11 @@
   /// [parameters].
   void set parameters(FormalParameterList parameters);
 
+  /// Return the question mark indicating that the function type is nullable, or
+  /// `null` if there is no question mark. Having a nullable function type means
+  /// that the parameter can be null.
+  Token get question;
+
   /// Return the return type of the function, or `null` if the function does not
   /// have a return type.
   TypeAnnotation get returnType;
diff --git a/pkg/analyzer/lib/dart/ast/ast_factory.dart b/pkg/analyzer/lib/dart/ast/ast_factory.dart
index 815ad03..2796e1a 100644
--- a/pkg/analyzer/lib/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/dart/ast/ast_factory.dart
@@ -339,6 +339,20 @@
   /// Returns a newly created extends clause.
   ExtendsClause extendsClause(Token extendsKeyword, TypeName superclass);
 
+  /// Return a newly created extention declaration. The list of [typeParameters]
+  /// can be `null` if there are no type parameters.
+  ExtensionDeclaration extensionDeclaration(
+      {Comment comment,
+      List<Annotation> metadata,
+      Token extensionKeyword,
+      @required SimpleIdentifier name,
+      TypeParameterList typeParameters,
+      Token onKeyword,
+      @required TypeAnnotation extendedType,
+      Token leftBracket,
+      List<ClassMember> members,
+      Token rightBracket});
+
   /// Returns a newly created field declaration. Either or both of the [comment]
   /// and [metadata] can be `null` if the declaration does not have the
   /// corresponding attribute. The [staticKeyword] can be `null` if the field is
@@ -535,7 +549,8 @@
       TypeAnnotation returnType,
       @required SimpleIdentifier identifier,
       TypeParameterList typeParameters,
-      @required FormalParameterList parameters});
+      @required FormalParameterList parameters,
+      Token question});
 
   /// Initialize a newly created generic function type.
   GenericFunctionType genericFunctionType(
diff --git a/pkg/analyzer/lib/dart/ast/visitor.dart b/pkg/analyzer/lib/dart/ast/visitor.dart
index 6646631..68f4621 100644
--- a/pkg/analyzer/lib/dart/ast/visitor.dart
+++ b/pkg/analyzer/lib/dart/ast/visitor.dart
@@ -277,6 +277,10 @@
   R visitExtendsClause(ExtendsClause node) => visitNode(node);
 
   @override
+  R visitExtensionDeclaration(ExtensionDeclaration node) =>
+      visitNamedCompilationUnitMember(node);
+
+  @override
   R visitFieldDeclaration(FieldDeclaration node) => visitClassMember(node);
 
   @override
@@ -839,6 +843,12 @@
   }
 
   @override
+  R visitExtensionDeclaration(ExtensionDeclaration node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
   R visitFieldDeclaration(FieldDeclaration node) {
     node.visitChildren(this);
     return null;
@@ -1447,6 +1457,9 @@
   R visitExtendsClause(ExtendsClause node) => null;
 
   @override
+  R visitExtensionDeclaration(ExtensionDeclaration node) => null;
+
+  @override
   R visitFieldDeclaration(FieldDeclaration node) => null;
 
   @override
@@ -1822,6 +1835,9 @@
   R visitExtendsClause(ExtendsClause node) => _throw(node);
 
   @override
+  R visitExtensionDeclaration(ExtensionDeclaration node) => _throw(node);
+
+  @override
   R visitFieldDeclaration(FieldDeclaration node) => _throw(node);
 
   @override
@@ -2406,6 +2422,14 @@
   }
 
   @override
+  T visitExtensionDeclaration(ExtensionDeclaration node) {
+    stopwatch.start();
+    T result = _baseVisitor.visitExtensionDeclaration(node);
+    stopwatch.stop();
+    return result;
+  }
+
+  @override
   T visitFieldDeclaration(FieldDeclaration node) {
     stopwatch.start();
     T result = _baseVisitor.visitFieldDeclaration(node);
@@ -3181,6 +3205,9 @@
   R visitExtendsClause(ExtendsClause node) => visitNode(node);
 
   @override
+  R visitExtensionDeclaration(ExtensionDeclaration node) => visitNode(node);
+
+  @override
   R visitFieldDeclaration(FieldDeclaration node) => visitNode(node);
 
   @override
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index ce67ab7..7c2812a 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -29,6 +29,9 @@
 abstract class DartType {
   /// Return the name of this type as it should appear when presented to users
   /// in contexts such as error messages.
+  ///
+  /// Clients should not depend on the content of the returned value as it will
+  /// be changed if doing so would improve the UX.
   String get displayName;
 
   /// Return the element representing the declaration of this type, or `null` if
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 8902935..ed09816 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -290,6 +290,7 @@
   CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR,
   CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS,
   CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER,
+  CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
   CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR,
   CompileTimeErrorCode.YIELD_IN_NON_GENERATOR,
   HintCode.CAN_BE_NULL_AFTER_NULL_AWARE,
@@ -423,6 +424,7 @@
   ParserErrorCode.EMPTY_ENUM_BODY,
   ParserErrorCode.ENUM_IN_CLASS,
   ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND,
+  ParserErrorCode.EXPECTED_BODY,
   ParserErrorCode.EXPECTED_CASE_OR_DEFAULT,
   ParserErrorCode.EXPECTED_CLASS_MEMBER,
   ParserErrorCode.EXPECTED_ELSE_OR_COMMA,
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index e179115..414ab6c 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 import 'dart:collection';
 import 'dart:convert';
+import 'dart:typed_data';
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/source_io.dart';
@@ -19,7 +20,7 @@
 class MemoryResourceProvider implements ResourceProvider {
   final Map<String, _MemoryResource> _pathToResource =
       new HashMap<String, _MemoryResource>();
-  final Map<String, List<int>> _pathToBytes = new HashMap<String, List<int>>();
+  final Map<String, Uint8List> _pathToBytes = new HashMap<String, Uint8List>();
   final Map<String, int> _pathToTimestamp = new HashMap<String, int>();
   final Map<String, List<StreamController<WatchEvent>>> _pathToWatchers =
       new HashMap<String, List<StreamController<WatchEvent>>>();
@@ -128,7 +129,7 @@
 
   void modifyFile(String path, String content) {
     _checkFileAtPath(path);
-    _pathToBytes[path] = utf8.encode(content);
+    _pathToBytes[path] = utf8.encode(content) as Uint8List;
     _pathToTimestamp[path] = nextStamp++;
     _notifyWatchers(path, ChangeType.MODIFY);
   }
@@ -150,7 +151,7 @@
   File newFile(String path, String content, [int stamp]) {
     _ensureAbsoluteAndNormalized(path);
     _MemoryFile file = _newFile(path);
-    _pathToBytes[path] = utf8.encode(content);
+    _pathToBytes[path] = utf8.encode(content) as Uint8List;
     _pathToTimestamp[path] = stamp ?? nextStamp++;
     _notifyWatchers(path, ChangeType.ADD);
     return file;
@@ -159,7 +160,7 @@
   File newFileWithBytes(String path, List<int> bytes, [int stamp]) {
     _ensureAbsoluteAndNormalized(path);
     _MemoryFile file = _newFile(path);
-    _pathToBytes[path] = bytes;
+    _pathToBytes[path] = Uint8List.fromList(bytes);
     _pathToTimestamp[path] = stamp ?? nextStamp++;
     _notifyWatchers(path, ChangeType.ADD);
     return file;
@@ -196,7 +197,7 @@
     newFolder(pathContext.dirname(path));
     _MemoryFile file = new _MemoryFile(this, path);
     _pathToResource[path] = file;
-    _pathToBytes[path] = utf8.encode(content);
+    _pathToBytes[path] = utf8.encode(content) as Uint8List;
     _pathToTimestamp[path] = stamp ?? nextStamp++;
     _notifyWatchers(path, ChangeType.MODIFY);
     return file;
@@ -300,7 +301,7 @@
   void _setFileContent(_MemoryFile file, List<int> bytes) {
     String path = file.path;
     _pathToResource[path] = file;
-    _pathToBytes[path] = bytes;
+    _pathToBytes[path] = Uint8List.fromList(bytes);
     _pathToTimestamp[path] = nextStamp++;
     _notifyWatchers(path, ChangeType.MODIFY);
   }
@@ -357,7 +358,7 @@
   }
 
   @override
-  List<int> readAsBytesSync() {
+  Uint8List readAsBytesSync() {
     throw new FileSystemException(path, 'File could not be read');
   }
 
@@ -436,8 +437,8 @@
   }
 
   @override
-  List<int> readAsBytesSync() {
-    List<int> content = _provider._pathToBytes[path];
+  Uint8List readAsBytesSync() {
+    Uint8List content = _provider._pathToBytes[path];
     if (content == null) {
       throw new FileSystemException(path, 'File "$path" does not exist.');
     }
@@ -446,7 +447,7 @@
 
   @override
   String readAsStringSync() {
-    List<int> content = _provider._pathToBytes[path];
+    Uint8List content = _provider._pathToBytes[path];
     if (content == null) {
       throw new FileSystemException(path, 'File "$path" does not exist.');
     }
diff --git a/pkg/analyzer/lib/file_system/overlay_file_system.dart b/pkg/analyzer/lib/file_system/overlay_file_system.dart
index 76879be..3628b8f 100644
--- a/pkg/analyzer/lib/file_system/overlay_file_system.dart
+++ b/pkg/analyzer/lib/file_system/overlay_file_system.dart
@@ -3,7 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:convert';
 import 'dart:core';
+import 'dart:typed_data';
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/source_io.dart';
@@ -70,6 +72,11 @@
 
   @override
   Resource getResource(String path) {
+    if (hasOverlay(path)) {
+      return new _OverlayResource._from(this, baseProvider.getFile(path));
+    } else if (_hasOverlayIn(path)) {
+      return new _OverlayResource._from(this, baseProvider.getFolder(path));
+    }
     return new _OverlayResource._from(this, baseProvider.getResource(path));
   }
 
@@ -140,14 +147,18 @@
   }
 
   /**
-   * Return the paths of all of the overlaid files that are immediate children
-   * of the given [folder].
+   * Return `true` if there is an overlay associated with at least one file
+   * contained inside the folder with the given [folderPath].
    */
-  Iterable<String> _overlaysInFolder(Folder folder) {
-    String folderPath = folder.path;
-    return _overlayContent.keys
-        .where((path) => pathContext.dirname(path) == folderPath);
-  }
+  bool _hasOverlayIn(String folderPath) => _overlayContent.keys
+      .any((filePath) => pathContext.isWithin(folderPath, filePath));
+
+  /**
+   * Return the paths of all of the overlaid files that are children of the
+   * given [folder], either directly or indirectly.
+   */
+  Iterable<String> _overlaysInFolder(String folderPath) => _overlayContent.keys
+      .where((filePath) => pathContext.isWithin(folderPath, filePath));
 }
 
 /**
@@ -221,10 +232,10 @@
   }
 
   @override
-  List<int> readAsBytesSync() {
+  Uint8List readAsBytesSync() {
     String content = _provider._getOverlayContent(path);
     if (content != null) {
-      return content.codeUnits;
+      return utf8.encode(content) as Uint8List;
     }
     return _file.readAsBytesSync();
   }
@@ -281,7 +292,7 @@
   Stream<WatchEvent> get changes => _folder.changes;
 
   @override
-  bool get exists => _resource.exists;
+  bool get exists => _provider._hasOverlayIn(path) || _resource.exists;
 
   /**
    * Return the folder from the base resource provider that corresponds to this
@@ -330,12 +341,24 @@
 
   @override
   List<Resource> getChildren() {
-    List<Resource> children = _folder
-        .getChildren()
-        .map((child) => new _OverlayResource._from(_provider, child))
-        .toList();
-    for (String overlayPath in _provider._overlaysInFolder(this)) {
-      children.add(_provider.getFile(overlayPath));
+    List<Resource> children;
+    try {
+      children = _folder
+          .getChildren()
+          .map((child) => new _OverlayResource._from(_provider, child))
+          .toList();
+    } on FileSystemException {
+      children = [];
+    }
+    for (String overlayPath in _provider._overlaysInFolder(path)) {
+      pathos.Context context = _provider.pathContext;
+      if (context.dirname(overlayPath) == path) {
+        children.add(_provider.getFile(overlayPath));
+      } else {
+        String relativePath = context.relative(overlayPath, from: path);
+        String folderName = context.split(relativePath)[0];
+        children.add(_provider.getFolder(context.join(path, folderName)));
+      }
     }
     return children;
   }
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index eb28314..83a34de 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 import 'dart:io' as io;
+import 'dart:typed_data';
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/source_io.dart';
@@ -193,7 +194,7 @@
   }
 
   @override
-  List<int> readAsBytesSync() {
+  Uint8List readAsBytesSync() {
     _throwIfWindowsDeviceDriver();
     try {
       return _file.readAsBytesSync();
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index f92f743..94d0216 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -28,7 +28,6 @@
 import 'package:analyzer/src/dart/analysis/search.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/analysis/status.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show
@@ -105,7 +104,7 @@
   /**
    * Whether summary2 should be used to resynthesize elements.
    */
-  static final bool useSummary2 = false;
+  static bool useSummary2 = false;
 
   /**
    * The scheduler that schedules analysis work in this, and possibly other
@@ -217,11 +216,6 @@
   final _referencingNameTasks = <_FilesReferencingNameTask>[];
 
   /**
-   * The list of tasks to compute top-level declarations of a name.
-   */
-  final _topLevelNameDeclarationsTasks = <_TopLevelNameDeclarationsTask>[];
-
-  /**
    * The mapping from the files for which the index was requested using
    * [getIndex] to the [Completer]s to report the result.
    */
@@ -519,9 +513,6 @@
     if (_unitElementRequestedFiles.isNotEmpty) {
       return AnalysisDriverPriority.interactive;
     }
-    if (_topLevelNameDeclarationsTasks.isNotEmpty) {
-      return AnalysisDriverPriority.interactive;
-    }
     if (_priorityFiles.isNotEmpty) {
       for (String path in _priorityFiles) {
         if (_fileTracker.isFilePending(path)) {
@@ -971,19 +962,6 @@
   }
 
   /**
-   * Return a [Future] that completes with top-level declarations with the
-   * given [name] in all known libraries.
-   */
-  Future<List<TopLevelDeclarationInSource>> getTopLevelNameDeclarations(
-      String name) {
-    _discoverAvailableFiles();
-    var task = new _TopLevelNameDeclarationsTask(this, name);
-    _topLevelNameDeclarationsTasks.add(task);
-    _scheduler.notify(this);
-    return task.completer.future;
-  }
-
-  /**
    * Return a [Future] that completes with the [UnitElementResult] for the
    * file with the given [path], or with `null` if the file cannot be analyzed.
    */
@@ -1208,16 +1186,6 @@
       return;
     }
 
-    // Compute top-level declarations.
-    if (_topLevelNameDeclarationsTasks.isNotEmpty) {
-      _TopLevelNameDeclarationsTask task = _topLevelNameDeclarationsTasks.first;
-      bool isDone = task.perform();
-      if (isDone) {
-        _topLevelNameDeclarationsTasks.remove(task);
-      }
-      return;
-    }
-
     // Analyze a priority file.
     if (_priorityFiles.isNotEmpty) {
       for (String path in _priorityFiles) {
@@ -2546,66 +2514,3 @@
     return true;
   }
 }
-
-/**
- * Task that computes top-level declarations for a certain name in all
- * known libraries.
- */
-class _TopLevelNameDeclarationsTask {
-  final AnalysisDriver driver;
-  final String name;
-  final Completer<List<TopLevelDeclarationInSource>> completer =
-      new Completer<List<TopLevelDeclarationInSource>>();
-
-  final List<TopLevelDeclarationInSource> libraryDeclarations =
-      <TopLevelDeclarationInSource>[];
-  final Set<String> checkedFiles = new Set<String>();
-  final List<String> filesToCheck = <String>[];
-
-  _TopLevelNameDeclarationsTask(this.driver, this.name);
-
-  /**
-   * Perform a single piece of work, and either complete the [completer] and
-   * return `true` to indicate that the task is done, return `false` to indicate
-   * that the task should continue to be run.
-   */
-  bool perform() {
-    // Prepare files to check.
-    if (filesToCheck.isEmpty) {
-      filesToCheck.addAll(driver.addedFiles.difference(checkedFiles));
-      filesToCheck.addAll(driver.knownFiles.difference(checkedFiles));
-    }
-
-    // If no more files to check, complete and done.
-    if (filesToCheck.isEmpty) {
-      completer.complete(libraryDeclarations);
-      return true;
-    }
-
-    // Check the next file.
-    String path = filesToCheck.removeLast();
-    if (checkedFiles.add(path)) {
-      FileState file = driver._fsState.getFileForPath(path);
-      if (!file.isPart) {
-        bool isExported = false;
-
-        TopLevelDeclaration declaration;
-        for (FileState part in file.libraryFiles) {
-          declaration ??= part.topLevelDeclarations[name];
-        }
-
-        if (declaration == null) {
-          declaration = file.exportedTopLevelDeclarations[name];
-          isExported = true;
-        }
-        if (declaration != null) {
-          libraryDeclarations.add(new TopLevelDeclarationInSource(
-              file.source, declaration, isExported));
-        }
-      }
-    }
-
-    // We're not done yet.
-    return false;
-  }
-}
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 1df560f..a0e0eb6 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -16,7 +16,6 @@
 import 'package:analyzer/src/dart/analysis/library_graph.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/analysis/referenced_names.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -82,11 +81,6 @@
  * should be called.
  */
 class FileState {
-  /**
-   * The next value for [_exportDeclarationsId].
-   */
-  static int _exportDeclarationsNextId = 0;
-
   final FileSystemState _fsState;
 
   /**
@@ -140,10 +134,6 @@
   String _transitiveSignature;
   String _transitiveSignatureLinked;
 
-  Map<String, TopLevelDeclaration> _topLevelDeclarations;
-  Map<String, TopLevelDeclaration> _exportedTopLevelDeclarations;
-  int _exportDeclarationsId = 0;
-
   /**
    * The flag that shows whether the file has an error or warning that
    * might be fixed by a change to another file.
@@ -214,15 +204,6 @@
    */
   List<FileState> get exportedFiles => _exportedFiles;
 
-  /**
-   * Return [TopLevelDeclaration]s exported from the this library file. The
-   * keys to the map are names of declarations.
-   */
-  Map<String, TopLevelDeclaration> get exportedTopLevelDeclarations {
-    _exportDeclarationsNextId = 1;
-    return _computeExportedDeclarations().declarations;
-  }
-
   @override
   int get hashCode => uri.hashCode;
 
@@ -321,59 +302,6 @@
   FileStateTestView get test => new FileStateTestView(this);
 
   /**
-   * Return public top-level declarations declared in the file. The keys to the
-   * map are names of declarations.
-   */
-  Map<String, TopLevelDeclaration> get topLevelDeclarations {
-    if (_topLevelDeclarations == null) {
-      _topLevelDeclarations = <String, TopLevelDeclaration>{};
-
-      void addDeclaration(TopLevelDeclarationKind kind, String name) {
-        if (!name.startsWith('_')) {
-          _topLevelDeclarations[name] = new TopLevelDeclaration(kind, name);
-        }
-      }
-
-      // Add types.
-      for (UnlinkedClass type in unlinked.classes) {
-        addDeclaration(TopLevelDeclarationKind.type, type.name);
-      }
-      for (UnlinkedEnum type in unlinked.enums) {
-        addDeclaration(TopLevelDeclarationKind.type, type.name);
-      }
-      for (UnlinkedClass type in unlinked.mixins) {
-        addDeclaration(TopLevelDeclarationKind.type, type.name);
-      }
-      for (UnlinkedTypedef type in unlinked.typedefs) {
-        addDeclaration(TopLevelDeclarationKind.type, type.name);
-      }
-      // Add functions and variables.
-      Set<String> addedVariableNames = new Set<String>();
-      for (UnlinkedExecutable executable in unlinked.executables) {
-        String name = executable.name;
-        if (executable.kind == UnlinkedExecutableKind.functionOrMethod) {
-          addDeclaration(TopLevelDeclarationKind.function, name);
-        } else if (executable.kind == UnlinkedExecutableKind.getter ||
-            executable.kind == UnlinkedExecutableKind.setter) {
-          if (executable.kind == UnlinkedExecutableKind.setter) {
-            name = name.substring(0, name.length - 1);
-          }
-          if (addedVariableNames.add(name)) {
-            addDeclaration(TopLevelDeclarationKind.variable, name);
-          }
-        }
-      }
-      for (UnlinkedVariable variable in unlinked.variables) {
-        String name = variable.name;
-        if (addedVariableNames.add(name)) {
-          addDeclaration(TopLevelDeclarationKind.variable, name);
-        }
-      }
-    }
-    return _topLevelDeclarations;
-  }
-
-  /**
    * Return the set of transitive files - the file itself and all of the
    * directly or indirectly referenced files.
    */
@@ -537,10 +465,6 @@
           library.libraryCycle?.invalidate();
         }
       }
-
-      for (FileState file in _fsState._uriToFile.values) {
-        file._exportedTopLevelDeclarations = null;
-      }
     }
 
     // This file is potentially not a library for its previous parts anymore.
@@ -619,69 +543,6 @@
   @override
   String toString() => path ?? '<unresolved>';
 
-  /**
-   * Compute the full or partial map of exported declarations for this library.
-   */
-  _ExportedDeclarations _computeExportedDeclarations() {
-    // If we know exported declarations, return them.
-    if (_exportedTopLevelDeclarations != null) {
-      return new _ExportedDeclarations(0, _exportedTopLevelDeclarations);
-    }
-
-    // If we are already computing exported declarations for this library,
-    // report that we found a cycle.
-    if (_exportDeclarationsId != 0) {
-      return new _ExportedDeclarations(_exportDeclarationsId, null);
-    }
-
-    var declarations = <String, TopLevelDeclaration>{};
-
-    // Give each library a unique identifier.
-    _exportDeclarationsId = _exportDeclarationsNextId++;
-
-    // Append the exported declarations.
-    int firstCycleId = 0;
-    for (int i = 0; i < _exportedFiles.length; i++) {
-      var exported = _exportedFiles[i]._computeExportedDeclarations();
-      if (exported.declarations != null) {
-        for (TopLevelDeclaration t in exported.declarations.values) {
-          if (_exportFilters[i].accepts(t.name)) {
-            declarations[t.name] = t;
-          }
-        }
-      }
-      if (exported.firstCycleId > 0) {
-        if (firstCycleId == 0 || firstCycleId > exported.firstCycleId) {
-          firstCycleId = exported.firstCycleId;
-        }
-      }
-    }
-
-    // If this library is the first component of the cycle, then we are at
-    // the beginning of this cycle, and combination of partial export
-    // namespaces of other exported libraries and declarations of this library
-    // is the full export namespace of this library.
-    if (firstCycleId != 0 && firstCycleId == _exportDeclarationsId) {
-      firstCycleId = 0;
-    }
-
-    // We're done with this library, successfully or not.
-    _exportDeclarationsId = 0;
-
-    // Append the library declarations.
-    for (FileState file in libraryFiles) {
-      declarations.addAll(file.topLevelDeclarations);
-    }
-
-    // Record the declarations only if it is the full result.
-    if (firstCycleId == 0) {
-      _exportedTopLevelDeclarations = declarations;
-    }
-
-    // Return the full or partial result.
-    return new _ExportedDeclarations(firstCycleId, declarations);
-  }
-
   CompilationUnit _createEmptyCompilationUnit(FeatureSet featureSet) {
     var token = new Token.eof(0);
     return astFactory.compilationUnit2(
@@ -717,7 +578,6 @@
     _definedTopLevelNames = null;
     _definedClassMemberNames = null;
     _referencedNames = null;
-    _topLevelDeclarations = null;
 
     if (_driverUnlinkedUnit != null) {
       for (var name in _driverUnlinkedUnit.subtypedNames) {
@@ -833,10 +693,6 @@
           library.libraryCycle?.invalidate();
         }
       }
-
-      for (FileState file in _fsState._uriToFile.values) {
-        file._exportedTopLevelDeclarations = null;
-      }
     }
 
     // This file is potentially not a library for its previous parts anymore.
@@ -1253,23 +1109,6 @@
         .where((f) => f._libraryCycle == null)
         .toSet();
   }
-
-  Set<FileState> get librariesWithComputedExportedDeclarations {
-    return state._uriToFile.values
-        .where((f) => !f.isPart && f._exportedTopLevelDeclarations != null)
-        .toSet();
-  }
-}
-
-/**
- * The result of computing exported top-level declarations.
- * It can be full (when [firstCycleId] is zero), or partial (when a cycle)
- */
-class _ExportedDeclarations {
-  final int firstCycleId;
-  final Map<String, TopLevelDeclaration> declarations;
-
-  _ExportedDeclarations(this.firstCycleId, this.declarations);
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index f8f7f01..89066af 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -51,6 +51,7 @@
   final PerformanceLog logger;
   final ByteStore byteStore;
   final AnalysisSession analysisSession;
+  final SummaryDataStore externalSummaries;
   final SummaryDataStore store = new SummaryDataStore([]);
 
   /// The size of the linked data that is loaded by this context.
@@ -73,7 +74,7 @@
     @required AnalysisOptions analysisOptions,
     @required DeclaredVariables declaredVariables,
     @required SourceFactory sourceFactory,
-    @required SummaryDataStore externalSummaries,
+    @required this.externalSummaries,
     @required FileState targetLibrary,
     @required bool useSummary2,
   })  : this.logger = logger,
@@ -150,6 +151,10 @@
 
   /// Load data required to access elements of the given [targetLibrary].
   void load(FileState targetLibrary) {
+    if (AnalysisDriver.useSummary2) {
+      throw StateError('Unexpected with summary2.');
+    }
+
     // The library is already a part of the context, nothing to do.
     if (store.linkedMap.containsKey(targetLibrary.uriStr)) {
       return;
@@ -352,10 +357,13 @@
       analysisSession,
       Reference.root(),
     );
-
-    var dartCoreRef = elementFactory.rootReference.getChild('dart:core');
-    dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
-    dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
+    if (externalSummaries != null) {
+      for (var bundle in externalSummaries.bundles) {
+        elementFactory.addBundle(
+          LinkedBundleContext(elementFactory, bundle.bundle2),
+        );
+      }
+    }
   }
 
   void _createElementFactoryTypeProvider() {
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index 908cc96..dd29d9d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -133,10 +133,13 @@
   Future<List<Declaration>> declarations(
       RegExp regExp, int maxResults, LinkedHashSet<String> files,
       {String onlyForFile}) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     List<Declaration> declarations = <Declaration>[];
 
+    // TODO(scheglov) Not implemented.
+    if (AnalysisDriver.useSummary2) {
+      return declarations;
+    }
+
     DeclarationKind getExecutableKind(
         UnlinkedExecutable executable, bool topLevel) {
       switch (executable.kind) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 30db6fa..376e315 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -12,7 +12,6 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart' as driver;
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/dart/analysis/uri_converter.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/resolver.dart';
@@ -159,13 +158,6 @@
   }
 
   @override
-  Future<List<TopLevelDeclarationInSource>> getTopLevelDeclarations(
-      String name) {
-    _checkConsistency();
-    return _driver.getTopLevelNameDeclarations(name);
-  }
-
-  @override
   Future<UnitElementResult> getUnitElement(String path) {
     _checkConsistency();
     return _driver.getUnitElement(path);
diff --git a/pkg/analyzer/lib/src/dart/analysis/top_level_declaration.dart b/pkg/analyzer/lib/src/dart/analysis/top_level_declaration.dart
deleted file mode 100644
index 1658aad..0000000
--- a/pkg/analyzer/lib/src/dart/analysis/top_level_declaration.dart
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/src/generated/source.dart';
-
-/**
- * Information about a single top-level declaration.
- */
-class TopLevelDeclaration {
-  final TopLevelDeclarationKind kind;
-  final String name;
-
-  TopLevelDeclaration(this.kind, this.name);
-
-  @override
-  String toString() => '($kind, $name)';
-}
-
-/**
- * A declaration in a source.
- */
-class TopLevelDeclarationInSource {
-  /**
-   * The declaring source.
-   */
-  final Source source;
-
-  /**
-   * The declaration.
-   */
-  final TopLevelDeclaration declaration;
-
-  /**
-   * Is `true` if the [declaration] is exported, not declared in the [source].
-   */
-  final bool isExported;
-
-  TopLevelDeclarationInSource(this.source, this.declaration, this.isExported);
-
-  @override
-  String toString() => '($source, $declaration, $isExported)';
-}
-
-/**
- * Kind of a top-level declaration.
- *
- * We don't need it to be precise, just enough to support quick fixes.
- */
-enum TopLevelDeclarationKind { type, function, variable }
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index e3064ce..8a79218 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -3821,6 +3821,109 @@
   }
 }
 
+/// The declaration of an extension of a type.
+///
+///    extension ::=
+///        'extension' [SimpleIdentifier] [TypeParameterList]?
+///        'on' [TypeAnnotation] '{' [ClassMember]* '}'
+///
+/// Clients may not extend, implement or mix-in this class.
+class ExtensionDeclarationImpl extends NamedCompilationUnitMemberImpl
+    implements ExtensionDeclaration {
+  @override
+  Token extensionKeyword;
+
+  /// The type parameters for the extension, or `null` if the extension
+  /// does not have any type parameters.
+  TypeParameterListImpl _typeParameters;
+
+  @override
+  Token onKeyword;
+
+  /// The type that is being extended.
+  TypeAnnotationImpl _extendedType;
+
+  @override
+  Token leftBracket;
+
+  /// The members being added to the extended class.
+  NodeList<ClassMember> _members;
+
+  @override
+  Token rightBracket;
+
+  ExtensionDeclarationImpl(
+      CommentImpl comment,
+      List<Annotation> metadata,
+      this.extensionKeyword,
+      SimpleIdentifierImpl name,
+      TypeParameterListImpl typeParameters,
+      this.onKeyword,
+      TypeAnnotationImpl extendedType,
+      this.leftBracket,
+      List<ClassMember> members,
+      this.rightBracket)
+      : super(comment, metadata, name) {
+    _typeParameters = _becomeParentOf(typeParameters);
+    _extendedType = _becomeParentOf(extendedType);
+    _members = new NodeListImpl<ClassMember>(this, members);
+  }
+
+  @override
+  Token get beginToken => extensionKeyword;
+
+  @override
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
+    ..add(extensionKeyword)
+    ..add(name)
+    ..add(typeParameters)
+    ..add(onKeyword)
+    ..add(extendedType)
+    ..add(leftBracket)
+    ..addAll(members)
+    ..add(rightBracket);
+
+  @override
+  Element get declaredElement => name.staticElement;
+
+  @override
+  Element get element => name.staticElement;
+
+  @override
+  Token get endToken => rightBracket;
+
+  @override
+  TypeAnnotation get extendedType => _extendedType;
+
+  void set extendedType(TypeAnnotation extendedClass) {
+    _extendedType = _becomeParentOf(extendedClass as TypeAnnotationImpl);
+  }
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata => name.beginToken;
+
+  @override
+  NodeList<ClassMember> get members => _members;
+
+  @override
+  TypeParameterList get typeParameters => _typeParameters;
+
+  void set typeParameters(TypeParameterList typeParameters) {
+    _typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl);
+  }
+
+  @override
+  E accept<E>(AstVisitor<E> visitor) => visitor.visitExtensionDeclaration(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    name?.accept(visitor);
+    _typeParameters?.accept(visitor);
+    _extendedType?.accept(visitor);
+    _members.accept(visitor);
+  }
+}
+
 /// The declaration of one or more fields of the same type.
 ///
 ///    fieldDeclaration ::=
@@ -5083,6 +5186,9 @@
   /// The parameters of the function-typed parameter.
   FormalParameterListImpl _parameters;
 
+  @override
+  Token question;
+
   /// Initialize a newly created formal parameter. Either or both of the
   /// [comment] and [metadata] can be `null` if the parameter does not have the
   /// corresponding attribute. The [returnType] can be `null` if no return type
@@ -5095,7 +5201,8 @@
       TypeAnnotationImpl returnType,
       SimpleIdentifierImpl identifier,
       TypeParameterListImpl typeParameters,
-      FormalParameterListImpl parameters)
+      FormalParameterListImpl parameters,
+      this.question)
       : super(
             comment, metadata, covariantKeyword, requiredKeyword, identifier) {
     _returnType = _becomeParentOf(returnType);
diff --git a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
index 95b5867..1cd13f3 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
@@ -370,6 +370,30 @@
       new ExtendsClauseImpl(extendsKeyword, superclass);
 
   @override
+  ExtensionDeclaration extensionDeclaration(
+          {Comment comment,
+          List<Annotation> metadata,
+          Token extensionKeyword,
+          @required SimpleIdentifier name,
+          TypeParameterList typeParameters,
+          Token onKeyword,
+          @required TypeAnnotation extendedType,
+          Token leftBracket,
+          List<ClassMember> members,
+          Token rightBracket}) =>
+      new ExtensionDeclarationImpl(
+          comment,
+          metadata,
+          extensionKeyword,
+          name,
+          typeParameters,
+          onKeyword,
+          extendedType,
+          leftBracket,
+          members,
+          rightBracket);
+
+  @override
   FieldDeclaration fieldDeclaration(
           Comment comment,
           List<Annotation> metadata,
@@ -564,7 +588,7 @@
           TypeParameterList typeParameters,
           FormalParameterList parameters) =>
       new FunctionTypedFormalParameterImpl(comment, metadata, null, null,
-          returnType, identifier, typeParameters, parameters);
+          returnType, identifier, typeParameters, parameters, null);
 
   @override
   FunctionTypedFormalParameter functionTypedFormalParameter2(
@@ -575,9 +599,18 @@
           TypeAnnotation returnType,
           @required SimpleIdentifier identifier,
           TypeParameterList typeParameters,
-          @required FormalParameterList parameters}) =>
-      new FunctionTypedFormalParameterImpl(comment, metadata, covariantKeyword,
-          requiredKeyword, returnType, identifier, typeParameters, parameters);
+          @required FormalParameterList parameters,
+          Token question}) =>
+      new FunctionTypedFormalParameterImpl(
+          comment,
+          metadata,
+          covariantKeyword,
+          requiredKeyword,
+          returnType,
+          identifier,
+          typeParameters,
+          parameters,
+          question);
 
   @override
   GenericFunctionType genericFunctionType(
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 5ac34d1..807d3c6 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -450,6 +450,20 @@
           cloneToken(node.extendsKeyword), cloneNode(node.superclass));
 
   @override
+  ExtensionDeclaration visitExtensionDeclaration(ExtensionDeclaration node) =>
+      astFactory.extensionDeclaration(
+          comment: cloneNode(node.documentationComment),
+          metadata: cloneNodeList(node.metadata),
+          extensionKeyword: cloneToken(node.extensionKeyword),
+          name: cloneNode(node.name),
+          typeParameters: cloneNode(node.typeParameters),
+          onKeyword: cloneToken(node.onKeyword),
+          extendedType: cloneNode(node.extendedType),
+          leftBracket: cloneToken(node.leftBracket),
+          members: cloneNodeList(node.members),
+          rightBracket: cloneToken(node.rightBracket));
+
+  @override
   FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
       astFactory.fieldDeclaration2(
           comment: cloneNode(node.documentationComment),
@@ -586,7 +600,8 @@
           returnType: cloneNode(node.returnType),
           identifier: cloneNode(node.identifier),
           typeParameters: cloneNode(node.typeParameters),
-          parameters: cloneNode(node.parameters));
+          parameters: cloneNode(node.parameters),
+          question: cloneToken(node.question));
 
   @override
   AstNode visitGenericFunctionType(GenericFunctionType node) =>
@@ -1577,6 +1592,22 @@
   }
 
   @override
+  bool visitExtensionDeclaration(ExtensionDeclaration node) {
+    ExtensionDeclaration other = _other as ExtensionDeclaration;
+    return isEqualNodes(
+            node.documentationComment, other.documentationComment) &&
+        _isEqualNodeLists(node.metadata, other.metadata) &&
+        isEqualTokens(node.extensionKeyword, other.extensionKeyword) &&
+        isEqualNodes(node.name, other.name) &&
+        isEqualNodes(node.typeParameters, other.typeParameters) &&
+        isEqualTokens(node.onKeyword, other.onKeyword) &&
+        isEqualNodes(node.extendedType, other.extendedType) &&
+        isEqualTokens(node.leftBracket, other.leftBracket) &&
+        _isEqualNodeLists(node.members, other.members) &&
+        isEqualTokens(node.rightBracket, other.rightBracket);
+  }
+
+  @override
   bool visitFieldDeclaration(FieldDeclaration node) {
     FieldDeclaration other = _other as FieldDeclaration;
     return isEqualNodes(
@@ -2817,6 +2848,20 @@
           _mapToken(node.extendsKeyword), _cloneNode(node.superclass));
 
   @override
+  ExtensionDeclaration visitExtensionDeclaration(ExtensionDeclaration node) =>
+      astFactory.extensionDeclaration(
+          comment: _cloneNode(node.documentationComment),
+          metadata: _cloneNodeList(node.metadata),
+          extensionKeyword: _mapToken(node.extensionKeyword),
+          name: _cloneNode(node.name),
+          typeParameters: _cloneNode(node.typeParameters),
+          onKeyword: _mapToken(node.onKeyword),
+          extendedType: _cloneNode(node.extendedType),
+          leftBracket: _mapToken(node.leftBracket),
+          members: _cloneNodeList(node.members),
+          rightBracket: _mapToken(node.rightBracket));
+
+  @override
   FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
       astFactory.fieldDeclaration2(
           comment: _cloneNode(node.documentationComment),
@@ -2965,7 +3010,8 @@
           returnType: _cloneNode(node.returnType),
           identifier: _cloneNode(node.identifier),
           typeParameters: _cloneNode(node.typeParameters),
-          parameters: _cloneNode(node.parameters));
+          parameters: _cloneNode(node.parameters),
+          question: _mapToken(node.question));
 
   @override
   AstNode visitGenericFunctionType(GenericFunctionType node) =>
@@ -4230,6 +4276,29 @@
     return visitNode(node);
   }
 
+  bool visitExtensionDeclaration(ExtensionDeclaration node) {
+    if (identical(node.documentationComment, _oldNode)) {
+      node.documentationComment = _newNode as Comment;
+      return true;
+    } else if (_replaceInList(node.metadata)) {
+      return true;
+    } else if (identical(node.name, _oldNode)) {
+      (node as ExtensionDeclarationImpl).name = _newNode as SimpleIdentifier;
+      return true;
+    } else if (identical(node.typeParameters, _oldNode)) {
+      (node as ExtensionDeclarationImpl).typeParameters =
+          _newNode as TypeParameterList;
+      return true;
+    } else if (identical(node.extendedType, _oldNode)) {
+      (node as ExtensionDeclarationImpl).extendedType =
+          _newNode as TypeAnnotation;
+      return true;
+    } else if (_replaceInList(node.members)) {
+      return true;
+    }
+    return visitNode(node);
+  }
+
   @override
   bool visitFieldDeclaration(FieldDeclaration node) {
     if (identical(node.fields, _oldNode)) {
@@ -5585,6 +5654,25 @@
   }
 
   @override
+  bool visitExtensionDeclaration(ExtensionDeclaration node) {
+    ExtensionDeclaration toNode = this._toNode as ExtensionDeclaration;
+    if (_and(
+        _isEqualNodes(node.documentationComment, toNode.documentationComment),
+        _isEqualNodeLists(node.metadata, toNode.metadata),
+        _isEqualTokens(node.extensionKeyword, toNode.extensionKeyword),
+        _isEqualNodes(node.name, toNode.name),
+        _isEqualNodes(node.typeParameters, toNode.typeParameters),
+        _isEqualTokens(node.onKeyword, toNode.onKeyword),
+        _isEqualNodes(node.extendedType, toNode.extendedType),
+        _isEqualTokens(node.leftBracket, toNode.leftBracket),
+        _isEqualNodeLists(node.members, toNode.members),
+        _isEqualTokens(node.rightBracket, toNode.rightBracket))) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
   bool visitFieldDeclaration(FieldDeclaration node) {
     FieldDeclaration toNode = this._toNode as FieldDeclaration;
     return _and(
@@ -7155,6 +7243,21 @@
   }
 
   @override
+  void visitExtensionDeclaration(ExtensionDeclaration node) {
+    _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+    _visitTokenWithSuffix(node.extensionKeyword, ' ');
+    _visitNode(node.name);
+    _visitNode(node.typeParameters);
+    _writer.print(' ');
+    _visitToken(node.onKeyword);
+    _writer.print(' ');
+    _visitNodeWithSuffix(node.extendedType, ' ');
+    _visitToken(node.leftBracket);
+    _visitNodeListWithSeparator(node.members, ' ');
+    _visitToken(node.rightBracket);
+  }
+
+  @override
   void visitFieldDeclaration(FieldDeclaration node) {
     _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
     _visitTokenWithSuffix(node.staticKeyword, " ");
@@ -7305,6 +7408,9 @@
     _visitNode(node.identifier);
     _visitNode(node.typeParameters);
     _visitNode(node.parameters);
+    if (node.question != null) {
+      _writer.print('?');
+    }
   }
 
   @override
@@ -7927,6 +8033,15 @@
   }
 
   /**
+   * Safely visit the given [token].
+   */
+  void _visitToken(Token token) {
+    if (token != null) {
+      _writer.print(token.lexeme);
+    }
+  }
+
+  /**
    * Safely visit the given [token], printing the [suffix] after the token if it
    * is non-`null`.
    */
@@ -8076,6 +8191,16 @@
   }
 
   /**
+   * Safely visit the given [token].
+   */
+  @protected
+  void safelyVisitToken(Token token) {
+    if (token != null) {
+      sink.write(token.lexeme);
+    }
+  }
+
+  /**
    * Safely visit the given [token], printing the [suffix] after the token if it
    * is non-`null`.
    */
@@ -8420,6 +8545,21 @@
   }
 
   @override
+  void visitExtensionDeclaration(ExtensionDeclaration node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+    safelyVisitTokenWithSuffix(node.extensionKeyword, ' ');
+    safelyVisitNode(node.name);
+    safelyVisitNode(node.typeParameters);
+    sink.write(' ');
+    safelyVisitToken(node.onKeyword);
+    sink.write(' ');
+    safelyVisitNodeWithSuffix(node.extendedType, ' ');
+    safelyVisitToken(node.leftBracket);
+    safelyVisitNodeListWithSeparator(node.members, ' ');
+    safelyVisitToken(node.rightBracket);
+  }
+
+  @override
   void visitFieldDeclaration(FieldDeclaration node) {
     safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
     safelyVisitTokenWithSuffix(node.staticKeyword, " ");
@@ -8570,6 +8710,9 @@
     safelyVisitNode(node.identifier);
     safelyVisitNode(node.typeParameters);
     safelyVisitNode(node.parameters);
+    if (node.question != null) {
+      sink.write('?');
+    }
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 3c98239..53e8356 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -1606,6 +1606,7 @@
             typeSystem.isAssignableTo(staticType, _typeProvider.boolType)) {
           // If the static type is not assignable, then we will have already
           // reported this error.
+          // TODO(mfairhurst) get the FeatureSet to suppress this for nnbd too.
           _errorReporter.reportErrorForNode(
               CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, condition);
         }
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index b917123..8086e2c 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -83,7 +83,7 @@
     SimpleIdentifier className = node.name;
     ClassElementImpl element = new ClassElementImpl.forNode(className);
     className.staticElement = element;
-    element.abstract = node.isAbstract;
+    element.isAbstract = node.isAbstract;
     _fillClassElement(node, element, holder);
 
     _currentHolder.addType(element);
@@ -97,7 +97,7 @@
     ClassElementImpl element = new ClassElementImpl.forNode(className);
     _setCodeRange(element, node);
     element.metadata = _createElementAnnotations(node.metadata);
-    element.abstract = node.abstractKeyword != null;
+    element.isAbstract = node.abstractKeyword != null;
     element.mixinApplication = true;
     element.typeParameters = holder.typeParameters;
     setElementDocumentationComment(element, node);
@@ -430,7 +430,7 @@
         _setCodeRange(element, node);
         element.metadata = _createElementAnnotations(node.metadata);
         setElementDocumentationComment(element, node);
-        element.abstract = node.isAbstract;
+        element.isAbstract = node.isAbstract;
         if (node.externalKeyword != null || body is NativeFunctionBody) {
           element.external = true;
         }
@@ -482,7 +482,7 @@
             getter.generator = true;
           }
           getter.variable = field;
-          getter.abstract = node.isAbstract;
+          getter.isAbstract = node.isAbstract;
           getter.getter = true;
           getter.isStatic = isStatic;
           field.getter = getter;
@@ -511,7 +511,7 @@
             setter.generator = true;
           }
           setter.variable = field;
-          setter.abstract = node.isAbstract;
+          setter.isAbstract = node.isAbstract;
           setter.setter = true;
           setter.isStatic = isStatic;
           if (node.returnType == null) {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 3543c8e..53cd4f7 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -18,6 +18,7 @@
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/handle.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/generated/constant.dart' show EvaluationResultImpl;
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisEngine, AnalysisOptionsImpl;
@@ -479,9 +480,9 @@
       : super.forSerialized(enclosingUnit);
 
   /// Set whether this class is abstract.
+  @Deprecated('Use isAbstract instead')
   void set abstract(bool isAbstract) {
-    _assertNotResynthesized(_unlinkedClass);
-    setModifier(Modifier.ABSTRACT, isAbstract);
+    this.isAbstract = isAbstract;
   }
 
   @override
@@ -824,6 +825,12 @@
     return hasModifier(Modifier.ABSTRACT);
   }
 
+  /// Set whether this class is abstract.
+  void set isAbstract(bool isAbstract) {
+    _assertNotResynthesized(_unlinkedClass);
+    setModifier(Modifier.ABSTRACT, isAbstract);
+  }
+
   @override
   bool get isMixinApplication {
     if (linkedNode != null) {
@@ -2608,6 +2615,15 @@
 
   @override
   int get nameEnd {
+    if (linkedNode != null) {
+      var node = linkedNode as ConstructorDeclaration;
+      if (node.name != null) {
+        return node.name.end;
+      } else {
+        return node.returnType.end;
+      }
+    }
+
     if (serializedExecutable != null) {
       if (serializedExecutable.name.isNotEmpty) {
         return serializedExecutable.nameEnd;
@@ -2625,6 +2641,11 @@
 
   @override
   int get periodOffset {
+    if (linkedNode != null) {
+      var node = linkedNode as ConstructorDeclaration;
+      return node.period?.offset;
+    }
+
     if (serializedExecutable != null) {
       if (serializedExecutable.name.isNotEmpty) {
         return serializedExecutable.periodOffset;
@@ -2703,6 +2724,7 @@
 
   @override
   void appendTo(StringBuffer buffer) {
+    String name;
     if (enclosingElement == null) {
       String message;
       String name = displayName;
@@ -2713,16 +2735,15 @@
         message = 'Found unnamed constructor element with no enclosing element';
       }
       AnalysisEngine.instance.logger.logError(message);
-      buffer.write('<unknown class>');
+      name = '<unknown class>';
     } else {
-      buffer.write(enclosingElement.displayName);
+      name = enclosingElement.displayName;
     }
-    String name = displayName;
-    if (name != null && !name.isEmpty) {
-      buffer.write(".");
-      buffer.write(name);
+    String constructorName = displayName;
+    if (constructorName != null && !constructorName.isEmpty) {
+      name = '$name.$constructorName';
     }
-    super.appendTo(buffer);
+    appendToWithName(buffer, name);
   }
 
   @deprecated
@@ -3207,6 +3228,7 @@
 /// A base class for concrete implementations of an [Element].
 abstract class ElementImpl implements Element {
   /// An Unicode right arrow.
+  @deprecated
   static final String RIGHT_ARROW = " \u2192 ";
 
   static int _NEXT_ID = 0;
@@ -4016,6 +4038,7 @@
       : super.forSerialized(enclosingUnit);
 
   /// Set whether this class is abstract.
+  @Deprecated('This setter will be removed')
   void set abstract(bool isAbstract) {
     _assertNotResynthesized(_unlinkedEnum);
   }
@@ -4617,6 +4640,23 @@
 
   @override
   void appendTo(StringBuffer buffer) {
+    appendToWithName(buffer, displayName);
+  }
+
+  /// Append a textual representation of this element to the given [buffer]. The
+  /// [name] is the name of the executable element or `null` if the element has
+  /// no name. If [includeType] is `true` then the return type will be included.
+  void appendToWithName(StringBuffer buffer, String name) {
+    FunctionType functionType = type;
+    if (functionType != null) {
+      buffer.write(functionType.returnType);
+      if (name != null) {
+        buffer.write(' ');
+        buffer.write(name);
+      }
+    } else if (name != null) {
+      buffer.write(name);
+    }
     if (this.kind != ElementKind.GETTER) {
       int typeParameterCount = typeParameters.length;
       if (typeParameterCount > 0) {
@@ -4665,10 +4705,6 @@
       }
       buffer.write(')');
     }
-    if (type != null) {
-      buffer.write(ElementImpl.RIGHT_ARROW);
-      buffer.write(type.returnType);
-    }
   }
 
   @override
@@ -5178,15 +5214,6 @@
   @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitFunctionElement(this);
 
-  @override
-  void appendTo(StringBuffer buffer) {
-    String name = displayName;
-    if (name != null) {
-      buffer.write(name);
-    }
-    super.appendTo(buffer);
-  }
-
   @deprecated
   @override
   FunctionDeclaration computeNode() =>
@@ -5795,15 +5822,23 @@
       return null;
     }
     FunctionType functionType = function.type;
+
     List<TypeParameterElement> parameterElements = element.typeParameters;
-    List<DartType> parameterTypes =
-        TypeParameterTypeImpl.getTypes(parameterElements);
-    int parameterCount = parameterTypes.length;
+    int parameterCount = parameterElements.length;
+
     if (typeArguments == null ||
         parameterElements.length != typeArguments.length) {
       DartType dynamicType = DynamicElementImpl.instance.type;
       typeArguments = new List<DartType>.filled(parameterCount, dynamicType);
     }
+
+    if (element is GenericTypeAliasElementImpl && element.linkedNode != null) {
+      return Substitution.fromPairs(parameterElements, typeArguments)
+          .substituteType(functionType);
+    }
+
+    List<DartType> parameterTypes =
+        TypeParameterTypeImpl.getTypes(parameterElements);
     return functionType.substitute2(typeArguments, parameterTypes);
   }
 }
@@ -7185,9 +7220,9 @@
       : super.forSerialized(serializedExecutable, enclosingClass);
 
   /// Set whether this method is abstract.
+  @Deprecated('Use isAbstract instead')
   void set abstract(bool isAbstract) {
-    _assertNotResynthesized(serializedExecutable);
-    setModifier(Modifier.ABSTRACT, isAbstract);
+    this.isAbstract = isAbstract;
   }
 
   @override
@@ -7206,6 +7241,12 @@
   TypeParameterizedElementMixin get enclosingTypeParameterContext =>
       super.enclosingElement as ClassElementImpl;
 
+  /// Set whether this class is abstract.
+  void set isAbstract(bool isAbstract) {
+    _assertNotResynthesized(serializedExecutable);
+    setModifier(Modifier.ABSTRACT, isAbstract);
+  }
+
   @override
   bool get isOperator {
     String name = displayName;
@@ -7251,12 +7292,6 @@
   @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitMethodElement(this);
 
-  @override
-  void appendTo(StringBuffer buffer) {
-    buffer.write(displayName);
-    super.appendTo(buffer);
-  }
-
   @deprecated
   @override
   MethodDeclaration computeNode() =>
@@ -8897,9 +8932,9 @@
   }
 
   /// Set whether this accessor is abstract.
+  @Deprecated('Use isAbstract instead')
   void set abstract(bool isAbstract) {
-    _assertNotResynthesized(serializedExecutable);
-    setModifier(Modifier.ABSTRACT, isAbstract);
+    this.isAbstract = isAbstract;
   }
 
   @override
@@ -8946,6 +8981,12 @@
     return "$name$suffix";
   }
 
+  /// Set whether this class is abstract.
+  void set isAbstract(bool isAbstract) {
+    _assertNotResynthesized(serializedExecutable);
+    setModifier(Modifier.ABSTRACT, isAbstract);
+  }
+
   @override
   bool get isGetter {
     if (linkedNode != null) {
@@ -9024,9 +9065,8 @@
 
   @override
   void appendTo(StringBuffer buffer) {
-    buffer.write(isGetter ? "get " : "set ");
-    buffer.write(variable.displayName);
-    super.appendTo(buffer);
+    super.appendToWithName(
+        buffer, (isGetter ? 'get ' : 'set ') + variable.displayName);
   }
 
   @deprecated
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index fc58f4f..f818145 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -73,26 +73,27 @@
     ConstructorElement baseElement = this.baseElement;
     List<ParameterElement> parameters = this.parameters;
     FunctionType type = this.type;
+
     StringBuffer buffer = new StringBuffer();
+    if (type != null) {
+      buffer.write(type.returnType);
+      buffer.write(' ');
+    }
     buffer.write(baseElement.enclosingElement.displayName);
     String name = displayName;
     if (name != null && !name.isEmpty) {
-      buffer.write(".");
+      buffer.write('.');
       buffer.write(name);
     }
-    buffer.write("(");
+    buffer.write('(');
     int parameterCount = parameters.length;
     for (int i = 0; i < parameterCount; i++) {
       if (i > 0) {
-        buffer.write(", ");
+        buffer.write(', ');
       }
       buffer.write(parameters[i]);
     }
-    buffer.write(")");
-    if (type != null) {
-      buffer.write(ElementImpl.RIGHT_ARROW);
-      buffer.write(type.returnType);
-    }
+    buffer.write(')');
     return buffer.toString();
   }
 
@@ -621,28 +622,33 @@
     MethodElement baseElement = this.baseElement;
     List<ParameterElement> parameters = this.parameters;
     FunctionType type = this.type;
+
     StringBuffer buffer = new StringBuffer();
+    if (type != null) {
+      buffer.write(type.returnType);
+      buffer.write(' ');
+    }
     buffer.write(baseElement.enclosingElement.displayName);
-    buffer.write(".");
+    buffer.write('.');
     buffer.write(baseElement.displayName);
     int typeParameterCount = typeParameters.length;
     if (typeParameterCount > 0) {
       buffer.write('<');
       for (int i = 0; i < typeParameterCount; i++) {
         if (i > 0) {
-          buffer.write(", ");
+          buffer.write(', ');
         }
         (typeParameters[i] as TypeParameterElementImpl).appendTo(buffer);
       }
       buffer.write('>');
     }
-    buffer.write("(");
+    buffer.write('(');
     String closing = null;
     ParameterKind kind = ParameterKind.REQUIRED;
     int parameterCount = parameters.length;
     for (int i = 0; i < parameterCount; i++) {
       if (i > 0) {
-        buffer.write(", ");
+        buffer.write(', ');
       }
       ParameterElement parameter = parameters[i];
       // ignore: deprecated_member_use_from_same_package
@@ -652,11 +658,11 @@
           buffer.write(closing);
         }
         if (parameter.isOptionalPositional) {
-          buffer.write("[");
-          closing = "]";
+          buffer.write('[');
+          closing = ']';
         } else if (parameter.isNamed) {
-          buffer.write("{");
-          closing = "}";
+          buffer.write('{');
+          closing = '}';
         } else {
           closing = null;
         }
@@ -667,11 +673,7 @@
     if (closing != null) {
       buffer.write(closing);
     }
-    buffer.write(")");
-    if (type != null) {
-      buffer.write(ElementImpl.RIGHT_ARROW);
-      buffer.write(type.returnType);
-    }
+    buffer.write(')');
     return buffer.toString();
   }
 
@@ -852,28 +854,29 @@
     PropertyAccessorElement baseElement = this.baseElement;
     List<ParameterElement> parameters = this.parameters;
     FunctionType type = this.type;
+
     StringBuffer builder = new StringBuffer();
+    if (type != null) {
+      builder.write(type.returnType);
+      builder.write(' ');
+    }
     if (isGetter) {
-      builder.write("get ");
+      builder.write('get ');
     } else {
-      builder.write("set ");
+      builder.write('set ');
     }
     builder.write(baseElement.enclosingElement.displayName);
-    builder.write(".");
+    builder.write('.');
     builder.write(baseElement.displayName);
-    builder.write("(");
+    builder.write('(');
     int parameterCount = parameters.length;
     for (int i = 0; i < parameterCount; i++) {
       if (i > 0) {
-        builder.write(", ");
+        builder.write(', ');
       }
       builder.write(parameters[i]);
     }
-    builder.write(")");
-    if (type != null) {
-      builder.write(ElementImpl.RIGHT_ARROW);
-      builder.write(type.returnType);
-    }
+    builder.write(')');
     return builder.toString();
   }
 
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index ec7f129..de53916 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -56,15 +56,34 @@
  */
 class BottomTypeImpl extends TypeImpl {
   /**
-   * The unique instance of this class.
+   * The unique instance of this class, nullable.
+   *
+   * This behaves equivalently to the `Null` type, but we distinguish it for two
+   * reasons: (1) there are circumstances where we need access to this type, but
+   * we don't have access to the type provider, so using `Never?` is a
+   * convenient solution.  (2) we may decide that the distinction is convenient
+   * in diagnostic messages (this is TBD).
    */
-  static final BottomTypeImpl instance = new BottomTypeImpl._();
+  static final BottomTypeImpl instanceNullable =
+      new BottomTypeImpl._(NullabilitySuffix.question);
+
+  /**
+   * The unique instance of this class, non-nullable.
+   */
+  static final BottomTypeImpl instance =
+      new BottomTypeImpl._(NullabilitySuffix.none);
+
+  @override
+  final NullabilitySuffix nullabilitySuffix;
 
   /**
    * Prevent the creation of instances of this class.
    */
-  BottomTypeImpl._() : super(new NeverElementImpl(), "Never") {
-    (element as NeverElementImpl).type = this;
+  BottomTypeImpl._(this.nullabilitySuffix)
+      : super(new NeverElementImpl(), "Never") {
+    if (nullabilitySuffix == NullabilitySuffix.none) {
+      (element as NeverElementImpl).type = this;
+    }
   }
 
   @override
@@ -74,7 +93,10 @@
   bool get isBottom => true;
 
   @override
-  NullabilitySuffix get nullabilitySuffix => NullabilitySuffix.none;
+  bool get isDartCoreNull {
+    // `Never?` is equivalent to `Null`, so make sure it behaves the same.
+    return nullabilitySuffix == NullabilitySuffix.question;
+  }
 
   @override
   bool operator ==(Object object) => identical(object, this);
@@ -119,8 +141,22 @@
 
   @override
   TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
-    // The bottom type is always non-nullable.
-    return this;
+    switch (nullabilitySuffix) {
+      case NullabilitySuffix.question:
+        return instanceNullable;
+      case NullabilitySuffix.star:
+        // This should never happen.  Converting `Never` to a legacy type should
+        // yield `Null`, because prior to NNBD, `Null` was at the bottom of the
+        // type hierarchy.
+        //
+        // However, due to bugs elsewhere in the analyzer, this does still
+        // happen sometimes, so for now just coerce to `Never?`.
+        // TODO(paulberry): change this to throw an exception.
+        return instanceNullable;
+      case NullabilitySuffix.none:
+        return instance;
+    }
+    throw StateError('Unexpected nullabilitySuffix: $nullabilitySuffix');
   }
 }
 
@@ -242,6 +278,12 @@
   TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) => this;
 
   @override
+  void _appendToWithTypeParameters(StringBuffer buffer,
+      Set<TypeImpl> visitedTypes, bool withNullability, String typeParameters) {
+    throw StateError('We should never get here.');
+  }
+
+  @override
   void _forEachParameterType(
       ParameterKind kind, callback(String name, DartType type)) {
     // There are no parameters.
@@ -309,8 +351,10 @@
 
   DeferredFunctionTypeImpl(this._computeElement, String name,
       List<DartType> typeArguments, bool isInstantiated,
-      {NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star})
-      : super._(null, name, null, typeArguments, null, null, isInstantiated,
+      {NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
+      FunctionTypedElement computedElement})
+      : _computedElement = computedElement,
+        super._(null, name, null, typeArguments, null, null, isInstantiated,
             nullabilitySuffix: nullabilitySuffix);
 
   @override
@@ -327,6 +371,7 @@
     if (this.nullabilitySuffix == nullabilitySuffix) return this;
     return DeferredFunctionTypeImpl(
         _computeElement, name, typeArguments, isInstantiated,
+        computedElement: _computedElement,
         nullabilitySuffix: nullabilitySuffix);
   }
 }
@@ -680,11 +725,11 @@
   @override
   void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
       {bool withNullability = false}) {
-    // TODO(paulberry): update to use the new "Function" syntax to avoid
-    // ambiguity with NNBD, and eliminate code duplication with
+    // TODO(paulberry): eliminate code duplication with
     // _ElementWriter.writeType.  See issue #35818.
     if (visitedTypes.add(this)) {
       if (typeFormals.isNotEmpty) {
+        StringBuffer typeParametersBuffer = StringBuffer();
         // To print a type with type variables, first make sure we have unique
         // variable names to print.
         Set<TypeParameterType> freeVariables = new HashSet<TypeParameterType>();
@@ -699,10 +744,10 @@
 
         List<DartType> instantiateTypeArgs = <DartType>[];
         List<DartType> variables = <DartType>[];
-        buffer.write("<");
+        typeParametersBuffer.write('<');
         for (TypeParameterElement e in typeFormals) {
           if (e != typeFormals[0]) {
-            buffer.write(",");
+            typeParametersBuffer.write(',');
           }
           String name = e.name;
           int counter = 0;
@@ -717,89 +762,27 @@
           }
           TypeParameterTypeImpl t =
               new TypeParameterTypeImpl(new TypeParameterElementImpl(name, -1));
-          t.appendTo(buffer, visitedTypes, withNullability: withNullability);
+          t.appendTo(typeParametersBuffer, visitedTypes,
+              withNullability: withNullability);
           instantiateTypeArgs.add(t);
           variables.add(e.type);
           if (e.bound != null) {
-            buffer.write(" extends ");
+            typeParametersBuffer.write(' extends ');
             TypeImpl renamed =
                 e.bound.substitute2(instantiateTypeArgs, variables);
-            renamed.appendTo(buffer, visitedTypes);
+            renamed.appendTo(typeParametersBuffer, visitedTypes);
           }
         }
-        buffer.write(">");
+        typeParametersBuffer.write('>');
 
-        // Instantiate it and print the resulting type. After instantiation, it
-        // will no longer have typeFormals, so we will continue below.
-        this
-            .instantiate(instantiateTypeArgs)
-            .appendTo(buffer, visitedTypes, withNullability: withNullability);
-        return;
-      }
-
-      List<DartType> normalParameterTypes = this.normalParameterTypes;
-      List<DartType> optionalParameterTypes = this.optionalParameterTypes;
-      Map<String, DartType> namedParameterTypes = this.namedParameterTypes;
-      DartType returnType = this.returnType;
-
-      bool needsComma = false;
-      void writeSeparator() {
-        if (needsComma) {
-          buffer.write(", ");
-        } else {
-          needsComma = true;
-        }
-      }
-
-      void startOptionalParameters() {
-        if (needsComma) {
-          buffer.write(", ");
-          needsComma = false;
-        }
-      }
-
-      buffer.write("(");
-      if (normalParameterTypes.isNotEmpty) {
-        for (DartType type in normalParameterTypes) {
-          writeSeparator();
-          (type as TypeImpl)
-              .appendTo(buffer, visitedTypes, withNullability: withNullability);
-        }
-      }
-      if (optionalParameterTypes.isNotEmpty) {
-        startOptionalParameters();
-        buffer.write("[");
-        for (DartType type in optionalParameterTypes) {
-          writeSeparator();
-          (type as TypeImpl)
-              .appendTo(buffer, visitedTypes, withNullability: withNullability);
-        }
-        buffer.write("]");
-        needsComma = true;
-      }
-      if (namedParameterTypes.isNotEmpty) {
-        startOptionalParameters();
-        buffer.write("{");
-        namedParameterTypes.forEach((String name, DartType type) {
-          writeSeparator();
-          buffer.write(name);
-          buffer.write(": ");
-          (type as TypeImpl)
-              .appendTo(buffer, visitedTypes, withNullability: withNullability);
-        });
-        buffer.write("}");
-        needsComma = true;
-      }
-      buffer.write(")");
-      buffer.write(ElementImpl.RIGHT_ARROW);
-      if (returnType == null) {
-        buffer.write("null");
+        // Instantiate it and print the resulting type.
+        this.instantiate(instantiateTypeArgs)._appendToWithTypeParameters(
+            buffer,
+            visitedTypes,
+            withNullability,
+            typeParametersBuffer.toString());
       } else {
-        (returnType as TypeImpl)
-            .appendTo(buffer, visitedTypes, withNullability: withNullability);
-      }
-      if (withNullability) {
-        _appendNullability(buffer);
+        _appendToWithTypeParameters(buffer, visitedTypes, withNullability, '');
       }
       visitedTypes.remove(this);
     } else {
@@ -902,6 +885,76 @@
   FunctionTypeImpl substitute3(List<DartType> argumentTypes) =>
       substitute2(argumentTypes, typeArguments);
 
+  void _appendToWithTypeParameters(StringBuffer buffer,
+      Set<TypeImpl> visitedTypes, bool withNullability, String typeParameters) {
+    List<DartType> normalParameterTypes = this.normalParameterTypes;
+    List<DartType> optionalParameterTypes = this.optionalParameterTypes;
+    Map<String, DartType> namedParameterTypes = this.namedParameterTypes;
+    DartType returnType = this.returnType;
+
+    if (returnType == null) {
+      buffer.write('null');
+    } else {
+      (returnType as TypeImpl)
+          .appendTo(buffer, visitedTypes, withNullability: withNullability);
+    }
+    buffer.write(' Function');
+    buffer.write(typeParameters);
+    bool needsComma = false;
+
+    void writeSeparator() {
+      if (needsComma) {
+        buffer.write(', ');
+      } else {
+        needsComma = true;
+      }
+    }
+
+    void startOptionalParameters() {
+      if (needsComma) {
+        buffer.write(', ');
+        needsComma = false;
+      }
+    }
+
+    buffer.write('(');
+    if (normalParameterTypes.isNotEmpty) {
+      for (DartType type in normalParameterTypes) {
+        writeSeparator();
+        (type as TypeImpl)
+            .appendTo(buffer, visitedTypes, withNullability: withNullability);
+      }
+    }
+    if (optionalParameterTypes.isNotEmpty) {
+      startOptionalParameters();
+      buffer.write('[');
+      for (DartType type in optionalParameterTypes) {
+        writeSeparator();
+        (type as TypeImpl)
+            .appendTo(buffer, visitedTypes, withNullability: withNullability);
+      }
+      buffer.write(']');
+      needsComma = true;
+    }
+    if (namedParameterTypes.isNotEmpty) {
+      startOptionalParameters();
+      buffer.write('{');
+      namedParameterTypes.forEach((String name, DartType type) {
+        writeSeparator();
+        buffer.write(name);
+        buffer.write(': ');
+        (type as TypeImpl)
+            .appendTo(buffer, visitedTypes, withNullability: withNullability);
+      });
+      buffer.write('}');
+      needsComma = true;
+    }
+    buffer.write(')');
+    if (withNullability) {
+      _appendNullability(buffer);
+    }
+  }
+
   /**
    * Invokes [callback] for each parameter of [kind] with the parameter's [name]
    * and type after any type parameters have been applied.
@@ -2924,11 +2977,17 @@
    *
    * If the nullability of `this` already matches [nullabilitySuffix], `this`
    * is returned.
+   *
+   * Note: this method just does low-level manipulations of the underlying type,
+   * so it is what you want if you are constructing a fresh type and want it to
+   * have the correct nullability suffix, but it is generally *not* what you
+   * want if you're manipulating existing types.  For manipulating existing
+   * types, please use the methods in [TypeSystem].
    */
   TypeImpl withNullability(NullabilitySuffix nullabilitySuffix);
 
   void _appendNullability(StringBuffer buffer) {
-    if (isDynamic || isBottom || isVoid) {
+    if (isDynamic || isVoid) {
       // These types don't have nullability variations, so don't append
       // anything.
       return;
@@ -3181,7 +3240,21 @@
       return objectType;
     }
 
-    return element.bound.resolveToBound(objectType);
+    NullabilitySuffix newNullabilitySuffix;
+    if (nullabilitySuffix == NullabilitySuffix.question ||
+        (element.bound as TypeImpl).nullabilitySuffix ==
+            NullabilitySuffix.question) {
+      newNullabilitySuffix = NullabilitySuffix.question;
+    } else if (nullabilitySuffix == NullabilitySuffix.star ||
+        (element.bound as TypeImpl).nullabilitySuffix ==
+            NullabilitySuffix.star) {
+      newNullabilitySuffix = NullabilitySuffix.star;
+    } else {
+      newNullabilitySuffix = NullabilitySuffix.none;
+    }
+
+    return (element.bound.resolveToBound(objectType) as TypeImpl)
+        .withNullability(newNullabilitySuffix);
   }
 
   @override
@@ -3190,7 +3263,8 @@
       [List<FunctionTypeAliasElement> prune]) {
     int length = parameterTypes.length;
     for (int i = 0; i < length; i++) {
-      if (parameterTypes[i] == this) {
+      var parameterType = parameterTypes[i];
+      if (parameterType is TypeParameterTypeImpl && parameterType == this) {
         TypeImpl argumentType = argumentTypes[i];
 
         // TODO(scheglov) It should not happen, but sometimes arguments are null.
@@ -3200,15 +3274,29 @@
 
         // TODO(scheglov) Proposed substitution rules for nullability.
         NullabilitySuffix resultNullability;
+        NullabilitySuffix parameterNullability =
+            parameterType.nullabilitySuffix;
         NullabilitySuffix argumentNullability = argumentType.nullabilitySuffix;
-        if (argumentNullability == NullabilitySuffix.question ||
-            nullabilitySuffix == NullabilitySuffix.question) {
-          resultNullability = NullabilitySuffix.question;
-        } else if (argumentNullability == NullabilitySuffix.star ||
-            nullabilitySuffix == NullabilitySuffix.star) {
-          resultNullability = NullabilitySuffix.star;
+        if (parameterNullability == NullabilitySuffix.none) {
+          if (argumentNullability == NullabilitySuffix.question ||
+              nullabilitySuffix == NullabilitySuffix.question) {
+            resultNullability = NullabilitySuffix.question;
+          } else if (argumentNullability == NullabilitySuffix.star ||
+              nullabilitySuffix == NullabilitySuffix.star) {
+            resultNullability = NullabilitySuffix.star;
+          } else {
+            resultNullability = NullabilitySuffix.none;
+          }
+        } else if (parameterNullability == NullabilitySuffix.star) {
+          if (argumentNullability == NullabilitySuffix.question ||
+              nullabilitySuffix == NullabilitySuffix.question) {
+            resultNullability = NullabilitySuffix.question;
+          } else {
+            resultNullability = argumentNullability;
+          }
         } else {
-          resultNullability = NullabilitySuffix.none;
+          // We should never be substituting for `T?`.
+          throw new StateError('Tried to substitute for T?');
         }
 
         return argumentType.withNullability(resultNullability);
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index a4376d3..0b16500 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -571,7 +571,7 @@
   static const HintCode SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT = const HintCode(
       'SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT',
       "The use of an as expression in a constant expression wasn't "
-          "supported until version 2.2.2, but this code is required to be able "
+          "supported until version 2.3.2, but this code is required to be able "
           "to run on earlier versions.",
       correction: "Try updating the SDK constraints.");
 
@@ -582,7 +582,7 @@
   static const HintCode SDK_VERSION_BOOL_OPERATOR = const HintCode(
       'SDK_VERSION_BOOL_OPERATOR',
       "Using the operator '{0}' for 'bool's was not supported until version "
-          "2.2.2, but this code is required to be able to run on earlier versions.",
+          "2.3.2, but this code is required to be able to run on earlier versions.",
       correction: "Try updating the SDK constraints.");
 
   /**
@@ -592,7 +592,7 @@
   static const HintCode SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT = const HintCode(
       'SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT',
       "Using the operator '==' for non-primitive types was not supported until "
-          "version 2.2.2, but this code is required to be able to run on earlier "
+          "version 2.3.2, but this code is required to be able to run on earlier "
           "versions.",
       correction: "Try updating the SDK constraints.");
 
@@ -602,7 +602,7 @@
    */
   static const HintCode SDK_VERSION_GT_GT_GT_OPERATOR = const HintCode(
       'SDK_VERSION_GT_GT_GT_OPERATOR',
-      "The operator '>>>' was not supported until version 2.2.2, but this code "
+      "The operator '>>>' was not supported until version 2.3.2, but this code "
           "is required to be able to run on earlier versions.",
       correction: "Try updating the SDK constraints.");
 
@@ -613,7 +613,7 @@
   static const HintCode SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT = const HintCode(
       'SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT',
       "The use of an is expression in a constant expression wasn't "
-          "supported until version 2.2.2, but this code is required to be able "
+          "supported until version 2.3.2, but this code is required to be able "
           "to run on earlier versions.",
       correction: "Try updating the SDK constraints.");
 
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index 5110557..cec3fe1 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -51,8 +51,8 @@
   static const ParserErrorCode ASYNC_KEYWORD_USED_AS_IDENTIFIER =
       const ParserErrorCode(
           'ASYNC_KEYWORD_USED_AS_IDENTIFIER',
-          "The keywords 'async', 'await', and 'yield' can't be used as "
-          "identifiers in an asynchronous or generator function.");
+          "The keywords 'await' and 'yield' can't be used as "
+              "identifiers in an asynchronous or generator function.");
 
   static const ParserErrorCode BREAK_OUTSIDE_OF_LOOP = _BREAK_OUTSIDE_OF_LOOP;
 
@@ -109,7 +109,7 @@
   // TODO(danrubel): Remove this unused error code
   static const ParserErrorCode COVARIANT_AFTER_FINAL = _MODIFIER_OUT_OF_ORDER;
 
-  static const ParserErrorCode COVARIANT_AFTER_VAR = _COVARIANT_AFTER_VAR;
+  static const ParserErrorCode COVARIANT_AFTER_VAR = _MODIFIER_OUT_OF_ORDER;
 
   static const ParserErrorCode COVARIANT_AND_STATIC = _COVARIANT_AND_STATIC;
 
@@ -161,6 +161,8 @@
   static const ParserErrorCode EQUALITY_CANNOT_BE_EQUALITY_OPERAND =
       _EQUALITY_CANNOT_BE_EQUALITY_OPERAND;
 
+  static const ParserErrorCode EXPECTED_BODY = _EXPECTED_BODY;
+
   static const ParserErrorCode EXPECTED_CASE_OR_DEFAULT = const ParserErrorCode(
       'EXPECTED_CASE_OR_DEFAULT', "Expected 'case' or 'default'.",
       correction: "Try placing this code inside a case clause.");
@@ -202,11 +204,11 @@
   static const ParserErrorCode EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE =
       _EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE;
 
-  static const ParserErrorCode EXTERNAL_AFTER_CONST = _EXTERNAL_AFTER_CONST;
+  static const ParserErrorCode EXTERNAL_AFTER_CONST = _MODIFIER_OUT_OF_ORDER;
 
-  static const ParserErrorCode EXTERNAL_AFTER_FACTORY = _EXTERNAL_AFTER_FACTORY;
+  static const ParserErrorCode EXTERNAL_AFTER_FACTORY = _MODIFIER_OUT_OF_ORDER;
 
-  static const ParserErrorCode EXTERNAL_AFTER_STATIC = _EXTERNAL_AFTER_STATIC;
+  static const ParserErrorCode EXTERNAL_AFTER_STATIC = _MODIFIER_OUT_OF_ORDER;
 
   static const ParserErrorCode EXTERNAL_CLASS = _EXTERNAL_CLASS;
 
@@ -340,7 +342,7 @@
   static const ParserErrorCode INVALID_COMMENT_REFERENCE = const ParserErrorCode(
       'INVALID_COMMENT_REFERENCE',
       "Comment references should contain a possibly prefixed identifier and "
-      "can start with 'new', but shouldn't contain anything else.");
+          "can start with 'new', but shouldn't contain anything else.");
 
   static const ParserErrorCode INVALID_CONSTRUCTOR_NAME = const ParserErrorCode(
       'INVALID_CONSTRUCTOR_NAME',
@@ -415,11 +417,7 @@
   static const ParserErrorCode MISSING_CATCH_OR_FINALLY =
       _MISSING_CATCH_OR_FINALLY;
 
-  /// TODO(danrubel): Consider splitting this into two separate error messages.
-  static const ParserErrorCode MISSING_CLASS_BODY = const ParserErrorCode(
-      'MISSING_CLASS_BODY',
-      "A class or mixin definition must have a body, even if it is empty.",
-      correction: "Try adding a body to your class or mixin.");
+  static const ParserErrorCode MISSING_CLASS_BODY = _EXPECTED_BODY;
 
   static const ParserErrorCode MISSING_CLOSING_PARENTHESIS =
       const ParserErrorCode(
@@ -564,7 +562,7 @@
       const ParserErrorCode(
           'MULTIPLE_VARIABLES_IN_FOR_EACH',
           "A single loop variable must be declared in a for-each loop before "
-          "the 'in', but {0} were found.",
+              "the 'in', but {0} were found.",
           correction:
               "Try moving all but one of the declarations inside the loop body.");
 
@@ -588,14 +586,14 @@
       const ParserErrorCode(
           'NATIVE_CLAUSE_IN_NON_SDK_CODE',
           "Native clause can only be used in the SDK and code that is loaded "
-          "through native extensions.",
+              "through native extensions.",
           correction: "Try removing the native clause.");
 
   static const ParserErrorCode NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE =
       const ParserErrorCode(
           'NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE',
           "Native functions can only be declared in the SDK and code that is "
-          "loaded through native extensions.",
+              "loaded through native extensions.",
           correction: "Try removing the word 'native'.");
 
   static const ParserErrorCode NATIVE_CLAUSE_SHOULD_BE_ANNOTATION =
@@ -665,11 +663,11 @@
 
   static const ParserErrorCode STACK_OVERFLOW = _STACK_OVERFLOW;
 
-  static const ParserErrorCode STATIC_AFTER_CONST = _STATIC_AFTER_CONST;
+  static const ParserErrorCode STATIC_AFTER_CONST = _MODIFIER_OUT_OF_ORDER;
 
-  static const ParserErrorCode STATIC_AFTER_FINAL = _STATIC_AFTER_FINAL;
+  static const ParserErrorCode STATIC_AFTER_FINAL = _MODIFIER_OUT_OF_ORDER;
 
-  static const ParserErrorCode STATIC_AFTER_VAR = _STATIC_AFTER_VAR;
+  static const ParserErrorCode STATIC_AFTER_VAR = _MODIFIER_OUT_OF_ORDER;
 
   static const ParserErrorCode STATIC_CONSTRUCTOR = _STATIC_CONSTRUCTOR;
 
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
index 25c445b..80d4ee8b 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -15,7 +15,7 @@
   _EXTERNAL_ENUM,
   _PREFIX_AFTER_COMBINATOR,
   _TYPEDEF_IN_CLASS,
-  _COVARIANT_AFTER_VAR,
+  _EXPECTED_BODY,
   _INVALID_AWAIT_IN_FOR,
   _IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE,
   _WITH_BEFORE_EXTENDS,
@@ -25,9 +25,9 @@
   _SWITCH_HAS_MULTIPLE_DEFAULT_CASES,
   _SWITCH_HAS_CASE_AFTER_DEFAULT_CASE,
   _STATIC_OPERATOR,
-  _STATIC_AFTER_VAR,
-  _STATIC_AFTER_FINAL,
-  _STATIC_AFTER_CONST,
+  _INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER,
+  _STACK_OVERFLOW,
+  _MISSING_CATCH_OR_FINALLY,
   _REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR,
   _REDIRECTING_CONSTRUCTOR_WITH_BODY,
   _NATIVE_CLAUSE_SHOULD_BE_ANNOTATION,
@@ -53,9 +53,9 @@
   _IMPLEMENTS_BEFORE_ON,
   _IMPLEMENTS_BEFORE_EXTENDS,
   _ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE,
-  _EXTERNAL_AFTER_CONST,
-  _EXTERNAL_AFTER_FACTORY,
-  _EXTERNAL_AFTER_STATIC,
+  _EXPECTED_ELSE_OR_COMMA,
+  _INVALID_SUPER_IN_INITIALIZER,
+  _EXPERIMENT_NOT_ENABLED,
   _EXTERNAL_METHOD_WITH_BODY,
   _EXTERNAL_FIELD,
   _ABSTRACT_CLASS_MEMBER,
@@ -97,12 +97,6 @@
   _EXTERNAL_CONSTRUCTOR_WITH_BODY,
   _FIELD_INITIALIZED_OUTSIDE_DECLARING_CLASS,
   _VAR_AND_TYPE,
-  _INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER,
-  _STACK_OVERFLOW,
-  _MISSING_CATCH_OR_FINALLY,
-  _EXPERIMENT_NOT_ENABLED,
-  _EXPECTED_ELSE_OR_COMMA,
-  _INVALID_SUPER_IN_INITIALIZER,
 ];
 
 const ParserErrorCode _ABSTRACT_CLASS_MEMBER = const ParserErrorCode(
@@ -174,11 +168,6 @@
     correction:
         "Try adding a label associated with one of the case clauses to the continue statement.");
 
-const ParserErrorCode _COVARIANT_AFTER_VAR = const ParserErrorCode(
-    'COVARIANT_AFTER_VAR',
-    r"The modifier 'covariant' should be before the modifier 'var'.",
-    correction: "Try re-ordering the modifiers.");
-
 const ParserErrorCode _COVARIANT_AND_STATIC = const ParserErrorCode(
     'COVARIANT_AND_STATIC',
     r"Members can't be declared to be both 'covariant' and 'static'.",
@@ -227,6 +216,10 @@
     r"An equality expression can't be an operand of another equality expression.",
     correction: "Try re-writing the expression.");
 
+const ParserErrorCode _EXPECTED_BODY = const ParserErrorCode(
+    'EXPECTED_BODY', r"A #string must have a body, even if it is empty.",
+    correction: "Try adding an empty body.");
+
 const ParserErrorCode _EXPECTED_ELSE_OR_COMMA = const ParserErrorCode(
     'EXPECTED_ELSE_OR_COMMA', r"Expected 'else' or comma.");
 
@@ -245,21 +238,6 @@
         correction:
             "Try moving the export directives before the part directives.");
 
-const ParserErrorCode _EXTERNAL_AFTER_CONST = const ParserErrorCode(
-    'EXTERNAL_AFTER_CONST',
-    r"The modifier 'external' should be before the modifier 'const'.",
-    correction: "Try re-ordering the modifiers.");
-
-const ParserErrorCode _EXTERNAL_AFTER_FACTORY = const ParserErrorCode(
-    'EXTERNAL_AFTER_FACTORY',
-    r"The modifier 'external' should be before the modifier 'factory'.",
-    correction: "Try re-ordering the modifiers.");
-
-const ParserErrorCode _EXTERNAL_AFTER_STATIC = const ParserErrorCode(
-    'EXTERNAL_AFTER_STATIC',
-    r"The modifier 'external' should be before the modifier 'static'.",
-    correction: "Try re-ordering the modifiers.");
-
 const ParserErrorCode _EXTERNAL_CLASS = const ParserErrorCode(
     'EXTERNAL_CLASS', r"Classes can't be declared to be 'external'.",
     correction: "Try removing the keyword 'external'.");
@@ -492,21 +470,6 @@
     r"The file has too many nested expressions or statements.",
     correction: "Try simplifying the code.");
 
-const ParserErrorCode _STATIC_AFTER_CONST = const ParserErrorCode(
-    'STATIC_AFTER_CONST',
-    r"The modifier 'static' should be before the modifier 'const'.",
-    correction: "Try re-ordering the modifiers.");
-
-const ParserErrorCode _STATIC_AFTER_FINAL = const ParserErrorCode(
-    'STATIC_AFTER_FINAL',
-    r"The modifier 'static' should be before the modifier 'final'.",
-    correction: "Try re-ordering the modifiers.");
-
-const ParserErrorCode _STATIC_AFTER_VAR = const ParserErrorCode(
-    'STATIC_AFTER_VAR',
-    r"The modifier 'static' should be before the modifier 'var'.",
-    correction: "Try re-ordering the modifiers.");
-
 const ParserErrorCode _STATIC_CONSTRUCTOR = const ParserErrorCode(
     'STATIC_CONSTRUCTOR', r"Constructors can't be static.",
     correction: "Try removing the keyword 'static'.");
diff --git a/pkg/analyzer/lib/src/dart/resolver/variance.dart b/pkg/analyzer/lib/src/dart/resolver/variance.dart
new file mode 100644
index 0000000..69bc580
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/variance.dart
@@ -0,0 +1,112 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+
+/// Computes the variance of the [typeParameter] in the [type].
+int computeVariance(TypeParameterElement typeParameter, DartType type) {
+  if (type is TypeParameterType) {
+    if (type.element == typeParameter) {
+      return Variance.covariant;
+    } else {
+      return Variance.unrelated;
+    }
+  } else if (type is InterfaceType) {
+    var result = Variance.unrelated;
+    for (var argument in type.typeArguments) {
+      result = Variance.meet(
+        result,
+        computeVariance(typeParameter, argument),
+      );
+    }
+    return result;
+  } else if (type is FunctionType) {
+    var result = computeVariance(typeParameter, type.returnType);
+
+    for (var parameter in type.typeFormals) {
+      // If [parameter] is referenced in the bound at all, it makes the
+      // variance of [parameter] in the entire type invariant.  The invocation
+      // of [computeVariance] below is made to simply figure out if [variable]
+      // occurs in the bound.
+      var bound = parameter.bound;
+      if (bound != null &&
+          computeVariance(typeParameter, bound) != Variance.unrelated) {
+        result = Variance.invariant;
+      }
+    }
+
+    for (var parameter in type.parameters) {
+      result = Variance.meet(
+        result,
+        Variance.combine(
+          Variance.contravariant,
+          computeVariance(typeParameter, parameter.type),
+        ),
+      );
+    }
+    return result;
+  }
+  return Variance.unrelated;
+}
+
+/// Value set for variance of a type parameter `X` in a type `T`.
+class Variance {
+  /// Used when `X` does not occur free in `T`.
+  static const int unrelated = 0;
+
+  /// Used when `X` occurs free in `T`, and `U <: V` implies `[U/X]T <: [V/X]T`.
+  static const int covariant = 1;
+
+  /// Used when `X` occurs free in `T`, and `U <: V` implies `[V/X]T <: [U/X]T`.
+  static const int contravariant = 2;
+
+  /// Used when there exists a pair `U` and `V` such that `U <: V`, but
+  /// `[U/X]T` and `[V/X]T` are incomparable.
+  static const int invariant = 3;
+
+  /// Combines variances of `X` in `T` and `Y` in `S` into variance of `X` in
+  /// `[Y/T]S`.
+  ///
+  /// Consider the following examples:
+  ///
+  /// * variance of `X` in `Function(X)` is [contravariant], variance of `Y`
+  /// in `List<Y>` is [covariant], so variance of `X` in `List<Function(X)>` is
+  /// [contravariant];
+  ///
+  /// * variance of `X` in `List<X>` is [covariant], variance of `Y` in
+  /// `Function(Y)` is [contravariant], so variance of `X` in
+  /// `Function(List<X>)` is [contravariant];
+  ///
+  /// * variance of `X` in `Function(X)` is [contravariant], variance of `Y` in
+  /// `Function(Y)` is [contravariant], so variance of `X` in
+  /// `Function(Function(X))` is [covariant];
+  ///
+  /// * let the following be declared:
+  ///
+  ///     typedef F<Z> = Function();
+  ///
+  /// then variance of `X` in `F<X>` is [unrelated], variance of `Y` in
+  /// `List<Y>` is [covariant], so variance of `X` in `List<F<X>>` is
+  /// [unrelated];
+  ///
+  /// * let the following be declared:
+  ///
+  ///     typedef G<Z> = Z Function(Z);
+  ///
+  /// then variance of `X` in `List<X>` is [covariant], variance of `Y` in
+  /// `G<Y>` is [invariant], so variance of `X` in `G<List<X>>` is [invariant].
+  static int combine(int a, int b) {
+    if (a == unrelated || b == unrelated) return unrelated;
+    if (a == invariant || b == invariant) return invariant;
+    return a == b ? covariant : contravariant;
+  }
+
+  /// Variance values form a lattice where [unrelated] is the top, [invariant]
+  /// is the bottom, and [covariant] and [contravariant] are incomparable.
+  /// [meet] calculates the meet of two elements of such lattice.  It can be
+  /// used, for example, to calculate the variance of a typedef type parameter
+  /// if it's encountered on the RHS of the typedef multiple times.
+  static int meet(int a, int b) => a | b;
+}
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 8a3e142..5b05f7a 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -2880,6 +2880,20 @@
           "Setters should declare exactly one required parameter.");
 
   /**
+   * Let `C` be a generic class that declares a formal type parameter `X`, and
+   * assume that `T` is a direct superinterface of `C`. It is a compile-time
+   * error if `X` occurs contravariantly or invariantly in `T`.
+   */
+  static const CompileTimeErrorCode
+      WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE =
+      const CompileTimeErrorCode(
+    'WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE',
+    "'{0}' can't be used contravariantly or invariantly in '{1}'.",
+    correction: "Try not using class type parameters in types of formal "
+        "parameters of function types.",
+  );
+
+  /**
    * ?? Yield: It is a compile-time error if a yield statement appears in a
    * function that is not a generator function.
    */
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index d120057..4edfcba 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -37,6 +38,7 @@
           typeProvider: _typeProvider,
           inheritance: _inheritance,
           reporter: _reporter,
+          featureSet: unit.featureSet,
           library: library,
           classNameNode: declaration.name,
           implementsClause: declaration.implementsClause,
@@ -50,6 +52,7 @@
           typeProvider: _typeProvider,
           inheritance: _inheritance,
           reporter: _reporter,
+          featureSet: unit.featureSet,
           library: library,
           classNameNode: declaration.name,
           implementsClause: declaration.implementsClause,
@@ -62,6 +65,7 @@
           typeProvider: _typeProvider,
           inheritance: _inheritance,
           reporter: _reporter,
+          featureSet: unit.featureSet,
           library: library,
           classNameNode: declaration.name,
           implementsClause: declaration.implementsClause,
@@ -85,6 +89,7 @@
   final InheritanceManager2 inheritance;
   final ErrorReporter reporter;
 
+  final FeatureSet featureSet;
   final LibraryElement library;
   final Uri libraryUri;
   final ClassElementImpl classElement;
@@ -108,6 +113,7 @@
     this.typeProvider,
     this.inheritance,
     this.reporter,
+    this.featureSet,
     this.library,
     this.classNameNode,
     this.implementsClause,
@@ -382,7 +388,8 @@
         if (setter != null && setter.parameters.length == 1) {
           var getterType = getter.returnType;
           var setterType = setter.parameters[0].type;
-          if (!typeSystem.isAssignableTo(getterType, setterType)) {
+          if (!typeSystem.isAssignableTo(getterType, setterType,
+              featureSet: featureSet)) {
             var getterElement = getter.element;
             var setterElement = setter.element;
 
diff --git a/pkg/analyzer/lib/src/error/literal_element_verifier.dart b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
index 89dcdce..ba32987 100644
--- a/pkg/analyzer/lib/src/error/literal_element_verifier.dart
+++ b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -15,6 +16,7 @@
   final TypeProvider typeProvider;
   final TypeSystem typeSystem;
   final ErrorReporter errorReporter;
+  final FeatureSet featureSet;
   final bool Function(Expression) checkForUseOfVoidResult;
 
   final bool forList;
@@ -36,6 +38,7 @@
     this.forMap = false,
     this.mapKeyType,
     this.mapValueType,
+    this.featureSet,
   });
 
   void verify(CollectionElement element) {
@@ -45,7 +48,7 @@
   /// Check that the given [type] is assignable to the [elementType], otherwise
   /// report the list or set error on the [errorNode].
   void _checkAssignableToElementType(DartType type, AstNode errorNode) {
-    if (!typeSystem.isAssignableTo(type, elementType)) {
+    if (!typeSystem.isAssignableTo(type, elementType, featureSet: featureSet)) {
       var errorCode = forList
           ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
           : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
@@ -106,7 +109,8 @@
     }
 
     var keyType = entry.key.staticType;
-    if (!typeSystem.isAssignableTo(keyType, mapKeyType)) {
+    if (!typeSystem.isAssignableTo(keyType, mapKeyType,
+        featureSet: featureSet)) {
       errorReporter.reportTypeErrorForNode(
         StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
         entry.key,
@@ -115,7 +119,8 @@
     }
 
     var valueType = entry.value.staticType;
-    if (!typeSystem.isAssignableTo(valueType, mapValueType)) {
+    if (!typeSystem.isAssignableTo(valueType, mapValueType,
+        featureSet: featureSet)) {
       errorReporter.reportTypeErrorForNode(
         StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
         entry.value,
@@ -157,7 +162,8 @@
     }
 
     var iterableElementType = iterableType.typeArguments[0];
-    if (!typeSystem.isAssignableTo(iterableElementType, elementType)) {
+    if (!typeSystem.isAssignableTo(iterableElementType, elementType,
+        featureSet: featureSet)) {
       var errorCode = forList
           ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
           : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
@@ -200,7 +206,8 @@
     }
 
     var keyType = mapType.typeArguments[0];
-    if (!typeSystem.isAssignableTo(keyType, mapKeyType)) {
+    if (!typeSystem.isAssignableTo(keyType, mapKeyType,
+        featureSet: featureSet)) {
       errorReporter.reportTypeErrorForNode(
         StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
         expression,
@@ -209,7 +216,8 @@
     }
 
     var valueType = mapType.typeArguments[1];
-    if (!typeSystem.isAssignableTo(valueType, mapValueType)) {
+    if (!typeSystem.isAssignableTo(valueType, mapValueType,
+        featureSet: featureSet)) {
       errorReporter.reportTypeErrorForNode(
         StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
         expression,
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index df9bd69..2d4fad3 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -12,8 +12,8 @@
 import 'package:analyzer/src/dart/ast/ast.dart'
     show
         ClassDeclarationImpl,
-        ClassOrMixinDeclarationImpl,
         CompilationUnitImpl,
+        ExtensionDeclarationImpl,
         MixinDeclarationImpl;
 import 'package:analyzer/src/fasta/error_converter.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -86,6 +86,9 @@
   /// The mixin currently being parsed, or `null` if no mixin is being parsed.
   MixinDeclarationImpl mixinDeclaration;
 
+  /// The extension currently being parsed, or `null` if none.
+  ExtensionDeclarationImpl extensionDeclaration;
+
   /// If true, this is building a full AST. Otherwise, only create method
   /// bodies.
   final bool isFullAst;
@@ -127,6 +130,26 @@
       : this.errorReporter = new FastaErrorReporter(errorReporter),
         uri = uri ?? fileUri;
 
+  NodeList<ClassMember> get currentDeclarationMembers {
+    if (classDeclaration != null) {
+      return classDeclaration.members;
+    } else if (mixinDeclaration != null) {
+      return mixinDeclaration.members;
+    } else {
+      return extensionDeclaration.members;
+    }
+  }
+
+  SimpleIdentifier get currentDeclarationName {
+    if (classDeclaration != null) {
+      return classDeclaration.name;
+    } else if (mixinDeclaration != null) {
+      return mixinDeclaration.name;
+    } else {
+      return extensionDeclaration.name;
+    }
+  }
+
   @override
   void addProblem(Message message, int charOffset, int length,
       {bool wasHandled: false, List<LocatedMessage> context}) {
@@ -155,7 +178,9 @@
 
   @override
   void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
-    assert(classDeclaration == null && mixinDeclaration == null);
+    assert(classDeclaration == null &&
+        mixinDeclaration == null &&
+        extensionDeclaration == null);
     push(new _Modifiers()..abstractKeyword = abstractToken);
   }
 
@@ -165,6 +190,30 @@
   }
 
   @override
+  void beginExtensionDeclaration(Token extensionKeyword, Token nameToken) {
+    assert(optional('extension', extensionKeyword));
+    assert(classDeclaration == null &&
+        mixinDeclaration == null &&
+        extensionDeclaration == null);
+    debugEvent("ExtensionHeader");
+
+    TypeParameterList typeParameters = pop();
+    SimpleIdentifier name = pop();
+    List<Annotation> metadata = pop();
+    Comment comment = _findComment(metadata, extensionKeyword);
+
+    extensionDeclaration = ast.extensionDeclaration(
+      comment: comment,
+      metadata: metadata,
+      name: name,
+      typeParameters: typeParameters,
+      extendedType: null, // extendedType is set in [endExtensionDeclaration]
+    ) as ExtensionDeclarationImpl;
+
+    declarations.add(extensionDeclaration);
+  }
+
+  @override
   void beginFactoryMethod(
       Token lastConsumed, Token externalToken, Token constToken) {
     push(new _Modifiers()
@@ -234,7 +283,9 @@
 
   @override
   void beginMixinDeclaration(Token mixinKeyword, Token name) {
-    assert(classDeclaration == null && mixinDeclaration == null);
+    assert(classDeclaration == null &&
+        mixinDeclaration == null &&
+        extensionDeclaration == null);
   }
 
   @override
@@ -481,14 +532,25 @@
   @override
   void endClassOrMixinBody(
       int memberCount, Token leftBracket, Token rightBracket) {
+    // TODO(danrubel): consider renaming endClassOrMixinBody
+    // to endClassOrMixinOrExtensionBody
     assert(optional('{', leftBracket));
     assert(optional('}', rightBracket));
     debugEvent("ClassOrMixinBody");
 
-    ClassOrMixinDeclarationImpl declaration =
-        classDeclaration ?? mixinDeclaration;
-    declaration.leftBracket = leftBracket;
-    declaration.rightBracket = rightBracket;
+    if (classDeclaration != null) {
+      classDeclaration
+        ..leftBracket = leftBracket
+        ..rightBracket = rightBracket;
+    } else if (mixinDeclaration != null) {
+      mixinDeclaration
+        ..leftBracket = leftBracket
+        ..rightBracket = rightBracket;
+    } else {
+      extensionDeclaration
+        ..leftBracket = leftBracket
+        ..rightBracket = rightBracket;
+    }
   }
 
   @override
@@ -643,6 +705,15 @@
   }
 
   @override
+  void endExtensionDeclaration(Token onKeyword, Token token) {
+    TypeAnnotation type = pop();
+    extensionDeclaration
+      ..extendedType = type
+      ..onKeyword = onKeyword;
+    extensionDeclaration = null;
+  }
+
+  @override
   void endFactoryMethod(
       Token beginToken, Token factoryKeyword, Token endToken) {
     assert(optional('factory', factoryKeyword));
@@ -694,21 +765,20 @@
           ast.simpleIdentifier(typeName.identifier.token, isDeclaration: true);
     }
 
-    (classDeclaration ?? mixinDeclaration).members.add(
-        ast.constructorDeclaration(
-            comment,
-            metadata,
-            modifiers?.externalKeyword,
-            modifiers?.finalConstOrVarKeyword,
-            factoryKeyword,
-            ast.simpleIdentifier(returnType.token),
-            period,
-            name,
-            parameters,
-            separator,
-            null,
-            redirectedConstructor,
-            body));
+    currentDeclarationMembers.add(ast.constructorDeclaration(
+        comment,
+        metadata,
+        modifiers?.externalKeyword,
+        modifiers?.finalConstOrVarKeyword,
+        factoryKeyword,
+        ast.simpleIdentifier(returnType.token),
+        period,
+        name,
+        parameters,
+        separator,
+        null,
+        redirectedConstructor,
+        body));
   }
 
   void endFieldInitializer(Token assignment, Token token) {
@@ -737,7 +807,7 @@
     Token covariantKeyword = covariantToken;
     List<Annotation> metadata = pop();
     Comment comment = _findComment(metadata, beginToken);
-    (classDeclaration ?? mixinDeclaration).members.add(ast.fieldDeclaration2(
+    currentDeclarationMembers.add(ast.fieldDeclaration2(
         comment: comment,
         metadata: metadata,
         covariantKeyword: covariantKeyword,
@@ -1415,9 +1485,6 @@
           beginToken.charOffset, uri);
     }
 
-    ClassOrMixinDeclarationImpl declaration =
-        classDeclaration ?? mixinDeclaration;
-
     void constructor(
         SimpleIdentifier prefixOrName, Token period, SimpleIdentifier name) {
       if (typeParameters != null) {
@@ -1453,7 +1520,7 @@
           initializers,
           redirectedConstructor,
           body);
-      declaration.members.add(constructor);
+      currentDeclarationMembers.add(constructor);
       if (mixinDeclaration != null) {
         // TODO (danrubel): Report an error if this is a mixin declaration.
       }
@@ -1466,7 +1533,7 @@
             messageConstMethod, modifiers.constKeyword, modifiers.constKeyword);
       }
       checkFieldFormalParameters(parameters);
-      declaration.members.add(ast.methodDeclaration(
+      currentDeclarationMembers.add(ast.methodDeclaration(
           comment,
           metadata,
           modifiers?.externalKeyword,
@@ -1481,9 +1548,9 @@
     }
 
     if (name is SimpleIdentifier) {
-      if (name.name == declaration.name.name && getOrSet == null) {
+      if (name.name == currentDeclarationName.name && getOrSet == null) {
         constructor(name, null, null);
-      } else if (initializers.isNotEmpty) {
+      } else if (initializers.isNotEmpty && getOrSet == null) {
         constructor(name, null, null);
       } else {
         method(null, name);
@@ -1941,8 +2008,7 @@
     }
   }
 
-  void finishFunction(
-      List annotations, formals, AsyncMarker asyncModifier, FunctionBody body) {
+  void finishFunction(formals, AsyncMarker asyncModifier, FunctionBody body) {
     debugEvent("finishFunction");
 
     Statement bodyStatement;
@@ -2291,10 +2357,7 @@
       if (variableOrDeclaration is! SimpleIdentifier) {
         // Parser has already reported the error.
         if (!leftParenthesis.next.isIdentifier) {
-          parser.rewriter.insertToken(
-              leftParenthesis,
-              new SyntheticStringToken(
-                  TokenType.IDENTIFIER, '', leftParenthesis.next.charOffset));
+          parser.rewriter.insertSyntheticIdentifier(leftParenthesis);
         }
         variableOrDeclaration = ast.simpleIdentifier(leftParenthesis.next);
       }
@@ -2686,7 +2749,9 @@
   @override
   void handleMixinHeader(Token mixinKeyword) {
     assert(optional('mixin', mixinKeyword));
-    assert(classDeclaration == null && mixinDeclaration == null);
+    assert(classDeclaration == null &&
+        mixinDeclaration == null &&
+        extensionDeclaration == null);
     debugEvent("MixinHeader");
 
     ImplementsClause implementsClause = pop(NullValue.IdentifierList);
diff --git a/pkg/analyzer/lib/src/fasta/error_converter.dart b/pkg/analyzer/lib/src/fasta/error_converter.dart
index 16f6f09..132cb54 100644
--- a/pkg/analyzer/lib/src/fasta/error_converter.dart
+++ b/pkg/analyzer/lib/src/fasta/error_converter.dart
@@ -205,10 +205,6 @@
         errorReporter?.reportErrorForOffset(
             StrongModeCode.INVALID_SUPER_INVOCATION, offset, length);
         return;
-      case "MISSING_CLASS_BODY":
-        errorReporter?.reportErrorForOffset(
-            ParserErrorCode.MISSING_CLASS_BODY, offset, length);
-        return;
       case "MISSING_DIGIT":
         errorReporter?.reportErrorForOffset(
             ScannerErrorCode.MISSING_DIGIT, offset, length);
diff --git a/pkg/analyzer/lib/src/generated/declaration_resolver.dart b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
index 16e265d..e336eb9 100644
--- a/pkg/analyzer/lib/src/generated/declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
@@ -245,6 +245,9 @@
     _setGenericFunctionType(node.returnType, element.returnType);
     (node.functionExpression as FunctionExpressionImpl).declaredElement =
         element;
+    if (AnalysisDriver.useSummary2 && _enclosingUnit.linkedContext != null) {
+      node.returnType?.accept(this);
+    }
     _walker._elementHolder?.addFunction(element);
     _walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
       super.visitFunctionDeclaration(node);
@@ -378,6 +381,9 @@
       }
     }
     _setGenericFunctionType(node.returnType, element.returnType);
+    if (AnalysisDriver.useSummary2 && _enclosingUnit.linkedContext != null) {
+      node.returnType?.accept(this);
+    }
     _walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
       super.visitMethodDeclaration(node);
     });
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index a5e2927..3791919 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -22,6 +22,7 @@
 import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/error/literal_element_verifier.dart';
@@ -291,7 +292,8 @@
   /// fixed.
   final bool disableConflictingGenericsCheck;
 
-  bool _isNonNullable = false;
+  /// The features enabled in the unit currently being checked for errors.
+  FeatureSet _featureSet;
 
   /**
    * Initialize a newly created error verifier.
@@ -343,6 +345,9 @@
     _enclosingClass = classElement;
   }
 
+  bool get _isNonNullable =>
+      _featureSet?.isEnabled(Feature.non_nullable) ?? false;
+
   @override
   void visitAnnotation(Annotation node) {
     _checkForInvalidAnnotationFromDeferredLibrary(node);
@@ -415,9 +420,10 @@
       _checkForUseOfVoidResult(node.rightOperand);
       _checkForNullableDereference(node.leftOperand);
       _checkForNullableDereference(node.rightOperand);
-    } else if (type != TokenType.EQ_EQ &&
-        type != TokenType.BANG_EQ &&
-        type != TokenType.QUESTION_QUESTION) {
+    } else if (type == TokenType.EQ_EQ || type == TokenType.BANG_EQ) {
+      _checkForArgumentTypeNotAssignableForArgument(node.rightOperand,
+          promoteParameterToNullable: true);
+    } else if (type != TokenType.QUESTION_QUESTION) {
       _checkForArgumentTypeNotAssignableForArgument(node.rightOperand);
       _checkForNullableDereference(node.leftOperand);
     } else {
@@ -523,6 +529,7 @@
       _initializeInitialFieldElementsMap(_enclosingClass.fields);
       _checkForFinalNotInitializedInClass(members);
       _checkForBadFunctionUse(node);
+      _checkForWrongTypeParameterVarianceInSuperinterfaces();
       super.visitClassDeclaration(node);
     } finally {
       _isInNativeClass = false;
@@ -540,6 +547,7 @@
       _enclosingClass = AbstractClassElementImpl.getImpl(node.declaredElement);
       _checkClassInheritance(
           node, node.superclass, node.withClause, node.implementsClause);
+      _checkForWrongTypeParameterVarianceInSuperinterfaces();
     } finally {
       _enclosingClass = outerClassElement;
     }
@@ -558,11 +566,11 @@
 
   @override
   void visitCompilationUnit(CompilationUnit node) {
-    _isNonNullable = node.featureSet.isEnabled(Feature.non_nullable);
+    _featureSet = node.featureSet;
     _checkDuplicateUnitMembers(node);
     _checkForDeferredPrefixCollisions(node);
     super.visitCompilationUnit(node);
-    _isNonNullable = false;
+    _featureSet = null;
   }
 
   @override
@@ -1101,6 +1109,7 @@
 
       _initializeInitialFieldElementsMap(_enclosingClass.fields);
       _checkForFinalNotInitializedInClass(members);
+      _checkForWrongTypeParameterVarianceInSuperinterfaces();
       //      _checkForBadFunctionUse(node);
       super.visitMixinDeclaration(node);
     } finally {
@@ -2103,8 +2112,8 @@
     FunctionType constructorType =
         resolutionMap.elementDeclaredByConstructorDeclaration(declaration).type;
     DartType constructorReturnType = constructorType.returnType;
-    if (!_typeSystem.isAssignableTo(
-        redirectedReturnType, constructorReturnType)) {
+    if (!_typeSystem.isAssignableTo(redirectedReturnType, constructorReturnType,
+        featureSet: _featureSet)) {
       _errorReporter.reportErrorForNode(
           StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE,
           redirectedConstructor,
@@ -2256,13 +2265,17 @@
    *
    * See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
    */
-  void _checkForArgumentTypeNotAssignableForArgument(Expression argument) {
+  void _checkForArgumentTypeNotAssignableForArgument(Expression argument,
+      {bool promoteParameterToNullable = false}) {
     if (argument == null) {
       return;
     }
 
     ParameterElement staticParameterElement = argument.staticParameterElement;
     DartType staticParameterType = staticParameterElement?.type;
+    if (promoteParameterToNullable && staticParameterType != null) {
+      staticParameterType = _typeSystem.makeNullable(staticParameterType);
+    }
     _checkForArgumentTypeNotAssignableWithExpectedTypes(argument,
         staticParameterType, StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
   }
@@ -2323,7 +2336,8 @@
     if (expressionType == null) {
       return;
     }
-    if (_typeSystem.isAssignableTo(expressionType, type)) {
+    if (_typeSystem.isAssignableTo(expressionType, type,
+        featureSet: _featureSet)) {
       return;
     }
     _errorReporter.reportErrorForNode(errorCode, expression, arguments);
@@ -2342,7 +2356,8 @@
       DartType actualStaticType,
       DartType expectedStaticType,
       ErrorCode errorCode) {
-    if (!_typeSystem.isAssignableTo(actualStaticType, expectedStaticType)) {
+    if (!_typeSystem.isAssignableTo(actualStaticType, expectedStaticType,
+        featureSet: _featureSet)) {
       _errorReporter.reportTypeErrorForNode(
           errorCode, expression, [actualStaticType, expectedStaticType]);
       return false;
@@ -3049,7 +3064,8 @@
           StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE,
           node.iterable,
           [iterableType, loopTypeName]);
-    } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType)) {
+    } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType,
+        featureSet: _featureSet)) {
       _errorReporter.reportTypeErrorForNode(
           StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE,
           node.iterable,
@@ -3223,7 +3239,8 @@
     if (staticType == null) {
       return;
     }
-    if (_typeSystem.isAssignableTo(staticType, fieldType)) {
+    if (_typeSystem.isAssignableTo(staticType, fieldType,
+        featureSet: _featureSet)) {
       return;
     }
     // report problem
@@ -3847,7 +3864,8 @@
     }
     DartType leftType = getStaticType(lhs);
     DartType rightType = getStaticType(assignment);
-    if (!_typeSystem.isAssignableTo(rightType, leftType)) {
+    if (!_typeSystem.isAssignableTo(rightType, leftType,
+        featureSet: _featureSet)) {
       _errorReporter.reportTypeErrorForNode(
           StaticTypeWarningCode.INVALID_ASSIGNMENT, rhs, [rightType, leftType]);
     }
@@ -3960,6 +3978,7 @@
       _checkForUseOfVoidResult,
       forList: true,
       elementType: listElementType,
+      featureSet: _featureSet,
     );
     for (CollectionElement element in literal.elements) {
       verifier.verify(element);
@@ -3995,6 +4014,7 @@
         forMap: true,
         mapKeyType: keyType,
         mapValueType: valueType,
+        featureSet: _featureSet,
       );
       for (CollectionElement element in literal.elements) {
         verifier.verify(element);
@@ -4069,7 +4089,8 @@
       // (if the getter is null, it is dynamic which is assignable to everything).
       if (setterType != null &&
           getterType != null &&
-          !_typeSystem.isAssignableTo(getterType, setterType)) {
+          !_typeSystem.isAssignableTo(getterType, setterType,
+              featureSet: _featureSet)) {
         _errorReporter.reportTypeErrorForNode(
             StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES,
             accessorDeclaration,
@@ -4539,7 +4560,8 @@
     if (!_checkForNullableDereference(condition) &&
         !_checkForUseOfVoidResult(condition) &&
         conditionType != null &&
-        !_typeSystem.isAssignableTo(conditionType, _boolType)) {
+        !_typeSystem.isAssignableTo(conditionType, _boolType,
+            featureSet: _featureSet)) {
       _errorReporter.reportErrorForNode(
           StaticTypeWarningCode.NON_BOOL_CONDITION, condition);
     }
@@ -4555,7 +4577,8 @@
     Expression expression = assertion.condition;
     DartType type = getStaticType(expression);
     if (type is InterfaceType) {
-      if (!_typeSystem.isAssignableTo(type, _boolType)) {
+      if (!_typeSystem.isAssignableTo(type, _boolType,
+          featureSet: _featureSet)) {
         _errorReporter.reportErrorForNode(
             StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression);
       }
@@ -4573,7 +4596,8 @@
   void _checkForNonBoolNegationExpression(Expression expression) {
     DartType conditionType = getStaticType(expression);
     if (conditionType != null &&
-        !_typeSystem.isAssignableTo(conditionType, _boolType)) {
+        !_typeSystem.isAssignableTo(conditionType, _boolType,
+            featureSet: _featureSet)) {
       _errorReporter.reportErrorForNode(
           StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION, expression);
     }
@@ -4660,8 +4684,8 @@
     if (expression == null ||
         !_isNonNullable ||
         expression.staticType == null ||
-        (expression.staticType as TypeImpl).nullabilitySuffix !=
-            NullabilitySuffix.question) {
+        expression.staticType.isDynamic ||
+        !_typeSystem.isPotentiallyNullable(expression.staticType)) {
       return false;
     }
 
@@ -5162,7 +5186,8 @@
       var checkWithType = (!_inAsync)
           ? fromType
           : _typeProvider.futureType.instantiate(<DartType>[fromType]);
-      if (_typeSystem.isAssignableTo(checkWithType, expectedType)) {
+      if (_typeSystem.isAssignableTo(checkWithType, expectedType,
+          featureSet: _featureSet)) {
         return;
       }
     }
@@ -5200,6 +5225,7 @@
         _checkForUseOfVoidResult,
         forSet: true,
         elementType: setElementType,
+        featureSet: _featureSet,
       );
       for (CollectionElement element in literal.elements) {
         verifier.verify(element);
@@ -5266,7 +5292,8 @@
     DartType caseType = getStaticType(caseExpression);
 
     // check types
-    if (!_typeSystem.isAssignableTo(expressionType, caseType)) {
+    if (!_typeSystem.isAssignableTo(expressionType, caseType,
+        featureSet: _featureSet)) {
       _errorReporter.reportErrorForNode(
           StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE,
           expression,
@@ -5592,7 +5619,8 @@
                 [parameter.identifier.name]);
           } else if (declaredType != null &&
               fieldType != null &&
-              !_typeSystem.isAssignableTo(declaredType, fieldType)) {
+              !_typeSystem.isAssignableTo(declaredType, fieldType,
+                  featureSet: _featureSet)) {
             _errorReporter.reportTypeErrorForNode(
                 StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE,
                 parameter,
@@ -5703,6 +5731,30 @@
     }
   }
 
+  void _checkForWrongTypeParameterVarianceInSuperinterfaces() {
+    void checkOne(DartType superInterface) {
+      if (superInterface != null) {
+        for (var typeParameter in _enclosingClass.typeParameters) {
+          var variance = computeVariance(typeParameter, superInterface);
+          if (variance == Variance.contravariant ||
+              variance == Variance.invariant) {
+            _errorReporter.reportErrorForElement(
+              CompileTimeErrorCode
+                  .WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+              typeParameter,
+              [typeParameter.name, superInterface],
+            );
+          }
+        }
+      }
+    }
+
+    checkOne(_enclosingClass.supertype);
+    _enclosingClass.interfaces.forEach(checkOne);
+    _enclosingClass.mixins.forEach(checkOne);
+    _enclosingClass.superclassConstraints.forEach(checkOne);
+  }
+
   /**
    * Check for a type mis-match between the yielded type and the declared
    * return type of a generator function.
@@ -5741,7 +5793,8 @@
       } else {
         requiredReturnType = _typeProvider.iterableDynamicType;
       }
-      if (!_typeSystem.isAssignableTo(impliedReturnType, requiredReturnType)) {
+      if (!_typeSystem.isAssignableTo(impliedReturnType, requiredReturnType,
+          featureSet: _featureSet)) {
         _errorReporter.reportTypeErrorForNode(
             StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
             yieldExpression,
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 21a62ae..d494c4e 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -6976,8 +6976,7 @@
   SimpleIdentifier _parseSimpleIdentifierUnchecked(
       {bool isDeclaration: false}) {
     String lexeme = _currentToken.lexeme;
-    if ((_inAsync || _inGenerator) &&
-        (lexeme == ASYNC || lexeme == _AWAIT || lexeme == _YIELD)) {
+    if ((_inAsync || _inGenerator) && (lexeme == _AWAIT || lexeme == _YIELD)) {
       _reportErrorForCurrentToken(
           ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER);
     }
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index f66ceb7..91657b9 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -92,15 +92,6 @@
         InstanceCreationExpression instanceCreationExpression =
             astFactory.instanceCreationExpression(
                 _getKeyword(node), constructorName, node.argumentList);
-        InterfaceType type = getType(typeSystem, element, node.typeArguments);
-        ConstructorElement constructorElement =
-            type.lookUpConstructor(null, definingLibrary);
-        methodName.staticElement = element;
-        methodName.staticType = type;
-        typeName.type = type;
-        constructorName.staticElement = constructorElement;
-        instanceCreationExpression.staticType = type;
-        instanceCreationExpression.staticElement = constructorElement;
         NodeReplacer.replace(node, instanceCreationExpression);
       }
     } else if (target is SimpleIdentifier) {
@@ -130,17 +121,6 @@
               astFactory.instanceCreationExpression(
                   _getKeyword(node), constructorName, node.argumentList,
                   typeArguments: typeArguments);
-          InterfaceType type = getType(typeSystem, element, null);
-          constructorElement =
-              type.lookUpConstructor(methodName.name, definingLibrary);
-          methodName.staticElement = element;
-          methodName.staticType = type;
-          target.staticElement = element;
-          target.staticType = type; // TODO(scheglov) remove this
-          typeName.type = type;
-          constructorName.staticElement = constructorElement;
-          instanceCreationExpression.staticType = type;
-          instanceCreationExpression.staticElement = constructorElement;
           NodeReplacer.replace(node, instanceCreationExpression);
         }
       } else if (element is PrefixElement) {
@@ -160,16 +140,6 @@
           InstanceCreationExpression instanceCreationExpression =
               astFactory.instanceCreationExpression(
                   _getKeyword(node), constructorName, node.argumentList);
-          InterfaceType type =
-              getType(typeSystem, prefixedElement, node.typeArguments);
-          ConstructorElement constructorElement =
-              type.lookUpConstructor(null, definingLibrary);
-          methodName.staticElement = element;
-          methodName.staticType = type;
-          typeName.type = type;
-          constructorName.staticElement = constructorElement;
-          instanceCreationExpression.staticType = type;
-          instanceCreationExpression.staticElement = constructorElement;
           NodeReplacer.replace(node, instanceCreationExpression);
         }
       }
@@ -197,16 +167,6 @@
             InstanceCreationExpression instanceCreationExpression =
                 astFactory.instanceCreationExpression(
                     _getKeyword(node), constructorName, node.argumentList);
-            InterfaceType type = getType(typeSystem, element, typeArguments);
-            constructorElement =
-                type.lookUpConstructor(methodName.name, definingLibrary);
-            methodName.staticElement = element;
-            methodName.staticType = type;
-            target.identifier.staticElement = element;
-            typeName.type = type;
-            constructorName.staticElement = constructorElement;
-            instanceCreationExpression.staticType = type;
-            instanceCreationExpression.staticElement = constructorElement;
             NodeReplacer.replace(node, instanceCreationExpression);
           }
         }
@@ -513,6 +473,14 @@
   }
 
   @override
+  void visitFunctionExpression(FunctionExpression node) {
+    if (node.parent is! FunctionDeclaration) {
+      _checkForMissingReturn(null, node.body, node.element, node);
+    }
+    super.visitFunctionExpression(node);
+  }
+
+  @override
   void visitImportDirective(ImportDirective node) {
     _checkForDeprecatedMemberUse(node.uriElement, node);
     ImportElement importElement = node.element;
@@ -1074,7 +1042,27 @@
       var flattenedType =
           body.isAsynchronous ? _typeSystem.flatten(returnType) : returnType;
 
-      // dynamic/Null/void are allowed to omit a return.
+      // Function expressions without a return will have their return type set
+      // to `Null` regardless of their context type. So we need to figure out
+      // if a return type was expected from the original downwards context.
+      //
+      // This helps detect hint cases like `int Function() f = () {}`.
+      // See https://github.com/dart-lang/sdk/issues/28233 for context.
+      if (flattenedType.isDartCoreNull && functionNode is FunctionExpression) {
+        var contextType = InferenceContext.getContext(functionNode);
+        if (contextType is FunctionType) {
+          returnType = contextType.returnType;
+          flattenedType = body.isAsynchronous
+              ? returnType.flattenFutures(_typeSystem)
+              : returnType;
+        }
+      }
+
+      // dynamic, Null, void, and FutureOr<T> where T is (dynamic, Null, void)
+      // are allowed to omit a return.
+      if (flattenedType.isDartAsyncFutureOr) {
+        flattenedType = (flattenedType as InterfaceType).typeArguments[0];
+      }
       if (flattenedType.isDynamic ||
           flattenedType.isDartCoreNull ||
           flattenedType.isVoid) {
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index dc2e4ce..1ce52ef 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -602,8 +602,10 @@
     var context = InferenceContext.getContext(
         (node as IntegerLiteralImpl).immediatelyNegated ? node.parent : node);
     if (context == null ||
-        _typeSystem.isAssignableTo(_typeProvider.intType, context) ||
-        !_typeSystem.isAssignableTo(_typeProvider.doubleType, context)) {
+        _typeSystem.isAssignableTo(_typeProvider.intType, context,
+            featureSet: _featureSet) ||
+        !_typeSystem.isAssignableTo(_typeProvider.doubleType, context,
+            featureSet: _featureSet)) {
       _recordStaticType(node, _nonNullable(_typeProvider.intType));
     } else {
       _recordStaticType(node, _nonNullable(_typeProvider.doubleType));
@@ -776,9 +778,7 @@
     TypeImpl staticType = _getStaticType(operand, read: true);
 
     if (node.operator.type == TokenType.BANG) {
-      // TODO(paulberry): This does the wrong thing if staticType is a type
-      // parameter type.
-      staticType = staticType.withNullability(NullabilitySuffix.none);
+      staticType = _typeSystem.promoteToNonNull(staticType);
     } else {
       // No need to check for `intVar++`, the result is `int`.
       if (!staticType.isDartCoreInt) {
@@ -914,8 +914,7 @@
 
     if (node.operator.type == TokenType.QUESTION_PERIOD &&
         _nonNullableEnabled) {
-      staticType =
-          (staticType as TypeImpl).withNullability(NullabilitySuffix.question);
+      staticType = _typeSystem.makeNullable(staticType);
     }
     staticType = _inferGenericInstantiationFromContext(node, staticType);
 
@@ -1165,7 +1164,8 @@
   void _checkForInvalidAssignmentIncDec(
       AstNode node, Expression operand, DartType type) {
     var operandWriteType = _getStaticType(operand);
-    if (!_typeSystem.isAssignableTo(type, operandWriteType)) {
+    if (!_typeSystem.isAssignableTo(type, operandWriteType,
+        featureSet: _featureSet)) {
       _resolver.errorReporter.reportTypeErrorForNode(
         StaticTypeWarningCode.INVALID_ASSIGNMENT,
         node,
@@ -1232,22 +1232,24 @@
    * Compute the return type of the method or function represented by the given
    * type that is being invoked.
    */
-  DartType _computeInvokeReturnType(DartType type,
+  DartType /*!*/ _computeInvokeReturnType(DartType type,
       {@required bool isNullableInvoke}) {
-    TypeImpl returnType;
+    TypeImpl /*!*/ returnType;
     if (type is InterfaceType) {
       MethodElement callMethod = type.lookUpMethod(
           FunctionElement.CALL_METHOD_NAME, _resolver.definingLibrary);
-      returnType = callMethod?.type?.returnType;
+      returnType = callMethod?.type?.returnType ?? _dynamicType;
     } else if (type is FunctionType) {
-      returnType = type.returnType;
+      returnType = type.returnType ?? _dynamicType;
+    } else {
+      returnType = _dynamicType;
     }
 
     if (isNullableInvoke && _nonNullableEnabled) {
-      returnType = returnType?.withNullability(NullabilitySuffix.question);
+      returnType = _typeSystem.makeNullable(returnType);
     }
 
-    return returnType ?? _dynamicType;
+    return returnType;
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
index ab12e27..469e29c 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:meta/meta.dart';
 
 /**
  * The class `AstTestFactory` defines utility methods that can be used to create AST nodes. The
@@ -469,6 +470,24 @@
   static ExtendsClause extendsClause(TypeName type) => astFactory.extendsClause(
       TokenFactory.tokenFromKeyword(Keyword.EXTENDS), type);
 
+  static ExtensionDeclaration extensionDeclaration(
+          {@required String name,
+          TypeParameterList typeParameters,
+          @required TypeAnnotation extendedType,
+          List<ClassMember> members}) =>
+      astFactory.extensionDeclaration(
+          comment: null,
+          metadata: null,
+          extensionKeyword: TokenFactory.tokenFromKeyword(Keyword.EXTENSION),
+          name: identifier3(name),
+          typeParameters: typeParameters,
+          onKeyword: TokenFactory.tokenFromKeyword(Keyword.ON),
+          extendedType: extendedType,
+          leftBracket: TokenFactory.tokenFromType(TokenType.OPEN_CURLY_BRACKET),
+          members: members,
+          rightBracket:
+              TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET));
+
   static FieldDeclaration fieldDeclaration(bool isStatic, Keyword keyword,
           TypeAnnotation type, List<VariableDeclaration> variables) =>
       astFactory.fieldDeclaration2(
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 4ef1a61..f3dce0d 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -51,7 +51,9 @@
 
 bool _isBottom(DartType t) {
   return t.isBottom ||
-      t.isDartCoreNull ||
+      // TODO(mfairhurst): Remove the exception treating Null* as Top.
+      t.isDartCoreNull &&
+          (t as TypeImpl).nullabilitySuffix == NullabilitySuffix.star ||
       identical(t, UnknownInferredType.instance);
 }
 
@@ -60,7 +62,8 @@
     return _isTop((t as InterfaceType).typeArguments[0]);
   }
   return t.isDynamic ||
-      t.isObject ||
+      (t.isObject &&
+          (t as TypeImpl).nullabilitySuffix != NullabilitySuffix.none) ||
       t.isVoid ||
       identical(t, UnknownInferredType.instance);
 }
@@ -75,7 +78,8 @@
       new HashSet<TypeComparison>();
 
   /**
-   * True if implicit casts should be allowed, otherwise false.
+   * False if implicit casts should always be disallowed, otherwise the
+   * [FeatureSet] will be used.
    *
    * This affects the behavior of [isAssignableTo].
    */
@@ -448,7 +452,8 @@
   }
 
   @override
-  bool isAssignableTo(DartType fromType, DartType toType) {
+  bool isAssignableTo(DartType fromType, DartType toType,
+      {FeatureSet featureSet}) {
     // An actual subtype
     if (isSubtypeOf(fromType, toType)) {
       return true;
@@ -457,15 +462,23 @@
     // A call method tearoff
     if (fromType is InterfaceType && acceptsFunctionType(toType)) {
       var callMethodType = getCallMethodType(fromType);
-      if (callMethodType != null && isAssignableTo(callMethodType, toType)) {
+      if (callMethodType != null &&
+          isAssignableTo(callMethodType, toType, featureSet: featureSet)) {
         return true;
       }
     }
 
+    // First make sure --no-implicit-casts disables all downcasts, including
+    // dynamic casts.
     if (!implicitCasts) {
       return false;
     }
 
+    // Now handle NNBD default behavior, where we disable non-dynamic downcasts.
+    if (featureSet != null && featureSet.isEnabled(Feature.non_nullable)) {
+      return fromType.isDynamic;
+    }
+
     // Don't allow implicit downcasts between function types
     // and call method objects, as these will almost always fail.
     if (fromType is FunctionType && getCallMethodType(toType) != null) {
@@ -484,8 +497,7 @@
       return false;
     }
 
-    // If the subtype relation goes the other way, allow the implicit
-    // downcast.
+    // If the subtype relation goes the other way, allow the implicit downcast.
     if (isSubtypeOf(toType, fromType)) {
       // TODO(leafp,jmesserly): we emit warnings/hints for these in
       // src/task/strong/checker.dart, which is a bit inconsistent. That
@@ -550,12 +562,23 @@
         p1.isCovariant && isSubtypeOf(p1.type, p2.type);
   }
 
+  /// Check if [_t1] is a subtype of [_t2].
+  ///
+  /// Partially updated to reflect
+  /// https://github.com/dart-lang/language/blob/da5adf7eb5f2d479069d8660ed7ca7b230098510/resources/type-system/subtyping.md
+  ///
+  /// However, it does not correllate 1:1 and does not specialize Null vs Never
+  /// cases. It also is not guaranteed to be exactly accurate vs the "spec"
+  /// because it has slightly different order of operations. These should be
+  /// brought in line or proven equivalent.
   @override
-  bool isSubtypeOf(DartType t1, DartType t2) {
+  bool isSubtypeOf(DartType _t1, DartType _t2) {
+    var t1 = _t1 as TypeImpl;
+    var t2 = _t2 as TypeImpl;
+
     if (identical(t1, t2)) {
       return true;
     }
-
     // The types are void, dynamic, bottom, interface types, function types,
     // FutureOr<T> and type parameters.
     //
@@ -574,10 +597,36 @@
       return false;
     }
 
+    // TODO(mfairhurst): Convert Null to Never?, to simplify the algorithm, and
+    // remove this check.
+    if (t1.isDartCoreNull) {
+      if (t2.nullabilitySuffix != NullabilitySuffix.none) {
+        return true;
+      }
+    }
+
+    // Handle T1? <: T2
+    if (t1.nullabilitySuffix == NullabilitySuffix.question) {
+      if (t2.nullabilitySuffix == NullabilitySuffix.none) {
+        // If T2 is not FutureOr<S2>, then subtype is false.
+        if (!t2.isDartAsyncFutureOr) {
+          return false;
+        }
+
+        // T1? <: FutureOr<T2> is true if T2 is S2?.
+        // TODO(mfairhurst): handle T1? <: FutureOr<dynamic>, etc.
+        if (t2 is InterfaceTypeImpl &&
+            (t2.typeArguments[0] as TypeImpl).nullabilitySuffix ==
+                NullabilitySuffix.none) {
+          return false;
+        }
+      }
+    }
+
     // Handle FutureOr<T> union type.
-    if (t1 is InterfaceType && t1.isDartAsyncFutureOr) {
+    if (t1 is InterfaceTypeImpl && t1.isDartAsyncFutureOr) {
       var t1TypeArg = t1.typeArguments[0];
-      if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
+      if (t2 is InterfaceTypeImpl && t2.isDartAsyncFutureOr) {
         var t2TypeArg = t2.typeArguments[0];
         // FutureOr<A> <: FutureOr<B> iff A <: B
         return isSubtypeOf(t1TypeArg, t2TypeArg);
@@ -589,7 +638,7 @@
       return isSubtypeOf(t1Future, t2) && isSubtypeOf(t1TypeArg, t2);
     }
 
-    if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
+    if (t2 is InterfaceTypeImpl && t2.isDartAsyncFutureOr) {
       // given t2 is Future<A> | A, then:
       // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A
       var t2TypeArg = t2.typeArguments[0];
@@ -601,23 +650,26 @@
     //  T is not dynamic or object (handled above)
     //  True if T == S
     //  Or true if bound of S is S' and S' <: T
-    if (t1 is TypeParameterType) {
-      if (t2 is TypeParameterType &&
+    if (t1 is TypeParameterTypeImpl) {
+      if (t2 is TypeParameterTypeImpl &&
           t1.definition == t2.definition &&
           _typeParameterBoundsSubtype(t1.bound, t2.bound, true)) {
         return true;
       }
+
       DartType bound = t1.element.bound;
       return bound == null
           ? false
           : _typeParameterBoundsSubtype(bound, t2, false);
     }
+
     if (t2 is TypeParameterType) {
       return false;
     }
 
-    // We've eliminated void, dynamic, bottom, type parameters, and FutureOr.
-    // The only cases are the combinations of interface type and function type.
+    // We've eliminated void, dynamic, bottom, type parameters, FutureOr,
+    // nullable, and legacy nullable types. The only cases are the combinations
+    // of interface type and function type.
 
     // A function type can only subtype an interface type if
     // the interface type is Function
@@ -628,11 +680,11 @@
     if (t1 is InterfaceType && t2 is FunctionType) return false;
 
     // Two interface types
-    if (t1 is InterfaceType && t2 is InterfaceType) {
+    if (t1 is InterfaceTypeImpl && t2 is InterfaceTypeImpl) {
       return _isInterfaceSubtypeOf(t1, t2, null);
     }
 
-    return _isFunctionSubtypeOf(t1, t2);
+    return _isFunctionSubtypeOf(t1 as FunctionType, t2 as FunctionType);
   }
 
   /// Given a [type] T that may have an unknown type `?`, returns a type
@@ -1978,9 +2030,11 @@
 
   /**
    * Return `true` if the [leftType] is assignable to the [rightType] (that is,
-   * if leftType <==> rightType).
+   * if leftType <==> rightType). Accepts a [FeatureSet] to correctly handle
+   * NNBD implicit downcasts.
    */
-  bool isAssignableTo(DartType leftType, DartType rightType);
+  bool isAssignableTo(DartType leftType, DartType rightType,
+      {FeatureSet featureSet});
 
   /**
    * Return `true` if the [leftType] is more specific than the [rightType]
@@ -2035,6 +2089,13 @@
     return getLeastUpperBound(leftType, rightType);
   }
 
+  /// Returns a nullable version of [type].  The result would be equivalent to
+  /// the union `type | Null` (if we supported union types).
+  DartType makeNullable(TypeImpl type) {
+    // TODO(paulberry): handle type parameter types
+    return type.withNullability(NullabilitySuffix.question);
+  }
+
   /// Attempts to find the appropriate substitution for [typeParameters] that can
   /// be applied to [src] to make it equal to [dest].  If no such substitution can
   /// be found, `null` is returned.
@@ -2089,7 +2150,10 @@
     return null;
   }
 
+  /// Returns a non-nullable version of [type].  This is equivalent to the
+  /// operation `NonNull` defined in the spec.
   DartType promoteToNonNull(TypeImpl type) {
+    if (type.isDartCoreNull) return typeProvider.bottomType;
     // TODO(mfairhurst): handle type parameter types
     return type.withNullability(NullabilitySuffix.none);
   }
diff --git a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
index 938d454..98a39ae 100644
--- a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
+++ b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
@@ -72,10 +72,14 @@
   VersionRange get before_2_2_2 =>
       new VersionRange(max: Version.parse('2.2.2'), includeMax: false);
 
+  /// Return a range covering every version up to, but not including, 2.3.2.
+  VersionRange get before_2_3_2 =>
+      new VersionRange(max: Version.parse('2.3.2'), includeMax: false);
+
   /// Return `true` if references to the constant-update-2018 features need to
   /// be checked.
   bool get checkConstantUpdate2018 => _checkConstantUpdate2018 ??=
-      !before_2_2_2.intersect(_versionConstraint).isEmpty;
+      !before_2_3_2.intersect(_versionConstraint).isEmpty;
 
   /// Return `true` if references to Future and Stream need to be checked.
   bool get checkFutureAndStream => _checkFutureAndStream ??=
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index 1f18466..6de334c 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -57,6 +57,7 @@
   final String typeParameters;
 
   List<String> _relevanceTags;
+  Uri _locationLibraryUri;
 
   Declaration({
     @required this.children,
@@ -84,6 +85,8 @@
     @required this.typeParameters,
   }) : _relevanceTags = relevanceTags;
 
+  Uri get locationLibraryUri => _locationLibraryUri;
+
   List<String> get relevanceTags => _relevanceTags;
 
   @override
@@ -474,6 +477,12 @@
     _changedPaths.add(path);
   }
 
+  /// Discard the [analysisContext], but don't discard any libraries that it
+  /// might have in its dependencies.
+  void discardContext(AnalysisContext analysisContext) {
+    _contexts.remove(analysisContext);
+  }
+
   /// Discard all contexts and libraries, notify the [changes] stream that
   /// these libraries are removed.
   void discardContexts() {
@@ -1104,6 +1113,7 @@
         libraryDeclarations.addAll(part.file.fileDeclarations);
       }
       _computeRelevanceTags(libraryDeclarations);
+      _setLocationLibraryUri();
     }
   }
 
@@ -1377,6 +1387,19 @@
           returnType: _getTypeAnnotationString(functionType.returnType),
           typeParameters: functionType.typeParameters?.toSource(),
         );
+      } else if (node is FunctionTypeAlias) {
+        var parameters = node.parameters;
+        addDeclaration(
+          isDeprecated: isDeprecated,
+          kind: DeclarationKind.FUNCTION_TYPE_ALIAS,
+          name: node.name,
+          parameters: parameters.toSource(),
+          parameterNames: _getFormalParameterNames(parameters),
+          parameterTypes: _getFormalParameterTypes(parameters),
+          requiredParameterCount: _getFormalParameterRequiredCount(parameters),
+          returnType: _getTypeAnnotationString(node.returnType),
+          typeParameters: node.typeParameters?.toSource(),
+        );
       } else if (node is MixinDeclaration) {
         addDeclaration(
           isDeprecated: isDeprecated,
@@ -1503,6 +1526,12 @@
     templateValues = idlFile.directiveInfo.templateValues.toList();
   }
 
+  void _setLocationLibraryUri() {
+    for (var declaration in libraryDeclarations) {
+      declaration._locationLibraryUri = uri;
+    }
+  }
+
   static _DefaultArguments _computeDefaultArguments(
       FormalParameterList parameters) {
     var buffer = StringBuffer();
diff --git a/pkg/analyzer/lib/src/summary/flat_buffers.dart b/pkg/analyzer/lib/src/summary/flat_buffers.dart
index da60445..96d0719 100644
--- a/pkg/analyzer/lib/src/summary/flat_buffers.dart
+++ b/pkg/analyzer/lib/src/summary/flat_buffers.dart
@@ -89,6 +89,16 @@
   final int initialSize;
 
   /**
+   * The list of field tails, reused by [_VTable] instances.
+   */
+  final Int32List _reusedFieldTails = Int32List(1024);
+
+  /**
+   * The list of field offsets, reused by [_VTable] instances.
+   */
+  final Int32List _reusedFieldOffsets = Int32List(1024);
+
+  /**
    * The list of existing VTable(s).
    */
   final List<_VTable> _vTables = <_VTable>[];
@@ -248,6 +258,7 @@
       }
       // Write a new VTable.
       if (vTableTail == null) {
+        _currentVTable.takeFieldOffsets();
         _prepare(2, _currentVTable.numOfUint16);
         vTableTail = _tail;
         _currentVTable.tail = vTableTail;
@@ -332,7 +343,7 @@
     if (_currentVTable != null) {
       throw new StateError('Inline tables are not supported.');
     }
-    _currentVTable = new _VTable();
+    _currentVTable = new _VTable(_reusedFieldTails, _reusedFieldOffsets);
     _currentTableEndTail = _tail;
   }
 
@@ -570,6 +581,19 @@
 }
 
 /**
+ * The reader of 64-bit floats.
+ */
+class Float64Reader extends Reader<double> {
+  const Float64Reader() : super();
+
+  @override
+  int get size => 8;
+
+  @override
+  double read(BufferContext bc, int offset) => bc._getFloat64(offset);
+}
+
+/**
  * The reader of signed 32-bit integers.
  */
 class Int32Reader extends Reader<int> {
@@ -768,19 +792,6 @@
 }
 
 /**
- * The reader of 64-bit floats.
- */
-class Float64Reader extends Reader<double> {
-  const Float64Reader() : super();
-
-  @override
-  int get size => 8;
-
-  @override
-  double read(BufferContext bc, int offset) => bc._getFloat64(offset);
-}
-
-/**
  * List of booleans backed by 8-bit unsigned integers.
  */
 class _FbBoolList with ListMixin<bool> implements List<bool> {
@@ -905,8 +916,19 @@
  * Class that describes the structure of a table.
  */
 class _VTable {
-  final List<int> fieldTails = <int>[];
-  List<int> fieldOffsets;
+  final Int32List _reusedFieldTails;
+  final Int32List _reusedFieldOffsets;
+
+  /**
+   * The number of fields in [_reusedFieldTails].
+   */
+  int _fieldCount = 0;
+
+  /**
+   * The private copy of [_reusedFieldOffsets], which is made only when we
+   * find that this table is unique.
+   */
+  Int32List _fieldOffsets;
 
   /**
    * The size of the table that uses this VTable.
@@ -919,13 +941,15 @@
    */
   int tail;
 
-  int get numOfUint16 => 1 + 1 + fieldTails.length;
+  _VTable(this._reusedFieldTails, this._reusedFieldOffsets);
+
+  int get numOfUint16 => 1 + 1 + _fieldCount;
 
   void addField(int field, int offset) {
-    while (fieldTails.length <= field) {
-      fieldTails.add(null);
+    while (_fieldCount <= field) {
+      _reusedFieldTails[_fieldCount++] = -1;
     }
-    fieldTails[field] = offset;
+    _reusedFieldTails[field] = offset;
   }
 
   /**
@@ -935,9 +959,9 @@
     assert(tail == null);
     assert(existing.tail != null);
     if (tableSize == existing.tableSize &&
-        fieldOffsets.length == existing.fieldOffsets.length) {
-      for (int i = 0; i < fieldOffsets.length; i++) {
-        if (fieldOffsets[i] != existing.fieldOffsets[i]) {
+        _fieldCount == existing._fieldCount) {
+      for (int i = 0; i < _fieldCount; i++) {
+        if (_reusedFieldOffsets[i] != existing._fieldOffsets[i]) {
           return false;
         }
       }
@@ -947,14 +971,12 @@
   }
 
   /**
-   * Fill the [fieldOffsets] field.
+   * Fill the [_reusedFieldOffsets] field.
    */
   void computeFieldOffsets(int tableTail) {
-    assert(fieldOffsets == null);
-    fieldOffsets = List<int>(fieldTails.length);
-    for (int i = 0; i < fieldTails.length; ++i) {
-      int fieldTail = fieldTails[i];
-      fieldOffsets[i] = fieldTail == null ? 0 : tableTail - fieldTail;
+    for (int i = 0; i < _fieldCount; ++i) {
+      int fieldTail = _reusedFieldTails[i];
+      _reusedFieldOffsets[i] = fieldTail == -1 ? 0 : tableTail - fieldTail;
     }
   }
 
@@ -970,9 +992,20 @@
     buf.setUint16(bufOffset, tableSize, Endian.little);
     bufOffset += 2;
     // Field offsets.
-    for (int fieldOffset in fieldOffsets) {
+    for (int fieldOffset in _fieldOffsets) {
       buf.setUint16(bufOffset, fieldOffset, Endian.little);
       bufOffset += 2;
     }
   }
+
+  /**
+   * Fill the [_fieldOffsets] field.
+   */
+  void takeFieldOffsets() {
+    assert(_fieldOffsets == null);
+    _fieldOffsets = Int32List(_fieldCount);
+    for (int i = 0; i < _fieldCount; ++i) {
+      _fieldOffsets[i] = _reusedFieldOffsets[i];
+    }
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index bcfbc8c..2b5c069 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -4737,11 +4737,12 @@
   LinkedNodeBuilder _variantField_12;
   List<LinkedNodeBuilder> _variantField_5;
   LinkedNodeBuilder _variantField_13;
-  int _variantField_34;
   int _variantField_33;
-  List<String> _variantField_36;
+  int _variantField_32;
+  List<String> _variantField_35;
   idl.LinkedNodeCommentType _variantField_29;
   List<LinkedNodeBuilder> _variantField_3;
+  int _variantField_19;
   LinkedNodeBuilder _variantField_10;
   idl.LinkedNodeFormalParameterKind _variantField_26;
   double _variantField_21;
@@ -4752,14 +4753,12 @@
   String _variantField_30;
   LinkedNodeBuilder _variantField_14;
   idl.LinkedNodeKind _kind;
-  String _name;
+  List<String> _variantField_36;
   String _variantField_20;
   bool _variantField_31;
-  idl.UnlinkedTokenType _variantField_38;
-  TopLevelInferenceErrorBuilder _variantField_35;
+  idl.UnlinkedTokenType _variantField_37;
+  TopLevelInferenceErrorBuilder _variantField_34;
   String _variantField_22;
-  int _variantField_19;
-  LinkedNodeVariablesDeclarationBuilder _variantField_32;
 
   @override
   LinkedNodeTypeBuilder get actualReturnType {
@@ -5376,6 +5375,12 @@
   }
 
   @override
+  LinkedNodeBuilder get enumConstantDeclaration_name {
+    assert(kind == idl.LinkedNodeKind.enumConstantDeclaration);
+    return _variantField_6;
+  }
+
+  @override
   LinkedNodeBuilder get expressionFunctionBody_expression {
     assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
     return _variantField_6;
@@ -5811,6 +5816,11 @@
     _variantField_6 = value;
   }
 
+  set enumConstantDeclaration_name(LinkedNodeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.enumConstantDeclaration);
+    _variantField_6 = value;
+  }
+
   set expressionFunctionBody_expression(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
     _variantField_6 = value;
@@ -6143,6 +6153,12 @@
   }
 
   @override
+  LinkedNodeBuilder get constructorDeclaration_name {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+    return _variantField_7;
+  }
+
+  @override
   LinkedNodeBuilder get constructorFieldInitializer_fieldName {
     assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
     return _variantField_7;
@@ -6341,6 +6357,18 @@
   }
 
   @override
+  LinkedNodeBuilder get typeParameter_name {
+    assert(kind == idl.LinkedNodeKind.typeParameter);
+    return _variantField_7;
+  }
+
+  @override
+  LinkedNodeBuilder get variableDeclaration_name {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    return _variantField_7;
+  }
+
+  @override
   LinkedNodeBuilder get whileStatement_condition {
     assert(kind == idl.LinkedNodeKind.whileStatement);
     return _variantField_7;
@@ -6401,6 +6429,11 @@
     _variantField_7 = value;
   }
 
+  set constructorDeclaration_name(LinkedNodeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+    _variantField_7 = value;
+  }
+
   set constructorFieldInitializer_fieldName(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
     _variantField_7 = value;
@@ -6567,6 +6600,16 @@
     _variantField_7 = value;
   }
 
+  set typeParameter_name(LinkedNodeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.typeParameter);
+    _variantField_7 = value;
+  }
+
+  set variableDeclaration_name(LinkedNodeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_7 = value;
+  }
+
   set whileStatement_condition(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.whileStatement);
     _variantField_7 = value;
@@ -6579,6 +6622,16 @@
   }
 
   @override
+  int get directive_keywordOffset {
+    assert(kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.libraryDirective ||
+        kind == idl.LinkedNodeKind.partDirective ||
+        kind == idl.LinkedNodeKind.partOfDirective);
+    return _variantField_17 ??= 0;
+  }
+
+  @override
   int get genericFunctionType_id {
     assert(kind == idl.LinkedNodeKind.genericFunctionType);
     return _variantField_17 ??= 0;
@@ -6590,6 +6643,16 @@
     _variantField_17 = value;
   }
 
+  set directive_keywordOffset(int value) {
+    assert(kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.libraryDirective ||
+        kind == idl.LinkedNodeKind.partDirective ||
+        kind == idl.LinkedNodeKind.partOfDirective);
+    assert(value == null || value >= 0);
+    _variantField_17 = value;
+  }
+
   set genericFunctionType_id(int value) {
     assert(kind == idl.LinkedNodeKind.genericFunctionType);
     assert(value == null || value >= 0);
@@ -7198,6 +7261,14 @@
     return _variantField_9;
   }
 
+  @override
+  LinkedNodeBuilder get normalFormalParameter_identifier {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    return _variantField_9;
+  }
+
   set catchClause_stackTraceParameter(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.catchClause);
     _variantField_9 = value;
@@ -7223,6 +7294,13 @@
     _variantField_9 = value;
   }
 
+  set normalFormalParameter_identifier(LinkedNodeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _variantField_9 = value;
+  }
+
   @override
   LinkedNodeBuilder get classOrMixinDeclaration_implementsClause {
     assert(kind == idl.LinkedNodeKind.classDeclaration ||
@@ -7306,52 +7384,10 @@
         kind == idl.LinkedNodeKind.simpleFormalParameter ||
         kind == idl.LinkedNodeKind.typeParameter ||
         kind == idl.LinkedNodeKind.variableDeclaration);
-    return _variantField_34 ??= 0;
-  }
-
-  set codeLength(int value) {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.compilationUnit ||
-        kind == idl.LinkedNodeKind.constructorDeclaration ||
-        kind == idl.LinkedNodeKind.defaultFormalParameter ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.methodDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter ||
-        kind == idl.LinkedNodeKind.typeParameter ||
-        kind == idl.LinkedNodeKind.variableDeclaration);
-    assert(value == null || value >= 0);
-    _variantField_34 = value;
-  }
-
-  @override
-  int get codeOffset {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.compilationUnit ||
-        kind == idl.LinkedNodeKind.constructorDeclaration ||
-        kind == idl.LinkedNodeKind.defaultFormalParameter ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.methodDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter ||
-        kind == idl.LinkedNodeKind.typeParameter ||
-        kind == idl.LinkedNodeKind.variableDeclaration);
     return _variantField_33 ??= 0;
   }
 
-  set codeOffset(int value) {
+  set codeLength(int value) {
     assert(kind == idl.LinkedNodeKind.classDeclaration ||
         kind == idl.LinkedNodeKind.classTypeAlias ||
         kind == idl.LinkedNodeKind.compilationUnit ||
@@ -7373,40 +7409,56 @@
   }
 
   @override
+  int get codeOffset {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.compilationUnit ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.defaultFormalParameter ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.typeParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    return _variantField_32 ??= 0;
+  }
+
+  set codeOffset(int value) {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.compilationUnit ||
+        kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.defaultFormalParameter ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.methodDeclaration ||
+        kind == idl.LinkedNodeKind.mixinDeclaration ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.typeParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    assert(value == null || value >= 0);
+    _variantField_32 = value;
+  }
+
+  @override
   List<String> get comment_tokens {
     assert(kind == idl.LinkedNodeKind.comment);
-    return _variantField_36 ??= <String>[];
-  }
-
-  @override
-  List<String> get mixinDeclaration_superInvokedNames {
-    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
-    return _variantField_36 ??= <String>[];
-  }
-
-  @override
-  List<String> get names {
-    assert(kind == idl.LinkedNodeKind.hideCombinator ||
-        kind == idl.LinkedNodeKind.showCombinator ||
-        kind == idl.LinkedNodeKind.symbolLiteral);
-    return _variantField_36 ??= <String>[];
+    return _variantField_35 ??= <String>[];
   }
 
   set comment_tokens(List<String> value) {
     assert(kind == idl.LinkedNodeKind.comment);
-    _variantField_36 = value;
-  }
-
-  set mixinDeclaration_superInvokedNames(List<String> value) {
-    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
-    _variantField_36 = value;
-  }
-
-  set names(List<String> value) {
-    assert(kind == idl.LinkedNodeKind.hideCombinator ||
-        kind == idl.LinkedNodeKind.showCombinator ||
-        kind == idl.LinkedNodeKind.symbolLiteral);
-    _variantField_36 = value;
+    _variantField_35 = value;
   }
 
   @override
@@ -7480,16 +7532,78 @@
   }
 
   @override
+  int get constructorDeclaration_periodOffset {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+    return _variantField_19 ??= 0;
+  }
+
+  @override
+  int get uriBasedDirective_uriElement {
+    assert(kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.partDirective);
+    return _variantField_19 ??= 0;
+  }
+
+  set constructorDeclaration_periodOffset(int value) {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+    assert(value == null || value >= 0);
+    _variantField_19 = value;
+  }
+
+  set uriBasedDirective_uriElement(int value) {
+    assert(kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.partDirective);
+    assert(value == null || value >= 0);
+    _variantField_19 = value;
+  }
+
+  @override
   LinkedNodeBuilder get constructorDeclaration_returnType {
     assert(kind == idl.LinkedNodeKind.constructorDeclaration);
     return _variantField_10;
   }
 
+  @override
+  LinkedNodeBuilder get methodDeclaration_name {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    return _variantField_10;
+  }
+
+  @override
+  LinkedNodeBuilder get namedCompilationUnitMember_name {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.mixinDeclaration);
+    return _variantField_10;
+  }
+
   set constructorDeclaration_returnType(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.constructorDeclaration);
     _variantField_10 = value;
   }
 
+  set methodDeclaration_name(LinkedNodeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_10 = value;
+  }
+
+  set namedCompilationUnitMember_name(LinkedNodeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.mixinDeclaration);
+    _variantField_10 = value;
+  }
+
   @override
   idl.LinkedNodeFormalParameterKind get defaultFormalParameter_kind {
     assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
@@ -7607,25 +7721,8 @@
   }
 
   @override
-  int get nameOffset {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.constructorDeclaration ||
-        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.methodDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration ||
-        kind == idl.LinkedNodeKind.partDirective ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter ||
-        kind == idl.LinkedNodeKind.typeParameter ||
-        kind == idl.LinkedNodeKind.variableDeclaration);
+  int get simpleIdentifier_offset {
+    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
     return _variantField_16 ??= 0;
   }
 
@@ -7635,25 +7732,8 @@
     _variantField_16 = value;
   }
 
-  set nameOffset(int value) {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.constructorDeclaration ||
-        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.methodDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration ||
-        kind == idl.LinkedNodeKind.partDirective ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter ||
-        kind == idl.LinkedNodeKind.typeParameter ||
-        kind == idl.LinkedNodeKind.variableDeclaration);
+  set simpleIdentifier_offset(int value) {
+    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
     assert(value == null || value >= 0);
     _variantField_16 = value;
   }
@@ -7720,10 +7800,29 @@
   }
 
   @override
-  String get name => _name ??= '';
+  List<String> get mixinDeclaration_superInvokedNames {
+    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
+    return _variantField_36 ??= <String>[];
+  }
 
-  set name(String value) {
-    this._name = value;
+  @override
+  List<String> get names {
+    assert(kind == idl.LinkedNodeKind.hideCombinator ||
+        kind == idl.LinkedNodeKind.showCombinator ||
+        kind == idl.LinkedNodeKind.symbolLiteral);
+    return _variantField_36 ??= <String>[];
+  }
+
+  set mixinDeclaration_superInvokedNames(List<String> value) {
+    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
+    _variantField_36 = value;
+  }
+
+  set names(List<String> value) {
+    assert(kind == idl.LinkedNodeKind.hideCombinator ||
+        kind == idl.LinkedNodeKind.showCombinator ||
+        kind == idl.LinkedNodeKind.symbolLiteral);
+    _variantField_36 = value;
   }
 
   @override
@@ -7734,6 +7833,12 @@
   }
 
   @override
+  String get simpleIdentifier_name {
+    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
+    return _variantField_20 ??= '';
+  }
+
+  @override
   String get simpleStringLiteral_value {
     assert(kind == idl.LinkedNodeKind.simpleStringLiteral);
     return _variantField_20 ??= '';
@@ -7745,6 +7850,11 @@
     _variantField_20 = value;
   }
 
+  set simpleIdentifier_name(String value) {
+    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
+    _variantField_20 = value;
+  }
+
   set simpleStringLiteral_value(String value) {
     assert(kind == idl.LinkedNodeKind.simpleStringLiteral);
     _variantField_20 = value;
@@ -7772,25 +7882,25 @@
   @override
   idl.UnlinkedTokenType get spreadElement_spreadOperator {
     assert(kind == idl.LinkedNodeKind.spreadElement);
-    return _variantField_38 ??= idl.UnlinkedTokenType.NOTHING;
+    return _variantField_37 ??= idl.UnlinkedTokenType.NOTHING;
   }
 
   set spreadElement_spreadOperator(idl.UnlinkedTokenType value) {
     assert(kind == idl.LinkedNodeKind.spreadElement);
-    _variantField_38 = value;
+    _variantField_37 = value;
   }
 
   @override
   TopLevelInferenceErrorBuilder get topLevelTypeInferenceError {
     assert(kind == idl.LinkedNodeKind.simpleFormalParameter ||
         kind == idl.LinkedNodeKind.variableDeclaration);
-    return _variantField_35;
+    return _variantField_34;
   }
 
   set topLevelTypeInferenceError(TopLevelInferenceErrorBuilder value) {
     assert(kind == idl.LinkedNodeKind.simpleFormalParameter ||
         kind == idl.LinkedNodeKind.variableDeclaration);
-    _variantField_35 = value;
+    _variantField_34 = value;
   }
 
   @override
@@ -7808,713 +7918,11 @@
     _variantField_22 = value;
   }
 
-  @override
-  int get uriBasedDirective_uriElement {
-    assert(kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.partDirective);
-    return _variantField_19 ??= 0;
-  }
-
-  set uriBasedDirective_uriElement(int value) {
-    assert(kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.partDirective);
-    assert(value == null || value >= 0);
-    _variantField_19 = value;
-  }
-
-  @override
-  LinkedNodeVariablesDeclarationBuilder get variableDeclaration_declaration {
-    assert(kind == idl.LinkedNodeKind.variableDeclaration);
-    return _variantField_32;
-  }
-
-  set variableDeclaration_declaration(
-      LinkedNodeVariablesDeclarationBuilder value) {
-    assert(kind == idl.LinkedNodeKind.variableDeclaration);
-    _variantField_32 = value;
-  }
-
-  LinkedNodeBuilder.functionDeclaration({
-    LinkedNodeTypeBuilder actualReturnType,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder functionDeclaration_functionExpression,
-    LinkedNodeBuilder functionDeclaration_returnType,
-    int codeLength,
-    int codeOffset,
-    int nameOffset,
-  })  : _kind = idl.LinkedNodeKind.functionDeclaration,
-        _variantField_24 = actualReturnType,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = functionDeclaration_functionExpression,
-        _variantField_7 = functionDeclaration_returnType,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_16 = nameOffset;
-
-  LinkedNodeBuilder.functionExpression({
-    LinkedNodeTypeBuilder actualReturnType,
-    LinkedNodeBuilder functionExpression_body,
-    LinkedNodeBuilder functionExpression_formalParameters,
-    LinkedNodeBuilder functionExpression_typeParameters,
-  })  : _kind = idl.LinkedNodeKind.functionExpression,
-        _variantField_24 = actualReturnType,
-        _variantField_6 = functionExpression_body,
-        _variantField_7 = functionExpression_formalParameters,
-        _variantField_8 = functionExpression_typeParameters;
-
-  LinkedNodeBuilder.functionTypeAlias({
-    LinkedNodeTypeBuilder actualReturnType,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder functionTypeAlias_formalParameters,
-    LinkedNodeBuilder functionTypeAlias_returnType,
-    LinkedNodeBuilder functionTypeAlias_typeParameters,
-    bool typeAlias_hasSelfReference,
-    int codeLength,
-    int codeOffset,
-    int nameOffset,
-    bool simplyBoundable_isSimplyBounded,
-  })  : _kind = idl.LinkedNodeKind.functionTypeAlias,
-        _variantField_24 = actualReturnType,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = functionTypeAlias_formalParameters,
-        _variantField_7 = functionTypeAlias_returnType,
-        _variantField_8 = functionTypeAlias_typeParameters,
-        _variantField_27 = typeAlias_hasSelfReference,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_16 = nameOffset,
-        _variantField_31 = simplyBoundable_isSimplyBounded;
-
-  LinkedNodeBuilder.genericFunctionType({
-    LinkedNodeTypeBuilder actualReturnType,
-    LinkedNodeBuilder genericFunctionType_typeParameters,
-    LinkedNodeBuilder genericFunctionType_returnType,
-    int genericFunctionType_id,
-    LinkedNodeBuilder genericFunctionType_formalParameters,
-    LinkedNodeTypeBuilder genericFunctionType_type,
-  })  : _kind = idl.LinkedNodeKind.genericFunctionType,
-        _variantField_24 = actualReturnType,
-        _variantField_6 = genericFunctionType_typeParameters,
-        _variantField_7 = genericFunctionType_returnType,
-        _variantField_17 = genericFunctionType_id,
-        _variantField_8 = genericFunctionType_formalParameters,
-        _variantField_25 = genericFunctionType_type;
-
-  LinkedNodeBuilder.methodDeclaration({
-    LinkedNodeTypeBuilder actualReturnType,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder methodDeclaration_body,
-    LinkedNodeBuilder methodDeclaration_formalParameters,
-    LinkedNodeBuilder methodDeclaration_returnType,
-    LinkedNodeBuilder methodDeclaration_typeParameters,
-    int codeLength,
-    int codeOffset,
-    int nameOffset,
-  })  : _kind = idl.LinkedNodeKind.methodDeclaration,
-        _variantField_24 = actualReturnType,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = methodDeclaration_body,
-        _variantField_7 = methodDeclaration_formalParameters,
-        _variantField_8 = methodDeclaration_returnType,
-        _variantField_9 = methodDeclaration_typeParameters,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_16 = nameOffset;
-
-  LinkedNodeBuilder.fieldFormalParameter({
-    LinkedNodeTypeBuilder actualType,
-    List<LinkedNodeBuilder> normalFormalParameter_metadata,
-    LinkedNodeBuilder fieldFormalParameter_type,
-    LinkedNodeBuilder fieldFormalParameter_typeParameters,
-    LinkedNodeBuilder fieldFormalParameter_formalParameters,
-    bool inheritsCovariant,
-    int codeLength,
-    int codeOffset,
-    int nameOffset,
-    LinkedNodeBuilder normalFormalParameter_comment,
-  })  : _kind = idl.LinkedNodeKind.fieldFormalParameter,
-        _variantField_24 = actualType,
-        _variantField_4 = normalFormalParameter_metadata,
-        _variantField_6 = fieldFormalParameter_type,
-        _variantField_7 = fieldFormalParameter_typeParameters,
-        _variantField_8 = fieldFormalParameter_formalParameters,
-        _variantField_27 = inheritsCovariant,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_16 = nameOffset,
-        _variantField_14 = normalFormalParameter_comment;
-
-  LinkedNodeBuilder.functionTypedFormalParameter({
-    LinkedNodeTypeBuilder actualType,
-    List<LinkedNodeBuilder> normalFormalParameter_metadata,
-    LinkedNodeBuilder functionTypedFormalParameter_formalParameters,
-    LinkedNodeBuilder functionTypedFormalParameter_returnType,
-    LinkedNodeBuilder functionTypedFormalParameter_typeParameters,
-    bool inheritsCovariant,
-    int codeLength,
-    int codeOffset,
-    int nameOffset,
-    LinkedNodeBuilder normalFormalParameter_comment,
-  })  : _kind = idl.LinkedNodeKind.functionTypedFormalParameter,
-        _variantField_24 = actualType,
-        _variantField_4 = normalFormalParameter_metadata,
-        _variantField_6 = functionTypedFormalParameter_formalParameters,
-        _variantField_7 = functionTypedFormalParameter_returnType,
-        _variantField_8 = functionTypedFormalParameter_typeParameters,
-        _variantField_27 = inheritsCovariant,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_16 = nameOffset,
-        _variantField_14 = normalFormalParameter_comment;
-
-  LinkedNodeBuilder.simpleFormalParameter({
-    LinkedNodeTypeBuilder actualType,
-    List<LinkedNodeBuilder> normalFormalParameter_metadata,
-    LinkedNodeBuilder simpleFormalParameter_type,
-    bool inheritsCovariant,
-    int codeLength,
-    int codeOffset,
-    int nameOffset,
-    LinkedNodeBuilder normalFormalParameter_comment,
-    TopLevelInferenceErrorBuilder topLevelTypeInferenceError,
-  })  : _kind = idl.LinkedNodeKind.simpleFormalParameter,
-        _variantField_24 = actualType,
-        _variantField_4 = normalFormalParameter_metadata,
-        _variantField_6 = simpleFormalParameter_type,
-        _variantField_27 = inheritsCovariant,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_16 = nameOffset,
-        _variantField_14 = normalFormalParameter_comment,
-        _variantField_35 = topLevelTypeInferenceError;
-
-  LinkedNodeBuilder.variableDeclaration({
-    LinkedNodeTypeBuilder actualType,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder variableDeclaration_initializer,
-    bool inheritsCovariant,
-    int codeLength,
-    int codeOffset,
-    int nameOffset,
-    TopLevelInferenceErrorBuilder topLevelTypeInferenceError,
-    LinkedNodeVariablesDeclarationBuilder variableDeclaration_declaration,
-  })  : _kind = idl.LinkedNodeKind.variableDeclaration,
-        _variantField_24 = actualType,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = variableDeclaration_initializer,
-        _variantField_27 = inheritsCovariant,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_16 = nameOffset,
-        _variantField_35 = topLevelTypeInferenceError,
-        _variantField_32 = variableDeclaration_declaration;
-
-  LinkedNodeBuilder.binaryExpression({
-    LinkedNodeTypeBuilder binaryExpression_invokeType,
-    LinkedNodeBuilder binaryExpression_leftOperand,
-    LinkedNodeBuilder binaryExpression_rightOperand,
-    LinkedNodeTypeBuilder binaryExpression_elementType,
-    int binaryExpression_element,
-    idl.UnlinkedTokenType binaryExpression_operator,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.binaryExpression,
-        _variantField_24 = binaryExpression_invokeType,
-        _variantField_6 = binaryExpression_leftOperand,
-        _variantField_7 = binaryExpression_rightOperand,
-        _variantField_23 = binaryExpression_elementType,
-        _variantField_15 = binaryExpression_element,
-        _variantField_28 = binaryExpression_operator,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.functionExpressionInvocation({
-    LinkedNodeTypeBuilder invocationExpression_invokeType,
-    LinkedNodeBuilder functionExpressionInvocation_function,
-    LinkedNodeBuilder invocationExpression_typeArguments,
-    LinkedNodeTypeBuilder expression_type,
-    LinkedNodeBuilder invocationExpression_arguments,
-  })  : _kind = idl.LinkedNodeKind.functionExpressionInvocation,
-        _variantField_24 = invocationExpression_invokeType,
-        _variantField_6 = functionExpressionInvocation_function,
-        _variantField_12 = invocationExpression_typeArguments,
-        _variantField_25 = expression_type,
-        _variantField_14 = invocationExpression_arguments;
-
-  LinkedNodeBuilder.methodInvocation({
-    LinkedNodeTypeBuilder invocationExpression_invokeType,
-    LinkedNodeBuilder methodInvocation_methodName,
-    LinkedNodeBuilder methodInvocation_target,
-    LinkedNodeBuilder invocationExpression_typeArguments,
-    LinkedNodeTypeBuilder expression_type,
-    LinkedNodeBuilder invocationExpression_arguments,
-  })  : _kind = idl.LinkedNodeKind.methodInvocation,
-        _variantField_24 = invocationExpression_invokeType,
-        _variantField_6 = methodInvocation_methodName,
-        _variantField_7 = methodInvocation_target,
-        _variantField_12 = invocationExpression_typeArguments,
-        _variantField_25 = expression_type,
-        _variantField_14 = invocationExpression_arguments;
-
   LinkedNodeBuilder.adjacentStrings({
     List<LinkedNodeBuilder> adjacentStrings_strings,
   })  : _kind = idl.LinkedNodeKind.adjacentStrings,
         _variantField_2 = adjacentStrings_strings;
 
-  LinkedNodeBuilder.argumentList({
-    List<LinkedNodeBuilder> argumentList_arguments,
-  })  : _kind = idl.LinkedNodeKind.argumentList,
-        _variantField_2 = argumentList_arguments;
-
-  LinkedNodeBuilder.block({
-    List<LinkedNodeBuilder> block_statements,
-  })  : _kind = idl.LinkedNodeKind.block,
-        _variantField_2 = block_statements;
-
-  LinkedNodeBuilder.cascadeExpression({
-    List<LinkedNodeBuilder> cascadeExpression_sections,
-    LinkedNodeBuilder cascadeExpression_target,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.cascadeExpression,
-        _variantField_2 = cascadeExpression_sections,
-        _variantField_6 = cascadeExpression_target,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.comment({
-    List<LinkedNodeBuilder> comment_references,
-    List<String> comment_tokens,
-    idl.LinkedNodeCommentType comment_type,
-  })  : _kind = idl.LinkedNodeKind.comment,
-        _variantField_2 = comment_references,
-        _variantField_36 = comment_tokens,
-        _variantField_29 = comment_type;
-
-  LinkedNodeBuilder.compilationUnit({
-    List<LinkedNodeBuilder> compilationUnit_declarations,
-    LinkedNodeBuilder compilationUnit_scriptTag,
-    int codeLength,
-    int codeOffset,
-    List<LinkedNodeBuilder> compilationUnit_directives,
-  })  : _kind = idl.LinkedNodeKind.compilationUnit,
-        _variantField_2 = compilationUnit_declarations,
-        _variantField_6 = compilationUnit_scriptTag,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_3 = compilationUnit_directives;
-
-  LinkedNodeBuilder.constructorDeclaration({
-    List<LinkedNodeBuilder> constructorDeclaration_initializers,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder constructorDeclaration_body,
-    LinkedNodeBuilder constructorDeclaration_parameters,
-    LinkedNodeBuilder constructorDeclaration_redirectedConstructor,
-    int codeLength,
-    int codeOffset,
-    LinkedNodeBuilder constructorDeclaration_returnType,
-    int nameOffset,
-  })  : _kind = idl.LinkedNodeKind.constructorDeclaration,
-        _variantField_2 = constructorDeclaration_initializers,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = constructorDeclaration_body,
-        _variantField_8 = constructorDeclaration_parameters,
-        _variantField_9 = constructorDeclaration_redirectedConstructor,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_10 = constructorDeclaration_returnType,
-        _variantField_16 = nameOffset;
-
-  LinkedNodeBuilder.dottedName({
-    List<LinkedNodeBuilder> dottedName_components,
-  })  : _kind = idl.LinkedNodeKind.dottedName,
-        _variantField_2 = dottedName_components;
-
-  LinkedNodeBuilder.enumDeclaration({
-    List<LinkedNodeBuilder> enumDeclaration_constants,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    int codeLength,
-    int codeOffset,
-    int nameOffset,
-  })  : _kind = idl.LinkedNodeKind.enumDeclaration,
-        _variantField_2 = enumDeclaration_constants,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_16 = nameOffset;
-
-  LinkedNodeBuilder.formalParameterList({
-    List<LinkedNodeBuilder> formalParameterList_parameters,
-  })  : _kind = idl.LinkedNodeKind.formalParameterList,
-        _variantField_2 = formalParameterList_parameters;
-
-  LinkedNodeBuilder.implementsClause({
-    List<LinkedNodeBuilder> implementsClause_interfaces,
-  })  : _kind = idl.LinkedNodeKind.implementsClause,
-        _variantField_2 = implementsClause_interfaces;
-
-  LinkedNodeBuilder.instanceCreationExpression({
-    List<LinkedNodeBuilder> instanceCreationExpression_arguments,
-    LinkedNodeBuilder instanceCreationExpression_constructorName,
-    LinkedNodeBuilder instanceCreationExpression_typeArguments,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.instanceCreationExpression,
-        _variantField_2 = instanceCreationExpression_arguments,
-        _variantField_7 = instanceCreationExpression_constructorName,
-        _variantField_8 = instanceCreationExpression_typeArguments,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.labeledStatement({
-    List<LinkedNodeBuilder> labeledStatement_labels,
-    LinkedNodeBuilder labeledStatement_statement,
-  })  : _kind = idl.LinkedNodeKind.labeledStatement,
-        _variantField_2 = labeledStatement_labels,
-        _variantField_6 = labeledStatement_statement;
-
-  LinkedNodeBuilder.libraryIdentifier({
-    List<LinkedNodeBuilder> libraryIdentifier_components,
-  })  : _kind = idl.LinkedNodeKind.libraryIdentifier,
-        _variantField_2 = libraryIdentifier_components;
-
-  LinkedNodeBuilder.exportDirective({
-    List<LinkedNodeBuilder> namespaceDirective_combinators,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    List<LinkedNodeBuilder> namespaceDirective_configurations,
-    int nameOffset,
-    LinkedNodeBuilder uriBasedDirective_uri,
-    String namespaceDirective_selectedUri,
-    String uriBasedDirective_uriContent,
-    int uriBasedDirective_uriElement,
-  })  : _kind = idl.LinkedNodeKind.exportDirective,
-        _variantField_2 = namespaceDirective_combinators,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_3 = namespaceDirective_configurations,
-        _variantField_16 = nameOffset,
-        _variantField_14 = uriBasedDirective_uri,
-        _variantField_20 = namespaceDirective_selectedUri,
-        _variantField_22 = uriBasedDirective_uriContent,
-        _variantField_19 = uriBasedDirective_uriElement;
-
-  LinkedNodeBuilder.importDirective({
-    List<LinkedNodeBuilder> namespaceDirective_combinators,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    int importDirective_prefixOffset,
-    List<LinkedNodeBuilder> namespaceDirective_configurations,
-    String importDirective_prefix,
-    int nameOffset,
-    LinkedNodeBuilder uriBasedDirective_uri,
-    String namespaceDirective_selectedUri,
-    String uriBasedDirective_uriContent,
-    int uriBasedDirective_uriElement,
-  })  : _kind = idl.LinkedNodeKind.importDirective,
-        _variantField_2 = namespaceDirective_combinators,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_15 = importDirective_prefixOffset,
-        _variantField_3 = namespaceDirective_configurations,
-        _variantField_1 = importDirective_prefix,
-        _variantField_16 = nameOffset,
-        _variantField_14 = uriBasedDirective_uri,
-        _variantField_20 = namespaceDirective_selectedUri,
-        _variantField_22 = uriBasedDirective_uriContent,
-        _variantField_19 = uriBasedDirective_uriElement;
-
-  LinkedNodeBuilder.onClause({
-    List<LinkedNodeBuilder> onClause_superclassConstraints,
-  })  : _kind = idl.LinkedNodeKind.onClause,
-        _variantField_2 = onClause_superclassConstraints;
-
-  LinkedNodeBuilder.stringInterpolation({
-    List<LinkedNodeBuilder> stringInterpolation_elements,
-  })  : _kind = idl.LinkedNodeKind.stringInterpolation,
-        _variantField_2 = stringInterpolation_elements;
-
-  LinkedNodeBuilder.switchStatement({
-    List<LinkedNodeBuilder> switchStatement_members,
-    LinkedNodeBuilder switchStatement_expression,
-  })  : _kind = idl.LinkedNodeKind.switchStatement,
-        _variantField_2 = switchStatement_members,
-        _variantField_7 = switchStatement_expression;
-
-  LinkedNodeBuilder.tryStatement({
-    List<LinkedNodeBuilder> tryStatement_catchClauses,
-    LinkedNodeBuilder tryStatement_body,
-    LinkedNodeBuilder tryStatement_finallyBlock,
-  })  : _kind = idl.LinkedNodeKind.tryStatement,
-        _variantField_2 = tryStatement_catchClauses,
-        _variantField_6 = tryStatement_body,
-        _variantField_7 = tryStatement_finallyBlock;
-
-  LinkedNodeBuilder.typeArgumentList({
-    List<LinkedNodeBuilder> typeArgumentList_arguments,
-  })  : _kind = idl.LinkedNodeKind.typeArgumentList,
-        _variantField_2 = typeArgumentList_arguments;
-
-  LinkedNodeBuilder.listLiteral({
-    List<LinkedNodeBuilder> typedLiteral_typeArguments,
-    List<LinkedNodeBuilder> listLiteral_elements,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.listLiteral,
-        _variantField_2 = typedLiteral_typeArguments,
-        _variantField_3 = listLiteral_elements,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.setOrMapLiteral({
-    List<LinkedNodeBuilder> typedLiteral_typeArguments,
-    List<LinkedNodeBuilder> setOrMapLiteral_elements,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.setOrMapLiteral,
-        _variantField_2 = typedLiteral_typeArguments,
-        _variantField_3 = setOrMapLiteral_elements,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.typeName({
-    List<LinkedNodeBuilder> typeName_typeArguments,
-    LinkedNodeBuilder typeName_name,
-    LinkedNodeTypeBuilder typeName_type,
-  })  : _kind = idl.LinkedNodeKind.typeName,
-        _variantField_2 = typeName_typeArguments,
-        _variantField_6 = typeName_name,
-        _variantField_23 = typeName_type;
-
-  LinkedNodeBuilder.typeParameterList({
-    List<LinkedNodeBuilder> typeParameterList_typeParameters,
-  })  : _kind = idl.LinkedNodeKind.typeParameterList,
-        _variantField_2 = typeParameterList_typeParameters;
-
-  LinkedNodeBuilder.variableDeclarationList({
-    List<LinkedNodeBuilder> variableDeclarationList_variables,
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder variableDeclarationList_type,
-  })  : _kind = idl.LinkedNodeKind.variableDeclarationList,
-        _variantField_2 = variableDeclarationList_variables,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = variableDeclarationList_type;
-
-  LinkedNodeBuilder.withClause({
-    List<LinkedNodeBuilder> withClause_mixinTypes,
-  })  : _kind = idl.LinkedNodeKind.withClause,
-        _variantField_2 = withClause_mixinTypes;
-
-  LinkedNodeBuilder.classDeclaration({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder classDeclaration_extendsClause,
-    LinkedNodeBuilder classDeclaration_withClause,
-    LinkedNodeBuilder classDeclaration_nativeClause,
-    bool classDeclaration_isDartObject,
-    LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
-    List<LinkedNodeBuilder> classOrMixinDeclaration_members,
-    LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
-    int codeLength,
-    int codeOffset,
-    int nameOffset,
-    bool simplyBoundable_isSimplyBounded,
-  })  : _kind = idl.LinkedNodeKind.classDeclaration,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = classDeclaration_extendsClause,
-        _variantField_7 = classDeclaration_withClause,
-        _variantField_8 = classDeclaration_nativeClause,
-        _variantField_27 = classDeclaration_isDartObject,
-        _variantField_12 = classOrMixinDeclaration_implementsClause,
-        _variantField_5 = classOrMixinDeclaration_members,
-        _variantField_13 = classOrMixinDeclaration_typeParameters,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_16 = nameOffset,
-        _variantField_31 = simplyBoundable_isSimplyBounded;
-
-  LinkedNodeBuilder.classTypeAlias({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder classTypeAlias_typeParameters,
-    LinkedNodeBuilder classTypeAlias_superclass,
-    LinkedNodeBuilder classTypeAlias_withClause,
-    LinkedNodeBuilder classTypeAlias_implementsClause,
-    int codeLength,
-    int codeOffset,
-    int nameOffset,
-    bool simplyBoundable_isSimplyBounded,
-  })  : _kind = idl.LinkedNodeKind.classTypeAlias,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = classTypeAlias_typeParameters,
-        _variantField_7 = classTypeAlias_superclass,
-        _variantField_8 = classTypeAlias_withClause,
-        _variantField_9 = classTypeAlias_implementsClause,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_16 = nameOffset,
-        _variantField_31 = simplyBoundable_isSimplyBounded;
-
-  LinkedNodeBuilder.declaredIdentifier({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder declaredIdentifier_identifier,
-    LinkedNodeBuilder declaredIdentifier_type,
-  })  : _kind = idl.LinkedNodeKind.declaredIdentifier,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = declaredIdentifier_identifier,
-        _variantField_7 = declaredIdentifier_type;
-
-  LinkedNodeBuilder.enumConstantDeclaration({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    int nameOffset,
-  })  : _kind = idl.LinkedNodeKind.enumConstantDeclaration,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_16 = nameOffset;
-
-  LinkedNodeBuilder.fieldDeclaration({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder fieldDeclaration_fields,
-  })  : _kind = idl.LinkedNodeKind.fieldDeclaration,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = fieldDeclaration_fields;
-
-  LinkedNodeBuilder.genericTypeAlias({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder genericTypeAlias_typeParameters,
-    LinkedNodeBuilder genericTypeAlias_functionType,
-    bool typeAlias_hasSelfReference,
-    int codeLength,
-    int codeOffset,
-    int nameOffset,
-    bool simplyBoundable_isSimplyBounded,
-  })  : _kind = idl.LinkedNodeKind.genericTypeAlias,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = genericTypeAlias_typeParameters,
-        _variantField_7 = genericTypeAlias_functionType,
-        _variantField_27 = typeAlias_hasSelfReference,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_16 = nameOffset,
-        _variantField_31 = simplyBoundable_isSimplyBounded;
-
-  LinkedNodeBuilder.libraryDirective({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder libraryDirective_name,
-  })  : _kind = idl.LinkedNodeKind.libraryDirective,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = libraryDirective_name;
-
-  LinkedNodeBuilder.mixinDeclaration({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder mixinDeclaration_onClause,
-    LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
-    List<LinkedNodeBuilder> classOrMixinDeclaration_members,
-    LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
-    int codeLength,
-    int codeOffset,
-    List<String> mixinDeclaration_superInvokedNames,
-    int nameOffset,
-    bool simplyBoundable_isSimplyBounded,
-  })  : _kind = idl.LinkedNodeKind.mixinDeclaration,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = mixinDeclaration_onClause,
-        _variantField_12 = classOrMixinDeclaration_implementsClause,
-        _variantField_5 = classOrMixinDeclaration_members,
-        _variantField_13 = classOrMixinDeclaration_typeParameters,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_36 = mixinDeclaration_superInvokedNames,
-        _variantField_16 = nameOffset,
-        _variantField_31 = simplyBoundable_isSimplyBounded;
-
-  LinkedNodeBuilder.partDirective({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    int nameOffset,
-    LinkedNodeBuilder uriBasedDirective_uri,
-    String uriBasedDirective_uriContent,
-    int uriBasedDirective_uriElement,
-  })  : _kind = idl.LinkedNodeKind.partDirective,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_16 = nameOffset,
-        _variantField_14 = uriBasedDirective_uri,
-        _variantField_22 = uriBasedDirective_uriContent,
-        _variantField_19 = uriBasedDirective_uriElement;
-
-  LinkedNodeBuilder.partOfDirective({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder partOfDirective_libraryName,
-    LinkedNodeBuilder partOfDirective_uri,
-  })  : _kind = idl.LinkedNodeKind.partOfDirective,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = partOfDirective_libraryName,
-        _variantField_7 = partOfDirective_uri;
-
-  LinkedNodeBuilder.topLevelVariableDeclaration({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder topLevelVariableDeclaration_variableList,
-  })  : _kind = idl.LinkedNodeKind.topLevelVariableDeclaration,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = topLevelVariableDeclaration_variableList;
-
-  LinkedNodeBuilder.typeParameter({
-    LinkedNodeBuilder annotatedNode_comment,
-    List<LinkedNodeBuilder> annotatedNode_metadata,
-    LinkedNodeBuilder typeParameter_bound,
-    LinkedNodeTypeBuilder typeParameter_defaultType,
-    int codeLength,
-    int codeOffset,
-    int nameOffset,
-  })  : _kind = idl.LinkedNodeKind.typeParameter,
-        _variantField_11 = annotatedNode_comment,
-        _variantField_4 = annotatedNode_metadata,
-        _variantField_6 = typeParameter_bound,
-        _variantField_23 = typeParameter_defaultType,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
-        _variantField_16 = nameOffset;
-
-  LinkedNodeBuilder.switchCase({
-    List<LinkedNodeBuilder> switchMember_statements,
-    LinkedNodeBuilder switchCase_expression,
-    List<LinkedNodeBuilder> switchMember_labels,
-  })  : _kind = idl.LinkedNodeKind.switchCase,
-        _variantField_4 = switchMember_statements,
-        _variantField_6 = switchCase_expression,
-        _variantField_3 = switchMember_labels;
-
-  LinkedNodeBuilder.switchDefault({
-    List<LinkedNodeBuilder> switchMember_statements,
-    List<LinkedNodeBuilder> switchMember_labels,
-  })  : _kind = idl.LinkedNodeKind.switchDefault,
-        _variantField_4 = switchMember_statements,
-        _variantField_3 = switchMember_labels;
-
   LinkedNodeBuilder.annotation({
     LinkedNodeBuilder annotation_arguments,
     LinkedNodeBuilder annotation_constructorName,
@@ -8528,6 +7936,11 @@
         _variantField_23 = annotation_elementType,
         _variantField_8 = annotation_name;
 
+  LinkedNodeBuilder.argumentList({
+    List<LinkedNodeBuilder> argumentList_arguments,
+  })  : _kind = idl.LinkedNodeKind.argumentList,
+        _variantField_2 = argumentList_arguments;
+
   LinkedNodeBuilder.asExpression({
     LinkedNodeBuilder asExpression_expression,
     LinkedNodeBuilder asExpression_type,
@@ -8573,16 +7986,52 @@
         _variantField_6 = awaitExpression_expression,
         _variantField_25 = expression_type;
 
+  LinkedNodeBuilder.binaryExpression({
+    LinkedNodeTypeBuilder binaryExpression_invokeType,
+    LinkedNodeBuilder binaryExpression_leftOperand,
+    LinkedNodeBuilder binaryExpression_rightOperand,
+    LinkedNodeTypeBuilder binaryExpression_elementType,
+    int binaryExpression_element,
+    idl.UnlinkedTokenType binaryExpression_operator,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.binaryExpression,
+        _variantField_24 = binaryExpression_invokeType,
+        _variantField_6 = binaryExpression_leftOperand,
+        _variantField_7 = binaryExpression_rightOperand,
+        _variantField_23 = binaryExpression_elementType,
+        _variantField_15 = binaryExpression_element,
+        _variantField_28 = binaryExpression_operator,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.block({
+    List<LinkedNodeBuilder> block_statements,
+  })  : _kind = idl.LinkedNodeKind.block,
+        _variantField_2 = block_statements;
+
   LinkedNodeBuilder.blockFunctionBody({
     LinkedNodeBuilder blockFunctionBody_block,
   })  : _kind = idl.LinkedNodeKind.blockFunctionBody,
         _variantField_6 = blockFunctionBody_block;
 
+  LinkedNodeBuilder.booleanLiteral({
+    bool booleanLiteral_value,
+  })  : _kind = idl.LinkedNodeKind.booleanLiteral,
+        _variantField_27 = booleanLiteral_value;
+
   LinkedNodeBuilder.breakStatement({
     LinkedNodeBuilder breakStatement_label,
   })  : _kind = idl.LinkedNodeKind.breakStatement,
         _variantField_6 = breakStatement_label;
 
+  LinkedNodeBuilder.cascadeExpression({
+    List<LinkedNodeBuilder> cascadeExpression_sections,
+    LinkedNodeBuilder cascadeExpression_target,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.cascadeExpression,
+        _variantField_2 = cascadeExpression_sections,
+        _variantField_6 = cascadeExpression_target,
+        _variantField_25 = expression_type;
+
   LinkedNodeBuilder.catchClause({
     LinkedNodeBuilder catchClause_body,
     LinkedNodeBuilder catchClause_exceptionParameter,
@@ -8594,11 +8043,85 @@
         _variantField_8 = catchClause_exceptionType,
         _variantField_9 = catchClause_stackTraceParameter;
 
+  LinkedNodeBuilder.classDeclaration({
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder classDeclaration_extendsClause,
+    LinkedNodeBuilder classDeclaration_withClause,
+    LinkedNodeBuilder classDeclaration_nativeClause,
+    bool classDeclaration_isDartObject,
+    LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
+    List<LinkedNodeBuilder> classOrMixinDeclaration_members,
+    LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
+    int codeLength,
+    int codeOffset,
+    LinkedNodeBuilder namedCompilationUnitMember_name,
+    bool simplyBoundable_isSimplyBounded,
+  })  : _kind = idl.LinkedNodeKind.classDeclaration,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = classDeclaration_extendsClause,
+        _variantField_7 = classDeclaration_withClause,
+        _variantField_8 = classDeclaration_nativeClause,
+        _variantField_27 = classDeclaration_isDartObject,
+        _variantField_12 = classOrMixinDeclaration_implementsClause,
+        _variantField_5 = classOrMixinDeclaration_members,
+        _variantField_13 = classOrMixinDeclaration_typeParameters,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
+        _variantField_10 = namedCompilationUnitMember_name,
+        _variantField_31 = simplyBoundable_isSimplyBounded;
+
+  LinkedNodeBuilder.classTypeAlias({
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder classTypeAlias_typeParameters,
+    LinkedNodeBuilder classTypeAlias_superclass,
+    LinkedNodeBuilder classTypeAlias_withClause,
+    LinkedNodeBuilder classTypeAlias_implementsClause,
+    int codeLength,
+    int codeOffset,
+    LinkedNodeBuilder namedCompilationUnitMember_name,
+    bool simplyBoundable_isSimplyBounded,
+  })  : _kind = idl.LinkedNodeKind.classTypeAlias,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = classTypeAlias_typeParameters,
+        _variantField_7 = classTypeAlias_superclass,
+        _variantField_8 = classTypeAlias_withClause,
+        _variantField_9 = classTypeAlias_implementsClause,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
+        _variantField_10 = namedCompilationUnitMember_name,
+        _variantField_31 = simplyBoundable_isSimplyBounded;
+
+  LinkedNodeBuilder.comment({
+    List<LinkedNodeBuilder> comment_references,
+    List<String> comment_tokens,
+    idl.LinkedNodeCommentType comment_type,
+  })  : _kind = idl.LinkedNodeKind.comment,
+        _variantField_2 = comment_references,
+        _variantField_35 = comment_tokens,
+        _variantField_29 = comment_type;
+
   LinkedNodeBuilder.commentReference({
     LinkedNodeBuilder commentReference_identifier,
   })  : _kind = idl.LinkedNodeKind.commentReference,
         _variantField_6 = commentReference_identifier;
 
+  LinkedNodeBuilder.compilationUnit({
+    List<LinkedNodeBuilder> compilationUnit_declarations,
+    LinkedNodeBuilder compilationUnit_scriptTag,
+    int codeLength,
+    int codeOffset,
+    List<LinkedNodeBuilder> compilationUnit_directives,
+  })  : _kind = idl.LinkedNodeKind.compilationUnit,
+        _variantField_2 = compilationUnit_declarations,
+        _variantField_6 = compilationUnit_scriptTag,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
+        _variantField_3 = compilationUnit_directives;
+
   LinkedNodeBuilder.conditionalExpression({
     LinkedNodeBuilder conditionalExpression_condition,
     LinkedNodeBuilder conditionalExpression_elseExpression,
@@ -8619,6 +8142,31 @@
         _variantField_7 = configuration_value,
         _variantField_8 = configuration_uri;
 
+  LinkedNodeBuilder.constructorDeclaration({
+    List<LinkedNodeBuilder> constructorDeclaration_initializers,
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder constructorDeclaration_body,
+    LinkedNodeBuilder constructorDeclaration_name,
+    LinkedNodeBuilder constructorDeclaration_parameters,
+    LinkedNodeBuilder constructorDeclaration_redirectedConstructor,
+    int codeLength,
+    int codeOffset,
+    int constructorDeclaration_periodOffset,
+    LinkedNodeBuilder constructorDeclaration_returnType,
+  })  : _kind = idl.LinkedNodeKind.constructorDeclaration,
+        _variantField_2 = constructorDeclaration_initializers,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = constructorDeclaration_body,
+        _variantField_7 = constructorDeclaration_name,
+        _variantField_8 = constructorDeclaration_parameters,
+        _variantField_9 = constructorDeclaration_redirectedConstructor,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
+        _variantField_19 = constructorDeclaration_periodOffset,
+        _variantField_10 = constructorDeclaration_returnType;
+
   LinkedNodeBuilder.constructorFieldInitializer({
     LinkedNodeBuilder constructorFieldInitializer_expression,
     LinkedNodeBuilder constructorFieldInitializer_fieldName,
@@ -8642,6 +8190,17 @@
   })  : _kind = idl.LinkedNodeKind.continueStatement,
         _variantField_6 = continueStatement_label;
 
+  LinkedNodeBuilder.declaredIdentifier({
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder declaredIdentifier_identifier,
+    LinkedNodeBuilder declaredIdentifier_type,
+  })  : _kind = idl.LinkedNodeKind.declaredIdentifier,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = declaredIdentifier_identifier,
+        _variantField_7 = declaredIdentifier_type;
+
   LinkedNodeBuilder.defaultFormalParameter({
     LinkedNodeBuilder defaultFormalParameter_defaultValue,
     LinkedNodeBuilder defaultFormalParameter_parameter,
@@ -8651,8 +8210,8 @@
   })  : _kind = idl.LinkedNodeKind.defaultFormalParameter,
         _variantField_6 = defaultFormalParameter_defaultValue,
         _variantField_7 = defaultFormalParameter_parameter,
-        _variantField_34 = codeLength,
-        _variantField_33 = codeOffset,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
         _variantField_26 = defaultFormalParameter_kind;
 
   LinkedNodeBuilder.doStatement({
@@ -8662,6 +8221,71 @@
         _variantField_6 = doStatement_body,
         _variantField_7 = doStatement_condition;
 
+  LinkedNodeBuilder.dottedName({
+    List<LinkedNodeBuilder> dottedName_components,
+  })  : _kind = idl.LinkedNodeKind.dottedName,
+        _variantField_2 = dottedName_components;
+
+  LinkedNodeBuilder.doubleLiteral({
+    double doubleLiteral_value,
+  })  : _kind = idl.LinkedNodeKind.doubleLiteral,
+        _variantField_21 = doubleLiteral_value;
+
+  LinkedNodeBuilder.emptyFunctionBody({
+    int emptyFunctionBody_fake,
+  })  : _kind = idl.LinkedNodeKind.emptyFunctionBody,
+        _variantField_15 = emptyFunctionBody_fake;
+
+  LinkedNodeBuilder.emptyStatement({
+    int emptyStatement_fake,
+  })  : _kind = idl.LinkedNodeKind.emptyStatement,
+        _variantField_15 = emptyStatement_fake;
+
+  LinkedNodeBuilder.enumConstantDeclaration({
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder enumConstantDeclaration_name,
+  })  : _kind = idl.LinkedNodeKind.enumConstantDeclaration,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = enumConstantDeclaration_name;
+
+  LinkedNodeBuilder.enumDeclaration({
+    List<LinkedNodeBuilder> enumDeclaration_constants,
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    int codeLength,
+    int codeOffset,
+    LinkedNodeBuilder namedCompilationUnitMember_name,
+  })  : _kind = idl.LinkedNodeKind.enumDeclaration,
+        _variantField_2 = enumDeclaration_constants,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
+        _variantField_10 = namedCompilationUnitMember_name;
+
+  LinkedNodeBuilder.exportDirective({
+    List<LinkedNodeBuilder> namespaceDirective_combinators,
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    int directive_keywordOffset,
+    List<LinkedNodeBuilder> namespaceDirective_configurations,
+    int uriBasedDirective_uriElement,
+    LinkedNodeBuilder uriBasedDirective_uri,
+    String namespaceDirective_selectedUri,
+    String uriBasedDirective_uriContent,
+  })  : _kind = idl.LinkedNodeKind.exportDirective,
+        _variantField_2 = namespaceDirective_combinators,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_17 = directive_keywordOffset,
+        _variantField_3 = namespaceDirective_configurations,
+        _variantField_19 = uriBasedDirective_uriElement,
+        _variantField_14 = uriBasedDirective_uri,
+        _variantField_20 = namespaceDirective_selectedUri,
+        _variantField_22 = uriBasedDirective_uriContent;
+
   LinkedNodeBuilder.expressionFunctionBody({
     LinkedNodeBuilder expressionFunctionBody_expression,
   })  : _kind = idl.LinkedNodeKind.expressionFunctionBody,
@@ -8677,6 +8301,38 @@
   })  : _kind = idl.LinkedNodeKind.extendsClause,
         _variantField_6 = extendsClause_superclass;
 
+  LinkedNodeBuilder.fieldDeclaration({
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder fieldDeclaration_fields,
+  })  : _kind = idl.LinkedNodeKind.fieldDeclaration,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = fieldDeclaration_fields;
+
+  LinkedNodeBuilder.fieldFormalParameter({
+    LinkedNodeTypeBuilder actualType,
+    List<LinkedNodeBuilder> normalFormalParameter_metadata,
+    LinkedNodeBuilder fieldFormalParameter_type,
+    LinkedNodeBuilder fieldFormalParameter_typeParameters,
+    LinkedNodeBuilder fieldFormalParameter_formalParameters,
+    bool inheritsCovariant,
+    LinkedNodeBuilder normalFormalParameter_identifier,
+    int codeLength,
+    int codeOffset,
+    LinkedNodeBuilder normalFormalParameter_comment,
+  })  : _kind = idl.LinkedNodeKind.fieldFormalParameter,
+        _variantField_24 = actualType,
+        _variantField_4 = normalFormalParameter_metadata,
+        _variantField_6 = fieldFormalParameter_type,
+        _variantField_7 = fieldFormalParameter_typeParameters,
+        _variantField_8 = fieldFormalParameter_formalParameters,
+        _variantField_27 = inheritsCovariant,
+        _variantField_9 = normalFormalParameter_identifier,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
+        _variantField_14 = normalFormalParameter_comment;
+
   LinkedNodeBuilder.forEachPartsWithDeclaration({
     LinkedNodeBuilder forEachParts_iterable,
     LinkedNodeBuilder forEachPartsWithDeclaration_loopVariable,
@@ -8698,13 +8354,6 @@
         _variantField_6 = forMixin_forLoopParts,
         _variantField_7 = forElement_body;
 
-  LinkedNodeBuilder.forStatement({
-    LinkedNodeBuilder forMixin_forLoopParts,
-    LinkedNodeBuilder forStatement_body,
-  })  : _kind = idl.LinkedNodeKind.forStatement,
-        _variantField_6 = forMixin_forLoopParts,
-        _variantField_7 = forStatement_body;
-
   LinkedNodeBuilder.forPartsWithDeclarations({
     LinkedNodeBuilder forParts_condition,
     LinkedNodeBuilder forPartsWithDeclarations_variables,
@@ -8723,11 +8372,155 @@
         _variantField_7 = forPartsWithExpression_initialization,
         _variantField_5 = forParts_updaters;
 
+  LinkedNodeBuilder.forStatement({
+    LinkedNodeBuilder forMixin_forLoopParts,
+    LinkedNodeBuilder forStatement_body,
+  })  : _kind = idl.LinkedNodeKind.forStatement,
+        _variantField_6 = forMixin_forLoopParts,
+        _variantField_7 = forStatement_body;
+
+  LinkedNodeBuilder.formalParameterList({
+    List<LinkedNodeBuilder> formalParameterList_parameters,
+  })  : _kind = idl.LinkedNodeKind.formalParameterList,
+        _variantField_2 = formalParameterList_parameters;
+
+  LinkedNodeBuilder.functionDeclaration({
+    LinkedNodeTypeBuilder actualReturnType,
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder functionDeclaration_functionExpression,
+    LinkedNodeBuilder functionDeclaration_returnType,
+    int codeLength,
+    int codeOffset,
+    LinkedNodeBuilder namedCompilationUnitMember_name,
+  })  : _kind = idl.LinkedNodeKind.functionDeclaration,
+        _variantField_24 = actualReturnType,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = functionDeclaration_functionExpression,
+        _variantField_7 = functionDeclaration_returnType,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
+        _variantField_10 = namedCompilationUnitMember_name;
+
   LinkedNodeBuilder.functionDeclarationStatement({
     LinkedNodeBuilder functionDeclarationStatement_functionDeclaration,
   })  : _kind = idl.LinkedNodeKind.functionDeclarationStatement,
         _variantField_6 = functionDeclarationStatement_functionDeclaration;
 
+  LinkedNodeBuilder.functionExpression({
+    LinkedNodeTypeBuilder actualReturnType,
+    LinkedNodeBuilder functionExpression_body,
+    LinkedNodeBuilder functionExpression_formalParameters,
+    LinkedNodeBuilder functionExpression_typeParameters,
+  })  : _kind = idl.LinkedNodeKind.functionExpression,
+        _variantField_24 = actualReturnType,
+        _variantField_6 = functionExpression_body,
+        _variantField_7 = functionExpression_formalParameters,
+        _variantField_8 = functionExpression_typeParameters;
+
+  LinkedNodeBuilder.functionExpressionInvocation({
+    LinkedNodeTypeBuilder invocationExpression_invokeType,
+    LinkedNodeBuilder functionExpressionInvocation_function,
+    LinkedNodeBuilder invocationExpression_typeArguments,
+    LinkedNodeTypeBuilder expression_type,
+    LinkedNodeBuilder invocationExpression_arguments,
+  })  : _kind = idl.LinkedNodeKind.functionExpressionInvocation,
+        _variantField_24 = invocationExpression_invokeType,
+        _variantField_6 = functionExpressionInvocation_function,
+        _variantField_12 = invocationExpression_typeArguments,
+        _variantField_25 = expression_type,
+        _variantField_14 = invocationExpression_arguments;
+
+  LinkedNodeBuilder.functionTypeAlias({
+    LinkedNodeTypeBuilder actualReturnType,
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder functionTypeAlias_formalParameters,
+    LinkedNodeBuilder functionTypeAlias_returnType,
+    LinkedNodeBuilder functionTypeAlias_typeParameters,
+    bool typeAlias_hasSelfReference,
+    int codeLength,
+    int codeOffset,
+    LinkedNodeBuilder namedCompilationUnitMember_name,
+    bool simplyBoundable_isSimplyBounded,
+  })  : _kind = idl.LinkedNodeKind.functionTypeAlias,
+        _variantField_24 = actualReturnType,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = functionTypeAlias_formalParameters,
+        _variantField_7 = functionTypeAlias_returnType,
+        _variantField_8 = functionTypeAlias_typeParameters,
+        _variantField_27 = typeAlias_hasSelfReference,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
+        _variantField_10 = namedCompilationUnitMember_name,
+        _variantField_31 = simplyBoundable_isSimplyBounded;
+
+  LinkedNodeBuilder.functionTypedFormalParameter({
+    LinkedNodeTypeBuilder actualType,
+    List<LinkedNodeBuilder> normalFormalParameter_metadata,
+    LinkedNodeBuilder functionTypedFormalParameter_formalParameters,
+    LinkedNodeBuilder functionTypedFormalParameter_returnType,
+    LinkedNodeBuilder functionTypedFormalParameter_typeParameters,
+    bool inheritsCovariant,
+    LinkedNodeBuilder normalFormalParameter_identifier,
+    int codeLength,
+    int codeOffset,
+    LinkedNodeBuilder normalFormalParameter_comment,
+  })  : _kind = idl.LinkedNodeKind.functionTypedFormalParameter,
+        _variantField_24 = actualType,
+        _variantField_4 = normalFormalParameter_metadata,
+        _variantField_6 = functionTypedFormalParameter_formalParameters,
+        _variantField_7 = functionTypedFormalParameter_returnType,
+        _variantField_8 = functionTypedFormalParameter_typeParameters,
+        _variantField_27 = inheritsCovariant,
+        _variantField_9 = normalFormalParameter_identifier,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
+        _variantField_14 = normalFormalParameter_comment;
+
+  LinkedNodeBuilder.genericFunctionType({
+    LinkedNodeTypeBuilder actualReturnType,
+    LinkedNodeBuilder genericFunctionType_typeParameters,
+    LinkedNodeBuilder genericFunctionType_returnType,
+    int genericFunctionType_id,
+    LinkedNodeBuilder genericFunctionType_formalParameters,
+    LinkedNodeTypeBuilder genericFunctionType_type,
+  })  : _kind = idl.LinkedNodeKind.genericFunctionType,
+        _variantField_24 = actualReturnType,
+        _variantField_6 = genericFunctionType_typeParameters,
+        _variantField_7 = genericFunctionType_returnType,
+        _variantField_17 = genericFunctionType_id,
+        _variantField_8 = genericFunctionType_formalParameters,
+        _variantField_25 = genericFunctionType_type;
+
+  LinkedNodeBuilder.genericTypeAlias({
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder genericTypeAlias_typeParameters,
+    LinkedNodeBuilder genericTypeAlias_functionType,
+    bool typeAlias_hasSelfReference,
+    int codeLength,
+    int codeOffset,
+    LinkedNodeBuilder namedCompilationUnitMember_name,
+    bool simplyBoundable_isSimplyBounded,
+  })  : _kind = idl.LinkedNodeKind.genericTypeAlias,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = genericTypeAlias_typeParameters,
+        _variantField_7 = genericTypeAlias_functionType,
+        _variantField_27 = typeAlias_hasSelfReference,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
+        _variantField_10 = namedCompilationUnitMember_name,
+        _variantField_31 = simplyBoundable_isSimplyBounded;
+
+  LinkedNodeBuilder.hideCombinator({
+    List<String> names,
+  })  : _kind = idl.LinkedNodeKind.hideCombinator,
+        _variantField_36 = names;
+
   LinkedNodeBuilder.ifElement({
     LinkedNodeBuilder ifMixin_condition,
     LinkedNodeBuilder ifElement_thenElement,
@@ -8746,6 +8539,36 @@
         _variantField_7 = ifStatement_elseStatement,
         _variantField_8 = ifStatement_thenStatement;
 
+  LinkedNodeBuilder.implementsClause({
+    List<LinkedNodeBuilder> implementsClause_interfaces,
+  })  : _kind = idl.LinkedNodeKind.implementsClause,
+        _variantField_2 = implementsClause_interfaces;
+
+  LinkedNodeBuilder.importDirective({
+    List<LinkedNodeBuilder> namespaceDirective_combinators,
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    int directive_keywordOffset,
+    int importDirective_prefixOffset,
+    List<LinkedNodeBuilder> namespaceDirective_configurations,
+    int uriBasedDirective_uriElement,
+    String importDirective_prefix,
+    LinkedNodeBuilder uriBasedDirective_uri,
+    String namespaceDirective_selectedUri,
+    String uriBasedDirective_uriContent,
+  })  : _kind = idl.LinkedNodeKind.importDirective,
+        _variantField_2 = namespaceDirective_combinators,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_17 = directive_keywordOffset,
+        _variantField_15 = importDirective_prefixOffset,
+        _variantField_3 = namespaceDirective_configurations,
+        _variantField_19 = uriBasedDirective_uriElement,
+        _variantField_1 = importDirective_prefix,
+        _variantField_14 = uriBasedDirective_uri,
+        _variantField_20 = namespaceDirective_selectedUri,
+        _variantField_22 = uriBasedDirective_uriContent;
+
   LinkedNodeBuilder.indexExpression({
     LinkedNodeBuilder indexExpression_index,
     LinkedNodeBuilder indexExpression_target,
@@ -8759,11 +8582,32 @@
         _variantField_15 = indexExpression_element,
         _variantField_25 = expression_type;
 
+  LinkedNodeBuilder.instanceCreationExpression({
+    List<LinkedNodeBuilder> instanceCreationExpression_arguments,
+    LinkedNodeBuilder instanceCreationExpression_constructorName,
+    LinkedNodeBuilder instanceCreationExpression_typeArguments,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.instanceCreationExpression,
+        _variantField_2 = instanceCreationExpression_arguments,
+        _variantField_7 = instanceCreationExpression_constructorName,
+        _variantField_8 = instanceCreationExpression_typeArguments,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.integerLiteral({
+    int integerLiteral_value,
+  })  : _kind = idl.LinkedNodeKind.integerLiteral,
+        _variantField_16 = integerLiteral_value;
+
   LinkedNodeBuilder.interpolationExpression({
     LinkedNodeBuilder interpolationExpression_expression,
   })  : _kind = idl.LinkedNodeKind.interpolationExpression,
         _variantField_6 = interpolationExpression_expression;
 
+  LinkedNodeBuilder.interpolationString({
+    String interpolationString_value,
+  })  : _kind = idl.LinkedNodeKind.interpolationString,
+        _variantField_30 = interpolationString_value;
+
   LinkedNodeBuilder.isExpression({
     LinkedNodeBuilder isExpression_expression,
     LinkedNodeBuilder isExpression_type,
@@ -8776,6 +8620,38 @@
   })  : _kind = idl.LinkedNodeKind.label,
         _variantField_6 = label_label;
 
+  LinkedNodeBuilder.labeledStatement({
+    List<LinkedNodeBuilder> labeledStatement_labels,
+    LinkedNodeBuilder labeledStatement_statement,
+  })  : _kind = idl.LinkedNodeKind.labeledStatement,
+        _variantField_2 = labeledStatement_labels,
+        _variantField_6 = labeledStatement_statement;
+
+  LinkedNodeBuilder.libraryDirective({
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder libraryDirective_name,
+    int directive_keywordOffset,
+  })  : _kind = idl.LinkedNodeKind.libraryDirective,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = libraryDirective_name,
+        _variantField_17 = directive_keywordOffset;
+
+  LinkedNodeBuilder.libraryIdentifier({
+    List<LinkedNodeBuilder> libraryIdentifier_components,
+  })  : _kind = idl.LinkedNodeKind.libraryIdentifier,
+        _variantField_2 = libraryIdentifier_components;
+
+  LinkedNodeBuilder.listLiteral({
+    List<LinkedNodeBuilder> typedLiteral_typeArguments,
+    List<LinkedNodeBuilder> listLiteral_elements,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.listLiteral,
+        _variantField_2 = typedLiteral_typeArguments,
+        _variantField_3 = listLiteral_elements,
+        _variantField_25 = expression_type;
+
   LinkedNodeBuilder.mapLiteralEntry({
     LinkedNodeBuilder mapLiteralEntry_key,
     LinkedNodeBuilder mapLiteralEntry_value,
@@ -8783,6 +8659,69 @@
         _variantField_6 = mapLiteralEntry_key,
         _variantField_7 = mapLiteralEntry_value;
 
+  LinkedNodeBuilder.methodDeclaration({
+    LinkedNodeTypeBuilder actualReturnType,
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder methodDeclaration_body,
+    LinkedNodeBuilder methodDeclaration_formalParameters,
+    LinkedNodeBuilder methodDeclaration_returnType,
+    LinkedNodeBuilder methodDeclaration_typeParameters,
+    int codeLength,
+    int codeOffset,
+    LinkedNodeBuilder methodDeclaration_name,
+  })  : _kind = idl.LinkedNodeKind.methodDeclaration,
+        _variantField_24 = actualReturnType,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = methodDeclaration_body,
+        _variantField_7 = methodDeclaration_formalParameters,
+        _variantField_8 = methodDeclaration_returnType,
+        _variantField_9 = methodDeclaration_typeParameters,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
+        _variantField_10 = methodDeclaration_name;
+
+  LinkedNodeBuilder.methodInvocation({
+    LinkedNodeTypeBuilder invocationExpression_invokeType,
+    LinkedNodeBuilder methodInvocation_methodName,
+    LinkedNodeBuilder methodInvocation_target,
+    LinkedNodeBuilder invocationExpression_typeArguments,
+    LinkedNodeTypeBuilder expression_type,
+    LinkedNodeBuilder invocationExpression_arguments,
+  })  : _kind = idl.LinkedNodeKind.methodInvocation,
+        _variantField_24 = invocationExpression_invokeType,
+        _variantField_6 = methodInvocation_methodName,
+        _variantField_7 = methodInvocation_target,
+        _variantField_12 = invocationExpression_typeArguments,
+        _variantField_25 = expression_type,
+        _variantField_14 = invocationExpression_arguments;
+
+  LinkedNodeBuilder.mixinDeclaration({
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder mixinDeclaration_onClause,
+    LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
+    List<LinkedNodeBuilder> classOrMixinDeclaration_members,
+    LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
+    int codeLength,
+    int codeOffset,
+    LinkedNodeBuilder namedCompilationUnitMember_name,
+    List<String> mixinDeclaration_superInvokedNames,
+    bool simplyBoundable_isSimplyBounded,
+  })  : _kind = idl.LinkedNodeKind.mixinDeclaration,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = mixinDeclaration_onClause,
+        _variantField_12 = classOrMixinDeclaration_implementsClause,
+        _variantField_5 = classOrMixinDeclaration_members,
+        _variantField_13 = classOrMixinDeclaration_typeParameters,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
+        _variantField_10 = namedCompilationUnitMember_name,
+        _variantField_36 = mixinDeclaration_superInvokedNames,
+        _variantField_31 = simplyBoundable_isSimplyBounded;
+
   LinkedNodeBuilder.namedExpression({
     LinkedNodeBuilder namedExpression_expression,
     LinkedNodeBuilder namedExpression_name,
@@ -8800,6 +8739,18 @@
   })  : _kind = idl.LinkedNodeKind.nativeFunctionBody,
         _variantField_6 = nativeFunctionBody_stringLiteral;
 
+  LinkedNodeBuilder.nullLiteral({
+    int nullLiteral_fake,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.nullLiteral,
+        _variantField_15 = nullLiteral_fake,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.onClause({
+    List<LinkedNodeBuilder> onClause_superclassConstraints,
+  })  : _kind = idl.LinkedNodeKind.onClause,
+        _variantField_2 = onClause_superclassConstraints;
+
   LinkedNodeBuilder.parenthesizedExpression({
     LinkedNodeBuilder parenthesizedExpression_expression,
     LinkedNodeTypeBuilder expression_type,
@@ -8807,6 +8758,34 @@
         _variantField_6 = parenthesizedExpression_expression,
         _variantField_25 = expression_type;
 
+  LinkedNodeBuilder.partDirective({
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    int directive_keywordOffset,
+    int uriBasedDirective_uriElement,
+    LinkedNodeBuilder uriBasedDirective_uri,
+    String uriBasedDirective_uriContent,
+  })  : _kind = idl.LinkedNodeKind.partDirective,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_17 = directive_keywordOffset,
+        _variantField_19 = uriBasedDirective_uriElement,
+        _variantField_14 = uriBasedDirective_uri,
+        _variantField_22 = uriBasedDirective_uriContent;
+
+  LinkedNodeBuilder.partOfDirective({
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder partOfDirective_libraryName,
+    LinkedNodeBuilder partOfDirective_uri,
+    int directive_keywordOffset,
+  })  : _kind = idl.LinkedNodeKind.partOfDirective,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = partOfDirective_libraryName,
+        _variantField_7 = partOfDirective_uri,
+        _variantField_17 = directive_keywordOffset;
+
   LinkedNodeBuilder.postfixExpression({
     LinkedNodeBuilder postfixExpression_operand,
     LinkedNodeTypeBuilder postfixExpression_elementType,
@@ -8820,15 +8799,6 @@
         _variantField_28 = postfixExpression_operator,
         _variantField_25 = expression_type;
 
-  LinkedNodeBuilder.prefixedIdentifier({
-    LinkedNodeBuilder prefixedIdentifier_identifier,
-    LinkedNodeBuilder prefixedIdentifier_prefix,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.prefixedIdentifier,
-        _variantField_6 = prefixedIdentifier_identifier,
-        _variantField_7 = prefixedIdentifier_prefix,
-        _variantField_25 = expression_type;
-
   LinkedNodeBuilder.prefixExpression({
     LinkedNodeBuilder prefixExpression_operand,
     LinkedNodeTypeBuilder prefixExpression_elementType,
@@ -8842,6 +8812,15 @@
         _variantField_28 = prefixExpression_operator,
         _variantField_25 = expression_type;
 
+  LinkedNodeBuilder.prefixedIdentifier({
+    LinkedNodeBuilder prefixedIdentifier_identifier,
+    LinkedNodeBuilder prefixedIdentifier_prefix,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.prefixedIdentifier,
+        _variantField_6 = prefixedIdentifier_identifier,
+        _variantField_7 = prefixedIdentifier_prefix,
+        _variantField_25 = expression_type;
+
   LinkedNodeBuilder.propertyAccess({
     LinkedNodeBuilder propertyAccess_propertyName,
     LinkedNodeBuilder propertyAccess_target,
@@ -8864,17 +8843,80 @@
         _variantField_23 = redirectingConstructorInvocation_elementType,
         _variantField_15 = redirectingConstructorInvocation_element;
 
+  LinkedNodeBuilder.rethrowExpression({
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.rethrowExpression,
+        _variantField_25 = expression_type;
+
   LinkedNodeBuilder.returnStatement({
     LinkedNodeBuilder returnStatement_expression,
   })  : _kind = idl.LinkedNodeKind.returnStatement,
         _variantField_6 = returnStatement_expression;
 
+  LinkedNodeBuilder.setOrMapLiteral({
+    List<LinkedNodeBuilder> typedLiteral_typeArguments,
+    List<LinkedNodeBuilder> setOrMapLiteral_elements,
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.setOrMapLiteral,
+        _variantField_2 = typedLiteral_typeArguments,
+        _variantField_3 = setOrMapLiteral_elements,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.showCombinator({
+    List<String> names,
+  })  : _kind = idl.LinkedNodeKind.showCombinator,
+        _variantField_36 = names;
+
+  LinkedNodeBuilder.simpleFormalParameter({
+    LinkedNodeTypeBuilder actualType,
+    List<LinkedNodeBuilder> normalFormalParameter_metadata,
+    LinkedNodeBuilder simpleFormalParameter_type,
+    bool inheritsCovariant,
+    LinkedNodeBuilder normalFormalParameter_identifier,
+    int codeLength,
+    int codeOffset,
+    LinkedNodeBuilder normalFormalParameter_comment,
+    TopLevelInferenceErrorBuilder topLevelTypeInferenceError,
+  })  : _kind = idl.LinkedNodeKind.simpleFormalParameter,
+        _variantField_24 = actualType,
+        _variantField_4 = normalFormalParameter_metadata,
+        _variantField_6 = simpleFormalParameter_type,
+        _variantField_27 = inheritsCovariant,
+        _variantField_9 = normalFormalParameter_identifier,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
+        _variantField_14 = normalFormalParameter_comment,
+        _variantField_34 = topLevelTypeInferenceError;
+
+  LinkedNodeBuilder.simpleIdentifier({
+    LinkedNodeTypeBuilder simpleIdentifier_elementType,
+    int simpleIdentifier_element,
+    LinkedNodeTypeBuilder expression_type,
+    int simpleIdentifier_offset,
+    String simpleIdentifier_name,
+  })  : _kind = idl.LinkedNodeKind.simpleIdentifier,
+        _variantField_23 = simpleIdentifier_elementType,
+        _variantField_15 = simpleIdentifier_element,
+        _variantField_25 = expression_type,
+        _variantField_16 = simpleIdentifier_offset,
+        _variantField_20 = simpleIdentifier_name;
+
+  LinkedNodeBuilder.simpleStringLiteral({
+    String simpleStringLiteral_value,
+  })  : _kind = idl.LinkedNodeKind.simpleStringLiteral,
+        _variantField_20 = simpleStringLiteral_value;
+
   LinkedNodeBuilder.spreadElement({
     LinkedNodeBuilder spreadElement_expression,
     idl.UnlinkedTokenType spreadElement_spreadOperator,
   })  : _kind = idl.LinkedNodeKind.spreadElement,
         _variantField_6 = spreadElement_expression,
-        _variantField_38 = spreadElement_spreadOperator;
+        _variantField_37 = spreadElement_spreadOperator;
+
+  LinkedNodeBuilder.stringInterpolation({
+    List<LinkedNodeBuilder> stringInterpolation_elements,
+  })  : _kind = idl.LinkedNodeKind.stringInterpolation,
+        _variantField_2 = stringInterpolation_elements;
 
   LinkedNodeBuilder.superConstructorInvocation({
     LinkedNodeBuilder superConstructorInvocation_arguments,
@@ -8887,6 +8929,46 @@
         _variantField_23 = superConstructorInvocation_elementType,
         _variantField_15 = superConstructorInvocation_element;
 
+  LinkedNodeBuilder.superExpression({
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.superExpression,
+        _variantField_25 = expression_type;
+
+  LinkedNodeBuilder.switchCase({
+    List<LinkedNodeBuilder> switchMember_statements,
+    LinkedNodeBuilder switchCase_expression,
+    List<LinkedNodeBuilder> switchMember_labels,
+  })  : _kind = idl.LinkedNodeKind.switchCase,
+        _variantField_4 = switchMember_statements,
+        _variantField_6 = switchCase_expression,
+        _variantField_3 = switchMember_labels;
+
+  LinkedNodeBuilder.switchDefault({
+    List<LinkedNodeBuilder> switchMember_statements,
+    List<LinkedNodeBuilder> switchMember_labels,
+  })  : _kind = idl.LinkedNodeKind.switchDefault,
+        _variantField_4 = switchMember_statements,
+        _variantField_3 = switchMember_labels;
+
+  LinkedNodeBuilder.switchStatement({
+    List<LinkedNodeBuilder> switchStatement_members,
+    LinkedNodeBuilder switchStatement_expression,
+  })  : _kind = idl.LinkedNodeKind.switchStatement,
+        _variantField_2 = switchStatement_members,
+        _variantField_7 = switchStatement_expression;
+
+  LinkedNodeBuilder.symbolLiteral({
+    LinkedNodeTypeBuilder expression_type,
+    List<String> names,
+  })  : _kind = idl.LinkedNodeKind.symbolLiteral,
+        _variantField_25 = expression_type,
+        _variantField_36 = names;
+
+  LinkedNodeBuilder.thisExpression({
+    LinkedNodeTypeBuilder expression_type,
+  })  : _kind = idl.LinkedNodeKind.thisExpression,
+        _variantField_25 = expression_type;
+
   LinkedNodeBuilder.throwExpression({
     LinkedNodeBuilder throwExpression_expression,
     LinkedNodeTypeBuilder expression_type,
@@ -8894,6 +8976,92 @@
         _variantField_6 = throwExpression_expression,
         _variantField_25 = expression_type;
 
+  LinkedNodeBuilder.topLevelVariableDeclaration({
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder topLevelVariableDeclaration_variableList,
+  })  : _kind = idl.LinkedNodeKind.topLevelVariableDeclaration,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = topLevelVariableDeclaration_variableList;
+
+  LinkedNodeBuilder.tryStatement({
+    List<LinkedNodeBuilder> tryStatement_catchClauses,
+    LinkedNodeBuilder tryStatement_body,
+    LinkedNodeBuilder tryStatement_finallyBlock,
+  })  : _kind = idl.LinkedNodeKind.tryStatement,
+        _variantField_2 = tryStatement_catchClauses,
+        _variantField_6 = tryStatement_body,
+        _variantField_7 = tryStatement_finallyBlock;
+
+  LinkedNodeBuilder.typeArgumentList({
+    List<LinkedNodeBuilder> typeArgumentList_arguments,
+  })  : _kind = idl.LinkedNodeKind.typeArgumentList,
+        _variantField_2 = typeArgumentList_arguments;
+
+  LinkedNodeBuilder.typeName({
+    List<LinkedNodeBuilder> typeName_typeArguments,
+    LinkedNodeBuilder typeName_name,
+    LinkedNodeTypeBuilder typeName_type,
+  })  : _kind = idl.LinkedNodeKind.typeName,
+        _variantField_2 = typeName_typeArguments,
+        _variantField_6 = typeName_name,
+        _variantField_23 = typeName_type;
+
+  LinkedNodeBuilder.typeParameter({
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder typeParameter_bound,
+    LinkedNodeBuilder typeParameter_name,
+    LinkedNodeTypeBuilder typeParameter_defaultType,
+    int codeLength,
+    int codeOffset,
+  })  : _kind = idl.LinkedNodeKind.typeParameter,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = typeParameter_bound,
+        _variantField_7 = typeParameter_name,
+        _variantField_23 = typeParameter_defaultType,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset;
+
+  LinkedNodeBuilder.typeParameterList({
+    List<LinkedNodeBuilder> typeParameterList_typeParameters,
+  })  : _kind = idl.LinkedNodeKind.typeParameterList,
+        _variantField_2 = typeParameterList_typeParameters;
+
+  LinkedNodeBuilder.variableDeclaration({
+    LinkedNodeTypeBuilder actualType,
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder variableDeclaration_initializer,
+    LinkedNodeBuilder variableDeclaration_name,
+    bool inheritsCovariant,
+    int codeLength,
+    int codeOffset,
+    TopLevelInferenceErrorBuilder topLevelTypeInferenceError,
+  })  : _kind = idl.LinkedNodeKind.variableDeclaration,
+        _variantField_24 = actualType,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = variableDeclaration_initializer,
+        _variantField_7 = variableDeclaration_name,
+        _variantField_27 = inheritsCovariant,
+        _variantField_33 = codeLength,
+        _variantField_32 = codeOffset,
+        _variantField_34 = topLevelTypeInferenceError;
+
+  LinkedNodeBuilder.variableDeclarationList({
+    List<LinkedNodeBuilder> variableDeclarationList_variables,
+    LinkedNodeBuilder annotatedNode_comment,
+    List<LinkedNodeBuilder> annotatedNode_metadata,
+    LinkedNodeBuilder variableDeclarationList_type,
+  })  : _kind = idl.LinkedNodeKind.variableDeclarationList,
+        _variantField_2 = variableDeclarationList_variables,
+        _variantField_11 = annotatedNode_comment,
+        _variantField_4 = annotatedNode_metadata,
+        _variantField_6 = variableDeclarationList_type;
+
   LinkedNodeBuilder.variableDeclarationStatement({
     LinkedNodeBuilder variableDeclarationStatement_variables,
   })  : _kind = idl.LinkedNodeKind.variableDeclarationStatement,
@@ -8906,210 +9074,1973 @@
         _variantField_6 = whileStatement_body,
         _variantField_7 = whileStatement_condition;
 
+  LinkedNodeBuilder.withClause({
+    List<LinkedNodeBuilder> withClause_mixinTypes,
+  })  : _kind = idl.LinkedNodeKind.withClause,
+        _variantField_2 = withClause_mixinTypes;
+
   LinkedNodeBuilder.yieldStatement({
     LinkedNodeBuilder yieldStatement_expression,
   })  : _kind = idl.LinkedNodeKind.yieldStatement,
         _variantField_6 = yieldStatement_expression;
 
-  LinkedNodeBuilder.simpleIdentifier({
-    LinkedNodeTypeBuilder simpleIdentifier_elementType,
-    int simpleIdentifier_element,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.simpleIdentifier,
-        _variantField_23 = simpleIdentifier_elementType,
-        _variantField_15 = simpleIdentifier_element,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.emptyFunctionBody({
-    int emptyFunctionBody_fake,
-  })  : _kind = idl.LinkedNodeKind.emptyFunctionBody,
-        _variantField_15 = emptyFunctionBody_fake;
-
-  LinkedNodeBuilder.emptyStatement({
-    int emptyStatement_fake,
-  })  : _kind = idl.LinkedNodeKind.emptyStatement,
-        _variantField_15 = emptyStatement_fake;
-
-  LinkedNodeBuilder.nullLiteral({
-    int nullLiteral_fake,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.nullLiteral,
-        _variantField_15 = nullLiteral_fake,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.booleanLiteral({
-    bool booleanLiteral_value,
-  })  : _kind = idl.LinkedNodeKind.booleanLiteral,
-        _variantField_27 = booleanLiteral_value;
-
-  LinkedNodeBuilder.hideCombinator({
-    List<String> names,
-  })  : _kind = idl.LinkedNodeKind.hideCombinator,
-        _variantField_36 = names;
-
-  LinkedNodeBuilder.showCombinator({
-    List<String> names,
-  })  : _kind = idl.LinkedNodeKind.showCombinator,
-        _variantField_36 = names;
-
-  LinkedNodeBuilder.symbolLiteral({
-    List<String> names,
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.symbolLiteral,
-        _variantField_36 = names,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.doubleLiteral({
-    double doubleLiteral_value,
-  })  : _kind = idl.LinkedNodeKind.doubleLiteral,
-        _variantField_21 = doubleLiteral_value;
-
-  LinkedNodeBuilder.rethrowExpression({
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.rethrowExpression,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.superExpression({
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.superExpression,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.thisExpression({
-    LinkedNodeTypeBuilder expression_type,
-  })  : _kind = idl.LinkedNodeKind.thisExpression,
-        _variantField_25 = expression_type;
-
-  LinkedNodeBuilder.integerLiteral({
-    int integerLiteral_value,
-  })  : _kind = idl.LinkedNodeKind.integerLiteral,
-        _variantField_16 = integerLiteral_value;
-
-  LinkedNodeBuilder.interpolationString({
-    String interpolationString_value,
-  })  : _kind = idl.LinkedNodeKind.interpolationString,
-        _variantField_30 = interpolationString_value;
-
-  LinkedNodeBuilder.simpleStringLiteral({
-    String simpleStringLiteral_value,
-  })  : _kind = idl.LinkedNodeKind.simpleStringLiteral,
-        _variantField_20 = simpleStringLiteral_value;
-
   /// Flush [informative] data recursively.
   void flushInformative() {
-    _variantField_24?.flushInformative();
-    _variantField_2?.forEach((b) => b.flushInformative());
-    _variantField_11?.flushInformative();
-    _variantField_4?.forEach((b) => b.flushInformative());
-    _variantField_6?.flushInformative();
-    _variantField_7?.flushInformative();
-    _variantField_23?.flushInformative();
-    _variantField_8?.flushInformative();
-    _variantField_9?.flushInformative();
-    _variantField_12?.flushInformative();
-    _variantField_5?.forEach((b) => b.flushInformative());
-    _variantField_13?.flushInformative();
-    _variantField_3?.forEach((b) => b.flushInformative());
-    _variantField_10?.flushInformative();
-    _variantField_25?.flushInformative();
-    _variantField_14?.flushInformative();
-    _variantField_35?.flushInformative();
-    _variantField_32?.flushInformative();
+    if (kind == idl.LinkedNodeKind.adjacentStrings) {
+      adjacentStrings_strings?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.annotation) {
+      annotation_arguments?.flushInformative();
+      annotation_constructorName?.flushInformative();
+      annotation_elementType?.flushInformative();
+      annotation_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.argumentList) {
+      argumentList_arguments?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.asExpression) {
+      asExpression_expression?.flushInformative();
+      asExpression_type?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.assertInitializer) {
+      assertInitializer_condition?.flushInformative();
+      assertInitializer_message?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.assertStatement) {
+      assertStatement_condition?.flushInformative();
+      assertStatement_message?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.assignmentExpression) {
+      assignmentExpression_leftHandSide?.flushInformative();
+      assignmentExpression_rightHandSide?.flushInformative();
+      assignmentExpression_elementType?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.awaitExpression) {
+      awaitExpression_expression?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.binaryExpression) {
+      binaryExpression_invokeType?.flushInformative();
+      binaryExpression_leftOperand?.flushInformative();
+      binaryExpression_rightOperand?.flushInformative();
+      binaryExpression_elementType?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.block) {
+      block_statements?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.blockFunctionBody) {
+      blockFunctionBody_block?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.booleanLiteral) {
+    } else if (kind == idl.LinkedNodeKind.breakStatement) {
+      breakStatement_label?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.cascadeExpression) {
+      cascadeExpression_sections?.forEach((b) => b.flushInformative());
+      cascadeExpression_target?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.catchClause) {
+      catchClause_body?.flushInformative();
+      catchClause_exceptionParameter?.flushInformative();
+      catchClause_exceptionType?.flushInformative();
+      catchClause_stackTraceParameter?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.classDeclaration) {
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      classDeclaration_extendsClause?.flushInformative();
+      classDeclaration_withClause?.flushInformative();
+      classDeclaration_nativeClause?.flushInformative();
+      classOrMixinDeclaration_implementsClause?.flushInformative();
+      classOrMixinDeclaration_members?.forEach((b) => b.flushInformative());
+      classOrMixinDeclaration_typeParameters?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+      namedCompilationUnitMember_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.classTypeAlias) {
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      classTypeAlias_typeParameters?.flushInformative();
+      classTypeAlias_superclass?.flushInformative();
+      classTypeAlias_withClause?.flushInformative();
+      classTypeAlias_implementsClause?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+      namedCompilationUnitMember_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.comment) {
+      comment_references?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.commentReference) {
+      commentReference_identifier?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.compilationUnit) {
+      compilationUnit_declarations?.forEach((b) => b.flushInformative());
+      compilationUnit_scriptTag?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+      compilationUnit_directives?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.conditionalExpression) {
+      conditionalExpression_condition?.flushInformative();
+      conditionalExpression_elseExpression?.flushInformative();
+      conditionalExpression_thenExpression?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.configuration) {
+      configuration_name?.flushInformative();
+      configuration_value?.flushInformative();
+      configuration_uri?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+      constructorDeclaration_initializers?.forEach((b) => b.flushInformative());
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      constructorDeclaration_body?.flushInformative();
+      constructorDeclaration_name?.flushInformative();
+      constructorDeclaration_parameters?.flushInformative();
+      constructorDeclaration_redirectedConstructor?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+      constructorDeclaration_periodOffset = null;
+      constructorDeclaration_returnType?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
+      constructorFieldInitializer_expression?.flushInformative();
+      constructorFieldInitializer_fieldName?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.constructorName) {
+      constructorName_name?.flushInformative();
+      constructorName_type?.flushInformative();
+      constructorName_elementType?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.continueStatement) {
+      continueStatement_label?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.declaredIdentifier) {
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      declaredIdentifier_identifier?.flushInformative();
+      declaredIdentifier_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
+      defaultFormalParameter_defaultValue?.flushInformative();
+      defaultFormalParameter_parameter?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+    } else if (kind == idl.LinkedNodeKind.doStatement) {
+      doStatement_body?.flushInformative();
+      doStatement_condition?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.dottedName) {
+      dottedName_components?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.doubleLiteral) {
+    } else if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
+    } else if (kind == idl.LinkedNodeKind.emptyStatement) {
+    } else if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      enumConstantDeclaration_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.enumDeclaration) {
+      enumDeclaration_constants?.forEach((b) => b.flushInformative());
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      codeLength = null;
+      codeOffset = null;
+      namedCompilationUnitMember_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.exportDirective) {
+      namespaceDirective_combinators?.forEach((b) => b.flushInformative());
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      directive_keywordOffset = null;
+      namespaceDirective_configurations?.forEach((b) => b.flushInformative());
+      uriBasedDirective_uri?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
+      expressionFunctionBody_expression?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.expressionStatement) {
+      expressionStatement_expression?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.extendsClause) {
+      extendsClause_superclass?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.fieldDeclaration) {
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      fieldDeclaration_fields?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+      actualType?.flushInformative();
+      normalFormalParameter_metadata?.forEach((b) => b.flushInformative());
+      fieldFormalParameter_type?.flushInformative();
+      fieldFormalParameter_typeParameters?.flushInformative();
+      fieldFormalParameter_formalParameters?.flushInformative();
+      normalFormalParameter_identifier?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+      normalFormalParameter_comment = null;
+    } else if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
+      forEachParts_iterable?.flushInformative();
+      forEachPartsWithDeclaration_loopVariable?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.forEachPartsWithIdentifier) {
+      forEachParts_iterable?.flushInformative();
+      forEachPartsWithIdentifier_identifier?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.forElement) {
+      forMixin_forLoopParts?.flushInformative();
+      forElement_body?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
+      forParts_condition?.flushInformative();
+      forPartsWithDeclarations_variables?.flushInformative();
+      forParts_updaters?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.forPartsWithExpression) {
+      forParts_condition?.flushInformative();
+      forPartsWithExpression_initialization?.flushInformative();
+      forParts_updaters?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.forStatement) {
+      forMixin_forLoopParts?.flushInformative();
+      forStatement_body?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.formalParameterList) {
+      formalParameterList_parameters?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.functionDeclaration) {
+      actualReturnType?.flushInformative();
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      functionDeclaration_functionExpression?.flushInformative();
+      functionDeclaration_returnType?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+      namedCompilationUnitMember_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
+      functionDeclarationStatement_functionDeclaration?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.functionExpression) {
+      actualReturnType?.flushInformative();
+      functionExpression_body?.flushInformative();
+      functionExpression_formalParameters?.flushInformative();
+      functionExpression_typeParameters?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
+      invocationExpression_invokeType?.flushInformative();
+      functionExpressionInvocation_function?.flushInformative();
+      invocationExpression_typeArguments?.flushInformative();
+      expression_type?.flushInformative();
+      invocationExpression_arguments?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+      actualReturnType?.flushInformative();
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      functionTypeAlias_formalParameters?.flushInformative();
+      functionTypeAlias_returnType?.flushInformative();
+      functionTypeAlias_typeParameters?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+      namedCompilationUnitMember_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+      actualType?.flushInformative();
+      normalFormalParameter_metadata?.forEach((b) => b.flushInformative());
+      functionTypedFormalParameter_formalParameters?.flushInformative();
+      functionTypedFormalParameter_returnType?.flushInformative();
+      functionTypedFormalParameter_typeParameters?.flushInformative();
+      normalFormalParameter_identifier?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+      normalFormalParameter_comment = null;
+    } else if (kind == idl.LinkedNodeKind.genericFunctionType) {
+      actualReturnType?.flushInformative();
+      genericFunctionType_typeParameters?.flushInformative();
+      genericFunctionType_returnType?.flushInformative();
+      genericFunctionType_formalParameters?.flushInformative();
+      genericFunctionType_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.genericTypeAlias) {
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      genericTypeAlias_typeParameters?.flushInformative();
+      genericTypeAlias_functionType?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+      namedCompilationUnitMember_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.hideCombinator) {
+    } else if (kind == idl.LinkedNodeKind.ifElement) {
+      ifMixin_condition?.flushInformative();
+      ifElement_thenElement?.flushInformative();
+      ifElement_elseElement?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.ifStatement) {
+      ifMixin_condition?.flushInformative();
+      ifStatement_elseStatement?.flushInformative();
+      ifStatement_thenStatement?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.implementsClause) {
+      implementsClause_interfaces?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.importDirective) {
+      namespaceDirective_combinators?.forEach((b) => b.flushInformative());
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      directive_keywordOffset = null;
+      namespaceDirective_configurations?.forEach((b) => b.flushInformative());
+      uriBasedDirective_uri?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.indexExpression) {
+      indexExpression_index?.flushInformative();
+      indexExpression_target?.flushInformative();
+      indexExpression_elementType?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
+      instanceCreationExpression_arguments
+          ?.forEach((b) => b.flushInformative());
+      instanceCreationExpression_constructorName?.flushInformative();
+      instanceCreationExpression_typeArguments?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.integerLiteral) {
+    } else if (kind == idl.LinkedNodeKind.interpolationExpression) {
+      interpolationExpression_expression?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.interpolationString) {
+    } else if (kind == idl.LinkedNodeKind.isExpression) {
+      isExpression_expression?.flushInformative();
+      isExpression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.label) {
+      label_label?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.labeledStatement) {
+      labeledStatement_labels?.forEach((b) => b.flushInformative());
+      labeledStatement_statement?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.libraryDirective) {
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      libraryDirective_name?.flushInformative();
+      directive_keywordOffset = null;
+    } else if (kind == idl.LinkedNodeKind.libraryIdentifier) {
+      libraryIdentifier_components?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.listLiteral) {
+      typedLiteral_typeArguments?.forEach((b) => b.flushInformative());
+      listLiteral_elements?.forEach((b) => b.flushInformative());
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
+      mapLiteralEntry_key?.flushInformative();
+      mapLiteralEntry_value?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.methodDeclaration) {
+      actualReturnType?.flushInformative();
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      methodDeclaration_body?.flushInformative();
+      methodDeclaration_formalParameters?.flushInformative();
+      methodDeclaration_returnType?.flushInformative();
+      methodDeclaration_typeParameters?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+      methodDeclaration_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.methodInvocation) {
+      invocationExpression_invokeType?.flushInformative();
+      methodInvocation_methodName?.flushInformative();
+      methodInvocation_target?.flushInformative();
+      invocationExpression_typeArguments?.flushInformative();
+      expression_type?.flushInformative();
+      invocationExpression_arguments?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.mixinDeclaration) {
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      mixinDeclaration_onClause?.flushInformative();
+      classOrMixinDeclaration_implementsClause?.flushInformative();
+      classOrMixinDeclaration_members?.forEach((b) => b.flushInformative());
+      classOrMixinDeclaration_typeParameters?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+      namedCompilationUnitMember_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.namedExpression) {
+      namedExpression_expression?.flushInformative();
+      namedExpression_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.nativeClause) {
+      nativeClause_name?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.nativeFunctionBody) {
+      nativeFunctionBody_stringLiteral?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.nullLiteral) {
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.onClause) {
+      onClause_superclassConstraints?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.parenthesizedExpression) {
+      parenthesizedExpression_expression?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.partDirective) {
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      directive_keywordOffset = null;
+      uriBasedDirective_uri?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.partOfDirective) {
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      partOfDirective_libraryName?.flushInformative();
+      partOfDirective_uri?.flushInformative();
+      directive_keywordOffset = null;
+    } else if (kind == idl.LinkedNodeKind.postfixExpression) {
+      postfixExpression_operand?.flushInformative();
+      postfixExpression_elementType?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.prefixExpression) {
+      prefixExpression_operand?.flushInformative();
+      prefixExpression_elementType?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
+      prefixedIdentifier_identifier?.flushInformative();
+      prefixedIdentifier_prefix?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.propertyAccess) {
+      propertyAccess_propertyName?.flushInformative();
+      propertyAccess_target?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.redirectingConstructorInvocation) {
+      redirectingConstructorInvocation_arguments?.flushInformative();
+      redirectingConstructorInvocation_constructorName?.flushInformative();
+      redirectingConstructorInvocation_elementType?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.rethrowExpression) {
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.returnStatement) {
+      returnStatement_expression?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
+      typedLiteral_typeArguments?.forEach((b) => b.flushInformative());
+      setOrMapLiteral_elements?.forEach((b) => b.flushInformative());
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.showCombinator) {
+    } else if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+      actualType?.flushInformative();
+      normalFormalParameter_metadata?.forEach((b) => b.flushInformative());
+      simpleFormalParameter_type?.flushInformative();
+      normalFormalParameter_identifier?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+      normalFormalParameter_comment = null;
+      topLevelTypeInferenceError?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.simpleIdentifier) {
+      simpleIdentifier_elementType?.flushInformative();
+      expression_type?.flushInformative();
+      simpleIdentifier_offset = null;
+    } else if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
+    } else if (kind == idl.LinkedNodeKind.spreadElement) {
+      spreadElement_expression?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.stringInterpolation) {
+      stringInterpolation_elements?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.superConstructorInvocation) {
+      superConstructorInvocation_arguments?.flushInformative();
+      superConstructorInvocation_constructorName?.flushInformative();
+      superConstructorInvocation_elementType?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.superExpression) {
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.switchCase) {
+      switchMember_statements?.forEach((b) => b.flushInformative());
+      switchCase_expression?.flushInformative();
+      switchMember_labels?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.switchDefault) {
+      switchMember_statements?.forEach((b) => b.flushInformative());
+      switchMember_labels?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.switchStatement) {
+      switchStatement_members?.forEach((b) => b.flushInformative());
+      switchStatement_expression?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.symbolLiteral) {
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.thisExpression) {
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.throwExpression) {
+      throwExpression_expression?.flushInformative();
+      expression_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      topLevelVariableDeclaration_variableList?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.tryStatement) {
+      tryStatement_catchClauses?.forEach((b) => b.flushInformative());
+      tryStatement_body?.flushInformative();
+      tryStatement_finallyBlock?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.typeArgumentList) {
+      typeArgumentList_arguments?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.typeName) {
+      typeName_typeArguments?.forEach((b) => b.flushInformative());
+      typeName_name?.flushInformative();
+      typeName_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.typeParameter) {
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      typeParameter_bound?.flushInformative();
+      typeParameter_name?.flushInformative();
+      typeParameter_defaultType?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+    } else if (kind == idl.LinkedNodeKind.typeParameterList) {
+      typeParameterList_typeParameters?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.variableDeclaration) {
+      actualType?.flushInformative();
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      variableDeclaration_initializer?.flushInformative();
+      variableDeclaration_name?.flushInformative();
+      codeLength = null;
+      codeOffset = null;
+      topLevelTypeInferenceError?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.variableDeclarationList) {
+      variableDeclarationList_variables?.forEach((b) => b.flushInformative());
+      annotatedNode_comment = null;
+      annotatedNode_metadata?.forEach((b) => b.flushInformative());
+      variableDeclarationList_type?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.variableDeclarationStatement) {
+      variableDeclarationStatement_variables?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.whileStatement) {
+      whileStatement_body?.flushInformative();
+      whileStatement_condition?.flushInformative();
+    } else if (kind == idl.LinkedNodeKind.withClause) {
+      withClause_mixinTypes?.forEach((b) => b.flushInformative());
+    } else if (kind == idl.LinkedNodeKind.yieldStatement) {
+      yieldStatement_expression?.flushInformative();
+    }
   }
 
   /// Accumulate non-[informative] data into [signature].
   void collectApiSignature(api_sig.ApiSignature signature) {
-    signature.addInt(this._kind == null ? 0 : this._kind.index);
-    signature.addString(this._variantField_1 ?? '');
-    if (this._variantField_2 == null) {
-      signature.addInt(0);
-    } else {
-      signature.addInt(this._variantField_2.length);
-      for (var x in this._variantField_2) {
-        x?.collectApiSignature(signature);
+    if (kind == idl.LinkedNodeKind.adjacentStrings) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.adjacentStrings_strings == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.adjacentStrings_strings.length);
+        for (var x in this.adjacentStrings_strings) {
+          x?.collectApiSignature(signature);
+        }
       }
-    }
-    if (this._variantField_3 == null) {
-      signature.addInt(0);
-    } else {
-      signature.addInt(this._variantField_3.length);
-      for (var x in this._variantField_3) {
-        x?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.annotation) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.annotation_arguments != null);
+      this.annotation_arguments?.collectApiSignature(signature);
+      signature.addBool(this.annotation_constructorName != null);
+      this.annotation_constructorName?.collectApiSignature(signature);
+      signature.addBool(this.annotation_name != null);
+      this.annotation_name?.collectApiSignature(signature);
+      signature.addInt(this.annotation_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.annotation_elementType != null);
+      this.annotation_elementType?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.argumentList) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.argumentList_arguments == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.argumentList_arguments.length);
+        for (var x in this.argumentList_arguments) {
+          x?.collectApiSignature(signature);
+        }
       }
-    }
-    if (this._variantField_4 == null) {
-      signature.addInt(0);
-    } else {
-      signature.addInt(this._variantField_4.length);
-      for (var x in this._variantField_4) {
-        x?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.asExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.asExpression_expression != null);
+      this.asExpression_expression?.collectApiSignature(signature);
+      signature.addBool(this.asExpression_type != null);
+      this.asExpression_type?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.assertInitializer) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.assertInitializer_condition != null);
+      this.assertInitializer_condition?.collectApiSignature(signature);
+      signature.addBool(this.assertInitializer_message != null);
+      this.assertInitializer_message?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.assertStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.assertStatement_condition != null);
+      this.assertStatement_condition?.collectApiSignature(signature);
+      signature.addBool(this.assertStatement_message != null);
+      this.assertStatement_message?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.assignmentExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.assignmentExpression_leftHandSide != null);
+      this.assignmentExpression_leftHandSide?.collectApiSignature(signature);
+      signature.addBool(this.assignmentExpression_rightHandSide != null);
+      this.assignmentExpression_rightHandSide?.collectApiSignature(signature);
+      signature.addInt(this.assignmentExpression_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.assignmentExpression_elementType != null);
+      this.assignmentExpression_elementType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addInt(this.assignmentExpression_operator == null
+          ? 0
+          : this.assignmentExpression_operator.index);
+    } else if (kind == idl.LinkedNodeKind.awaitExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.awaitExpression_expression != null);
+      this.awaitExpression_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.binaryExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.binaryExpression_leftOperand != null);
+      this.binaryExpression_leftOperand?.collectApiSignature(signature);
+      signature.addBool(this.binaryExpression_rightOperand != null);
+      this.binaryExpression_rightOperand?.collectApiSignature(signature);
+      signature.addInt(this.binaryExpression_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.binaryExpression_elementType != null);
+      this.binaryExpression_elementType?.collectApiSignature(signature);
+      signature.addBool(this.binaryExpression_invokeType != null);
+      this.binaryExpression_invokeType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addInt(this.binaryExpression_operator == null
+          ? 0
+          : this.binaryExpression_operator.index);
+    } else if (kind == idl.LinkedNodeKind.block) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.block_statements == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.block_statements.length);
+        for (var x in this.block_statements) {
+          x?.collectApiSignature(signature);
+        }
       }
-    }
-    if (this._variantField_5 == null) {
-      signature.addInt(0);
-    } else {
-      signature.addInt(this._variantField_5.length);
-      for (var x in this._variantField_5) {
-        x?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.blockFunctionBody) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.blockFunctionBody_block != null);
+      this.blockFunctionBody_block?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.booleanLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.booleanLiteral_value == true);
+    } else if (kind == idl.LinkedNodeKind.breakStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.breakStatement_label != null);
+      this.breakStatement_label?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.cascadeExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.cascadeExpression_sections == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.cascadeExpression_sections.length);
+        for (var x in this.cascadeExpression_sections) {
+          x?.collectApiSignature(signature);
+        }
       }
-    }
-    signature.addBool(this._variantField_6 != null);
-    this._variantField_6?.collectApiSignature(signature);
-    signature.addBool(this._variantField_7 != null);
-    this._variantField_7?.collectApiSignature(signature);
-    signature.addBool(this._variantField_8 != null);
-    this._variantField_8?.collectApiSignature(signature);
-    signature.addBool(this._variantField_9 != null);
-    this._variantField_9?.collectApiSignature(signature);
-    signature.addBool(this._variantField_10 != null);
-    this._variantField_10?.collectApiSignature(signature);
-    signature.addBool(this._variantField_11 != null);
-    this._variantField_11?.collectApiSignature(signature);
-    signature.addBool(this._variantField_12 != null);
-    this._variantField_12?.collectApiSignature(signature);
-    signature.addBool(this._variantField_13 != null);
-    this._variantField_13?.collectApiSignature(signature);
-    signature.addBool(this._variantField_14 != null);
-    this._variantField_14?.collectApiSignature(signature);
-    signature.addInt(this._variantField_15 ?? 0);
-    signature.addInt(this._variantField_16 ?? 0);
-    signature.addInt(this._variantField_17 ?? 0);
-    signature.addInt(this._flags ?? 0);
-    signature.addInt(this._variantField_19 ?? 0);
-    signature.addString(this._variantField_20 ?? '');
-    signature.addDouble(this._variantField_21 ?? 0.0);
-    signature.addString(this._variantField_22 ?? '');
-    signature.addBool(this._variantField_23 != null);
-    this._variantField_23?.collectApiSignature(signature);
-    signature.addBool(this._variantField_24 != null);
-    this._variantField_24?.collectApiSignature(signature);
-    signature.addBool(this._variantField_25 != null);
-    this._variantField_25?.collectApiSignature(signature);
-    signature.addInt(
-        this._variantField_26 == null ? 0 : this._variantField_26.index);
-    signature.addBool(this._variantField_27 == true);
-    signature.addInt(
-        this._variantField_28 == null ? 0 : this._variantField_28.index);
-    signature.addInt(
-        this._variantField_29 == null ? 0 : this._variantField_29.index);
-    signature.addString(this._variantField_30 ?? '');
-    signature.addBool(this._variantField_31 == true);
-    signature.addBool(this._variantField_32 != null);
-    this._variantField_32?.collectApiSignature(signature);
-    signature.addInt(this._variantField_33 ?? 0);
-    signature.addInt(this._variantField_34 ?? 0);
-    signature.addBool(this._variantField_35 != null);
-    this._variantField_35?.collectApiSignature(signature);
-    if (this._variantField_36 == null) {
-      signature.addInt(0);
-    } else {
-      signature.addInt(this._variantField_36.length);
-      for (var x in this._variantField_36) {
-        signature.addString(x);
+      signature.addBool(this.cascadeExpression_target != null);
+      this.cascadeExpression_target?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.catchClause) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.catchClause_body != null);
+      this.catchClause_body?.collectApiSignature(signature);
+      signature.addBool(this.catchClause_exceptionParameter != null);
+      this.catchClause_exceptionParameter?.collectApiSignature(signature);
+      signature.addBool(this.catchClause_exceptionType != null);
+      this.catchClause_exceptionType?.collectApiSignature(signature);
+      signature.addBool(this.catchClause_stackTraceParameter != null);
+      this.catchClause_stackTraceParameter?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.classDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
       }
+      if (this.classOrMixinDeclaration_members == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.classOrMixinDeclaration_members.length);
+        for (var x in this.classOrMixinDeclaration_members) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.classDeclaration_extendsClause != null);
+      this.classDeclaration_extendsClause?.collectApiSignature(signature);
+      signature.addBool(this.classDeclaration_withClause != null);
+      this.classDeclaration_withClause?.collectApiSignature(signature);
+      signature.addBool(this.classDeclaration_nativeClause != null);
+      this.classDeclaration_nativeClause?.collectApiSignature(signature);
+      signature.addBool(this.namedCompilationUnitMember_name != null);
+      this.namedCompilationUnitMember_name?.collectApiSignature(signature);
+      signature.addBool(this.classOrMixinDeclaration_implementsClause != null);
+      this
+          .classOrMixinDeclaration_implementsClause
+          ?.collectApiSignature(signature);
+      signature.addBool(this.classOrMixinDeclaration_typeParameters != null);
+      this
+          .classOrMixinDeclaration_typeParameters
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.classDeclaration_isDartObject == true);
+      signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+    } else if (kind == idl.LinkedNodeKind.classTypeAlias) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.classTypeAlias_typeParameters != null);
+      this.classTypeAlias_typeParameters?.collectApiSignature(signature);
+      signature.addBool(this.classTypeAlias_superclass != null);
+      this.classTypeAlias_superclass?.collectApiSignature(signature);
+      signature.addBool(this.classTypeAlias_withClause != null);
+      this.classTypeAlias_withClause?.collectApiSignature(signature);
+      signature.addBool(this.classTypeAlias_implementsClause != null);
+      this.classTypeAlias_implementsClause?.collectApiSignature(signature);
+      signature.addBool(this.namedCompilationUnitMember_name != null);
+      this.namedCompilationUnitMember_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+    } else if (kind == idl.LinkedNodeKind.comment) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.comment_references == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.comment_references.length);
+        for (var x in this.comment_references) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addInt(this.comment_type == null ? 0 : this.comment_type.index);
+      if (this.comment_tokens == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.comment_tokens.length);
+        for (var x in this.comment_tokens) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.commentReference) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.commentReference_identifier != null);
+      this.commentReference_identifier?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.compilationUnit) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.compilationUnit_declarations == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.compilationUnit_declarations.length);
+        for (var x in this.compilationUnit_declarations) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.compilationUnit_directives == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.compilationUnit_directives.length);
+        for (var x in this.compilationUnit_directives) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.compilationUnit_scriptTag != null);
+      this.compilationUnit_scriptTag?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.conditionalExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.conditionalExpression_condition != null);
+      this.conditionalExpression_condition?.collectApiSignature(signature);
+      signature.addBool(this.conditionalExpression_elseExpression != null);
+      this.conditionalExpression_elseExpression?.collectApiSignature(signature);
+      signature.addBool(this.conditionalExpression_thenExpression != null);
+      this.conditionalExpression_thenExpression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.configuration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.configuration_name != null);
+      this.configuration_name?.collectApiSignature(signature);
+      signature.addBool(this.configuration_value != null);
+      this.configuration_value?.collectApiSignature(signature);
+      signature.addBool(this.configuration_uri != null);
+      this.configuration_uri?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.constructorDeclaration_initializers == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.constructorDeclaration_initializers.length);
+        for (var x in this.constructorDeclaration_initializers) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.constructorDeclaration_body != null);
+      this.constructorDeclaration_body?.collectApiSignature(signature);
+      signature.addBool(this.constructorDeclaration_name != null);
+      this.constructorDeclaration_name?.collectApiSignature(signature);
+      signature.addBool(this.constructorDeclaration_parameters != null);
+      this.constructorDeclaration_parameters?.collectApiSignature(signature);
+      signature
+          .addBool(this.constructorDeclaration_redirectedConstructor != null);
+      this
+          .constructorDeclaration_redirectedConstructor
+          ?.collectApiSignature(signature);
+      signature.addBool(this.constructorDeclaration_returnType != null);
+      this.constructorDeclaration_returnType?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.constructorFieldInitializer_expression != null);
+      this
+          .constructorFieldInitializer_expression
+          ?.collectApiSignature(signature);
+      signature.addBool(this.constructorFieldInitializer_fieldName != null);
+      this
+          .constructorFieldInitializer_fieldName
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.constructorName) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.constructorName_name != null);
+      this.constructorName_name?.collectApiSignature(signature);
+      signature.addBool(this.constructorName_type != null);
+      this.constructorName_type?.collectApiSignature(signature);
+      signature.addInt(this.constructorName_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.constructorName_elementType != null);
+      this.constructorName_elementType?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.continueStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.continueStatement_label != null);
+      this.continueStatement_label?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.declaredIdentifier) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.declaredIdentifier_identifier != null);
+      this.declaredIdentifier_identifier?.collectApiSignature(signature);
+      signature.addBool(this.declaredIdentifier_type != null);
+      this.declaredIdentifier_type?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.defaultFormalParameter_defaultValue != null);
+      this.defaultFormalParameter_defaultValue?.collectApiSignature(signature);
+      signature.addBool(this.defaultFormalParameter_parameter != null);
+      this.defaultFormalParameter_parameter?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addInt(this.defaultFormalParameter_kind == null
+          ? 0
+          : this.defaultFormalParameter_kind.index);
+    } else if (kind == idl.LinkedNodeKind.doStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.doStatement_body != null);
+      this.doStatement_body?.collectApiSignature(signature);
+      signature.addBool(this.doStatement_condition != null);
+      this.doStatement_condition?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.dottedName) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.dottedName_components == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.dottedName_components.length);
+        for (var x in this.dottedName_components) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.doubleLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addDouble(this.doubleLiteral_value ?? 0.0);
+    } else if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.emptyFunctionBody_fake ?? 0);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.emptyStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.emptyStatement_fake ?? 0);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.enumConstantDeclaration_name != null);
+      this.enumConstantDeclaration_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.enumDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.enumDeclaration_constants == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.enumDeclaration_constants.length);
+        for (var x in this.enumDeclaration_constants) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.namedCompilationUnitMember_name != null);
+      this.namedCompilationUnitMember_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.exportDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.namespaceDirective_combinators == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.namespaceDirective_combinators.length);
+        for (var x in this.namespaceDirective_combinators) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.namespaceDirective_configurations == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.namespaceDirective_configurations.length);
+        for (var x in this.namespaceDirective_configurations) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.uriBasedDirective_uri != null);
+      this.uriBasedDirective_uri?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addInt(this.uriBasedDirective_uriElement ?? 0);
+      signature.addString(this.namespaceDirective_selectedUri ?? '');
+      signature.addString(this.uriBasedDirective_uriContent ?? '');
+    } else if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.expressionFunctionBody_expression != null);
+      this.expressionFunctionBody_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.expressionStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.expressionStatement_expression != null);
+      this.expressionStatement_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.extendsClause) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.extendsClause_superclass != null);
+      this.extendsClause_superclass?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.fieldDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.fieldDeclaration_fields != null);
+      this.fieldDeclaration_fields?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.normalFormalParameter_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.normalFormalParameter_metadata.length);
+        for (var x in this.normalFormalParameter_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.fieldFormalParameter_type != null);
+      this.fieldFormalParameter_type?.collectApiSignature(signature);
+      signature.addBool(this.fieldFormalParameter_typeParameters != null);
+      this.fieldFormalParameter_typeParameters?.collectApiSignature(signature);
+      signature.addBool(this.fieldFormalParameter_formalParameters != null);
+      this
+          .fieldFormalParameter_formalParameters
+          ?.collectApiSignature(signature);
+      signature.addBool(this.normalFormalParameter_identifier != null);
+      this.normalFormalParameter_identifier?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualType != null);
+      this.actualType?.collectApiSignature(signature);
+      signature.addBool(this.inheritsCovariant == true);
+    } else if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.forEachParts_iterable != null);
+      this.forEachParts_iterable?.collectApiSignature(signature);
+      signature.addBool(this.forEachPartsWithDeclaration_loopVariable != null);
+      this
+          .forEachPartsWithDeclaration_loopVariable
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.forEachPartsWithIdentifier) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.forEachParts_iterable != null);
+      this.forEachParts_iterable?.collectApiSignature(signature);
+      signature.addBool(this.forEachPartsWithIdentifier_identifier != null);
+      this
+          .forEachPartsWithIdentifier_identifier
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.forElement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.forMixin_forLoopParts != null);
+      this.forMixin_forLoopParts?.collectApiSignature(signature);
+      signature.addBool(this.forElement_body != null);
+      this.forElement_body?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.forParts_updaters == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.forParts_updaters.length);
+        for (var x in this.forParts_updaters) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.forParts_condition != null);
+      this.forParts_condition?.collectApiSignature(signature);
+      signature.addBool(this.forPartsWithDeclarations_variables != null);
+      this.forPartsWithDeclarations_variables?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.forPartsWithExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.forParts_updaters == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.forParts_updaters.length);
+        for (var x in this.forParts_updaters) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.forParts_condition != null);
+      this.forParts_condition?.collectApiSignature(signature);
+      signature.addBool(this.forPartsWithExpression_initialization != null);
+      this
+          .forPartsWithExpression_initialization
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.forStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.forMixin_forLoopParts != null);
+      this.forMixin_forLoopParts?.collectApiSignature(signature);
+      signature.addBool(this.forStatement_body != null);
+      this.forStatement_body?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.formalParameterList) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.formalParameterList_parameters == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.formalParameterList_parameters.length);
+        for (var x in this.formalParameterList_parameters) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.functionDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.functionDeclaration_functionExpression != null);
+      this
+          .functionDeclaration_functionExpression
+          ?.collectApiSignature(signature);
+      signature.addBool(this.functionDeclaration_returnType != null);
+      this.functionDeclaration_returnType?.collectApiSignature(signature);
+      signature.addBool(this.namedCompilationUnitMember_name != null);
+      this.namedCompilationUnitMember_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualReturnType != null);
+      this.actualReturnType?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(
+          this.functionDeclarationStatement_functionDeclaration != null);
+      this
+          .functionDeclarationStatement_functionDeclaration
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.functionExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.functionExpression_body != null);
+      this.functionExpression_body?.collectApiSignature(signature);
+      signature.addBool(this.functionExpression_formalParameters != null);
+      this.functionExpression_formalParameters?.collectApiSignature(signature);
+      signature.addBool(this.functionExpression_typeParameters != null);
+      this.functionExpression_typeParameters?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualReturnType != null);
+      this.actualReturnType?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.functionExpressionInvocation_function != null);
+      this
+          .functionExpressionInvocation_function
+          ?.collectApiSignature(signature);
+      signature.addBool(this.invocationExpression_typeArguments != null);
+      this.invocationExpression_typeArguments?.collectApiSignature(signature);
+      signature.addBool(this.invocationExpression_arguments != null);
+      this.invocationExpression_arguments?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.invocationExpression_invokeType != null);
+      this.invocationExpression_invokeType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.functionTypeAlias_formalParameters != null);
+      this.functionTypeAlias_formalParameters?.collectApiSignature(signature);
+      signature.addBool(this.functionTypeAlias_returnType != null);
+      this.functionTypeAlias_returnType?.collectApiSignature(signature);
+      signature.addBool(this.functionTypeAlias_typeParameters != null);
+      this.functionTypeAlias_typeParameters?.collectApiSignature(signature);
+      signature.addBool(this.namedCompilationUnitMember_name != null);
+      this.namedCompilationUnitMember_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualReturnType != null);
+      this.actualReturnType?.collectApiSignature(signature);
+      signature.addBool(this.typeAlias_hasSelfReference == true);
+      signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+    } else if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.normalFormalParameter_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.normalFormalParameter_metadata.length);
+        for (var x in this.normalFormalParameter_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature
+          .addBool(this.functionTypedFormalParameter_formalParameters != null);
+      this
+          .functionTypedFormalParameter_formalParameters
+          ?.collectApiSignature(signature);
+      signature.addBool(this.functionTypedFormalParameter_returnType != null);
+      this
+          .functionTypedFormalParameter_returnType
+          ?.collectApiSignature(signature);
+      signature
+          .addBool(this.functionTypedFormalParameter_typeParameters != null);
+      this
+          .functionTypedFormalParameter_typeParameters
+          ?.collectApiSignature(signature);
+      signature.addBool(this.normalFormalParameter_identifier != null);
+      this.normalFormalParameter_identifier?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualType != null);
+      this.actualType?.collectApiSignature(signature);
+      signature.addBool(this.inheritsCovariant == true);
+    } else if (kind == idl.LinkedNodeKind.genericFunctionType) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.genericFunctionType_typeParameters != null);
+      this.genericFunctionType_typeParameters?.collectApiSignature(signature);
+      signature.addBool(this.genericFunctionType_returnType != null);
+      this.genericFunctionType_returnType?.collectApiSignature(signature);
+      signature.addBool(this.genericFunctionType_formalParameters != null);
+      this.genericFunctionType_formalParameters?.collectApiSignature(signature);
+      signature.addInt(this.genericFunctionType_id ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualReturnType != null);
+      this.actualReturnType?.collectApiSignature(signature);
+      signature.addBool(this.genericFunctionType_type != null);
+      this.genericFunctionType_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.genericTypeAlias) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.genericTypeAlias_typeParameters != null);
+      this.genericTypeAlias_typeParameters?.collectApiSignature(signature);
+      signature.addBool(this.genericTypeAlias_functionType != null);
+      this.genericTypeAlias_functionType?.collectApiSignature(signature);
+      signature.addBool(this.namedCompilationUnitMember_name != null);
+      this.namedCompilationUnitMember_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.typeAlias_hasSelfReference == true);
+      signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+    } else if (kind == idl.LinkedNodeKind.hideCombinator) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      if (this.names == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.names.length);
+        for (var x in this.names) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.ifElement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.ifMixin_condition != null);
+      this.ifMixin_condition?.collectApiSignature(signature);
+      signature.addBool(this.ifElement_thenElement != null);
+      this.ifElement_thenElement?.collectApiSignature(signature);
+      signature.addBool(this.ifElement_elseElement != null);
+      this.ifElement_elseElement?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.ifStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.ifMixin_condition != null);
+      this.ifMixin_condition?.collectApiSignature(signature);
+      signature.addBool(this.ifStatement_elseStatement != null);
+      this.ifStatement_elseStatement?.collectApiSignature(signature);
+      signature.addBool(this.ifStatement_thenStatement != null);
+      this.ifStatement_thenStatement?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.implementsClause) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.implementsClause_interfaces == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.implementsClause_interfaces.length);
+        for (var x in this.implementsClause_interfaces) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.importDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addString(this.importDirective_prefix ?? '');
+      if (this.namespaceDirective_combinators == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.namespaceDirective_combinators.length);
+        for (var x in this.namespaceDirective_combinators) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.namespaceDirective_configurations == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.namespaceDirective_configurations.length);
+        for (var x in this.namespaceDirective_configurations) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.uriBasedDirective_uri != null);
+      this.uriBasedDirective_uri?.collectApiSignature(signature);
+      signature.addInt(this.importDirective_prefixOffset ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addInt(this.uriBasedDirective_uriElement ?? 0);
+      signature.addString(this.namespaceDirective_selectedUri ?? '');
+      signature.addString(this.uriBasedDirective_uriContent ?? '');
+    } else if (kind == idl.LinkedNodeKind.indexExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.indexExpression_index != null);
+      this.indexExpression_index?.collectApiSignature(signature);
+      signature.addBool(this.indexExpression_target != null);
+      this.indexExpression_target?.collectApiSignature(signature);
+      signature.addInt(this.indexExpression_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.indexExpression_elementType != null);
+      this.indexExpression_elementType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.instanceCreationExpression_arguments == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.instanceCreationExpression_arguments.length);
+        for (var x in this.instanceCreationExpression_arguments) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature
+          .addBool(this.instanceCreationExpression_constructorName != null);
+      this
+          .instanceCreationExpression_constructorName
+          ?.collectApiSignature(signature);
+      signature.addBool(this.instanceCreationExpression_typeArguments != null);
+      this
+          .instanceCreationExpression_typeArguments
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.integerLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.integerLiteral_value ?? 0);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.interpolationExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.interpolationExpression_expression != null);
+      this.interpolationExpression_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.interpolationString) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.interpolationString_value ?? '');
+    } else if (kind == idl.LinkedNodeKind.isExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.isExpression_expression != null);
+      this.isExpression_expression?.collectApiSignature(signature);
+      signature.addBool(this.isExpression_type != null);
+      this.isExpression_type?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.label) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.label_label != null);
+      this.label_label?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.labeledStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.labeledStatement_labels == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.labeledStatement_labels.length);
+        for (var x in this.labeledStatement_labels) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.labeledStatement_statement != null);
+      this.labeledStatement_statement?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.libraryDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.libraryDirective_name != null);
+      this.libraryDirective_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.libraryIdentifier) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.libraryIdentifier_components == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.libraryIdentifier_components.length);
+        for (var x in this.libraryIdentifier_components) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.listLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.typedLiteral_typeArguments == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.typedLiteral_typeArguments.length);
+        for (var x in this.typedLiteral_typeArguments) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.listLiteral_elements == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.listLiteral_elements.length);
+        for (var x in this.listLiteral_elements) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.mapLiteralEntry_key != null);
+      this.mapLiteralEntry_key?.collectApiSignature(signature);
+      signature.addBool(this.mapLiteralEntry_value != null);
+      this.mapLiteralEntry_value?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.methodDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.methodDeclaration_body != null);
+      this.methodDeclaration_body?.collectApiSignature(signature);
+      signature.addBool(this.methodDeclaration_formalParameters != null);
+      this.methodDeclaration_formalParameters?.collectApiSignature(signature);
+      signature.addBool(this.methodDeclaration_returnType != null);
+      this.methodDeclaration_returnType?.collectApiSignature(signature);
+      signature.addBool(this.methodDeclaration_typeParameters != null);
+      this.methodDeclaration_typeParameters?.collectApiSignature(signature);
+      signature.addBool(this.methodDeclaration_name != null);
+      this.methodDeclaration_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualReturnType != null);
+      this.actualReturnType?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.methodInvocation) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.methodInvocation_methodName != null);
+      this.methodInvocation_methodName?.collectApiSignature(signature);
+      signature.addBool(this.methodInvocation_target != null);
+      this.methodInvocation_target?.collectApiSignature(signature);
+      signature.addBool(this.invocationExpression_typeArguments != null);
+      this.invocationExpression_typeArguments?.collectApiSignature(signature);
+      signature.addBool(this.invocationExpression_arguments != null);
+      this.invocationExpression_arguments?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.invocationExpression_invokeType != null);
+      this.invocationExpression_invokeType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.mixinDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.classOrMixinDeclaration_members == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.classOrMixinDeclaration_members.length);
+        for (var x in this.classOrMixinDeclaration_members) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.mixinDeclaration_onClause != null);
+      this.mixinDeclaration_onClause?.collectApiSignature(signature);
+      signature.addBool(this.namedCompilationUnitMember_name != null);
+      this.namedCompilationUnitMember_name?.collectApiSignature(signature);
+      signature.addBool(this.classOrMixinDeclaration_implementsClause != null);
+      this
+          .classOrMixinDeclaration_implementsClause
+          ?.collectApiSignature(signature);
+      signature.addBool(this.classOrMixinDeclaration_typeParameters != null);
+      this
+          .classOrMixinDeclaration_typeParameters
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+      if (this.mixinDeclaration_superInvokedNames == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.mixinDeclaration_superInvokedNames.length);
+        for (var x in this.mixinDeclaration_superInvokedNames) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.namedExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.namedExpression_expression != null);
+      this.namedExpression_expression?.collectApiSignature(signature);
+      signature.addBool(this.namedExpression_name != null);
+      this.namedExpression_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.nativeClause) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.nativeClause_name != null);
+      this.nativeClause_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.nativeFunctionBody) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.nativeFunctionBody_stringLiteral != null);
+      this.nativeFunctionBody_stringLiteral?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.nullLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.nullLiteral_fake ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.onClause) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.onClause_superclassConstraints == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.onClause_superclassConstraints.length);
+        for (var x in this.onClause_superclassConstraints) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.parenthesizedExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.parenthesizedExpression_expression != null);
+      this.parenthesizedExpression_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.partDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.uriBasedDirective_uri != null);
+      this.uriBasedDirective_uri?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addInt(this.uriBasedDirective_uriElement ?? 0);
+      signature.addString(this.uriBasedDirective_uriContent ?? '');
+    } else if (kind == idl.LinkedNodeKind.partOfDirective) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.partOfDirective_libraryName != null);
+      this.partOfDirective_libraryName?.collectApiSignature(signature);
+      signature.addBool(this.partOfDirective_uri != null);
+      this.partOfDirective_uri?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.postfixExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.postfixExpression_operand != null);
+      this.postfixExpression_operand?.collectApiSignature(signature);
+      signature.addInt(this.postfixExpression_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.postfixExpression_elementType != null);
+      this.postfixExpression_elementType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addInt(this.postfixExpression_operator == null
+          ? 0
+          : this.postfixExpression_operator.index);
+    } else if (kind == idl.LinkedNodeKind.prefixExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.prefixExpression_operand != null);
+      this.prefixExpression_operand?.collectApiSignature(signature);
+      signature.addInt(this.prefixExpression_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.prefixExpression_elementType != null);
+      this.prefixExpression_elementType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addInt(this.prefixExpression_operator == null
+          ? 0
+          : this.prefixExpression_operator.index);
+    } else if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.prefixedIdentifier_identifier != null);
+      this.prefixedIdentifier_identifier?.collectApiSignature(signature);
+      signature.addBool(this.prefixedIdentifier_prefix != null);
+      this.prefixedIdentifier_prefix?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.propertyAccess) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.propertyAccess_propertyName != null);
+      this.propertyAccess_propertyName?.collectApiSignature(signature);
+      signature.addBool(this.propertyAccess_target != null);
+      this.propertyAccess_target?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      signature.addInt(this.propertyAccess_operator == null
+          ? 0
+          : this.propertyAccess_operator.index);
+    } else if (kind == idl.LinkedNodeKind.redirectingConstructorInvocation) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature
+          .addBool(this.redirectingConstructorInvocation_arguments != null);
+      this
+          .redirectingConstructorInvocation_arguments
+          ?.collectApiSignature(signature);
+      signature.addBool(
+          this.redirectingConstructorInvocation_constructorName != null);
+      this
+          .redirectingConstructorInvocation_constructorName
+          ?.collectApiSignature(signature);
+      signature.addInt(this.redirectingConstructorInvocation_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature
+          .addBool(this.redirectingConstructorInvocation_elementType != null);
+      this
+          .redirectingConstructorInvocation_elementType
+          ?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.rethrowExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.returnStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.returnStatement_expression != null);
+      this.returnStatement_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.typedLiteral_typeArguments == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.typedLiteral_typeArguments.length);
+        for (var x in this.typedLiteral_typeArguments) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.setOrMapLiteral_elements == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.setOrMapLiteral_elements.length);
+        for (var x in this.setOrMapLiteral_elements) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.showCombinator) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      if (this.names == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.names.length);
+        for (var x in this.names) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.normalFormalParameter_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.normalFormalParameter_metadata.length);
+        for (var x in this.normalFormalParameter_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.simpleFormalParameter_type != null);
+      this.simpleFormalParameter_type?.collectApiSignature(signature);
+      signature.addBool(this.normalFormalParameter_identifier != null);
+      this.normalFormalParameter_identifier?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualType != null);
+      this.actualType?.collectApiSignature(signature);
+      signature.addBool(this.inheritsCovariant == true);
+      signature.addBool(this.topLevelTypeInferenceError != null);
+      this.topLevelTypeInferenceError?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.simpleIdentifier) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.simpleIdentifier_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.simpleIdentifier_name ?? '');
+      signature.addBool(this.simpleIdentifier_elementType != null);
+      this.simpleIdentifier_elementType?.collectApiSignature(signature);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addString(this.simpleStringLiteral_value ?? '');
+    } else if (kind == idl.LinkedNodeKind.spreadElement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.spreadElement_expression != null);
+      this.spreadElement_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addInt(this.spreadElement_spreadOperator == null
+          ? 0
+          : this.spreadElement_spreadOperator.index);
+    } else if (kind == idl.LinkedNodeKind.stringInterpolation) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.stringInterpolation_elements == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.stringInterpolation_elements.length);
+        for (var x in this.stringInterpolation_elements) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.superConstructorInvocation) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.superConstructorInvocation_arguments != null);
+      this.superConstructorInvocation_arguments?.collectApiSignature(signature);
+      signature
+          .addBool(this.superConstructorInvocation_constructorName != null);
+      this
+          .superConstructorInvocation_constructorName
+          ?.collectApiSignature(signature);
+      signature.addInt(this.superConstructorInvocation_element ?? 0);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.superConstructorInvocation_elementType != null);
+      this
+          .superConstructorInvocation_elementType
+          ?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.superExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.switchCase) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.switchMember_labels == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.switchMember_labels.length);
+        for (var x in this.switchMember_labels) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.switchMember_statements == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.switchMember_statements.length);
+        for (var x in this.switchMember_statements) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.switchCase_expression != null);
+      this.switchCase_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.switchDefault) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.switchMember_labels == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.switchMember_labels.length);
+        for (var x in this.switchMember_labels) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.switchMember_statements == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.switchMember_statements.length);
+        for (var x in this.switchMember_statements) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.switchStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.switchStatement_members == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.switchStatement_members.length);
+        for (var x in this.switchStatement_members) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.switchStatement_expression != null);
+      this.switchStatement_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.symbolLiteral) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+      if (this.names == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.names.length);
+        for (var x in this.names) {
+          signature.addString(x);
+        }
+      }
+    } else if (kind == idl.LinkedNodeKind.thisExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.throwExpression) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.throwExpression_expression != null);
+      this.throwExpression_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.expression_type != null);
+      this.expression_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.topLevelVariableDeclaration_variableList != null);
+      this
+          .topLevelVariableDeclaration_variableList
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.tryStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.tryStatement_catchClauses == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.tryStatement_catchClauses.length);
+        for (var x in this.tryStatement_catchClauses) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.tryStatement_body != null);
+      this.tryStatement_body?.collectApiSignature(signature);
+      signature.addBool(this.tryStatement_finallyBlock != null);
+      this.tryStatement_finallyBlock?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.typeArgumentList) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.typeArgumentList_arguments == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.typeArgumentList_arguments.length);
+        for (var x in this.typeArgumentList_arguments) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.typeName) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.typeName_typeArguments == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.typeName_typeArguments.length);
+        for (var x in this.typeName_typeArguments) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.typeName_name != null);
+      this.typeName_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.typeName_type != null);
+      this.typeName_type?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.typeParameter) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.typeParameter_bound != null);
+      this.typeParameter_bound?.collectApiSignature(signature);
+      signature.addBool(this.typeParameter_name != null);
+      this.typeParameter_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.typeParameter_defaultType != null);
+      this.typeParameter_defaultType?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.typeParameterList) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.typeParameterList_typeParameters == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.typeParameterList_typeParameters.length);
+        for (var x in this.typeParameterList_typeParameters) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.variableDeclaration) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.variableDeclaration_initializer != null);
+      this.variableDeclaration_initializer?.collectApiSignature(signature);
+      signature.addBool(this.variableDeclaration_name != null);
+      this.variableDeclaration_name?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.actualType != null);
+      this.actualType?.collectApiSignature(signature);
+      signature.addBool(this.inheritsCovariant == true);
+      signature.addBool(this.topLevelTypeInferenceError != null);
+      this.topLevelTypeInferenceError?.collectApiSignature(signature);
+    } else if (kind == idl.LinkedNodeKind.variableDeclarationList) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.variableDeclarationList_variables == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.variableDeclarationList_variables.length);
+        for (var x in this.variableDeclarationList_variables) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      if (this.annotatedNode_metadata == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.annotatedNode_metadata.length);
+        for (var x in this.annotatedNode_metadata) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.variableDeclarationList_type != null);
+      this.variableDeclarationList_type?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.variableDeclarationStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.variableDeclarationStatement_variables != null);
+      this
+          .variableDeclarationStatement_variables
+          ?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.whileStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.whileStatement_body != null);
+      this.whileStatement_body?.collectApiSignature(signature);
+      signature.addBool(this.whileStatement_condition != null);
+      this.whileStatement_condition?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.withClause) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.withClause_mixinTypes == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.withClause_mixinTypes.length);
+        for (var x in this.withClause_mixinTypes) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addInt(this.flags ?? 0);
+    } else if (kind == idl.LinkedNodeKind.yieldStatement) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      signature.addBool(this.yieldStatement_expression != null);
+      this.yieldStatement_expression?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
     }
-    signature.addString(this._name ?? '');
-    signature.addInt(
-        this._variantField_38 == null ? 0 : this._variantField_38.index);
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -9125,18 +11056,17 @@
     fb.Offset offset_variantField_12;
     fb.Offset offset_variantField_5;
     fb.Offset offset_variantField_13;
-    fb.Offset offset_variantField_36;
+    fb.Offset offset_variantField_35;
     fb.Offset offset_variantField_3;
     fb.Offset offset_variantField_10;
     fb.Offset offset_variantField_25;
     fb.Offset offset_variantField_1;
     fb.Offset offset_variantField_30;
     fb.Offset offset_variantField_14;
-    fb.Offset offset_name;
+    fb.Offset offset_variantField_36;
     fb.Offset offset_variantField_20;
-    fb.Offset offset_variantField_35;
+    fb.Offset offset_variantField_34;
     fb.Offset offset_variantField_22;
-    fb.Offset offset_variantField_32;
     if (_variantField_24 != null) {
       offset_variantField_24 = _variantField_24.finish(fbBuilder);
     }
@@ -9176,9 +11106,9 @@
     if (_variantField_13 != null) {
       offset_variantField_13 = _variantField_13.finish(fbBuilder);
     }
-    if (!(_variantField_36 == null || _variantField_36.isEmpty)) {
-      offset_variantField_36 = fbBuilder.writeList(
-          _variantField_36.map((b) => fbBuilder.writeString(b)).toList());
+    if (!(_variantField_35 == null || _variantField_35.isEmpty)) {
+      offset_variantField_35 = fbBuilder.writeList(
+          _variantField_35.map((b) => fbBuilder.writeString(b)).toList());
     }
     if (!(_variantField_3 == null || _variantField_3.isEmpty)) {
       offset_variantField_3 = fbBuilder
@@ -9199,21 +11129,19 @@
     if (_variantField_14 != null) {
       offset_variantField_14 = _variantField_14.finish(fbBuilder);
     }
-    if (_name != null) {
-      offset_name = fbBuilder.writeString(_name);
+    if (!(_variantField_36 == null || _variantField_36.isEmpty)) {
+      offset_variantField_36 = fbBuilder.writeList(
+          _variantField_36.map((b) => fbBuilder.writeString(b)).toList());
     }
     if (_variantField_20 != null) {
       offset_variantField_20 = fbBuilder.writeString(_variantField_20);
     }
-    if (_variantField_35 != null) {
-      offset_variantField_35 = _variantField_35.finish(fbBuilder);
+    if (_variantField_34 != null) {
+      offset_variantField_34 = _variantField_34.finish(fbBuilder);
     }
     if (_variantField_22 != null) {
       offset_variantField_22 = fbBuilder.writeString(_variantField_22);
     }
-    if (_variantField_32 != null) {
-      offset_variantField_32 = _variantField_32.finish(fbBuilder);
-    }
     fbBuilder.startTable();
     if (offset_variantField_24 != null) {
       fbBuilder.addOffset(24, offset_variantField_24);
@@ -9264,14 +11192,14 @@
     if (offset_variantField_13 != null) {
       fbBuilder.addOffset(13, offset_variantField_13);
     }
-    if (_variantField_34 != null && _variantField_34 != 0) {
-      fbBuilder.addUint32(34, _variantField_34);
-    }
     if (_variantField_33 != null && _variantField_33 != 0) {
       fbBuilder.addUint32(33, _variantField_33);
     }
-    if (offset_variantField_36 != null) {
-      fbBuilder.addOffset(36, offset_variantField_36);
+    if (_variantField_32 != null && _variantField_32 != 0) {
+      fbBuilder.addUint32(32, _variantField_32);
+    }
+    if (offset_variantField_35 != null) {
+      fbBuilder.addOffset(35, offset_variantField_35);
     }
     if (_variantField_29 != null &&
         _variantField_29 != idl.LinkedNodeCommentType.block) {
@@ -9280,6 +11208,9 @@
     if (offset_variantField_3 != null) {
       fbBuilder.addOffset(3, offset_variantField_3);
     }
+    if (_variantField_19 != null && _variantField_19 != 0) {
+      fbBuilder.addUint32(19, _variantField_19);
+    }
     if (offset_variantField_10 != null) {
       fbBuilder.addOffset(10, offset_variantField_10);
     }
@@ -9312,8 +11243,8 @@
     if (_kind != null && _kind != idl.LinkedNodeKind.adjacentStrings) {
       fbBuilder.addUint8(0, _kind.index);
     }
-    if (offset_name != null) {
-      fbBuilder.addOffset(37, offset_name);
+    if (offset_variantField_36 != null) {
+      fbBuilder.addOffset(36, offset_variantField_36);
     }
     if (offset_variantField_20 != null) {
       fbBuilder.addOffset(20, offset_variantField_20);
@@ -9321,22 +11252,16 @@
     if (_variantField_31 == true) {
       fbBuilder.addBool(31, true);
     }
-    if (_variantField_38 != null &&
-        _variantField_38 != idl.UnlinkedTokenType.NOTHING) {
-      fbBuilder.addUint8(38, _variantField_38.index);
+    if (_variantField_37 != null &&
+        _variantField_37 != idl.UnlinkedTokenType.NOTHING) {
+      fbBuilder.addUint8(37, _variantField_37.index);
     }
-    if (offset_variantField_35 != null) {
-      fbBuilder.addOffset(35, offset_variantField_35);
+    if (offset_variantField_34 != null) {
+      fbBuilder.addOffset(34, offset_variantField_34);
     }
     if (offset_variantField_22 != null) {
       fbBuilder.addOffset(22, offset_variantField_22);
     }
-    if (_variantField_19 != null && _variantField_19 != 0) {
-      fbBuilder.addUint32(19, _variantField_19);
-    }
-    if (offset_variantField_32 != null) {
-      fbBuilder.addOffset(32, offset_variantField_32);
-    }
     return fbBuilder.endTable();
   }
 }
@@ -9373,11 +11298,12 @@
   idl.LinkedNode _variantField_12;
   List<idl.LinkedNode> _variantField_5;
   idl.LinkedNode _variantField_13;
-  int _variantField_34;
   int _variantField_33;
-  List<String> _variantField_36;
+  int _variantField_32;
+  List<String> _variantField_35;
   idl.LinkedNodeCommentType _variantField_29;
   List<idl.LinkedNode> _variantField_3;
+  int _variantField_19;
   idl.LinkedNode _variantField_10;
   idl.LinkedNodeFormalParameterKind _variantField_26;
   double _variantField_21;
@@ -9388,14 +11314,12 @@
   String _variantField_30;
   idl.LinkedNode _variantField_14;
   idl.LinkedNodeKind _kind;
-  String _name;
+  List<String> _variantField_36;
   String _variantField_20;
   bool _variantField_31;
-  idl.UnlinkedTokenType _variantField_38;
-  idl.TopLevelInferenceError _variantField_35;
+  idl.UnlinkedTokenType _variantField_37;
+  idl.TopLevelInferenceError _variantField_34;
   String _variantField_22;
-  int _variantField_19;
-  idl.LinkedNodeVariablesDeclaration _variantField_32;
 
   @override
   idl.LinkedNodeType get actualReturnType {
@@ -9935,6 +11859,14 @@
   }
 
   @override
+  idl.LinkedNode get enumConstantDeclaration_name {
+    assert(kind == idl.LinkedNodeKind.enumConstantDeclaration);
+    _variantField_6 ??=
+        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 6, null);
+    return _variantField_6;
+  }
+
+  @override
   idl.LinkedNode get expressionFunctionBody_expression {
     assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
     _variantField_6 ??=
@@ -10443,6 +12375,14 @@
   }
 
   @override
+  idl.LinkedNode get constructorDeclaration_name {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+    _variantField_7 ??=
+        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 7, null);
+    return _variantField_7;
+  }
+
+  @override
   idl.LinkedNode get constructorFieldInitializer_fieldName {
     assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
     _variantField_7 ??=
@@ -10707,6 +12647,22 @@
   }
 
   @override
+  idl.LinkedNode get typeParameter_name {
+    assert(kind == idl.LinkedNodeKind.typeParameter);
+    _variantField_7 ??=
+        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 7, null);
+    return _variantField_7;
+  }
+
+  @override
+  idl.LinkedNode get variableDeclaration_name {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_7 ??=
+        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 7, null);
+    return _variantField_7;
+  }
+
+  @override
   idl.LinkedNode get whileStatement_condition {
     assert(kind == idl.LinkedNodeKind.whileStatement);
     _variantField_7 ??=
@@ -10723,6 +12679,18 @@
   }
 
   @override
+  int get directive_keywordOffset {
+    assert(kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.libraryDirective ||
+        kind == idl.LinkedNodeKind.partDirective ||
+        kind == idl.LinkedNodeKind.partOfDirective);
+    _variantField_17 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
+    return _variantField_17;
+  }
+
+  @override
   int get genericFunctionType_id {
     assert(kind == idl.LinkedNodeKind.genericFunctionType);
     _variantField_17 ??=
@@ -11175,6 +13143,16 @@
   }
 
   @override
+  idl.LinkedNode get normalFormalParameter_identifier {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _variantField_9 ??=
+        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 9, null);
+    return _variantField_9;
+  }
+
+  @override
   idl.LinkedNode get classOrMixinDeclaration_implementsClause {
     assert(kind == idl.LinkedNodeKind.classDeclaration ||
         kind == idl.LinkedNodeKind.mixinDeclaration);
@@ -11239,9 +13217,9 @@
         kind == idl.LinkedNodeKind.simpleFormalParameter ||
         kind == idl.LinkedNodeKind.typeParameter ||
         kind == idl.LinkedNodeKind.variableDeclaration);
-    _variantField_34 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 34, 0);
-    return _variantField_34;
+    _variantField_33 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 33, 0);
+    return _variantField_33;
   }
 
   @override
@@ -11262,35 +13240,17 @@
         kind == idl.LinkedNodeKind.simpleFormalParameter ||
         kind == idl.LinkedNodeKind.typeParameter ||
         kind == idl.LinkedNodeKind.variableDeclaration);
-    _variantField_33 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 33, 0);
-    return _variantField_33;
+    _variantField_32 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 32, 0);
+    return _variantField_32;
   }
 
   @override
   List<String> get comment_tokens {
     assert(kind == idl.LinkedNodeKind.comment);
-    _variantField_36 ??= const fb.ListReader<String>(const fb.StringReader())
-        .vTableGet(_bc, _bcOffset, 36, const <String>[]);
-    return _variantField_36;
-  }
-
-  @override
-  List<String> get mixinDeclaration_superInvokedNames {
-    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
-    _variantField_36 ??= const fb.ListReader<String>(const fb.StringReader())
-        .vTableGet(_bc, _bcOffset, 36, const <String>[]);
-    return _variantField_36;
-  }
-
-  @override
-  List<String> get names {
-    assert(kind == idl.LinkedNodeKind.hideCombinator ||
-        kind == idl.LinkedNodeKind.showCombinator ||
-        kind == idl.LinkedNodeKind.symbolLiteral);
-    _variantField_36 ??= const fb.ListReader<String>(const fb.StringReader())
-        .vTableGet(_bc, _bcOffset, 36, const <String>[]);
-    return _variantField_36;
+    _variantField_35 ??= const fb.ListReader<String>(const fb.StringReader())
+        .vTableGet(_bc, _bcOffset, 35, const <String>[]);
+    return _variantField_35;
   }
 
   @override
@@ -11349,6 +13309,24 @@
   }
 
   @override
+  int get constructorDeclaration_periodOffset {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+    _variantField_19 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
+    return _variantField_19;
+  }
+
+  @override
+  int get uriBasedDirective_uriElement {
+    assert(kind == idl.LinkedNodeKind.exportDirective ||
+        kind == idl.LinkedNodeKind.importDirective ||
+        kind == idl.LinkedNodeKind.partDirective);
+    _variantField_19 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
+    return _variantField_19;
+  }
+
+  @override
   idl.LinkedNode get constructorDeclaration_returnType {
     assert(kind == idl.LinkedNodeKind.constructorDeclaration);
     _variantField_10 ??=
@@ -11357,6 +13335,28 @@
   }
 
   @override
+  idl.LinkedNode get methodDeclaration_name {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_10 ??=
+        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 10, null);
+    return _variantField_10;
+  }
+
+  @override
+  idl.LinkedNode get namedCompilationUnitMember_name {
+    assert(kind == idl.LinkedNodeKind.classDeclaration ||
+        kind == idl.LinkedNodeKind.classTypeAlias ||
+        kind == idl.LinkedNodeKind.enumDeclaration ||
+        kind == idl.LinkedNodeKind.functionDeclaration ||
+        kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias ||
+        kind == idl.LinkedNodeKind.mixinDeclaration);
+    _variantField_10 ??=
+        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 10, null);
+    return _variantField_10;
+  }
+
+  @override
   idl.LinkedNodeFormalParameterKind get defaultFormalParameter_kind {
     assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
     _variantField_26 ??= const _LinkedNodeFormalParameterKindReader().vTableGet(
@@ -11437,25 +13437,8 @@
   }
 
   @override
-  int get nameOffset {
-    assert(kind == idl.LinkedNodeKind.classDeclaration ||
-        kind == idl.LinkedNodeKind.classTypeAlias ||
-        kind == idl.LinkedNodeKind.constructorDeclaration ||
-        kind == idl.LinkedNodeKind.enumConstantDeclaration ||
-        kind == idl.LinkedNodeKind.enumDeclaration ||
-        kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionDeclaration ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypeAlias ||
-        kind == idl.LinkedNodeKind.genericTypeAlias ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.methodDeclaration ||
-        kind == idl.LinkedNodeKind.mixinDeclaration ||
-        kind == idl.LinkedNodeKind.partDirective ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter ||
-        kind == idl.LinkedNodeKind.typeParameter ||
-        kind == idl.LinkedNodeKind.variableDeclaration);
+  int get simpleIdentifier_offset {
+    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
     _variantField_16 ??=
         const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
     return _variantField_16;
@@ -11506,9 +13489,21 @@
   }
 
   @override
-  String get name {
-    _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 37, '');
-    return _name;
+  List<String> get mixinDeclaration_superInvokedNames {
+    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
+    _variantField_36 ??= const fb.ListReader<String>(const fb.StringReader())
+        .vTableGet(_bc, _bcOffset, 36, const <String>[]);
+    return _variantField_36;
+  }
+
+  @override
+  List<String> get names {
+    assert(kind == idl.LinkedNodeKind.hideCombinator ||
+        kind == idl.LinkedNodeKind.showCombinator ||
+        kind == idl.LinkedNodeKind.symbolLiteral);
+    _variantField_36 ??= const fb.ListReader<String>(const fb.StringReader())
+        .vTableGet(_bc, _bcOffset, 36, const <String>[]);
+    return _variantField_36;
   }
 
   @override
@@ -11521,6 +13516,14 @@
   }
 
   @override
+  String get simpleIdentifier_name {
+    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
+    _variantField_20 ??=
+        const fb.StringReader().vTableGet(_bc, _bcOffset, 20, '');
+    return _variantField_20;
+  }
+
+  @override
   String get simpleStringLiteral_value {
     assert(kind == idl.LinkedNodeKind.simpleStringLiteral);
     _variantField_20 ??=
@@ -11543,18 +13546,18 @@
   @override
   idl.UnlinkedTokenType get spreadElement_spreadOperator {
     assert(kind == idl.LinkedNodeKind.spreadElement);
-    _variantField_38 ??= const _UnlinkedTokenTypeReader()
-        .vTableGet(_bc, _bcOffset, 38, idl.UnlinkedTokenType.NOTHING);
-    return _variantField_38;
+    _variantField_37 ??= const _UnlinkedTokenTypeReader()
+        .vTableGet(_bc, _bcOffset, 37, idl.UnlinkedTokenType.NOTHING);
+    return _variantField_37;
   }
 
   @override
   idl.TopLevelInferenceError get topLevelTypeInferenceError {
     assert(kind == idl.LinkedNodeKind.simpleFormalParameter ||
         kind == idl.LinkedNodeKind.variableDeclaration);
-    _variantField_35 ??= const _TopLevelInferenceErrorReader()
-        .vTableGet(_bc, _bcOffset, 35, null);
-    return _variantField_35;
+    _variantField_34 ??= const _TopLevelInferenceErrorReader()
+        .vTableGet(_bc, _bcOffset, 34, null);
+    return _variantField_34;
   }
 
   @override
@@ -11566,24 +13569,6 @@
         const fb.StringReader().vTableGet(_bc, _bcOffset, 22, '');
     return _variantField_22;
   }
-
-  @override
-  int get uriBasedDirective_uriElement {
-    assert(kind == idl.LinkedNodeKind.exportDirective ||
-        kind == idl.LinkedNodeKind.importDirective ||
-        kind == idl.LinkedNodeKind.partDirective);
-    _variantField_19 ??=
-        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
-    return _variantField_19;
-  }
-
-  @override
-  idl.LinkedNodeVariablesDeclaration get variableDeclaration_declaration {
-    assert(kind == idl.LinkedNodeKind.variableDeclaration);
-    _variantField_32 ??= const _LinkedNodeVariablesDeclarationReader()
-        .vTableGet(_bc, _bcOffset, 32, null);
-    return _variantField_32;
-  }
 }
 
 abstract class _LinkedNodeMixin implements idl.LinkedNode {
@@ -11593,759 +13578,11 @@
     if (flags != 0) _result["flags"] = flags;
     if (kind != idl.LinkedNodeKind.adjacentStrings)
       _result["kind"] = kind.toString().split('.')[1];
-    if (name != '') _result["name"] = name;
-    if (kind == idl.LinkedNodeKind.functionDeclaration) {
-      if (actualReturnType != null)
-        _result["actualReturnType"] = actualReturnType.toJson();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (functionDeclaration_functionExpression != null)
-        _result["functionDeclaration_functionExpression"] =
-            functionDeclaration_functionExpression.toJson();
-      if (functionDeclaration_returnType != null)
-        _result["functionDeclaration_returnType"] =
-            functionDeclaration_returnType.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-    }
-    if (kind == idl.LinkedNodeKind.functionExpression) {
-      if (actualReturnType != null)
-        _result["actualReturnType"] = actualReturnType.toJson();
-      if (functionExpression_body != null)
-        _result["functionExpression_body"] = functionExpression_body.toJson();
-      if (functionExpression_formalParameters != null)
-        _result["functionExpression_formalParameters"] =
-            functionExpression_formalParameters.toJson();
-      if (functionExpression_typeParameters != null)
-        _result["functionExpression_typeParameters"] =
-            functionExpression_typeParameters.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.functionTypeAlias) {
-      if (actualReturnType != null)
-        _result["actualReturnType"] = actualReturnType.toJson();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (functionTypeAlias_formalParameters != null)
-        _result["functionTypeAlias_formalParameters"] =
-            functionTypeAlias_formalParameters.toJson();
-      if (functionTypeAlias_returnType != null)
-        _result["functionTypeAlias_returnType"] =
-            functionTypeAlias_returnType.toJson();
-      if (functionTypeAlias_typeParameters != null)
-        _result["functionTypeAlias_typeParameters"] =
-            functionTypeAlias_typeParameters.toJson();
-      if (typeAlias_hasSelfReference != false)
-        _result["typeAlias_hasSelfReference"] = typeAlias_hasSelfReference;
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-      if (simplyBoundable_isSimplyBounded != false)
-        _result["simplyBoundable_isSimplyBounded"] =
-            simplyBoundable_isSimplyBounded;
-    }
-    if (kind == idl.LinkedNodeKind.genericFunctionType) {
-      if (actualReturnType != null)
-        _result["actualReturnType"] = actualReturnType.toJson();
-      if (genericFunctionType_typeParameters != null)
-        _result["genericFunctionType_typeParameters"] =
-            genericFunctionType_typeParameters.toJson();
-      if (genericFunctionType_returnType != null)
-        _result["genericFunctionType_returnType"] =
-            genericFunctionType_returnType.toJson();
-      if (genericFunctionType_id != 0)
-        _result["genericFunctionType_id"] = genericFunctionType_id;
-      if (genericFunctionType_formalParameters != null)
-        _result["genericFunctionType_formalParameters"] =
-            genericFunctionType_formalParameters.toJson();
-      if (genericFunctionType_type != null)
-        _result["genericFunctionType_type"] = genericFunctionType_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.methodDeclaration) {
-      if (actualReturnType != null)
-        _result["actualReturnType"] = actualReturnType.toJson();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (methodDeclaration_body != null)
-        _result["methodDeclaration_body"] = methodDeclaration_body.toJson();
-      if (methodDeclaration_formalParameters != null)
-        _result["methodDeclaration_formalParameters"] =
-            methodDeclaration_formalParameters.toJson();
-      if (methodDeclaration_returnType != null)
-        _result["methodDeclaration_returnType"] =
-            methodDeclaration_returnType.toJson();
-      if (methodDeclaration_typeParameters != null)
-        _result["methodDeclaration_typeParameters"] =
-            methodDeclaration_typeParameters.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-    }
-    if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
-      if (actualType != null) _result["actualType"] = actualType.toJson();
-      if (normalFormalParameter_metadata.isNotEmpty)
-        _result["normalFormalParameter_metadata"] =
-            normalFormalParameter_metadata
-                .map((_value) => _value.toJson())
-                .toList();
-      if (fieldFormalParameter_type != null)
-        _result["fieldFormalParameter_type"] =
-            fieldFormalParameter_type.toJson();
-      if (fieldFormalParameter_typeParameters != null)
-        _result["fieldFormalParameter_typeParameters"] =
-            fieldFormalParameter_typeParameters.toJson();
-      if (fieldFormalParameter_formalParameters != null)
-        _result["fieldFormalParameter_formalParameters"] =
-            fieldFormalParameter_formalParameters.toJson();
-      if (inheritsCovariant != false)
-        _result["inheritsCovariant"] = inheritsCovariant;
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-      if (normalFormalParameter_comment != null)
-        _result["normalFormalParameter_comment"] =
-            normalFormalParameter_comment.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
-      if (actualType != null) _result["actualType"] = actualType.toJson();
-      if (normalFormalParameter_metadata.isNotEmpty)
-        _result["normalFormalParameter_metadata"] =
-            normalFormalParameter_metadata
-                .map((_value) => _value.toJson())
-                .toList();
-      if (functionTypedFormalParameter_formalParameters != null)
-        _result["functionTypedFormalParameter_formalParameters"] =
-            functionTypedFormalParameter_formalParameters.toJson();
-      if (functionTypedFormalParameter_returnType != null)
-        _result["functionTypedFormalParameter_returnType"] =
-            functionTypedFormalParameter_returnType.toJson();
-      if (functionTypedFormalParameter_typeParameters != null)
-        _result["functionTypedFormalParameter_typeParameters"] =
-            functionTypedFormalParameter_typeParameters.toJson();
-      if (inheritsCovariant != false)
-        _result["inheritsCovariant"] = inheritsCovariant;
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-      if (normalFormalParameter_comment != null)
-        _result["normalFormalParameter_comment"] =
-            normalFormalParameter_comment.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
-      if (actualType != null) _result["actualType"] = actualType.toJson();
-      if (normalFormalParameter_metadata.isNotEmpty)
-        _result["normalFormalParameter_metadata"] =
-            normalFormalParameter_metadata
-                .map((_value) => _value.toJson())
-                .toList();
-      if (simpleFormalParameter_type != null)
-        _result["simpleFormalParameter_type"] =
-            simpleFormalParameter_type.toJson();
-      if (inheritsCovariant != false)
-        _result["inheritsCovariant"] = inheritsCovariant;
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-      if (normalFormalParameter_comment != null)
-        _result["normalFormalParameter_comment"] =
-            normalFormalParameter_comment.toJson();
-      if (topLevelTypeInferenceError != null)
-        _result["topLevelTypeInferenceError"] =
-            topLevelTypeInferenceError.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.variableDeclaration) {
-      if (actualType != null) _result["actualType"] = actualType.toJson();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (variableDeclaration_initializer != null)
-        _result["variableDeclaration_initializer"] =
-            variableDeclaration_initializer.toJson();
-      if (inheritsCovariant != false)
-        _result["inheritsCovariant"] = inheritsCovariant;
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-      if (topLevelTypeInferenceError != null)
-        _result["topLevelTypeInferenceError"] =
-            topLevelTypeInferenceError.toJson();
-      if (variableDeclaration_declaration != null)
-        _result["variableDeclaration_declaration"] =
-            variableDeclaration_declaration.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.binaryExpression) {
-      if (binaryExpression_invokeType != null)
-        _result["binaryExpression_invokeType"] =
-            binaryExpression_invokeType.toJson();
-      if (binaryExpression_leftOperand != null)
-        _result["binaryExpression_leftOperand"] =
-            binaryExpression_leftOperand.toJson();
-      if (binaryExpression_rightOperand != null)
-        _result["binaryExpression_rightOperand"] =
-            binaryExpression_rightOperand.toJson();
-      if (binaryExpression_elementType != null)
-        _result["binaryExpression_elementType"] =
-            binaryExpression_elementType.toJson();
-      if (binaryExpression_element != 0)
-        _result["binaryExpression_element"] = binaryExpression_element;
-      if (binaryExpression_operator != idl.UnlinkedTokenType.NOTHING)
-        _result["binaryExpression_operator"] =
-            binaryExpression_operator.toString().split('.')[1];
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
-      if (invocationExpression_invokeType != null)
-        _result["invocationExpression_invokeType"] =
-            invocationExpression_invokeType.toJson();
-      if (functionExpressionInvocation_function != null)
-        _result["functionExpressionInvocation_function"] =
-            functionExpressionInvocation_function.toJson();
-      if (invocationExpression_typeArguments != null)
-        _result["invocationExpression_typeArguments"] =
-            invocationExpression_typeArguments.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-      if (invocationExpression_arguments != null)
-        _result["invocationExpression_arguments"] =
-            invocationExpression_arguments.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.methodInvocation) {
-      if (invocationExpression_invokeType != null)
-        _result["invocationExpression_invokeType"] =
-            invocationExpression_invokeType.toJson();
-      if (methodInvocation_methodName != null)
-        _result["methodInvocation_methodName"] =
-            methodInvocation_methodName.toJson();
-      if (methodInvocation_target != null)
-        _result["methodInvocation_target"] = methodInvocation_target.toJson();
-      if (invocationExpression_typeArguments != null)
-        _result["invocationExpression_typeArguments"] =
-            invocationExpression_typeArguments.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-      if (invocationExpression_arguments != null)
-        _result["invocationExpression_arguments"] =
-            invocationExpression_arguments.toJson();
-    }
     if (kind == idl.LinkedNodeKind.adjacentStrings) {
       if (adjacentStrings_strings.isNotEmpty)
         _result["adjacentStrings_strings"] =
             adjacentStrings_strings.map((_value) => _value.toJson()).toList();
     }
-    if (kind == idl.LinkedNodeKind.argumentList) {
-      if (argumentList_arguments.isNotEmpty)
-        _result["argumentList_arguments"] =
-            argumentList_arguments.map((_value) => _value.toJson()).toList();
-    }
-    if (kind == idl.LinkedNodeKind.block) {
-      if (block_statements.isNotEmpty)
-        _result["block_statements"] =
-            block_statements.map((_value) => _value.toJson()).toList();
-    }
-    if (kind == idl.LinkedNodeKind.cascadeExpression) {
-      if (cascadeExpression_sections.isNotEmpty)
-        _result["cascadeExpression_sections"] = cascadeExpression_sections
-            .map((_value) => _value.toJson())
-            .toList();
-      if (cascadeExpression_target != null)
-        _result["cascadeExpression_target"] = cascadeExpression_target.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.comment) {
-      if (comment_references.isNotEmpty)
-        _result["comment_references"] =
-            comment_references.map((_value) => _value.toJson()).toList();
-      if (comment_tokens.isNotEmpty) _result["comment_tokens"] = comment_tokens;
-      if (comment_type != idl.LinkedNodeCommentType.block)
-        _result["comment_type"] = comment_type.toString().split('.')[1];
-    }
-    if (kind == idl.LinkedNodeKind.compilationUnit) {
-      if (compilationUnit_declarations.isNotEmpty)
-        _result["compilationUnit_declarations"] = compilationUnit_declarations
-            .map((_value) => _value.toJson())
-            .toList();
-      if (compilationUnit_scriptTag != null)
-        _result["compilationUnit_scriptTag"] =
-            compilationUnit_scriptTag.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (compilationUnit_directives.isNotEmpty)
-        _result["compilationUnit_directives"] = compilationUnit_directives
-            .map((_value) => _value.toJson())
-            .toList();
-    }
-    if (kind == idl.LinkedNodeKind.constructorDeclaration) {
-      if (constructorDeclaration_initializers.isNotEmpty)
-        _result["constructorDeclaration_initializers"] =
-            constructorDeclaration_initializers
-                .map((_value) => _value.toJson())
-                .toList();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (constructorDeclaration_body != null)
-        _result["constructorDeclaration_body"] =
-            constructorDeclaration_body.toJson();
-      if (constructorDeclaration_parameters != null)
-        _result["constructorDeclaration_parameters"] =
-            constructorDeclaration_parameters.toJson();
-      if (constructorDeclaration_redirectedConstructor != null)
-        _result["constructorDeclaration_redirectedConstructor"] =
-            constructorDeclaration_redirectedConstructor.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (constructorDeclaration_returnType != null)
-        _result["constructorDeclaration_returnType"] =
-            constructorDeclaration_returnType.toJson();
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-    }
-    if (kind == idl.LinkedNodeKind.dottedName) {
-      if (dottedName_components.isNotEmpty)
-        _result["dottedName_components"] =
-            dottedName_components.map((_value) => _value.toJson()).toList();
-    }
-    if (kind == idl.LinkedNodeKind.enumDeclaration) {
-      if (enumDeclaration_constants.isNotEmpty)
-        _result["enumDeclaration_constants"] =
-            enumDeclaration_constants.map((_value) => _value.toJson()).toList();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-    }
-    if (kind == idl.LinkedNodeKind.formalParameterList) {
-      if (formalParameterList_parameters.isNotEmpty)
-        _result["formalParameterList_parameters"] =
-            formalParameterList_parameters
-                .map((_value) => _value.toJson())
-                .toList();
-    }
-    if (kind == idl.LinkedNodeKind.implementsClause) {
-      if (implementsClause_interfaces.isNotEmpty)
-        _result["implementsClause_interfaces"] = implementsClause_interfaces
-            .map((_value) => _value.toJson())
-            .toList();
-    }
-    if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
-      if (instanceCreationExpression_arguments.isNotEmpty)
-        _result["instanceCreationExpression_arguments"] =
-            instanceCreationExpression_arguments
-                .map((_value) => _value.toJson())
-                .toList();
-      if (instanceCreationExpression_constructorName != null)
-        _result["instanceCreationExpression_constructorName"] =
-            instanceCreationExpression_constructorName.toJson();
-      if (instanceCreationExpression_typeArguments != null)
-        _result["instanceCreationExpression_typeArguments"] =
-            instanceCreationExpression_typeArguments.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.labeledStatement) {
-      if (labeledStatement_labels.isNotEmpty)
-        _result["labeledStatement_labels"] =
-            labeledStatement_labels.map((_value) => _value.toJson()).toList();
-      if (labeledStatement_statement != null)
-        _result["labeledStatement_statement"] =
-            labeledStatement_statement.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.libraryIdentifier) {
-      if (libraryIdentifier_components.isNotEmpty)
-        _result["libraryIdentifier_components"] = libraryIdentifier_components
-            .map((_value) => _value.toJson())
-            .toList();
-    }
-    if (kind == idl.LinkedNodeKind.exportDirective) {
-      if (namespaceDirective_combinators.isNotEmpty)
-        _result["namespaceDirective_combinators"] =
-            namespaceDirective_combinators
-                .map((_value) => _value.toJson())
-                .toList();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (namespaceDirective_configurations.isNotEmpty)
-        _result["namespaceDirective_configurations"] =
-            namespaceDirective_configurations
-                .map((_value) => _value.toJson())
-                .toList();
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-      if (uriBasedDirective_uri != null)
-        _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
-      if (namespaceDirective_selectedUri != '')
-        _result["namespaceDirective_selectedUri"] =
-            namespaceDirective_selectedUri;
-      if (uriBasedDirective_uriContent != '')
-        _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
-      if (uriBasedDirective_uriElement != 0)
-        _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
-    }
-    if (kind == idl.LinkedNodeKind.importDirective) {
-      if (namespaceDirective_combinators.isNotEmpty)
-        _result["namespaceDirective_combinators"] =
-            namespaceDirective_combinators
-                .map((_value) => _value.toJson())
-                .toList();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (importDirective_prefixOffset != 0)
-        _result["importDirective_prefixOffset"] = importDirective_prefixOffset;
-      if (namespaceDirective_configurations.isNotEmpty)
-        _result["namespaceDirective_configurations"] =
-            namespaceDirective_configurations
-                .map((_value) => _value.toJson())
-                .toList();
-      if (importDirective_prefix != '')
-        _result["importDirective_prefix"] = importDirective_prefix;
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-      if (uriBasedDirective_uri != null)
-        _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
-      if (namespaceDirective_selectedUri != '')
-        _result["namespaceDirective_selectedUri"] =
-            namespaceDirective_selectedUri;
-      if (uriBasedDirective_uriContent != '')
-        _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
-      if (uriBasedDirective_uriElement != 0)
-        _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
-    }
-    if (kind == idl.LinkedNodeKind.onClause) {
-      if (onClause_superclassConstraints.isNotEmpty)
-        _result["onClause_superclassConstraints"] =
-            onClause_superclassConstraints
-                .map((_value) => _value.toJson())
-                .toList();
-    }
-    if (kind == idl.LinkedNodeKind.stringInterpolation) {
-      if (stringInterpolation_elements.isNotEmpty)
-        _result["stringInterpolation_elements"] = stringInterpolation_elements
-            .map((_value) => _value.toJson())
-            .toList();
-    }
-    if (kind == idl.LinkedNodeKind.switchStatement) {
-      if (switchStatement_members.isNotEmpty)
-        _result["switchStatement_members"] =
-            switchStatement_members.map((_value) => _value.toJson()).toList();
-      if (switchStatement_expression != null)
-        _result["switchStatement_expression"] =
-            switchStatement_expression.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.tryStatement) {
-      if (tryStatement_catchClauses.isNotEmpty)
-        _result["tryStatement_catchClauses"] =
-            tryStatement_catchClauses.map((_value) => _value.toJson()).toList();
-      if (tryStatement_body != null)
-        _result["tryStatement_body"] = tryStatement_body.toJson();
-      if (tryStatement_finallyBlock != null)
-        _result["tryStatement_finallyBlock"] =
-            tryStatement_finallyBlock.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.typeArgumentList) {
-      if (typeArgumentList_arguments.isNotEmpty)
-        _result["typeArgumentList_arguments"] = typeArgumentList_arguments
-            .map((_value) => _value.toJson())
-            .toList();
-    }
-    if (kind == idl.LinkedNodeKind.listLiteral) {
-      if (typedLiteral_typeArguments.isNotEmpty)
-        _result["typedLiteral_typeArguments"] = typedLiteral_typeArguments
-            .map((_value) => _value.toJson())
-            .toList();
-      if (listLiteral_elements.isNotEmpty)
-        _result["listLiteral_elements"] =
-            listLiteral_elements.map((_value) => _value.toJson()).toList();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
-      if (typedLiteral_typeArguments.isNotEmpty)
-        _result["typedLiteral_typeArguments"] = typedLiteral_typeArguments
-            .map((_value) => _value.toJson())
-            .toList();
-      if (setOrMapLiteral_elements.isNotEmpty)
-        _result["setOrMapLiteral_elements"] =
-            setOrMapLiteral_elements.map((_value) => _value.toJson()).toList();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.typeName) {
-      if (typeName_typeArguments.isNotEmpty)
-        _result["typeName_typeArguments"] =
-            typeName_typeArguments.map((_value) => _value.toJson()).toList();
-      if (typeName_name != null)
-        _result["typeName_name"] = typeName_name.toJson();
-      if (typeName_type != null)
-        _result["typeName_type"] = typeName_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.typeParameterList) {
-      if (typeParameterList_typeParameters.isNotEmpty)
-        _result["typeParameterList_typeParameters"] =
-            typeParameterList_typeParameters
-                .map((_value) => _value.toJson())
-                .toList();
-    }
-    if (kind == idl.LinkedNodeKind.variableDeclarationList) {
-      if (variableDeclarationList_variables.isNotEmpty)
-        _result["variableDeclarationList_variables"] =
-            variableDeclarationList_variables
-                .map((_value) => _value.toJson())
-                .toList();
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (variableDeclarationList_type != null)
-        _result["variableDeclarationList_type"] =
-            variableDeclarationList_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.withClause) {
-      if (withClause_mixinTypes.isNotEmpty)
-        _result["withClause_mixinTypes"] =
-            withClause_mixinTypes.map((_value) => _value.toJson()).toList();
-    }
-    if (kind == idl.LinkedNodeKind.classDeclaration) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (classDeclaration_extendsClause != null)
-        _result["classDeclaration_extendsClause"] =
-            classDeclaration_extendsClause.toJson();
-      if (classDeclaration_withClause != null)
-        _result["classDeclaration_withClause"] =
-            classDeclaration_withClause.toJson();
-      if (classDeclaration_nativeClause != null)
-        _result["classDeclaration_nativeClause"] =
-            classDeclaration_nativeClause.toJson();
-      if (classDeclaration_isDartObject != false)
-        _result["classDeclaration_isDartObject"] =
-            classDeclaration_isDartObject;
-      if (classOrMixinDeclaration_implementsClause != null)
-        _result["classOrMixinDeclaration_implementsClause"] =
-            classOrMixinDeclaration_implementsClause.toJson();
-      if (classOrMixinDeclaration_members.isNotEmpty)
-        _result["classOrMixinDeclaration_members"] =
-            classOrMixinDeclaration_members
-                .map((_value) => _value.toJson())
-                .toList();
-      if (classOrMixinDeclaration_typeParameters != null)
-        _result["classOrMixinDeclaration_typeParameters"] =
-            classOrMixinDeclaration_typeParameters.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-      if (simplyBoundable_isSimplyBounded != false)
-        _result["simplyBoundable_isSimplyBounded"] =
-            simplyBoundable_isSimplyBounded;
-    }
-    if (kind == idl.LinkedNodeKind.classTypeAlias) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (classTypeAlias_typeParameters != null)
-        _result["classTypeAlias_typeParameters"] =
-            classTypeAlias_typeParameters.toJson();
-      if (classTypeAlias_superclass != null)
-        _result["classTypeAlias_superclass"] =
-            classTypeAlias_superclass.toJson();
-      if (classTypeAlias_withClause != null)
-        _result["classTypeAlias_withClause"] =
-            classTypeAlias_withClause.toJson();
-      if (classTypeAlias_implementsClause != null)
-        _result["classTypeAlias_implementsClause"] =
-            classTypeAlias_implementsClause.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-      if (simplyBoundable_isSimplyBounded != false)
-        _result["simplyBoundable_isSimplyBounded"] =
-            simplyBoundable_isSimplyBounded;
-    }
-    if (kind == idl.LinkedNodeKind.declaredIdentifier) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (declaredIdentifier_identifier != null)
-        _result["declaredIdentifier_identifier"] =
-            declaredIdentifier_identifier.toJson();
-      if (declaredIdentifier_type != null)
-        _result["declaredIdentifier_type"] = declaredIdentifier_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-    }
-    if (kind == idl.LinkedNodeKind.fieldDeclaration) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (fieldDeclaration_fields != null)
-        _result["fieldDeclaration_fields"] = fieldDeclaration_fields.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.genericTypeAlias) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (genericTypeAlias_typeParameters != null)
-        _result["genericTypeAlias_typeParameters"] =
-            genericTypeAlias_typeParameters.toJson();
-      if (genericTypeAlias_functionType != null)
-        _result["genericTypeAlias_functionType"] =
-            genericTypeAlias_functionType.toJson();
-      if (typeAlias_hasSelfReference != false)
-        _result["typeAlias_hasSelfReference"] = typeAlias_hasSelfReference;
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-      if (simplyBoundable_isSimplyBounded != false)
-        _result["simplyBoundable_isSimplyBounded"] =
-            simplyBoundable_isSimplyBounded;
-    }
-    if (kind == idl.LinkedNodeKind.libraryDirective) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (libraryDirective_name != null)
-        _result["libraryDirective_name"] = libraryDirective_name.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.mixinDeclaration) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (mixinDeclaration_onClause != null)
-        _result["mixinDeclaration_onClause"] =
-            mixinDeclaration_onClause.toJson();
-      if (classOrMixinDeclaration_implementsClause != null)
-        _result["classOrMixinDeclaration_implementsClause"] =
-            classOrMixinDeclaration_implementsClause.toJson();
-      if (classOrMixinDeclaration_members.isNotEmpty)
-        _result["classOrMixinDeclaration_members"] =
-            classOrMixinDeclaration_members
-                .map((_value) => _value.toJson())
-                .toList();
-      if (classOrMixinDeclaration_typeParameters != null)
-        _result["classOrMixinDeclaration_typeParameters"] =
-            classOrMixinDeclaration_typeParameters.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (mixinDeclaration_superInvokedNames.isNotEmpty)
-        _result["mixinDeclaration_superInvokedNames"] =
-            mixinDeclaration_superInvokedNames;
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-      if (simplyBoundable_isSimplyBounded != false)
-        _result["simplyBoundable_isSimplyBounded"] =
-            simplyBoundable_isSimplyBounded;
-    }
-    if (kind == idl.LinkedNodeKind.partDirective) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-      if (uriBasedDirective_uri != null)
-        _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
-      if (uriBasedDirective_uriContent != '')
-        _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
-      if (uriBasedDirective_uriElement != 0)
-        _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
-    }
-    if (kind == idl.LinkedNodeKind.partOfDirective) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (partOfDirective_libraryName != null)
-        _result["partOfDirective_libraryName"] =
-            partOfDirective_libraryName.toJson();
-      if (partOfDirective_uri != null)
-        _result["partOfDirective_uri"] = partOfDirective_uri.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (topLevelVariableDeclaration_variableList != null)
-        _result["topLevelVariableDeclaration_variableList"] =
-            topLevelVariableDeclaration_variableList.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.typeParameter) {
-      if (annotatedNode_comment != null)
-        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
-      if (annotatedNode_metadata.isNotEmpty)
-        _result["annotatedNode_metadata"] =
-            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
-      if (typeParameter_bound != null)
-        _result["typeParameter_bound"] = typeParameter_bound.toJson();
-      if (typeParameter_defaultType != null)
-        _result["typeParameter_defaultType"] =
-            typeParameter_defaultType.toJson();
-      if (codeLength != 0) _result["codeLength"] = codeLength;
-      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
-      if (nameOffset != 0) _result["nameOffset"] = nameOffset;
-    }
-    if (kind == idl.LinkedNodeKind.switchCase) {
-      if (switchMember_statements.isNotEmpty)
-        _result["switchMember_statements"] =
-            switchMember_statements.map((_value) => _value.toJson()).toList();
-      if (switchCase_expression != null)
-        _result["switchCase_expression"] = switchCase_expression.toJson();
-      if (switchMember_labels.isNotEmpty)
-        _result["switchMember_labels"] =
-            switchMember_labels.map((_value) => _value.toJson()).toList();
-    }
-    if (kind == idl.LinkedNodeKind.switchDefault) {
-      if (switchMember_statements.isNotEmpty)
-        _result["switchMember_statements"] =
-            switchMember_statements.map((_value) => _value.toJson()).toList();
-      if (switchMember_labels.isNotEmpty)
-        _result["switchMember_labels"] =
-            switchMember_labels.map((_value) => _value.toJson()).toList();
-    }
     if (kind == idl.LinkedNodeKind.annotation) {
       if (annotation_arguments != null)
         _result["annotation_arguments"] = annotation_arguments.toJson();
@@ -12359,6 +13596,11 @@
       if (annotation_name != null)
         _result["annotation_name"] = annotation_name.toJson();
     }
+    if (kind == idl.LinkedNodeKind.argumentList) {
+      if (argumentList_arguments.isNotEmpty)
+        _result["argumentList_arguments"] =
+            argumentList_arguments.map((_value) => _value.toJson()).toList();
+    }
     if (kind == idl.LinkedNodeKind.asExpression) {
       if (asExpression_expression != null)
         _result["asExpression_expression"] = asExpression_expression.toJson();
@@ -12407,14 +13649,54 @@
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
+    if (kind == idl.LinkedNodeKind.binaryExpression) {
+      if (binaryExpression_invokeType != null)
+        _result["binaryExpression_invokeType"] =
+            binaryExpression_invokeType.toJson();
+      if (binaryExpression_leftOperand != null)
+        _result["binaryExpression_leftOperand"] =
+            binaryExpression_leftOperand.toJson();
+      if (binaryExpression_rightOperand != null)
+        _result["binaryExpression_rightOperand"] =
+            binaryExpression_rightOperand.toJson();
+      if (binaryExpression_elementType != null)
+        _result["binaryExpression_elementType"] =
+            binaryExpression_elementType.toJson();
+      if (binaryExpression_element != 0)
+        _result["binaryExpression_element"] = binaryExpression_element;
+      if (binaryExpression_operator != idl.UnlinkedTokenType.NOTHING)
+        _result["binaryExpression_operator"] =
+            binaryExpression_operator.toString().split('.')[1];
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.block) {
+      if (block_statements.isNotEmpty)
+        _result["block_statements"] =
+            block_statements.map((_value) => _value.toJson()).toList();
+    }
     if (kind == idl.LinkedNodeKind.blockFunctionBody) {
       if (blockFunctionBody_block != null)
         _result["blockFunctionBody_block"] = blockFunctionBody_block.toJson();
     }
+    if (kind == idl.LinkedNodeKind.booleanLiteral) {
+      if (booleanLiteral_value != false)
+        _result["booleanLiteral_value"] = booleanLiteral_value;
+    }
     if (kind == idl.LinkedNodeKind.breakStatement) {
       if (breakStatement_label != null)
         _result["breakStatement_label"] = breakStatement_label.toJson();
     }
+    if (kind == idl.LinkedNodeKind.cascadeExpression) {
+      if (cascadeExpression_sections.isNotEmpty)
+        _result["cascadeExpression_sections"] = cascadeExpression_sections
+            .map((_value) => _value.toJson())
+            .toList();
+      if (cascadeExpression_target != null)
+        _result["cascadeExpression_target"] = cascadeExpression_target.toJson();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
     if (kind == idl.LinkedNodeKind.catchClause) {
       if (catchClause_body != null)
         _result["catchClause_body"] = catchClause_body.toJson();
@@ -12428,11 +13710,99 @@
         _result["catchClause_stackTraceParameter"] =
             catchClause_stackTraceParameter.toJson();
     }
+    if (kind == idl.LinkedNodeKind.classDeclaration) {
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (classDeclaration_extendsClause != null)
+        _result["classDeclaration_extendsClause"] =
+            classDeclaration_extendsClause.toJson();
+      if (classDeclaration_withClause != null)
+        _result["classDeclaration_withClause"] =
+            classDeclaration_withClause.toJson();
+      if (classDeclaration_nativeClause != null)
+        _result["classDeclaration_nativeClause"] =
+            classDeclaration_nativeClause.toJson();
+      if (classDeclaration_isDartObject != false)
+        _result["classDeclaration_isDartObject"] =
+            classDeclaration_isDartObject;
+      if (classOrMixinDeclaration_implementsClause != null)
+        _result["classOrMixinDeclaration_implementsClause"] =
+            classOrMixinDeclaration_implementsClause.toJson();
+      if (classOrMixinDeclaration_members.isNotEmpty)
+        _result["classOrMixinDeclaration_members"] =
+            classOrMixinDeclaration_members
+                .map((_value) => _value.toJson())
+                .toList();
+      if (classOrMixinDeclaration_typeParameters != null)
+        _result["classOrMixinDeclaration_typeParameters"] =
+            classOrMixinDeclaration_typeParameters.toJson();
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (namedCompilationUnitMember_name != null)
+        _result["namedCompilationUnitMember_name"] =
+            namedCompilationUnitMember_name.toJson();
+      if (simplyBoundable_isSimplyBounded != false)
+        _result["simplyBoundable_isSimplyBounded"] =
+            simplyBoundable_isSimplyBounded;
+    }
+    if (kind == idl.LinkedNodeKind.classTypeAlias) {
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (classTypeAlias_typeParameters != null)
+        _result["classTypeAlias_typeParameters"] =
+            classTypeAlias_typeParameters.toJson();
+      if (classTypeAlias_superclass != null)
+        _result["classTypeAlias_superclass"] =
+            classTypeAlias_superclass.toJson();
+      if (classTypeAlias_withClause != null)
+        _result["classTypeAlias_withClause"] =
+            classTypeAlias_withClause.toJson();
+      if (classTypeAlias_implementsClause != null)
+        _result["classTypeAlias_implementsClause"] =
+            classTypeAlias_implementsClause.toJson();
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (namedCompilationUnitMember_name != null)
+        _result["namedCompilationUnitMember_name"] =
+            namedCompilationUnitMember_name.toJson();
+      if (simplyBoundable_isSimplyBounded != false)
+        _result["simplyBoundable_isSimplyBounded"] =
+            simplyBoundable_isSimplyBounded;
+    }
+    if (kind == idl.LinkedNodeKind.comment) {
+      if (comment_references.isNotEmpty)
+        _result["comment_references"] =
+            comment_references.map((_value) => _value.toJson()).toList();
+      if (comment_tokens.isNotEmpty) _result["comment_tokens"] = comment_tokens;
+      if (comment_type != idl.LinkedNodeCommentType.block)
+        _result["comment_type"] = comment_type.toString().split('.')[1];
+    }
     if (kind == idl.LinkedNodeKind.commentReference) {
       if (commentReference_identifier != null)
         _result["commentReference_identifier"] =
             commentReference_identifier.toJson();
     }
+    if (kind == idl.LinkedNodeKind.compilationUnit) {
+      if (compilationUnit_declarations.isNotEmpty)
+        _result["compilationUnit_declarations"] = compilationUnit_declarations
+            .map((_value) => _value.toJson())
+            .toList();
+      if (compilationUnit_scriptTag != null)
+        _result["compilationUnit_scriptTag"] =
+            compilationUnit_scriptTag.toJson();
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (compilationUnit_directives.isNotEmpty)
+        _result["compilationUnit_directives"] = compilationUnit_directives
+            .map((_value) => _value.toJson())
+            .toList();
+    }
     if (kind == idl.LinkedNodeKind.conditionalExpression) {
       if (conditionalExpression_condition != null)
         _result["conditionalExpression_condition"] =
@@ -12454,6 +13824,38 @@
       if (configuration_uri != null)
         _result["configuration_uri"] = configuration_uri.toJson();
     }
+    if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+      if (constructorDeclaration_initializers.isNotEmpty)
+        _result["constructorDeclaration_initializers"] =
+            constructorDeclaration_initializers
+                .map((_value) => _value.toJson())
+                .toList();
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (constructorDeclaration_body != null)
+        _result["constructorDeclaration_body"] =
+            constructorDeclaration_body.toJson();
+      if (constructorDeclaration_name != null)
+        _result["constructorDeclaration_name"] =
+            constructorDeclaration_name.toJson();
+      if (constructorDeclaration_parameters != null)
+        _result["constructorDeclaration_parameters"] =
+            constructorDeclaration_parameters.toJson();
+      if (constructorDeclaration_redirectedConstructor != null)
+        _result["constructorDeclaration_redirectedConstructor"] =
+            constructorDeclaration_redirectedConstructor.toJson();
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (constructorDeclaration_periodOffset != 0)
+        _result["constructorDeclaration_periodOffset"] =
+            constructorDeclaration_periodOffset;
+      if (constructorDeclaration_returnType != null)
+        _result["constructorDeclaration_returnType"] =
+            constructorDeclaration_returnType.toJson();
+    }
     if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
       if (constructorFieldInitializer_expression != null)
         _result["constructorFieldInitializer_expression"] =
@@ -12477,6 +13879,18 @@
       if (continueStatement_label != null)
         _result["continueStatement_label"] = continueStatement_label.toJson();
     }
+    if (kind == idl.LinkedNodeKind.declaredIdentifier) {
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (declaredIdentifier_identifier != null)
+        _result["declaredIdentifier_identifier"] =
+            declaredIdentifier_identifier.toJson();
+      if (declaredIdentifier_type != null)
+        _result["declaredIdentifier_type"] = declaredIdentifier_type.toJson();
+    }
     if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
       if (defaultFormalParameter_defaultValue != null)
         _result["defaultFormalParameter_defaultValue"] =
@@ -12497,6 +13911,78 @@
       if (doStatement_condition != null)
         _result["doStatement_condition"] = doStatement_condition.toJson();
     }
+    if (kind == idl.LinkedNodeKind.dottedName) {
+      if (dottedName_components.isNotEmpty)
+        _result["dottedName_components"] =
+            dottedName_components.map((_value) => _value.toJson()).toList();
+    }
+    if (kind == idl.LinkedNodeKind.doubleLiteral) {
+      if (doubleLiteral_value != 0.0)
+        _result["doubleLiteral_value"] = doubleLiteral_value.isFinite
+            ? doubleLiteral_value
+            : doubleLiteral_value.toString();
+    }
+    if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
+      if (emptyFunctionBody_fake != 0)
+        _result["emptyFunctionBody_fake"] = emptyFunctionBody_fake;
+    }
+    if (kind == idl.LinkedNodeKind.emptyStatement) {
+      if (emptyStatement_fake != 0)
+        _result["emptyStatement_fake"] = emptyStatement_fake;
+    }
+    if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (enumConstantDeclaration_name != null)
+        _result["enumConstantDeclaration_name"] =
+            enumConstantDeclaration_name.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.enumDeclaration) {
+      if (enumDeclaration_constants.isNotEmpty)
+        _result["enumDeclaration_constants"] =
+            enumDeclaration_constants.map((_value) => _value.toJson()).toList();
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (namedCompilationUnitMember_name != null)
+        _result["namedCompilationUnitMember_name"] =
+            namedCompilationUnitMember_name.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.exportDirective) {
+      if (namespaceDirective_combinators.isNotEmpty)
+        _result["namespaceDirective_combinators"] =
+            namespaceDirective_combinators
+                .map((_value) => _value.toJson())
+                .toList();
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (directive_keywordOffset != 0)
+        _result["directive_keywordOffset"] = directive_keywordOffset;
+      if (namespaceDirective_configurations.isNotEmpty)
+        _result["namespaceDirective_configurations"] =
+            namespaceDirective_configurations
+                .map((_value) => _value.toJson())
+                .toList();
+      if (uriBasedDirective_uriElement != 0)
+        _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
+      if (uriBasedDirective_uri != null)
+        _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
+      if (namespaceDirective_selectedUri != '')
+        _result["namespaceDirective_selectedUri"] =
+            namespaceDirective_selectedUri;
+      if (uriBasedDirective_uriContent != '')
+        _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
+    }
     if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
       if (expressionFunctionBody_expression != null)
         _result["expressionFunctionBody_expression"] =
@@ -12511,6 +13997,42 @@
       if (extendsClause_superclass != null)
         _result["extendsClause_superclass"] = extendsClause_superclass.toJson();
     }
+    if (kind == idl.LinkedNodeKind.fieldDeclaration) {
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (fieldDeclaration_fields != null)
+        _result["fieldDeclaration_fields"] = fieldDeclaration_fields.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+      if (actualType != null) _result["actualType"] = actualType.toJson();
+      if (normalFormalParameter_metadata.isNotEmpty)
+        _result["normalFormalParameter_metadata"] =
+            normalFormalParameter_metadata
+                .map((_value) => _value.toJson())
+                .toList();
+      if (fieldFormalParameter_type != null)
+        _result["fieldFormalParameter_type"] =
+            fieldFormalParameter_type.toJson();
+      if (fieldFormalParameter_typeParameters != null)
+        _result["fieldFormalParameter_typeParameters"] =
+            fieldFormalParameter_typeParameters.toJson();
+      if (fieldFormalParameter_formalParameters != null)
+        _result["fieldFormalParameter_formalParameters"] =
+            fieldFormalParameter_formalParameters.toJson();
+      if (inheritsCovariant != false)
+        _result["inheritsCovariant"] = inheritsCovariant;
+      if (normalFormalParameter_identifier != null)
+        _result["normalFormalParameter_identifier"] =
+            normalFormalParameter_identifier.toJson();
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (normalFormalParameter_comment != null)
+        _result["normalFormalParameter_comment"] =
+            normalFormalParameter_comment.toJson();
+    }
     if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
       if (forEachParts_iterable != null)
         _result["forEachParts_iterable"] = forEachParts_iterable.toJson();
@@ -12531,12 +14053,6 @@
       if (forElement_body != null)
         _result["forElement_body"] = forElement_body.toJson();
     }
-    if (kind == idl.LinkedNodeKind.forStatement) {
-      if (forMixin_forLoopParts != null)
-        _result["forMixin_forLoopParts"] = forMixin_forLoopParts.toJson();
-      if (forStatement_body != null)
-        _result["forStatement_body"] = forStatement_body.toJson();
-    }
     if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
       if (forParts_condition != null)
         _result["forParts_condition"] = forParts_condition.toJson();
@@ -12557,11 +14073,170 @@
         _result["forParts_updaters"] =
             forParts_updaters.map((_value) => _value.toJson()).toList();
     }
+    if (kind == idl.LinkedNodeKind.forStatement) {
+      if (forMixin_forLoopParts != null)
+        _result["forMixin_forLoopParts"] = forMixin_forLoopParts.toJson();
+      if (forStatement_body != null)
+        _result["forStatement_body"] = forStatement_body.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.formalParameterList) {
+      if (formalParameterList_parameters.isNotEmpty)
+        _result["formalParameterList_parameters"] =
+            formalParameterList_parameters
+                .map((_value) => _value.toJson())
+                .toList();
+    }
+    if (kind == idl.LinkedNodeKind.functionDeclaration) {
+      if (actualReturnType != null)
+        _result["actualReturnType"] = actualReturnType.toJson();
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (functionDeclaration_functionExpression != null)
+        _result["functionDeclaration_functionExpression"] =
+            functionDeclaration_functionExpression.toJson();
+      if (functionDeclaration_returnType != null)
+        _result["functionDeclaration_returnType"] =
+            functionDeclaration_returnType.toJson();
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (namedCompilationUnitMember_name != null)
+        _result["namedCompilationUnitMember_name"] =
+            namedCompilationUnitMember_name.toJson();
+    }
     if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
       if (functionDeclarationStatement_functionDeclaration != null)
         _result["functionDeclarationStatement_functionDeclaration"] =
             functionDeclarationStatement_functionDeclaration.toJson();
     }
+    if (kind == idl.LinkedNodeKind.functionExpression) {
+      if (actualReturnType != null)
+        _result["actualReturnType"] = actualReturnType.toJson();
+      if (functionExpression_body != null)
+        _result["functionExpression_body"] = functionExpression_body.toJson();
+      if (functionExpression_formalParameters != null)
+        _result["functionExpression_formalParameters"] =
+            functionExpression_formalParameters.toJson();
+      if (functionExpression_typeParameters != null)
+        _result["functionExpression_typeParameters"] =
+            functionExpression_typeParameters.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
+      if (invocationExpression_invokeType != null)
+        _result["invocationExpression_invokeType"] =
+            invocationExpression_invokeType.toJson();
+      if (functionExpressionInvocation_function != null)
+        _result["functionExpressionInvocation_function"] =
+            functionExpressionInvocation_function.toJson();
+      if (invocationExpression_typeArguments != null)
+        _result["invocationExpression_typeArguments"] =
+            invocationExpression_typeArguments.toJson();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+      if (invocationExpression_arguments != null)
+        _result["invocationExpression_arguments"] =
+            invocationExpression_arguments.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+      if (actualReturnType != null)
+        _result["actualReturnType"] = actualReturnType.toJson();
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (functionTypeAlias_formalParameters != null)
+        _result["functionTypeAlias_formalParameters"] =
+            functionTypeAlias_formalParameters.toJson();
+      if (functionTypeAlias_returnType != null)
+        _result["functionTypeAlias_returnType"] =
+            functionTypeAlias_returnType.toJson();
+      if (functionTypeAlias_typeParameters != null)
+        _result["functionTypeAlias_typeParameters"] =
+            functionTypeAlias_typeParameters.toJson();
+      if (typeAlias_hasSelfReference != false)
+        _result["typeAlias_hasSelfReference"] = typeAlias_hasSelfReference;
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (namedCompilationUnitMember_name != null)
+        _result["namedCompilationUnitMember_name"] =
+            namedCompilationUnitMember_name.toJson();
+      if (simplyBoundable_isSimplyBounded != false)
+        _result["simplyBoundable_isSimplyBounded"] =
+            simplyBoundable_isSimplyBounded;
+    }
+    if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+      if (actualType != null) _result["actualType"] = actualType.toJson();
+      if (normalFormalParameter_metadata.isNotEmpty)
+        _result["normalFormalParameter_metadata"] =
+            normalFormalParameter_metadata
+                .map((_value) => _value.toJson())
+                .toList();
+      if (functionTypedFormalParameter_formalParameters != null)
+        _result["functionTypedFormalParameter_formalParameters"] =
+            functionTypedFormalParameter_formalParameters.toJson();
+      if (functionTypedFormalParameter_returnType != null)
+        _result["functionTypedFormalParameter_returnType"] =
+            functionTypedFormalParameter_returnType.toJson();
+      if (functionTypedFormalParameter_typeParameters != null)
+        _result["functionTypedFormalParameter_typeParameters"] =
+            functionTypedFormalParameter_typeParameters.toJson();
+      if (inheritsCovariant != false)
+        _result["inheritsCovariant"] = inheritsCovariant;
+      if (normalFormalParameter_identifier != null)
+        _result["normalFormalParameter_identifier"] =
+            normalFormalParameter_identifier.toJson();
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (normalFormalParameter_comment != null)
+        _result["normalFormalParameter_comment"] =
+            normalFormalParameter_comment.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.genericFunctionType) {
+      if (actualReturnType != null)
+        _result["actualReturnType"] = actualReturnType.toJson();
+      if (genericFunctionType_typeParameters != null)
+        _result["genericFunctionType_typeParameters"] =
+            genericFunctionType_typeParameters.toJson();
+      if (genericFunctionType_returnType != null)
+        _result["genericFunctionType_returnType"] =
+            genericFunctionType_returnType.toJson();
+      if (genericFunctionType_id != 0)
+        _result["genericFunctionType_id"] = genericFunctionType_id;
+      if (genericFunctionType_formalParameters != null)
+        _result["genericFunctionType_formalParameters"] =
+            genericFunctionType_formalParameters.toJson();
+      if (genericFunctionType_type != null)
+        _result["genericFunctionType_type"] = genericFunctionType_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.genericTypeAlias) {
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (genericTypeAlias_typeParameters != null)
+        _result["genericTypeAlias_typeParameters"] =
+            genericTypeAlias_typeParameters.toJson();
+      if (genericTypeAlias_functionType != null)
+        _result["genericTypeAlias_functionType"] =
+            genericTypeAlias_functionType.toJson();
+      if (typeAlias_hasSelfReference != false)
+        _result["typeAlias_hasSelfReference"] = typeAlias_hasSelfReference;
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (namedCompilationUnitMember_name != null)
+        _result["namedCompilationUnitMember_name"] =
+            namedCompilationUnitMember_name.toJson();
+      if (simplyBoundable_isSimplyBounded != false)
+        _result["simplyBoundable_isSimplyBounded"] =
+            simplyBoundable_isSimplyBounded;
+    }
+    if (kind == idl.LinkedNodeKind.hideCombinator) {
+      if (names.isNotEmpty) _result["names"] = names;
+    }
     if (kind == idl.LinkedNodeKind.ifElement) {
       if (ifMixin_condition != null)
         _result["ifMixin_condition"] = ifMixin_condition.toJson();
@@ -12580,6 +14255,44 @@
         _result["ifStatement_thenStatement"] =
             ifStatement_thenStatement.toJson();
     }
+    if (kind == idl.LinkedNodeKind.implementsClause) {
+      if (implementsClause_interfaces.isNotEmpty)
+        _result["implementsClause_interfaces"] = implementsClause_interfaces
+            .map((_value) => _value.toJson())
+            .toList();
+    }
+    if (kind == idl.LinkedNodeKind.importDirective) {
+      if (namespaceDirective_combinators.isNotEmpty)
+        _result["namespaceDirective_combinators"] =
+            namespaceDirective_combinators
+                .map((_value) => _value.toJson())
+                .toList();
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (directive_keywordOffset != 0)
+        _result["directive_keywordOffset"] = directive_keywordOffset;
+      if (importDirective_prefixOffset != 0)
+        _result["importDirective_prefixOffset"] = importDirective_prefixOffset;
+      if (namespaceDirective_configurations.isNotEmpty)
+        _result["namespaceDirective_configurations"] =
+            namespaceDirective_configurations
+                .map((_value) => _value.toJson())
+                .toList();
+      if (uriBasedDirective_uriElement != 0)
+        _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
+      if (importDirective_prefix != '')
+        _result["importDirective_prefix"] = importDirective_prefix;
+      if (uriBasedDirective_uri != null)
+        _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
+      if (namespaceDirective_selectedUri != '')
+        _result["namespaceDirective_selectedUri"] =
+            namespaceDirective_selectedUri;
+      if (uriBasedDirective_uriContent != '')
+        _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
+    }
     if (kind == idl.LinkedNodeKind.indexExpression) {
       if (indexExpression_index != null)
         _result["indexExpression_index"] = indexExpression_index.toJson();
@@ -12593,11 +14306,34 @@
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
+    if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
+      if (instanceCreationExpression_arguments.isNotEmpty)
+        _result["instanceCreationExpression_arguments"] =
+            instanceCreationExpression_arguments
+                .map((_value) => _value.toJson())
+                .toList();
+      if (instanceCreationExpression_constructorName != null)
+        _result["instanceCreationExpression_constructorName"] =
+            instanceCreationExpression_constructorName.toJson();
+      if (instanceCreationExpression_typeArguments != null)
+        _result["instanceCreationExpression_typeArguments"] =
+            instanceCreationExpression_typeArguments.toJson();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.integerLiteral) {
+      if (integerLiteral_value != 0)
+        _result["integerLiteral_value"] = integerLiteral_value;
+    }
     if (kind == idl.LinkedNodeKind.interpolationExpression) {
       if (interpolationExpression_expression != null)
         _result["interpolationExpression_expression"] =
             interpolationExpression_expression.toJson();
     }
+    if (kind == idl.LinkedNodeKind.interpolationString) {
+      if (interpolationString_value != '')
+        _result["interpolationString_value"] = interpolationString_value;
+    }
     if (kind == idl.LinkedNodeKind.isExpression) {
       if (isExpression_expression != null)
         _result["isExpression_expression"] = isExpression_expression.toJson();
@@ -12607,12 +14343,122 @@
     if (kind == idl.LinkedNodeKind.label) {
       if (label_label != null) _result["label_label"] = label_label.toJson();
     }
+    if (kind == idl.LinkedNodeKind.labeledStatement) {
+      if (labeledStatement_labels.isNotEmpty)
+        _result["labeledStatement_labels"] =
+            labeledStatement_labels.map((_value) => _value.toJson()).toList();
+      if (labeledStatement_statement != null)
+        _result["labeledStatement_statement"] =
+            labeledStatement_statement.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.libraryDirective) {
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (libraryDirective_name != null)
+        _result["libraryDirective_name"] = libraryDirective_name.toJson();
+      if (directive_keywordOffset != 0)
+        _result["directive_keywordOffset"] = directive_keywordOffset;
+    }
+    if (kind == idl.LinkedNodeKind.libraryIdentifier) {
+      if (libraryIdentifier_components.isNotEmpty)
+        _result["libraryIdentifier_components"] = libraryIdentifier_components
+            .map((_value) => _value.toJson())
+            .toList();
+    }
+    if (kind == idl.LinkedNodeKind.listLiteral) {
+      if (typedLiteral_typeArguments.isNotEmpty)
+        _result["typedLiteral_typeArguments"] = typedLiteral_typeArguments
+            .map((_value) => _value.toJson())
+            .toList();
+      if (listLiteral_elements.isNotEmpty)
+        _result["listLiteral_elements"] =
+            listLiteral_elements.map((_value) => _value.toJson()).toList();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
     if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
       if (mapLiteralEntry_key != null)
         _result["mapLiteralEntry_key"] = mapLiteralEntry_key.toJson();
       if (mapLiteralEntry_value != null)
         _result["mapLiteralEntry_value"] = mapLiteralEntry_value.toJson();
     }
+    if (kind == idl.LinkedNodeKind.methodDeclaration) {
+      if (actualReturnType != null)
+        _result["actualReturnType"] = actualReturnType.toJson();
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (methodDeclaration_body != null)
+        _result["methodDeclaration_body"] = methodDeclaration_body.toJson();
+      if (methodDeclaration_formalParameters != null)
+        _result["methodDeclaration_formalParameters"] =
+            methodDeclaration_formalParameters.toJson();
+      if (methodDeclaration_returnType != null)
+        _result["methodDeclaration_returnType"] =
+            methodDeclaration_returnType.toJson();
+      if (methodDeclaration_typeParameters != null)
+        _result["methodDeclaration_typeParameters"] =
+            methodDeclaration_typeParameters.toJson();
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (methodDeclaration_name != null)
+        _result["methodDeclaration_name"] = methodDeclaration_name.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.methodInvocation) {
+      if (invocationExpression_invokeType != null)
+        _result["invocationExpression_invokeType"] =
+            invocationExpression_invokeType.toJson();
+      if (methodInvocation_methodName != null)
+        _result["methodInvocation_methodName"] =
+            methodInvocation_methodName.toJson();
+      if (methodInvocation_target != null)
+        _result["methodInvocation_target"] = methodInvocation_target.toJson();
+      if (invocationExpression_typeArguments != null)
+        _result["invocationExpression_typeArguments"] =
+            invocationExpression_typeArguments.toJson();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+      if (invocationExpression_arguments != null)
+        _result["invocationExpression_arguments"] =
+            invocationExpression_arguments.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.mixinDeclaration) {
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (mixinDeclaration_onClause != null)
+        _result["mixinDeclaration_onClause"] =
+            mixinDeclaration_onClause.toJson();
+      if (classOrMixinDeclaration_implementsClause != null)
+        _result["classOrMixinDeclaration_implementsClause"] =
+            classOrMixinDeclaration_implementsClause.toJson();
+      if (classOrMixinDeclaration_members.isNotEmpty)
+        _result["classOrMixinDeclaration_members"] =
+            classOrMixinDeclaration_members
+                .map((_value) => _value.toJson())
+                .toList();
+      if (classOrMixinDeclaration_typeParameters != null)
+        _result["classOrMixinDeclaration_typeParameters"] =
+            classOrMixinDeclaration_typeParameters.toJson();
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (namedCompilationUnitMember_name != null)
+        _result["namedCompilationUnitMember_name"] =
+            namedCompilationUnitMember_name.toJson();
+      if (mixinDeclaration_superInvokedNames.isNotEmpty)
+        _result["mixinDeclaration_superInvokedNames"] =
+            mixinDeclaration_superInvokedNames;
+      if (simplyBoundable_isSimplyBounded != false)
+        _result["simplyBoundable_isSimplyBounded"] =
+            simplyBoundable_isSimplyBounded;
+    }
     if (kind == idl.LinkedNodeKind.namedExpression) {
       if (namedExpression_expression != null)
         _result["namedExpression_expression"] =
@@ -12629,6 +14475,18 @@
         _result["nativeFunctionBody_stringLiteral"] =
             nativeFunctionBody_stringLiteral.toJson();
     }
+    if (kind == idl.LinkedNodeKind.nullLiteral) {
+      if (nullLiteral_fake != 0) _result["nullLiteral_fake"] = nullLiteral_fake;
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.onClause) {
+      if (onClause_superclassConstraints.isNotEmpty)
+        _result["onClause_superclassConstraints"] =
+            onClause_superclassConstraints
+                .map((_value) => _value.toJson())
+                .toList();
+    }
     if (kind == idl.LinkedNodeKind.parenthesizedExpression) {
       if (parenthesizedExpression_expression != null)
         _result["parenthesizedExpression_expression"] =
@@ -12636,6 +14494,35 @@
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
+    if (kind == idl.LinkedNodeKind.partDirective) {
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (directive_keywordOffset != 0)
+        _result["directive_keywordOffset"] = directive_keywordOffset;
+      if (uriBasedDirective_uriElement != 0)
+        _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
+      if (uriBasedDirective_uri != null)
+        _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
+      if (uriBasedDirective_uriContent != '')
+        _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
+    }
+    if (kind == idl.LinkedNodeKind.partOfDirective) {
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (partOfDirective_libraryName != null)
+        _result["partOfDirective_libraryName"] =
+            partOfDirective_libraryName.toJson();
+      if (partOfDirective_uri != null)
+        _result["partOfDirective_uri"] = partOfDirective_uri.toJson();
+      if (directive_keywordOffset != 0)
+        _result["directive_keywordOffset"] = directive_keywordOffset;
+    }
     if (kind == idl.LinkedNodeKind.postfixExpression) {
       if (postfixExpression_operand != null)
         _result["postfixExpression_operand"] =
@@ -12651,16 +14538,6 @@
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
-    if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
-      if (prefixedIdentifier_identifier != null)
-        _result["prefixedIdentifier_identifier"] =
-            prefixedIdentifier_identifier.toJson();
-      if (prefixedIdentifier_prefix != null)
-        _result["prefixedIdentifier_prefix"] =
-            prefixedIdentifier_prefix.toJson();
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
     if (kind == idl.LinkedNodeKind.prefixExpression) {
       if (prefixExpression_operand != null)
         _result["prefixExpression_operand"] = prefixExpression_operand.toJson();
@@ -12675,6 +14552,16 @@
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
+    if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
+      if (prefixedIdentifier_identifier != null)
+        _result["prefixedIdentifier_identifier"] =
+            prefixedIdentifier_identifier.toJson();
+      if (prefixedIdentifier_prefix != null)
+        _result["prefixedIdentifier_prefix"] =
+            prefixedIdentifier_prefix.toJson();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
     if (kind == idl.LinkedNodeKind.propertyAccess) {
       if (propertyAccess_propertyName != null)
         _result["propertyAccess_propertyName"] =
@@ -12701,11 +14588,70 @@
         _result["redirectingConstructorInvocation_element"] =
             redirectingConstructorInvocation_element;
     }
+    if (kind == idl.LinkedNodeKind.rethrowExpression) {
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
     if (kind == idl.LinkedNodeKind.returnStatement) {
       if (returnStatement_expression != null)
         _result["returnStatement_expression"] =
             returnStatement_expression.toJson();
     }
+    if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
+      if (typedLiteral_typeArguments.isNotEmpty)
+        _result["typedLiteral_typeArguments"] = typedLiteral_typeArguments
+            .map((_value) => _value.toJson())
+            .toList();
+      if (setOrMapLiteral_elements.isNotEmpty)
+        _result["setOrMapLiteral_elements"] =
+            setOrMapLiteral_elements.map((_value) => _value.toJson()).toList();
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.showCombinator) {
+      if (names.isNotEmpty) _result["names"] = names;
+    }
+    if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+      if (actualType != null) _result["actualType"] = actualType.toJson();
+      if (normalFormalParameter_metadata.isNotEmpty)
+        _result["normalFormalParameter_metadata"] =
+            normalFormalParameter_metadata
+                .map((_value) => _value.toJson())
+                .toList();
+      if (simpleFormalParameter_type != null)
+        _result["simpleFormalParameter_type"] =
+            simpleFormalParameter_type.toJson();
+      if (inheritsCovariant != false)
+        _result["inheritsCovariant"] = inheritsCovariant;
+      if (normalFormalParameter_identifier != null)
+        _result["normalFormalParameter_identifier"] =
+            normalFormalParameter_identifier.toJson();
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (normalFormalParameter_comment != null)
+        _result["normalFormalParameter_comment"] =
+            normalFormalParameter_comment.toJson();
+      if (topLevelTypeInferenceError != null)
+        _result["topLevelTypeInferenceError"] =
+            topLevelTypeInferenceError.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.simpleIdentifier) {
+      if (simpleIdentifier_elementType != null)
+        _result["simpleIdentifier_elementType"] =
+            simpleIdentifier_elementType.toJson();
+      if (simpleIdentifier_element != 0)
+        _result["simpleIdentifier_element"] = simpleIdentifier_element;
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+      if (simpleIdentifier_offset != 0)
+        _result["simpleIdentifier_offset"] = simpleIdentifier_offset;
+      if (simpleIdentifier_name != '')
+        _result["simpleIdentifier_name"] = simpleIdentifier_name;
+    }
+    if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
+      if (simpleStringLiteral_value != '')
+        _result["simpleStringLiteral_value"] = simpleStringLiteral_value;
+    }
     if (kind == idl.LinkedNodeKind.spreadElement) {
       if (spreadElement_expression != null)
         _result["spreadElement_expression"] = spreadElement_expression.toJson();
@@ -12713,6 +14659,12 @@
         _result["spreadElement_spreadOperator"] =
             spreadElement_spreadOperator.toString().split('.')[1];
     }
+    if (kind == idl.LinkedNodeKind.stringInterpolation) {
+      if (stringInterpolation_elements.isNotEmpty)
+        _result["stringInterpolation_elements"] = stringInterpolation_elements
+            .map((_value) => _value.toJson())
+            .toList();
+    }
     if (kind == idl.LinkedNodeKind.superConstructorInvocation) {
       if (superConstructorInvocation_arguments != null)
         _result["superConstructorInvocation_arguments"] =
@@ -12727,6 +14679,45 @@
         _result["superConstructorInvocation_element"] =
             superConstructorInvocation_element;
     }
+    if (kind == idl.LinkedNodeKind.superExpression) {
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.switchCase) {
+      if (switchMember_statements.isNotEmpty)
+        _result["switchMember_statements"] =
+            switchMember_statements.map((_value) => _value.toJson()).toList();
+      if (switchCase_expression != null)
+        _result["switchCase_expression"] = switchCase_expression.toJson();
+      if (switchMember_labels.isNotEmpty)
+        _result["switchMember_labels"] =
+            switchMember_labels.map((_value) => _value.toJson()).toList();
+    }
+    if (kind == idl.LinkedNodeKind.switchDefault) {
+      if (switchMember_statements.isNotEmpty)
+        _result["switchMember_statements"] =
+            switchMember_statements.map((_value) => _value.toJson()).toList();
+      if (switchMember_labels.isNotEmpty)
+        _result["switchMember_labels"] =
+            switchMember_labels.map((_value) => _value.toJson()).toList();
+    }
+    if (kind == idl.LinkedNodeKind.switchStatement) {
+      if (switchStatement_members.isNotEmpty)
+        _result["switchStatement_members"] =
+            switchStatement_members.map((_value) => _value.toJson()).toList();
+      if (switchStatement_expression != null)
+        _result["switchStatement_expression"] =
+            switchStatement_expression.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.symbolLiteral) {
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+      if (names.isNotEmpty) _result["names"] = names;
+    }
+    if (kind == idl.LinkedNodeKind.thisExpression) {
+      if (expression_type != null)
+        _result["expression_type"] = expression_type.toJson();
+    }
     if (kind == idl.LinkedNodeKind.throwExpression) {
       if (throwExpression_expression != null)
         _result["throwExpression_expression"] =
@@ -12734,6 +14725,99 @@
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
+    if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (topLevelVariableDeclaration_variableList != null)
+        _result["topLevelVariableDeclaration_variableList"] =
+            topLevelVariableDeclaration_variableList.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.tryStatement) {
+      if (tryStatement_catchClauses.isNotEmpty)
+        _result["tryStatement_catchClauses"] =
+            tryStatement_catchClauses.map((_value) => _value.toJson()).toList();
+      if (tryStatement_body != null)
+        _result["tryStatement_body"] = tryStatement_body.toJson();
+      if (tryStatement_finallyBlock != null)
+        _result["tryStatement_finallyBlock"] =
+            tryStatement_finallyBlock.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.typeArgumentList) {
+      if (typeArgumentList_arguments.isNotEmpty)
+        _result["typeArgumentList_arguments"] = typeArgumentList_arguments
+            .map((_value) => _value.toJson())
+            .toList();
+    }
+    if (kind == idl.LinkedNodeKind.typeName) {
+      if (typeName_typeArguments.isNotEmpty)
+        _result["typeName_typeArguments"] =
+            typeName_typeArguments.map((_value) => _value.toJson()).toList();
+      if (typeName_name != null)
+        _result["typeName_name"] = typeName_name.toJson();
+      if (typeName_type != null)
+        _result["typeName_type"] = typeName_type.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.typeParameter) {
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (typeParameter_bound != null)
+        _result["typeParameter_bound"] = typeParameter_bound.toJson();
+      if (typeParameter_name != null)
+        _result["typeParameter_name"] = typeParameter_name.toJson();
+      if (typeParameter_defaultType != null)
+        _result["typeParameter_defaultType"] =
+            typeParameter_defaultType.toJson();
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+    }
+    if (kind == idl.LinkedNodeKind.typeParameterList) {
+      if (typeParameterList_typeParameters.isNotEmpty)
+        _result["typeParameterList_typeParameters"] =
+            typeParameterList_typeParameters
+                .map((_value) => _value.toJson())
+                .toList();
+    }
+    if (kind == idl.LinkedNodeKind.variableDeclaration) {
+      if (actualType != null) _result["actualType"] = actualType.toJson();
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (variableDeclaration_initializer != null)
+        _result["variableDeclaration_initializer"] =
+            variableDeclaration_initializer.toJson();
+      if (variableDeclaration_name != null)
+        _result["variableDeclaration_name"] = variableDeclaration_name.toJson();
+      if (inheritsCovariant != false)
+        _result["inheritsCovariant"] = inheritsCovariant;
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (topLevelTypeInferenceError != null)
+        _result["topLevelTypeInferenceError"] =
+            topLevelTypeInferenceError.toJson();
+    }
+    if (kind == idl.LinkedNodeKind.variableDeclarationList) {
+      if (variableDeclarationList_variables.isNotEmpty)
+        _result["variableDeclarationList_variables"] =
+            variableDeclarationList_variables
+                .map((_value) => _value.toJson())
+                .toList();
+      if (annotatedNode_comment != null)
+        _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+      if (annotatedNode_metadata.isNotEmpty)
+        _result["annotatedNode_metadata"] =
+            annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+      if (variableDeclarationList_type != null)
+        _result["variableDeclarationList_type"] =
+            variableDeclarationList_type.toJson();
+    }
     if (kind == idl.LinkedNodeKind.variableDeclarationStatement) {
       if (variableDeclarationStatement_variables != null)
         _result["variableDeclarationStatement_variables"] =
@@ -12745,233 +14829,90 @@
       if (whileStatement_condition != null)
         _result["whileStatement_condition"] = whileStatement_condition.toJson();
     }
+    if (kind == idl.LinkedNodeKind.withClause) {
+      if (withClause_mixinTypes.isNotEmpty)
+        _result["withClause_mixinTypes"] =
+            withClause_mixinTypes.map((_value) => _value.toJson()).toList();
+    }
     if (kind == idl.LinkedNodeKind.yieldStatement) {
       if (yieldStatement_expression != null)
         _result["yieldStatement_expression"] =
             yieldStatement_expression.toJson();
     }
-    if (kind == idl.LinkedNodeKind.simpleIdentifier) {
-      if (simpleIdentifier_elementType != null)
-        _result["simpleIdentifier_elementType"] =
-            simpleIdentifier_elementType.toJson();
-      if (simpleIdentifier_element != 0)
-        _result["simpleIdentifier_element"] = simpleIdentifier_element;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
-      if (emptyFunctionBody_fake != 0)
-        _result["emptyFunctionBody_fake"] = emptyFunctionBody_fake;
-    }
-    if (kind == idl.LinkedNodeKind.emptyStatement) {
-      if (emptyStatement_fake != 0)
-        _result["emptyStatement_fake"] = emptyStatement_fake;
-    }
-    if (kind == idl.LinkedNodeKind.nullLiteral) {
-      if (nullLiteral_fake != 0) _result["nullLiteral_fake"] = nullLiteral_fake;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.booleanLiteral) {
-      if (booleanLiteral_value != false)
-        _result["booleanLiteral_value"] = booleanLiteral_value;
-    }
-    if (kind == idl.LinkedNodeKind.hideCombinator) {
-      if (names.isNotEmpty) _result["names"] = names;
-    }
-    if (kind == idl.LinkedNodeKind.showCombinator) {
-      if (names.isNotEmpty) _result["names"] = names;
-    }
-    if (kind == idl.LinkedNodeKind.symbolLiteral) {
-      if (names.isNotEmpty) _result["names"] = names;
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.doubleLiteral) {
-      if (doubleLiteral_value != 0.0)
-        _result["doubleLiteral_value"] = doubleLiteral_value.isFinite
-            ? doubleLiteral_value
-            : doubleLiteral_value.toString();
-    }
-    if (kind == idl.LinkedNodeKind.rethrowExpression) {
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.superExpression) {
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.thisExpression) {
-      if (expression_type != null)
-        _result["expression_type"] = expression_type.toJson();
-    }
-    if (kind == idl.LinkedNodeKind.integerLiteral) {
-      if (integerLiteral_value != 0)
-        _result["integerLiteral_value"] = integerLiteral_value;
-    }
-    if (kind == idl.LinkedNodeKind.interpolationString) {
-      if (interpolationString_value != '')
-        _result["interpolationString_value"] = interpolationString_value;
-    }
-    if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
-      if (simpleStringLiteral_value != '')
-        _result["simpleStringLiteral_value"] = simpleStringLiteral_value;
-    }
     return _result;
   }
 
   @override
   Map<String, Object> toMap() {
-    if (kind == idl.LinkedNodeKind.functionDeclaration) {
+    if (kind == idl.LinkedNodeKind.adjacentStrings) {
       return {
-        "actualReturnType": actualReturnType,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "functionDeclaration_functionExpression":
-            functionDeclaration_functionExpression,
-        "functionDeclaration_returnType": functionDeclaration_returnType,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
+        "adjacentStrings_strings": adjacentStrings_strings,
         "flags": flags,
-        "nameOffset": nameOffset,
         "kind": kind,
-        "name": name,
       };
     }
-    if (kind == idl.LinkedNodeKind.functionExpression) {
+    if (kind == idl.LinkedNodeKind.annotation) {
       return {
-        "actualReturnType": actualReturnType,
-        "functionExpression_body": functionExpression_body,
-        "functionExpression_formalParameters":
-            functionExpression_formalParameters,
-        "functionExpression_typeParameters": functionExpression_typeParameters,
+        "annotation_arguments": annotation_arguments,
+        "annotation_constructorName": annotation_constructorName,
+        "annotation_element": annotation_element,
+        "annotation_elementType": annotation_elementType,
+        "annotation_name": annotation_name,
         "flags": flags,
         "kind": kind,
-        "name": name,
       };
     }
-    if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+    if (kind == idl.LinkedNodeKind.argumentList) {
       return {
-        "actualReturnType": actualReturnType,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "functionTypeAlias_formalParameters":
-            functionTypeAlias_formalParameters,
-        "functionTypeAlias_returnType": functionTypeAlias_returnType,
-        "functionTypeAlias_typeParameters": functionTypeAlias_typeParameters,
-        "typeAlias_hasSelfReference": typeAlias_hasSelfReference,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
+        "argumentList_arguments": argumentList_arguments,
         "flags": flags,
-        "nameOffset": nameOffset,
         "kind": kind,
-        "name": name,
-        "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
       };
     }
-    if (kind == idl.LinkedNodeKind.genericFunctionType) {
+    if (kind == idl.LinkedNodeKind.asExpression) {
       return {
-        "actualReturnType": actualReturnType,
-        "genericFunctionType_typeParameters":
-            genericFunctionType_typeParameters,
-        "genericFunctionType_returnType": genericFunctionType_returnType,
-        "genericFunctionType_id": genericFunctionType_id,
-        "genericFunctionType_formalParameters":
-            genericFunctionType_formalParameters,
-        "genericFunctionType_type": genericFunctionType_type,
+        "asExpression_expression": asExpression_expression,
+        "asExpression_type": asExpression_type,
+        "expression_type": expression_type,
         "flags": flags,
         "kind": kind,
-        "name": name,
       };
     }
-    if (kind == idl.LinkedNodeKind.methodDeclaration) {
+    if (kind == idl.LinkedNodeKind.assertInitializer) {
       return {
-        "actualReturnType": actualReturnType,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "methodDeclaration_body": methodDeclaration_body,
-        "methodDeclaration_formalParameters":
-            methodDeclaration_formalParameters,
-        "methodDeclaration_returnType": methodDeclaration_returnType,
-        "methodDeclaration_typeParameters": methodDeclaration_typeParameters,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
+        "assertInitializer_condition": assertInitializer_condition,
+        "assertInitializer_message": assertInitializer_message,
         "flags": flags,
-        "nameOffset": nameOffset,
         "kind": kind,
-        "name": name,
       };
     }
-    if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+    if (kind == idl.LinkedNodeKind.assertStatement) {
       return {
-        "actualType": actualType,
-        "normalFormalParameter_metadata": normalFormalParameter_metadata,
-        "fieldFormalParameter_type": fieldFormalParameter_type,
-        "fieldFormalParameter_typeParameters":
-            fieldFormalParameter_typeParameters,
-        "fieldFormalParameter_formalParameters":
-            fieldFormalParameter_formalParameters,
-        "inheritsCovariant": inheritsCovariant,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
+        "assertStatement_condition": assertStatement_condition,
+        "assertStatement_message": assertStatement_message,
         "flags": flags,
-        "nameOffset": nameOffset,
-        "normalFormalParameter_comment": normalFormalParameter_comment,
         "kind": kind,
-        "name": name,
       };
     }
-    if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+    if (kind == idl.LinkedNodeKind.assignmentExpression) {
       return {
-        "actualType": actualType,
-        "normalFormalParameter_metadata": normalFormalParameter_metadata,
-        "functionTypedFormalParameter_formalParameters":
-            functionTypedFormalParameter_formalParameters,
-        "functionTypedFormalParameter_returnType":
-            functionTypedFormalParameter_returnType,
-        "functionTypedFormalParameter_typeParameters":
-            functionTypedFormalParameter_typeParameters,
-        "inheritsCovariant": inheritsCovariant,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
+        "assignmentExpression_leftHandSide": assignmentExpression_leftHandSide,
+        "assignmentExpression_rightHandSide":
+            assignmentExpression_rightHandSide,
+        "assignmentExpression_elementType": assignmentExpression_elementType,
+        "assignmentExpression_element": assignmentExpression_element,
+        "assignmentExpression_operator": assignmentExpression_operator,
+        "expression_type": expression_type,
         "flags": flags,
-        "nameOffset": nameOffset,
-        "normalFormalParameter_comment": normalFormalParameter_comment,
         "kind": kind,
-        "name": name,
       };
     }
-    if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+    if (kind == idl.LinkedNodeKind.awaitExpression) {
       return {
-        "actualType": actualType,
-        "normalFormalParameter_metadata": normalFormalParameter_metadata,
-        "simpleFormalParameter_type": simpleFormalParameter_type,
-        "inheritsCovariant": inheritsCovariant,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
+        "awaitExpression_expression": awaitExpression_expression,
+        "expression_type": expression_type,
         "flags": flags,
-        "nameOffset": nameOffset,
-        "normalFormalParameter_comment": normalFormalParameter_comment,
         "kind": kind,
-        "name": name,
-        "topLevelTypeInferenceError": topLevelTypeInferenceError,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.variableDeclaration) {
-      return {
-        "actualType": actualType,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "variableDeclaration_initializer": variableDeclaration_initializer,
-        "inheritsCovariant": inheritsCovariant,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "flags": flags,
-        "nameOffset": nameOffset,
-        "kind": kind,
-        "name": name,
-        "topLevelTypeInferenceError": topLevelTypeInferenceError,
-        "variableDeclaration_declaration": variableDeclaration_declaration,
       };
     }
     if (kind == idl.LinkedNodeKind.binaryExpression) {
@@ -12985,51 +14926,6 @@
         "expression_type": expression_type,
         "flags": flags,
         "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
-      return {
-        "invocationExpression_invokeType": invocationExpression_invokeType,
-        "functionExpressionInvocation_function":
-            functionExpressionInvocation_function,
-        "invocationExpression_typeArguments":
-            invocationExpression_typeArguments,
-        "expression_type": expression_type,
-        "flags": flags,
-        "invocationExpression_arguments": invocationExpression_arguments,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.methodInvocation) {
-      return {
-        "invocationExpression_invokeType": invocationExpression_invokeType,
-        "methodInvocation_methodName": methodInvocation_methodName,
-        "methodInvocation_target": methodInvocation_target,
-        "invocationExpression_typeArguments":
-            invocationExpression_typeArguments,
-        "expression_type": expression_type,
-        "flags": flags,
-        "invocationExpression_arguments": invocationExpression_arguments,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.adjacentStrings) {
-      return {
-        "adjacentStrings_strings": adjacentStrings_strings,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.argumentList) {
-      return {
-        "argumentList_arguments": argumentList_arguments,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.block) {
@@ -13037,7 +14933,27 @@
         "block_statements": block_statements,
         "flags": flags,
         "kind": kind,
-        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.blockFunctionBody) {
+      return {
+        "blockFunctionBody_block": blockFunctionBody_block,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.booleanLiteral) {
+      return {
+        "booleanLiteral_value": booleanLiteral_value,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.breakStatement) {
+      return {
+        "breakStatement_label": breakStatement_label,
+        "flags": flags,
+        "kind": kind,
       };
     }
     if (kind == idl.LinkedNodeKind.cascadeExpression) {
@@ -13047,250 +14963,16 @@
         "expression_type": expression_type,
         "flags": flags,
         "kind": kind,
-        "name": name,
       };
     }
-    if (kind == idl.LinkedNodeKind.comment) {
+    if (kind == idl.LinkedNodeKind.catchClause) {
       return {
-        "comment_references": comment_references,
-        "comment_tokens": comment_tokens,
-        "comment_type": comment_type,
+        "catchClause_body": catchClause_body,
+        "catchClause_exceptionParameter": catchClause_exceptionParameter,
+        "catchClause_exceptionType": catchClause_exceptionType,
+        "catchClause_stackTraceParameter": catchClause_stackTraceParameter,
         "flags": flags,
         "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.compilationUnit) {
-      return {
-        "compilationUnit_declarations": compilationUnit_declarations,
-        "compilationUnit_scriptTag": compilationUnit_scriptTag,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "compilationUnit_directives": compilationUnit_directives,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.constructorDeclaration) {
-      return {
-        "constructorDeclaration_initializers":
-            constructorDeclaration_initializers,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "constructorDeclaration_body": constructorDeclaration_body,
-        "constructorDeclaration_parameters": constructorDeclaration_parameters,
-        "constructorDeclaration_redirectedConstructor":
-            constructorDeclaration_redirectedConstructor,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "constructorDeclaration_returnType": constructorDeclaration_returnType,
-        "flags": flags,
-        "nameOffset": nameOffset,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.dottedName) {
-      return {
-        "dottedName_components": dottedName_components,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.enumDeclaration) {
-      return {
-        "enumDeclaration_constants": enumDeclaration_constants,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "flags": flags,
-        "nameOffset": nameOffset,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.formalParameterList) {
-      return {
-        "formalParameterList_parameters": formalParameterList_parameters,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.implementsClause) {
-      return {
-        "implementsClause_interfaces": implementsClause_interfaces,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
-      return {
-        "instanceCreationExpression_arguments":
-            instanceCreationExpression_arguments,
-        "instanceCreationExpression_constructorName":
-            instanceCreationExpression_constructorName,
-        "instanceCreationExpression_typeArguments":
-            instanceCreationExpression_typeArguments,
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.labeledStatement) {
-      return {
-        "labeledStatement_labels": labeledStatement_labels,
-        "labeledStatement_statement": labeledStatement_statement,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.libraryIdentifier) {
-      return {
-        "libraryIdentifier_components": libraryIdentifier_components,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.exportDirective) {
-      return {
-        "namespaceDirective_combinators": namespaceDirective_combinators,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "namespaceDirective_configurations": namespaceDirective_configurations,
-        "flags": flags,
-        "nameOffset": nameOffset,
-        "uriBasedDirective_uri": uriBasedDirective_uri,
-        "kind": kind,
-        "name": name,
-        "namespaceDirective_selectedUri": namespaceDirective_selectedUri,
-        "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
-        "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.importDirective) {
-      return {
-        "namespaceDirective_combinators": namespaceDirective_combinators,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "importDirective_prefixOffset": importDirective_prefixOffset,
-        "namespaceDirective_configurations": namespaceDirective_configurations,
-        "flags": flags,
-        "importDirective_prefix": importDirective_prefix,
-        "nameOffset": nameOffset,
-        "uriBasedDirective_uri": uriBasedDirective_uri,
-        "kind": kind,
-        "name": name,
-        "namespaceDirective_selectedUri": namespaceDirective_selectedUri,
-        "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
-        "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.onClause) {
-      return {
-        "onClause_superclassConstraints": onClause_superclassConstraints,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.stringInterpolation) {
-      return {
-        "stringInterpolation_elements": stringInterpolation_elements,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.switchStatement) {
-      return {
-        "switchStatement_members": switchStatement_members,
-        "switchStatement_expression": switchStatement_expression,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.tryStatement) {
-      return {
-        "tryStatement_catchClauses": tryStatement_catchClauses,
-        "tryStatement_body": tryStatement_body,
-        "tryStatement_finallyBlock": tryStatement_finallyBlock,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.typeArgumentList) {
-      return {
-        "typeArgumentList_arguments": typeArgumentList_arguments,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.listLiteral) {
-      return {
-        "typedLiteral_typeArguments": typedLiteral_typeArguments,
-        "listLiteral_elements": listLiteral_elements,
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
-      return {
-        "typedLiteral_typeArguments": typedLiteral_typeArguments,
-        "setOrMapLiteral_elements": setOrMapLiteral_elements,
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.typeName) {
-      return {
-        "typeName_typeArguments": typeName_typeArguments,
-        "typeName_name": typeName_name,
-        "typeName_type": typeName_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.typeParameterList) {
-      return {
-        "typeParameterList_typeParameters": typeParameterList_typeParameters,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.variableDeclarationList) {
-      return {
-        "variableDeclarationList_variables": variableDeclarationList_variables,
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "variableDeclarationList_type": variableDeclarationList_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.withClause) {
-      return {
-        "withClause_mixinTypes": withClause_mixinTypes,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.classDeclaration) {
@@ -13308,10 +14990,9 @@
             classOrMixinDeclaration_typeParameters,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
+        "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
         "flags": flags,
-        "nameOffset": nameOffset,
         "kind": kind,
-        "name": name,
         "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
       };
     }
@@ -13325,13 +15006,107 @@
         "classTypeAlias_implementsClause": classTypeAlias_implementsClause,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
+        "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
         "flags": flags,
-        "nameOffset": nameOffset,
         "kind": kind,
-        "name": name,
         "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
       };
     }
+    if (kind == idl.LinkedNodeKind.comment) {
+      return {
+        "comment_references": comment_references,
+        "comment_tokens": comment_tokens,
+        "comment_type": comment_type,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.commentReference) {
+      return {
+        "commentReference_identifier": commentReference_identifier,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.compilationUnit) {
+      return {
+        "compilationUnit_declarations": compilationUnit_declarations,
+        "compilationUnit_scriptTag": compilationUnit_scriptTag,
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "compilationUnit_directives": compilationUnit_directives,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.conditionalExpression) {
+      return {
+        "conditionalExpression_condition": conditionalExpression_condition,
+        "conditionalExpression_elseExpression":
+            conditionalExpression_elseExpression,
+        "conditionalExpression_thenExpression":
+            conditionalExpression_thenExpression,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.configuration) {
+      return {
+        "configuration_name": configuration_name,
+        "configuration_value": configuration_value,
+        "configuration_uri": configuration_uri,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+      return {
+        "constructorDeclaration_initializers":
+            constructorDeclaration_initializers,
+        "annotatedNode_comment": annotatedNode_comment,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "constructorDeclaration_body": constructorDeclaration_body,
+        "constructorDeclaration_name": constructorDeclaration_name,
+        "constructorDeclaration_parameters": constructorDeclaration_parameters,
+        "constructorDeclaration_redirectedConstructor":
+            constructorDeclaration_redirectedConstructor,
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "constructorDeclaration_periodOffset":
+            constructorDeclaration_periodOffset,
+        "constructorDeclaration_returnType": constructorDeclaration_returnType,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
+      return {
+        "constructorFieldInitializer_expression":
+            constructorFieldInitializer_expression,
+        "constructorFieldInitializer_fieldName":
+            constructorFieldInitializer_fieldName,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.constructorName) {
+      return {
+        "constructorName_name": constructorName_name,
+        "constructorName_type": constructorName_type,
+        "constructorName_elementType": constructorName_elementType,
+        "constructorName_element": constructorName_element,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.continueStatement) {
+      return {
+        "continueStatement_label": continueStatement_label,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
     if (kind == idl.LinkedNodeKind.declaredIdentifier) {
       return {
         "annotatedNode_comment": annotatedNode_comment,
@@ -13340,17 +15115,111 @@
         "declaredIdentifier_type": declaredIdentifier_type,
         "flags": flags,
         "kind": kind,
-        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
+      return {
+        "defaultFormalParameter_defaultValue":
+            defaultFormalParameter_defaultValue,
+        "defaultFormalParameter_parameter": defaultFormalParameter_parameter,
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "defaultFormalParameter_kind": defaultFormalParameter_kind,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.doStatement) {
+      return {
+        "doStatement_body": doStatement_body,
+        "doStatement_condition": doStatement_condition,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.dottedName) {
+      return {
+        "dottedName_components": dottedName_components,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.doubleLiteral) {
+      return {
+        "doubleLiteral_value": doubleLiteral_value,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
+      return {
+        "emptyFunctionBody_fake": emptyFunctionBody_fake,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.emptyStatement) {
+      return {
+        "emptyStatement_fake": emptyStatement_fake,
+        "flags": flags,
+        "kind": kind,
       };
     }
     if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
       return {
         "annotatedNode_comment": annotatedNode_comment,
         "annotatedNode_metadata": annotatedNode_metadata,
+        "enumConstantDeclaration_name": enumConstantDeclaration_name,
         "flags": flags,
-        "nameOffset": nameOffset,
         "kind": kind,
-        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.enumDeclaration) {
+      return {
+        "enumDeclaration_constants": enumDeclaration_constants,
+        "annotatedNode_comment": annotatedNode_comment,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.exportDirective) {
+      return {
+        "namespaceDirective_combinators": namespaceDirective_combinators,
+        "annotatedNode_comment": annotatedNode_comment,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "directive_keywordOffset": directive_keywordOffset,
+        "namespaceDirective_configurations": namespaceDirective_configurations,
+        "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
+        "flags": flags,
+        "uriBasedDirective_uri": uriBasedDirective_uri,
+        "kind": kind,
+        "namespaceDirective_selectedUri": namespaceDirective_selectedUri,
+        "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
+      return {
+        "expressionFunctionBody_expression": expressionFunctionBody_expression,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.expressionStatement) {
+      return {
+        "expressionStatement_expression": expressionStatement_expression,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.extendsClause) {
+      return {
+        "extendsClause_superclass": extendsClause_superclass,
+        "flags": flags,
+        "kind": kind,
       };
     }
     if (kind == idl.LinkedNodeKind.fieldDeclaration) {
@@ -13360,7 +15229,183 @@
         "fieldDeclaration_fields": fieldDeclaration_fields,
         "flags": flags,
         "kind": kind,
-        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+      return {
+        "actualType": actualType,
+        "normalFormalParameter_metadata": normalFormalParameter_metadata,
+        "fieldFormalParameter_type": fieldFormalParameter_type,
+        "fieldFormalParameter_typeParameters":
+            fieldFormalParameter_typeParameters,
+        "fieldFormalParameter_formalParameters":
+            fieldFormalParameter_formalParameters,
+        "inheritsCovariant": inheritsCovariant,
+        "normalFormalParameter_identifier": normalFormalParameter_identifier,
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "flags": flags,
+        "normalFormalParameter_comment": normalFormalParameter_comment,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
+      return {
+        "forEachParts_iterable": forEachParts_iterable,
+        "forEachPartsWithDeclaration_loopVariable":
+            forEachPartsWithDeclaration_loopVariable,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.forEachPartsWithIdentifier) {
+      return {
+        "forEachParts_iterable": forEachParts_iterable,
+        "forEachPartsWithIdentifier_identifier":
+            forEachPartsWithIdentifier_identifier,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.forElement) {
+      return {
+        "forMixin_forLoopParts": forMixin_forLoopParts,
+        "forElement_body": forElement_body,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
+      return {
+        "forParts_condition": forParts_condition,
+        "forPartsWithDeclarations_variables":
+            forPartsWithDeclarations_variables,
+        "forParts_updaters": forParts_updaters,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.forPartsWithExpression) {
+      return {
+        "forParts_condition": forParts_condition,
+        "forPartsWithExpression_initialization":
+            forPartsWithExpression_initialization,
+        "forParts_updaters": forParts_updaters,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.forStatement) {
+      return {
+        "forMixin_forLoopParts": forMixin_forLoopParts,
+        "forStatement_body": forStatement_body,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.formalParameterList) {
+      return {
+        "formalParameterList_parameters": formalParameterList_parameters,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.functionDeclaration) {
+      return {
+        "actualReturnType": actualReturnType,
+        "annotatedNode_comment": annotatedNode_comment,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "functionDeclaration_functionExpression":
+            functionDeclaration_functionExpression,
+        "functionDeclaration_returnType": functionDeclaration_returnType,
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
+      return {
+        "functionDeclarationStatement_functionDeclaration":
+            functionDeclarationStatement_functionDeclaration,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.functionExpression) {
+      return {
+        "actualReturnType": actualReturnType,
+        "functionExpression_body": functionExpression_body,
+        "functionExpression_formalParameters":
+            functionExpression_formalParameters,
+        "functionExpression_typeParameters": functionExpression_typeParameters,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
+      return {
+        "invocationExpression_invokeType": invocationExpression_invokeType,
+        "functionExpressionInvocation_function":
+            functionExpressionInvocation_function,
+        "invocationExpression_typeArguments":
+            invocationExpression_typeArguments,
+        "expression_type": expression_type,
+        "flags": flags,
+        "invocationExpression_arguments": invocationExpression_arguments,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+      return {
+        "actualReturnType": actualReturnType,
+        "annotatedNode_comment": annotatedNode_comment,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "functionTypeAlias_formalParameters":
+            functionTypeAlias_formalParameters,
+        "functionTypeAlias_returnType": functionTypeAlias_returnType,
+        "functionTypeAlias_typeParameters": functionTypeAlias_typeParameters,
+        "typeAlias_hasSelfReference": typeAlias_hasSelfReference,
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
+        "flags": flags,
+        "kind": kind,
+        "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+      return {
+        "actualType": actualType,
+        "normalFormalParameter_metadata": normalFormalParameter_metadata,
+        "functionTypedFormalParameter_formalParameters":
+            functionTypedFormalParameter_formalParameters,
+        "functionTypedFormalParameter_returnType":
+            functionTypedFormalParameter_returnType,
+        "functionTypedFormalParameter_typeParameters":
+            functionTypedFormalParameter_typeParameters,
+        "inheritsCovariant": inheritsCovariant,
+        "normalFormalParameter_identifier": normalFormalParameter_identifier,
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "flags": flags,
+        "normalFormalParameter_comment": normalFormalParameter_comment,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.genericFunctionType) {
+      return {
+        "actualReturnType": actualReturnType,
+        "genericFunctionType_typeParameters":
+            genericFunctionType_typeParameters,
+        "genericFunctionType_returnType": genericFunctionType_returnType,
+        "genericFunctionType_id": genericFunctionType_id,
+        "genericFunctionType_formalParameters":
+            genericFunctionType_formalParameters,
+        "genericFunctionType_type": genericFunctionType_type,
+        "flags": flags,
+        "kind": kind,
       };
     }
     if (kind == idl.LinkedNodeKind.genericTypeAlias) {
@@ -13372,21 +15417,192 @@
         "typeAlias_hasSelfReference": typeAlias_hasSelfReference,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
+        "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
         "flags": flags,
-        "nameOffset": nameOffset,
         "kind": kind,
-        "name": name,
         "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
       };
     }
+    if (kind == idl.LinkedNodeKind.hideCombinator) {
+      return {
+        "flags": flags,
+        "kind": kind,
+        "names": names,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.ifElement) {
+      return {
+        "ifMixin_condition": ifMixin_condition,
+        "ifElement_thenElement": ifElement_thenElement,
+        "ifElement_elseElement": ifElement_elseElement,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.ifStatement) {
+      return {
+        "ifMixin_condition": ifMixin_condition,
+        "ifStatement_elseStatement": ifStatement_elseStatement,
+        "ifStatement_thenStatement": ifStatement_thenStatement,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.implementsClause) {
+      return {
+        "implementsClause_interfaces": implementsClause_interfaces,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.importDirective) {
+      return {
+        "namespaceDirective_combinators": namespaceDirective_combinators,
+        "annotatedNode_comment": annotatedNode_comment,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "directive_keywordOffset": directive_keywordOffset,
+        "importDirective_prefixOffset": importDirective_prefixOffset,
+        "namespaceDirective_configurations": namespaceDirective_configurations,
+        "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
+        "flags": flags,
+        "importDirective_prefix": importDirective_prefix,
+        "uriBasedDirective_uri": uriBasedDirective_uri,
+        "kind": kind,
+        "namespaceDirective_selectedUri": namespaceDirective_selectedUri,
+        "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.indexExpression) {
+      return {
+        "indexExpression_index": indexExpression_index,
+        "indexExpression_target": indexExpression_target,
+        "indexExpression_elementType": indexExpression_elementType,
+        "indexExpression_element": indexExpression_element,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
+      return {
+        "instanceCreationExpression_arguments":
+            instanceCreationExpression_arguments,
+        "instanceCreationExpression_constructorName":
+            instanceCreationExpression_constructorName,
+        "instanceCreationExpression_typeArguments":
+            instanceCreationExpression_typeArguments,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.integerLiteral) {
+      return {
+        "flags": flags,
+        "integerLiteral_value": integerLiteral_value,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.interpolationExpression) {
+      return {
+        "interpolationExpression_expression":
+            interpolationExpression_expression,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.interpolationString) {
+      return {
+        "flags": flags,
+        "interpolationString_value": interpolationString_value,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.isExpression) {
+      return {
+        "isExpression_expression": isExpression_expression,
+        "isExpression_type": isExpression_type,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.label) {
+      return {
+        "label_label": label_label,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.labeledStatement) {
+      return {
+        "labeledStatement_labels": labeledStatement_labels,
+        "labeledStatement_statement": labeledStatement_statement,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
     if (kind == idl.LinkedNodeKind.libraryDirective) {
       return {
         "annotatedNode_comment": annotatedNode_comment,
         "annotatedNode_metadata": annotatedNode_metadata,
         "libraryDirective_name": libraryDirective_name,
+        "directive_keywordOffset": directive_keywordOffset,
         "flags": flags,
         "kind": kind,
-        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.libraryIdentifier) {
+      return {
+        "libraryIdentifier_components": libraryIdentifier_components,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.listLiteral) {
+      return {
+        "typedLiteral_typeArguments": typedLiteral_typeArguments,
+        "listLiteral_elements": listLiteral_elements,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
+      return {
+        "mapLiteralEntry_key": mapLiteralEntry_key,
+        "mapLiteralEntry_value": mapLiteralEntry_value,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.methodDeclaration) {
+      return {
+        "actualReturnType": actualReturnType,
+        "annotatedNode_comment": annotatedNode_comment,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "methodDeclaration_body": methodDeclaration_body,
+        "methodDeclaration_formalParameters":
+            methodDeclaration_formalParameters,
+        "methodDeclaration_returnType": methodDeclaration_returnType,
+        "methodDeclaration_typeParameters": methodDeclaration_typeParameters,
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "methodDeclaration_name": methodDeclaration_name,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.methodInvocation) {
+      return {
+        "invocationExpression_invokeType": invocationExpression_invokeType,
+        "methodInvocation_methodName": methodInvocation_methodName,
+        "methodInvocation_target": methodInvocation_target,
+        "invocationExpression_typeArguments":
+            invocationExpression_typeArguments,
+        "expression_type": expression_type,
+        "flags": flags,
+        "invocationExpression_arguments": invocationExpression_arguments,
+        "kind": kind,
       };
     }
     if (kind == idl.LinkedNodeKind.mixinDeclaration) {
@@ -13401,423 +15617,20 @@
             classOrMixinDeclaration_typeParameters,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
+        "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
+        "flags": flags,
+        "kind": kind,
         "mixinDeclaration_superInvokedNames":
             mixinDeclaration_superInvokedNames,
-        "flags": flags,
-        "nameOffset": nameOffset,
-        "kind": kind,
-        "name": name,
         "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
       };
     }
-    if (kind == idl.LinkedNodeKind.partDirective) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "flags": flags,
-        "nameOffset": nameOffset,
-        "uriBasedDirective_uri": uriBasedDirective_uri,
-        "kind": kind,
-        "name": name,
-        "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
-        "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.partOfDirective) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "partOfDirective_libraryName": partOfDirective_libraryName,
-        "partOfDirective_uri": partOfDirective_uri,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "topLevelVariableDeclaration_variableList":
-            topLevelVariableDeclaration_variableList,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.typeParameter) {
-      return {
-        "annotatedNode_comment": annotatedNode_comment,
-        "annotatedNode_metadata": annotatedNode_metadata,
-        "typeParameter_bound": typeParameter_bound,
-        "typeParameter_defaultType": typeParameter_defaultType,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "flags": flags,
-        "nameOffset": nameOffset,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.switchCase) {
-      return {
-        "switchMember_statements": switchMember_statements,
-        "switchCase_expression": switchCase_expression,
-        "switchMember_labels": switchMember_labels,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.switchDefault) {
-      return {
-        "switchMember_statements": switchMember_statements,
-        "switchMember_labels": switchMember_labels,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.annotation) {
-      return {
-        "annotation_arguments": annotation_arguments,
-        "annotation_constructorName": annotation_constructorName,
-        "annotation_element": annotation_element,
-        "annotation_elementType": annotation_elementType,
-        "annotation_name": annotation_name,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.asExpression) {
-      return {
-        "asExpression_expression": asExpression_expression,
-        "asExpression_type": asExpression_type,
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.assertInitializer) {
-      return {
-        "assertInitializer_condition": assertInitializer_condition,
-        "assertInitializer_message": assertInitializer_message,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.assertStatement) {
-      return {
-        "assertStatement_condition": assertStatement_condition,
-        "assertStatement_message": assertStatement_message,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.assignmentExpression) {
-      return {
-        "assignmentExpression_leftHandSide": assignmentExpression_leftHandSide,
-        "assignmentExpression_rightHandSide":
-            assignmentExpression_rightHandSide,
-        "assignmentExpression_elementType": assignmentExpression_elementType,
-        "assignmentExpression_element": assignmentExpression_element,
-        "assignmentExpression_operator": assignmentExpression_operator,
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.awaitExpression) {
-      return {
-        "awaitExpression_expression": awaitExpression_expression,
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.blockFunctionBody) {
-      return {
-        "blockFunctionBody_block": blockFunctionBody_block,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.breakStatement) {
-      return {
-        "breakStatement_label": breakStatement_label,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.catchClause) {
-      return {
-        "catchClause_body": catchClause_body,
-        "catchClause_exceptionParameter": catchClause_exceptionParameter,
-        "catchClause_exceptionType": catchClause_exceptionType,
-        "catchClause_stackTraceParameter": catchClause_stackTraceParameter,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.commentReference) {
-      return {
-        "commentReference_identifier": commentReference_identifier,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.conditionalExpression) {
-      return {
-        "conditionalExpression_condition": conditionalExpression_condition,
-        "conditionalExpression_elseExpression":
-            conditionalExpression_elseExpression,
-        "conditionalExpression_thenExpression":
-            conditionalExpression_thenExpression,
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.configuration) {
-      return {
-        "configuration_name": configuration_name,
-        "configuration_value": configuration_value,
-        "configuration_uri": configuration_uri,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
-      return {
-        "constructorFieldInitializer_expression":
-            constructorFieldInitializer_expression,
-        "constructorFieldInitializer_fieldName":
-            constructorFieldInitializer_fieldName,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.constructorName) {
-      return {
-        "constructorName_name": constructorName_name,
-        "constructorName_type": constructorName_type,
-        "constructorName_elementType": constructorName_elementType,
-        "constructorName_element": constructorName_element,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.continueStatement) {
-      return {
-        "continueStatement_label": continueStatement_label,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
-      return {
-        "defaultFormalParameter_defaultValue":
-            defaultFormalParameter_defaultValue,
-        "defaultFormalParameter_parameter": defaultFormalParameter_parameter,
-        "codeLength": codeLength,
-        "codeOffset": codeOffset,
-        "defaultFormalParameter_kind": defaultFormalParameter_kind,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.doStatement) {
-      return {
-        "doStatement_body": doStatement_body,
-        "doStatement_condition": doStatement_condition,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
-      return {
-        "expressionFunctionBody_expression": expressionFunctionBody_expression,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.expressionStatement) {
-      return {
-        "expressionStatement_expression": expressionStatement_expression,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.extendsClause) {
-      return {
-        "extendsClause_superclass": extendsClause_superclass,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
-      return {
-        "forEachParts_iterable": forEachParts_iterable,
-        "forEachPartsWithDeclaration_loopVariable":
-            forEachPartsWithDeclaration_loopVariable,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.forEachPartsWithIdentifier) {
-      return {
-        "forEachParts_iterable": forEachParts_iterable,
-        "forEachPartsWithIdentifier_identifier":
-            forEachPartsWithIdentifier_identifier,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.forElement) {
-      return {
-        "forMixin_forLoopParts": forMixin_forLoopParts,
-        "forElement_body": forElement_body,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.forStatement) {
-      return {
-        "forMixin_forLoopParts": forMixin_forLoopParts,
-        "forStatement_body": forStatement_body,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
-      return {
-        "forParts_condition": forParts_condition,
-        "forPartsWithDeclarations_variables":
-            forPartsWithDeclarations_variables,
-        "forParts_updaters": forParts_updaters,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.forPartsWithExpression) {
-      return {
-        "forParts_condition": forParts_condition,
-        "forPartsWithExpression_initialization":
-            forPartsWithExpression_initialization,
-        "forParts_updaters": forParts_updaters,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
-      return {
-        "functionDeclarationStatement_functionDeclaration":
-            functionDeclarationStatement_functionDeclaration,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.ifElement) {
-      return {
-        "ifMixin_condition": ifMixin_condition,
-        "ifElement_thenElement": ifElement_thenElement,
-        "ifElement_elseElement": ifElement_elseElement,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.ifStatement) {
-      return {
-        "ifMixin_condition": ifMixin_condition,
-        "ifStatement_elseStatement": ifStatement_elseStatement,
-        "ifStatement_thenStatement": ifStatement_thenStatement,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.indexExpression) {
-      return {
-        "indexExpression_index": indexExpression_index,
-        "indexExpression_target": indexExpression_target,
-        "indexExpression_elementType": indexExpression_elementType,
-        "indexExpression_element": indexExpression_element,
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.interpolationExpression) {
-      return {
-        "interpolationExpression_expression":
-            interpolationExpression_expression,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.isExpression) {
-      return {
-        "isExpression_expression": isExpression_expression,
-        "isExpression_type": isExpression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.label) {
-      return {
-        "label_label": label_label,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
-      return {
-        "mapLiteralEntry_key": mapLiteralEntry_key,
-        "mapLiteralEntry_value": mapLiteralEntry_value,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
     if (kind == idl.LinkedNodeKind.namedExpression) {
       return {
         "namedExpression_expression": namedExpression_expression,
         "namedExpression_name": namedExpression_name,
         "flags": flags,
         "kind": kind,
-        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.nativeClause) {
@@ -13825,7 +15638,6 @@
         "nativeClause_name": nativeClause_name,
         "flags": flags,
         "kind": kind,
-        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.nativeFunctionBody) {
@@ -13833,7 +15645,21 @@
         "nativeFunctionBody_stringLiteral": nativeFunctionBody_stringLiteral,
         "flags": flags,
         "kind": kind,
-        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.nullLiteral) {
+      return {
+        "nullLiteral_fake": nullLiteral_fake,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.onClause) {
+      return {
+        "onClause_superclassConstraints": onClause_superclassConstraints,
+        "flags": flags,
+        "kind": kind,
       };
     }
     if (kind == idl.LinkedNodeKind.parenthesizedExpression) {
@@ -13843,7 +15669,29 @@
         "expression_type": expression_type,
         "flags": flags,
         "kind": kind,
-        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.partDirective) {
+      return {
+        "annotatedNode_comment": annotatedNode_comment,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "directive_keywordOffset": directive_keywordOffset,
+        "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
+        "flags": flags,
+        "uriBasedDirective_uri": uriBasedDirective_uri,
+        "kind": kind,
+        "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.partOfDirective) {
+      return {
+        "annotatedNode_comment": annotatedNode_comment,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "partOfDirective_libraryName": partOfDirective_libraryName,
+        "partOfDirective_uri": partOfDirective_uri,
+        "directive_keywordOffset": directive_keywordOffset,
+        "flags": flags,
+        "kind": kind,
       };
     }
     if (kind == idl.LinkedNodeKind.postfixExpression) {
@@ -13855,17 +15703,6 @@
         "expression_type": expression_type,
         "flags": flags,
         "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
-      return {
-        "prefixedIdentifier_identifier": prefixedIdentifier_identifier,
-        "prefixedIdentifier_prefix": prefixedIdentifier_prefix,
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.prefixExpression) {
@@ -13877,7 +15714,15 @@
         "expression_type": expression_type,
         "flags": flags,
         "kind": kind,
-        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
+      return {
+        "prefixedIdentifier_identifier": prefixedIdentifier_identifier,
+        "prefixedIdentifier_prefix": prefixedIdentifier_prefix,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
       };
     }
     if (kind == idl.LinkedNodeKind.propertyAccess) {
@@ -13888,7 +15733,6 @@
         "expression_type": expression_type,
         "flags": flags,
         "kind": kind,
-        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.redirectingConstructorInvocation) {
@@ -13903,7 +15747,13 @@
             redirectingConstructorInvocation_element,
         "flags": flags,
         "kind": kind,
-        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.rethrowExpression) {
+      return {
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
       };
     }
     if (kind == idl.LinkedNodeKind.returnStatement) {
@@ -13911,7 +15761,55 @@
         "returnStatement_expression": returnStatement_expression,
         "flags": flags,
         "kind": kind,
-        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
+      return {
+        "typedLiteral_typeArguments": typedLiteral_typeArguments,
+        "setOrMapLiteral_elements": setOrMapLiteral_elements,
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.showCombinator) {
+      return {
+        "flags": flags,
+        "kind": kind,
+        "names": names,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+      return {
+        "actualType": actualType,
+        "normalFormalParameter_metadata": normalFormalParameter_metadata,
+        "simpleFormalParameter_type": simpleFormalParameter_type,
+        "inheritsCovariant": inheritsCovariant,
+        "normalFormalParameter_identifier": normalFormalParameter_identifier,
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "flags": flags,
+        "normalFormalParameter_comment": normalFormalParameter_comment,
+        "kind": kind,
+        "topLevelTypeInferenceError": topLevelTypeInferenceError,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.simpleIdentifier) {
+      return {
+        "simpleIdentifier_elementType": simpleIdentifier_elementType,
+        "simpleIdentifier_element": simpleIdentifier_element,
+        "expression_type": expression_type,
+        "flags": flags,
+        "simpleIdentifier_offset": simpleIdentifier_offset,
+        "kind": kind,
+        "simpleIdentifier_name": simpleIdentifier_name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
+      return {
+        "flags": flags,
+        "kind": kind,
+        "simpleStringLiteral_value": simpleStringLiteral_value,
       };
     }
     if (kind == idl.LinkedNodeKind.spreadElement) {
@@ -13919,10 +15817,16 @@
         "spreadElement_expression": spreadElement_expression,
         "flags": flags,
         "kind": kind,
-        "name": name,
         "spreadElement_spreadOperator": spreadElement_spreadOperator,
       };
     }
+    if (kind == idl.LinkedNodeKind.stringInterpolation) {
+      return {
+        "stringInterpolation_elements": stringInterpolation_elements,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
     if (kind == idl.LinkedNodeKind.superConstructorInvocation) {
       return {
         "superConstructorInvocation_arguments":
@@ -13935,7 +15839,53 @@
             superConstructorInvocation_element,
         "flags": flags,
         "kind": kind,
-        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.superExpression) {
+      return {
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.switchCase) {
+      return {
+        "switchMember_statements": switchMember_statements,
+        "switchCase_expression": switchCase_expression,
+        "switchMember_labels": switchMember_labels,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.switchDefault) {
+      return {
+        "switchMember_statements": switchMember_statements,
+        "switchMember_labels": switchMember_labels,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.switchStatement) {
+      return {
+        "switchStatement_members": switchStatement_members,
+        "switchStatement_expression": switchStatement_expression,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.symbolLiteral) {
+      return {
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
+        "names": names,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.thisExpression) {
+      return {
+        "expression_type": expression_type,
+        "flags": flags,
+        "kind": kind,
       };
     }
     if (kind == idl.LinkedNodeKind.throwExpression) {
@@ -13944,7 +15894,86 @@
         "expression_type": expression_type,
         "flags": flags,
         "kind": kind,
-        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+      return {
+        "annotatedNode_comment": annotatedNode_comment,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "topLevelVariableDeclaration_variableList":
+            topLevelVariableDeclaration_variableList,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.tryStatement) {
+      return {
+        "tryStatement_catchClauses": tryStatement_catchClauses,
+        "tryStatement_body": tryStatement_body,
+        "tryStatement_finallyBlock": tryStatement_finallyBlock,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.typeArgumentList) {
+      return {
+        "typeArgumentList_arguments": typeArgumentList_arguments,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.typeName) {
+      return {
+        "typeName_typeArguments": typeName_typeArguments,
+        "typeName_name": typeName_name,
+        "typeName_type": typeName_type,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.typeParameter) {
+      return {
+        "annotatedNode_comment": annotatedNode_comment,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "typeParameter_bound": typeParameter_bound,
+        "typeParameter_name": typeParameter_name,
+        "typeParameter_defaultType": typeParameter_defaultType,
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.typeParameterList) {
+      return {
+        "typeParameterList_typeParameters": typeParameterList_typeParameters,
+        "flags": flags,
+        "kind": kind,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.variableDeclaration) {
+      return {
+        "actualType": actualType,
+        "annotatedNode_comment": annotatedNode_comment,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "variableDeclaration_initializer": variableDeclaration_initializer,
+        "variableDeclaration_name": variableDeclaration_name,
+        "inheritsCovariant": inheritsCovariant,
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
+        "flags": flags,
+        "kind": kind,
+        "topLevelTypeInferenceError": topLevelTypeInferenceError,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.variableDeclarationList) {
+      return {
+        "variableDeclarationList_variables": variableDeclarationList_variables,
+        "annotatedNode_comment": annotatedNode_comment,
+        "annotatedNode_metadata": annotatedNode_metadata,
+        "variableDeclarationList_type": variableDeclarationList_type,
+        "flags": flags,
+        "kind": kind,
       };
     }
     if (kind == idl.LinkedNodeKind.variableDeclarationStatement) {
@@ -13953,7 +15982,6 @@
             variableDeclarationStatement_variables,
         "flags": flags,
         "kind": kind,
-        "name": name,
       };
     }
     if (kind == idl.LinkedNodeKind.whileStatement) {
@@ -13962,7 +15990,13 @@
         "whileStatement_condition": whileStatement_condition,
         "flags": flags,
         "kind": kind,
-        "name": name,
+      };
+    }
+    if (kind == idl.LinkedNodeKind.withClause) {
+      return {
+        "withClause_mixinTypes": withClause_mixinTypes,
+        "flags": flags,
+        "kind": kind,
       };
     }
     if (kind == idl.LinkedNodeKind.yieldStatement) {
@@ -13970,131 +16004,6 @@
         "yieldStatement_expression": yieldStatement_expression,
         "flags": flags,
         "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.simpleIdentifier) {
-      return {
-        "simpleIdentifier_elementType": simpleIdentifier_elementType,
-        "simpleIdentifier_element": simpleIdentifier_element,
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
-      return {
-        "emptyFunctionBody_fake": emptyFunctionBody_fake,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.emptyStatement) {
-      return {
-        "emptyStatement_fake": emptyStatement_fake,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.nullLiteral) {
-      return {
-        "nullLiteral_fake": nullLiteral_fake,
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.booleanLiteral) {
-      return {
-        "booleanLiteral_value": booleanLiteral_value,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.hideCombinator) {
-      return {
-        "names": names,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.showCombinator) {
-      return {
-        "names": names,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.symbolLiteral) {
-      return {
-        "names": names,
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.doubleLiteral) {
-      return {
-        "doubleLiteral_value": doubleLiteral_value,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.rethrowExpression) {
-      return {
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.superExpression) {
-      return {
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.thisExpression) {
-      return {
-        "expression_type": expression_type,
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.integerLiteral) {
-      return {
-        "flags": flags,
-        "integerLiteral_value": integerLiteral_value,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.interpolationString) {
-      return {
-        "flags": flags,
-        "interpolationString_value": interpolationString_value,
-        "kind": kind,
-        "name": name,
-      };
-    }
-    if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
-      return {
-        "flags": flags,
-        "kind": kind,
-        "name": name,
-        "simpleStringLiteral_value": simpleStringLiteral_value,
       };
     }
     throw StateError("Unexpected $kind");
@@ -15258,12 +17167,12 @@
     with _LinkedNodeUnitMixin
     implements idl.LinkedNodeUnit {
   List<LinkedNodeBuilder> _genericFunctionTypes;
+  bool _isNNBD;
   bool _isSynthetic;
   List<int> _lineStarts;
   LinkedNodeBuilder _node;
   UnlinkedTokensBuilder _tokens;
   String _uriStr;
-  bool _isNNBD;
 
   @override
   List<LinkedNodeBuilder> get genericFunctionTypes =>
@@ -15280,6 +17189,13 @@
   }
 
   @override
+  bool get isNNBD => _isNNBD ??= false;
+
+  set isNNBD(bool value) {
+    this._isNNBD = value;
+  }
+
+  @override
   bool get isSynthetic => _isSynthetic ??= false;
 
   set isSynthetic(bool value) {
@@ -15316,28 +17232,21 @@
     this._uriStr = value;
   }
 
-  @override
-  bool get isNNBD => _isNNBD ??= false;
-
-  set isNNBD(bool value) {
-    this._isNNBD = value;
-  }
-
   LinkedNodeUnitBuilder(
       {List<LinkedNodeBuilder> genericFunctionTypes,
+      bool isNNBD,
       bool isSynthetic,
       List<int> lineStarts,
       LinkedNodeBuilder node,
       UnlinkedTokensBuilder tokens,
-      String uriStr,
-      bool isNNBD})
+      String uriStr})
       : _genericFunctionTypes = genericFunctionTypes,
+        _isNNBD = isNNBD,
         _isSynthetic = isSynthetic,
         _lineStarts = lineStarts,
         _node = node,
         _tokens = tokens,
-        _uriStr = uriStr,
-        _isNNBD = isNNBD;
+        _uriStr = uriStr;
 
   /// Flush [informative] data recursively.
   void flushInformative() {
@@ -15392,6 +17301,9 @@
     if (offset_genericFunctionTypes != null) {
       fbBuilder.addOffset(5, offset_genericFunctionTypes);
     }
+    if (_isNNBD == true) {
+      fbBuilder.addBool(6, true);
+    }
     if (_isSynthetic == true) {
       fbBuilder.addBool(3, true);
     }
@@ -15407,9 +17319,6 @@
     if (offset_uriStr != null) {
       fbBuilder.addOffset(0, offset_uriStr);
     }
-    if (_isNNBD == true) {
-      fbBuilder.addBool(6, true);
-    }
     return fbBuilder.endTable();
   }
 }
@@ -15431,12 +17340,12 @@
   _LinkedNodeUnitImpl(this._bc, this._bcOffset);
 
   List<idl.LinkedNode> _genericFunctionTypes;
+  bool _isNNBD;
   bool _isSynthetic;
   List<int> _lineStarts;
   idl.LinkedNode _node;
   idl.UnlinkedTokens _tokens;
   String _uriStr;
-  bool _isNNBD;
 
   @override
   List<idl.LinkedNode> get genericFunctionTypes {
@@ -15447,6 +17356,12 @@
   }
 
   @override
+  bool get isNNBD {
+    _isNNBD ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 6, false);
+    return _isNNBD;
+  }
+
+  @override
   bool get isSynthetic {
     _isSynthetic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
     return _isSynthetic;
@@ -15477,12 +17392,6 @@
     _uriStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
     return _uriStr;
   }
-
-  @override
-  bool get isNNBD {
-    _isNNBD ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 6, false);
-    return _isNNBD;
-  }
 }
 
 abstract class _LinkedNodeUnitMixin implements idl.LinkedNodeUnit {
@@ -15492,201 +17401,24 @@
     if (genericFunctionTypes.isNotEmpty)
       _result["genericFunctionTypes"] =
           genericFunctionTypes.map((_value) => _value.toJson()).toList();
+    if (isNNBD != false) _result["isNNBD"] = isNNBD;
     if (isSynthetic != false) _result["isSynthetic"] = isSynthetic;
     if (lineStarts.isNotEmpty) _result["lineStarts"] = lineStarts;
     if (node != null) _result["node"] = node.toJson();
     if (tokens != null) _result["tokens"] = tokens.toJson();
     if (uriStr != '') _result["uriStr"] = uriStr;
-    if (isNNBD != false) _result["isNNBD"] = isNNBD;
     return _result;
   }
 
   @override
   Map<String, Object> toMap() => {
         "genericFunctionTypes": genericFunctionTypes,
+        "isNNBD": isNNBD,
         "isSynthetic": isSynthetic,
         "lineStarts": lineStarts,
         "node": node,
         "tokens": tokens,
         "uriStr": uriStr,
-        "isNNBD": isNNBD,
-      };
-
-  @override
-  String toString() => convert.json.encode(toJson());
-}
-
-class LinkedNodeVariablesDeclarationBuilder extends Object
-    with _LinkedNodeVariablesDeclarationMixin
-    implements idl.LinkedNodeVariablesDeclaration {
-  LinkedNodeBuilder _comment;
-  bool _isConst;
-  bool _isCovariant;
-  bool _isFinal;
-  bool _isStatic;
-
-  @override
-  LinkedNodeBuilder get comment => _comment;
-
-  set comment(LinkedNodeBuilder value) {
-    this._comment = value;
-  }
-
-  @override
-  bool get isConst => _isConst ??= false;
-
-  set isConst(bool value) {
-    this._isConst = value;
-  }
-
-  @override
-  bool get isCovariant => _isCovariant ??= false;
-
-  set isCovariant(bool value) {
-    this._isCovariant = value;
-  }
-
-  @override
-  bool get isFinal => _isFinal ??= false;
-
-  set isFinal(bool value) {
-    this._isFinal = value;
-  }
-
-  @override
-  bool get isStatic => _isStatic ??= false;
-
-  set isStatic(bool value) {
-    this._isStatic = value;
-  }
-
-  LinkedNodeVariablesDeclarationBuilder(
-      {LinkedNodeBuilder comment,
-      bool isConst,
-      bool isCovariant,
-      bool isFinal,
-      bool isStatic})
-      : _comment = comment,
-        _isConst = isConst,
-        _isCovariant = isCovariant,
-        _isFinal = isFinal,
-        _isStatic = isStatic;
-
-  /// Flush [informative] data recursively.
-  void flushInformative() {
-    _comment?.flushInformative();
-  }
-
-  /// Accumulate non-[informative] data into [signature].
-  void collectApiSignature(api_sig.ApiSignature signature) {
-    signature.addBool(this._comment != null);
-    this._comment?.collectApiSignature(signature);
-    signature.addBool(this._isConst == true);
-    signature.addBool(this._isCovariant == true);
-    signature.addBool(this._isFinal == true);
-    signature.addBool(this._isStatic == true);
-  }
-
-  fb.Offset finish(fb.Builder fbBuilder) {
-    fb.Offset offset_comment;
-    if (_comment != null) {
-      offset_comment = _comment.finish(fbBuilder);
-    }
-    fbBuilder.startTable();
-    if (offset_comment != null) {
-      fbBuilder.addOffset(0, offset_comment);
-    }
-    if (_isConst == true) {
-      fbBuilder.addBool(1, true);
-    }
-    if (_isCovariant == true) {
-      fbBuilder.addBool(2, true);
-    }
-    if (_isFinal == true) {
-      fbBuilder.addBool(3, true);
-    }
-    if (_isStatic == true) {
-      fbBuilder.addBool(4, true);
-    }
-    return fbBuilder.endTable();
-  }
-}
-
-class _LinkedNodeVariablesDeclarationReader
-    extends fb.TableReader<_LinkedNodeVariablesDeclarationImpl> {
-  const _LinkedNodeVariablesDeclarationReader();
-
-  @override
-  _LinkedNodeVariablesDeclarationImpl createObject(
-          fb.BufferContext bc, int offset) =>
-      new _LinkedNodeVariablesDeclarationImpl(bc, offset);
-}
-
-class _LinkedNodeVariablesDeclarationImpl extends Object
-    with _LinkedNodeVariablesDeclarationMixin
-    implements idl.LinkedNodeVariablesDeclaration {
-  final fb.BufferContext _bc;
-  final int _bcOffset;
-
-  _LinkedNodeVariablesDeclarationImpl(this._bc, this._bcOffset);
-
-  idl.LinkedNode _comment;
-  bool _isConst;
-  bool _isCovariant;
-  bool _isFinal;
-  bool _isStatic;
-
-  @override
-  idl.LinkedNode get comment {
-    _comment ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 0, null);
-    return _comment;
-  }
-
-  @override
-  bool get isConst {
-    _isConst ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 1, false);
-    return _isConst;
-  }
-
-  @override
-  bool get isCovariant {
-    _isCovariant ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 2, false);
-    return _isCovariant;
-  }
-
-  @override
-  bool get isFinal {
-    _isFinal ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
-    return _isFinal;
-  }
-
-  @override
-  bool get isStatic {
-    _isStatic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 4, false);
-    return _isStatic;
-  }
-}
-
-abstract class _LinkedNodeVariablesDeclarationMixin
-    implements idl.LinkedNodeVariablesDeclaration {
-  @override
-  Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
-    if (comment != null) _result["comment"] = comment.toJson();
-    if (isConst != false) _result["isConst"] = isConst;
-    if (isCovariant != false) _result["isCovariant"] = isCovariant;
-    if (isFinal != false) _result["isFinal"] = isFinal;
-    if (isStatic != false) _result["isStatic"] = isStatic;
-    return _result;
-  }
-
-  @override
-  Map<String, Object> toMap() => {
-        "comment": comment,
-        "isConst": isConst,
-        "isCovariant": isCovariant,
-        "isFinal": isFinal,
-        "isStatic": isStatic,
       };
 
   @override
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 6d9af7a..1230c79 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -1914,16 +1914,18 @@
 
   variantField_13:LinkedNode (id: 13);
 
-  variantField_34:uint (id: 34);
-
   variantField_33:uint (id: 33);
 
-  variantField_36:[string] (id: 36);
+  variantField_32:uint (id: 32);
+
+  variantField_35:[string] (id: 35);
 
   variantField_29:LinkedNodeCommentType (id: 29);
 
   variantField_3:[LinkedNode] (id: 3);
 
+  variantField_19:uint (id: 19);
+
   variantField_10:LinkedNode (id: 10);
 
   variantField_26:LinkedNodeFormalParameterKind (id: 26);
@@ -1944,21 +1946,17 @@
 
   kind:LinkedNodeKind (id: 0);
 
-  name:string (id: 37);
+  variantField_36:[string] (id: 36);
 
   variantField_20:string (id: 20);
 
   variantField_31:bool (id: 31);
 
-  variantField_38:UnlinkedTokenType (id: 38);
+  variantField_37:UnlinkedTokenType (id: 37);
 
-  variantField_35:TopLevelInferenceError (id: 35);
+  variantField_34:TopLevelInferenceError (id: 34);
 
   variantField_22:string (id: 22);
-
-  variantField_19:uint (id: 19);
-
-  variantField_32:LinkedNodeVariablesDeclaration (id: 32);
 }
 
 /// Information about a group of libraries linked together, for example because
@@ -2044,6 +2042,8 @@
   /// AST in declaration resolver.
   genericFunctionTypes:[LinkedNode] (id: 5);
 
+  isNNBD:bool (id: 6);
+
   isSynthetic:bool (id: 3);
 
   /// Offsets of the first character of each line in the source code.
@@ -2054,22 +2054,6 @@
   tokens:UnlinkedTokens (id: 1);
 
   uriStr:string (id: 0);
-
-  isNNBD:bool (id: 6);
-}
-
-/// Information about a top-level declaration, or a field declaration that
-/// contributes information to [LinkedNodeKind.variableDeclaration].
-table LinkedNodeVariablesDeclaration {
-  comment:LinkedNode (id: 0);
-
-  isConst:bool (id: 1);
-
-  isCovariant:bool (id: 2);
-
-  isFinal:bool (id: 3);
-
-  isStatic:bool (id: 4);
 }
 
 /// Information about the resolution of an [UnlinkedReference].
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 3e2a821..3a60a94 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -845,6 +845,7 @@
     LinkedNodeKind.variableDeclaration,
     LinkedNodeKind.variableDeclarationList,
   ])
+  @informative
   LinkedNode get annotatedNode_comment;
 
   @VariantId(4, variantList: [
@@ -1016,26 +1017,6 @@
   @VariantId(8, variant: LinkedNodeKind.classTypeAlias)
   LinkedNode get classTypeAlias_withClause;
 
-  @VariantId(34, variantList: [
-    LinkedNodeKind.classDeclaration,
-    LinkedNodeKind.classTypeAlias,
-    LinkedNodeKind.compilationUnit,
-    LinkedNodeKind.constructorDeclaration,
-    LinkedNodeKind.defaultFormalParameter,
-    LinkedNodeKind.enumDeclaration,
-    LinkedNodeKind.fieldFormalParameter,
-    LinkedNodeKind.functionDeclaration,
-    LinkedNodeKind.functionTypeAlias,
-    LinkedNodeKind.functionTypedFormalParameter,
-    LinkedNodeKind.genericTypeAlias,
-    LinkedNodeKind.methodDeclaration,
-    LinkedNodeKind.mixinDeclaration,
-    LinkedNodeKind.simpleFormalParameter,
-    LinkedNodeKind.typeParameter,
-    LinkedNodeKind.variableDeclaration,
-  ])
-  int get codeLength;
-
   @VariantId(33, variantList: [
     LinkedNodeKind.classDeclaration,
     LinkedNodeKind.classTypeAlias,
@@ -1054,12 +1035,34 @@
     LinkedNodeKind.typeParameter,
     LinkedNodeKind.variableDeclaration,
   ])
+  @informative
+  int get codeLength;
+
+  @VariantId(32, variantList: [
+    LinkedNodeKind.classDeclaration,
+    LinkedNodeKind.classTypeAlias,
+    LinkedNodeKind.compilationUnit,
+    LinkedNodeKind.constructorDeclaration,
+    LinkedNodeKind.defaultFormalParameter,
+    LinkedNodeKind.enumDeclaration,
+    LinkedNodeKind.fieldFormalParameter,
+    LinkedNodeKind.functionDeclaration,
+    LinkedNodeKind.functionTypeAlias,
+    LinkedNodeKind.functionTypedFormalParameter,
+    LinkedNodeKind.genericTypeAlias,
+    LinkedNodeKind.methodDeclaration,
+    LinkedNodeKind.mixinDeclaration,
+    LinkedNodeKind.simpleFormalParameter,
+    LinkedNodeKind.typeParameter,
+    LinkedNodeKind.variableDeclaration,
+  ])
+  @informative
   int get codeOffset;
 
   @VariantId(2, variant: LinkedNodeKind.comment)
   List<LinkedNode> get comment_references;
 
-  @VariantId(36, variant: LinkedNodeKind.comment)
+  @VariantId(35, variant: LinkedNodeKind.comment)
   List<String> get comment_tokens;
 
   @VariantId(29, variant: LinkedNodeKind.comment)
@@ -1101,9 +1104,16 @@
   @VariantId(2, variant: LinkedNodeKind.constructorDeclaration)
   List<LinkedNode> get constructorDeclaration_initializers;
 
+  @VariantId(7, variant: LinkedNodeKind.constructorDeclaration)
+  LinkedNode get constructorDeclaration_name;
+
   @VariantId(8, variant: LinkedNodeKind.constructorDeclaration)
   LinkedNode get constructorDeclaration_parameters;
 
+  @VariantId(19, variant: LinkedNodeKind.constructorDeclaration)
+  @informative
+  int get constructorDeclaration_periodOffset;
+
   @VariantId(9, variant: LinkedNodeKind.constructorDeclaration)
   LinkedNode get constructorDeclaration_redirectedConstructor;
 
@@ -1146,6 +1156,16 @@
   @VariantId(7, variant: LinkedNodeKind.defaultFormalParameter)
   LinkedNode get defaultFormalParameter_parameter;
 
+  @VariantId(17, variantList: [
+    LinkedNodeKind.exportDirective,
+    LinkedNodeKind.importDirective,
+    LinkedNodeKind.libraryDirective,
+    LinkedNodeKind.partDirective,
+    LinkedNodeKind.partOfDirective,
+  ])
+  @informative
+  int get directive_keywordOffset;
+
   @VariantId(6, variant: LinkedNodeKind.doStatement)
   LinkedNode get doStatement_body;
 
@@ -1164,6 +1184,9 @@
   @VariantId(15, variant: LinkedNodeKind.emptyStatement)
   int get emptyStatement_fake;
 
+  @VariantId(6, variant: LinkedNodeKind.enumConstantDeclaration)
+  LinkedNode get enumConstantDeclaration_name;
+
   @VariantId(2, variant: LinkedNodeKind.enumDeclaration)
   List<LinkedNode> get enumDeclaration_constants;
 
@@ -1446,6 +1469,9 @@
   @VariantId(7, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_formalParameters;
 
+  @VariantId(10, variant: LinkedNodeKind.methodDeclaration)
+  LinkedNode get methodDeclaration_name;
+
   @VariantId(8, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_returnType;
 
@@ -1464,8 +1490,16 @@
   @VariantId(36, variant: LinkedNodeKind.mixinDeclaration)
   List<String> get mixinDeclaration_superInvokedNames;
 
-  @Id(37)
-  String get name;
+  @VariantId(10, variantList: [
+    LinkedNodeKind.classDeclaration,
+    LinkedNodeKind.classTypeAlias,
+    LinkedNodeKind.enumDeclaration,
+    LinkedNodeKind.functionDeclaration,
+    LinkedNodeKind.functionTypeAlias,
+    LinkedNodeKind.genericTypeAlias,
+    LinkedNodeKind.mixinDeclaration,
+  ])
+  LinkedNode get namedCompilationUnitMember_name;
 
   @VariantId(6, variant: LinkedNodeKind.namedExpression)
   LinkedNode get namedExpression_expression;
@@ -1473,28 +1507,6 @@
   @VariantId(7, variant: LinkedNodeKind.namedExpression)
   LinkedNode get namedExpression_name;
 
-  @VariantId(16, variantList: [
-    LinkedNodeKind.classDeclaration,
-    LinkedNodeKind.classTypeAlias,
-    LinkedNodeKind.constructorDeclaration,
-    LinkedNodeKind.enumConstantDeclaration,
-    LinkedNodeKind.enumDeclaration,
-    LinkedNodeKind.exportDirective,
-    LinkedNodeKind.fieldFormalParameter,
-    LinkedNodeKind.functionDeclaration,
-    LinkedNodeKind.functionTypedFormalParameter,
-    LinkedNodeKind.functionTypeAlias,
-    LinkedNodeKind.genericTypeAlias,
-    LinkedNodeKind.importDirective,
-    LinkedNodeKind.methodDeclaration,
-    LinkedNodeKind.mixinDeclaration,
-    LinkedNodeKind.partDirective,
-    LinkedNodeKind.simpleFormalParameter,
-    LinkedNodeKind.typeParameter,
-    LinkedNodeKind.variableDeclaration,
-  ])
-  int get nameOffset;
-
   @VariantId(36, variantList: [
     LinkedNodeKind.hideCombinator,
     LinkedNodeKind.showCombinator,
@@ -1531,8 +1543,16 @@
     LinkedNodeKind.functionTypedFormalParameter,
     LinkedNodeKind.simpleFormalParameter,
   ])
+  @informative
   LinkedNode get normalFormalParameter_comment;
 
+  @VariantId(9, variantList: [
+    LinkedNodeKind.fieldFormalParameter,
+    LinkedNodeKind.functionTypedFormalParameter,
+    LinkedNodeKind.simpleFormalParameter,
+  ])
+  LinkedNode get normalFormalParameter_identifier;
+
   @VariantId(4, variantList: [
     LinkedNodeKind.fieldFormalParameter,
     LinkedNodeKind.functionTypedFormalParameter,
@@ -1621,6 +1641,13 @@
   @VariantId(23, variant: LinkedNodeKind.simpleIdentifier)
   LinkedNodeType get simpleIdentifier_elementType;
 
+  @VariantId(20, variant: LinkedNodeKind.simpleIdentifier)
+  String get simpleIdentifier_name;
+
+  @VariantId(16, variant: LinkedNodeKind.simpleIdentifier)
+  @informative
+  int get simpleIdentifier_offset;
+
   @VariantId(20, variant: LinkedNodeKind.simpleStringLiteral)
   String get simpleStringLiteral_value;
 
@@ -1636,7 +1663,7 @@
   @VariantId(6, variant: LinkedNodeKind.spreadElement)
   LinkedNode get spreadElement_expression;
 
-  @VariantId(38, variant: LinkedNodeKind.spreadElement)
+  @VariantId(37, variant: LinkedNodeKind.spreadElement)
   UnlinkedTokenType get spreadElement_spreadOperator;
 
   @VariantId(2, variant: LinkedNodeKind.stringInterpolation)
@@ -1678,7 +1705,7 @@
   @VariantId(6, variant: LinkedNodeKind.throwExpression)
   LinkedNode get throwExpression_expression;
 
-  @VariantId(35, variantList: [
+  @VariantId(34, variantList: [
     LinkedNodeKind.simpleFormalParameter,
     LinkedNodeKind.variableDeclaration,
   ])
@@ -1726,6 +1753,9 @@
   @VariantId(23, variant: LinkedNodeKind.typeParameter)
   LinkedNodeType get typeParameter_defaultType;
 
+  @VariantId(7, variant: LinkedNodeKind.typeParameter)
+  LinkedNode get typeParameter_name;
+
   @VariantId(2, variant: LinkedNodeKind.typeParameterList)
   List<LinkedNode> get typeParameterList_typeParameters;
 
@@ -1750,12 +1780,12 @@
   ])
   int get uriBasedDirective_uriElement;
 
-  @VariantId(32, variant: LinkedNodeKind.variableDeclaration)
-  LinkedNodeVariablesDeclaration get variableDeclaration_declaration;
-
   @VariantId(6, variant: LinkedNodeKind.variableDeclaration)
   LinkedNode get variableDeclaration_initializer;
 
+  @VariantId(7, variant: LinkedNodeKind.variableDeclaration)
+  LinkedNode get variableDeclaration_name;
+
   @VariantId(6, variant: LinkedNodeKind.variableDeclarationList)
   LinkedNode get variableDeclarationList_type;
 
@@ -2035,6 +2065,9 @@
   @Id(5)
   List<LinkedNode> get genericFunctionTypes;
 
+  @Id(6)
+  bool get isNNBD;
+
   @Id(3)
   bool get isSynthetic;
 
@@ -2051,28 +2084,6 @@
 
   @Id(0)
   String get uriStr;
-
-  @Id(6)
-  bool get isNNBD;
-}
-
-/// Information about a top-level declaration, or a field declaration that
-/// contributes information to [LinkedNodeKind.variableDeclaration].
-abstract class LinkedNodeVariablesDeclaration extends base.SummaryClass {
-  @Id(0)
-  LinkedNode get comment;
-
-  @Id(1)
-  bool get isConst;
-
-  @Id(2)
-  bool get isCovariant;
-
-  @Id(3)
-  bool get isFinal;
-
-  @Id(4)
-  bool get isStatic;
 }
 
 /// Information about the resolution of an [UnlinkedReference].
diff --git a/pkg/analyzer/lib/src/summary/summary_file_builder.dart b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
index 7bbab6b..cf9c22f 100644
--- a/pkg/analyzer/lib/src/summary/summary_file_builder.dart
+++ b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
@@ -11,7 +11,6 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
@@ -148,15 +147,10 @@
   }
 
   void _link2() {
-    var rootReference = summary2.Reference.root();
-    var dartCoreRef = rootReference.getChild('dart:core');
-    dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
-    dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
-
     var elementFactory = summary2.LinkedElementFactory(
       context,
       null,
-      rootReference,
+      summary2.Reference.root(),
     );
 
     var linkResult = summary2.link(elementFactory, inputLibraries);
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 9de3d22..21464da 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -33,6 +33,13 @@
   /// Set to `true` when this reader is used to lazily read its unit.
   bool isLazy = false;
 
+  /// Whether we are reading a directive.
+  ///
+  /// [StringLiteral]s in directives are not actual expressions, and don't need
+  /// a type. Moreover, when we are reading `dart:core` imports, the type
+  /// provider is not ready yet, so we cannot access type `String`.
+  bool _isReadingDirective = false;
+
   AstBinaryReader(this._unitContext);
 
   InterfaceType get _boolType => _unitContext.typeProvider.boolType;
@@ -82,7 +89,7 @@
         typeParameters[i] = astFactory.typeParameter(
           _readNode(data.annotatedNode_comment),
           _readNodeList(data.annotatedNode_metadata),
-          _declaredIdentifier(data),
+          _readNode(data.typeParameter_name),
           data.typeParameter_bound != null ? _Tokens.EXTENDS : null,
           null,
         );
@@ -119,13 +126,6 @@
     return _readType(data);
   }
 
-  SimpleIdentifier _declaredIdentifier(LinkedNode data) {
-    return astFactory.simpleIdentifier(
-      TokenFactory.tokenFromString(data.name)..offset = data.nameOffset,
-      isDeclaration: true,
-    );
-  }
-
   Element _elementOfComponents(
     int rawElementIndex,
     LinkedNodeType definingTypeNode,
@@ -151,9 +151,13 @@
   }
 
   AdjacentStrings _read_adjacentStrings(LinkedNode data) {
-    return astFactory.adjacentStrings(
+    var node = astFactory.adjacentStrings(
       _readNodeList(data.adjacentStrings_strings),
-    )..staticType = _stringType;
+    );
+    if (!_isReadingDirective) {
+      node.staticType = _stringType;
+    }
+    return node;
   }
 
   Annotation _read_annotation(LinkedNode data) {
@@ -312,7 +316,7 @@
         _readNodeListLazy(data.annotatedNode_metadata),
         AstBinaryFlags.isAbstract(data.flags) ? _Tokens.ABSTRACT : null,
         _Tokens.CLASS,
-        _declaredIdentifier(data),
+        _readNode(data.namedCompilationUnitMember_name),
         _readNode(data.classOrMixinDeclaration_typeParameters),
         _readNodeLazy(data.classDeclaration_extendsClause),
         _readNodeLazy(data.classDeclaration_withClause),
@@ -336,7 +340,7 @@
         _readNodeLazy(data.annotatedNode_comment),
         _readNodeListLazy(data.annotatedNode_metadata),
         _Tokens.CLASS,
-        _declaredIdentifier(data),
+        _readNode(data.namedCompilationUnitMember_name),
         _readNode(data.classTypeAlias_typeParameters),
         _Tokens.EQ,
         AstBinaryFlags.isAbstract(data.flags) ? _Tokens.ABSTRACT : null,
@@ -415,6 +419,7 @@
   }
 
   ConstructorDeclaration _read_constructorDeclaration(LinkedNode data) {
+    var name = _readNode(data.constructorDeclaration_name);
     var node = astFactory.constructorDeclaration(
       _readNodeLazy(data.annotatedNode_comment),
       _readNodeListLazy(data.annotatedNode_metadata),
@@ -422,8 +427,10 @@
       AstBinaryFlags.isConst(data.flags) ? _Tokens.CONST : null,
       AstBinaryFlags.isFactory(data.flags) ? _Tokens.FACTORY : null,
       _readNode(data.constructorDeclaration_returnType),
-      data.name.isNotEmpty ? _Tokens.PERIOD : null,
-      _declaredIdentifier(data),
+      name != null
+          ? Token(TokenType.PERIOD, data.constructorDeclaration_periodOffset)
+          : null,
+      name,
       _readNodeLazy(data.constructorDeclaration_parameters),
       _Tokens.choose(
         AstBinaryFlags.hasSeparatorColon(data.flags),
@@ -537,7 +544,7 @@
     var node = astFactory.enumConstantDeclaration(
       _readNodeLazy(data.annotatedNode_comment),
       _readNodeListLazy(data.annotatedNode_metadata),
-      _declaredIdentifier(data),
+      _readNode(data.enumConstantDeclaration_name),
     );
     LazyEnumConstantDeclaration.setData(node, data);
     return node;
@@ -548,7 +555,7 @@
       _readNodeLazy(data.annotatedNode_comment),
       _readNodeListLazy(data.annotatedNode_metadata),
       _Tokens.ENUM,
-      _declaredIdentifier(data),
+      _readNode(data.namedCompilationUnitMember_name),
       _Tokens.OPEN_CURLY_BRACKET,
       _readNodeListLazy(data.enumDeclaration_constants),
       _Tokens.CLOSE_CURLY_BRACKET,
@@ -559,6 +566,7 @@
 
   ExportDirective _read_exportDirective(LinkedNode data) {
     timerAstBinaryReaderDirective.start();
+    _isReadingDirective = true;
     try {
       var node = astFactory.exportDirective(
         _readNode(data.annotatedNode_comment),
@@ -572,6 +580,7 @@
       LazyDirective.setData(node, data);
       return node;
     } finally {
+      _isReadingDirective = false;
       timerAstBinaryReaderDirective.stop();
     }
   }
@@ -626,7 +635,7 @@
 
   FieldFormalParameter _read_fieldFormalParameter(LinkedNode data) {
     var node = astFactory.fieldFormalParameter2(
-      identifier: _declaredIdentifier(data),
+      identifier: _readNode(data.normalFormalParameter_identifier),
       period: _Tokens.PERIOD,
       thisKeyword: _Tokens.THIS,
       covariantKeyword:
@@ -744,7 +753,7 @@
           AstBinaryFlags.isSet(data.flags),
           _Tokens.SET,
         ),
-        _declaredIdentifier(data),
+        _readNode(data.namedCompilationUnitMember_name),
         _readNodeLazy(data.functionDeclaration_functionExpression),
       );
       LazyFunctionDeclaration.setData(node, data);
@@ -786,7 +795,7 @@
       _readNodeListLazy(data.annotatedNode_metadata),
       _Tokens.TYPEDEF,
       _readNodeLazy(data.functionTypeAlias_returnType),
-      _declaredIdentifier(data),
+      _readNode(data.namedCompilationUnitMember_name),
       _readNode(data.functionTypeAlias_typeParameters),
       _readNodeLazy(data.functionTypeAlias_formalParameters),
       _Tokens.SEMICOLON,
@@ -805,7 +814,7 @@
       comment: _readNodeLazy(data.normalFormalParameter_comment),
       covariantKeyword:
           AstBinaryFlags.isCovariant(data.flags) ? _Tokens.COVARIANT : null,
-      identifier: _declaredIdentifier(data),
+      identifier: _readNode(data.normalFormalParameter_identifier),
       metadata: _readNodeListLazy(data.normalFormalParameter_metadata),
       parameters: _readNodeLazy(
         data.functionTypedFormalParameter_formalParameters,
@@ -831,7 +840,7 @@
       _readNodeLazy(data.annotatedNode_comment),
       _readNodeListLazy(data.annotatedNode_metadata),
       _Tokens.TYPEDEF,
-      _declaredIdentifier(data),
+      _readNode(data.namedCompilationUnitMember_name),
       _readNode(data.genericTypeAlias_typeParameters),
       _Tokens.EQ,
       _readNodeLazy(data.genericTypeAlias_functionType),
@@ -887,6 +896,7 @@
 
   ImportDirective _read_importDirective(LinkedNode data) {
     timerAstBinaryReaderDirective.start();
+    _isReadingDirective = true;
     try {
       SimpleIdentifier prefix;
       if (data.importDirective_prefix.isNotEmpty) {
@@ -911,6 +921,7 @@
       LazyDirective.setData(node, data);
       return node;
     } finally {
+      _isReadingDirective = false;
       timerAstBinaryReaderDirective.stop();
     }
   }
@@ -1003,6 +1014,7 @@
 
   LibraryDirective _read_libraryDirective(LinkedNode data) {
     timerAstBinaryReaderDirective.start();
+    _isReadingDirective = true;
     try {
       var node = astFactory.libraryDirective(
         _readNode(data.annotatedNode_comment),
@@ -1014,6 +1026,7 @@
       LazyDirective.setData(node, data);
       return node;
     } finally {
+      _isReadingDirective = false;
       timerAstBinaryReaderDirective.stop();
     }
   }
@@ -1062,7 +1075,7 @@
         _Tokens.SET,
       ),
       AstBinaryFlags.isOperator(data.flags) ? _Tokens.OPERATOR : null,
-      _declaredIdentifier(data),
+      _readNode(data.methodDeclaration_name),
       _readNode(data.methodDeclaration_typeParameters),
       _readNodeLazy(data.methodDeclaration_formalParameters),
       AstBinaryFlags.isAbstract(data.flags)
@@ -1095,7 +1108,7 @@
         _readNodeLazy(data.annotatedNode_comment),
         _readNodeListLazy(data.annotatedNode_metadata),
         _Tokens.MIXIN,
-        _declaredIdentifier(data),
+        _readNode(data.namedCompilationUnitMember_name),
         _readNode(data.classOrMixinDeclaration_typeParameters),
         _readNodeLazy(data.mixinDeclaration_onClause),
         _readNodeLazy(data.classOrMixinDeclaration_implementsClause),
@@ -1156,6 +1169,7 @@
 
   PartDirective _read_partDirective(LinkedNode data) {
     timerAstBinaryReaderDirective.start();
+    _isReadingDirective = true;
     try {
       var node = astFactory.partDirective(
         _readNode(data.annotatedNode_comment),
@@ -1167,12 +1181,14 @@
       LazyDirective.setData(node, data);
       return node;
     } finally {
+      _isReadingDirective = false;
       timerAstBinaryReaderDirective.stop();
     }
   }
 
   PartOfDirective _read_partOfDirective(LinkedNode data) {
     timerAstBinaryReaderDirective.start();
+    _isReadingDirective = true;
     try {
       var node = astFactory.partOfDirective(
         _readNode(data.annotatedNode_comment),
@@ -1186,6 +1202,7 @@
       LazyDirective.setData(node, data);
       return node;
     } finally {
+      _isReadingDirective = false;
       timerAstBinaryReaderDirective.stop();
     }
   }
@@ -1289,7 +1306,7 @@
 
   SimpleFormalParameter _read_simpleFormalParameter(LinkedNode data) {
     SimpleFormalParameterImpl node = astFactory.simpleFormalParameter2(
-      identifier: _declaredIdentifier(data),
+      identifier: _readNode(data.normalFormalParameter_identifier),
       type: _readNode(data.simpleFormalParameter_type),
       covariantKeyword:
           AstBinaryFlags.isCovariant(data.flags) ? _Tokens.COVARIANT : null,
@@ -1313,7 +1330,8 @@
 
   SimpleIdentifier _read_simpleIdentifier(LinkedNode data) {
     return astFactory.simpleIdentifier(
-      TokenFactory.tokenFromString(data.name),
+      TokenFactory.tokenFromString(data.simpleIdentifier_name)
+        ..offset = data.simpleIdentifier_offset,
       isDeclaration: AstBinaryFlags.isDeclaration(data.flags),
     )
       ..staticElement = _elementOfComponents(
@@ -1324,10 +1342,11 @@
   }
 
   SimpleStringLiteral _read_simpleStringLiteral(LinkedNode data) {
-    // TODO(scheglov) restore staticType
-    return AstTestFactory.string2(data.simpleStringLiteral_value)
-//      ..staticType = _stringType
-        ;
+    var node = AstTestFactory.string2(data.simpleStringLiteral_value);
+    if (!_isReadingDirective) {
+      node.staticType = _stringType;
+    }
+    return node;
   }
 
   SpreadElement _read_spreadElement(LinkedNode data) {
@@ -1466,7 +1485,7 @@
     var node = astFactory.typeParameter(
       _readNodeLazy(data.annotatedNode_comment),
       _readNodeListLazy(data.annotatedNode_metadata),
-      _declaredIdentifier(data),
+      _readNode(data.typeParameter_name),
       _Tokens.EXTENDS,
       _readNodeLazy(data.typeParameter_bound),
     );
@@ -1484,7 +1503,7 @@
 
   VariableDeclaration _read_variableDeclaration(LinkedNode data) {
     var node = astFactory.variableDeclaration(
-      _declaredIdentifier(data),
+      _readNode(data.variableDeclaration_name),
       _Tokens.EQ,
       _readNodeLazy(data.variableDeclaration_initializer),
     );
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index ce98e5d..1b7c7d6 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -31,11 +31,6 @@
   /// The list stored [GenericFunctionType]s, as visited in depth-first order.
   final List<LinkedNodeBuilder> genericFunctionTypes = [];
 
-  /// This field is set temporary while visiting [FieldDeclaration] or
-  /// [TopLevelVariableDeclaration] to store data shared among all variables
-  /// in these declarations.
-  LinkedNodeVariablesDeclarationBuilder _variablesDeclaration;
-
   /// Is `true` if the current [ClassDeclaration] has a const constructor,
   /// so initializers of final fields should be written.
   bool _hasConstConstructor = false;
@@ -315,6 +310,7 @@
   LinkedNodeBuilder visitConstructorDeclaration(ConstructorDeclaration node) {
     var builder = LinkedNodeBuilder.constructorDeclaration(
       constructorDeclaration_initializers: _writeNodeList(node.initializers),
+      constructorDeclaration_name: node.name?.accept(this),
       constructorDeclaration_parameters: node.parameters.accept(this),
       constructorDeclaration_redirectedConstructor:
           node.redirectedConstructor?.accept(this),
@@ -329,11 +325,7 @@
       isFactory: node.factoryKeyword != null,
     );
     if (node.name != null) {
-      builder
-        ..name = node.name.name
-        ..nameOffset = node.name.offset;
-    } else {
-      builder..nameOffset = node.returnType.offset;
+      builder..constructorDeclaration_periodOffset = node.period.offset;
     }
     _storeClassMember(builder, node);
     _storeCodeOffsetLength(builder, node);
@@ -440,9 +432,8 @@
   @override
   LinkedNodeBuilder visitEnumConstantDeclaration(EnumConstantDeclaration node) {
     var builder = LinkedNodeBuilder.enumConstantDeclaration(
-      nameOffset: node.name.offset,
+      enumConstantDeclaration_name: node.name.accept(this),
     );
-    builder..name = node.name.name;
     _storeDeclaration(builder, node);
     return builder;
   }
@@ -501,11 +492,6 @@
 
   @override
   LinkedNodeBuilder visitFieldDeclaration(FieldDeclaration node) {
-    _variablesDeclaration = LinkedNodeVariablesDeclarationBuilder(
-      isCovariant: node.covariantKeyword != null,
-      isStatic: node.isStatic,
-    );
-
     var builder = LinkedNodeBuilder.fieldDeclaration(
       fieldDeclaration_fields: node.fields.accept(this),
     );
@@ -515,9 +501,6 @@
     );
     _storeClassMember(builder, node);
 
-    _variablesDeclaration.comment = builder.annotatedNode_comment;
-    _variablesDeclaration = null;
-
     return builder;
   }
 
@@ -636,9 +619,9 @@
       bodyToStore = null;
     }
     var builder = LinkedNodeBuilder.functionExpression(
-      functionExpression_body: bodyToStore?.accept(this),
-      functionExpression_formalParameters: node.parameters?.accept(this),
       functionExpression_typeParameters: node.typeParameters?.accept(this),
+      functionExpression_formalParameters: node.parameters?.accept(this),
+      functionExpression_body: bodyToStore?.accept(this),
     );
     builder.flags = AstBinaryFlags.encode(
       isAsync: node.body?.isAsynchronous ?? false,
@@ -699,10 +682,10 @@
     genericFunctionTypes.add(null);
 
     var builder = LinkedNodeBuilder.genericFunctionType(
-      genericFunctionType_formalParameters: node.parameters.accept(this),
       genericFunctionType_returnType: node.returnType?.accept(this),
-      genericFunctionType_type: _writeType(node.type),
       genericFunctionType_typeParameters: node.typeParameters?.accept(this),
+      genericFunctionType_formalParameters: node.parameters.accept(this),
+      genericFunctionType_type: _writeType(node.type),
     );
     builder.flags = AstBinaryFlags.encode(
       hasQuestion: node.question != null,
@@ -917,13 +900,11 @@
   @override
   LinkedNodeBuilder visitMethodDeclaration(MethodDeclaration node) {
     var builder = LinkedNodeBuilder.methodDeclaration(
-      methodDeclaration_formalParameters: node.parameters?.accept(this),
       methodDeclaration_returnType: node.returnType?.accept(this),
       methodDeclaration_typeParameters: node.typeParameters?.accept(this),
+      methodDeclaration_formalParameters: node.parameters?.accept(this),
+      methodDeclaration_name: node.name.accept(this),
     );
-    builder
-      ..name = node.name.name
-      ..nameOffset = node.name.offset;
     builder.flags = AstBinaryFlags.encode(
       isAbstract: node.body is EmptyFunctionBody,
       isAsync: node.body?.isAsynchronous ?? false,
@@ -1171,12 +1152,13 @@
     var builder = LinkedNodeBuilder.simpleIdentifier(
       simpleIdentifier_element: elementComponents.rawElement,
       simpleIdentifier_elementType: elementComponents.definingType,
+      simpleIdentifier_name: node.name,
+      simpleIdentifier_offset: node.offset,
       expression_type: _writeType(node.staticType),
     );
     builder.flags = AstBinaryFlags.encode(
       isDeclaration: node is DeclaredSimpleIdentifier,
     );
-    builder.name = node.name;
     return builder;
   }
 
@@ -1280,16 +1262,11 @@
       TopLevelVariableDeclaration node) {
     timerAstBinaryWriterTopVar.start();
     try {
-      _variablesDeclaration = LinkedNodeVariablesDeclarationBuilder();
-
       var builder = LinkedNodeBuilder.topLevelVariableDeclaration(
         topLevelVariableDeclaration_variableList: node.variables?.accept(this),
       );
       _storeCompilationUnitMember(builder, node);
 
-      _variablesDeclaration.comment = builder.annotatedNode_comment;
-      _variablesDeclaration = null;
-
       return builder;
     } finally {
       timerAstBinaryWriterTopVar.stop();
@@ -1331,10 +1308,8 @@
     var builder = LinkedNodeBuilder.typeParameter(
       typeParameter_bound: node.bound?.accept(this),
       typeParameter_defaultType: _writeType(LazyAst.getDefaultType(node)),
+      typeParameter_name: node.name.accept(this),
     );
-    builder
-      ..name = node.name.name
-      ..nameOffset = node.name.offset;
     _storeDeclaration(builder, node);
     _storeCodeOffsetLength(builder, node);
     return builder;
@@ -1366,15 +1341,12 @@
     }
 
     var builder = LinkedNodeBuilder.variableDeclaration(
+      variableDeclaration_name: node.name.accept(this),
       variableDeclaration_initializer: initializer?.accept(this),
-      variableDeclaration_declaration: _variablesDeclaration,
     );
     builder.flags = AstBinaryFlags.encode(
       hasInitializer: node.initializer != null,
     );
-    builder
-      ..name = node.name.name
-      ..nameOffset = node.name.offset;
     builder.topLevelTypeInferenceError = LazyAst.getTypeInferenceError(node);
     _writeActualType(builder, node);
     _storeInheritsCovariant(builder, node);
@@ -1383,11 +1355,6 @@
 
   @override
   LinkedNodeBuilder visitVariableDeclarationList(VariableDeclarationList node) {
-    if (_variablesDeclaration != null) {
-      _variablesDeclaration.isConst = node.isConst;
-      _variablesDeclaration.isFinal = node.isFinal;
-    }
-
     var builder = LinkedNodeBuilder.variableDeclarationList(
       variableDeclarationList_type: node.type?.accept(this),
       variableDeclarationList_variables: _writeNodeList(node.variables),
@@ -1519,6 +1486,7 @@
 
   void _storeDirective(LinkedNodeBuilder builder, Directive node) {
     _storeAnnotatedNode(builder, node);
+    builder..directive_keywordOffset = node.keyword.offset;
   }
 
   void _storeExpression(LinkedNodeBuilder builder, Expression node) {
@@ -1577,9 +1545,7 @@
       LinkedNodeBuilder builder, NamedCompilationUnitMember node) {
     _storeCompilationUnitMember(builder, node);
     _storeCodeOffsetLength(builder, node);
-    builder
-      ..name = node.name.name
-      ..nameOffset = node.name.offset;
+    builder.namedCompilationUnitMember_name = node.name.accept(this);
   }
 
   void _storeNamespaceDirective(
@@ -1588,8 +1554,7 @@
     builder
       ..namespaceDirective_combinators = _writeNodeList(node.combinators)
       ..namespaceDirective_configurations = _writeNodeList(node.configurations)
-      ..namespaceDirective_selectedUri = LazyDirective.getSelectedUri(node)
-      ..nameOffset = node.offset;
+      ..namespaceDirective_selectedUri = LazyDirective.getSelectedUri(node);
   }
 
   void _storeNormalFormalParameter(
@@ -1604,9 +1569,8 @@
         isRequired: node.requiredKeyword != null,
         isVar: keyword?.type == Keyword.VAR,
       )
-      ..name = node.identifier?.name
-      ..nameOffset = node.identifier?.offset ?? 0
-      ..normalFormalParameter_metadata = _writeNodeList(node.metadata);
+      ..normalFormalParameter_metadata = _writeNodeList(node.metadata)
+      ..normalFormalParameter_identifier = node.identifier?.accept(this);
   }
 
   void _storeStatement(LinkedNodeBuilder builder, Statement node) {}
diff --git a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
index c411c79..2845328 100644
--- a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
@@ -65,6 +65,7 @@
             var nameList = node.hiddenNames.map((i) => i.name).toList();
             return Combinator.hide(nameList);
           }
+          return null;
         }).toList();
 
         var exported = linker.builders[uri];
diff --git a/pkg/analyzer/lib/src/summary2/default_value_resolver.dart b/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
index f531465..9fa79b02 100644
--- a/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
@@ -27,19 +27,12 @@
 
   void resolve() {
     for (CompilationUnitElementImpl unit in _libraryElement.units) {
+      for (var classElement in unit.mixins) {
+        _class(classElement);
+      }
+
       for (var classElement in unit.types) {
-        _classElement = classElement;
-
-        for (var element in classElement.constructors) {
-          _constructor(element);
-        }
-
-        for (var element in classElement.methods) {
-          _setScopeFromElement(element);
-          _method(element);
-        }
-
-        _classElement = null;
+        _class(classElement);
       }
 
       for (var element in unit.functions) {
@@ -48,6 +41,21 @@
     }
   }
 
+  void _class(ClassElement classElement) {
+    _classElement = classElement;
+
+    for (var element in classElement.constructors) {
+      _constructor(element);
+    }
+
+    for (var element in classElement.methods) {
+      _setScopeFromElement(element);
+      _method(element);
+    }
+
+    _classElement = null;
+  }
+
   void _constructor(ConstructorElementImpl element) {
     if (element.isSynthetic) return;
 
diff --git a/pkg/analyzer/lib/src/summary2/lazy_ast.dart b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
index 13d6511..b8d1771 100644
--- a/pkg/analyzer/lib/src/summary2/lazy_ast.dart
+++ b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
@@ -513,12 +513,12 @@
     return node.getProperty(_key);
   }
 
-  static int getNameOffset(Directive node) {
+  static int getKeywordOffset(Directive node) {
     var lazy = get(node);
     if (lazy != null) {
-      return lazy.data.nameOffset;
+      return lazy.data.directive_keywordOffset;
     } else {
-      return node.offset;
+      return node.keyword.offset;
     }
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index e4f4f7b..7d9f6f5 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -5,7 +5,6 @@
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit;
-import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -50,12 +49,9 @@
   InheritanceManager2 inheritance; // TODO(scheglov) cache it
 
   Linker(this.elementFactory) {
-    var dynamicRef = rootReference.getChild('dart:core').getChild('dynamic');
-    dynamicRef.element = DynamicElementImpl.instance;
-    var neverRef = rootReference.getChild('dart:core').getChild('Never');
-    neverRef.element = NeverElementImpl.instance;
-
-    linkingBundleContext = LinkingBundleContext(dynamicRef);
+    linkingBundleContext = LinkingBundleContext(
+      elementFactory.dynamicRef,
+    );
 
     bundleContext = LinkedBundleContext.forAst(
       elementFactory,
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index 94fef40a..9ce9558 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -23,12 +23,23 @@
   CoreTypes _coreTypes;
 
   LinkedElementFactory(
-      this.analysisContext, this.analysisSession, this.rootReference);
+    this.analysisContext,
+    this.analysisSession,
+    this.rootReference,
+  ) {
+    var dartCoreRef = rootReference.getChild('dart:core');
+    dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
+    dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
+  }
 
   CoreTypes get coreTypes {
     return _coreTypes ??= CoreTypes(this);
   }
 
+  Reference get dynamicRef {
+    return rootReference.getChild('dart:core').getChild('dynamic');
+  }
+
   bool get hasDartCore {
     return libraryMap.containsKey('dart:core');
   }
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 320f151..4f1d87f 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -223,7 +223,7 @@
   }
 
   int getDirectiveOffset(AstNode node) {
-    return LazyDirective.getNameOffset(node);
+    return LazyDirective.getKeywordOffset(node);
   }
 
   Comment getDocumentationComment(AstNode node) {
@@ -406,14 +406,6 @@
     }
   }
 
-  InterfaceType getInterfaceType(LinkedNodeType linkedType) {
-    var type = readType(linkedType);
-    if (type is InterfaceType && !type.element.isEnum) {
-      return type;
-    }
-    return null;
-  }
-
   Comment getLibraryDocumentationComment(CompilationUnit unit) {
     for (var directive in unit.directives) {
       if (directive is LibraryDirective) {
@@ -573,10 +565,6 @@
     return LazyDirective.getSelectedUri(node);
   }
 
-  String getStringContent(LinkedNode node) {
-    return node.simpleStringLiteral_value;
-  }
-
   TypeName getSuperclass(AstNode node) {
     if (node is ClassDeclaration) {
       LazyClassDeclaration.readExtendsClause(_astReader, node);
@@ -749,7 +737,9 @@
   }
 
   bool isExplicitlyCovariant(AstNode node) {
-    if (node is EnumConstantDeclaration) {
+    if (node is DefaultFormalParameter) {
+      return isExplicitlyCovariant(node.parameter);
+    } else if (node is EnumConstantDeclaration) {
       return false;
     } else if (node is FormalParameter) {
       return node.covariantKeyword != null;
@@ -784,10 +774,6 @@
     throw UnimplementedError('${node.runtimeType}');
   }
 
-  bool isFunction(LinkedNode node) {
-    return node.kind == LinkedNodeKind.functionDeclaration;
-  }
-
   bool isGenerator(AstNode node) {
     if (node is ConstructorDeclaration) {
       return false;
@@ -826,10 +812,6 @@
     throw UnimplementedError('${node.runtimeType}');
   }
 
-  bool isMethod(LinkedNode node) {
-    return node.kind == LinkedNodeKind.methodDeclaration;
-  }
-
   bool isSetter(AstNode node) {
     if (node is FunctionDeclaration) {
       return node.isSetter;
@@ -868,10 +850,6 @@
     }
   }
 
-  AstNode readNode(LinkedNode linkedNode) {
-    return _astReader.readNode(linkedNode);
-  }
-
   DartType readType(LinkedNodeType linkedType) {
     if (linkedType == null) return null;
 
@@ -946,7 +924,9 @@
   }
 
   void setInheritsCovariant(AstNode node, bool value) {
-    if (node is FormalParameter) {
+    if (node is DefaultFormalParameter) {
+      setInheritsCovariant(node.parameter, value);
+    } else if (node is FormalParameter) {
       LazyAst.setInheritsCovariant(node, value);
     } else if (node is VariableDeclaration) {
       LazyAst.setInheritsCovariant(node, value);
@@ -1038,34 +1018,6 @@
     throw StateError('Expected to find $indexInLibrary part directive.');
   }
 
-  static List<LinkedNode> getTypeParameters(LinkedNode node) {
-    LinkedNode typeParameterList;
-    var kind = node.kind;
-    if (kind == LinkedNodeKind.classTypeAlias) {
-      typeParameterList = node.classTypeAlias_typeParameters;
-    } else if (kind == LinkedNodeKind.classDeclaration ||
-        kind == LinkedNodeKind.mixinDeclaration) {
-      typeParameterList = node.classOrMixinDeclaration_typeParameters;
-    } else if (kind == LinkedNodeKind.constructorDeclaration) {
-      return const [];
-    } else if (kind == LinkedNodeKind.functionDeclaration) {
-      return getTypeParameters(node.functionDeclaration_functionExpression);
-    } else if (kind == LinkedNodeKind.functionExpression) {
-      typeParameterList = node.functionExpression_typeParameters;
-    } else if (kind == LinkedNodeKind.functionTypeAlias) {
-      typeParameterList = node.functionTypeAlias_typeParameters;
-    } else if (kind == LinkedNodeKind.genericFunctionType) {
-      typeParameterList = node.genericFunctionType_typeParameters;
-    } else if (kind == LinkedNodeKind.genericTypeAlias) {
-      typeParameterList = node.genericTypeAlias_typeParameters;
-    } else if (kind == LinkedNodeKind.methodDeclaration) {
-      typeParameterList = node.methodDeclaration_typeParameters;
-    } else {
-      throw UnimplementedError('$kind');
-    }
-    return typeParameterList?.typeParameterList_typeParameters;
-  }
-
   static NullabilitySuffix _nullabilitySuffix(EntityRefNullabilitySuffix data) {
     switch (data) {
       case EntityRefNullabilitySuffix.starOrIrrelevant:
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index e54f0a3..e9efbb0 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -66,8 +66,15 @@
 
     ClassElementImpl element = reference.element;
     node.name.staticElement = element;
+
     _createTypeParameterElements(node.typeParameters);
     scope = new TypeParameterScope(scope, element);
+
+    node.typeParameters?.accept(this);
+    node.extendsClause?.accept(this);
+    node.implementsClause?.accept(this);
+    node.withClause?.accept(this);
+
     scope = new ClassScope(scope, element);
     LinkingNodeContext(node, scope);
 
@@ -79,10 +86,6 @@
       }
     }
 
-    node.typeParameters?.accept(this);
-    node.extendsClause?.accept(this);
-    node.implementsClause?.accept(this);
-    node.withClause?.accept(this);
     node.members.accept(this);
     nodesToBuildType.addDeclaration(node);
 
@@ -359,8 +362,8 @@
     LinkingNodeContext(node, scope);
 
     node.returnType?.accept(this);
-    node.parameters?.accept(this);
     node.typeParameters?.accept(this);
+    node.parameters?.accept(this);
     nodesToBuildType.addDeclaration(node);
 
     scope = outerScope;
@@ -377,14 +380,17 @@
 
     MixinElementImpl element = reference.element;
     node.name.staticElement = element;
+
     _createTypeParameterElements(node.typeParameters);
     scope = new TypeParameterScope(scope, element);
-    scope = new ClassScope(scope, element);
-    LinkingNodeContext(node, scope);
 
     node.typeParameters?.accept(this);
     node.onClause?.accept(this);
     node.implementsClause?.accept(this);
+
+    scope = new ClassScope(scope, element);
+    LinkingNodeContext(node, scope);
+
     node.members.accept(this);
     nodesToBuildType.addDeclaration(node);
 
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index eef737d..ac469fd 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -67,9 +67,11 @@
   }
 
   void _variableDeclarationList(VariableDeclarationList node) {
-    if (node.isConst && node.type != null) {
+    var typeNode = node.type;
+    if (node.isConst && typeNode != null) {
       for (var variable in node.variables) {
         if (variable.initializer != null) {
+          InferenceContext.setType(variable.initializer, typeNode.type);
           var astResolver = AstResolver(linker, _library, _scope);
           astResolver.rewriteAst(variable.initializer);
           astResolver.resolve(variable.initializer);
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index e451ec6..2ca6313 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -1118,7 +1118,7 @@
     }
 
     // Down cast or legal sideways cast, coercion needed.
-    if (rules.isAssignableTo(from, to)) {
+    if (rules.isAssignableTo(from, to, featureSet: _featureSet)) {
       return true;
     }
 
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index ce217cf..7a1f121 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -87,6 +87,10 @@
     return _node(search, (n) => n is ExpressionStatement);
   }
 
+  FieldDeclaration fieldDeclaration(String search) {
+    return _node(search, (n) => n is FieldDeclaration);
+  }
+
   FieldFormalParameter fieldFormalParameter(String search) {
     return _node(search, (n) => n is FieldFormalParameter);
   }
diff --git a/pkg/analyzer/test/file_system/overlay_file_system_test.dart b/pkg/analyzer/test/file_system/overlay_file_system_test.dart
index c422ade..7ee7052 100644
--- a/pkg/analyzer/test/file_system/overlay_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/overlay_file_system_test.dart
@@ -179,6 +179,15 @@
     expect(file.readAsBytesSync(), <int>[98, 98, 98]);
   }
 
+  test_readAsBytesSync_existing_withOverlay_utf8() {
+    // Strings should be encoded as UTF8 when they're written, so when we read
+    // them back as bytes we should see the UTF8-encoded version of the string.
+    String overlayContent = '\u00e5'; // latin small letter a with ring above
+    File file =
+        _file(exists: true, withOverlay: true, overlayContent: overlayContent);
+    expect(file.readAsBytesSync(), <int>[0xc3, 0xa5]);
+  }
+
   test_readAsBytesSync_notExisting_withoutOverlay() {
     File file = _file(exists: false);
     expect(() => file.readAsBytesSync(), throwsA(_isFileSystemException));
@@ -506,7 +515,7 @@
     expect(child, isNotNull);
   }
 
-  test_getChildren() {
+  test_getChildren_existing() {
     Folder folder = _folder(exists: true);
     Folder child1 = _folder(
         exists: true, path: provider.pathContext.join(folder.path, 'lib'));
@@ -523,6 +532,13 @@
         unorderedEquals([child1.path, child2.path, child3.path]));
   }
 
+  test_getChildren_nonExisting_withOverlay() {
+    File file = _file(exists: false, withOverlay: true);
+    List<Resource> children = file.parent.parent.getChildren();
+    expect(children, hasLength(1));
+    expect(children[0], _isFolder);
+  }
+
   test_isOrContains_false() {
     Folder folder = _folder(exists: true);
     expect(folder.isOrContains(baseProvider.convertPath('/foo/baz')), isFalse);
@@ -662,20 +678,28 @@
     expect(file.exists, isTrue);
   }
 
-  test_getFolder_existing() {
+  test_getFolder_existing_withoutOverlay() {
     Folder folder = _folder(exists: true);
     expect(folder, isNotNull);
     expect(folder.path, defaultFolderPath);
     expect(folder.exists, isTrue);
   }
 
-  test_getFolder_notExisting() {
+  test_getFolder_notExisting_withoutOverlay() {
     Folder folder = _folder(exists: false);
     expect(folder, isNotNull);
     expect(folder.path, defaultFolderPath);
     expect(folder.exists, isFalse);
   }
 
+  test_getFolder_notExisting_withOverlay() {
+    File file = _file(exists: false, withOverlay: true);
+    Folder folder = file.parent;
+    expect(folder, isNotNull);
+    expect(folder.path, defaultFolderPath);
+    expect(folder.exists, isTrue);
+  }
+
   test_getModificationTimes_withoutOverlay() async {
     Source source = _file(exists: true).createSource();
     List<int> times = await provider.getModificationTimes([source]);
@@ -688,36 +712,43 @@
     expect(times, [42]);
   }
 
-  test_getResource_existingFile_withoutOverlay() {
+  test_getResource_file_existing_withoutOverlay() {
     String path = _file(exists: true).path;
     Resource resource = provider.getResource(path);
     expect(resource, _isFile);
   }
 
-  test_getResource_existingFile_withOverlay() {
+  test_getResource_file_existing_withOverlay() {
     String path = _file(exists: true, withOverlay: true).path;
     Resource resource = provider.getResource(path);
     expect(resource, _isFile);
   }
 
-  test_getResource_existingFolder() {
-    String path = _folder(exists: true).path;
-    Resource resource = provider.getResource(path);
-    expect(resource, _isFolder);
-  }
-
-  test_getResource_notExisting_withoutOverlay() {
+  test_getResource_file_notExisting_withoutOverlay() {
     String path = _file(exists: false).path;
     Resource resource = provider.getResource(path);
     expect(resource, _isFile);
   }
 
-  test_getResource_notExisting_withOverlay() {
+  test_getResource_file_notExisting_withOverlay() {
     String path = _file(exists: false, withOverlay: true).path;
     Resource resource = provider.getResource(path);
     expect(resource, _isFile);
   }
 
+  test_getResource_folder_existing() {
+    String path = _folder(exists: true).path;
+    Resource resource = provider.getResource(path);
+    expect(resource, _isFolder);
+  }
+
+  test_getResource_folder_nonExisting_withOverlay() {
+    String filePath = _file(exists: false, withOverlay: true).path;
+    String folderPath = provider.pathContext.dirname(filePath);
+    Resource resource = provider.getResource(folderPath);
+    expect(resource, _isFolder);
+  }
+
   test_getStateLocation_uniqueness() {
     String idOne = 'one';
     Folder folderOne = provider.getStateLocation(idOne);
@@ -763,7 +794,8 @@
       {@required bool exists,
       String content,
       String path,
-      bool withOverlay = false}) {
+      bool withOverlay = false,
+      String overlayContent = 'bbb'}) {
     if (path == null) {
       path = defaultFilePath;
     } else {
@@ -773,7 +805,7 @@
       baseProvider.newFile(path, content ?? 'a');
     }
     if (withOverlay) {
-      provider.setOverlay(path, content: 'bbb', modificationStamp: 42);
+      provider.setOverlay(path, content: overlayContent, modificationStamp: 42);
     }
     return provider.getFile(path);
   }
diff --git a/pkg/analyzer/test/generated/analysis_context_factory.dart b/pkg/analyzer/test/generated/analysis_context_factory.dart
index b70df9d..b7ae647 100644
--- a/pkg/analyzer/test/generated/analysis_context_factory.dart
+++ b/pkg/analyzer/test/generated/analysis_context_factory.dart
@@ -245,7 +245,7 @@
     // Stream
     ClassElementImpl streamElement =
         ElementFactory.classElement2("Stream", ["T"]);
-    streamElement.abstract = true;
+    streamElement.isAbstract = true;
     streamElement.constructors = <ConstructorElement>[
       ElementFactory.constructorElement2(streamElement, null)
     ];
@@ -365,7 +365,7 @@
     TopLevelVariableElement piElement = ElementFactory.topLevelVariableElement3(
         "PI", true, false, provider.doubleType);
     ClassElementImpl randomElement = ElementFactory.classElement2("Random");
-    randomElement.abstract = true;
+    randomElement.isAbstract = true;
     ConstructorElementImpl randomConstructor =
         ElementFactory.constructorElement2(randomElement, null);
     randomConstructor.factory = true;
diff --git a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
index 4a01b55..f92a108 100644
--- a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
@@ -16,12 +16,14 @@
 @reflectiveTest
 class CheckedModeCompileTimeErrorCodeTest extends DriverResolutionTest {
   test_assertion_throws() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(int x, int y) : assert(x < y);
 }
 var v = const A(3, 2);
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 61, 13),
+    ]);
   }
 
   test_fieldFormalParameterAssignableToField_extends() async {
@@ -46,13 +48,15 @@
   test_fieldFormalParameterAssignableToField_fieldType_unresolved_null() async {
     // Null always passes runtime type checks, even when the type is
     // unresolved.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   final Unresolved x;
   const A(String this.x);
 }
 var v = const A(null);
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 18, 10),
+    ]);
   }
 
   test_fieldFormalParameterAssignableToField_implements() async {
@@ -151,7 +155,7 @@
   test_fieldFormalParameterAssignableToField_typedef() async {
     // foo has the runtime type dynamic -> dynamic, so it is not assignable
     // to A.f.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 typedef String Int2String(int x);
 class A {
   final Int2String f;
@@ -159,7 +163,9 @@
 }
 foo(x) => 1;
 var v = const A(foo);
-''', [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 116, 3),
+    ]);
   }
 
   test_fieldFormalParameterAssignableToField_typeSubstitution() async {
@@ -175,15 +181,18 @@
   }
 
   test_fieldFormalParameterNotAssignableToField() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   final int x;
   const A(this.x);
 }
 var v = const A('foo');
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          62,
+          5),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 62, 5),
     ]);
   }
 
@@ -191,7 +200,7 @@
     // According to checked-mode type checking rules, a value of type A is not
     // assignable to a field of type B, because B extends A (the subtyping
     // relationship is in the wrong direction).
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A();
 }
@@ -204,37 +213,47 @@
 }
 const A u = const A();
 var v = const C(u);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          143,
+          1),
+    ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_fieldType() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   final int x;
   const A(this.x);
 }
 var v = const A('foo');
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          62,
+          5),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 62, 5),
     ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_fieldType_unresolved() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   final Unresolved x;
   const A(String this.x);
 }
 var v = const A('foo');
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 18, 10),
+    ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_implements() async {
     // According to checked-mode type checking rules, a value of type A is not
     // assignable to a field of type B, because B implements A (the subtyping
     // relationship is in the wrong direction).
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A();
 }
@@ -245,61 +264,84 @@
 }
 const A u = const A();
 var v = const C(u);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          132,
+          1),
+    ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_list() async {
     // <num>[1, 2, 3] has type List<num>, which is not a subtype of List<int>.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(List<int> x);
 }
 const dynamic w = const <num>[1, 2, 3];
 var x = const A(w);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          92,
+          1),
+    ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_map_keyMismatch() async {
     // <num, int>{1: 2} has type Map<num, int>, which is not a subtype of
     // Map<int, int>.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(Map<int, int> x);
 }
 const dynamic w = const <num, int>{1: 2};
 var x = const A(w);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          98,
+          1),
+    ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_map_valueMismatch() async {
     // <int, num>{1: 2} has type Map<int, num>, which is not a subtype of
     // Map<int, int>.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(Map<int, int> x);
 }
 const dynamic w = const <int, num>{1: 2};
 var x = const A(w);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          98,
+          1),
+    ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_optional() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   final int x;
   const A([this.x = 'foo']);
 }
 var v = const A();
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticTypeWarningCode.INVALID_ASSIGNMENT
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 45, 5),
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          64,
+          9),
     ]);
   }
 
   test_fieldFormalParameterNotAssignableToField_typedef() async {
     // foo has the runtime type String -> int, so it should not be assignable
     // to A.f (A.f requires it to be int -> String).
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 typedef String Int2String(int x);
 class A {
   final Int2String f;
@@ -308,35 +350,47 @@
 int foo(String x) => 1;
 var v = const A(foo);
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 127, 3),
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          127,
+          3),
     ]);
   }
 
   test_fieldInitializerNotAssignable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   final int x;
   const A() : x = '';
 }
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE,
-      StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE
+      error(StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE, 43, 2),
+      error(
+          CheckedModeCompileTimeErrorCode
+              .CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE,
+          43,
+          2),
     ]);
   }
 
   test_fieldTypeMismatch() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(x) : y = x;
   final int y;
 }
 var v = const A('foo');
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH]);
+''', [
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
+          57,
+          14),
+    ]);
   }
 
   test_fieldTypeMismatch_generic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
       r'''
 class C<T> {
   final T x = y;
@@ -346,24 +400,30 @@
 var v = const C<String>();
 ''',
       [
-        CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
-        StaticTypeWarningCode.INVALID_ASSIGNMENT
+        error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 27, 1),
+        error(
+            CheckedModeCompileTimeErrorCode
+                .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
+            70,
+            17),
       ],
     );
   }
 
   test_fieldTypeMismatch_unresolved() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(x) : y = x;
   final Unresolved y;
 }
 var v = const A('foo');
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 40, 10),
+    ]);
   }
 
   test_fieldTypeOk_generic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
       r'''
 class C<T> {
   final T x = y;
@@ -372,7 +432,9 @@
 const int y = 1;
 var v = const C<int>();
 ''',
-      [StaticTypeWarningCode.INVALID_ASSIGNMENT],
+      [
+        error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 27, 1),
+      ],
     );
   }
 
@@ -389,40 +451,50 @@
   test_fieldTypeOk_unresolved_null() async {
     // Null always passes runtime type checks, even when the type is
     // unresolved.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(x) : y = x;
   final Unresolved y;
 }
 var v = const A(null);
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 40, 10),
+    ]);
   }
 
   test_listElementTypeNotAssignable() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = const <String> [42];
-''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 24, 2),
+    ]);
   }
 
   test_listLiteral_inferredElementType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const Object x = [1];
 const List<String> y = x;
-''', [CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH]);
+''', [
+      error(CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, 41, 1),
+    ]);
   }
 
   test_mapLiteral_inferredKeyType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const Object x = {1: 1};
 const Map<String, dynamic> y = x;
-''', [CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH]);
+''', [
+      error(CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, 52, 1),
+    ]);
   }
 
   test_mapLiteral_inferredValueType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const Object x = {1: 1};
 const Map<dynamic, String> y = x;
-''', [CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH]);
+''', [
+      error(CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, 52, 1),
+    ]);
   }
 
   test_parameterAssignable_null() async {
@@ -445,59 +517,71 @@
   test_parameterAssignable_undefined_null() async {
     // Null always passes runtime type checks, even when the type is
     // unresolved.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(Unresolved x);
 }
 var v = const A(null);
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 20, 10),
+    ]);
   }
 
   test_parameterNotAssignable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(int x);
 }
 var v = const A('foo');
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          46,
+          5),
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 46, 5),
     ]);
   }
 
   test_parameterNotAssignable_typeSubstitution() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A<T> {
   const A(T x);
 }
 var v = const A<int>('foo');
 ''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 52, 5),
+      error(
+          CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+          52,
+          5),
     ]);
   }
 
   test_parameterNotAssignable_undefined() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A(Unresolved x);
 }
 var v = const A('foo');
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 20, 10),
+    ]);
   }
 
   test_redirectingConstructor_paramTypeMismatch() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   const A.a1(x) : this.a2(x);
   const A.a2(String x);
 }
 var v = const A.a1(0);
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 74, 13),
+    ]);
   }
 
   test_superConstructor_paramTypeMismatch() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class C {
   final double d;
   const C(this.d);
@@ -506,7 +590,9 @@
   const D(d) : super(d);
 }
 const f = const D('0.0');
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 106, 14),
+    ]);
   }
 
   test_topLevelVarAssignable_null() async {
@@ -518,23 +604,27 @@
   test_topLevelVarAssignable_undefined_null() async {
     // Null always passes runtime type checks, even when the type is
     // unresolved.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const Unresolved x = null;
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 6, 10),
+    ]);
   }
 
   test_topLevelVarNotAssignable() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const int x = 'foo';
 ''', [
-      CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
-      StaticTypeWarningCode.INVALID_ASSIGNMENT
+      error(CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, 10, 1),
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 14, 5),
     ]);
   }
 
   test_topLevelVarNotAssignable_undefined() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const Unresolved x = 'foo';
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 6, 10),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index e11ba55..e1db296 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code.dart
@@ -2726,7 +2726,6 @@
 }
 ''', [
       error(HintCode.UNUSED_LOCAL_VARIABLE, 32, 5),
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 32, 5),
     ]);
   }
 
@@ -5134,12 +5133,17 @@
   }
 
   test_typeAliasCannotReferenceItself_typeVariableBounds() async {
+    var errors = [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 30),
+    ];
+    if (!AnalysisDriver.useSummary2) {
+      errors.add(
+        error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 22, 3),
+      );
+    }
     await assertErrorsInCode('''
 typedef A<T extends A<int>>();
-''', [
-      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 30),
-      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 22, 3),
-    ]);
+''', errors);
   }
 
   test_typeArgumentNotMatchingBounds_const() async {
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 57e5769..7346b25 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -79,21 +79,21 @@
 class CompileTimeErrorCodeTest_WithUIAsCode extends DriverResolutionTest {
   test_defaultValueInFunctionTypeAlias_new_named() async {
     // This test used to fail with UI as code enabled. Test the fix here.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 typedef F = int Function({Map<String, String> m: const {}});
 ''', [
-      ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
+      error(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 47, 1),
     ]);
   }
 
   test_defaultValueInFunctionTypeAlias_new_named_ambiguous() async {
     // Test that the strong checker does not crash when given an ambiguous
     // set or map literal.
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 typedef F = int Function({Object m: const {1, 2: 3}});
 ''', [
-      ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
-      CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH,
+      error(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 34, 1),
+      error(CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH, 36, 15),
     ]);
   }
 }
@@ -101,236 +101,298 @@
 @reflectiveTest
 class ControlFlowCollectionsTest extends DriverResolutionTest {
   test_awaitForIn_declaredVariableWrongType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 import 'dart:async';
 f() async {
   Stream<String> stream;
   await for (int i in stream) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 75, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 80, 6),
+    ]);
   }
 
   test_awaitForIn_existingVariableWrongType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 import 'dart:async';
 f() async {
   Stream<String> stream;
   int i;
   await for (i in stream) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 64, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 85, 6),
+    ]);
   }
 
   test_awaitForIn_notStream() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 f() async {
   await for (var i in true) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 29, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, 34, 4),
+    ]);
   }
 
   test_duplicateDefinition_for_initializers() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   for (int i = 0, i = 0; i < 5;) {}
 }
-''', [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 24, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 24, 1),
+    ]);
   }
 
   test_expectedOneListTypeArgument() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   <int, int>[];
-}''', [StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS]);
+}''', [
+      error(StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS, 11, 10),
+    ]);
   }
 
   test_expectedOneSetTypeArgument() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   <int, int, int>{2, 3};
-}''', [StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS]);
+}''', [
+      error(StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS, 11, 15),
+    ]);
   }
 
   test_expectedTwoMapTypeArguments_three_ambiguous() async {
     // TODO(brianwilkerson) We probably need a new error code for "expected
     //  either one or two type arguments" to handle the ambiguous case.
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   <int, int, int>{};
-}''', [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]);
+}''', [
+      error(StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS, 11, 15),
+    ]);
   }
 
   test_expectedTwoMapTypeArguments_three_map() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 main() {
   <int, int, int>{1:2};
-}''', [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]);
+}''', [
+      error(StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS, 11, 15),
+    ]);
   }
 
   test_forIn_declaredVariableWrongType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 f() {
   for (int i in <String>[]) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 22, 10),
+    ]);
   }
 
   test_forIn_existingVariableWrongType() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 f() {
   int i;
   for (i in <String>[]) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 12, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 27, 10),
+    ]);
   }
 
   test_forIn_notIterable() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 f() {
   for (var i in true) {}
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, 22, 4),
+    ]);
   }
 
   test_forIn_typeBoundBad() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 class Foo<T extends Iterable<int>> {
   void method(T iterable) {
     for (String i in iterable) {}
   }
 }
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 81, 1),
+      error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 86, 8),
+    ]);
   }
 
   test_forInWithConstVariable_forEach_identifier() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   const x = 0;
   for (x in [0, 1, 2]) {}
 }
-''', [CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+      error(CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, 28, 1),
+    ]);
   }
 
   test_forInWithConstVariable_forEach_loopVariable() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   for (const x in [0, 1, 2]) {}
 }
-''', [CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE]);
+''', [
+      error(CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, 13, 7),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 19, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfInForeachIterableError() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 void main() {
   void x;
   for (var v in x) {}
 }
-''', [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 35, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 40, 1),
+    ]);
   }
 
   test_generalizedVoid_useOfVoidInForeachVariableError() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 void main() {
   void x;
   var y;
   for (y in x) {}
 }
-''', [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 30, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 45, 1),
+    ]);
   }
 
   test_invalidTypeArgumentInConstList() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A<E> {
   m() {
     return const <E>[];
   }
 }
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST]);
+''', [
+      error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST, 39, 1),
+    ]);
   }
 
   test_invalidTypeArgumentInConstMap_key() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A<E> {
   m() {
     return const <E, String>{};
   }
 }
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP]);
+''', [
+      error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP, 39, 1),
+    ]);
   }
 
   test_invalidTypeArgumentInConstMap_value() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A<E> {
   m() {
     return const <String, E>{};
   }
 }
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP]);
+''', [
+      error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP, 47, 1),
+    ]);
   }
 
   test_invalidTypeArgumentInConstSet_class() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A<E> {
   m() {
     return const <E>{};
   }
 }
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET]);
+''', [
+      error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET, 39, 1),
+    ]);
   }
 
   test_listElementTypeNotAssignable_const() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = const <String>[42];
-''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 23, 2),
+    ]);
   }
 
   test_mapValueTypeNotAssignable_const() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = const <String, String>{'a' : 2};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 37, 1),
+    ]);
   }
 
   test_nonBoolCondition_for_declaration() async {
     // https://github.com/dart-lang/sdk/issues/24713
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   for (int i = 0; 3;) {}
 }
-''', [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+      error(StaticTypeWarningCode.NON_BOOL_CONDITION, 24, 1),
+    ]);
   }
 
   test_nonBoolCondition_for_expression() async {
     // https://github.com/dart-lang/sdk/issues/24713
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   int i;
   for (i = 0; 3;) {}
-}''', [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 12, 1),
+      error(StaticTypeWarningCode.NON_BOOL_CONDITION, 29, 1),
+    ]);
   }
 
   test_nonConstMapAsExpressionStatement_begin() async {
     // TODO(danrubel) Fasta is not recovering well.
     // Ideally we would produce a single diagnostic:
     // CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   {'a' : 0, 'b' : 1}.length;
 }
 ''', [
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
+      error(ParserErrorCode.EXPECTED_TOKEN, 9, 3),
+      error(ParserErrorCode.EXPECTED_TOKEN, 13, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 13, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 15, 1),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 16, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 16, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 18, 3),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 22, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 22, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 22, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 24, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
     ]);
   }
 
@@ -338,43 +400,47 @@
     // TODO(danrubel) Fasta is not recovering well.
     // Ideally we would produce a single diagnostic:
     // CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 f() {
   {'a' : 0, 'b' : 1};
 }
 ''', [
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.UNEXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
+      error(ParserErrorCode.EXPECTED_TOKEN, 9, 3),
+      error(ParserErrorCode.EXPECTED_TOKEN, 13, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 13, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 15, 1),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 16, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 16, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 18, 3),
+      error(ParserErrorCode.UNEXPECTED_TOKEN, 22, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 22, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 22, 1),
+      error(ParserErrorCode.EXPECTED_TOKEN, 24, 1),
     ]);
   }
 
   test_setElementTypeNotAssignable_const() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = const <String>{42};
-''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 23, 2),
+    ]);
   }
 }
 
 @reflectiveTest
 class InvalidTypeArgumentInConstSetTest extends DriverResolutionTest {
   test_class() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A<E> {
   m() {
     return const <E>{};
   }
 }
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET]);
+''', [
+      error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET, 39, 1),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index fe23034..11fa1ce 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -1901,7 +1901,7 @@
   }
 
   test_infer_mixin_with_substitution_functionType_new_syntax() async {
-    await assertNoErrorsInCode('''
+    await assertErrorsInCode('''
 abstract class A<T> {}
 
 class B {}
@@ -1909,7 +1909,13 @@
 mixin M<T, U> on A<T Function(U)> {}
 
 class C extends A<int Function(String)> with M {}
-''');
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        47,
+        1,
+      ),
+    ]);
     CompilationUnit unit = result.unit;
     ClassElement classC =
         resolutionMap.elementDeclaredByCompilationUnit(unit).getType('C');
diff --git a/pkg/analyzer/test/generated/parser_fasta_listener.dart b/pkg/analyzer/test/generated/parser_fasta_listener.dart
index 20e6f2d..26fff6d 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -108,12 +108,6 @@
   }
 
   @override
-  void beginClassOrMixinBody(Token token) {
-    super.beginClassOrMixinBody(token);
-    begin('ClassOrMixinBody');
-  }
-
-  @override
   void beginClassDeclaration(
       Token beginToken, Token abstractToken, Token name) {
     super.beginClassDeclaration(beginToken, abstractToken, name);
@@ -121,6 +115,12 @@
   }
 
   @override
+  void beginClassOrMixinBody(Token token) {
+    super.beginClassOrMixinBody(token);
+    begin('ClassOrMixinBody');
+  }
+
+  @override
   void beginClassOrNamedMixinApplication(Token token) {
     super.beginClassOrNamedMixinApplication(token);
     begin('ClassOrNamedMixinApplication');
@@ -201,6 +201,12 @@
   }
 
   @override
+  void beginExtensionDeclaration(Token extensionKeyword, Token name) {
+    super.beginExtensionDeclaration(extensionKeyword, name);
+    begin('ExtensionDeclaration');
+  }
+
+  @override
   void beginFactoryMethod(
       Token lastConsumed, Token externalToken, Token constToken) {
     super.beginFactoryMethod(lastConsumed, externalToken, constToken);
@@ -232,18 +238,6 @@
   }
 
   @override
-  void beginForStatement(Token token) {
-    super.beginForStatement(token);
-    begin('ForStatement');
-  }
-
-  @override
-  void beginForStatementBody(Token token) {
-    super.beginForStatementBody(token);
-    begin('ForStatementBody');
-  }
-
-  @override
   void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
       Token covariantToken, Token varFinalOrConst) {
     super.beginFormalParameter(
@@ -258,15 +252,15 @@
   }
 
   @override
-  void beginIfControlFlow(Token ifToken) {
-    super.beginIfControlFlow(ifToken);
-    begin('IfControlFlow');
+  void beginForStatement(Token token) {
+    super.beginForStatement(token);
+    begin('ForStatement');
   }
 
   @override
-  void beginLocalFunctionDeclaration(Token token) {
-    super.beginLocalFunctionDeclaration(token);
-    begin('LocalFunctionDeclaration');
+  void beginForStatementBody(Token token) {
+    super.beginForStatementBody(token);
+    begin('ForStatementBody');
   }
 
   @override
@@ -306,6 +300,12 @@
   }
 
   @override
+  void beginIfControlFlow(Token ifToken) {
+    super.beginIfControlFlow(ifToken);
+    begin('IfControlFlow');
+  }
+
+  @override
   void beginIfStatement(Token token) {
     super.beginIfStatement(token);
     begin('IfStatement');
@@ -360,6 +360,12 @@
   }
 
   @override
+  void beginLocalFunctionDeclaration(Token token) {
+    super.beginLocalFunctionDeclaration(token);
+    begin('LocalFunctionDeclaration');
+  }
+
+  @override
   void beginMember() {
     expectIn('ClassOrMixinBody');
     super.beginMember();
@@ -602,12 +608,6 @@
   }
 
   @override
-  void endClassOrMixinBody(int memberCount, Token beginToken, Token endToken) {
-    end('ClassOrMixinBody');
-    super.endClassOrMixinBody(memberCount, beginToken, endToken);
-  }
-
-  @override
   void endClassDeclaration(Token beginToken, Token endToken) {
     end('ClassDeclaration');
     end('ClassOrNamedMixinApplication');
@@ -615,6 +615,12 @@
   }
 
   @override
+  void endClassOrMixinBody(int memberCount, Token beginToken, Token endToken) {
+    end('ClassOrMixinBody');
+    super.endClassOrMixinBody(memberCount, beginToken, endToken);
+  }
+
+  @override
   void endCombinators(int count) {
     end('Combinators');
     super.endCombinators(count);
@@ -690,6 +696,12 @@
   }
 
   @override
+  void endExtensionDeclaration(Token onKeyword, Token token) {
+    super.endExtensionDeclaration(onKeyword, token);
+    end('ExtensionDeclaration');
+  }
+
+  @override
   void endFactoryMethod(
       Token beginToken, Token factoryKeyword, Token endToken) {
     end('FactoryMethod');
@@ -718,12 +730,6 @@
   }
 
   @override
-  void endForInControlFlow(Token token) {
-    end('ForControlFlow');
-    super.endForInControlFlow(token);
-  }
-
-  @override
   void endForIn(Token endToken) {
     end('ForStatement');
     super.endForIn(endToken);
@@ -736,24 +742,18 @@
   }
 
   @override
+  void endForInControlFlow(Token token) {
+    end('ForControlFlow');
+    super.endForInControlFlow(token);
+  }
+
+  @override
   void endForInExpression(Token token) {
     end('ForInExpression');
     super.endForInExpression(token);
   }
 
   @override
-  void endForStatement(Token endToken) {
-    end('ForStatement');
-    super.endForStatement(endToken);
-  }
-
-  @override
-  void endForStatementBody(Token token) {
-    end('ForStatementBody');
-    super.endForStatementBody(token);
-  }
-
-  @override
   void endFormalParameter(Token thisKeyword, Token periodAfterThis,
       Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
     end('FormalParameter');
@@ -769,9 +769,15 @@
   }
 
   @override
-  void endLocalFunctionDeclaration(Token endToken) {
-    end('LocalFunctionDeclaration');
-    super.endLocalFunctionDeclaration(endToken);
+  void endForStatement(Token endToken) {
+    end('ForStatement');
+    super.endForStatement(endToken);
+  }
+
+  @override
+  void endForStatementBody(Token token) {
+    end('ForStatementBody');
+    super.endForStatementBody(token);
   }
 
   @override
@@ -878,6 +884,12 @@
   }
 
   @override
+  void endLocalFunctionDeclaration(Token endToken) {
+    end('LocalFunctionDeclaration');
+    super.endLocalFunctionDeclaration(endToken);
+  }
+
+  @override
   void endMember() {
     end('Member');
     super.endMember();
@@ -1116,33 +1128,23 @@
   }
 
   @override
-  void handleIdentifierList(int count) {
-    expectInOneOf(['Hide', 'Show']);
-    super.handleIdentifierList(count);
-  }
-
-  @override
   void handleDottedName(int count, Token firstIdentifier) {
     expectIn('ConditionalUri');
     super.handleDottedName(count, firstIdentifier);
   }
 
   @override
-  void handleRecoverClassHeader() {
-    expectIn('ClassDeclaration');
-    listener.handleRecoverClassHeader();
+  void handleIdentifierList(int count) {
+    expectInOneOf(['Hide', 'Show']);
+    super.handleIdentifierList(count);
   }
 
   @override
-  void handleRecoverImport(Token semicolon) {
-    expectIn('CompilationUnit');
-    listener.handleRecoverImport(semicolon);
-  }
-
-  @override
-  void handleRecoverMixinHeader() {
-    expectIn('MixinDeclaration');
-    listener.handleRecoverMixinHeader();
+  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+    // This event normally happens within "Import",
+    // but happens within "CompilationUnit" during recovery.
+    expectInOneOf(const ['Import', 'CompilationUnit']);
+    listener.handleImportPrefix(deferredKeyword, asKeyword);
   }
 
   @override
@@ -1182,11 +1184,21 @@
   }
 
   @override
-  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
-    // This event normally happens within "Import",
-    // but happens within "CompilationUnit" during recovery.
-    expectInOneOf(const ['Import', 'CompilationUnit']);
-    listener.handleImportPrefix(deferredKeyword, asKeyword);
+  void handleRecoverClassHeader() {
+    expectIn('ClassDeclaration');
+    listener.handleRecoverClassHeader();
+  }
+
+  @override
+  void handleRecoverImport(Token semicolon) {
+    expectIn('CompilationUnit');
+    listener.handleRecoverImport(semicolon);
+  }
+
+  @override
+  void handleRecoverMixinHeader() {
+    expectIn('MixinDeclaration');
+    listener.handleRecoverMixinHeader();
   }
 
   @override
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 6de285d..4f0c894 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -36,6 +36,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ClassMemberParserTest_Fasta);
+    defineReflectiveTests(ExtensionMethodsParserTest_Fasta);
     defineReflectiveTests(CollectionLiteralParserTest);
     defineReflectiveTests(ComplexParserTest_Fasta);
     defineReflectiveTests(ErrorParserTest_Fasta);
@@ -1435,6 +1436,163 @@
   }
 }
 
+@reflectiveTest
+class ExtensionMethodsParserTest_Fasta extends FastaParserTestCase {
+  @override
+  CompilationUnit parseCompilationUnit(String content,
+      {List<ErrorCode> codes,
+      List<ExpectedError> errors,
+      FeatureSet featureSet}) {
+    return super.parseCompilationUnit(content,
+        codes: codes,
+        errors: errors,
+        featureSet: featureSet ??
+            FeatureSet.forTesting(
+              sdkVersion: '2.3.0',
+              additionalFeatures: [Feature.extension_methods],
+            ));
+  }
+
+  void test_complex_extends() {
+    var unit = parseCompilationUnit(
+        'extension E extends A with B, C implements D { }',
+        errors: [
+          expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 7),
+          expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 22, 4),
+          expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 28, 1),
+          expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 32, 10),
+        ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'extends');
+    expect((extension.extendedType as NamedType).name.name, 'A');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_complex_implements() {
+    var unit = parseCompilationUnit('extension E implements C, D { }', errors: [
+      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 10),
+      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 24, 1),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'implements');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_complex_type() {
+    var unit = parseCompilationUnit('extension E on C<T> { }');
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    var namedType = (extension.extendedType as NamedType);
+    expect(namedType.name.name, 'C');
+    expect(namedType.typeArguments.arguments, hasLength(1));
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_missing_on() {
+    var unit = parseCompilationUnit('extension E', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 11, 0),
+      expectedError(ParserErrorCode.MISSING_CLASS_BODY, 11, 0),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    expect((extension.extendedType as NamedType).name.name, '');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_missing_on_withBlock() {
+    var unit = parseCompilationUnit('extension E {}', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 1),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    expect((extension.extendedType as NamedType).name.name, '');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_missing_on_withClassAndBlock() {
+    var unit = parseCompilationUnit('extension E C {}', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_simple() {
+    var unit = parseCompilationUnit('extension E on C { }');
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    var namedType = (extension.extendedType as NamedType);
+    expect(namedType.name.name, 'C');
+    expect(namedType.typeArguments, isNull);
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_simple_extends() {
+    var unit = parseCompilationUnit('extension E extends C { }', errors: [
+      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 7),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'extends');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_simple_implements() {
+    var unit = parseCompilationUnit('extension E implements C { }', errors: [
+      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 10),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'implements');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_simple_not_enabled() {
+    parseCompilationUnit('extension E on C { }',
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 0, 9),
+          expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 15, 1)
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.3.0'));
+  }
+
+  void test_simple_with() {
+    var unit = parseCompilationUnit('extension E with C { }', errors: [
+      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 4),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'with');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+}
+
 /**
  * Implementation of [AbstractParserTestCase] specialized for testing the
  * Fasta parser.
@@ -2131,19 +2289,24 @@
  */
 @reflectiveTest
 class NNBDParserTest_Fasta extends FastaParserTestCase {
+  @override
+  CompilationUnit parseCompilationUnit(String content,
+          {List<ErrorCode> codes,
+          List<ExpectedError> errors,
+          FeatureSet featureSet}) =>
+      super.parseCompilationUnit(content,
+          codes: codes, errors: errors, featureSet: featureSet ?? nonNullable);
+
   void test_assignment_complex() {
-    parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x + bar(7); }',
-        featureSet: nonNullable);
+    parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x + bar(7); }');
   }
 
   void test_assignment_simple() {
-    parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }');
   }
 
   void test_binary_expression_statement() {
-    final unit = parseCompilationUnit('D? foo(X? x) { X ?? x2; }',
-        featureSet: nonNullable);
+    final unit = parseCompilationUnit('D? foo(X? x) { X ?? x2; }');
     FunctionDeclaration funct = unit.declarations[0];
     BlockFunctionBody body = funct.functionExpression.body;
     ExpressionStatement statement = body.block.statements[0];
@@ -2156,13 +2319,11 @@
   }
 
   void test_conditional() {
-    parseCompilationUnit('D? foo(X? x) { X ? 7 : y; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('D? foo(X? x) { X ? 7 : y; }');
   }
 
   void test_conditional_complex() {
-    parseCompilationUnit('D? foo(X? x) { X ? x2 = x + bar(7) : y; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('D? foo(X? x) { X ? x2 = x + bar(7) : y; }');
   }
 
   void test_conditional_error() {
@@ -2171,74 +2332,62 @@
           expectedError(ParserErrorCode.MISSING_IDENTIFIER, 19, 1),
           expectedError(ParserErrorCode.EXPECTED_TOKEN, 40, 1),
           expectedError(ParserErrorCode.MISSING_IDENTIFIER, 40, 1),
-        ],
-        featureSet: nonNullable);
+        ]);
   }
 
   void test_conditional_simple() {
-    parseCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }');
   }
 
   void test_enableNonNullable_false() {
     parseCompilationUnit('main() { x is String? ? (x + y) : z; }',
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 20, 1)]);
+        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 20, 1)],
+        featureSet: preNonNullable);
   }
 
   void test_for() {
-    parseCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }',
-        featureSet: nonNullable);
+    parseCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }');
   }
 
   void test_for_conditional() {
-    parseCompilationUnit('main() { for(x ? y = 7 : y = 8; y < 10; ++y) { } }',
-        featureSet: nonNullable);
+    parseCompilationUnit('main() { for(x ? y = 7 : y = 8; y < 10; ++y) { } }');
   }
 
   void test_for_nullable() {
-    parseCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }',
-        featureSet: nonNullable);
+    parseCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }');
   }
 
   void test_foreach() {
-    parseCompilationUnit('main() { for(int x in [7]) { } }',
-        featureSet: nonNullable);
+    parseCompilationUnit('main() { for(int x in [7]) { } }');
   }
 
   void test_foreach_nullable() {
-    parseCompilationUnit('main() { for(int? x in [7, null]) { } }',
-        featureSet: nonNullable);
+    parseCompilationUnit('main() { for(int? x in [7, null]) { } }');
   }
 
   void test_gft_nullable() {
-    parseCompilationUnit('main() { C? Function() x = 7; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('main() { C? Function() x = 7; }');
   }
 
   void test_gft_nullable_1() {
-    parseCompilationUnit('main() { C Function()? x = 7; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('main() { C Function()? x = 7; }');
   }
 
   void test_gft_nullable_2() {
-    parseCompilationUnit('main() { C? Function()? x = 7; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('main() { C? Function()? x = 7; }');
   }
 
   void test_gft_nullable_3() {
-    parseCompilationUnit('main() { C? Function()? Function()? x = 7; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('main() { C? Function()? Function()? x = 7; }');
   }
 
   void test_gft_nullable_prefixed() {
-    parseCompilationUnit('main() { C.a? Function()? x = 7; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('main() { C.a? Function()? x = 7; }');
   }
 
   void test_is_nullable() {
-    CompilationUnit unit = parseCompilationUnit(
-        'main() { x is String? ? (x + y) : z; }',
-        featureSet: nonNullable);
+    CompilationUnit unit =
+        parseCompilationUnit('main() { x is String? ? (x + y) : z; }');
     FunctionDeclaration function = unit.declarations[0];
     BlockFunctionBody body = function.functionExpression.body;
     ExpressionStatement statement = body.block.statements[0];
@@ -2253,9 +2402,8 @@
   }
 
   void test_is_nullable_parenthesis() {
-    CompilationUnit unit = parseCompilationUnit(
-        'main() { (x is String?) ? (x + y) : z; }',
-        featureSet: nonNullable);
+    CompilationUnit unit =
+        parseCompilationUnit('main() { (x is String?) ? (x + y) : z; }');
     FunctionDeclaration function = unit.declarations[0];
     BlockFunctionBody body = function.functionExpression.body;
     ExpressionStatement statement = body.block.statements[0];
@@ -2274,9 +2422,7 @@
     parseCompilationUnit('''
 // @dart = 2.2
 main() { (x is String?) ? (x + y) : z; }
-''',
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 36, 1)],
-        featureSet: nonNullable);
+''', errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 36, 1)]);
   }
 
   void test_late_as_identifier() {
@@ -2309,12 +2455,11 @@
 main() {
   f(new C());
 }
-''', featureSet: nonNullable);
+''');
   }
 
   void test_nullCheck() {
-    var unit = parseCompilationUnit('f(int? y) { var x = y!; }',
-        featureSet: nonNullable);
+    var unit = parseCompilationUnit('f(int? y) { var x = y!; }');
     FunctionDeclaration function = unit.declarations[0];
     BlockFunctionBody body = function.functionExpression.body;
     VariableDeclarationStatement statement = body.block.statements[0];
@@ -2338,23 +2483,36 @@
     expect(identifier.name, 'y');
   }
 
+  void test_nullCheckAfterGetterAccess() {
+    parseCompilationUnit('f() { var x = g.x!.y + 7; }');
+  }
+
+  void test_nullCheckAfterMethodCall() {
+    parseCompilationUnit('f() { var x = g.m()!.y + 7; }');
+  }
+
+  void test_nullCheckBeforeGetterAccess() {
+    parseCompilationUnit('f() { var x = g!.x + 7; }');
+  }
+
+  void test_nullCheckBeforeMethodCall() {
+    parseCompilationUnit('f() { var x = g!.m() + 7; }');
+  }
+
   void test_nullCheckFunctionResult() {
-    parseCompilationUnit('f() { var x = g()! + 7; }', featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = g()! + 7; }');
   }
 
   void test_nullCheckIndexedValue() {
-    parseCompilationUnit('f(int? y) { var x = y[0]! + 7; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('f(int? y) { var x = y[0]! + 7; }');
   }
 
   void test_nullCheckIndexedValue2() {
-    parseCompilationUnit('f(int? y) { var x = super.y[0]! + 7; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('f(int? y) { var x = super.y[0]! + 7; }');
   }
 
   void test_nullCheckInExpression() {
-    parseCompilationUnit('f(int? y) { var x = y! + 7; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('f(int? y) { var x = y! + 7; }');
   }
 
   void test_nullCheckInExpression_disabled() {
@@ -2367,28 +2525,23 @@
   }
 
   void test_nullCheckMethodResult() {
-    parseCompilationUnit('f() { var x = g.m()! + 7; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = g.m()! + 7; }');
   }
 
   void test_nullCheckMethodResult2() {
-    parseCompilationUnit('f() { var x = g?.m()! + 7; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = g?.m()! + 7; }');
   }
 
   void test_nullCheckMethodResult3() {
-    parseCompilationUnit('f() { var x = super.m()! + 7; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = super.m()! + 7; }');
   }
 
   void test_nullCheckOnConstConstructor() {
-    parseCompilationUnit('f() { var x = const Foo()!; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = const Foo()!; }');
   }
 
   void test_nullCheckOnConstructor() {
-    parseCompilationUnit('f() { var x = new Foo()!; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = new Foo()!; }');
   }
 
   void test_nullCheckOnLiteral_disabled() {
@@ -2399,47 +2552,46 @@
 
   void test_nullCheckOnLiteralDouble() {
     // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = 1.2!; }', featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = 1.2!; }');
   }
 
   void test_nullCheckOnLiteralInt() {
     // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = 0!; }', featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = 0!; }');
   }
 
   void test_nullCheckOnLiteralList() {
     // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = [1,2]!; }', featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = [1,2]!; }');
   }
 
   void test_nullCheckOnLiteralMap() {
     // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = {1:2}!; }', featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = {1:2}!; }');
   }
 
   void test_nullCheckOnLiteralSet() {
     // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = {1,2}!; }', featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = {1,2}!; }');
   }
 
   void test_nullCheckOnLiteralString() {
     // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = "seven"!; }', featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = "seven"!; }');
   }
 
   void test_nullCheckOnNull() {
     // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = null!; }', featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = null!; }');
   }
 
   void test_nullCheckOnSymbol() {
     // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = #seven!; }', featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = #seven!; }');
   }
 
   void test_nullCheckOnValue() {
-    parseCompilationUnit('f(Point p) { var x = p.y! + 7; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('f(Point p) { var x = p.y! + 7; }');
   }
 
   void test_nullCheckOnValue_disabled() {
@@ -2449,27 +2601,24 @@
   }
 
   void test_nullCheckParenthesizedExpression() {
-    parseCompilationUnit('f(int? y) { var x = (y)! + 7; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('f(int? y) { var x = (y)! + 7; }');
   }
 
   void test_nullCheckPropertyAccess() {
-    parseCompilationUnit('f() { var x = g.p! + 7; }', featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = g.p! + 7; }');
   }
 
   void test_nullCheckPropertyAccess2() {
-    parseCompilationUnit('f() { var x = g?.p! + 7; }', featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = g?.p! + 7; }');
   }
 
   void test_nullCheckPropertyAccess3() {
-    parseCompilationUnit('f() { var x = super.p! + 7; }',
-        featureSet: nonNullable);
+    parseCompilationUnit('f() { var x = super.p! + 7; }');
   }
 
   void test_postfix_null_assertion_and_unary_prefix_operator_precedence() {
     // -x! is parsed as -(x!).
-    var unit =
-        parseCompilationUnit('void main() { -x!; }', featureSet: nonNullable);
+    var unit = parseCompilationUnit('void main() { -x!; }');
     var function = unit.declarations[0] as FunctionDeclaration;
     var body = function.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
@@ -2481,8 +2630,7 @@
 
   void test_postfix_null_assertion_of_postfix_expression() {
     // x++! is parsed as (x++)!.
-    var unit =
-        parseCompilationUnit('void main() { x++!; }', featureSet: nonNullable);
+    var unit = parseCompilationUnit('void main() { x++!; }');
     var function = unit.declarations[0] as FunctionDeclaration;
     var body = function.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 1f29027..26edc07 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -1628,6 +1628,25 @@
     expect(initializer.period, isNull);
   }
 
+  void test_parseGetter_identifier_colon_issue_36961() {
+    createParser('get a:');
+    MethodDeclaration method = parser.parseClassMember('C');
+    expect(method, isNotNull);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_INITIALIZER, 5, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 6, 0),
+    ]);
+    expect(method.body, isNotNull);
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.parameters, isNull);
+    expect(method.propertyKeyword, isNotNull);
+    expect(method.returnType, isNull);
+  }
+
   void test_parseGetter_nonStatic() {
     createParser('/// Doc\nT get a;');
     MethodDeclaration method = parser.parseClassMember('C');
@@ -3234,7 +3253,7 @@
     ClassMember member = parser.parseClassMember('C');
     expectNotNullIfNoErrors(member);
     listener.assertErrors(
-        [expectedError(ParserErrorCode.EXTERNAL_AFTER_FACTORY, 8, 8)]);
+        [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 8, 8)]);
   }
 
   void test_externalAfterStatic() {
@@ -4394,7 +4413,7 @@
 
   void test_missingClassBody() {
     parseCompilationUnit("class A class B {}",
-        errors: [expectedError(ParserErrorCode.MISSING_CLASS_BODY, 8, 5)]);
+        errors: [expectedError(ParserErrorCode.MISSING_CLASS_BODY, 6, 1)]);
   }
 
   void test_missingClosingParenthesis() {
@@ -5310,7 +5329,7 @@
         parseStatement('switch (a) return;', expectedEndOffset: 11);
     expect(statement, isNotNull);
     listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 6)]
+        ? [expectedError(ParserErrorCode.EXPECTED_BODY, 9, 1)]
         : [
             expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 6),
             expectedError(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT, 11, 6),
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 7fa83ed..9cc2c26 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -170,7 +170,7 @@
 @reflectiveTest
 class ErrorResolverTest extends DriverResolutionTest {
   test_breakLabelOnSwitchMember() async {
-    assertErrorCodesInCode(r'''
+    assertErrorsInCode(r'''
 class A {
   void m(int i) {
     switch (i) {
@@ -180,11 +180,13 @@
         break l;
     }
   }
-}''', [ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER]);
+}''', [
+      error(ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER, 105, 1),
+    ]);
   }
 
   test_continueLabelOnSwitch() async {
-    assertErrorCodesInCode(r'''
+    assertErrorsInCode(r'''
 class A {
   void m(int i) {
     l: switch (i) {
@@ -192,7 +194,9 @@
         continue l;
     }
   }
-}''', [ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH]);
+}''', [
+      error(ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH, 79, 1),
+    ]);
   }
 
   test_enclosingElement_invalidLocalFunction() async {
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
index 47bfbff..de35b72 100644
--- a/pkg/analyzer/test/generated/simple_resolver_test.dart
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -993,7 +993,7 @@
     await resolveTestFile();
 
     var node = findNode.simple('myVar(42)');
-    assertType(node, '(int) → String');
+    assertType(node, 'String Function(int)');
   }
 
   test_metadata_class() async {
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index e261136..36b6c24 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -138,7 +138,7 @@
 }
 """;
     await resolveTestUnit(code);
-    expectIdentifierType("p()", '() → dynamic');
+    expectIdentifierType("p()", 'dynamic Function()');
   }
 
   test_staticMethods_classTypeParameters() async {
@@ -151,7 +151,7 @@
 }
 ''';
     await resolveTestUnit(code);
-    expectFunctionType('m);', '() → void');
+    expectFunctionType('m);', 'void Function()');
   }
 
   test_staticMethods_classTypeParameters_genericMethod() async {
@@ -170,29 +170,30 @@
     // C - m
     TypeParameterType typeS;
     {
-      FunctionTypeImpl type = expectFunctionType('m);', '<S>(S) → void',
+      FunctionTypeImpl type = expectFunctionType('m);', 'void Function<S>(S)',
           elementTypeParams: '[S]',
           typeFormals: '[S]',
-          identifierType: '<S>(S) → void');
+          identifierType: 'void Function<S>(S)');
 
       typeS = type.typeFormals[0].type;
       type = type.instantiate([DynamicTypeImpl.instance]);
-      expect(type.toString(), '(dynamic) → void');
+      expect(type.toString(), 'void Function(dynamic)');
       expect(type.typeParameters.toString(), '[S]');
       expect(type.typeArguments, [DynamicTypeImpl.instance]);
       expect(type.typeFormals, isEmpty);
     }
     // C - m - f
     {
-      FunctionTypeImpl type = expectFunctionType('f);', '<U>(S, U) → void',
+      FunctionTypeImpl type = expectFunctionType(
+          'f);', 'void Function<U>(S, U)',
           elementTypeParams: '[U]',
           typeParams: '[S]',
           typeArgs: '[S]',
           typeFormals: '[U]',
-          identifierType: '<U>(S, U) → void');
+          identifierType: 'void Function<U>(S, U)');
 
       type = type.instantiate([DynamicTypeImpl.instance]);
-      expect(type.toString(), '(S, dynamic) → void');
+      expect(type.toString(), 'void Function(S, dynamic)');
       expect(type.typeParameters.toString(), '[S, U]');
       expect(type.typeArguments, [typeS, DynamicTypeImpl.instance]);
       expect(type.typeFormals, isEmpty);
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 4d44cbd..1f4358e 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -2528,8 +2528,8 @@
 Couldn't infer type parameter 'T'.
 
 Tried to infer 'double' for 'T' which doesn't work:
-  Parameter 'f' declared as     '(T) → T'
-                but argument is '(int) → double'.
+  Parameter 'f' declared as     'T Function(T)'
+                but argument is 'double Function(int)'.
 
 Consider passing explicit type argument(s) to the generic.
 
@@ -2555,10 +2555,10 @@
 Couldn't infer type parameter 'T'.
 
 Tried to infer 'num' for 'T' which doesn't work:
-  Parameter 'a' declared as     '(T) → T'
-                but argument is '(int) → double'.
-  Parameter 'b' declared as     '(T) → T'
-                but argument is '(double) → int'.
+  Parameter 'a' declared as     'T Function(T)'
+                but argument is 'double Function(int)'.
+  Parameter 'b' declared as     'T Function(T)'
+                but argument is 'int Function(double)'.
 
 Consider passing explicit type argument(s) to the generic.
 
@@ -2585,7 +2585,7 @@
         .variables
         .variables[0];
     var call = h.initializer as MethodInvocation;
-    expect(call.staticInvokeType.toString(), '(Null, Null) → Null');
+    expect(call.staticInvokeType.toString(), 'Null Function(Null, Null)');
   }
 
   test_inference_error_extendsFromReturn2() async {
@@ -2606,8 +2606,8 @@
 Tried to infer 'String' for 'T' which doesn't work:
   Type parameter 'T' declared to extend 'num'.
 The type 'String' was inferred from:
-  Return type declared as '(T) → T'
-              used where  '(String) → String' is required.
+  Return type declared as 'T Function(T)'
+              used where  'String Function(String)' is required.
 
 Consider passing explicit type argument(s) to the generic.
 
@@ -2633,8 +2633,8 @@
 Couldn't infer type parameter 'T'.
 
 Tried to infer 'dynamic' for 'T' which doesn't work:
-  Function type declared as '<T extends num>(T, T) → T'
-                used where  '(num, dynamic) → num' is required.
+  Function type declared as 'T Function<T extends num>(T, T)'
+                used where  'num Function(num, dynamic)' is required.
 
 Consider passing explicit type argument(s) to the generic.
 
@@ -2656,8 +2656,8 @@
 Couldn't infer type parameter 'T'.
 
 Tried to infer 'num' for 'T' which doesn't work:
-  Return type declared as '(T) → T'
-              used where  '(num) → int' is required.
+  Return type declared as 'T Function(T)'
+              used where  'int Function(num)' is required.
 
 Consider passing explicit type argument(s) to the generic.
 
@@ -2700,7 +2700,8 @@
       MethodInvocation invoke = stmt.expression;
       FunctionType fType = invoke.staticInvokeType;
       if (AnalysisDriver.useSummary2) {
-        expect('$fType', '((T) → T, (T, T) → int, (T) → T) → void');
+        expect('$fType',
+            'void Function(T Function(T), int Function(T, T), T Function(T))');
       } else {
         expect(fType.typeArguments[0].toString(), 'T');
       }
@@ -2731,7 +2732,7 @@
       MethodInvocation invoke = stmt.expression;
       FunctionType fType = invoke.staticInvokeType;
       if (AnalysisDriver.useSummary2) {
-        expect('$fType', '(List<T>, (T, T) → int, List<T>) → void');
+        expect('$fType', 'void Function(List<T>, int Function(T, T), List<T>)');
       } else {
         expect(fType.typeArguments[0].toString(), 'T');
       }
@@ -2762,7 +2763,7 @@
       MethodInvocation invoke = stmt.expression;
       FunctionType fType = invoke.staticInvokeType;
       if (AnalysisDriver.useSummary2) {
-        expect('$fType', '(T, (T, T) → int, T) → void');
+        expect('$fType', 'void Function(T, int Function(T, T), T)');
       } else {
         expect(fType.typeArguments[0].toString(), 'T');
       }
@@ -2788,10 +2789,10 @@
         .variables[0];
     _isDynamic(h.declaredElement.type);
     var fCall = h.initializer as MethodInvocation;
-    expect(
-        fCall.staticInvokeType.toString(), '((dynamic) → dynamic) → dynamic');
+    expect(fCall.staticInvokeType.toString(),
+        'dynamic Function(dynamic Function(dynamic))');
     var g = fCall.argumentList.arguments[0];
-    expect(g.staticType.toString(), '(dynamic) → dynamic');
+    expect(g.staticType.toString(), 'dynamic Function(dynamic)');
   }
 
   test_inferGenericInstantiation2() async {
@@ -2816,11 +2817,11 @@
             .functionExpression
             .body as ExpressionFunctionBody)
         .expression as MethodInvocation;
-    expect(
-        fold.staticInvokeType.toString(), '(num, (num, dynamic) → num) → num');
+    expect(fold.staticInvokeType.toString(),
+        'num Function(num, num Function(num, dynamic))');
     var max = fold.argumentList.arguments[1];
-    // TODO(jmesserly): arguably (num, num) → num is better here.
-    expect(max.staticType.toString(), '(dynamic, dynamic) → dynamic');
+    // TODO(jmesserly): arguably num Function(num, num) is better here.
+    expect(max.staticType.toString(), 'dynamic Function(dynamic, dynamic)');
   }
 
   test_inferredFieldDeclaration_propagation() async {
@@ -3608,7 +3609,7 @@
     expect(typeName.type.toString(), 'A<T2, U2>');
 
     var constructorMember = redirected.staticElement;
-    expect(constructorMember.toString(), 'A.named() → A<T2, U2>');
+    expect(constructorMember.toString(), 'A<T2, U2> A.named()');
     expect(redirected.name.staticElement, constructorMember);
   }
 
@@ -3645,7 +3646,7 @@
     expect(typeName.type.toString(), 'A<T2, U2>');
 
     expect(redirected.name, isNull);
-    expect(redirected.staticElement.toString(), 'A() → A<T2, U2>');
+    expect(redirected.staticElement.toString(), 'A<T2, U2> A()');
   }
 
   test_redirectingConstructor_propagation() async {
@@ -3984,17 +3985,17 @@
 
   test_genericFunction() async {
     await resolveTestUnit(r'T f<T>(T x) => null;');
-    expectFunctionType('f', '<T>(T) → T',
+    expectFunctionType('f', 'T Function<T>(T)',
         elementTypeParams: '[T]', typeFormals: '[T]');
     SimpleIdentifier f = findIdentifier('f');
     FunctionElementImpl e = f.staticElement;
     FunctionType ft = e.type.instantiate([typeProvider.stringType]);
-    expect(ft.toString(), '(String) → String');
+    expect(ft.toString(), 'String Function(String)');
   }
 
   test_genericFunction_bounds() async {
     await resolveTestUnit(r'T f<T extends num>(T x) => null;');
-    expectFunctionType('f', '<T extends num>(T) → T',
+    expectFunctionType('f', 'T Function<T extends num>(T)',
         elementTypeParams: '[T extends num]', typeFormals: '[T extends num]');
   }
 
@@ -4005,9 +4006,9 @@
     await resolveTestUnit(r'''
 void g(T f<T>(T x)) {}
 ''');
-    var type = expectFunctionType2('f', '<T>(T) → T');
+    var type = expectFunctionType2('f', 'T Function<T>(T)');
     FunctionType ft = type.instantiate([typeProvider.stringType]);
-    expect(ft.toString(), '(String) → String');
+    expect(ft.toString(), 'String Function(String)');
   }
 
   test_genericFunction_static() async {
@@ -4016,12 +4017,12 @@
   static T f<T>(T x) => null;
 }
 ''');
-    expectFunctionType('f', '<T>(T) → T',
+    expectFunctionType('f', 'T Function<T>(T)',
         elementTypeParams: '[T]', typeFormals: '[T]');
     SimpleIdentifier f = findIdentifier('f');
     MethodElementImpl e = f.staticElement;
     FunctionType ft = e.type.instantiate([typeProvider.stringType]);
-    expect(ft.toString(), '(String) → String');
+    expect(ft.toString(), 'String Function(String)');
   }
 
   test_genericFunction_typedef() async {
@@ -4102,16 +4103,16 @@
   C<String> cOfString;
 }
 ''');
-    expectFunctionType('f', '<T>(E) → List<T>',
+    expectFunctionType('f', 'List<T> Function<T>(E)',
         elementTypeParams: '[T]',
         typeParams: '[E]',
         typeArgs: '[E]',
         typeFormals: '[T]');
     SimpleIdentifier c = findIdentifier('cOfString');
     FunctionType ft = (c.staticType as InterfaceType).getMethod('f').type;
-    expect(ft.toString(), '<T>(String) → List<T>');
+    expect(ft.toString(), 'List<T> Function<T>(String)');
     ft = ft.instantiate([typeProvider.intType]);
-    expect(ft.toString(), '(String) → List<int>');
+    expect(ft.toString(), 'List<int> Function(String)');
     expect('${ft.typeArguments}/${ft.typeParameters}', '[String, int]/[E, T]');
   }
 
@@ -4127,7 +4128,7 @@
 ''');
     MethodInvocation f = findIdentifier('f<int>').parent;
     FunctionType ft = f.staticInvokeType;
-    expect(ft.toString(), '(String) → List<int>');
+    expect(ft.toString(), 'List<int> Function(String)');
     expect('${ft.typeArguments}/${ft.typeParameters}', '[String, int]/[E, T]');
 
     SimpleIdentifier x = findIdentifier('x');
@@ -4325,7 +4326,7 @@
   C<String> cOfString;
 }
 ''');
-    expectFunctionType('f', '<T>((E) → T) → List<T>',
+    expectFunctionType('f', 'List<T> Function<T>(T Function(E))',
         elementTypeParams: '[T]',
         typeParams: '[E]',
         typeArgs: '[E]',
@@ -4333,9 +4334,9 @@
 
     SimpleIdentifier c = findIdentifier('cOfString');
     FunctionType ft = (c.staticType as InterfaceType).getMethod('f').type;
-    expect(ft.toString(), '<T>((String) → T) → List<T>');
+    expect(ft.toString(), 'List<T> Function<T>(T Function(String))');
     ft = ft.instantiate([typeProvider.intType]);
-    expect(ft.toString(), '((String) → int) → List<int>');
+    expect(ft.toString(), 'List<int> Function(int Function(String))');
   }
 
   test_genericMethod_functionTypedParameter_tearoff() async {
@@ -4347,7 +4348,7 @@
   var paramTearOff = pf;
 }
 ''');
-    expectIdentifierType('paramTearOff', "<T>(T) → T");
+    expectIdentifierType('paramTearOff', "T Function<T>(T)");
   }
 
   test_genericMethod_implicitDynamic() async {
@@ -4363,13 +4364,17 @@
   list.map((e) => e);
   list.map((e) => 3);
 }''');
-    expectIdentifierType('map((e) => e);', '<T>((dynamic) → T) → T');
-    expectIdentifierType('map((e) => 3);', '<T>((dynamic) → T) → T');
+    expectIdentifierType(
+        'map((e) => e);', 'T Function<T>(T Function(dynamic))');
+    expectIdentifierType(
+        'map((e) => 3);', 'T Function<T>(T Function(dynamic))');
 
     MethodInvocation m1 = findIdentifier('map((e) => e);').parent;
-    expect(m1.staticInvokeType.toString(), '((dynamic) → dynamic) → dynamic');
+    expect(m1.staticInvokeType.toString(),
+        'dynamic Function(dynamic Function(dynamic))');
     MethodInvocation m2 = findIdentifier('map((e) => 3);').parent;
-    expect(m2.staticInvokeType.toString(), '((dynamic) → int) → int');
+    expect(
+        m2.staticInvokeType.toString(), 'int Function(int Function(dynamic))');
   }
 
   test_genericMethod_max_doubleDouble() async {
@@ -4450,11 +4455,11 @@
 }
 ''');
     MethodInvocation f = findIdentifier('f<int>(3);').parent;
-    expect(f.staticInvokeType.toString(), '(int) → S');
+    expect(f.staticInvokeType.toString(), 'S Function(int)');
     FunctionType ft = f.staticInvokeType;
     expect('${ft.typeArguments}/${ft.typeParameters}', '[S, int]/[T, S]');
 
-    expectIdentifierType('f;', '<Sâ‚€>(Sâ‚€) → S');
+    expectIdentifierType('f;', 'S Function<Sâ‚€>(Sâ‚€)');
   }
 
   @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/30236')
@@ -4469,12 +4474,12 @@
 }
 ''');
     MethodInvocation f = findIdentifier('f<int>(3);').parent;
-    expect(f.staticInvokeType.toString(), '(int) → S');
+    expect(f.staticInvokeType.toString(), 'S Function(int)');
     FunctionType ft = f.staticInvokeType;
     expect('${ft.typeArguments}/${ft.typeParameters}',
         '[S, int]/[T, S extends T]');
 
-    expectIdentifierType('f;', '<Sâ‚€ extends S>(Sâ‚€) → S');
+    expectIdentifierType('f;', 'S Function<Sâ‚€ extends S>(Sâ‚€)');
   }
 
   test_genericMethod_nestedFunctions() async {
@@ -4484,8 +4489,8 @@
   return null;
 }
 ''');
-    expectIdentifierType('f', '<S>(S) → S');
-    expectIdentifierType('g', '<S>(S) → <S>(S) → S');
+    expectIdentifierType('f', 'S Function<S>(S)');
+    expectIdentifierType('g', 'S Function<S>(S) Function<S>(S)');
   }
 
   test_genericMethod_override() async {
@@ -4497,12 +4502,12 @@
   T f<T>(T x) => null; // from D
 }
 ''');
-    expectFunctionType('f<T>(T x) => null; // from D', '<T>(T) → T',
+    expectFunctionType('f<T>(T x) => null; // from D', 'T Function<T>(T)',
         elementTypeParams: '[T]', typeFormals: '[T]');
     SimpleIdentifier f = findIdentifier('f<T>(T x) => null; // from D');
     MethodElementImpl e = f.staticElement;
     FunctionType ft = e.type.instantiate([typeProvider.stringType]);
-    expect(ft.toString(), '(String) → String');
+    expect(ft.toString(), 'String Function(String)');
   }
 
   test_genericMethod_override_bounds() async {
@@ -4658,13 +4663,13 @@
   var paramTearOff = pf;
 }
 ''');
-    expectIdentifierType('methodTearOff', "<T>(int) → T");
-    expectIdentifierType('staticTearOff', "<T>(T) → T");
-    expectIdentifierType('staticFieldTearOff', "<T>(T) → T");
-    expectIdentifierType('topFunTearOff', "<T>(T) → T");
-    expectIdentifierType('topFieldTearOff', "<T>(T) → T");
-    expectIdentifierType('localTearOff', "<T>(T) → T");
-    expectIdentifierType('paramTearOff', "<T>(T) → T");
+    expectIdentifierType('methodTearOff', "T Function<T>(int)");
+    expectIdentifierType('staticTearOff', "T Function<T>(T)");
+    expectIdentifierType('staticFieldTearOff', "T Function<T>(T)");
+    expectIdentifierType('topFunTearOff', "T Function<T>(T)");
+    expectIdentifierType('topFieldTearOff', "T Function<T>(T)");
+    expectIdentifierType('localTearOff', "T Function<T>(T)");
+    expectIdentifierType('paramTearOff', "T Function<T>(T)");
   }
 
   @failingTest
@@ -4690,13 +4695,13 @@
   var paramTearOffInst = pf<int>;
 }
 ''');
-    expectIdentifierType('methodTearOffInst', "(int) → int");
-    expectIdentifierType('staticTearOffInst', "(int) → int");
-    expectIdentifierType('staticFieldTearOffInst', "(int) → int");
-    expectIdentifierType('topFunTearOffInst', "(int) → int");
-    expectIdentifierType('topFieldTearOffInst', "(int) → int");
-    expectIdentifierType('localTearOffInst', "(int) → int");
-    expectIdentifierType('paramTearOffInst', "(int) → int");
+    expectIdentifierType('methodTearOffInst', "int Function(int)");
+    expectIdentifierType('staticTearOffInst', "int Function(int)");
+    expectIdentifierType('staticFieldTearOffInst', "int Function(int)");
+    expectIdentifierType('topFunTearOffInst', "int Function(int)");
+    expectIdentifierType('topFieldTearOffInst', "int Function(int)");
+    expectIdentifierType('localTearOffInst', "int Function(int)");
+    expectIdentifierType('paramTearOffInst', "int Function(int)");
   }
 
   test_genericMethod_then() async {
@@ -4754,7 +4759,7 @@
   var fieldRead = C.h;
 }
 ''');
-    expectIdentifierType('fieldRead', "<T>(T) → T");
+    expectIdentifierType('fieldRead', "T Function<T>(T)");
   }
 
   test_implicitBounds() async {
@@ -4876,7 +4881,7 @@
 ''';
     await resolveTestUnit(code, noErrors: false);
     assertNoErrors(testSource);
-    expectIdentifierType('c;', 'C<(dynamic) → dynamic>');
+    expectIdentifierType('c;', 'C<dynamic Function(dynamic)>');
   }
 
   test_instantiateToBounds_class_ok_implicitDynamic_multi() async {
@@ -4979,7 +4984,7 @@
 ''';
     await resolveTestUnit(code);
     assertNoErrors(testSource);
-    expectStaticInvokeType('m(null', '(Null, Null) → void');
+    expectStaticInvokeType('m(null', 'void Function(Null, Null)');
   }
 
   test_instantiateToBounds_method_ok_referenceOther_before2() async {
@@ -4994,7 +4999,7 @@
 ''';
     await resolveTestUnit(code);
     assertNoErrors(testSource);
-    expectStaticInvokeType('m();', '() → Map<T, List<T>>');
+    expectStaticInvokeType('m();', 'Map<T, List<T>> Function()');
   }
 
   test_instantiateToBounds_method_ok_simpleBounds() async {
@@ -5009,7 +5014,7 @@
 ''';
     await resolveTestUnit(code);
     assertNoErrors(testSource);
-    expectStaticInvokeType('m(null)', '(Null) → void');
+    expectStaticInvokeType('m(null)', 'void Function(Null)');
   }
 
   test_instantiateToBounds_method_ok_simpleBounds2() async {
@@ -5024,7 +5029,7 @@
 ''';
     await resolveTestUnit(code);
     assertNoErrors(testSource);
-    expectStaticInvokeType('m();', '() → T');
+    expectStaticInvokeType('m();', 'T Function()');
   }
 
   test_issue32396() async {
@@ -5430,10 +5435,10 @@
   Future<void> _objectMethodOnFunctions_helper2(String code) async {
     await resolveTestUnit(code);
     expectIdentifierType('t0', "String");
-    expectIdentifierType('t1', "() → String");
+    expectIdentifierType('t1', "String Function()");
     expectIdentifierType('t2', "int");
     expectIdentifierType('t3', "String");
-    expectIdentifierType('t4', "() → String");
+    expectIdentifierType('t4', "String Function()");
     expectIdentifierType('t5', "int");
   }
 }
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index 9084e64..16599ec 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -4,6 +4,7 @@
 
 // Tests related to the [TypeSystem] class.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart' show astFactory;
 import 'package:analyzer/dart/ast/token.dart' show Keyword;
 import 'package:analyzer/dart/element/element.dart';
@@ -32,6 +33,7 @@
     defineReflectiveTests(ConstraintMatchingTest);
     defineReflectiveTests(StrongAssignabilityTest);
     defineReflectiveTests(StrongSubtypingTest);
+    defineReflectiveTests(NonNullableSubtypingTest);
     defineReflectiveTests(StrongGenericFunctionInferenceTest);
     defineReflectiveTests(StrongLeastUpperBoundTest);
     defineReflectiveTests(StrongGreatestLowerBoundTest);
@@ -78,6 +80,7 @@
   InterfaceType get intType => typeProvider.intType;
   InterfaceType get iterableType => typeProvider.iterableType;
   InterfaceType get listType => typeProvider.listType;
+  InterfaceType get nullType => typeProvider.nullType;
   InterfaceType get numType => typeProvider.numType;
   InterfaceType get objectType => typeProvider.objectType;
   InterfaceType get stringType => typeProvider.stringType;
@@ -850,6 +853,94 @@
 }
 
 @reflectiveTest
+class NonNullableSubtypingTest extends StrongSubtypingTestBase {
+  @override
+  void setUp() {
+    typeProvider = AnalysisContextFactory.contextWithCoreAndOptions(
+            new AnalysisOptionsImpl()
+              ..contextFeatures = FeatureSet.forTesting(
+                  additionalFeatures: [Feature.non_nullable]),
+            resourceProvider: new MemoryResourceProvider())
+        .typeProvider;
+
+    // TypeSystem should use the context type provider.
+    typeSystem = new Dart2TypeSystem(typeProvider);
+
+    LibraryElement coreLibrary = typeProvider.objectType.element.library;
+    LibraryElement asyncLibrary = typeProvider.streamType.element.library;
+
+    // Get a non-nullable type provider for convience during the test.
+    typeProvider = new NonNullableTypeProvider(coreLibrary, asyncLibrary);
+  }
+
+  void test_int_nullableTypes() {
+    List<DartType> equivalents = <DartType>[
+      intType,
+      _star(intType),
+    ];
+    List<DartType> supertypes = <DartType>[
+      _question(intType),
+      objectType,
+      _question(objectType),
+    ];
+    List<DartType> unrelated = <DartType>[doubleType, nullType];
+    _checkGroups(intType,
+        equivalents: equivalents, supertypes: supertypes, unrelated: unrelated);
+  }
+
+  void test_intQuestion_nullableTypes() {
+    List<DartType> equivalents = <DartType>[
+      _question(intType),
+      _star(intType),
+    ];
+    List<DartType> subtypes = <DartType>[
+      intType,
+      nullType,
+    ];
+    List<DartType> supertypes = <DartType>[
+      _question(numType),
+      _star(numType),
+      _question(objectType),
+      _star(objectType),
+    ];
+    List<DartType> unrelated = <DartType>[doubleType, numType, objectType];
+    _checkGroups(_question(intType),
+        equivalents: equivalents,
+        supertypes: supertypes,
+        unrelated: unrelated,
+        subtypes: subtypes);
+  }
+
+  void test_intStar_nullableTypes() {
+    List<DartType> equivalents = <DartType>[
+      intType,
+      _question(intType),
+      _star(intType),
+    ];
+    List<DartType> subtypes = <DartType>[nullType];
+    List<DartType> supertypes = <DartType>[
+      numType,
+      _question(numType),
+      _star(numType),
+      objectType,
+      _question(objectType),
+    ];
+    List<DartType> unrelated = <DartType>[doubleType];
+    _checkGroups(_star(intType),
+        equivalents: equivalents,
+        supertypes: supertypes,
+        unrelated: unrelated,
+        subtypes: subtypes);
+  }
+
+  DartType _question(DartType dartType) =>
+      (dartType as TypeImpl).withNullability(NullabilitySuffix.question);
+
+  DartType _star(DartType dartType) =>
+      (dartType as TypeImpl).withNullability(NullabilitySuffix.star);
+}
+
+@reflectiveTest
 class StrongAssignabilityTest extends AbstractTypeSystemTest {
   void test_isAssignableTo_bottom_isBottom() {
     DartType interfaceType = ElementFactory.classElement2('A', []).type;
@@ -1852,29 +1943,7 @@
 }
 
 @reflectiveTest
-class StrongSubtypingTest {
-  TypeProvider typeProvider;
-  TypeSystem typeSystem;
-
-  DartType get bottomType => typeProvider.bottomType;
-  InterfaceType get doubleType => typeProvider.doubleType;
-  DartType get dynamicType => typeProvider.dynamicType;
-  InterfaceType get functionType => typeProvider.functionType;
-  InterfaceType get futureOrType => typeProvider.futureOrType;
-  InterfaceType get intType => typeProvider.intType;
-  InterfaceType get listType => typeProvider.listType;
-  InterfaceType get numType => typeProvider.numType;
-  InterfaceType get objectType => typeProvider.objectType;
-  InterfaceType get stringType => typeProvider.stringType;
-  DartType get voidType => VoidTypeImpl.instance;
-
-  void setUp() {
-    typeProvider = AnalysisContextFactory.contextWithCore(
-            resourceProvider: new MemoryResourceProvider())
-        .typeProvider;
-    typeSystem = new Dart2TypeSystem(typeProvider);
-  }
-
+class StrongSubtypingTest extends StrongSubtypingTestBase {
   void test_bottom_isBottom() {
     DartType interfaceType = ElementFactory.classElement2('A', []).type;
     List<DartType> equivalents = <DartType>[bottomType];
@@ -2184,6 +2253,31 @@
     ];
     _checkGroups(voidType, equivalents: equivalents, subtypes: subtypes);
   }
+}
+
+class StrongSubtypingTestBase {
+  TypeProvider typeProvider;
+  TypeSystem typeSystem;
+
+  DartType get bottomType => typeProvider.bottomType;
+  InterfaceType get doubleType => typeProvider.doubleType;
+  DartType get dynamicType => typeProvider.dynamicType;
+  InterfaceType get functionType => typeProvider.functionType;
+  InterfaceType get futureOrType => typeProvider.futureOrType;
+  InterfaceType get intType => typeProvider.intType;
+  InterfaceType get listType => typeProvider.listType;
+  DartType get nullType => typeProvider.nullType;
+  InterfaceType get numType => typeProvider.numType;
+  InterfaceType get objectType => typeProvider.objectType;
+  InterfaceType get stringType => typeProvider.stringType;
+  DartType get voidType => VoidTypeImpl.instance;
+
+  void setUp() {
+    typeProvider = AnalysisContextFactory.contextWithCore(
+            resourceProvider: new MemoryResourceProvider())
+        .typeProvider;
+    typeSystem = new Dart2TypeSystem(typeProvider);
+  }
 
   void _checkEquivalent(DartType type1, DartType type2) {
     _checkIsSubtypeOf(type1, type2);
@@ -2218,7 +2312,8 @@
   }
 
   void _checkIsNotSubtypeOf(DartType type1, DartType type2) {
-    expect(typeSystem.isSubtypeOf(type1, type2), false);
+    expect(typeSystem.isSubtypeOf(type1, type2), false,
+        reason: '$type1 was not supposed to be a subtype of $type2');
   }
 
   void _checkIsStrictSubtypeOf(DartType type1, DartType type2) {
@@ -2227,7 +2322,8 @@
   }
 
   void _checkIsSubtypeOf(DartType type1, DartType type2) {
-    expect(typeSystem.isSubtypeOf(type1, type2), true);
+    expect(typeSystem.isSubtypeOf(type1, type2), true,
+        reason: '$type1 is not a subtype of $type2');
   }
 
   void _checkLattice(
diff --git a/pkg/analyzer/test/snippets/README.md b/pkg/analyzer/test/snippets/README.md
new file mode 100644
index 0000000..aab390e
--- /dev/null
+++ b/pkg/analyzer/test/snippets/README.md
@@ -0,0 +1 @@
+The 'snippets' directory exists to enable the test in 'verify_docs_test.dart'.
\ No newline at end of file
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index 73fc758..40d5bc6 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -637,7 +637,7 @@
 
     SimpleIdentifier constructorName = annotation.constructorName;
     expect(constructorName.staticElement, same(constructor));
-    expect(constructorName.staticType.toString(), '(int, {b: int}) → A');
+    expect(constructorName.staticType.toString(), 'A Function(int, {b: int})');
 
     var arguments = annotation.arguments.arguments;
     var parameters = constructor.parameters;
@@ -764,7 +764,8 @@
     expect(prefixed.prefix.staticType, aClass.type);
 
     expect(prefixed.identifier.staticElement, same(constructor));
-    expect(prefixed.identifier.staticType.toString(), '(int, {b: int}) → A');
+    expect(
+        prefixed.identifier.staticType.toString(), 'A Function(int, {b: int})');
 
     expect(annotation.constructorName, isNull);
 
@@ -1080,7 +1081,7 @@
       SimpleIdentifier forTarget = forInvocation.target;
       expect(forTarget.staticElement, itemsElement);
 
-      var closureTypeStr = '(int) → Null';
+      var closureTypeStr = 'Null Function(int)';
       FunctionExpression closure = forInvocation.argumentList.arguments[0];
 
       FunctionElementImpl closureElement = closure.declaredElement;
@@ -1121,7 +1122,7 @@
       SimpleIdentifier forTarget = forInvocation.target;
       expect(forTarget.staticElement, itemsElement);
 
-      var closureTypeStr = '(int) → Null';
+      var closureTypeStr = 'Null Function(int)';
       FunctionExpression closure = forInvocation.argumentList.arguments[0];
 
       FunctionElementImpl closureElement = closure.declaredElement;
@@ -1166,7 +1167,7 @@
     await resolveTestFile();
 
     var closure = findNode.functionExpression('<T>() =>');
-    assertType(closure, '<T>() → List<T>');
+    assertType(closure, 'List<T> Function<T>()');
 
     FunctionElementImpl closureElement = closure.declaredElement;
     expect(closureElement.enclosingElement, findElement.function('main'));
@@ -1546,7 +1547,7 @@
 
     var invocation = findNode.methodInvocation('loadLibrary');
     assertType(invocation, 'Future<dynamic>');
-    assertInvokeType(invocation, '() → Future<dynamic>');
+    assertInvokeType(invocation, 'Future<dynamic> Function()');
 
     SimpleIdentifier target = invocation.target;
     assertElement(target, import.prefix);
@@ -1554,7 +1555,7 @@
 
     var name = invocation.methodName;
     assertElement(name, import.importedLibrary.loadLibraryFunction);
-    assertType(name, '() → Future<dynamic>');
+    assertType(name, 'Future<dynamic> Function()');
   }
 
   @failingTest
@@ -1573,7 +1574,7 @@
 
     var invocation = findNode.methodInvocation('loadLibrary');
     assertType(invocation, 'Future<dynamic>');
-    assertInvokeType(invocation, '() → Future<dynamic>');
+    assertInvokeType(invocation, 'Future<dynamic> Function()');
 
     SimpleIdentifier target = invocation.target;
     assertElement(target, import.prefix);
@@ -1581,7 +1582,7 @@
 
     var name = invocation.methodName;
     assertElement(name, import.importedLibrary.loadLibraryFunction);
-    assertType(name, '() → Future<dynamic>');
+    assertType(name, 'Future<dynamic> Function()');
 
     var bRef = invocation.argumentList.arguments[0];
     assertElement(bRef, findElement.topGet('b'));
@@ -1604,7 +1605,7 @@
     var import = findElement.import('package:test/a.dart');
 
     var prefixed = findNode.prefixed('a.loadLibrary');
-    assertType(prefixed, '() → Future<dynamic>');
+    assertType(prefixed, 'Future<dynamic> Function()');
 
     var prefix = prefixed.prefix;
     assertElement(prefix, import.prefix);
@@ -1612,7 +1613,7 @@
 
     var identifier = prefixed.identifier;
     assertElement(identifier, import.importedLibrary.loadLibraryFunction);
-    assertType(identifier, '() → Future<dynamic>');
+    assertType(identifier, 'Future<dynamic> Function()');
   }
 
   test_deferredImport_variable() async {
@@ -1815,7 +1816,7 @@
 
     ExpressionStatement statement = mainStatements[0];
     MethodInvocation invocation = statement.expression;
-    expect(invocation.staticInvokeType.toString(), '() → String');
+    expect(invocation.staticInvokeType.toString(), 'String Function()');
 
     MethodElement methodElement = invocation.methodName.staticElement;
     expect(methodElement.name, 'toString');
@@ -1945,7 +1946,7 @@
     expect(p.declaredElement, same(pElement));
 
     expect(p.identifier.staticElement, same(pElement));
-    expect(p.identifier.staticType.toString(), '(int) → String');
+    expect(p.identifier.staticType.toString(), 'String Function(int)');
 
     {
       FunctionType type = p.identifier.staticType;
@@ -2044,7 +2045,7 @@
 
     ExpressionStatement statement = mainStatements[0];
     MethodInvocation invocation = statement.expression;
-    expect(invocation.staticInvokeType.toString(), '(int) → void');
+    expect(invocation.staticInvokeType.toString(), 'void Function(int)');
     // TODO(scheglov) Check for MethodElement
 //    expect(invocation.methodName.staticElement, same(mElement));
   }
@@ -2080,7 +2081,7 @@
     FunctionExpressionInvocation invocation = statement.expression;
 
     expect(invocation.staticElement, isNull);
-    expect(invocation.staticInvokeType.toString(), '(String) → int');
+    expect(invocation.staticInvokeType.toString(), 'int Function(String)');
     expect(invocation.staticType, typeProvider.intType);
 
     List<TypeAnnotation> typeArguments = invocation.typeArguments.arguments;
@@ -2107,7 +2108,7 @@
 ''');
     await resolveTestFile();
     var f = findNode.simple('f;');
-    assertType(f, '<T>(T) → void');
+    assertType(f, 'void Function<T>(T)');
     var fType = f.staticType as FunctionType;
     var fTypeTypeParameter = fType.typeFormals[0];
     var fTypeParameter = fType.normalParameterTypes[0] as TypeParameterType;
@@ -2710,7 +2711,7 @@
 
     var invocation = findNode.methodInvocation('codeUnitAt');
     assertType(invocation, 'int');
-    assertInvokeType(invocation, '(int) → int');
+    assertInvokeType(invocation, 'int Function(int)');
     assertElement(invocation.methodName, stringElement.getMethod('codeUnitAt'));
 
     var aRef = invocation.target;
@@ -2734,7 +2735,7 @@
 
     var invocation = findNode.methodInvocation('m();');
     assertType(invocation, 'int');
-    assertInvokeType(invocation, '() → int');
+    assertInvokeType(invocation, 'int Function()');
     assertElement(invocation.methodName, findElement.method('m'));
   }
 
@@ -2750,7 +2751,7 @@
 
     var invocation = findNode.methodInvocation('id(');
     assertType(invocation, 'bool');
-    assertInvokeType(invocation, '(Object, Object) → bool');
+    assertInvokeType(invocation, 'bool Function(Object, Object)');
     assertElement(invocation.methodName, findElement.topGet('id'));
 
     var aRef = invocation.argumentList.arguments[0];
@@ -3042,7 +3043,7 @@
 
     var aRef = findNode.simple('a + 1');
     assertElement(aRef, findElement.method('a'));
-    assertType(aRef, '() → int');
+    assertType(aRef, 'int Function()');
   }
 
   test_invalid_fieldInitializer_this() async {
@@ -3355,7 +3356,7 @@
 
     var invocation = findNode.methodInvocation('m(a)');
     assertElement(invocation.methodName, m);
-    assertType(invocation.methodName, '() → void');
+    assertType(invocation.methodName, 'void Function()');
     assertType(invocation, 'void');
 
     var aRef = invocation.argumentList.arguments[0];
@@ -3377,7 +3378,7 @@
 
     var invocation = findNode.methodInvocation('f(p: a');
     assertElement(invocation.methodName, f);
-    assertType(invocation.methodName, '({p: dynamic}) → void');
+    assertType(invocation.methodName, 'void Function({p: dynamic})');
     assertType(invocation, 'void');
 
     NamedExpression arg0 = invocation.argumentList.arguments[0];
@@ -3403,7 +3404,7 @@
 
     var invocation = findNode.methodInvocation('f(p: a');
     assertElement(invocation.methodName, f);
-    assertType(invocation.methodName, '({p: dynamic}) → void');
+    assertType(invocation.methodName, 'void Function({p: dynamic})');
     assertType(invocation, 'void');
 
     NamedExpression arg0 = invocation.argumentList.arguments[0];
@@ -3450,7 +3451,7 @@
 
     var invocation = findNode.methodInvocation('m(a)');
     assertElement(invocation.methodName, m);
-    assertType(invocation.methodName, '() → void');
+    assertType(invocation.methodName, 'void Function()');
     assertType(invocation, 'void');
 
     var aRef = invocation.argumentList.arguments[0];
@@ -3496,7 +3497,7 @@
 
     var invocation = findNode.methodInvocation('f(a)');
     assertElement(invocation.methodName, f);
-    assertType(invocation.methodName, '() → void');
+    assertType(invocation.methodName, 'void Function()');
     assertType(invocation, 'void');
 
     var aRef = invocation.argumentList.arguments[0];
@@ -3518,7 +3519,7 @@
 
     var invocation = findNode.methodInvocation('f(a)');
     assertElement(invocation.methodName, f);
-    assertType(invocation.methodName, '() → void');
+    assertType(invocation.methodName, 'void Function()');
     assertType(invocation, 'void');
 
     var aRef = invocation.argumentList.arguments[0];
@@ -4032,7 +4033,7 @@
   var v = f(1, '2');
 }
 ''');
-    String fTypeString = '(int, String) → double';
+    String fTypeString = 'double Function(int, String)';
 
     await resolveTestFile();
     List<Statement> mainStatements = _getMainStatements(result);
@@ -4139,7 +4140,7 @@
     }
 
     expect(fElement, isNotNull);
-    expect(fElement.type.toString(), '<T,U>(T, U) → T');
+    expect(fElement.type.toString(), 'T Function<T,U>(T, U)');
 
     expect(fNode.name.staticElement, same(fElement));
     expect(fNode.name.staticType, fElement.type);
@@ -4187,7 +4188,8 @@
     expect(fInvocation.staticType, typeProvider.intType);
 
     assertTypeNull(fInvocation.methodName);
-    expect(fInvocation.staticInvokeType.toString(), '(int, String) → int');
+    expect(
+        fInvocation.staticInvokeType.toString(), 'int Function(int, String)');
   }
 
   test_local_function_generic_f_bounded() async {
@@ -4204,7 +4206,7 @@
     FunctionElement fElement = fNode.declaredElement;
 
     expect(fElement.type.toString(),
-        '<T extends U,U,V extends U>(T, U, V) → void');
+        'void Function<T extends U,U,V extends U>(T, U, V)');
     var tElement = fElement.typeParameters[0];
     var uElement = fElement.typeParameters[1];
     var vElement = fElement.typeParameters[2];
@@ -4225,7 +4227,7 @@
     FunctionDeclaration fNode = fStatement.functionDeclaration;
     FunctionElement fElement = fNode.declaredElement;
 
-    expect(fElement.type.toString(), '<T>({x: T}) → void');
+    expect(fElement.type.toString(), 'void Function<T>({x: T})');
     var tElement = fElement.typeParameters[0];
     expect(fElement.type.typeFormals[0], same(tElement));
     expect((fElement.type.parameters[0].type as TypeParameterType).element,
@@ -4245,7 +4247,7 @@
     FunctionDeclaration fNode = fStatement.functionDeclaration;
     FunctionElement fElement = fNode.declaredElement;
 
-    expect(fElement.type.toString(), '<T>([T]) → void');
+    expect(fElement.type.toString(), 'void Function<T>([T])');
     var tElement = fElement.typeParameters[0];
     expect(fElement.type.typeFormals[0], same(tElement));
     expect((fElement.type.parameters[0].type as TypeParameterType).element,
@@ -4259,7 +4261,7 @@
   f(1, b: '2', c: true);
 }
 ''');
-    String fTypeString = '(int, {b: String, c: bool}) → double';
+    String fTypeString = 'double Function(int, {b: String, c: bool})';
 
     await resolveTestFile();
     List<Statement> mainStatements = _getMainStatements(result);
@@ -4336,7 +4338,7 @@
 
     expect(fNode.returnType, isNull);
     expect(fElement, isNotNull);
-    expect(fElement.type.toString(), '() → Null');
+    expect(fElement.type.toString(), 'Null Function()');
 
     expect(fNode.name.staticElement, same(fElement));
     expect(fNode.name.staticType, fElement.type);
@@ -4351,7 +4353,7 @@
   var v = f(1, '2', true);
 }
 ''');
-    String fTypeString = '(int, [String, bool]) → double';
+    String fTypeString = 'double Function(int, [String, bool])';
 
     await resolveTestFile();
     List<Statement> mainStatements = _getMainStatements(result);
@@ -4429,7 +4431,7 @@
 ''');
     await resolveTestFile();
     var callback = findNode.simple('callback');
-    assertType(callback, '<T extends E>(D) → C');
+    assertType(callback, 'C Function<T extends E>(D)');
     var cReference = findNode.simple('C callback');
     var cElement = findElement.class_('C');
     assertType(cReference, 'C');
@@ -4748,20 +4750,20 @@
 ''');
     await resolveTestFile();
 
-    var mainStatements = _getMainStatements(result);
-    var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
-    var fElement = fDeclaration.functionDeclaration.declaredElement;
-    var tElement = fElement.typeParameters[0];
-    var body = fDeclaration.functionDeclaration.functionExpression.body
-        as BlockFunctionBody;
-    var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
-    var gType = gDeclaration.variables.type as TypeName;
+    var tElement = findNode.typeParameter('T>(T x)').declaredElement;
+
+    var gType = findNode.typeName('Consumer<T>');
     var gTypeType = gType.type as FunctionType;
-    var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
-    expect(gTypeTypeArgument.element, same(tElement));
+
+    if (!AnalysisDriver.useSummary2) {
+      var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
+      expect(gTypeTypeArgument.element, same(tElement));
+    }
+
     var gTypeParameterType =
         gTypeType.namedParameterTypes['u'] as TypeParameterType;
     expect(gTypeParameterType.element, same(tElement));
+
     var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
     var tReference = gArgumentType.name;
     assertElement(tReference, tElement);
@@ -4781,20 +4783,20 @@
 ''');
     await resolveTestFile();
 
-    var mainStatements = _getMainStatements(result);
-    var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
-    var fElement = fDeclaration.functionDeclaration.declaredElement;
-    var tElement = fElement.typeParameters[0];
-    var body = fDeclaration.functionDeclaration.functionExpression.body
-        as BlockFunctionBody;
-    var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
-    var gType = gDeclaration.variables.type as TypeName;
+    var tElement = findNode.typeParameter('T>(T x)').declaredElement;
+
+    var gType = findNode.typeName('Consumer<T>');
     var gTypeType = gType.type as FunctionType;
-    var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
-    expect(gTypeTypeArgument.element, same(tElement));
+
+    if (!AnalysisDriver.useSummary2) {
+      var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
+      expect(gTypeTypeArgument.element, same(tElement));
+    }
+
     var gTypeParameterType =
         gTypeType.normalParameterTypes[0] as TypeParameterType;
     expect(gTypeParameterType.element, same(tElement));
+
     var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
     var tReference = gArgumentType.name;
     assertElement(tReference, tElement);
@@ -4814,20 +4816,20 @@
 ''');
     await resolveTestFile();
 
-    var mainStatements = _getMainStatements(result);
-    var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
-    var fElement = fDeclaration.functionDeclaration.declaredElement;
-    var tElement = fElement.typeParameters[0];
-    var body = fDeclaration.functionDeclaration.functionExpression.body
-        as BlockFunctionBody;
-    var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
-    var gType = gDeclaration.variables.type as TypeName;
+    var tElement = findNode.typeParameter('T>(T x)').declaredElement;
+
+    var gType = findNode.typeName('Consumer<T>');
     var gTypeType = gType.type as FunctionType;
-    var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
-    expect(gTypeTypeArgument.element, same(tElement));
+
+    if (!AnalysisDriver.useSummary2) {
+      var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
+      expect(gTypeTypeArgument.element, same(tElement));
+    }
+
     var gTypeParameterType =
         gTypeType.optionalParameterTypes[0] as TypeParameterType;
     expect(gTypeParameterType.element, same(tElement));
+
     var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
     var tReference = gArgumentType.name;
     assertElement(tReference, tElement);
@@ -4847,19 +4849,19 @@
 ''');
     await resolveTestFile();
 
-    var mainStatements = _getMainStatements(result);
-    var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
-    var fElement = fDeclaration.functionDeclaration.declaredElement;
-    var tElement = fElement.typeParameters[0];
-    var body = fDeclaration.functionDeclaration.functionExpression.body
-        as BlockFunctionBody;
-    var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
-    var gType = gDeclaration.variables.type as TypeName;
+    var tElement = findNode.typeParameter('T>(T x)').declaredElement;
+
+    var gType = findNode.typeName('Producer<T>');
     var gTypeType = gType.type as FunctionType;
-    var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
-    expect(gTypeTypeArgument.element, same(tElement));
+
+    if (!AnalysisDriver.useSummary2) {
+      var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
+      expect(gTypeTypeArgument.element, same(tElement));
+    }
+
     var gTypeReturnType = gTypeType.returnType as TypeParameterType;
     expect(gTypeReturnType.element, same(tElement));
+
     var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
     var tReference = gArgumentType.name;
     assertElement(tReference, tElement);
@@ -4883,7 +4885,7 @@
     FunctionDeclaration main = result.unit.declarations[0];
     expect(main.declaredElement, isNotNull);
     expect(main.name.staticElement, isNotNull);
-    expect(main.name.staticType.toString(), '() → void');
+    expect(main.name.staticType.toString(), 'void Function()');
 
     BlockFunctionBody body = main.functionExpression.body;
     NodeList<Statement> statements = body.block.statements;
@@ -5243,7 +5245,7 @@
   c.f(1, b: '2', c: true);
 }
 ''');
-    String fTypeString = '(int, {b: String, c: bool}) → double';
+    String fTypeString = 'double Function(int, {b: String, c: bool})';
 
     await resolveTestFile();
     ClassDeclaration classDeclaration = result.unit.declarations[0];
@@ -5323,11 +5325,11 @@
     MethodInvocation invocation = statement.expression;
 
     expect(invocation.staticType, typeProvider.doubleType);
-    expect(invocation.staticInvokeType.toString(), '(int) → double');
+    expect(invocation.staticInvokeType.toString(), 'double Function(int)');
 
     SimpleIdentifier methodName = invocation.methodName;
     expect(methodName.staticElement, same(callElement));
-    expect(methodName.staticType.toString(), '(int) → double');
+    expect(methodName.staticType.toString(), 'double Function(int)');
   }
 
   test_methodInvocation_explicitCall_functionTarget() async {
@@ -5350,11 +5352,11 @@
     MethodInvocation invocation = statement.expression;
 
     expect(invocation.staticType, typeProvider.doubleType);
-    expect(invocation.staticInvokeType.toString(), '(int) → double');
+    expect(invocation.staticInvokeType.toString(), 'double Function(int)');
 
     SimpleIdentifier target = invocation.target;
     expect(target.staticElement, same(parameter));
-    expect(target.staticType.toString(), '(int) → double');
+    expect(target.staticType.toString(), 'double Function(int)');
 
     SimpleIdentifier methodName = invocation.methodName;
     expect(methodName.staticElement, isNull);
@@ -5385,7 +5387,7 @@
     MethodInvocation invocation = statement.expression;
     expect(invocation.methodName.staticElement, same(fooElement));
 
-    var invokeTypeStr = '(int) → void';
+    var invokeTypeStr = 'void Function(int)';
     expect(invocation.staticType.toString(), 'void');
     expect(invocation.staticInvokeType.toString(), invokeTypeStr);
   }
@@ -5406,7 +5408,7 @@
       var invocation = findNode.methodInvocation('m(1)');
       List<Expression> arguments = invocation.argumentList.arguments;
 
-      var invokeTypeStr = '(int) → void';
+      var invokeTypeStr = 'void Function(int)';
       assertType(invocation, 'void');
       assertInvokeType(invocation, invokeTypeStr);
 
@@ -5433,12 +5435,12 @@
       var invocation = findNode.methodInvocation('m(1, 2.3)');
       List<Expression> arguments = invocation.argumentList.arguments;
 
-      var invokeTypeStr = '(int, double) → Map<int, double>';
+      var invokeTypeStr = 'Map<int, double> Function(int, double)';
       assertType(invocation, 'Map<int, double>');
       assertInvokeType(invocation, invokeTypeStr);
 
       assertMember(invocation.methodName, 'C<int>', mElement);
-      assertType(invocation.methodName, '<U>(int, U) → Map<int, U>');
+      assertType(invocation.methodName, 'Map<int, U> Function<U>(int, U)');
 
       if (AnalysisDriver.useSummary2) {
         _assertArgumentToParameter2(arguments[0], 'int');
@@ -5562,7 +5564,8 @@
     ExpressionStatement statement = fooStatements[0];
     MethodInvocation invocation = statement.expression;
     expect(invocation.methodName.staticElement, same(fElement));
-    expect(invocation.staticInvokeType.toString(), '(int, {b: int}) → String');
+    expect(invocation.staticInvokeType.toString(),
+        'String Function(int, {b: int})');
     expect(invocation.staticType, typeProvider.stringType);
 
     List<Expression> arguments = invocation.argumentList.arguments;
@@ -5622,7 +5625,7 @@
     ExpressionStatement statement = mainStatements[0];
     MethodInvocation invocation = statement.expression;
     expect(invocation.methodName.staticElement, same(fElement));
-    expect(invocation.staticInvokeType.toString(), '(int) → String');
+    expect(invocation.staticInvokeType.toString(), 'String Function(int)');
     expect(invocation.staticType, typeProvider.stringType);
 
     List<Expression> arguments = invocation.argumentList.arguments;
@@ -5686,7 +5689,7 @@
       expect(target.staticElement, same(cElement));
       expect(target.staticType, same(cElement.type));
 
-      var invokeTypeStr = '(int) → void';
+      var invokeTypeStr = 'void Function(int)';
       expect(invocation.staticType.toString(), 'void');
       expect(invocation.staticInvokeType.toString(), invokeTypeStr);
       expect(invocation.staticInvokeType.element, same(mElement));
@@ -5708,7 +5711,7 @@
 
       expect(invocation.target, isNull);
 
-      var invokeTypeStr = '(int) → void';
+      var invokeTypeStr = 'void Function(int)';
       expect(invocation.staticType.toString(), 'void');
       expect(invocation.staticInvokeType.toString(), invokeTypeStr);
       expect(invocation.staticInvokeType.element, same(mElement));
@@ -5738,7 +5741,7 @@
     BlockFunctionBody barBody = barNode.body;
     ExpressionStatement fooStatement = barBody.block.statements[0];
     MethodInvocation fooInvocation = fooStatement.expression;
-    expect(fooInvocation.staticInvokeType.toString(), '(C<T>) → T');
+    expect(fooInvocation.staticInvokeType.toString(), 'T Function(C<T>)');
     expect(fooInvocation.staticType.toString(), 'T');
     expect(fooInvocation.staticType.element, same(tElement));
   }
@@ -5750,7 +5753,7 @@
 }
 double f(int a, String b) {}
 ''');
-    String fTypeString = '(int, String) → double';
+    String fTypeString = 'double Function(int, String)';
 
     await resolveTestFile();
     List<Statement> mainStatements = _getMainStatements(result);
@@ -5791,7 +5794,7 @@
 
     // f<bool, String>(true, 'str');
     {
-      String fTypeString = '(bool, String) → void';
+      String fTypeString = 'void Function(bool, String)';
       ExpressionStatement statement = mainStatements[0];
       MethodInvocation invocation = statement.expression;
 
@@ -5827,7 +5830,7 @@
 
     // f(1, 2.3);
     {
-      String fTypeString = '(int, double) → void';
+      String fTypeString = 'void Function(int, double)';
       ExpressionStatement statement = mainStatements[1];
       MethodInvocation invocation = statement.expression;
       List<Expression> arguments = invocation.argumentList.arguments;
@@ -5876,7 +5879,6 @@
     }
   }
 
-  @failingTest
   test_optionalConst_prefixed() async {
     newFile('/test/lib/a.dart', content: r'''
 class C {
@@ -6131,7 +6133,7 @@
     assertTypeName(intRef, intElement, 'int');
 
     var functionRef = findNode.genericFunctionType('Function(double)');
-    assertType(functionRef, '(double) → int');
+    assertType(functionRef, 'int Function(double)');
 
     var doubleRef = findNode.typeName('double) g');
     assertTypeName(doubleRef, doubleElement, 'double');
@@ -6180,7 +6182,7 @@
     await resolveTestFile();
 
     var gRef = findNode.simple('g()++');
-    assertType(gRef, '() → int');
+    assertType(gRef, 'int Function()');
     assertElement(gRef, findElement.parameter('g'));
   }
 
@@ -6397,7 +6399,7 @@
     PrefixedIdentifier prefixed = statement.expression;
 
     expect(prefixed.prefix.staticElement, same(parameter));
-    expect(prefixed.prefix.staticType.toString(), '(int) → double');
+    expect(prefixed.prefix.staticType.toString(), 'double Function(int)');
 
     SimpleIdentifier methodName = prefixed.identifier;
     expect(methodName.staticElement, isNull);
@@ -6760,7 +6762,7 @@
     FunctionDeclaration main = result.unit.declarations[0];
     expect(main.declaredElement, isNotNull);
     expect(main.name.staticElement, isNotNull);
-    expect(main.name.staticType.toString(), '() → void');
+    expect(main.name.staticType.toString(), 'void Function()');
 
     BlockFunctionBody body = main.functionExpression.body;
     NodeList<Statement> statements = body.block.statements;
@@ -7280,7 +7282,7 @@
     {
       ConstructorDeclaration node = cNode.members[0];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '(int) → C');
+      expect(node.declaredElement.type.toString(), 'C Function(int)');
       expect(node.returnType.staticElement, same(cElement));
       expect(node.returnType.staticType, typeType);
       expect(node.name, isNull);
@@ -7290,18 +7292,18 @@
     {
       ConstructorDeclaration node = cNode.members[1];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '(int) → C');
+      expect(node.declaredElement.type.toString(), 'C Function(int)');
       expect(node.returnType.staticElement, same(cElement));
       expect(node.returnType.staticType, typeType);
       expect(node.name.staticElement, same(node.declaredElement));
-      expect(node.name.staticType.toString(), '(int) → C');
+      expect(node.name.staticType.toString(), 'C Function(int)');
     }
 
     // publicMethod()
     {
       MethodDeclaration node = cNode.members[2];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '(double) → int');
+      expect(node.declaredElement.type.toString(), 'int Function(double)');
 
       // method return type
       TypeName returnType = node.returnType;
@@ -7333,7 +7335,7 @@
     {
       MethodDeclaration node = cNode.members[3];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '() → int');
+      expect(node.declaredElement.type.toString(), 'int Function()');
 
       // getter return type
       TypeName returnType = node.returnType;
@@ -7351,7 +7353,7 @@
     {
       MethodDeclaration node = cNode.members[4];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '(double) → void');
+      expect(node.declaredElement.type.toString(), 'void Function(double)');
 
       // setter return type
       TypeName returnType = node.returnType;
@@ -7400,7 +7402,7 @@
     {
       FunctionDeclaration node = result.unit.declarations[0];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '(double) → int');
+      expect(node.declaredElement.type.toString(), 'int Function(double)');
 
       // function return type
       TypeName returnType = node.returnType;
@@ -7433,7 +7435,7 @@
     {
       FunctionDeclaration node = result.unit.declarations[1];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '() → int');
+      expect(node.declaredElement.type.toString(), 'int Function()');
 
       // getter return type
       TypeName returnType = node.returnType;
@@ -7451,7 +7453,7 @@
     {
       FunctionDeclaration node = result.unit.declarations[2];
       expect(node.declaredElement, isNotNull);
-      expect(node.declaredElement.type.toString(), '(double) → void');
+      expect(node.declaredElement.type.toString(), 'void Function(double)');
 
       // setter return type
       TypeName returnType = node.returnType;
@@ -7669,7 +7671,7 @@
   f(1, b: '2', c: true);
 }
 ''');
-    String fTypeString = '(int, {b: String, c: bool}) → double';
+    String fTypeString = 'double Function(int, {b: String, c: bool})';
 
     await resolveTestFile();
     FunctionDeclaration fDeclaration = result.unit.declarations[0];
@@ -7969,26 +7971,18 @@
 ''');
 
     await resolveTestFile();
-    CompilationUnit unit = result.unit;
-    CompilationUnitElement unitElement = unit.declaredElement;
-    var typeProvider = unitElement.context.typeProvider;
 
-    FunctionTypeAlias alias = unit.declarations[0];
+    FunctionTypeAlias alias = findNode.functionTypeAlias('F<T>');
     GenericTypeAliasElement aliasElement = alias.declaredElement;
-    FunctionType aliasType = aliasElement.type;
 
-    ClassDeclaration cNode = unit.declarations[1];
-
-    FieldDeclaration fDeclaration = cNode.members[0];
-    FunctionType instantiatedAliasType =
-        aliasType.instantiate([typeProvider.intType]);
+    FieldDeclaration fDeclaration = findNode.fieldDeclaration('F<int> f');
 
     TypeName typeName = fDeclaration.fields.type;
-    expect(typeName.type, instantiatedAliasType);
+    expect('${typeName.type}', 'int Function(bool)');
 
     SimpleIdentifier typeIdentifier = typeName.name;
     expect(typeIdentifier.staticElement, same(aliasElement));
-    expect(typeIdentifier.staticType, instantiatedAliasType);
+    expect('${typeIdentifier.staticType}', 'int Function(bool)');
 
     List<TypeAnnotation> typeArguments = typeName.typeArguments.arguments;
     expect(typeArguments, hasLength(1));
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 964254e..dcc2fad 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -15,7 +15,6 @@
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/analysis/status.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/error/codes.dart';
@@ -1754,7 +1753,7 @@
     expect(result.errors, hasLength(0));
 
     var f = result.unit.declarations[0] as FunctionDeclaration;
-    expect(f.name.staticType.toString(), '() → int');
+    expect(f.name.staticType.toString(), 'int Function()');
     expect(f.returnType.type.toString(), 'int');
 
     // The same result is also received through the stream.
@@ -2228,102 +2227,6 @@
     expect(await driver.getSourceKind(path), SourceKind.PART);
   }
 
-  test_getTopLevelNameDeclarations() async {
-    var a = convertPath('/test/lib/a.dart');
-    var b = convertPath('/test/lib/b.dart');
-    var c = convertPath('/test/lib/c.dart');
-    var d = convertPath('/test/lib/d.dart');
-
-    newFile(a, content: 'class A {}');
-    newFile(b, content: 'export "a.dart"; class B {}');
-    newFile(c, content: 'import "d.dart"; class C {}');
-    newFile(d, content: 'class D {}');
-
-    driver.addFile(a);
-    driver.addFile(b);
-    driver.addFile(c);
-    // Don't add d.dart, it is referenced implicitly.
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('A'), [a, b], [false, true]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('B'), [b], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('C'), [c], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('D'), [d], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('X'), [], []);
-  }
-
-  test_getTopLevelNameDeclarations_discover() async {
-    var t = convertPath('/test/lib/test.dart');
-    var a1 = convertPath('/aaa/lib/a1.dart');
-    var a2 = convertPath('/aaa/lib/src/a2.dart');
-    var b = convertPath('/bbb/lib/b.dart');
-    var c = convertPath('/ccc/lib/c.dart');
-
-    newFile(t, content: 'class T {}');
-    newFile(a1, content: 'class A1 {}');
-    newFile(a2, content: 'class A2 {}');
-    newFile(b, content: 'class B {}');
-    newFile(c, content: 'class C {}');
-
-    driver.addFile(t);
-    // Don't add a1.dart, a2.dart, or b.dart - they should be discovered.
-    // And c.dart is not in .packages, so should not be discovered.
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('T'), [t], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('A1'), [a1], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('A2'), [a2], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('B'), [b], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('C'), [], []);
-  }
-
-  test_getTopLevelNameDeclarations_parts() async {
-    var a = convertPath('/test/lib/a.dart');
-    var b = convertPath('/test/lib/b.dart');
-    var c = convertPath('/test/lib/c.dart');
-
-    newFile(a, content: r'''
-library lib;
-part 'b.dart';
-part 'c.dart';
-class A {}
-''');
-    newFile(b, content: 'part of lib; class B {}');
-    newFile(c, content: 'part of lib; class C {}');
-
-    driver.addFile(a);
-    driver.addFile(b);
-    driver.addFile(c);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('A'), [a], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('B'), [a], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('C'), [a], [false]);
-
-    _assertTopLevelDeclarations(
-        await driver.getTopLevelNameDeclarations('X'), [], []);
-  }
-
   test_getUnitElement() async {
     String content = r'''
 foo(int p) {}
@@ -3392,7 +3295,7 @@
     expect(result.errors, hasLength(0));
 
     var f = result.unit.declarations[0] as FunctionDeclaration;
-    expect(f.name.staticType.toString(), '() → int');
+    expect(f.name.staticType.toString(), 'int Function()');
     expect(f.returnType.type.toString(), 'int');
   }
 
@@ -3513,20 +3416,6 @@
     }
   }
 
-  void _assertTopLevelDeclarations(
-      List<TopLevelDeclarationInSource> declarations,
-      List<String> expectedFiles,
-      List<bool> expectedIsExported) {
-    expect(expectedFiles, hasLength(expectedIsExported.length));
-    for (int i = 0; i < expectedFiles.length; i++) {
-      expect(declarations,
-          contains(predicate((TopLevelDeclarationInSource declaration) {
-        return declaration.source.fullName == expectedFiles[i] &&
-            declaration.isExported == expectedIsExported[i];
-      })));
-    }
-  }
-
   void _expectCircularityError(EvaluationResultImpl evaluationResult) {
     expect(evaluationResult, isNotNull);
     expect(evaluationResult.value, isNull);
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index f69ba70..24ec015 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -10,7 +10,6 @@
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/library_graph.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisOptions, AnalysisOptionsImpl;
@@ -104,249 +103,6 @@
         unorderedEquals(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']));
   }
 
-  test_exportedTopLevelDeclarations_cycle() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    String c = convertPath('/aaa/lib/c.dart');
-    newFile(a, content: r'''
-export 'b.dart';
-class A {}
-''');
-    newFile(b, content: r'''
-export 'c.dart';
-class B {}
-''');
-    newFile(c, content: r'''
-export 'a.dart';
-class C {}
-''');
-    _assertExportedTopLevelDeclarations(a, ['A', 'B', 'C']);
-
-    // We asked for 'a', and it was computed.
-    // But 'b' and 'c' are not computed, because we detect that there is
-    // cycle with 'a', so we cannot get all exported declarations of 'a'.
-    _assertHasComputedExportedDeclarations([a]);
-  }
-
-  test_exportedTopLevelDeclarations_cycle_anotherOutsideCycle() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    String c = convertPath('/aaa/lib/c.dart');
-    String d = convertPath('/aaa/lib/d.dart');
-    newFile(a, content: r'''
-export 'b.dart';
-class A {}
-''');
-    newFile(b, content: r'''
-export 'c.dart';
-class B {}
-''');
-    newFile(c, content: r'''
-export 'b.dart';
-export 'd.dart';
-class C {}
-''');
-    newFile(d, content: r'''
-class D {}
-''');
-    _assertExportedTopLevelDeclarations(a, ['A', 'B', 'C', 'D']);
-
-    // To compute 'a' we compute 'b'.
-    // But 'c' is not computed, because of the cycle [b, c].
-    // However 'd' is not a part of a cycle, so it is computed too.
-    _assertHasComputedExportedDeclarations([a, b, d]);
-  }
-
-  test_exportedTopLevelDeclarations_cycle_onSequence() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    String c = convertPath('/aaa/lib/c.dart');
-    String d = convertPath('/aaa/lib/d.dart');
-    String e = convertPath('/aaa/lib/e.dart');
-    newFile(a, content: r'''
-export 'b.dart';
-class A {}
-''');
-    newFile(b, content: r'''
-export 'c.dart';
-class B {}
-''');
-    newFile(c, content: r'''
-export 'd.dart';
-class C {}
-''');
-    newFile(d, content: r'''
-export 'e.dart';
-class D {}
-''');
-    newFile(e, content: r'''
-export 'c.dart';
-class E {}
-''');
-    // We compute 'a'.
-    // To compute it we also compute 'b' and 'c'.
-    // But 'd' and 'e' are not computed, because of the cycle [c, d, e].
-    _assertExportedTopLevelDeclarations(a, ['A', 'B', 'C', 'D', 'E']);
-    _assertHasComputedExportedDeclarations([a, b, c]);
-
-    // We compute 'd', and try to compute 'e', because 'd' needs 'e'; 'e' can
-    // be computed because 'c' is ready, so the cycle [c, d, e] is broken.
-    _assertExportedTopLevelDeclarations(d, ['C', 'D', 'E']);
-    _assertHasComputedExportedDeclarations([a, b, c, d, e]);
-  }
-
-  test_exportedTopLevelDeclarations_export() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    newFile(a, content: r'''
-class A {}
-''');
-    newFile(b, content: r'''
-export 'a.dart';
-class B {}
-''');
-    _assertExportedTopLevelDeclarations(b, ['A', 'B']);
-    _assertHasComputedExportedDeclarations([a, b]);
-  }
-
-  test_exportedTopLevelDeclarations_export2_show() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    String c = convertPath('/aaa/lib/c.dart');
-    newFile(a, content: r'''
-class A1 {}
-class A2 {}
-class A3 {}
-''');
-    newFile(b, content: r'''
-export 'a.dart' show A1, A2;
-class B1 {}
-class B2 {}
-''');
-    newFile(c, content: r'''
-export 'b.dart' show A2, A3, B1;
-class C {}
-''');
-    _assertExportedTopLevelDeclarations(c, ['A2', 'B1', 'C']);
-    _assertHasComputedExportedDeclarations([a, b, c]);
-  }
-
-  test_exportedTopLevelDeclarations_export_flushOnChange() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    newFile(a, content: r'''
-class A {}
-''');
-    newFile(b, content: r'''
-export 'a.dart';
-class B {}
-''');
-
-    // Initial exported declarations.
-    _assertExportedTopLevelDeclarations(b, ['A', 'B']);
-
-    // Update a.dart, so a.dart and b.dart exported declarations are flushed.
-    newFile(a, content: 'class A {} class A2 {}');
-    fileSystemState.getFileForPath(a).refresh();
-    _assertExportedTopLevelDeclarations(b, ['A', 'A2', 'B']);
-  }
-
-  test_exportedTopLevelDeclarations_export_hide() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    newFile(a, content: r'''
-class A1 {}
-class A2 {}
-class A3 {}
-''');
-    newFile(b, content: r'''
-export 'a.dart' hide A2;
-class B {}
-''');
-    _assertExportedTopLevelDeclarations(b, ['A1', 'A3', 'B']);
-  }
-
-  test_exportedTopLevelDeclarations_export_preferLocal() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    newFile(a, content: r'''
-class V {}
-''');
-    newFile(b, content: r'''
-export 'a.dart';
-int V;
-''');
-    FileState file = fileSystemState.getFileForPath(b);
-    Map<String, TopLevelDeclaration> declarations =
-        file.exportedTopLevelDeclarations;
-    expect(declarations.keys, unorderedEquals(['V']));
-    expect(declarations['V'].kind, TopLevelDeclarationKind.variable);
-  }
-
-  test_exportedTopLevelDeclarations_export_show() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    newFile(a, content: r'''
-class A1 {}
-class A2 {}
-''');
-    newFile(b, content: r'''
-export 'a.dart' show A2;
-class B {}
-''');
-    _assertExportedTopLevelDeclarations(b, ['A2', 'B']);
-  }
-
-  test_exportedTopLevelDeclarations_export_show2() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    String c = convertPath('/aaa/lib/c.dart');
-    String d = convertPath('/aaa/lib/d.dart');
-    newFile(a, content: r'''
-export 'b.dart' show Foo;
-export 'c.dart' show Bar;
-''');
-    newFile(b, content: r'''
-export 'd.dart';
-''');
-    newFile(c, content: r'''
-export 'd.dart';
-''');
-    newFile(d, content: r'''
-class Foo {}
-class Bar {}
-''');
-    _assertExportedTopLevelDeclarations(a, ['Foo', 'Bar']);
-  }
-
-  test_exportedTopLevelDeclarations_import() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String b = convertPath('/aaa/lib/b.dart');
-    newFile(a, content: r'''
-class A {}
-''');
-    newFile(b, content: r'''
-import 'a.dart';
-class B {}
-''');
-    _assertExportedTopLevelDeclarations(b, ['B']);
-  }
-
-  test_exportedTopLevelDeclarations_parts() {
-    String a = convertPath('/aaa/lib/a.dart');
-    String a2 = convertPath('/aaa/lib/a2.dart');
-    newFile(a, content: r'''
-library lib;
-part 'a2.dart';
-class A1 {}
-''');
-    newFile(a2, content: r'''
-part of lib;
-class A2 {}
-''');
-    _assertExportedTopLevelDeclarations(a, ['A1', 'A2']);
-  }
-
   test_getFileForPath_doesNotExist() {
     String path = convertPath('/aaa/lib/a.dart');
     FileState file = fileSystemState.getFileForPath(path);
@@ -811,52 +567,6 @@
     expect(file.referencedNames, unorderedEquals(['A', 'B', 'C', 'D']));
   }
 
-  test_topLevelDeclarations() {
-    String path = convertPath('/aaa/lib/a.dart');
-    newFile(path, content: r'''
-class C {}
-typedef F();
-enum E {E1, E2}
-mixin M {}
-void f() {}
-var V1;
-get V2 => null;
-set V3(_) {}
-get V4 => null;
-set V4(_) {}
-
-class _C {}
-typedef _F();
-enum _E {E1, E2}
-mixin _M {}
-void _f() {}
-var _V1;
-get _V2 => null;
-set _V3(_) {}
-''');
-    FileState file = fileSystemState.getFileForPath(path);
-
-    Map<String, TopLevelDeclaration> declarations = file.topLevelDeclarations;
-
-    void assertHas(String name, TopLevelDeclarationKind kind) {
-      expect(declarations[name]?.kind, kind);
-    }
-
-    expect(
-      declarations.keys,
-      unorderedEquals(['C', 'F', 'E', 'M', 'f', 'V1', 'V2', 'V3', 'V4']),
-    );
-    assertHas('C', TopLevelDeclarationKind.type);
-    assertHas('F', TopLevelDeclarationKind.type);
-    assertHas('E', TopLevelDeclarationKind.type);
-    assertHas('M', TopLevelDeclarationKind.type);
-    assertHas('f', TopLevelDeclarationKind.function);
-    assertHas('V1', TopLevelDeclarationKind.variable);
-    assertHas('V2', TopLevelDeclarationKind.variable);
-    assertHas('V3', TopLevelDeclarationKind.variable);
-    assertHas('V4', TopLevelDeclarationKind.variable);
-  }
-
   test_transitiveSignature() {
     String pa = convertPath('/aaa/lib/a.dart');
     String pb = convertPath('/aaa/lib/b.dart');
@@ -917,24 +627,11 @@
     expect(bSignature, isNot(aSignature));
   }
 
-  void _assertExportedTopLevelDeclarations(String path, List<String> expected) {
-    FileState file = fileSystemState.getFileForPath(path);
-    Map<String, TopLevelDeclaration> declarations =
-        file.exportedTopLevelDeclarations;
-    expect(declarations.keys, unorderedEquals(expected));
-  }
-
   void _assertFilesWithoutLibraryCycle(List<FileState> expected) {
     var actual = fileSystemState.test.filesWithoutLibraryCycle;
     expect(_excludeSdk(actual), unorderedEquals(expected));
   }
 
-  void _assertHasComputedExportedDeclarations(List<String> expectedPathList) {
-    FileSystemStateTestView test = fileSystemState.test;
-    expect(test.librariesWithComputedExportedDeclarations.map((f) => f.path),
-        unorderedEquals(expectedPathList));
-  }
-
   void _assertIsUnresolvedFile(FileState file) {
     expect(file.path, isNull);
     expect(file.uri, isNull);
diff --git a/pkg/analyzer/test/src/dart/ast/utilities_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
index 5771180..00cf65e 100644
--- a/pkg/analyzer/test/src/dart/ast/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -1713,6 +1713,48 @@
         AstTestFactory.extendsClause(AstTestFactory.typeName4("C")));
   }
 
+  void test_visitExtensionDeclaration_empty() {
+    _assertSource(
+        'extension E on C {}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E', extendedType: AstTestFactory.typeName4('C')));
+  }
+
+  void test_visitExtensionDeclaration_multipleMember() {
+    _assertSource(
+        'extension E on C {var a; var b;}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            extendedType: AstTestFactory.typeName4('C'),
+            members: [
+              AstTestFactory.fieldDeclaration2(false, Keyword.VAR,
+                  [AstTestFactory.variableDeclaration('a')]),
+              AstTestFactory.fieldDeclaration2(
+                  false, Keyword.VAR, [AstTestFactory.variableDeclaration('b')])
+            ]));
+  }
+
+  void test_visitExtensionDeclaration_parameters() {
+    _assertSource(
+        'extension E<T> on C {}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            typeParameters: AstTestFactory.typeParameterList(['T']),
+            extendedType: AstTestFactory.typeName4('C')));
+  }
+
+  void test_visitExtensionDeclaration_singleMember() {
+    _assertSource(
+        'extension E on C {var a;}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            extendedType: AstTestFactory.typeName4('C'),
+            members: [
+              AstTestFactory.fieldDeclaration2(
+                  false, Keyword.VAR, [AstTestFactory.variableDeclaration('a')])
+            ]));
+  }
+
   void test_visitFieldDeclaration_instance() {
     _assertSource(
         "var a;",
@@ -2351,6 +2393,16 @@
         "f()", AstTestFactory.functionTypedFormalParameter(null, "f"));
   }
 
+  void test_visitFunctionTypedFormalParameter_nullable() {
+    _assertSource(
+        "T f()?",
+        astFactory.functionTypedFormalParameter2(
+            returnType: AstTestFactory.typeName4("T"),
+            identifier: AstTestFactory.identifier3('f'),
+            parameters: AstTestFactory.formalParameterList([]),
+            question: TokenFactory.tokenFromType(TokenType.QUESTION)));
+  }
+
   void test_visitFunctionTypedFormalParameter_type() {
     _assertSource(
         "T f()",
@@ -4427,6 +4479,48 @@
         AstTestFactory.extendsClause(AstTestFactory.typeName4("C")));
   }
 
+  void test_visitExtensionDeclaration_empty() {
+    _assertSource(
+        'extension E on C {}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E', extendedType: AstTestFactory.typeName4('C')));
+  }
+
+  void test_visitExtensionDeclaration_multipleMember() {
+    _assertSource(
+        'extension E on C {var a; var b;}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            extendedType: AstTestFactory.typeName4('C'),
+            members: [
+              AstTestFactory.fieldDeclaration2(false, Keyword.VAR,
+                  [AstTestFactory.variableDeclaration('a')]),
+              AstTestFactory.fieldDeclaration2(
+                  false, Keyword.VAR, [AstTestFactory.variableDeclaration('b')])
+            ]));
+  }
+
+  void test_visitExtensionDeclaration_parameters() {
+    _assertSource(
+        'extension E<T> on C {}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            typeParameters: AstTestFactory.typeParameterList(['T']),
+            extendedType: AstTestFactory.typeName4('C')));
+  }
+
+  void test_visitExtensionDeclaration_singleMember() {
+    _assertSource(
+        'extension E on C {var a;}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            extendedType: AstTestFactory.typeName4('C'),
+            members: [
+              AstTestFactory.fieldDeclaration2(
+                  false, Keyword.VAR, [AstTestFactory.variableDeclaration('a')])
+            ]));
+  }
+
   void test_visitFieldDeclaration_instance() {
     _assertSource(
         "var a;",
@@ -5065,6 +5159,16 @@
         "f()", AstTestFactory.functionTypedFormalParameter(null, "f"));
   }
 
+  void test_visitFunctionTypedFormalParameter_nullable() {
+    _assertSource(
+        "T f()?",
+        astFactory.functionTypedFormalParameter2(
+            returnType: AstTestFactory.typeName4("T"),
+            identifier: AstTestFactory.identifier3('f'),
+            parameters: AstTestFactory.formalParameterList([]),
+            question: TokenFactory.tokenFromType(TokenType.QUESTION)));
+  }
+
   void test_visitFunctionTypedFormalParameter_type() {
     _assertSource(
         "T f()",
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index bc41dcb..792b693 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -238,7 +238,7 @@
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElementImpl method = ElementFactory.methodElement(methodName, null);
-    method.abstract = true;
+    method.isAbstract = true;
     classA.methods = <MethodElement>[method];
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
@@ -260,7 +260,7 @@
     classA.methods = <MethodElement>[inheritedMethod];
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     MethodElementImpl method = ElementFactory.methodElement(methodName, null);
-    method.abstract = true;
+    method.isAbstract = true;
     classB.methods = <MethodElement>[method];
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
@@ -298,11 +298,11 @@
     // }
     LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.abstract = true;
+    classA.isAbstract = true;
     String methodName = "m";
     MethodElementImpl inheritedMethod =
         ElementFactory.methodElement(methodName, null);
-    inheritedMethod.abstract = true;
+    inheritedMethod.isAbstract = true;
     classA.methods = <MethodElement>[inheritedMethod];
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     MethodElement method = ElementFactory.methodElement(methodName, null);
@@ -485,7 +485,7 @@
     classA.methods = <MethodElement>[inheritedMethod];
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     MethodElementImpl method = ElementFactory.methodElement(methodName, null);
-    method.abstract = true;
+    method.isAbstract = true;
     classB.methods = <MethodElement>[method];
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
@@ -524,11 +524,11 @@
     // }
     LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.abstract = true;
+    classA.isAbstract = true;
     String methodName = "m";
     MethodElementImpl inheritedMethod =
         ElementFactory.methodElement(methodName, null);
-    inheritedMethod.abstract = true;
+    inheritedMethod.isAbstract = true;
     classA.methods = <MethodElement>[inheritedMethod];
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     MethodElement method = ElementFactory.methodElement(methodName, null);
@@ -558,7 +558,7 @@
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     MethodElementImpl abstractMethod =
         ElementFactory.methodElement(methodName, null);
-    abstractMethod.abstract = true;
+    abstractMethod.isAbstract = true;
     classB.methods = <MethodElement>[abstractMethod];
     ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
     MethodElementImpl method = ElementFactory.methodElement(methodName, null);
@@ -1834,14 +1834,14 @@
     var s = ElementFactory.genericTypeAliasElement("s");
     t.function.returnType = s.type;
     s.function.returnType = t.type;
-    expect(t.type.toString(), '() \u2192 () \u2192 ...');
+    expect(t.type.toString(), '... Function() Function()');
   }
 
   void test_toString_recursive_via_interface_type() {
     var f = ElementFactory.genericTypeAliasElement('f');
     ClassElementImpl c = ElementFactory.classElement2('C', ['T']);
     f.function.returnType = c.type.instantiate([f.type]);
-    expect(f.type.toString(), '() \u2192 C<...>');
+    expect(f.type.toString(), 'C<...> Function()');
   }
 
   void test_typeParameters_genericLocalFunction_genericMethod_genericClass() {
@@ -3844,6 +3844,88 @@
     expect(type.resolveToBound(null), same(classS.type));
   }
 
+  void test_resolveToBound_bound_nullableInner() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+    element.bound =
+        (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
+    expect(type.resolveToBound(null), same(element.bound));
+  }
+
+  void test_resolveToBound_bound_nullableInnerOuter() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+    element.bound =
+        (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+        .withNullability(NullabilitySuffix.question);
+    expect(type.resolveToBound(null), same(element.bound));
+  }
+
+  void test_resolveToBound_bound_nullableInnerStarOuter() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+    element.bound =
+        (classS.type as TypeImpl).withNullability(NullabilitySuffix.star);
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+        .withNullability(NullabilitySuffix.question);
+    expect(
+        type.resolveToBound(null),
+        equals((classS.type as TypeImpl)
+            .withNullability(NullabilitySuffix.question)));
+  }
+
+  void test_resolveToBound_bound_nullableOuter() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+    element.bound = classS.type;
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+        .withNullability(NullabilitySuffix.question);
+    expect(
+        type.resolveToBound(null),
+        equals((classS.type as TypeImpl)
+            .withNullability(NullabilitySuffix.question)));
+  }
+
+  void test_resolveToBound_bound_starInner() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+    element.bound =
+        (classS.type as TypeImpl).withNullability(NullabilitySuffix.star);
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
+    expect(type.resolveToBound(null), same(element.bound));
+  }
+
+  void test_resolveToBound_bound_starInnerNullableOuter() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+    element.bound =
+        (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+        .withNullability(NullabilitySuffix.star);
+    expect(type.resolveToBound(null), same(element.bound));
+  }
+
+  void test_resolveToBound_bound_starOuter() {
+    ClassElementImpl classS = ElementFactory.classElement2("A");
+    TypeParameterElementImpl element =
+        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+    element.bound = classS.type;
+    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+        .withNullability(NullabilitySuffix.star);
+    expect(
+        type.resolveToBound(null),
+        same(
+            (classS.type as TypeImpl).withNullability(NullabilitySuffix.star)));
+  }
+
   void test_resolveToBound_nestedBound() {
     ClassElementImpl classS = ElementFactory.classElement2("A");
     TypeParameterElementImpl elementE =
diff --git a/pkg/analyzer/test/src/dart/element/function_type_test.dart b/pkg/analyzer/test/src/dart/element/function_type_test.dart
index a0c2fd3..d5bb2f7 100644
--- a/pkg/analyzer/test/src/dart/element/function_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/function_type_test.dart
@@ -46,7 +46,7 @@
 
   void basicChecks(FunctionType f,
       {element,
-      displayName: '() → dynamic',
+      displayName: 'dynamic Function()',
       returnType,
       namedParameterTypes: isEmpty,
       normalParameterNames: isEmpty,
@@ -148,7 +148,7 @@
     var e = new MockGenericTypeAliasElement('F');
     basicChecks(e.type, element: same(e), displayName: 'F', name: 'F');
     basicChecks(e.function.type,
-        element: same(e.function), displayName: '() → dynamic');
+        element: same(e.function), displayName: 'dynamic Function()');
   }
 
   test_forTypedef_innerAndOuterTypeParameter() {
@@ -172,7 +172,7 @@
         typeFormals: [same(t)]);
     basicChecks(e.function.type,
         element: same(e.function),
-        displayName: '<U>(U) → T',
+        displayName: 'T Function<U>(U)',
         returnType: same(t.type),
         typeArguments: [same(t.type)],
         typeParameters: [same(t)],
@@ -223,7 +223,7 @@
         returnType: same(t.type));
     basicChecks(e.function.type,
         element: same(e.function),
-        displayName: '<T>() → T',
+        displayName: 'T Function<T>()',
         returnType: same(t.type),
         typeFormals: [same(t)]);
   }
@@ -240,7 +240,7 @@
         parameters: [same(p)]);
     basicChecks(e.function.type,
         element: same(e.function),
-        displayName: '(dynamic) → dynamic',
+        displayName: 'dynamic Function(dynamic)',
         normalParameterNames: ['p'],
         normalParameterTypes: [same(dynamicType)],
         parameters: [same(p)]);
@@ -260,7 +260,7 @@
     if (bug_33302_fixed) {
       expect(fReturn.displayName, 'List<G>');
     } else {
-      expect(fReturn.displayName, 'List<() → List<...>>');
+      expect(fReturn.displayName, 'List<List<...> Function()>');
     }
     var fReturnArg = (fReturn as InterfaceType).typeArguments[0];
     expect(fReturnArg.element, same(g.function));
@@ -271,9 +271,10 @@
     basicChecks(f.function.type,
         element: same(f.function), displayName: isNotNull, returnType: fReturn);
     if (bug_33302_fixed) {
-      expect(f.function.type.displayName, '() → List<G>');
+      expect(f.function.type.displayName, 'List<G> Function()');
     } else {
-      expect(f.function.type.displayName, '() → List<() → List<...>>');
+      expect(
+          f.function.type.displayName, 'List<List<...> Function()> Function()');
     }
     basicChecks(g.type,
         element: same(g), displayName: 'G', name: 'G', returnType: isNotNull);
@@ -282,7 +283,7 @@
     if (bug_33302_fixed) {
       expect(gReturn.displayName, 'List<F>');
     } else {
-      expect(gReturn.displayName, 'List<() → List<...>>');
+      expect(gReturn.displayName, 'List<List<...> Function()>');
     }
     var gReturnArg = (gReturn as InterfaceType).typeArguments[0];
     expect(gReturnArg.element, same(f.function));
@@ -293,9 +294,10 @@
     basicChecks(g.function.type,
         element: same(g.function), displayName: isNotNull, returnType: gReturn);
     if (bug_33302_fixed) {
-      expect(g.function.type.displayName, '() → F');
+      expect(g.function.type.displayName, 'F Function()');
     } else {
-      expect(g.function.type.displayName, '() → List<() → List<...>>');
+      expect(
+          g.function.type.displayName, 'List<List<...> Function()> Function()');
     }
   }
 
@@ -326,9 +328,9 @@
         normalParameterNames: ['g'],
         returnType: same(voidType));
     if (bug_33302_fixed) {
-      expect(f.function.type.displayName, '(G) → void');
+      expect(f.function.type.displayName, 'void Function(G)');
     } else {
-      expect(f.function.type.displayName, '((...) → void) → void');
+      expect(f.function.type.displayName, 'void Function(void Function(...))');
     }
     basicChecks(g.type,
         element: same(g),
@@ -350,9 +352,9 @@
         normalParameterNames: ['f'],
         returnType: same(voidType));
     if (bug_33302_fixed) {
-      expect(g.function.type.displayName, '(F) → void');
+      expect(g.function.type.displayName, 'void Function(F)');
     } else {
-      expect(g.function.type.displayName, '((...) → void) → void');
+      expect(g.function.type.displayName, 'void Function(void Function(...))');
     }
   }
 
@@ -372,9 +374,9 @@
     basicChecks(f.function.type,
         element: same(f.function), displayName: isNotNull, returnType: fReturn);
     if (bug_33302_fixed) {
-      expect(f.function.type.displayName, '() → G');
+      expect(f.function.type.displayName, 'G Function()');
     } else {
-      expect(f.function.type.displayName, '() → () → ...');
+      expect(f.function.type.displayName, '... Function() Function()');
     }
     basicChecks(g.type,
         element: same(g), displayName: 'G', name: 'G', returnType: isNotNull);
@@ -385,9 +387,9 @@
     basicChecks(g.function.type,
         element: same(g.function), displayName: isNotNull, returnType: gReturn);
     if (bug_33302_fixed) {
-      expect(g.function.type.displayName, '() → F');
+      expect(g.function.type.displayName, 'F Function()');
     } else {
-      expect(g.function.type.displayName, '() → () → ...');
+      expect(g.function.type.displayName, '... Function() Function()');
     }
   }
 
@@ -397,7 +399,7 @@
         element: same(e), displayName: 'F', name: 'F', returnType: objectType);
     basicChecks(e.function.type,
         element: same(e.function),
-        displayName: '() → Object',
+        displayName: 'Object Function()',
         returnType: objectType);
   }
 
@@ -405,7 +407,7 @@
     var e = new MockGenericTypeAliasElement.withNullReturn('F');
     basicChecks(e.type, element: same(e), displayName: 'F', name: 'F');
     basicChecks(e.function.type,
-        element: same(e.function), displayName: '() → dynamic');
+        element: same(e.function), displayName: 'dynamic Function()');
   }
 
   test_forTypedef_typeParameter() {
@@ -421,7 +423,7 @@
         typeFormals: [same(t)]);
     basicChecks(e.function.type,
         element: same(e.function),
-        displayName: '() → T',
+        displayName: 'T Function()',
         returnType: same(t.type),
         typeArguments: [same(t.type)],
         typeParameters: [same(t)]);
@@ -440,7 +442,7 @@
     FunctionType instantiated = f.instantiate([objectType]);
     basicChecks(instantiated,
         element: isNull,
-        displayName: '(Object) → Object',
+        displayName: 'Object Function(Object)',
         returnType: same(objectType),
         normalParameterNames: ['x'],
         normalParameterTypes: [same(objectType)],
@@ -467,7 +469,7 @@
     FunctionType instantiated = f.instantiate([objectType]);
     basicChecks(instantiated,
         element: isNull,
-        displayName: '(int) → Object',
+        displayName: 'Object Function(int)',
         returnType: same(objectType),
         normalParameterNames: ['x'],
         normalParameterTypes: [same(intType)],
@@ -480,7 +482,7 @@
     FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
     basicChecks(f,
         element: isNull,
-        displayName: '({x: Object}) → dynamic',
+        displayName: 'dynamic Function({x: Object})',
         namedParameterTypes: {'x': same(objectType)},
         parameters: hasLength(1));
     expect(f.parameters[0].isNamed, isTrue);
@@ -493,7 +495,7 @@
     FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
     basicChecks(f,
         element: isNull,
-        displayName: '(Object) → dynamic',
+        displayName: 'dynamic Function(Object)',
         normalParameterNames: ['x'],
         normalParameterTypes: [same(objectType)],
         parameters: hasLength(1));
@@ -508,7 +510,7 @@
     FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
     basicChecks(f,
         element: isNull,
-        displayName: '([Object]) → dynamic',
+        displayName: 'dynamic Function([Object])',
         optionalParameterNames: ['x'],
         optionalParameterTypes: [same(objectType)],
         parameters: hasLength(1));
@@ -521,7 +523,7 @@
     FunctionType f = new FunctionTypeImpl.synthetic(objectType, [], []);
     basicChecks(f,
         element: isNull,
-        displayName: '() → Object',
+        displayName: 'Object Function()',
         returnType: same(objectType));
   }
 
@@ -537,7 +539,7 @@
     var uSubstituted = substituted.typeFormals[0];
     basicChecks(substituted,
         element: isNull,
-        displayName: '<U extends Object>(Object, U) → Map<Object, U>',
+        displayName: 'Map<Object, U> Function<U extends Object>(Object, U)',
         returnType: mapOf(objectType, uSubstituted.type),
         typeFormals: [uSubstituted],
         normalParameterNames: ['x', 'y'],
@@ -562,7 +564,7 @@
     FunctionType substituted = f.substitute2([objectType], [t.type]);
     basicChecks(substituted,
         element: isNull,
-        displayName: '<U extends Object>(int) → int',
+        displayName: 'int Function<U extends Object>(int)',
         returnType: same(f.returnType),
         typeFormals: hasLength(1),
         normalParameterNames: ['x'],
@@ -582,7 +584,7 @@
     FunctionType substituted = f.substitute2([objectType], [t.type]);
     basicChecks(substituted,
         element: isNull,
-        displayName: '<U>(Object, U) → int',
+        displayName: 'int Function<U>(Object, U)',
         returnType: same(f.returnType),
         typeFormals: same(f.typeFormals),
         normalParameterNames: ['x', 'y'],
@@ -599,7 +601,7 @@
     FunctionType substituted = f.substitute2([objectType], [t.type]);
     basicChecks(substituted,
         element: isNull,
-        displayName: '<U>(U) → Object',
+        displayName: 'Object Function<U>(U)',
         returnType: same(objectType),
         typeFormals: same(f.typeFormals),
         normalParameterNames: ['x'],
@@ -622,7 +624,7 @@
     FunctionType f = new FunctionTypeImpl.synthetic(t.type, [t], []);
     basicChecks(f,
         element: isNull,
-        displayName: '<T>() → T',
+        displayName: 'T Function<T>()',
         returnType: same(t.type),
         typeFormals: [same(t)]);
   }
@@ -648,7 +650,7 @@
     var instantiated = f.instantiate([t.type]);
     basicChecks(instantiated,
         element: same(e),
-        displayName: '(T) → dynamic',
+        displayName: 'dynamic Function(T)',
         typeArguments: hasLength(1),
         typeParameters: [same(t)],
         normalParameterNames: ['x'],
@@ -671,7 +673,7 @@
     var instantiated = f.instantiate([objectType]);
     basicChecks(instantiated,
         element: same(e),
-        displayName: '(Object) → dynamic',
+        displayName: 'dynamic Function(Object)',
         typeArguments: hasLength(1),
         typeParameters: [same(t)],
         normalParameterNames: ['x'],
@@ -690,7 +692,7 @@
     var instantiated = f.instantiate([objectType]);
     basicChecks(instantiated,
         element: same(e),
-        displayName: '() → Object',
+        displayName: 'Object Function()',
         typeArguments: hasLength(1),
         typeParameters: [same(t)],
         returnType: same(objectType));
@@ -703,7 +705,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '({x: dynamic}) → dynamic',
+        displayName: 'dynamic Function({x: dynamic})',
         namedParameterTypes: {'x': same(dynamicType)},
         parameters: [same(p)]);
   }
@@ -715,7 +717,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '({x: Object}) → dynamic',
+        displayName: 'dynamic Function({x: Object})',
         namedParameterTypes: {'x': same(objectType)},
         parameters: [same(p)]);
   }
@@ -735,7 +737,7 @@
         element: same(e),
         typeArguments: [same(t.type)],
         typeParameters: [same(t)],
-        displayName: '() → T',
+        displayName: 'T Function()',
         returnType: same(t.type));
   }
 
@@ -745,7 +747,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '(dynamic) → dynamic',
+        displayName: 'dynamic Function(dynamic)',
         normalParameterNames: ['x'],
         normalParameterTypes: [same(dynamicType)],
         parameters: [same(p)]);
@@ -757,7 +759,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '(Object) → dynamic',
+        displayName: 'dynamic Function(Object)',
         normalParameterNames: ['x'],
         normalParameterTypes: [same(objectType)],
         parameters: [same(p)]);
@@ -770,7 +772,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '([dynamic]) → dynamic',
+        displayName: 'dynamic Function([dynamic])',
         optionalParameterNames: ['x'],
         optionalParameterTypes: [same(dynamicType)],
         parameters: [same(p)]);
@@ -783,7 +785,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '([Object]) → dynamic',
+        displayName: 'dynamic Function([Object])',
         optionalParameterNames: ['x'],
         optionalParameterTypes: [same(objectType)],
         parameters: [same(p)]);
@@ -795,7 +797,7 @@
     basicChecks(f,
         element: same(e),
         returnType: same(objectType),
-        displayName: '() → Object');
+        displayName: 'Object Function()');
   }
 
   test_unnamedConstructor_returnType_null() {
@@ -804,7 +806,7 @@
     basicChecks(f,
         element: same(e),
         returnType: same(dynamicType),
-        displayName: '() → dynamic');
+        displayName: 'dynamic Function()');
   }
 
   test_unnamedConstructor_staticMethod_ignores_enclosing_type_params() {
@@ -854,10 +856,10 @@
         typeArguments: [same(objectType)]);
     if (bug_33300_fixed) {
       expect(substituted.displayName,
-          '<S extends T,T extends Object,V extends T>() → Map<S, V>');
+          'Map<S, V> Function<S extends T,T extends Object,V extends T>()');
     } else {
       expect(substituted.displayName,
-          '<S extends T extends Object,T extends Object,V extends T>() → Map<S, V>');
+          'Map<S, V> Function<S extends T extends Object,T extends Object,V extends T>()');
     }
     var s2 = substituted.typeFormals[0];
     var t2 = substituted.typeFormals[1];
@@ -908,12 +910,10 @@
         typeArguments: [same(objectType)]);
     if (bug_33300_fixed) {
       expect(substituted.displayName,
-          '<S extends T,T extends Object,V extends T>(S, V) → void');
+          'void Function<S extends T,T extends Object,V extends T>(S, V)');
     } else {
-      expect(
-          substituted.displayName,
-          '<S extends T extends Object,T extends Object,V extends T>(S, V) '
-          '→ void');
+      expect(substituted.displayName,
+          'void Function<S extends T extends Object,T extends Object,V extends T>(S, V)');
     }
     var s2 = substituted.typeFormals[0];
     var t2 = substituted.typeFormals[1];
@@ -944,7 +944,7 @@
     var substituted = f.substitute2([objectType], [t.type]);
     basicChecks(substituted,
         element: same(e),
-        displayName: '<U extends Object>() → U',
+        displayName: 'U Function<U extends Object>()',
         typeArguments: [same(objectType)],
         typeParameters: [same(t)],
         returnType: isNotNull,
@@ -961,7 +961,9 @@
     FunctionType f = new FunctionTypeImpl(e);
     var substituted = f.substitute2([t.type], [t.type]);
     basicChecks(substituted,
-        element: same(e), displayName: '() → T', returnType: same(t.type));
+        element: same(e),
+        displayName: 'T Function()',
+        returnType: same(t.type));
     // TODO(paulberry): test substitute length mismatch
   }
 
@@ -974,7 +976,7 @@
     var substituted = f.substitute2([objectType], [t.type]);
     basicChecks(substituted,
         element: same(e),
-        displayName: '(Object) → dynamic',
+        displayName: 'dynamic Function(Object)',
         normalParameterNames: ['x'],
         normalParameterTypes: [same(objectType)],
         parameters: hasLength(1),
@@ -993,7 +995,7 @@
     var substituted = f.substitute2([objectType], [t.type]);
     basicChecks(substituted,
         element: same(e),
-        displayName: '() → Object',
+        displayName: 'Object Function()',
         returnType: same(objectType),
         typeArguments: [same(objectType)],
         typeParameters: [same(t)]);
@@ -1005,7 +1007,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '<T>() → dynamic',
+        displayName: 'dynamic Function<T>()',
         typeFormals: [same(t)]);
     // TODO(paulberry): test pruning of bounds
   }
@@ -1019,7 +1021,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '<U extends T>() → U',
+        displayName: 'U Function<U extends T>()',
         typeArguments: [same(t.type)],
         typeParameters: [same(t)],
         returnType: same(u.type),
@@ -1038,7 +1040,7 @@
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
-        displayName: '() → T',
+        displayName: 'T Function()',
         returnType: same(t.type),
         typeArguments: [same(t.type)],
         typeParameters: [same(t)]);
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
index 07b9de2..6286672 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
@@ -47,7 +47,7 @@
     _assertGetInherited(
       className: 'X',
       name: 'foo',
-      expected: 'B.foo: () → void',
+      expected: 'B.foo: void Function()',
     );
   }
 
@@ -70,7 +70,7 @@
     _assertGetInherited(
       className: 'X',
       name: 'foo',
-      expected: 'J.foo: () → void',
+      expected: 'J.foo: void Function()',
     );
   }
 
@@ -93,7 +93,7 @@
     _assertGetInherited(
       className: 'X',
       name: 'foo',
-      expected: 'M.foo: () → void',
+      expected: 'M.foo: void Function()',
     );
   }
 
@@ -116,7 +116,7 @@
     _assertGetInherited(
       className: 'X',
       name: 'foo',
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -131,7 +131,7 @@
     await resolveTestFile();
 
     _assertInheritedConcreteMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
 ''');
   }
 
@@ -158,7 +158,7 @@
     await resolveTestFile();
 
     _assertInheritedConcreteMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
 ''');
   }
 
@@ -181,7 +181,7 @@
     await resolveTestFile();
 
     _assertInheritedConcreteMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
 ''');
   }
 
@@ -214,7 +214,7 @@
     await resolveTestFile();
 
     _assertInheritedConcreteMap('C', r'''
-A.foo: (int) → void
+A.foo: void Function(int)
 ''');
   }
 
@@ -242,7 +242,7 @@
     await resolveTestFile();
 
     _assertInheritedConcreteMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
 ''');
   }
 
@@ -261,8 +261,8 @@
     await resolveTestFile();
 
     _assertInheritedConcreteMap('C', r'''
-A.foo: () → void
-B.bar: () → void
+A.foo: void Function()
+B.bar: void Function()
 ''');
   }
 
@@ -277,7 +277,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
 ''');
   }
 
@@ -292,7 +292,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
 ''');
   }
 
@@ -307,7 +307,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
 ''');
   }
 
@@ -326,7 +326,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('X', r'''
-B.foo: () → void
+B.foo: void Function()
 ''');
   }
 
@@ -341,8 +341,8 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → int
-A.foo=: (int) → void
+A.foo: int Function()
+A.foo=: void Function(int)
 ''');
   }
 
@@ -357,8 +357,8 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → int
-A.foo=: (int) → void
+A.foo: int Function()
+A.foo=: void Function(int)
 ''');
   }
 
@@ -373,8 +373,8 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → int
-A.foo=: (int) → void
+A.foo: int Function()
+A.foo=: void Function(int)
 ''');
   }
 
@@ -398,7 +398,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
 ''');
   }
 
@@ -413,7 +413,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
 ''');
   }
 
@@ -428,7 +428,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
 ''');
   }
 
@@ -449,7 +449,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('X', r'''
-A.foo: () → void
+A.foo: void Function()
 ''');
   }
 
@@ -470,7 +470,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('A', r'''
-J.bar: () → void
+J.bar: void Function()
 ''');
   }
 
@@ -489,8 +489,8 @@
     await resolveTestFile();
 
     _assertInheritedMap('A', r'''
-I.foo: () → int
-J.bar: () → double
+I.foo: int Function()
+J.bar: double Function()
 ''');
   }
 
@@ -509,7 +509,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('A', r'''
-J.foo: () → int
+J.foo: int Function()
 ''');
   }
 
@@ -528,7 +528,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('A', r'''
-J.foo: () → void
+J.foo: void Function()
 ''');
   }
 
@@ -548,11 +548,11 @@
     await resolveTestFile();
 
     _assertInheritedMap('A', r'''
-I.foo=: (num) → void
+I.foo=: void Function(num)
 ''');
 
     _assertInheritedMap('B', r'''
-I.foo=: (num) → void
+I.foo=: void Function(num)
 ''');
   }
 
@@ -580,11 +580,11 @@
     await resolveTestFile();
 
     _assertInheritedMap('D', r'''
-I3.foo: () → C
+I3.foo: C Function()
 ''');
 
     _assertInheritedMap('E', r'''
-I3.foo: () → C
+I3.foo: C Function()
 ''');
   }
 
@@ -612,7 +612,7 @@
     await resolveTestFile();
 
     _assertInheritedMap('D', r'''
-I1.foo: (A) → void
+I1.foo: void Function(A)
 ''');
   }
 
@@ -640,11 +640,11 @@
     await resolveTestFile();
 
     _assertInheritedMap('D', r'''
-I1.foo=: (A) → void
+I1.foo=: void Function(A)
 ''');
 
     _assertInheritedMap('E', r'''
-I1.foo=: (A) → void
+I1.foo=: void Function(A)
 ''');
   }
 
@@ -664,11 +664,11 @@
     await resolveTestFile();
 
     _assertInheritedMap('A', r'''
-I2.foo: ([int]) → int
+I2.foo: int Function([int])
 ''');
 
     _assertInheritedMap('B', r'''
-I2.foo: ([int]) → int
+I2.foo: int Function([int])
 ''');
   }
 
@@ -692,11 +692,11 @@
     await resolveTestFile();
 
     _assertInheritedMap('A', r'''
-I3.foo: ([int, int]) → int
+I3.foo: int Function([int, int])
 ''');
 
     _assertInheritedMap('B', r'''
-I3.foo: ([int, int]) → int
+I3.foo: int Function([int, int])
 ''');
   }
 
@@ -717,7 +717,7 @@
     _assertGetMember(
       className: 'C',
       name: 'f',
-      expected: 'I2.f: (Object) → void',
+      expected: 'I2.f: void Function(Object)',
     );
   }
 
@@ -733,7 +733,7 @@
       className: 'A',
       name: 'foo',
       concrete: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -766,7 +766,7 @@
       className: 'X',
       name: 'foo',
       concrete: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -786,7 +786,7 @@
       className: 'X',
       name: 'foo',
       concrete: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -806,7 +806,7 @@
       className: 'X',
       name: 'toString',
       concrete: true,
-      expected: 'A.toString: () → String',
+      expected: 'A.toString: String Function()',
     );
   }
 
@@ -824,7 +824,7 @@
       className: 'X',
       name: 'foo',
       concrete: true,
-      expected: 'M.foo: () → void',
+      expected: 'M.foo: void Function()',
     );
   }
 
@@ -844,14 +844,14 @@
       className: 'B',
       name: 'foo',
       concrete: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
 
     _assertGetMember(
       className: 'C',
       name: 'foo',
       concrete: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -886,14 +886,14 @@
       className: 'B',
       name: 'foo',
       concrete: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
 
     _assertGetMember(
       className: 'C',
       name: 'foo',
       concrete: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -938,7 +938,7 @@
       className: 'C',
       name: 'foo',
       concrete: true,
-      expected: 'C.foo: ([int]) → void',
+      expected: 'C.foo: void Function([int])',
     );
   }
 
@@ -967,7 +967,7 @@
     _assertGetMember(
       className: 'X',
       name: 'foo',
-      expected: 'M2.foo: () → void',
+      expected: 'M2.foo: void Function()',
     );
   }
 
@@ -992,7 +992,7 @@
     _assertGetMember(
       className: 'X',
       name: 'foo',
-      expected: 'B.foo: () → void',
+      expected: 'B.foo: void Function()',
     );
   }
 
@@ -1015,7 +1015,7 @@
     _assertGetMember(
       className: 'X',
       name: 'foo',
-      expected: 'X.foo: () → void',
+      expected: 'X.foo: void Function()',
     );
   }
 
@@ -1069,7 +1069,7 @@
       className: 'M',
       name: 'foo',
       forSuper: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -1089,7 +1089,7 @@
       className: 'X',
       name: 'foo',
       forSuper: true,
-      expected: 'M.foo: () → void',
+      expected: 'M.foo: void Function()',
     );
   }
 
@@ -1109,7 +1109,7 @@
       className: 'B',
       name: 'foo',
       forSuper: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
@@ -1145,7 +1145,7 @@
       className: 'B',
       name: 'foo',
       forSuper: true,
-      expected: 'A.foo: () → void',
+      expected: 'A.foo: void Function()',
     );
   }
 
diff --git a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
index d3bf71a..0069fd1 100644
--- a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
@@ -92,7 +92,7 @@
       {t: intType},
       {t: BottomTypeImpl.instance},
     ).substituteType(type);
-    assertElementTypeString(result, '(Never) → int');
+    assertElementTypeString(result, 'int Function(Never)');
   }
 }
 
@@ -138,11 +138,11 @@
 
     var type = findElement.genericTypeAlias('F').function.type;
     var t = findElement.typeParameter('T');
-    assertElementTypeString(type, '<U extends T>(U) → T');
+    assertElementTypeString(type, 'T Function<U extends T>(U)');
     _assertSubstitution(
       type,
       {t: intType},
-      '<U extends int>(U) → int',
+      'int Function<U extends int>(U)',
     );
   }
 
@@ -155,16 +155,16 @@
     var type = findElement.genericTypeAlias('F').function.type;
     var t = findElement.typeParameter('T');
     var u = findElement.typeParameter('U');
-    assertElementTypeString(type, '(U, bool) → T');
+    assertElementTypeString(type, 'T Function(U, bool)');
     _assertSubstitution(
       type,
       {t: intType},
-      '(U, bool) → int',
+      'int Function(U, bool)',
     );
     _assertSubstitution(
       type,
       {t: intType, u: doubleType},
-      '(double, bool) → int',
+      'int Function(double, bool)',
     );
   }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart b/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
index 37aa571..d1b41ac 100644
--- a/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
@@ -26,7 +26,7 @@
 ''');
     await resolveTestFile();
     assertNoTestErrors();
-    assertConstructors(findElement.class_('X'), ['X() → X']);
+    assertConstructors(findElement.class_('X'), ['X X()']);
   }
 
   test_element() async {
@@ -83,8 +83,8 @@
     await resolveTestFile();
     assertNoTestErrors();
 
-    assertConstructors(findElement.class_('C1'), ['C1(int i) → C1']);
-    assertConstructors(findElement.class_('C2'), ['C2(int i) → C2']);
+    assertConstructors(findElement.class_('C1'), ['C1 C1(int i)']);
+    assertConstructors(findElement.class_('C2'), ['C2 C2(int i)']);
   }
 
   test_implicitConstructors_optionalParameters() async {
@@ -105,9 +105,9 @@
     assertConstructors(
       findElement.class_('C'),
       [
-        'C.c1(int a) → C',
-        'C.c2(int a, [int b, int c]) → C',
-        'C.c3(int a, {int b, int c}) → C'
+        'C C.c1(int a)',
+        'C C.c2(int a, [int b, int c])',
+        'C C.c3(int a, {int b, int c})'
       ],
     );
   }
@@ -125,6 +125,6 @@
     await resolveTestFile();
     assertNoTestErrors();
 
-    assertConstructors(findElement.class_('B'), ['B(E x, E y) → B<E>']);
+    assertConstructors(findElement.class_('B'), ['B<E> B(E x, E y)']);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
index 7bfebe1..503a83f 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
@@ -51,7 +51,7 @@
 
     var invocation = findNode.functionExpressionInvocation('(0)');
     assertType(invocation, 'bool');
-    assertInvokeType(invocation, '(int) → bool');
+    assertInvokeType(invocation, 'bool Function(int)');
     assertTypeArgumentTypes(invocation, ['int']);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart b/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart
index 59062c6..ae124eb 100644
--- a/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart
@@ -46,4 +46,101 @@
 int Function(int a) y;
 ''');
   }
+
+  /// Test that when multiple [GenericFunctionType]s are used in a
+  /// [FunctionDeclaration], all of them are resolved correctly.
+  test_typeAnnotation_function() async {
+    await assertNoErrorsInCode('''
+void Function() f<T extends bool Function()>(int Function() a) {
+  return null;
+}
+
+double Function() x;
+''');
+    assertType(
+      findNode.genericFunctionType('void Function()'),
+      'void Function()',
+    );
+    assertType(
+      findNode.genericFunctionType('bool Function()'),
+      'bool Function()',
+    );
+    assertType(
+      findNode.genericFunctionType('int Function()'),
+      'int Function()',
+    );
+    assertType(
+      findNode.genericFunctionType('double Function()'),
+      'double Function()',
+    );
+  }
+
+  /// Test that when multiple [GenericFunctionType]s are used in a
+  /// [FunctionDeclaration], the one in the return type is consumed before the
+  /// one in the parameter type. This is necessary because matching of
+  /// [GenericFunctionType] nodes to their elements is based on the sequential
+  /// identifier of a node in the unit.
+  test_typeAnnotation_function_returnType_parameterType() async {
+    await assertNoErrorsInCode(r'''
+void Function(E a) f<E>(void Function() b) {
+  return (_) {};
+}
+''');
+  }
+
+  /// Test that when multiple [GenericFunctionType]s are used in a
+  /// [GenericFunctionType], all of them are resolved correctly.
+  test_typeAnnotation_genericFunctionType() async {
+    await assertNoErrorsInCode('''
+void f(
+  void Function() a,
+  bool Function() Function(int Function()) b,
+) {}
+''');
+  }
+
+  /// Test that when multiple [GenericFunctionType]s are used in a
+  /// [FunctionDeclaration], all of them are resolved correctly.
+  test_typeAnnotation_method() async {
+    await assertNoErrorsInCode('''
+class C {
+  void Function() m<T extends bool Function()>(int Function() a) {
+    return null;
+  }
+}
+
+double Function() x;
+''');
+    assertType(
+      findNode.genericFunctionType('void Function()'),
+      'void Function()',
+    );
+    assertType(
+      findNode.genericFunctionType('bool Function()'),
+      'bool Function()',
+    );
+    assertType(
+      findNode.genericFunctionType('int Function()'),
+      'int Function()',
+    );
+    assertType(
+      findNode.genericFunctionType('double Function()'),
+      'double Function()',
+    );
+  }
+
+  /// Test that when multiple [GenericFunctionType]s are used in a
+  /// [MethodDeclaration], the one in the return type is consumed before the
+  /// one in the parameter type. This is necessary because matching of
+  /// [GenericFunctionType] nodes to their elements is based on the sequential
+  /// identifier of a node in the unit.
+  test_typeAnnotation_method_returnType_parameterType() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  void Function(E a) f<E>(void Function() b) {
+    return (_) {};
+  }
+}
+''');
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index 0f402b5..c31ff84 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -38,7 +38,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'A'),
-      '(int) → void',
+      'void Function(int)',
     );
     assertSuperExpression(invocation.target);
   }
@@ -63,7 +63,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'A'),
-      '(int) → void',
+      'void Function(int)',
     );
     assertSuperExpression(invocation.target);
   }
@@ -88,7 +88,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'A'),
-      '() → int',
+      'int Function()',
     );
     assertSuperExpression(invocation.target);
   }
@@ -116,7 +116,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'M'),
-      '(int) → void',
+      'void Function(int)',
     );
     assertSuperExpression(invocation.target);
   }
@@ -140,7 +140,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'A'),
-      '() → int',
+      'int Function()',
     );
     assertSuperExpression(invocation.target);
   }
@@ -168,7 +168,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'A'),
-      '(int) → void',
+      'void Function(int)',
     );
     assertSuperExpression(invocation.target);
   }
@@ -195,7 +195,7 @@
     ]);
 
     var invocation = findNode.methodInvocation('foo(0)');
-    assertInvokeType(invocation, '(int) → void');
+    assertInvokeType(invocation, 'void Function(int)');
     assertType(invocation, 'void');
   }
 
@@ -221,7 +221,7 @@
     ]);
 
     var invocation = findNode.methodInvocation('foo(0)');
-    assertInvokeType(invocation, '(int) → void');
+    assertInvokeType(invocation, 'void Function(int)');
     assertType(invocation, 'void');
   }
 
@@ -311,7 +311,7 @@
     _assertInvalidInvocation(
       'c.foo();',
       findElement.getter('foo'),
-      expectedMethodNameType: '() → dynamic',
+      expectedMethodNameType: 'dynamic Function()',
     );
   }
 
@@ -332,7 +332,7 @@
     _assertInvalidInvocation(
       'foo();',
       findElement.getter('foo'),
-      expectedMethodNameType: '() → dynamic',
+      expectedMethodNameType: 'dynamic Function()',
     );
   }
 
@@ -351,7 +351,7 @@
     _assertInvalidInvocation(
       'foo();',
       findElement.getter('foo'),
-      expectedMethodNameType: '() → dynamic',
+      expectedMethodNameType: 'dynamic Function()',
     );
   }
 
@@ -383,8 +383,8 @@
     assertMethodInvocation(
       findNode.methodInvocation('foo(0)'),
       findElement.getter('foo'),
-      '(int) → double',
-      expectedMethodNameType: '() → T',
+      'double Function(int)',
+      expectedMethodNameType: 'T Function()',
     );
   }
 
@@ -405,7 +405,7 @@
     _assertInvalidInvocation(
       'foo()',
       findElement.getter('foo'),
-      expectedMethodNameType: '() → int',
+      expectedMethodNameType: 'int Function()',
     );
   }
 
@@ -426,7 +426,7 @@
     _assertInvalidInvocation(
       'foo()',
       findElement.getter('foo'),
-      expectedMethodNameType: '() → int',
+      expectedMethodNameType: 'int Function()',
     );
   }
 
@@ -449,7 +449,7 @@
     _assertInvalidInvocation(
       'foo()',
       findElement.getter('foo'),
-      expectedMethodNameType: '() → int',
+      expectedMethodNameType: 'int Function()',
     );
   }
 
@@ -476,7 +476,7 @@
     assertMethodInvocation(
       invocation,
       import.topFunction('foo'),
-      '() → void',
+      'void Function()',
     );
     assertImportPrefix(invocation.target, import.prefix);
   }
@@ -500,7 +500,7 @@
     assertMethodInvocation(
       invocation,
       import.importedLibrary.loadLibraryFunction,
-      '() → Future<dynamic>',
+      'Future<dynamic> Function()',
     );
     assertImportPrefix(invocation.target, import.prefix);
   }
@@ -867,7 +867,7 @@
       'c.foo()',
       findElement.getter('foo'),
       expectedNameType: 'void',
-      expectedMethodNameType: '() → void',
+      expectedMethodNameType: 'void Function()',
     );
   }
 
@@ -904,7 +904,7 @@
     assertMethodInvocation(
       findNode.methodInvocation('foo()()'),
       findElement.topFunction('foo'),
-      '() → void',
+      'void Function()',
     );
   }
 
@@ -924,7 +924,7 @@
       'foo()',
       findElement.topGet('foo'),
       expectedNameType: 'void',
-      expectedMethodNameType: '() → void',
+      expectedMethodNameType: 'void Function()',
     );
   }
 
@@ -943,7 +943,7 @@
     assertMethodInvocation(
       findNode.methodInvocation('toString()'),
       null,
-      '() → String',
+      'String Function()',
     );
   }
 
@@ -962,7 +962,7 @@
     assertMethodInvocation(
       findNode.methodInvocation('toString()'),
       null,
-      '() → String',
+      'String Function()',
     );
   }
 
@@ -981,7 +981,7 @@
     assertMethodInvocation(
       findNode.methodInvocation('toString()'),
       null,
-      '() → String',
+      'String Function()',
     );
   }
 
@@ -1000,7 +1000,7 @@
     assertMethodInvocation(
       findNode.methodInvocation('foo<int>()'),
       findElement.topFunction('foo'),
-      '() → void',
+      'void Function()',
     );
     assertTypeName(findNode.typeName('int>'), intElement, 'int');
   }
@@ -1020,7 +1020,7 @@
     assertMethodInvocation(
       findNode.methodInvocation('foo<int>()'),
       findElement.topFunction('foo'),
-      '() → Map<num, dynamic>',
+      'Map<num, dynamic> Function()',
       expectedTypeArguments: ['num', 'dynamic'],
     );
     assertTypeName(findNode.typeName('int>'), intElement, 'int');
@@ -1043,8 +1043,8 @@
     assertMethodInvocation(
       invocation,
       findElement.getter('foo'),
-      '(int) → double',
-      expectedMethodNameType: '() → (int) → double',
+      'double Function(int)',
+      expectedMethodNameType: 'double Function(int) Function()',
     );
     assertClassRef(invocation.target, findElement.class_('C'));
   }
@@ -1066,7 +1066,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
     assertClassRef(invocation.target, findElement.class_('C'));
   }
@@ -1088,7 +1088,7 @@
     assertMethodInvocation(
       invocation,
       import.importedLibrary.loadLibraryFunction,
-      '() → Future<dynamic>',
+      'Future<dynamic> Function()',
     );
     assertImportPrefix(invocation.target, import.prefix);
   }
@@ -1108,10 +1108,10 @@
     assertMethodInvocation(
       invocation,
       null,
-      '(int) → void',
+      'void Function(int)',
     );
     assertElement(invocation.target, findElement.topFunction('foo'));
-    assertType(invocation.target, '(int) → void');
+    assertType(invocation.target, 'void Function(int)');
   }
 
   test_hasReceiver_importPrefix_topFunction() async {
@@ -1135,7 +1135,7 @@
     assertMethodInvocation(
       invocation,
       import.topFunction('foo'),
-      '(int, int) → int',
+      'int Function(int, int)',
       expectedTypeArguments: ['int'],
     );
     assertImportPrefix(invocation.target, import.prefix);
@@ -1162,8 +1162,8 @@
     assertMethodInvocation(
       invocation,
       import.topGetter('foo'),
-      '(int, int) → int',
-      expectedMethodNameType: '() → <T>(T, T) → T',
+      'int Function(int, int)',
+      expectedMethodNameType: 'T Function<T>(T, T) Function()',
       expectedTypeArguments: ['int'],
     );
     assertImportPrefix(invocation.target, import.prefix);
@@ -1212,8 +1212,8 @@
     assertMethodInvocation(
       invocation,
       findElement.getter('foo'),
-      '(int) → double',
-      expectedMethodNameType: '() → (int) → double',
+      'double Function(int)',
+      expectedMethodNameType: 'double Function(int) Function()',
     );
   }
 
@@ -1234,8 +1234,8 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo'),
-      '(int) → void',
-      expectedMethodNameType: '(int) → void',
+      'void Function(int)',
+      expectedMethodNameType: 'void Function(int)',
     );
     assertTypeArgumentTypes(invocation, []);
   }
@@ -1259,8 +1259,8 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo'),
-      '(int) → int',
-      expectedMethodNameType: '(int) → int',
+      'int Function(int)',
+      expectedMethodNameType: 'int Function(int)',
       expectedTypeArguments: ['int'],
     );
     assertTypeArgumentTypes(invocation, ['int']);
@@ -1293,7 +1293,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'I2'),
-      '(Object) → void',
+      'void Function(Object)',
     );
   }
 
@@ -1318,7 +1318,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
   }
 
@@ -1345,8 +1345,8 @@
     assertMethodInvocation(
       invocation,
       import.class_('C').getGetter('foo'),
-      '(int) → double',
-      expectedMethodNameType: '() → (int) → double',
+      'double Function(int)',
+      expectedMethodNameType: 'double Function(int) Function()',
     );
 
     PrefixedIdentifier target = invocation.target;
@@ -1377,7 +1377,7 @@
     assertMethodInvocation(
       invocation,
       import.class_('C').getMethod('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
 
     PrefixedIdentifier target = invocation.target;
@@ -1404,8 +1404,8 @@
     assertMethodInvocation(
       invocation,
       findElement.getter('foo', of: 'A'),
-      '(int) → double',
-      expectedMethodNameType: '() → (int) → double',
+      'double Function(int)',
+      expectedMethodNameType: 'double Function(int) Function()',
     );
     assertSuperExpression(invocation.target);
   }
@@ -1429,7 +1429,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo', of: 'A'),
-      '(int) → void',
+      'void Function(int)',
     );
     assertSuperExpression(invocation.target);
   }
@@ -1449,7 +1449,7 @@
     assertMethodInvocation(
       invocation,
       findElement.topFunction('foo'),
-      '({a: int, b: bool}) → void',
+      'void Function({a: int, b: bool})',
     );
     assertNamedParameterRef('b: false', 'b');
     assertNamedParameterRef('a: 0', 'a');
@@ -1474,8 +1474,8 @@
     assertMethodInvocation(
       invocation,
       findElement.getter('foo'),
-      '(int) → double',
-      expectedMethodNameType: '() → (int) → double',
+      'double Function(int)',
+      expectedMethodNameType: 'double Function(int) Function()',
     );
   }
 
@@ -1496,8 +1496,8 @@
     assertMethodInvocation(
       invocation,
       findElement.getter('foo'),
-      '(int) → double',
-      expectedMethodNameType: '() → (int) → double',
+      'double Function(int)',
+      expectedMethodNameType: 'double Function(int) Function()',
     );
   }
 
@@ -1531,7 +1531,7 @@
     assertMethodInvocation(
       invocation,
       findElement.localFunction('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
   }
 
@@ -1550,7 +1550,7 @@
     assertMethodInvocation(
       invocation,
       findElement.localVar('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
   }
 
@@ -1571,7 +1571,7 @@
     assertMethodInvocation(
       invocation,
       findElement.parameter('c'),
-      '(int) → void',
+      'void Function(int)',
     );
   }
 
@@ -1591,7 +1591,7 @@
     assertMethodInvocation(
       invocation,
       findElement.localVar('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
   }
 
@@ -1614,7 +1614,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
   }
 
@@ -1635,7 +1635,7 @@
     assertMethodInvocation(
       invocation,
       findElement.method('foo'),
-      '(int) → void',
+      'void Function(int)',
     );
   }
 
@@ -1654,8 +1654,8 @@
     assertMethodInvocation(
       invocation,
       findElement.topFunction('foo'),
-      '(int) → void',
-      expectedMethodNameType: '(int) → void',
+      'void Function(int)',
+      expectedMethodNameType: 'void Function(int)',
     );
   }
 
@@ -1674,8 +1674,8 @@
     assertMethodInvocation(
       invocation,
       findElement.topGet('foo'),
-      '(int) → double',
-      expectedMethodNameType: '() → (int) → double',
+      'double Function(int)',
+      expectedMethodNameType: 'double Function(int) Function()',
     );
   }
 
@@ -1694,8 +1694,8 @@
     assertMethodInvocation(
       invocation,
       findElement.topGet('foo'),
-      '(int) → void',
-      expectedMethodNameType: '() → (int) → void',
+      'void Function(int)',
+      expectedMethodNameType: 'void Function(int) Function()',
     );
   }
 
@@ -1726,7 +1726,7 @@
     assertMethodInvocation(
       invocation,
       typeProvider.objectType.getMethod('toString'),
-      '() → String',
+      'String Function()',
     );
   }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
index a88f8a3..671bdef5 100644
--- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -1689,7 +1689,7 @@
 M<T> f<T>() => null;
 ''');
     var fInvocation = findNode.methodInvocation('f()');
-    expect(fInvocation.staticInvokeType.toString(), '() → M<int>');
+    expect(fInvocation.staticInvokeType.toString(), 'M<int> Function()');
   }
 
   test_onClause() async {
@@ -1776,7 +1776,7 @@
 
     var invocation = findNode.methodInvocation('foo(42)');
     assertElement(invocation, findElement.method('foo'));
-    assertInvokeType(invocation, '(int) → void');
+    assertInvokeType(invocation, 'void Function(int)');
     assertType(invocation, 'void');
   }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
index 0011f32..7be6ca3 100644
--- a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
@@ -195,6 +195,30 @@
     assertType(findNode.typeName('T? b'), 'T?');
   }
 
+  test_member_potentiallyNullable_called() async {
+    addTestFile(r'''
+m<T extends Function>() {
+  List<T?> x;
+  x.first();
+}
+''');
+    await resolveTestFile();
+    // Do not assert no test errors. Deliberately invokes nullable type.
+    assertType(findNode.methodInvocation('first').methodName, 'Function?');
+  }
+
+  test_null_assertion_operator_changes_null_to_never() async {
+    addTestFile('''
+main() {
+  Null x = null;
+  x!;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.postfix('x!'), 'Never');
+  }
+
   test_null_assertion_operator_removes_nullability() async {
     addTestFile('''
 main() {
@@ -218,7 +242,7 @@
     await resolveTestFile();
     assertNoTestErrors();
 
-    assertType(findNode.typeName('F? a'), '(bool, String?) → int??');
+    assertType(findNode.typeName('F? a'), 'int? Function(bool, String?)?');
   }
 
   @failingTest
@@ -235,7 +259,7 @@
 
     assertType(
       findNode.typeName('F<String>'),
-      '(bool!, String!, String?) → int??',
+      'int? Function(bool!, String!, String?)?',
     );
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
index 813eec5..5a47b69 100644
--- a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
@@ -114,6 +114,46 @@
     );
   }
 
+  test_prefixed_unnamed_generic() async {
+    newFile('/test/lib/a.dart', content: r'''
+class C<T> {
+  const C();
+}
+''');
+    await assertNoErrorsInCode(r'''
+import 'a.dart' as p;
+
+const x = p.C<int>();
+''');
+    _fillLibraries();
+
+    var element_C = libraryA.getType('C');
+    var element_p = findElement.prefix('p');
+
+    var creation = findNode.instanceCreation('p.C<int>()');
+    assertType(creation, 'C<int>');
+
+    var constructorName = creation.constructorName;
+
+    var typeName = constructorName.type;
+    assertType(typeName, 'C<int>');
+
+    var pC = typeName.name as PrefixedIdentifier;
+    assertElement(pC, element_C);
+    // TODO(scheglov) enforce
+//    assertTypeNull(pC);
+
+    var ref_p = pC.prefix;
+    assertElement(ref_p, element_p);
+    assertTypeNull(ref_p);
+
+    var ref_C = pC.identifier;
+    assertElement(ref_C, element_C);
+    assertTypeNull(ref_C);
+
+    assertType(typeName.typeArguments.arguments[0], 'int');
+  }
+
   void _fillLibraries([LibraryElement library]) {
     library ??= result.unit.declaredElement.library;
     var uriStr = library.source.uri.toString();
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index fadcc32..56deafe 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -198,7 +198,7 @@
     var getter = findElement.topGet(name);
     assertElement(ref, getter);
 
-    var type = getter.returnType.toString();
+    var type = typeString(getter.returnType);
     assertType(ref, type);
   }
 
@@ -206,7 +206,7 @@
     var setter = findElement.topSet(name);
     assertElement(ref, setter);
 
-    var type = setter.parameters[0].type.toString();
+    var type = typeString(setter.parameters[0].type);
     assertType(ref, type);
   }
 
@@ -263,8 +263,8 @@
   }
 
   void assertInvokeType(InvocationExpression node, String expected) {
-    DartType actual = node.staticInvokeType;
-    expect(actual?.toString(), expected);
+    TypeImpl actual = node.staticInvokeType;
+    expect(typeString(actual), expected);
   }
 
   void assertInvokeTypeDynamic(InvocationExpression node) {
@@ -275,7 +275,7 @@
   void assertMember(
       Expression node, String expectedDefiningType, Element expectedBase) {
     Member actual = getNodeElement(node);
-    expect(actual.definingType.toString(), expectedDefiningType);
+    expect(typeString(actual.definingType), expectedDefiningType);
     expect(actual.baseElement, same(expectedBase));
   }
 
@@ -373,15 +373,14 @@
     } else {
       fail('Unsupported node: (${node.runtimeType}) $node');
     }
-    expect(actual?.toString(withNullability: typeToStringWithNullability),
-        expected);
+    expect(typeString(actual), expected);
   }
 
   void assertTypeArgumentTypes(
     InvocationExpression node,
     List<String> expected,
   ) {
-    var actual = node.typeArgumentTypes.map((t) => '$t').toList();
+    var actual = node.typeArgumentTypes.map((t) => typeString(t)).toList();
     expect(actual, expected);
   }
 
@@ -460,6 +459,11 @@
     findElement = new FindElement(result.unit);
   }
 
+  /// Return a textual representation of the [type] that is appropriate for
+  /// tests.
+  String typeString(DartType type) => (type as TypeImpl)
+      ?.toString(withNullability: typeToStringWithNullability);
+
   Element _unwrapHandle(Element element) {
     if (element is ElementHandle && element is! Member) {
       return element.actualElement;
@@ -468,8 +472,8 @@
   }
 
   static String _extractReturnType(String invokeType) {
-    int arrowIndex = invokeType.indexOf('→');
-    expect(arrowIndex, isNonNegative);
-    return invokeType.substring(arrowIndex + 1).trim();
+    int functionIndex = invokeType.indexOf(' Function');
+    expect(functionIndex, isNonNegative);
+    return invokeType.substring(0, functionIndex);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart
new file mode 100644
index 0000000..0b07098
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart
@@ -0,0 +1,335 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ForElementWithNnbdTest);
+    defineReflectiveTests(IfElementWithNnbdTest);
+    defineReflectiveTests(SpreadElementWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class ForElementWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_list_awaitForIn_dynamic_downward() async {
+    addTestFile('''
+void f() async {
+  var b = <int>[await for (var e in a()) e];
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
+  }
+
+  @failingTest
+  test_list_awaitForIn_int_downward() async {
+    addTestFile('''
+void f() async {
+  var b = <int>[await for (int e in a()) e];
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
+  }
+
+  @failingTest
+  test_list_for_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>[for (int i = 0; a(); i++) i];
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+
+  @failingTest
+  test_list_forIn_dynamic_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>[for (var e in a()) e];
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
+  }
+
+  @failingTest
+  test_list_forIn_int_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>[for (int e in a()) e];
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<int> Function()');
+  }
+
+  @failingTest
+  test_map_awaitForIn_dynamic_downward() async {
+    addTestFile('''
+void f() async {
+  var b = <int, int>{await for (var e in a()) e : e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
+  }
+
+  @failingTest
+  test_map_awaitForIn_int_downward() async {
+    addTestFile('''
+void f() async {
+  var b = <int, int>{await for (int e in a()) e : e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
+  }
+
+  @failingTest
+  test_map_for_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int, int>{for (int i = 0; a(); i++) i : i};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+
+  @failingTest
+  test_map_forIn_dynamic_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int, int>{for (var e in a()) e : e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
+  }
+
+  @failingTest
+  test_map_forIn_int_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int, int>{for (int e in a()) e : e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<int> Function()');
+  }
+
+  @failingTest
+  test_set_awaitForIn_dynamic_downward() async {
+    addTestFile('''
+void f() async {
+  var b = <int>{await for (var e in a()) e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
+  }
+
+  @failingTest
+  test_set_awaitForIn_int_downward() async {
+    addTestFile('''
+void f() async {
+  var b = <int>{await for (int e in a()) e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
+  }
+
+  @failingTest
+  test_set_for_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>{for (int i = 0; a(); i++) i};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+
+  @failingTest
+  test_set_forIn_dynamic_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>{for (var e in a()) e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
+  }
+
+  @failingTest
+  test_set_forIn_int_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>{for (int e in a()) e};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<int> Function()');
+  }
+}
+
+@reflectiveTest
+class IfElementWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_list_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>[if (a()) 1];
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+
+  @failingTest
+  test_map_downward() async {
+    addTestFile('''
+void f() {
+  var b = <String, int>{if (a()) 'a' : 1};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+
+  @failingTest
+  test_set_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>{if (a()) 1};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+}
+
+@reflectiveTest
+class SpreadElementWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_list_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>[...a()];
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<int> Function()');
+  }
+
+  @failingTest
+  test_map_downward() async {
+    addTestFile('''
+void f() {
+  var b = <String, int>{...a()};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Map<String, int> Function()');
+  }
+
+  @failingTest
+  test_set_downward() async {
+    addTestFile('''
+void f() {
+  var b = <int>{...a()};
+  print(b);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<int> Function()');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
new file mode 100644
index 0000000..72ebc03
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConditionalExpressionTest);
+    defineReflectiveTests(ConditionalExpressionWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class ConditionalExpressionTest extends DriverResolutionTest {
+  test_upward() async {
+    addTestFile('''
+void f(bool a, int b, int c) {
+  var d = a ? b : c;
+  print(d);
+}
+''');
+    await resolveTestFile();
+    assertType(findNode.simple('d)'), 'int');
+  }
+}
+
+@reflectiveTest
+class ConditionalExpressionWithNnbdTest extends ConditionalExpressionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f(int b, int c) {
+  var d = a() ? b : c;
+  print(d);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('d)'), 'bool Function()');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart
index 7f26d21..bf31077 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart
@@ -19,7 +19,7 @@
 
 @reflectiveTest
 class LogicalAndTest extends DriverResolutionTest {
-  test_simple() async {
+  test_upward() async {
     addTestFile('''
 void f(bool a, bool b) {
   var c = a && b;
@@ -40,11 +40,26 @@
 
   @override
   bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f(b) {
+  var c = a() && b();
+  print(c);
+}
+T a<T>() => throw '';
+T b<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+    assertInvokeType(findNode.methodInvocation('b('), 'bool Function()');
+  }
 }
 
 @reflectiveTest
 class LogicalOrTest extends DriverResolutionTest {
-  test_simple() async {
+  test_upward() async {
     addTestFile('''
 void f(bool a, bool b) {
   var c = a || b;
@@ -65,4 +80,19 @@
 
   @override
   bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f(b) {
+  var c = a() || b();
+  print(c);
+}
+T a<T>() => throw '';
+T b<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+    assertInvokeType(findNode.methodInvocation('b('), 'bool Function()');
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart
index 2f8bf00..60335c4 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart
@@ -17,7 +17,7 @@
 
 @reflectiveTest
 class NotTest extends DriverResolutionTest {
-  test_simple() async {
+  test_upward() async {
     addTestFile('''
 void f(bool a) {
   var b = !a;
@@ -38,4 +38,17 @@
 
   @override
   bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f(b) {
+  var c = !a();
+  print(c);
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart
new file mode 100644
index 0000000..6137756
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart
@@ -0,0 +1,185 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AssertWithNnbdTest);
+    defineReflectiveTests(DoWithNnbdTest);
+    defineReflectiveTests(ForWithNnbdTest);
+    defineReflectiveTests(IfWithNnbdTest);
+    defineReflectiveTests(WhileWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class AssertWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f() {
+  assert(a());
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+}
+
+@reflectiveTest
+class DoWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f() {
+  do {} while(a())
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+}
+
+@reflectiveTest
+class ForWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_awaitForIn_dynamic_downward() async {
+    addTestFile('''
+void f() async {
+  await for (var e in a()) {}
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
+  }
+
+  @failingTest
+  test_awaitForIn_int_downward() async {
+    addTestFile('''
+void f() async {
+  await for (int e in a()) {}
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
+  }
+
+  @failingTest
+  test_for_downward() async {
+    addTestFile('''
+void f() {
+  for (int i = 0; a(); i++) {}
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+
+  @failingTest
+  test_forIn_dynamic_downward() async {
+    addTestFile('''
+void f() {
+  for (var e in a()) {}
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
+  }
+
+  @failingTest
+  test_forIn_int_downward() async {
+    addTestFile('''
+void f() {
+  for (int e in a()) {}
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(
+        findNode.methodInvocation('a('), 'Iterable<int> Function()');
+  }
+}
+
+@reflectiveTest
+class IfWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f() {
+  if (a()) {}
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+}
+
+@reflectiveTest
+class WhileWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f() {
+  while (a()) {}
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
index 8d7aae0..0369a65 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
@@ -4,22 +4,30 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'collection_elements_test.dart' as collection_elements;
+import 'conditional_expression_test.dart' as conditional_expression;
 import 'equality_expressions_test.dart' as equality_expressions;
 import 'list_literal_test.dart' as list_literal;
 import 'logical_boolean_expressions_test.dart' as logical_boolean_expressions;
 import 'map_literal_test.dart' as map_literal;
 import 'prefix_expressions_test.dart' as prefix_expressions;
 import 'set_literal_test.dart' as set_literal;
+import 'statements_test.dart' as statements;
+import 'throw_test.dart' as throw_expression;
 import 'type_test_expressions_test.dart' as type_test_expressions;
 
 main() {
   defineReflectiveSuite(() {
+    collection_elements.main();
+    conditional_expression.main();
     equality_expressions.main();
     list_literal.main();
     logical_boolean_expressions.main();
     map_literal.main();
     prefix_expressions.main();
     set_literal.main();
+    statements.main();
+    throw_expression.main();
     type_test_expressions.main();
   }, name: 'type inference');
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart
new file mode 100644
index 0000000..8cdfe3a
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ThrowWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class ThrowWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  @failingTest
+  test_downward() async {
+    addTestFile('''
+void f() {
+  throw a();
+}
+T a<T>() => throw '';
+''');
+    await resolveTestFile();
+    assertInvokeType(findNode.methodInvocation('a('), 'dynamic Function()');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
index 28b285e..06192b0 100644
--- a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
@@ -2,7 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -10,6 +12,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ArgumentTypeNotAssignableTest);
+    defineReflectiveTests(ArgumentTypeNotAssignableTest_NNBD);
   });
 }
 
@@ -41,3 +44,45 @@
     ]);
   }
 }
+
+@reflectiveTest
+class ArgumentTypeNotAssignableTest_NNBD extends ArgumentTypeNotAssignableTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions =>
+      AnalysisOptionsImpl()..enabledExperiments = [EnableString.non_nullable];
+
+  test_downcast() async {
+    await assertErrorsInCode(r'''
+m() {
+  num y = 1;
+  n(y);
+}
+n(int x) {}
+''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 23, 1),
+    ]);
+  }
+
+  @failingTest
+  test_downcast_nullableNonNullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? y;
+  n(y);
+}
+n(int x) {}
+''', [
+      error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 24, 1),
+    ]);
+  }
+
+  test_dynamicCast() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  dynamic i;
+  n(i);
+}
+n(int i) {}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart b/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart
index 28ab163..f773a8c 100644
--- a/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart
@@ -16,278 +16,6 @@
 
 @reflectiveTest
 class AsyncKeywordUsedAsIdentifierTest extends DriverResolutionTest {
-  test_async_annotation() async {
-    await assertErrorsInCode('''
-const int async = 0;
-f() async {
-  g(@async x) {}
-  g(0);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 38, 5),
-    ]);
-  }
-
-  test_async_argumentLabel() async {
-    await assertErrorsInCode('''
-f(c) async {
-  c.g(async: 0);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 19, 5),
-    ]);
-  }
-
-  test_async_async() async {
-    await assertErrorsInCode('''
-f() async {
-  var async = 1;
-  print(async);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 18, 5),
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 37, 5),
-    ]);
-  }
-
-  test_async_asyncStar() async {
-    await assertErrorsInCode('''
-f() async* {
-  var async = 1;
-  print(async);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 19, 5),
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 38, 5),
-    ]);
-  }
-
-  test_async_break() async {
-    await assertErrorsInCode('''
-f() async {
-  while (true) {
-    break async;
-  }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 39, 5),
-      error(CompileTimeErrorCode.LABEL_UNDEFINED, 39, 5),
-    ]);
-  }
-
-  test_async_catchException() async {
-    await assertErrorsInCode('''
-g() {}
-f() async {
-  try {
-    g();
-  } catch (async) { }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 47, 5),
-    ]);
-  }
-
-  test_async_catchStacktrace() async {
-    await assertErrorsInCode('''
-g() {}
-f() async {
-  try {
-    g();
-  } catch (e, async) { }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 50, 5),
-      error(HintCode.UNUSED_CATCH_STACK, 50, 5),
-    ]);
-  }
-
-  test_async_continue() async {
-    await assertErrorsInCode('''
-f() async {
-  while (true) {
-    continue async;
-  }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 42, 5),
-      error(CompileTimeErrorCode.LABEL_UNDEFINED, 42, 5),
-    ]);
-  }
-
-  test_async_for() async {
-    await assertErrorsInCode('''
-var async;
-f() async {
-  for (async in []) {}
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 30, 5),
-    ]);
-  }
-
-  test_async_formalParameter() async {
-    await assertErrorsInCode('''
-f() async {
-  g(int async) {}
-  g(0);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 20, 5),
-    ]);
-  }
-
-  test_async_getter() async {
-    await assertErrorsInCode('''
-class C {
-  int get async => 1;
-}
-f() async {
-  return new C().async;
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 63, 5),
-    ]);
-  }
-
-  test_async_invocation() async {
-    await assertErrorsInCode('''
-class C {
-  int async() => 1;
-}
-f() async {
-  return new C().async();
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 61, 5),
-    ]);
-  }
-
-  test_async_invocation_cascaded() async {
-    await assertErrorsInCode('''
-class C {
-  int async() => 1;
-}
-f() async {
-  return new C()..async();
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 62, 5),
-    ]);
-  }
-
-  test_async_label() async {
-    await assertErrorsInCode('''
-f() async {
-  async: g();
-}
-g() {}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 14, 5),
-      error(HintCode.UNUSED_LABEL, 14, 6),
-    ]);
-  }
-
-  test_async_localFunction() async {
-    await assertErrorsInCode('''
-f() async {
-  int async() => null;
-  async();
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 18, 5),
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 37, 5),
-    ]);
-  }
-
-  test_async_prefix() async {
-    await assertErrorsInCode('''
-import 'dart:async' as async;
-f() async {
-  return new async.Future.value(0);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 55, 5),
-    ]);
-  }
-
-  test_async_setter() async {
-    await assertErrorsInCode('''
-class C {
-  void set async(int i) {}
-}
-f() async {
-  new C().async = 1;
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 61, 5),
-    ]);
-  }
-
-  test_async_setter_cascaded() async {
-    await assertErrorsInCode('''
-class C {
-  void set async(int i) {}
-}
-f() async {
-  return new C()..async = 1;
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 69, 5),
-    ]);
-  }
-
-  test_async_stringInterpolation() async {
-    await assertErrorsInCode(r'''
-int async = 1;
-f() async {
-  return "$async";
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 38, 5),
-    ]);
-  }
-
-  test_async_suffix() async {
-    newFile("/test/lib/lib1.dart", content: r'''
-library lib1;
-int async;
-''');
-    await assertErrorsInCode('''
-import 'lib1.dart' as l;
-f() async {
-  return l.async;
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 48, 5),
-    ]);
-  }
-
-  test_async_switchLabel() async {
-    await assertErrorsInCode('''
-f() async {
-  switch (0) {
-    async: case 0: break;
-  }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 31, 5),
-      error(HintCode.UNUSED_LABEL, 31, 6),
-    ]);
-  }
-
-  test_async_syncStar() async {
-    await assertErrorsInCode('''
-f() sync* {
-  var async = 1;
-  print(async);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 18, 5),
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 37, 5),
-    ]);
-  }
-
   test_await_async() async {
     await assertErrorsInCode('''
 f() async {
diff --git a/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart b/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
index 1769170..30e9267 100644
--- a/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
@@ -36,10 +36,7 @@
 ''');
   }
 
-  @failingTest
   test_inferredType() async {
-    // This test is failing because summary support is incomplete, which results
-    // in the constructor having a type of 'List<C*>*'.
     await assertErrorsInCode('''
 class C {}
 List<C> v = List(5);
@@ -48,16 +45,6 @@
     ]);
   }
 
-  test_starType() async {
-    // TODO(brianwilkerson) This test is currently taking advantage of the fact
-    //  that the SDK is not opted in, which makes the use of `int` below a
-    //  reference to 'int*'. When it's possible to opt-out in a test this needs
-    //  to be updated to use an explicitly opted out type.
-    await assertNoErrorsInCode('''
-List<int> v = List(5);
-''');
-  }
-
   test_typeParameter() async {
     await assertErrorsInCode('''
 class C<T> {
diff --git a/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart b/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart
index cee830f..3a1725e 100644
--- a/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart
@@ -16,14 +16,18 @@
 @reflectiveTest
 class MapEntryNotInMapTest extends DriverResolutionTest {
   test_set() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var c = <int>{1:2};
-''', [CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP]);
+''', [
+      error(CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP, 14, 3),
+    ]);
   }
 
   test_set_const() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var c = const <int>{1:2};
-''', [CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP]);
+''', [
+      error(CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP, 20, 3),
+    ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
index 9fea9f5..949841c 100644
--- a/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
@@ -19,7 +19,7 @@
 @reflectiveTest
 class MapKeyTypeNotAssignableTest extends DriverResolutionTest {
   test_const_ifElement_thenElseFalse_intInt_dynamic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 0;
 const dynamic b = 0;
@@ -27,76 +27,96 @@
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 68, 32),
+              ]);
   }
 
   test_const_ifElement_thenElseFalse_intString_dynamic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 0;
 const dynamic b = 'b';
 var v = const <int, bool>{if (1 < 0) a: true else b: false};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 94, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 70, 32),
+              ]);
   }
 
   test_const_ifElement_thenFalse_intString_dynamic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 'a';
 var v = const <int, bool>{if (1 < 0) a: true};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 18),
+              ]);
   }
 
   test_const_ifElement_thenFalse_intString_value() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 var v = const <int, bool>{if (1 < 0) 'a': true};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]
+            ? [
+                error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 37, 3),
+              ]
             : [
-                StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
-                CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 26, 20),
+                error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 37, 3),
               ]);
   }
 
   test_const_ifElement_thenTrue_intInt_dynamic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 0;
 var v = const <int, bool>{if (true) a: true};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 47, 17),
+              ]);
   }
 
   test_const_ifElement_thenTrue_intString_dynamic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 'a';
 var v = const <int, bool>{if (true) a: true};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 59, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 17),
+              ]);
   }
 
   test_const_ifElement_thenTrue_notConst() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 final a = 0;
 var v = const <int, bool>{if (1 < 2) a: true};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 50, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 39, 18),
+              ]);
   }
 
   test_const_intInt_dynamic() async {
@@ -107,39 +127,47 @@
   }
 
   test_const_intString_dynamic() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const dynamic a = 'a';
 var v = const <int, bool>{a : true};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 49, 1),
+    ]);
   }
 
   test_const_intString_value() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = const <int, bool>{'a' : true};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 26, 3),
+    ]);
   }
 
   test_const_spread_intInt() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 var v = const <int, String>{...{1: 'a'}};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 28, 11),
+              ]);
   }
 
   test_const_spread_intString_dynamic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 'a';
 var v = const <int, String>{...{a: 'a'}};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]
+            ? [
+                error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 55, 1),
+              ]
             : [
-                StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
-                CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 51, 11),
+                error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 55, 1),
               ]);
   }
 
@@ -160,9 +188,11 @@
   }
 
   test_nonConst_ifElement_thenFalse_intString_value() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <int, bool>{if (1 < 0) 'a': true};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 31, 3),
+    ]);
   }
 
   test_nonConst_ifElement_thenTrue_intInt_dynamic() async {
@@ -194,9 +224,11 @@
   }
 
   test_nonConst_intString_value() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <int, bool>{'a' : true};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 20, 3),
+    ]);
   }
 
   test_nonConst_spread_intInt() async {
@@ -212,9 +244,11 @@
   }
 
   test_nonConst_spread_intString() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <int, String>{...{'a': 'a'}};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 26, 3),
+    ]);
   }
 
   test_nonConst_spread_intString_dynamic() async {
diff --git a/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
index 30e7865..86a5746 100644
--- a/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
@@ -2,7 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -10,13 +12,14 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MapValueTypeNotAssignableTest);
+    defineReflectiveTests(MapValueTypeNotAssignableWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class MapValueTypeNotAssignableTest extends DriverResolutionTest {
   test_const_ifElement_thenElseFalse_intInt_dynamic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 0;
 const dynamic b = 0;
@@ -24,76 +27,96 @@
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 68, 32),
+              ]);
   }
 
   test_const_ifElement_thenElseFalse_intString_dynamic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 0;
 const dynamic b = 'b';
 var v = const <bool, int>{if (1 < 0) true: a else false: b};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 101, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 70, 32),
+              ]);
   }
 
   test_const_ifElement_thenFalse_intString_dynamic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 'a';
 var v = const <bool, int>{if (1 < 0) true: a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 18),
+              ]);
   }
 
   test_const_ifElement_thenFalse_intString_value() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 var v = const <bool, int>{if (1 < 0) true: 'a'};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]
+            ? [
+                error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 43, 3),
+              ]
             : [
-                StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
-                CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 26, 20),
+                error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 43, 3),
               ]);
   }
 
   test_const_ifElement_thenTrue_intInt_dynamic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 0;
 var v = const <bool, int>{if (true) true: a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 47, 17),
+              ]);
   }
 
   test_const_ifElement_thenTrue_intString_dynamic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 'a';
 var v = const <bool, int>{if (true) true: a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 65, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 17),
+              ]);
   }
 
   test_const_ifElement_thenTrue_notConst() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 final a = 0;
 var v = const <bool, int>{if (1 < 2) true: a};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            ? [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 56, 1),
+              ]
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 39, 18),
+              ]);
   }
 
   test_const_intInt_dynamic() async {
@@ -104,39 +127,47 @@
   }
 
   test_const_intString_dynamic() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 const dynamic a = 'a';
 var v = const <bool, int>{true: a};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 55, 1),
+    ]);
   }
 
   test_const_intString_value() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = const <bool, int>{true: 'a'};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 32, 3),
+    ]);
   }
 
   test_const_spread_intInt() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 var v = const <bool, int>{...{true: 1}};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
             ? []
-            : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+            : [
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 26, 12),
+              ]);
   }
 
   test_const_spread_intString_dynamic() async {
-    await assertErrorCodesInCode(
+    await assertErrorsInCode(
         '''
 const dynamic a = 'a';
 var v = const <bool, int>{...{true: a}};
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]
+            ? [
+                error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 59, 1),
+              ]
             : [
-                StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
-                CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT
+                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 12),
+                error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 59, 1),
               ]);
   }
 
@@ -157,9 +188,11 @@
   }
 
   test_nonConst_ifElement_thenFalse_intString_value() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <bool, int>{if (1 < 0) true: 'a'};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 37, 3),
+    ]);
   }
 
   test_nonConst_ifElement_thenTrue_intInt_dynamic() async {
@@ -191,9 +224,11 @@
   }
 
   test_nonConst_intString_value() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <bool, int>{true: 'a'};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 26, 3),
+    ]);
   }
 
   test_nonConst_spread_intInt() async {
@@ -209,9 +244,11 @@
   }
 
   test_nonConst_spread_intString() async {
-    await assertErrorCodesInCode('''
+    await assertErrorsInCode('''
 var v = <bool, int>{...{true: 'a'}};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+      error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 30, 3),
+    ]);
   }
 
   test_nonConst_spread_intString_dynamic() async {
@@ -221,3 +258,11 @@
 ''');
   }
 }
+
+@reflectiveTest
+class MapValueTypeNotAssignableWithConstantsTest
+    extends MapValueTypeNotAssignableTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
+}
diff --git a/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart b/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
index dd0e60d..fa860a6 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
@@ -248,12 +248,12 @@
 
   test_functionInvocation() async {
     await assertErrorsInCode(r'''
-void Function({required int a}) f() => null;
+void Function({required int a}) f() => throw '';
 g() {
   f()();
 }
 ''', [
-      error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 53, 5),
+      error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 57, 5),
     ]);
   }
 
@@ -305,7 +305,7 @@
 typedef String F({required String x});
 
 class C {
-  F m() => ({required String x}) => null;
+  F m() => ({required String x}) => throw '';
 }
 ''', [
       error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 20, 7),
diff --git a/pkg/analyzer/test/src/diagnostics/missing_return_test.dart b/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
index 41042fb..56a4de8 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
@@ -32,10 +32,12 @@
   }
 
   test_async() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'dart:async';
 Future<int> f() async {}
-''', [HintCode.MISSING_RETURN]);
+''', [
+      error(HintCode.MISSING_RETURN, 21, 11),
+    ]);
   }
 
   test_async_futureOrVoid() async {
@@ -66,35 +68,139 @@
   }
 
   test_factory() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   factory A() {}
 }
-''', [HintCode.MISSING_RETURN]);
+''', [
+      error(HintCode.MISSING_RETURN, 12, 14),
+    ]);
   }
 
   test_function() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 int f() {}
-''', [HintCode.MISSING_RETURN]);
+''', [
+      error(HintCode.MISSING_RETURN, 0, 3),
+    ]);
+  }
+
+  test_functionExpression_declared() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  f() {} // no hint
+}
+''');
+  }
+
+  test_functionExpression_expression() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  int Function() f = () => null; // no hint
+}
+''');
+  }
+
+  test_functionExpression_futureOrDynamic() async {
+    await assertNoErrorsInCode(r'''
+import 'dart:async';
+main() {
+  FutureOr<dynamic> Function() f = () { print(42); };
+}
+''');
+  }
+
+  test_functionExpression_futureOrInt() async {
+    await assertErrorsInCode(r'''
+import 'dart:async';
+main() {
+  FutureOr<int> Function() f = () { print(42); };
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 57, 1),
+      error(HintCode.MISSING_RETURN, 61, 17),
+    ]);
+  }
+
+  test_functionExpression_inferred() async {
+    await assertErrorsInCode(r'''
+main() {
+  int Function() f = () { print(42); };
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 26, 1),
+      error(HintCode.MISSING_RETURN, 30, 17),
+    ]);
+  }
+
+  test_functionExpression_inferred_dynamic() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  Function() f = () { print(42); }; // no hint
+}
+''');
+  }
+
+  test_functionExpressionAsync_inferred() async {
+    await assertErrorsInCode(r'''
+main() {
+  Future<int> Function() f = () async { print(42); }; 
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 34, 1),
+      error(HintCode.MISSING_RETURN, 38, 23),
+    ]);
+  }
+
+  test_functionExpressionAsync_inferred_dynamic() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  Future Function() f = () async { print(42); }; // no hint
+}
+''');
   }
 
   test_method() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 class A {
   int m() {}
-}''', [HintCode.MISSING_RETURN]);
+}
+''', [
+      error(HintCode.MISSING_RETURN, 12, 3),
+    ]);
+  }
+
+  test_method_futureOrDynamic() async {
+    await assertNoErrorsInCode(r'''
+import 'dart:async';
+class A {
+  FutureOr<dynamic> m() {}
+}
+''');
+  }
+
+  test_method_futureOrInt() async {
+    await assertErrorsInCode(r'''
+import 'dart:async';
+class A {
+  FutureOr<int> m() {}
+}
+''', [
+      error(HintCode.MISSING_RETURN, 33, 13),
+    ]);
   }
 
   test_method_inferred() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 abstract class A {
   int m();
 }
 class B extends A {
   m() {}
 }
-''', [HintCode.MISSING_RETURN]);
+''', [
+      error(HintCode.MISSING_RETURN, 54, 6),
+    ]);
   }
 
   test_noReturnType() async {
diff --git a/pkg/analyzer/test/src/diagnostics/must_be_immutable_test.dart b/pkg/analyzer/test/src/diagnostics/must_be_immutable_test.dart
index e907d2c..8ada226 100644
--- a/pkg/analyzer/test/src/diagnostics/must_be_immutable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_be_immutable_test.dart
@@ -22,34 +22,40 @@
   }
 
   test_directAnnotation() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @immutable
 class A {
   int x;
 }
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+      error(HintCode.MUST_BE_IMMUTABLE, 50, 1),
+    ]);
   }
 
   test_directMixinAnnotation() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @immutable
 mixin A {
   int x;
 }
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+      error(HintCode.MUST_BE_IMMUTABLE, 50, 1),
+    ]);
   }
 
   test_extendsClassWithAnnotation() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @immutable
 class A {}
 class B extends A {
   int x;
 }
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+      error(HintCode.MUST_BE_IMMUTABLE, 61, 1),
+    ]);
   }
 
   test_finalField() async {
@@ -64,7 +70,7 @@
   }
 
   test_fromMixinWithAnnotation() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @immutable
 class A {}
@@ -72,11 +78,13 @@
   int x;
 }
 class C extends A with B {}
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+      error(HintCode.MUST_BE_IMMUTABLE, 82, 1),
+    ]);
   }
 
   test_mixinApplication() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 @immutable
 class A {}
@@ -84,11 +92,13 @@
   int x;
 }
 class C = A with B;
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+      error(HintCode.MUST_BE_IMMUTABLE, 82, 1),
+    ]);
   }
 
   test_mixinApplicationBase() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class A {
   int x;
@@ -96,7 +106,9 @@
 class B {}
 @immutable
 class C = A with B;
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+      error(HintCode.MUST_BE_IMMUTABLE, 82, 1),
+    ]);
   }
 
   test_staticField() async {
diff --git a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
index 7230ed0..32d9967 100644
--- a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
@@ -38,7 +38,7 @@
   }
 
   test_fromExtendingClass() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class A {
   @mustCallSuper
@@ -49,7 +49,9 @@
   void a()
   {}
 }
-''', [HintCode.MUST_CALL_SUPER]);
+''', [
+      error(HintCode.MUST_CALL_SUPER, 115, 1),
+    ]);
   }
 
   test_fromExtendingClass_abstractImplementation() async {
@@ -81,7 +83,7 @@
   }
 
   test_fromMixin() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class Mixin {
   @mustCallSuper
@@ -91,11 +93,13 @@
   @override
   void a() {}
 }
-''', [HintCode.MUST_CALL_SUPER]);
+''', [
+      error(HintCode.MUST_CALL_SUPER, 120, 1),
+    ]);
   }
 
   test_indirectlyInherited() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class A {
   @mustCallSuper
@@ -111,11 +115,13 @@
   @override
   void a() {}
 }
-''', [HintCode.MUST_CALL_SUPER]);
+''', [
+      error(HintCode.MUST_CALL_SUPER, 181, 1),
+    ]);
   }
 
   test_indirectlyInheritedFromMixin() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class Mixin {
   @mustCallSuper
@@ -126,11 +132,13 @@
   @override
   void b() {}
 }
-''', [HintCode.MUST_CALL_SUPER]);
+''', [
+      error(HintCode.MUST_CALL_SUPER, 156, 1),
+    ]);
   }
 
   test_indirectlyInheritedFromMixinConstraint() async {
-    await assertErrorCodesInCode(r'''
+    await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
 class A {
   @mustCallSuper
@@ -140,7 +148,9 @@
   @override
   void a() {}
 }
-''', [HintCode.MUST_CALL_SUPER]);
+''', [
+      error(HintCode.MUST_CALL_SUPER, 110, 1),
+    ]);
   }
 
   test_overriddenWithFuture() async {
diff --git a/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart b/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
index 511316a..b32c756 100644
--- a/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
@@ -19,15 +19,17 @@
 @reflectiveTest
 class NonBoolConditionTest extends DriverResolutionTest {
   test_ifElement() async {
-    assertErrorCodesInCode(
+    assertErrorsInCode(
         '''
 const c = [if (3) 1];
 ''',
         analysisOptions.experimentStatus.constant_update_2018
-            ? [StaticTypeWarningCode.NON_BOOL_CONDITION]
+            ? [
+                error(StaticTypeWarningCode.NON_BOOL_CONDITION, 15, 1),
+              ]
             : [
-                StaticTypeWarningCode.NON_BOOL_CONDITION,
-                CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT
+                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 11, 8),
+                error(StaticTypeWarningCode.NON_BOOL_CONDITION, 15, 1),
               ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart
index b63e481..2dc0373 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart
@@ -23,7 +23,7 @@
     ..enabledExperiments = [EnableString.constant_update_2018];
 
   test_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 const dynamic a = 2;
 const c = (a as int) + 2;
 ''');
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart
index 1b16612..29f4773 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart
@@ -22,7 +22,7 @@
     ..enabledExperiments = [EnableString.constant_update_2018];
 
   test_and_const_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 const c = true & false;
 ''');
   }
@@ -46,7 +46,7 @@
   }
 
   test_or_const_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 const c = true | false;
 ''');
   }
@@ -70,7 +70,7 @@
   }
 
   test_xor_const_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 const c = true ^ false;
 ''');
   }
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart
index 3d6b6ca..f8093af 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart
@@ -22,7 +22,7 @@
     ..enabledExperiments = [EnableString.constant_update_2018];
 
   test_left_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 class A {
   const A();
 }
@@ -42,7 +42,7 @@
   }
 
   test_right_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 class A {
   const A();
 }
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
index 5e5f140..38d71f0 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
@@ -24,7 +24,7 @@
   test_const_equals() {
     // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
     //  UNDEFINED_OPERATOR when triple_shift is enabled by default.
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 const a = 42 >>> 3;
 ''', errorCodes: [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
@@ -41,7 +41,7 @@
   }
 
   test_declaration_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 class A {
   A operator >>>(A a) => this;
 }
@@ -59,7 +59,7 @@
   test_nonConst_equals() {
     // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
     //  UNDEFINED_OPERATOR when constant update is enabled by default.
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 var a = 42 >>> 3;
 ''', errorCodes: [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart
index 70778cf..9b19e3c 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart
@@ -23,7 +23,7 @@
     ..enabledExperiments = [EnableString.constant_update_2018];
 
   test_equals() {
-    verifyVersion('2.2.2', '''
+    verifyVersion('2.3.2', '''
 const dynamic a = 2;
 const c = a is int;
 ''');
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index fff3f23..bf27038 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -165,6 +165,8 @@
 import 'unused_shown_name_test.dart' as unused_shown_name;
 import 'use_of_void_result_test.dart' as use_of_void_result;
 import 'variable_type_mismatch_test.dart' as variable_type_mismatch;
+import 'wrong_type_parameter_variance_in_superinterface_test.dart'
+    as wrong_type_parameter_variance_in_superinterface;
 
 main() {
   defineReflectiveSuite(() {
@@ -287,5 +289,6 @@
     unused_shown_name.main();
     use_of_void_result.main();
     variable_type_mismatch.main();
+    wrong_type_parameter_variance_in_superinterface.main();
   }, name: 'diagnostics');
 }
diff --git a/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart b/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
index d008f0a..08ffb33 100644
--- a/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
@@ -48,6 +48,24 @@
 ''');
   }
 
+  test_assert_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  bool x = true;
+  assert(x);
+}
+''');
+  }
+
+  test_assert_nullable() async {
+    await assertErrorCodesInCode(r'''
+m() {
+  bool? x;
+  assert(x);
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
   test_await_nonNullable() async {
     await assertNoErrorsInCode(r'''
 m() async {
@@ -201,6 +219,15 @@
 ''');
   }
 
+  test_member_dynamic_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  dynamic x;
+  x.foo;
+}
+''');
+  }
+
   test_member_hashCode_nullable() async {
     await assertNoErrorsInCode(r'''
 m() {
@@ -255,6 +282,24 @@
 ''');
   }
 
+  test_member_potentiallyNullable() async {
+    await assertErrorCodesInCode(r'''
+m<T extends int?>() {
+  T x;
+  x.isEven;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_member_potentiallyNullable_called() async {
+    await assertErrorCodesInCode(r'''
+m<T extends Function>() {
+  List<T?> x;
+  x.first();
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
   test_member_questionDot_nullable() async {
     await assertNoErrorsInCode(r'''
 m() {
@@ -286,7 +331,7 @@
     await assertNoErrorsInCode(r'''
 m() {
   int x;
-  x.noSuchMethod(null);
+  x.noSuchMethod(throw '');
 }
 ''');
   }
diff --git a/pkg/analyzer/test/src/diagnostics/wrong_type_parameter_variance_in_superinterface_test.dart b/pkg/analyzer/test/src/diagnostics/wrong_type_parameter_variance_in_superinterface_test.dart
new file mode 100644
index 0000000..5815369
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/wrong_type_parameter_variance_in_superinterface_test.dart
@@ -0,0 +1,334 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(WrongTypeParameterVarianceInSuperinterfaceTest);
+  });
+}
+
+@reflectiveTest
+class WrongTypeParameterVarianceInSuperinterfaceTest
+    extends DriverResolutionTest {
+  test_class_extends_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+class B<X> extends A<F<X>> {}
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        55,
+        1,
+      ),
+    ]);
+  }
+
+  test_class_extends_function_parameterType_parameterType() async {
+    await assertNoErrorsInCode(r'''
+typedef F1<X> = void Function(X);
+typedef F2<X> = void Function(F1<X>);
+class A<X> {}
+class B<X> extends A<F2<X>> {}
+''');
+  }
+
+  test_class_extends_function_parameterType_returnType() async {
+    await assertErrorsInCode(r'''
+typedef F1<X> = X Function();
+typedef F2<X> = void Function(F1<X>);
+class A<X> {}
+class B<X> extends A<F2<X>> {}
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        90,
+        1,
+      ),
+    ]);
+  }
+
+  test_class_extends_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+class B<X> extends A<F<X>> {}
+''');
+  }
+
+  test_class_extends_function_returnType_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F1<X> = void Function(X);
+typedef F2<X> = F1<X> Function();
+class A<X> {}
+class B<X> extends A<F2<X>> {}
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        90,
+        1,
+      ),
+    ]);
+  }
+
+  test_class_extends_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+class A<X> {}
+class B<X> extends A<X> {}
+''');
+  }
+
+  test_class_implements_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+class B<X> implements A<F<X>> {}
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        55,
+        1,
+      ),
+    ]);
+  }
+
+  test_class_implements_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+class B<X> implements A<F<X>> {}
+''');
+  }
+
+  test_class_implements_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+class A<X> {}
+class B<X> implements A<X> {}
+''');
+  }
+
+  test_class_with_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+class B<X> extends Object with A<F<X>> {}
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        55,
+        1,
+      ),
+    ]);
+  }
+
+  test_class_with_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+class B<X> extends Object with A<F<X>> {}
+''');
+  }
+
+  test_class_with_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+class A<X> {}
+class B<X> extends Object with A<X> {}
+''');
+  }
+
+  test_classTypeAlias_extends_function_invariant() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = X Function(X);
+class A<X> {}
+mixin M {}
+class B<X> = A<F<X>> with M;
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        63,
+        1,
+      ),
+    ]);
+  }
+
+  test_classTypeAlias_extends_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+mixin M {}
+class B<X> = A<F<X>> with M;
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        66,
+        1,
+      ),
+    ]);
+  }
+
+  test_classTypeAlias_extends_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+mixin M {}
+class B<X> = A<F<X>> with M;
+''');
+  }
+
+  test_classTypeAlias_extends_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+class A<X> {}
+mixin M {}
+class B<X> = A<X> with M;
+''');
+  }
+
+  test_classTypeAlias_implements_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+mixin M {}
+class B<X> = Object with M implements A<F<X>>;
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        66,
+        1,
+      ),
+    ]);
+  }
+
+  test_classTypeAlias_implements_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+mixin M {}
+class B<X> = Object with M implements A<F<X>>;
+''');
+  }
+
+  test_classTypeAlias_implements_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+class A<X> {}
+mixin M {}
+class B<X> = Object with M implements A<X>;
+''');
+  }
+
+  test_classTypeAlias_with_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+mixin M<X> {}
+class B<X> = Object with M<F<X>>;
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        55,
+        1,
+      ),
+    ]);
+  }
+
+  test_classTypeAlias_with_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+mixin M<X> {}
+class B<X> = Object with M<F<X>>;
+''');
+  }
+
+  test_classTypeAlias_with_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+mixin M<X> {}
+class B<X> = Object with M<X>;
+''');
+  }
+
+  test_mixin_implements_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+mixin B<X> implements A<F<X>> {}
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        55,
+        1,
+      ),
+    ]);
+  }
+
+  test_mixin_implements_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+mixin B<X> implements A<F<X>> {}
+''');
+  }
+
+  test_mixin_implements_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+class A<X> {}
+mixin B<X> implements A<X> {}
+''');
+  }
+
+  test_mixin_on_function_parameterType() async {
+    await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+mixin B<X> on A<F<X>> {}
+''', [
+      error(
+        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+        55,
+        1,
+      ),
+    ]);
+  }
+
+  test_mixin_on_function_returnType() async {
+    await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+mixin B<X> on A<F<X>> {}
+''');
+  }
+
+  test_mixin_on_withoutFunction() async {
+    await assertNoErrorsInCode(r'''
+class A<X> {}
+mixin B<X> on A<X> {}
+''');
+  }
+
+  test_typeParameter_bound() async {
+    try {
+      await assertErrorsInCode(r'''
+class A<X> {}
+class B<X> extends A<void Function<Y extends X>()> {}
+''', [
+        error(
+          CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+          22,
+          1,
+        ),
+      ]);
+    } catch (_) {
+      // TODO(scheglov) This code crashes with summary1.
+//    NoSuchMethodError: The getter 'bound' was called on null.
+//    Receiver: null
+//    Tried calling: bound
+//    #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5)
+//    #1      ErrorVerifier._checkForTypeParameterSupertypeOfItsBound (error_verifier.dart:5438:30)
+      if (AnalysisDriver.useSummary2) rethrow;
+    }
+  }
+}
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/switch_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/switch_statement_test.dart
index f8a05c4..914e1f6 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/switch_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/switch_statement_test.dart
@@ -22,7 +22,7 @@
               'switch',
               [
                 ParserErrorCode.MISSING_IDENTIFIER,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ParserErrorCode.EXPECTED_TOKEN
               ],
               "switch (_s_) {}",
@@ -32,7 +32,7 @@
               'switch (',
               [
                 ParserErrorCode.MISSING_IDENTIFIER,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "switch (_s_) {}",
@@ -47,11 +47,11 @@
           new TestDescriptor(
               'expression',
               'switch (a',
-              [ParserErrorCode.EXPECTED_TOKEN, ScannerErrorCode.EXPECTED_TOKEN],
+              [ParserErrorCode.EXPECTED_BODY, ScannerErrorCode.EXPECTED_TOKEN],
               "switch (a) {}",
               failing: ['block']),
           new TestDescriptor('rightParen', 'switch (a)',
-              [ParserErrorCode.EXPECTED_TOKEN], "switch (a) {}",
+              [ParserErrorCode.EXPECTED_BODY], "switch (a) {}",
               failing: ['block']),
           new TestDescriptor('leftBrace', 'switch (a) {',
               [ScannerErrorCode.EXPECTED_TOKEN], "switch (a) {}",
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
index ca80f4c..1e2f8a5 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
@@ -22,7 +22,7 @@
               'keyword',
               'try',
               [
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ParserErrorCode.MISSING_CATCH_OR_FINALLY
               ],
               "try {} finally {}",
@@ -38,7 +38,7 @@
               'try {} on',
               [
                 ParserErrorCode.EXPECTED_TYPE_NAME,
-                ParserErrorCode.EXPECTED_TOKEN
+                ParserErrorCode.EXPECTED_BODY
               ],
               "try {} on _s_ {}",
               failing: [
@@ -48,7 +48,7 @@
                 'localFunctionVoid'
               ]),
           new TestDescriptor('on_identifier', 'try {} on A',
-              [ParserErrorCode.EXPECTED_TOKEN], "try {} on A {}",
+              [ParserErrorCode.EXPECTED_BODY], "try {} on A {}",
               failing: ['block']),
           //
           // Single catch clause.
@@ -56,7 +56,7 @@
           new TestDescriptor(
               'catch',
               'try {} catch',
-              [ParserErrorCode.CATCH_SYNTAX, ParserErrorCode.EXPECTED_TOKEN],
+              [ParserErrorCode.CATCH_SYNTAX, ParserErrorCode.EXPECTED_BODY],
               "try {} catch (e) {}",
               failing: ['block']),
           new TestDescriptor(
@@ -65,7 +65,7 @@
               [
                 ScannerErrorCode.EXPECTED_TOKEN,
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.EXPECTED_TOKEN
+                ParserErrorCode.EXPECTED_BODY
               ],
               "try {} catch (e) {}",
               failing: ['block', 'labeled', 'localFunctionNonVoid']),
@@ -74,7 +74,7 @@
               'try {} catch (e',
               [
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} catch (e) {}",
@@ -84,7 +84,7 @@
               'try {} catch (e, ',
               [
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} catch (e, _s_) {}",
@@ -96,13 +96,13 @@
                 // TODO(danrubel): Update parser to generate CATCH_SYNTAX
                 // because in this situation there are not any extra parameters.
                 ParserErrorCode.CATCH_SYNTAX_EXTRA_PARAMETERS,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} catch (e, s) {}",
               failing: ['eof', 'block']),
           new TestDescriptor('catch_rightParen', 'try {} catch (e, s)',
-              [ParserErrorCode.EXPECTED_TOKEN], "try {} catch (e, s) {}",
+              [ParserErrorCode.EXPECTED_BODY], "try {} catch (e, s) {}",
               failing: ['block']),
           //
           // Single catch clause after an on clause.
@@ -110,7 +110,7 @@
           new TestDescriptor(
               'on_catch',
               'try {} on A catch',
-              [ParserErrorCode.CATCH_SYNTAX, ParserErrorCode.EXPECTED_TOKEN],
+              [ParserErrorCode.CATCH_SYNTAX, ParserErrorCode.EXPECTED_BODY],
               "try {} on A catch (e) {}",
               failing: ['block']),
           new TestDescriptor(
@@ -118,7 +118,7 @@
               'try {} on A catch (',
               [
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} on A catch (e) {}",
@@ -128,7 +128,7 @@
               'try {} on A catch (e',
               [
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} on A catch (e) {}",
@@ -138,7 +138,7 @@
               'try {} on A catch (e, ',
               [
                 ParserErrorCode.CATCH_SYNTAX,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} on A catch (e, _s_) {}",
@@ -150,19 +150,19 @@
                 // TODO(danrubel): Update parser to generate CATCH_SYNTAX
                 // because in this situation there are not any extra parameters.
                 ParserErrorCode.CATCH_SYNTAX_EXTRA_PARAMETERS,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.EXPECTED_BODY,
                 ScannerErrorCode.EXPECTED_TOKEN
               ],
               "try {} on A catch (e, s) {}",
               failing: ['eof', 'block']),
           new TestDescriptor('on_catch_rightParen', 'try {} on A catch (e, s)',
-              [ParserErrorCode.EXPECTED_TOKEN], "try {} on A catch (e, s) {}",
+              [ParserErrorCode.EXPECTED_BODY], "try {} on A catch (e, s) {}",
               failing: ['block']),
           //
           // Only a finally clause.
           //
           new TestDescriptor('finally_noCatch_noBlock', 'try {} finally',
-              [ParserErrorCode.EXPECTED_TOKEN], "try {} finally {}",
+              [ParserErrorCode.EXPECTED_BODY], "try {} finally {}",
               failing: ['block']),
           //
           // A catch and finally clause.
@@ -170,7 +170,7 @@
           new TestDescriptor(
               'finally_catch_noBlock',
               'try {} catch (e) {} finally',
-              [ParserErrorCode.EXPECTED_TOKEN],
+              [ParserErrorCode.EXPECTED_BODY],
               "try {} catch (e) {} finally {}",
               failing: ['block']),
         ],
diff --git a/pkg/analyzer/test/src/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index 6834f37..38bd97b 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -226,6 +226,51 @@
 
 @reflectiveTest
 class ChangeFileTest extends _Base {
+  disabled_test_updated_library_parted() async {
+    // TODO(scheglov) Figure out why this fails on Windows.
+    var a = convertPath('/home/test/lib/a.dart');
+    var b = convertPath('/home/test/lib/b.dart');
+
+    newFile(a, content: r'''
+class A {}
+''');
+    newFile(b, content: r'''
+part 'a.dart';
+class B {}
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+    _assertHasNoLibrary('package:test/a.dart');
+    _assertHasLibrary('package:test/b.dart', declarations: [
+      _ExpectedDeclaration.class_('A', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+      _ExpectedDeclaration.class_('B', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+    ]);
+
+    newFile(a, content: r'''
+class A2 {}
+''');
+    tracker.changeFile(a);
+    await _doAllTrackerWork();
+    _assertHasLibrary('package:test/a.dart', declarations: [
+      _ExpectedDeclaration.class_('A2', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+    ]);
+    _assertHasLibrary('package:test/b.dart', declarations: [
+      _ExpectedDeclaration.class_('A2', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+      _ExpectedDeclaration.class_('B', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+    ]);
+  }
+
   test_added_exported() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
@@ -855,51 +900,6 @@
     ]);
   }
 
-  disabled_test_updated_library_parted() async {
-    // TODO(scheglov) Figure out why this fails on Windows.
-    var a = convertPath('/home/test/lib/a.dart');
-    var b = convertPath('/home/test/lib/b.dart');
-
-    newFile(a, content: r'''
-class A {}
-''');
-    newFile(b, content: r'''
-part 'a.dart';
-class B {}
-''');
-    tracker.addContext(testAnalysisContext);
-
-    await _doAllTrackerWork();
-    _assertHasNoLibrary('package:test/a.dart');
-    _assertHasLibrary('package:test/b.dart', declarations: [
-      _ExpectedDeclaration.class_('A', [
-        _ExpectedDeclaration.constructor(''),
-      ]),
-      _ExpectedDeclaration.class_('B', [
-        _ExpectedDeclaration.constructor(''),
-      ]),
-    ]);
-
-    newFile(a, content: r'''
-class A2 {}
-''');
-    tracker.changeFile(a);
-    await _doAllTrackerWork();
-    _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration.class_('A2', [
-        _ExpectedDeclaration.constructor(''),
-      ]),
-    ]);
-    _assertHasLibrary('package:test/b.dart', declarations: [
-      _ExpectedDeclaration.class_('A2', [
-        _ExpectedDeclaration.constructor(''),
-      ]),
-      _ExpectedDeclaration.class_('B', [
-        _ExpectedDeclaration.constructor(''),
-      ]),
-    ]);
-  }
-
   test_updated_library_to_part() async {
     var a = convertPath('/home/test/lib/a.dart');
 
@@ -1607,6 +1607,101 @@
     _assertNoDeclaration(library, 'A');
   }
 
+  test_FUNCTION_TYPE_ALIAS_old() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+typedef void A();
+
+@deprecated
+typedef void B();
+
+/// aaa
+///
+/// bbb bbb
+typedef void C();
+
+typedef int D(int p1, [double p2, String p3]);
+
+typedef void E(int p1, double p2, {String p3});
+
+typedef void F<T extends num, U>();
+''');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(
+      _getDeclaration(library.declarations, 'A'),
+      'A',
+      DeclarationKind.FUNCTION_TYPE_ALIAS,
+      parameters: '()',
+      parameterNames: [],
+      parameterTypes: [],
+      relevanceTags: ['package:test/test.dart::A'],
+      requiredParameterCount: 0,
+      returnType: 'void',
+    );
+    _assertDeclaration(
+      _getDeclaration(library.declarations, 'B'),
+      'B',
+      DeclarationKind.FUNCTION_TYPE_ALIAS,
+      isDeprecated: true,
+      parameters: '()',
+      parameterNames: [],
+      parameterTypes: [],
+      relevanceTags: ['package:test/test.dart::B'],
+      requiredParameterCount: 0,
+      returnType: 'void',
+    );
+    _assertDeclaration(
+      _getDeclaration(library.declarations, 'C'),
+      'C',
+      DeclarationKind.FUNCTION_TYPE_ALIAS,
+      docSummary: 'aaa',
+      docComplete: 'aaa\n\nbbb bbb',
+      parameters: '()',
+      parameterNames: [],
+      parameterTypes: [],
+      relevanceTags: ['package:test/test.dart::C'],
+      requiredParameterCount: 0,
+      returnType: 'void',
+    );
+    _assertDeclaration(
+      _getDeclaration(library.declarations, 'D'),
+      'D',
+      DeclarationKind.FUNCTION_TYPE_ALIAS,
+      parameters: '(int p1, [double p2, String p3])',
+      parameterNames: ['p1', 'p2', 'p3'],
+      parameterTypes: ['int', 'double', 'String'],
+      relevanceTags: ['package:test/test.dart::D'],
+      requiredParameterCount: 1,
+      returnType: 'int',
+    );
+    _assertDeclaration(
+      _getDeclaration(library.declarations, 'E'),
+      'E',
+      DeclarationKind.FUNCTION_TYPE_ALIAS,
+      parameters: '(int p1, double p2, {String p3})',
+      parameterNames: ['p1', 'p2', 'p3'],
+      parameterTypes: ['int', 'double', 'String'],
+      relevanceTags: ['package:test/test.dart::E'],
+      requiredParameterCount: 2,
+      returnType: 'void',
+    );
+    _assertDeclaration(
+      _getDeclaration(library.declarations, 'F'),
+      'F',
+      DeclarationKind.FUNCTION_TYPE_ALIAS,
+      parameters: '()',
+      parameterNames: [],
+      parameterTypes: [],
+      requiredParameterCount: 0,
+      relevanceTags: ['package:test/test.dart::F'],
+      returnType: 'void',
+      typeParameters: '<T extends num, U>',
+    );
+  }
+
   test_GETTER() async {
     newFile('/home/test/lib/test.dart', content: r'''
 int get a => 0;
diff --git a/pkg/analyzer/test/src/summary/linker_test.dart b/pkg/analyzer/test/src/summary/linker_test.dart
index 0e738780..3a24bb1 100644
--- a/pkg/analyzer/test/src/summary/linker_test.dart
+++ b/pkg/analyzer/test/src/summary/linker_test.dart
@@ -225,7 +225,7 @@
     ClassElementForLink_Class B = library.getContainedName('B');
     expect(B.fields, hasLength(1));
     FieldElementForLink f = B.fields[0];
-    expect(f.type.toString(), '(num) → int');
+    expect(f.type.toString(), 'int Function(num)');
   }
 
   void test_getContainedName_nonStaticField() {
@@ -267,7 +267,7 @@
 ''');
     LibraryElementForLink library = linker.getLibrary(testDartUri);
     expect(_getVariable(library.getContainedName('y')).inferredType.toString(),
-        '() → Null');
+        'Null Function()');
   }
 
   void test_inferredType_closure_fromBundle_identifierSequence() {
@@ -287,7 +287,7 @@
 ''');
     LibraryElementForLink library = linker.getLibrary(testDartUri);
     expect(_getVariable(library.getContainedName('y')).inferredType.toString(),
-        '(D) → E');
+        'E Function(D)');
   }
 
   void test_inferredType_implicitFunctionTypeIndices() {
@@ -327,7 +327,7 @@
     ClassElementForLink_Class cls = library.getContainedName('C');
     expect(cls.fields, hasLength(1));
     var field = cls.fields[0];
-    expect(field.type.toString(), '(Never) → int');
+    expect(field.type.toString(), 'int Function(Never)');
   }
 
   void test_inferredType_instanceField_dynamic() {
@@ -379,7 +379,7 @@
     var method = cls.methods[0];
     expect(method.parameters, hasLength(1));
     var pType = method.parameters[0].type;
-    expect(pType.toString(), '<T,U>(T, U) → Map<T, List<U>>');
+    expect(pType.toString(), 'Map<T, List<U>> Function<T,U>(T, U)');
   }
 
   void test_inferredType_methodReturnType_dynamic() {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index 041f812..800bdd1 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -51,11 +51,6 @@
       );
     }
 
-    var rootReference = Reference.root();
-    var dartCoreRef = rootReference.getChild('dart:core');
-    dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
-    dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
-
     var elementFactory = LinkedElementFactory(
       RestrictedAnalysisContext(
         SynchronousSession(
@@ -65,7 +60,7 @@
         sourceFactory,
       ),
       _AnalysisSessionForLinking(),
-      rootReference,
+      Reference.root(),
     );
 
     var sdkLinkResult = link(elementFactory, inputLibraries);
@@ -90,16 +85,10 @@
       sourceFactory,
     );
 
-    var rootReference = Reference.root();
-    rootReference.getChild('dart:core').getChild('dynamic').element =
-        DynamicElementImpl.instance;
-    rootReference.getChild('dart:core').getChild('Never').element =
-        NeverElementImpl.instance;
-
     var elementFactory = LinkedElementFactory(
       analysisContext,
       _AnalysisSessionForLinking(),
-      rootReference,
+      Reference.root(),
     );
     elementFactory.addBundle(
       LinkedBundleContext(elementFactory, sdkBundle),
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index b602cc7..b67a6f2 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -1202,6 +1202,22 @@
 ''');
   }
 
+  test_class_method_namedAsSupertype() async {
+    var library = await checkLibrary(r'''
+class A {}
+class B extends A {
+  void A() {}
+}
+''');
+    checkElementText(library, r'''
+class A {
+}
+class B extends A {
+  void A() {}
+}
+''');
+  }
+
   test_class_method_params() async {
     var library = await checkLibrary('class C { f(x, y) {} }');
     checkElementText(library, r'''
@@ -2521,6 +2537,66 @@
 ''');
   }
 
+  test_const_inference_downward_list() async {
+    var library = await checkLibrary('''
+class P<T> {
+  const P();
+}
+
+class P1<T> extends P<T> {
+  const P1();
+}
+
+class P2<T> extends P<T> {
+  const P2();
+}
+
+const List<P> values = [
+  P1(),
+  P2<int>(),
+];
+''');
+    if (isAstBasedSummary) {
+      checkElementText(
+          library,
+          '''
+class P<T> {
+  const P();
+}
+class P1<T> extends P<T> {
+  const P1();
+}
+class P2<T> extends P<T> {
+  const P2();
+}
+const List<P<dynamic>> values = /*typeArgs=P<dynamic>*/[/*typeArgs=dynamic*/
+        P1/*location: test.dart;P1*/(),
+        P2/*location: test.dart;P2*/<
+        int/*location: dart:core;int*/>()];
+''',
+          withTypes: true);
+    } else {
+      checkElementText(
+          library,
+          '''
+class P<T> {
+  const P();
+}
+class P1<T> extends P<T> {
+  const P1();
+}
+class P2<T> extends P<T> {
+  const P2();
+}
+const List<P<dynamic>> values = const /*typeArgs=dynamic*/[const /*typeArgs=dynamic*/
+        P1/*location: test.dart;P1*/(), const
+        P2/*location: test.dart;P2*/<
+        int/*location: dart:core;int*/>()];
+''',
+          withTypes: true);
+    }
+  }
+
   test_const_invalid_field_const() async {
     var library = await checkLibrary(r'''
 class C {
@@ -8666,6 +8742,22 @@
 ''');
   }
 
+  test_mixin_method_namedAsConstraint() async {
+    var library = await checkLibrary(r'''
+class A {}
+mixin B on A {
+  void A() {}
+}
+''');
+    checkElementText(library, r'''
+class A {
+}
+mixin B on A {
+  void A() {}
+}
+''');
+  }
+
   test_nameConflict_exportedAndLocal() async {
     addLibrarySource('/a.dart', 'class C {}');
     addLibrarySource('/c.dart', '''
@@ -8955,11 +9047,41 @@
         withOffsets: true);
   }
 
-  test_parameter_covariant() async {
-    var library = await checkLibrary('class C { void m(covariant C c) {} }');
+  test_parameter_covariant_explicit_named() async {
+    var library = await checkLibrary('''
+class A {
+  void m({covariant A a}) {}
+}
+''');
     checkElementText(library, r'''
-class C {
-  void m(covariant C c) {}
+class A {
+  void m({covariant A a}) {}
+}
+''');
+  }
+
+  test_parameter_covariant_explicit_positional() async {
+    var library = await checkLibrary('''
+class A {
+  void m([covariant A a]) {}
+}
+''');
+    checkElementText(library, r'''
+class A {
+  void m([covariant A a]) {}
+}
+''');
+  }
+
+  test_parameter_covariant_explicit_required() async {
+    var library = await checkLibrary('''
+class A {
+  void m(covariant A a) {}
+}
+''');
+    checkElementText(library, r'''
+class A {
+  void m(covariant A a) {}
 }
 ''');
   }
@@ -8983,6 +9105,25 @@
 ''');
   }
 
+  test_parameter_covariant_inherited_named() async {
+    var library = await checkLibrary('''
+class A {
+  void m({covariant A a}) {}
+}
+class B extends A {
+  void m({B a}) {}
+}
+''');
+    checkElementText(library, r'''
+class A {
+  void m({covariant A a}) {}
+}
+class B extends A {
+  void m({covariant B a}) {}
+}
+''');
+  }
+
   test_parameter_parameters() async {
     var library = await checkLibrary('class C { f(g(x, y)) {} }');
     checkElementText(library, r'''
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index d881108..e93a4af 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -240,6 +240,14 @@
         declaredNames.remove('CONST_AND_COVARIANT');
         declaredNames.remove('CONST_AND_VAR');
         declaredNames.remove('COVARIANT_AFTER_FINAL');
+        declaredNames.remove('COVARIANT_AFTER_VAR');
+        declaredNames.remove('EXTERNAL_AFTER_CONST');
+        declaredNames.remove('EXTERNAL_AFTER_FACTORY');
+        declaredNames.remove('EXTERNAL_AFTER_STATIC');
+        declaredNames.remove('MISSING_CLASS_BODY');
+        declaredNames.remove('STATIC_AFTER_CONST');
+        declaredNames.remove('STATIC_AFTER_FINAL');
+        declaredNames.remove('STATIC_AFTER_VAR');
       }
 
       // Assert that all remaining declared names are in errorCodeValues
diff --git a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
index c2960c3..2ec431a6 100644
--- a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
+++ b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
@@ -51,15 +51,15 @@
       return invocation.staticInvokeType.toString();
     }
 
-    expect(getType('f()); // 1'), '() → bool');
+    expect(getType('f()); // 1'), 'bool Function()');
 
-    expect(getType('f(), '), '() → bool');
-    expect(getType('f()); // 2'), '() → dynamic');
+    expect(getType('f(), '), 'bool Function()');
+    expect(getType('f()); // 2'), 'dynamic Function()');
 
-    expect(getType('f()), // 3'), '() → bool');
+    expect(getType('f()), // 3'), 'bool Function()');
 
-    expect(getType('f(), '), '() → bool');
-    expect(getType('f()); // 4'), '() → dynamic');
+    expect(getType('f(), '), 'bool Function()');
+    expect(getType('f()); // 4'), 'dynamic Function()');
   }
 
   test_bool_logical() async {
@@ -80,7 +80,7 @@
 
     void assertType(String prefix) {
       var invocation = _findMethodInvocation(unit, code, prefix);
-      expect(invocation.staticInvokeType.toString(), '() → bool');
+      expect(invocation.staticInvokeType.toString(), 'bool Function()');
     }
 
     assertType('f() || f(); // 1');
@@ -111,7 +111,7 @@
 
     void assertType(String prefix) {
       var invocation = _findMethodInvocation(unit, code, prefix);
-      expect(invocation.staticInvokeType.toString(), '() → bool');
+      expect(invocation.staticInvokeType.toString(), 'bool Function()');
     }
 
     assertType('f()) {} // 1');
@@ -132,7 +132,7 @@
     var unit = analysisResult.unit;
 
     Expression closure = _findExpression(unit, code, '() => 42');
-    expect(closure.staticType.toString(), '() → List<int>');
+    expect(closure.staticType.toString(), 'List<int> Function()');
   }
 
   test_closure_downwardReturnType_block() async {
@@ -149,7 +149,7 @@
     var unit = analysisResult.unit;
 
     Expression closure = _findExpression(unit, code, '() { // mark');
-    expect(closure.staticType.toString(), '() → List<int>');
+    expect(closure.staticType.toString(), 'List<int> Function()');
   }
 
   test_compoundAssignment_index() async {
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index d3502e5..a3a31c2 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -60,10 +60,10 @@
     expect(futureInt.type.toString(), 'Future<int>');
     var f = mainUnit.topLevelVariables[1];
     expect(f.name, 'f');
-    expect(f.type.toString(), '() → Future<int>');
+    expect(f.type.toString(), 'Future<int> Function()');
     var g = mainUnit.topLevelVariables[2];
     expect(g.name, 'g');
-    expect(g.type.toString(), '() → Future<int>');
+    expect(g.type.toString(), 'Future<int> Function()');
   }
 
   test_asyncClosureReturnType_future() async {
@@ -72,7 +72,7 @@
 ''');
     var f = mainUnit.topLevelVariables[0];
     expect(f.name, 'f');
-    expect(f.type.toString(), '() → Future<int>');
+    expect(f.type.toString(), 'Future<int> Function()');
   }
 
   test_asyncClosureReturnType_futureOr() async {
@@ -87,10 +87,10 @@
     expect(futureOrInt.type.toString(), 'FutureOr<int>');
     var f = mainUnit.topLevelVariables[1];
     expect(f.name, 'f');
-    expect(f.type.toString(), '() → FutureOr<int>');
+    expect(f.type.toString(), 'FutureOr<int> Function()');
     var g = mainUnit.topLevelVariables[2];
     expect(g.name, 'g');
-    expect(g.type.toString(), '() → Future<int>');
+    expect(g.type.toString(), 'Future<int> Function()');
   }
 
   test_blockBodiedLambdas_async_allReturnsAreFutures() async {
@@ -113,7 +113,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Future<num>');
+    expect(f.type.toString(), 'Future<num> Function()');
   }
 
   test_blockBodiedLambdas_async_allReturnsAreValues() async {
@@ -136,7 +136,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Future<num>');
+    expect(f.type.toString(), 'Future<num> Function()');
   }
 
   test_blockBodiedLambdas_async_mixOfValuesAndFutures() async {
@@ -159,7 +159,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Future<num>');
+    expect(f.type.toString(), 'Future<num> Function()');
   }
 
   test_blockBodiedLambdas_asyncStar() async {
@@ -179,7 +179,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Stream<num>');
+    expect(f.type.toString(), 'Stream<num> Function()');
   }
 
   test_blockBodiedLambdas_basic() async {
@@ -204,7 +204,7 @@
 }
 ''');
     var g = findLocalVariable(unit, 'g');
-    expect(g.type.toString(), '() → String');
+    expect(g.type.toString(), 'String Function()');
   }
 
   test_blockBodiedLambdas_downwardsIncompatibleWithUpwardsInference_topLevel() async {
@@ -213,7 +213,7 @@
 var g = f;
 ''');
     var g = unit.topLevelVariables[0];
-    expect(g.type.toString(), '() → String');
+    expect(g.type.toString(), 'String Function()');
   }
 
   test_blockBodiedLambdas_inferBottom_async() async {
@@ -230,7 +230,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Future<Null>');
+    expect(f.type.toString(), 'Future<Null> Function()');
   }
 
   test_blockBodiedLambdas_inferBottom_asyncStar() async {
@@ -247,7 +247,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Stream<Null>');
+    expect(f.type.toString(), 'Stream<Null> Function()');
   }
 
   test_blockBodiedLambdas_inferBottom_sync() async {
@@ -272,7 +272,7 @@
 ''');
 
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '(Object) → Null');
+    expect(f.type.toString(), 'Null Function(Object)');
   }
 
   test_blockBodiedLambdas_inferBottom_syncStar() async {
@@ -288,7 +288,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Iterable<Null>');
+    expect(f.type.toString(), 'Iterable<Null> Function()');
   }
 
   test_blockBodiedLambdas_LUB() async {
@@ -322,7 +322,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → (int) → double');
+    expect(f.type.toString(), 'double Function(int) Function()');
   }
 
   test_blockBodiedLambdas_noReturn() async {
@@ -355,7 +355,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Iterable<num>');
+    expect(f.type.toString(), 'Iterable<num> Function()');
   }
 
   test_bottom() async {
@@ -368,9 +368,9 @@
     var v = mainUnit.topLevelVariables[0];
     expect(v.type.toString(), 'dynamic');
     if (AnalysisDriver.useSummary2) {
-      expect(v.initializer.type.toString(), '() → dynamic');
+      expect(v.initializer.type.toString(), 'dynamic Function()');
     } else {
-      expect(v.initializer.type.toString(), '() → Null');
+      expect(v.initializer.type.toString(), 'Null Function()');
     }
   }
 
@@ -381,8 +381,8 @@
 var v = /*info:INFERRED_TYPE_CLOSURE*/() => null;
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), '() → Null');
-    expect(v.initializer.type.toString(), '() → () → Null');
+    expect(v.type.toString(), 'Null Function()');
+    expect(v.initializer.type.toString(), 'Null Function() Function()');
   }
 
   test_circularReference_viaClosures() async {
@@ -407,8 +407,8 @@
     var y = mainUnit.topLevelVariables[1];
     expect(x.name, 'x');
     expect(y.name, 'y');
-    expect(x.initializer.returnType.toString(), '() → dynamic');
-    expect(y.initializer.returnType.toString(), '() → dynamic');
+    expect(x.initializer.returnType.toString(), 'dynamic Function()');
+    expect(y.initializer.returnType.toString(), 'dynamic Function()');
   }
 
   test_conflictsCanHappen() async {
@@ -1985,7 +1985,7 @@
 typedef void F<V>(V v);
 ''');
     var f = mainUnit.getType('C').methods[0];
-    expect(f.type.toString(), '<U>(U) → (U) → void');
+    expect(f.type.toString(), 'void Function(U) Function<U>(U)');
   }
 
   test_genericMethods_inferGenericFunctionParameterType2() async {
@@ -1999,7 +1999,7 @@
 typedef List<V> G<V>();
 ''');
     var f = mainUnit.getType('C').methods[0];
-    expect(f.type.toString(), '<U>(() → List<U>) → void');
+    expect(f.type.toString(), 'void Function<U>(List<U> Function())');
   }
 
   test_genericMethods_inferGenericFunctionReturnType() async {
@@ -2013,7 +2013,7 @@
 typedef V F<V>();
 ''');
     var f = mainUnit.getType('C').methods[0];
-    expect(f.type.toString(), '<U>(U) → () → U');
+    expect(f.type.toString(), 'U Function() Function<U>(U)');
   }
 
   test_genericMethods_inferGenericInstantiation() async {
@@ -2192,7 +2192,7 @@
 }
 ''');
     var v = findLocalVariable(unit, 'v');
-    expect(v.type.toString(), '(num) → List<int>');
+    expect(v.type.toString(), 'List<int> Function(num)');
   }
 
   test_genericMethods_usesGreatestLowerBound_topLevel() async {
@@ -2205,7 +2205,7 @@
 var v = generic(/*info:INFERRED_TYPE_CLOSURE*/(F f) => null, /*info:INFERRED_TYPE_CLOSURE*/(G g) => null);
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), '(num) → List<int>');
+    expect(v.type.toString(), 'List<int> Function(num)');
   }
 
   test_infer_assignToIndex() async {
@@ -2495,7 +2495,7 @@
 var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<() → Object>');
+    expect(v.type.toString(), 'List<Object Function()>');
   }
 
   test_inferedType_usesSyntheticFunctionType_functionTypedParam() async {
@@ -2505,7 +2505,7 @@
 var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<((String) → int) → Object>');
+    expect(v.type.toString(), 'List<Object Function(int Function(String))>');
   }
 
   test_inferedType_usesSyntheticFunctionType_namedParam() async {
@@ -2515,7 +2515,7 @@
 var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<({x: int}) → Object>');
+    expect(v.type.toString(), 'List<Object Function({x: int})>');
   }
 
   test_inferedType_usesSyntheticFunctionType_positionalParam() async {
@@ -2525,7 +2525,7 @@
 var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<([int]) → Object>');
+    expect(v.type.toString(), 'List<Object Function([int])>');
   }
 
   test_inferedType_usesSyntheticFunctionType_requiredParam() async {
@@ -2535,7 +2535,7 @@
 var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<(int) → Object>');
+    expect(v.type.toString(), 'List<Object Function(int)>');
   }
 
   test_inferFromComplexExpressionsIfOuterMostValueIsPrecise() async {
@@ -2783,20 +2783,25 @@
   f9 /*info:INFERRED_TYPE_CLOSURE*/() => f5();
 }
 ''');
-    expect(findLocalFunction(unit, 'f0').type.toString(), '() → int');
-    expect(findLocalFunction(unit, 'f1').type.toString(), '() → Future<int>');
+    expect(findLocalFunction(unit, 'f0').type.toString(), 'int Function()');
+    expect(findLocalFunction(unit, 'f1').type.toString(),
+        'Future<int> Function()');
 
-    expect(findLocalFunction(unit, 'f2').type.toString(), '() → int');
-    expect(findLocalFunction(unit, 'f3').type.toString(), '() → Future<int>');
-    expect(findLocalFunction(unit, 'f4').type.toString(), '() → Iterable<int>');
-    expect(findLocalFunction(unit, 'f5').type.toString(), '() → Stream<int>');
+    expect(findLocalFunction(unit, 'f2').type.toString(), 'int Function()');
+    expect(findLocalFunction(unit, 'f3').type.toString(),
+        'Future<int> Function()');
+    expect(findLocalFunction(unit, 'f4').type.toString(),
+        'Iterable<int> Function()');
+    expect(findLocalFunction(unit, 'f5').type.toString(),
+        'Stream<int> Function()');
 
-    expect(findLocalFunction(unit, 'f6').type.toString(), '() → num');
+    expect(findLocalFunction(unit, 'f6').type.toString(), 'num Function()');
 
     // Recursive cases: these infer in declaration order.
-    expect(findLocalFunction(unit, 'f7').type.toString(), '() → dynamic');
-    expect(findLocalFunction(unit, 'f8').type.toString(), '() → dynamic');
-    expect(findLocalFunction(unit, 'f9').type.toString(), '() → Stream<int>');
+    expect(findLocalFunction(unit, 'f7').type.toString(), 'dynamic Function()');
+    expect(findLocalFunction(unit, 'f8').type.toString(), 'dynamic Function()');
+    expect(findLocalFunction(unit, 'f9').type.toString(),
+        'Stream<int> Function()');
   }
 
   test_inferParameterType_setter_fromField() async {
@@ -2809,7 +2814,7 @@
 }
 ''');
     var f = mainUnit.getType('C').accessors[0];
-    expect(f.type.toString(), '(int) → void');
+    expect(f.type.toString(), 'void Function(int)');
   }
 
   test_inferParameterType_setter_fromSetter() async {
@@ -2822,7 +2827,7 @@
 }
 ''');
     var f = mainUnit.getType('C').accessors[0];
-    expect(f.type.toString(), '(int) → void');
+    expect(f.type.toString(), 'void Function(int)');
   }
 
   test_inferred_nonstatic_field_depends_on_static_field_complex() async {
@@ -2873,7 +2878,7 @@
 }
 ''');
     var f = findLocalVariable(unit, 'f');
-    expect(f.type.toString(), '() → Null');
+    expect(f.type.toString(), 'Null Function()');
   }
 
   test_inferredType_cascade() async {
@@ -2984,7 +2989,7 @@
 ''');
     var x = mainUnit.topLevelVariables[0];
     expect(x.name, 'x');
-    expect(x.type.toString(), '() → bool');
+    expect(x.type.toString(), 'bool Function()');
   }
 
   test_inferredType_extractMethodTearOff_viaInterface() async {
@@ -2998,7 +3003,7 @@
 ''');
     var x = mainUnit.topLevelVariables[0];
     expect(x.name, 'x');
-    expect(x.type.toString(), '() → bool');
+    expect(x.type.toString(), 'bool Function()');
   }
 
   test_inferredType_fromTopLevelExecutableTearoff() async {
@@ -3006,7 +3011,7 @@
 var v = print;
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), '(Object) → void');
+    expect(v.type.toString(), 'void Function(Object)');
   }
 
   test_inferredType_invokeMethod() async {
@@ -3060,7 +3065,7 @@
 final x = <String, F>{};
 ''');
     var x = mainUnit.topLevelVariables[0];
-    expect(x.type.toString(), 'Map<String, () → void>');
+    expect(x.type.toString(), 'Map<String, void Function()>');
   }
 
   test_inferredType_isTypedef_parameterized() async {
@@ -3069,7 +3074,7 @@
 final x = <String, F<int>>{};
 ''');
     var x = mainUnit.topLevelVariables[0];
-    expect(x.type.toString(), 'Map<String, () → int>');
+    expect(x.type.toString(), 'Map<String, int Function()>');
   }
 
   test_inferredType_viaClosure_multipleLevelsOfNesting() async {
@@ -3080,7 +3085,7 @@
 }
 ''');
     var f = mainUnit.getType('C').fields[0];
-    expect(f.type.toString(), '(bool) → (int) → Map<int, bool>');
+    expect(f.type.toString(), 'Map<int, bool> Function(int) Function(bool)');
   }
 
   test_inferredType_viaClosure_typeDependsOnArgs() async {
@@ -3090,7 +3095,7 @@
 }
 ''');
     var f = mainUnit.getType('C').fields[0];
-    expect(f.type.toString(), '(bool) → bool');
+    expect(f.type.toString(), 'bool Function(bool)');
   }
 
   test_inferredType_viaClosure_typeIndependentOfArgs_field() async {
@@ -3100,7 +3105,7 @@
 }
 ''');
     var f = mainUnit.getType('C').fields[0];
-    expect(f.type.toString(), '(bool) → int');
+    expect(f.type.toString(), 'int Function(bool)');
   }
 
   test_inferredType_viaClosure_typeIndependentOfArgs_topLevel() async {
@@ -3108,7 +3113,7 @@
 final f = /*info:INFERRED_TYPE_CLOSURE*/(bool b) => 1;
 ''');
     var f = mainUnit.topLevelVariables[0];
-    expect(f.type.toString(), '(bool) → int');
+    expect(f.type.toString(), 'int Function(bool)');
   }
 
   test_inferReturnOfStatementLambda() async {
@@ -4071,7 +4076,7 @@
 }
 ''');
     var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), '(String) → int');
+    expect(v.type.toString(), 'int Function(String)');
   }
 
   test_unsafeBlockClosureInference_closureCall() async {
@@ -4271,7 +4276,7 @@
 }
 ''');
     var v = findLocalVariable(unit, 'v');
-    expect(v.type.toString(), 'List<() → int>');
+    expect(v.type.toString(), 'List<int Function()>');
   }
 
   test_unsafeBlockClosureInference_inList_untyped() async {
@@ -4284,7 +4289,7 @@
 }
 ''');
     var v = findLocalVariable(unit, 'v');
-    expect(v.type.toString(), 'List<() → int>');
+    expect(v.type.toString(), 'List<int Function()>');
   }
 
   test_unsafeBlockClosureInference_inMap_dynamic() async {
@@ -4305,7 +4310,7 @@
 }
 ''');
     var v = findLocalVariable(unit, 'v');
-    expect(v.type.toString(), 'Map<int, () → int>');
+    expect(v.type.toString(), 'Map<int, int Function()>');
   }
 
   test_unsafeBlockClosureInference_inMap_untyped() async {
@@ -4318,7 +4323,7 @@
 }
 ''');
     var v = findLocalVariable(unit, 'v');
-    expect(v.type.toString(), 'Map<int, () → int>');
+    expect(v.type.toString(), 'Map<int, int Function()>');
   }
 
   test_unsafeBlockClosureInference_methodCall_explicitDynamicParam() async {
diff --git a/pkg/analyzer/test/test_all.dart b/pkg/analyzer/test/test_all.dart
index a27c273..f68ff2b 100644
--- a/pkg/analyzer/test/test_all.dart
+++ b/pkg/analyzer/test/test_all.dart
@@ -13,6 +13,7 @@
 import 'parse_compilation_unit_test.dart' as parse_compilation_unit;
 import 'source/test_all.dart' as source;
 import 'src/test_all.dart' as src;
+import 'verify_docs_test.dart' as verify_docs;
 import 'verify_tests_test.dart' as verify_tests;
 
 main() {
@@ -26,6 +27,7 @@
     parse_compilation_unit.main();
     source.main();
     src.main();
+    verify_docs.main();
     verify_tests.main();
   }, name: 'analyzer');
 }
diff --git a/pkg/analyzer/test/verify_docs_test.dart b/pkg/analyzer/test/verify_docs_test.dart
new file mode 100644
index 0000000..90fbc51
--- /dev/null
+++ b/pkg/analyzer/test/verify_docs_test.dart
@@ -0,0 +1,153 @@
+// Copyright (c) 2019, 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 'package:analyzer/dart/analysis/analysis_context.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/overlay_file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:front_end/src/testing/package_root.dart' as package_root;
+import 'package:test/test.dart';
+
+main() async {
+  SnippetTester tester = SnippetTester();
+  await tester.verify();
+  if (tester.output.isNotEmpty) {
+    fail(tester.output.toString());
+  }
+}
+
+class SnippetTester {
+  OverlayResourceProvider provider;
+  Folder docFolder;
+  String snippetDirPath;
+  String snippetPath;
+
+  StringBuffer output = StringBuffer();
+
+  SnippetTester() {
+    provider = OverlayResourceProvider(PhysicalResourceProvider.INSTANCE);
+    String packageRoot =
+        provider.pathContext.normalize(package_root.packageRoot);
+    String analyzerPath = provider.pathContext.join(packageRoot, 'analyzer');
+    String docPath = provider.pathContext.join(analyzerPath, 'doc');
+    docFolder = provider.getFolder(docPath);
+    snippetDirPath =
+        provider.pathContext.join(analyzerPath, 'test', 'snippets');
+    snippetPath = provider.pathContext.join(snippetDirPath, 'snippet.dart');
+  }
+
+  void verify() async {
+    await verifyFolder(docFolder);
+  }
+
+  void verifyFile(File file) async {
+    String content = file.readAsStringSync();
+    List<String> lines = const LineSplitter().convert(content);
+    List<String> codeLines = [];
+    bool inCode = false;
+    for (int i = 0; i < lines.length; i++) {
+      String line = lines[i];
+      if (line == '```dart') {
+        if (inCode) {
+          // TODO(brianwilkerson) Report this.
+        }
+        inCode = true;
+      } else if (line == '```') {
+        if (!inCode) {
+          // TODO(brianwilkerson) Report this.
+        }
+        await verifySnippet(file, codeLines.join('\n'));
+        codeLines.clear();
+        inCode = false;
+      } else if (inCode) {
+        codeLines.add(line);
+      }
+    }
+  }
+
+  void verifyFolder(Folder folder) async {
+    for (Resource child in folder.getChildren()) {
+      if (child is File) {
+        if (child.shortName.endsWith('.md')) {
+          await verifyFile(child);
+        }
+      } else if (child is Folder) {
+        await verifyFolder(child);
+      }
+    }
+  }
+
+  void verifySnippet(File file, String snippet) async {
+    // TODO(brianwilkerson) When the files outside of 'src' contain only public
+    //  API, write code to compute the list of imports so that new public API
+    //  will automatically be allowed.
+    String imports = '''
+import 'dart:math' as math;
+
+import 'package:analyzer/dart/analysis/analysis_context.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+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/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/visitor.dart';
+
+''';
+    provider.setOverlay(snippetPath,
+        content: '''
+$imports
+$snippet
+''',
+        modificationStamp: 1);
+    try {
+      AnalysisContextCollection collection = new AnalysisContextCollection(
+          includedPaths: <String>[snippetDirPath], resourceProvider: provider);
+      List<AnalysisContext> contexts = collection.contexts;
+      if (contexts.length != 1) {
+        fail('The snippets directory contains multiple analysis contexts.');
+      }
+      ErrorsResult results =
+          await contexts[0].currentSession.getErrors(snippetPath);
+      Iterable<AnalysisError> errors = results.errors.where((error) {
+        ErrorCode errorCode = error.errorCode;
+        return errorCode != HintCode.UNUSED_IMPORT &&
+            errorCode != HintCode.UNUSED_LOCAL_VARIABLE;
+      });
+      if (errors.isNotEmpty) {
+        String filePath =
+            provider.pathContext.relative(file.path, from: docFolder.path);
+        if (output.isNotEmpty) {
+          output.writeln();
+        }
+        output.writeln('Errors in snippet in "$filePath":');
+        output.writeln();
+        output.writeln(snippet);
+        output.writeln();
+        int importsLength = imports.length + 1; // account for the '\n'.
+        for (var error in errors) {
+          writeError(error, importsLength);
+        }
+      }
+    } finally {
+      provider.removeOverlay(snippetPath);
+    }
+  }
+
+  void writeError(AnalysisError error, int prefixLength) {
+    output.write(error.errorCode);
+    output.write(' (');
+    output.write(error.offset - prefixLength);
+    output.write(', ');
+    output.write(error.length);
+    output.write(') ');
+    output.writeln(error.message);
+  }
+}
diff --git a/pkg/analyzer/tool/summary/generate.dart b/pkg/analyzer/tool/summary/generate.dart
index 798e369..d27a4d8 100644
--- a/pkg/analyzer/tool/summary/generate.dart
+++ b/pkg/analyzer/tool/summary/generate.dart
@@ -54,16 +54,591 @@
 
 typedef String _StringToString(String s);
 
-class _CodeGenerator {
+class _BaseGenerator {
   static const String _throwDeprecated =
       "throw new UnimplementedError('attempt to access deprecated field')";
 
+  /// Semantic model of the "IDL" input file.
+  final idlModel.Idl _idl;
+
   /// Buffer in which generated code is accumulated.
-  final StringBuffer _outBuffer = new StringBuffer();
+  final StringBuffer _outBuffer;
 
   /// Current indentation level.
   String _indentation = '';
 
+  _BaseGenerator(this._idl, this._outBuffer);
+
+  /// Generate a Dart expression representing the default value for a field
+  /// having the given [type], or `null` if there is no default value.
+  ///
+  /// If [builder] is `true`, the returned type should be appropriate for use in
+  /// a builder class.
+  String defaultValue(idlModel.FieldType type, bool builder) {
+    if (type.isList) {
+      if (builder) {
+        idlModel.FieldType elementType =
+            new idlModel.FieldType(type.typeName, false);
+        return '<${encodedType(elementType)}>[]';
+      } else {
+        return 'const <${idlPrefix(type.typeName)}>[]';
+      }
+    } else if (_idl.enums.containsKey(type.typeName)) {
+      return '${idlPrefix(type.typeName)}.'
+          '${_idl.enums[type.typeName].values[0].name}';
+    } else if (type.typeName == 'double') {
+      return '0.0';
+    } else if (type.typeName == 'int') {
+      return '0';
+    } else if (type.typeName == 'String') {
+      return "''";
+    } else if (type.typeName == 'bool') {
+      return 'false';
+    } else {
+      return null;
+    }
+  }
+
+  /// Generate a string representing the Dart type which should be used to
+  /// represent [type] while building a serialized data structure.
+  String encodedType(idlModel.FieldType type) {
+    String typeStr;
+    if (_idl.classes.containsKey(type.typeName)) {
+      typeStr = '${type.typeName}Builder';
+    } else {
+      typeStr = idlPrefix(type.typeName);
+    }
+    if (type.isList) {
+      return 'List<$typeStr>';
+    } else {
+      return typeStr;
+    }
+  }
+
+  /// Add the prefix `idl.` to a type name, unless that type name is the name of
+  /// a built-in type.
+  String idlPrefix(String s) {
+    switch (s) {
+      case 'bool':
+      case 'double':
+      case 'int':
+      case 'String':
+        return s;
+      default:
+        return 'idl.$s';
+    }
+  }
+
+  /// Execute [callback] with two spaces added to [_indentation].
+  void indent(void callback()) {
+    String oldIndentation = _indentation;
+    try {
+      _indentation += '  ';
+      callback();
+    } finally {
+      _indentation = oldIndentation;
+    }
+  }
+
+  /// Add the string [s] to the output as a single line, indenting as
+  /// appropriate.
+  void out([String s = '']) {
+    if (s == '') {
+      _outBuffer.writeln('');
+    } else {
+      _outBuffer.writeln('$_indentation$s');
+    }
+  }
+
+  void outDoc(String documentation) {
+    if (documentation != null) {
+      documentation.split('\n').forEach(out);
+    }
+  }
+
+  /// Enclose [s] in quotes, escaping as necessary.
+  String quoted(String s) {
+    return json.encode(s);
+  }
+
+  List<String> _computeVariants(idlModel.ClassDeclaration cls) {
+    var allVariants = Set<String>();
+    for (var field in cls.fields) {
+      var logicalFields = field.logicalProperties?.values;
+      if (logicalFields != null) {
+        for (var logicalField in logicalFields) {
+          allVariants.addAll(logicalField.variants);
+        }
+      }
+    }
+    return allVariants.toList()..sort();
+  }
+
+  String _variantAssertStatement(
+    idlModel.ClassDeclaration class_,
+    idlModel.LogicalProperty property,
+  ) {
+    var assertCondition = property.variants
+        ?.map((key) => '${class_.variantField} == idl.$key')
+        ?.join(' || ');
+    return 'assert($assertCondition);';
+  }
+}
+
+class _BuilderGenerator extends _BaseGenerator {
+  final idlModel.ClassDeclaration cls;
+  List<String> constructorParams = <String>[];
+
+  _BuilderGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+      : super(idl, outBuffer);
+
+  String get builderName => name + 'Builder';
+
+  String get name => cls.name;
+
+  void generate() {
+    String mixinName = '_${name}Mixin';
+    var implementsClause =
+        cls.isDeprecated ? '' : ' implements ${idlPrefix(name)}';
+    out('class $builderName extends Object with $mixinName$implementsClause {');
+    indent(() {
+      _generateFields();
+      _generateGettersSetters();
+      _generateConstructors();
+      _generateFlushInformative();
+      _generateCollectApiSignature();
+      _generateToBuffer();
+      _generateFinish();
+    });
+    out('}');
+  }
+
+  void _generateCollectApiSignature() {
+    out();
+    out('/// Accumulate non-[informative] data into [signature].');
+    out('void collectApiSignature(api_sig.ApiSignature signature) {');
+
+    void writeField(String name, idlModel.FieldType type, bool isInformative) {
+      if (isInformative) {
+        return;
+      }
+      String ref = 'this.$name';
+      if (type.isList) {
+        out('if ($ref == null) {');
+        indent(() {
+          out('signature.addInt(0);');
+        });
+        out('} else {');
+        indent(() {
+          out('signature.addInt($ref.length);');
+          out('for (var x in $ref) {');
+          indent(() {
+            _generateSignatureCall(type.typeName, 'x', false);
+          });
+          out('}');
+        });
+        out('}');
+      } else {
+        _generateSignatureCall(type.typeName, ref, true);
+      }
+    }
+
+    indent(() {
+      List<idlModel.FieldDeclaration> sortedFields = cls.fields.toList()
+        ..sort((idlModel.FieldDeclaration a, idlModel.FieldDeclaration b) =>
+            a.id.compareTo(b.id));
+      if (cls.variantField != null) {
+        var firstVariant = true;
+        for (var variant in _computeVariants(cls)) {
+          if (firstVariant) {
+            firstVariant = false;
+          } else {
+            out('else');
+          }
+          out('if (${cls.variantField} == idl.$variant) {');
+          indent(() {
+            for (var field in sortedFields) {
+              var logicalProperties = field.logicalProperties;
+              if (logicalProperties != null) {
+                for (var logicalName in logicalProperties.keys) {
+                  var logicalProperty = logicalProperties[logicalName];
+                  if (logicalProperty.variants.contains(variant)) {
+                    writeField(
+                      logicalName,
+                      field.type,
+                      logicalProperty.isInformative,
+                    );
+                  }
+                }
+              } else {
+                writeField(field.name, field.type, field.isInformative);
+              }
+            }
+          });
+          out('}');
+        }
+      } else {
+        for (idlModel.FieldDeclaration field in sortedFields) {
+          writeField('_${field.name}', field.type, field.isInformative);
+        }
+      }
+    });
+    out('}');
+  }
+
+  void _generateConstructors() {
+    out();
+    if (cls.variantField != null) {
+      for (var variant in _computeVariants(cls)) {
+        var constructorName = variant.split('.')[1];
+        out('$builderName.$constructorName({');
+
+        for (var field in cls.fields) {
+          if (field.logicalProperties != null) {
+            for (var logicalName in field.logicalProperties.keys) {
+              var logicalProperty = field.logicalProperties[logicalName];
+              if (logicalProperty.variants.contains(variant)) {
+                out('${encodedType(field.type)} $logicalName,');
+              }
+            }
+          }
+        }
+
+        out('}) : ');
+
+        out('_${cls.variantField} = idl.$variant');
+
+        var separator = ',';
+        for (var field in cls.fields) {
+          if (field.logicalProperties != null) {
+            for (var logicalName in field.logicalProperties.keys) {
+              var logicalProperty = field.logicalProperties[logicalName];
+              if (logicalProperty.variants.contains(variant)) {
+                out('$separator _${field.name} = $logicalName');
+                separator = ', ';
+              }
+            }
+          }
+        }
+
+        out(';');
+        out();
+      }
+    } else {
+      out('$builderName({${constructorParams.join(', ')}})');
+      List<idlModel.FieldDeclaration> fields = cls.fields.toList();
+      for (int i = 0; i < fields.length; i++) {
+        idlModel.FieldDeclaration field = fields[i];
+        String prefix = i == 0 ? '  : ' : '    ';
+        String suffix = i == fields.length - 1 ? ';' : ',';
+        out('${prefix}_${field.name} = ${field.name}$suffix');
+      }
+    }
+  }
+
+  void _generateFields() {
+    for (idlModel.FieldDeclaration field in cls.fields) {
+      String fieldName = field.name;
+      idlModel.FieldType type = field.type;
+      String typeStr = encodedType(type);
+      out('$typeStr _$fieldName;');
+    }
+  }
+
+  void _generateFinish() {
+    out();
+    out('fb.Offset finish(fb.Builder fbBuilder) {');
+    indent(() {
+      // Write objects and remember Offset(s).
+      for (idlModel.FieldDeclaration field in cls.fields) {
+        idlModel.FieldType fieldType = field.type;
+        String offsetName = 'offset_' + field.name;
+        if (fieldType.isList ||
+            fieldType.typeName == 'String' ||
+            _idl.classes.containsKey(fieldType.typeName)) {
+          out('fb.Offset $offsetName;');
+        }
+      }
+
+      for (idlModel.FieldDeclaration field in cls.fields) {
+        idlModel.FieldType fieldType = field.type;
+        String valueName = '_' + field.name;
+        String offsetName = 'offset_' + field.name;
+        String condition;
+        String writeCode;
+        if (fieldType.isList) {
+          condition = ' || $valueName.isEmpty';
+          if (_idl.classes.containsKey(fieldType.typeName)) {
+            String itemCode = 'b.finish(fbBuilder)';
+            String listCode = '$valueName.map((b) => $itemCode).toList()';
+            writeCode = '$offsetName = fbBuilder.writeList($listCode);';
+          } else if (_idl.enums.containsKey(fieldType.typeName)) {
+            String itemCode = 'b.index';
+            String listCode = '$valueName.map((b) => $itemCode).toList()';
+            writeCode = '$offsetName = fbBuilder.writeListUint8($listCode);';
+          } else if (fieldType.typeName == 'bool') {
+            writeCode = '$offsetName = fbBuilder.writeListBool($valueName);';
+          } else if (fieldType.typeName == 'int') {
+            writeCode = '$offsetName = fbBuilder.writeListUint32($valueName);';
+          } else if (fieldType.typeName == 'double') {
+            writeCode = '$offsetName = fbBuilder.writeListFloat64($valueName);';
+          } else {
+            assert(fieldType.typeName == 'String');
+            String itemCode = 'fbBuilder.writeString(b)';
+            String listCode = '$valueName.map((b) => $itemCode).toList()';
+            writeCode = '$offsetName = fbBuilder.writeList($listCode);';
+          }
+        } else if (fieldType.typeName == 'String') {
+          writeCode = '$offsetName = fbBuilder.writeString($valueName);';
+        } else if (_idl.classes.containsKey(fieldType.typeName)) {
+          writeCode = '$offsetName = $valueName.finish(fbBuilder);';
+        }
+        if (writeCode != null) {
+          if (condition == null) {
+            out('if ($valueName != null) {');
+          } else {
+            out('if (!($valueName == null$condition)) {');
+          }
+          indent(() {
+            out(writeCode);
+          });
+          out('}');
+        }
+      }
+
+      // Write the table.
+      out('fbBuilder.startTable();');
+      for (idlModel.FieldDeclaration field in cls.fields) {
+        int index = field.id;
+        idlModel.FieldType fieldType = field.type;
+        String valueName = '_' + field.name;
+        String condition = '$valueName != null';
+        String writeCode;
+        if (fieldType.isList ||
+            fieldType.typeName == 'String' ||
+            _idl.classes.containsKey(fieldType.typeName)) {
+          String offsetName = 'offset_' + field.name;
+          condition = '$offsetName != null';
+          writeCode = 'fbBuilder.addOffset($index, $offsetName);';
+        } else if (fieldType.typeName == 'bool') {
+          condition = '$valueName == true';
+          writeCode = 'fbBuilder.addBool($index, true);';
+        } else if (fieldType.typeName == 'double') {
+          condition += ' && $valueName != ${defaultValue(fieldType, true)}';
+          writeCode = 'fbBuilder.addFloat64($index, $valueName);';
+        } else if (fieldType.typeName == 'int') {
+          condition += ' && $valueName != ${defaultValue(fieldType, true)}';
+          writeCode = 'fbBuilder.addUint32($index, $valueName);';
+        } else if (_idl.enums.containsKey(fieldType.typeName)) {
+          condition += ' && $valueName != ${defaultValue(fieldType, true)}';
+          writeCode = 'fbBuilder.addUint8($index, $valueName.index);';
+        }
+        if (writeCode == null) {
+          throw new UnimplementedError('Writing type ${fieldType.typeName}');
+        }
+        out('if ($condition) {');
+        indent(() {
+          out(writeCode);
+        });
+        out('}');
+      }
+      out('return fbBuilder.endTable();');
+    });
+    out('}');
+  }
+
+  void _generateFlushInformative() {
+    out();
+    out('/// Flush [informative] data recursively.');
+    out('void flushInformative() {');
+
+    void writeField(String name, idlModel.FieldType type, bool isInformative) {
+      if (isInformative) {
+        out('$name = null;');
+      } else if (_idl.classes.containsKey(type.typeName)) {
+        if (type.isList) {
+          out('$name?.forEach((b) => b.flushInformative());');
+        } else {
+          out('$name?.flushInformative();');
+        }
+      }
+    }
+
+    indent(() {
+      if (cls.variantField != null) {
+        var firstVariant = true;
+        for (var variant in _computeVariants(cls)) {
+          if (firstVariant) {
+            firstVariant = false;
+          } else {
+            out('else');
+          }
+          out('if (${cls.variantField} == idl.$variant) {');
+          indent(() {
+            for (var field in cls.fields) {
+              var logicalProperties = field.logicalProperties;
+              if (logicalProperties != null) {
+                for (var logicalName in logicalProperties.keys) {
+                  var logicalProperty = logicalProperties[logicalName];
+                  if (logicalProperty.variants.contains(variant)) {
+                    writeField(
+                      logicalName,
+                      field.type,
+                      logicalProperty.isInformative,
+                    );
+                  }
+                }
+              } else {
+                writeField(field.name, field.type, field.isInformative);
+              }
+            }
+          });
+          out('}');
+        }
+      } else {
+        for (idlModel.FieldDeclaration field in cls.fields) {
+          writeField('_${field.name}', field.type, field.isInformative);
+        }
+      }
+    });
+    out('}');
+  }
+
+  void _generateGettersSetters() {
+    for (idlModel.FieldDeclaration field in cls.allFields) {
+      String fieldName = field.name;
+      idlModel.FieldType fieldType = field.type;
+      String typeStr = encodedType(fieldType);
+      String def = defaultValue(fieldType, true);
+      String defSuffix = def == null ? '' : ' ??= $def';
+      out();
+      if (field.isDeprecated) {
+        out('@override');
+        out('Null get $fieldName => ${_BaseGenerator._throwDeprecated};');
+      } else {
+        if (field.logicalProperties != null) {
+          for (var logicalName in field.logicalProperties.keys) {
+            var logicalProperty = field.logicalProperties[logicalName];
+            out('@override');
+            out('$typeStr get $logicalName {');
+            indent(() {
+              out(_variantAssertStatement(cls, logicalProperty));
+              out('return _${field.name}$defSuffix;');
+            });
+            out('}');
+            out();
+          }
+        } else {
+          out('@override');
+          out('$typeStr get $fieldName => _$fieldName$defSuffix;');
+        }
+        out();
+
+        constructorParams.add('$typeStr $fieldName');
+
+        outDoc(field.documentation);
+
+        if (field.logicalProperties != null) {
+          for (var logicalName in field.logicalProperties.keys) {
+            var logicalProperty = field.logicalProperties[logicalName];
+            out('set $logicalName($typeStr value) {');
+            indent(() {
+              out(_variantAssertStatement(cls, logicalProperty));
+              _generateNonNegativeInt(fieldType);
+              out('_variantField_${field.id} = value;');
+            });
+            out('}');
+            out();
+          }
+        } else {
+          out('set $fieldName($typeStr value) {');
+          indent(() {
+            _generateNonNegativeInt(fieldType);
+            out('this._$fieldName = value;');
+          });
+          out('}');
+        }
+      }
+    }
+  }
+
+  void _generateNonNegativeInt(idlModel.FieldType fieldType) {
+    if (fieldType.typeName == 'int') {
+      if (!fieldType.isList) {
+        out('assert(value == null || value >= 0);');
+      } else {
+        out('assert(value == null || value.every((e) => e >= 0));');
+      }
+    }
+  }
+
+  /// Generate a call to the appropriate method of [ApiSignature] for the type
+  /// [typeName], using the data named by [ref].  If [couldBeNull] is `true`,
+  /// generate code to handle the possibility that [ref] is `null` (substituting
+  /// in the appropriate default value).
+  void _generateSignatureCall(String typeName, String ref, bool couldBeNull) {
+    if (_idl.enums.containsKey(typeName)) {
+      if (couldBeNull) {
+        out('signature.addInt($ref == null ? 0 : $ref.index);');
+      } else {
+        out('signature.addInt($ref.index);');
+      }
+    } else if (_idl.classes.containsKey(typeName)) {
+      if (couldBeNull) {
+        out('signature.addBool($ref != null);');
+      }
+      out('$ref?.collectApiSignature(signature);');
+    } else {
+      switch (typeName) {
+        case 'String':
+          if (couldBeNull) {
+            ref += " ?? ''";
+          }
+          out("signature.addString($ref);");
+          break;
+        case 'int':
+          if (couldBeNull) {
+            ref += ' ?? 0';
+          }
+          out('signature.addInt($ref);');
+          break;
+        case 'bool':
+          if (couldBeNull) {
+            ref += ' == true';
+          }
+          out('signature.addBool($ref);');
+          break;
+        case 'double':
+          if (couldBeNull) {
+            ref += ' ?? 0.0';
+          }
+          out('signature.addDouble($ref);');
+          break;
+        default:
+          throw "Don't know how to generate signature call for $typeName";
+      }
+    }
+  }
+
+  void _generateToBuffer() {
+    if (cls.isTopLevel) {
+      out();
+      out('List<int> toBuffer() {');
+      indent(() {
+        out('fb.Builder fbBuilder = new fb.Builder();');
+        String fileId =
+            cls.fileIdentifier == null ? '' : ', ${quoted(cls.fileIdentifier)}';
+        out('return fbBuilder.finish(finish(fbBuilder)$fileId);');
+      });
+      out('}');
+    }
+  }
+}
+
+class _CodeGenerator {
+  /// Buffer in which generated code is accumulated.
+  final StringBuffer _outBuffer = new StringBuffer();
+
   /// Semantic model of the "IDL" input file.
   idlModel.Idl _idl;
 
@@ -133,63 +708,6 @@
     });
   }
 
-  /// Generate a string representing the Dart type which should be used to
-  /// represent [type] when deserialized.
-  String dartType(idlModel.FieldType type) {
-    String baseType = idlPrefix(type.typeName);
-    if (type.isList) {
-      return 'List<$baseType>';
-    } else {
-      return baseType;
-    }
-  }
-
-  /// Generate a Dart expression representing the default value for a field
-  /// having the given [type], or `null` if there is no default value.
-  ///
-  /// If [builder] is `true`, the returned type should be appropriate for use in
-  /// a builder class.
-  String defaultValue(idlModel.FieldType type, bool builder) {
-    if (type.isList) {
-      if (builder) {
-        idlModel.FieldType elementType =
-            new idlModel.FieldType(type.typeName, false);
-        return '<${encodedType(elementType)}>[]';
-      } else {
-        return 'const <${idlPrefix(type.typeName)}>[]';
-      }
-    } else if (_idl.enums.containsKey(type.typeName)) {
-      return '${idlPrefix(type.typeName)}.'
-          '${_idl.enums[type.typeName].values[0].name}';
-    } else if (type.typeName == 'double') {
-      return '0.0';
-    } else if (type.typeName == 'int') {
-      return '0';
-    } else if (type.typeName == 'String') {
-      return "''";
-    } else if (type.typeName == 'bool') {
-      return 'false';
-    } else {
-      return null;
-    }
-  }
-
-  /// Generate a string representing the Dart type which should be used to
-  /// represent [type] while building a serialized data structure.
-  String encodedType(idlModel.FieldType type) {
-    String typeStr;
-    if (_idl.classes.containsKey(type.typeName)) {
-      typeStr = '${type.typeName}Builder';
-    } else {
-      typeStr = idlPrefix(type.typeName);
-    }
-    if (type.isList) {
-      return 'List<$typeStr>';
-    } else {
-      return typeStr;
-    }
-  }
-
   /// Process the AST in [idlParsed] and store the resulting semantic model in
   /// [_idl].  Also perform some error checking.
   void extractIdl(CompilationUnit idlParsed) {
@@ -283,91 +801,10 @@
     }
   }
 
-  /// Generate a string representing the FlatBuffer schema type which should be
-  /// used to represent [type].
-  String fbsType(idlModel.FieldType type) {
-    String typeStr;
-    switch (type.typeName) {
-      case 'bool':
-        typeStr = 'bool';
-        break;
-      case 'double':
-        typeStr = 'double';
-        break;
-      case 'int':
-        typeStr = 'uint';
-        break;
-      case 'String':
-        typeStr = 'string';
-        break;
-      default:
-        typeStr = type.typeName;
-        break;
-    }
-    if (type.isList) {
-      // FlatBuffers don't natively support a packed list of booleans, so we
-      // treat it as a list of unsigned bytes, which is a compatible data
-      // structure.
-      if (typeStr == 'bool') {
-        typeStr = 'ubyte';
-      }
-      return '[$typeStr]';
-    } else {
-      return typeStr;
-    }
-  }
-
   /// Entry point to the code generator when generating the "format.fbs" file.
   void generateFlatBufferSchema() {
     outputHeader();
-    for (idlModel.EnumDeclaration enm in _idl.enums.values) {
-      out();
-      outDoc(enm.documentation);
-      out('enum ${enm.name} : byte {');
-      indent(() {
-        for (int i = 0; i < enm.values.length; i++) {
-          idlModel.EnumValueDeclaration value = enm.values[i];
-          if (i != 0) {
-            out();
-          }
-          String suffix = i < enm.values.length - 1 ? ',' : '';
-          outDoc(value.documentation);
-          out('${value.name}$suffix');
-        }
-      });
-      out('}');
-    }
-    for (idlModel.ClassDeclaration cls in _idl.classes.values) {
-      out();
-      outDoc(cls.documentation);
-      out('table ${cls.name} {');
-      indent(() {
-        for (int i = 0; i < cls.allFields.length; i++) {
-          idlModel.FieldDeclaration field = cls.allFields[i];
-          if (i != 0) {
-            out();
-          }
-          outDoc(field.documentation);
-          List<String> attributes = <String>['id: ${field.id}'];
-          if (field.isDeprecated) {
-            attributes.add('deprecated');
-          }
-          String attrText = attributes.join(', ');
-          out('${field.name}:${fbsType(field.type)} ($attrText);');
-        }
-      });
-      out('}');
-    }
-    out();
-    // Standard flatbuffers only support one root type.  We support multiple
-    // root types.  For now work around this by forcing PackageBundle to be the
-    // root type.  TODO(paulberry): come up with a better solution.
-    idlModel.ClassDeclaration rootType = _idl.classes['PackageBundle'];
-    out('root_type ${rootType.name};');
-    if (rootType.fileIdentifier != null) {
-      out();
-      out('file_identifier ${quoted(rootType.fileIdentifier)};');
-    }
+    _FlatBufferSchemaGenerator(_idl, _outBuffer).generate();
   }
 
   /// Entry point to the code generator when generating the "format.dart" file.
@@ -382,69 +819,33 @@
     out();
     out("import 'idl.dart' as idl;");
     out();
-    for (idlModel.EnumDeclaration enm in _idl.enums.values) {
-      _generateEnumReader(enm);
+    for (idlModel.EnumDeclaration enum_ in _idl.enums.values) {
+      _EnumReaderGenerator(_idl, _outBuffer, enum_).generate();
       out();
     }
     for (idlModel.ClassDeclaration cls in _idl.classes.values) {
       if (!cls.isDeprecated) {
-        _generateBuilder(cls);
+        _BuilderGenerator(_idl, _outBuffer, cls).generate();
         out();
       }
       if (cls.isTopLevel) {
-        _generateReadFunction(cls);
+        _ReaderGenerator(_idl, _outBuffer, cls).generateReaderFunction();
         out();
       }
       if (!cls.isDeprecated) {
-        _generateReader(cls);
+        _ReaderGenerator(_idl, _outBuffer, cls).generateReader();
         out();
-        _generateImpl(cls);
+        _ImplGenerator(_idl, _outBuffer, cls).generate();
         out();
-        _generateMixin(cls);
+        _MixinGenerator(_idl, _outBuffer, cls).generate();
         out();
       }
     }
   }
 
-  /// Add the prefix `idl.` to a type name, unless that type name is the name of
-  /// a built-in type.
-  String idlPrefix(String s) {
-    switch (s) {
-      case 'bool':
-      case 'double':
-      case 'int':
-      case 'String':
-        return s;
-      default:
-        return 'idl.$s';
-    }
-  }
-
-  /// Execute [callback] with two spaces added to [_indentation].
-  void indent(void callback()) {
-    String oldIndentation = _indentation;
-    try {
-      _indentation += '  ';
-      callback();
-    } finally {
-      _indentation = oldIndentation;
-    }
-  }
-
-  /// Add the string [s] to the output as a single line, indenting as
-  /// appropriate.
+  /// Add the string [s] to the output as a single line.
   void out([String s = '']) {
-    if (s == '') {
-      _outBuffer.writeln('');
-    } else {
-      _outBuffer.writeln('$_indentation$s');
-    }
-  }
-
-  void outDoc(String documentation) {
-    if (documentation != null) {
-      documentation.split('\n').forEach(out);
-    }
+    _outBuffer.writeln(s);
   }
 
   void outputHeader() {
@@ -459,11 +860,6 @@
     out();
   }
 
-  /// Enclose [s] in quotes, escaping as necessary.
-  String quoted(String s) {
-    return json.encode(s);
-  }
-
   void _addFieldForGetter(
     idlModel.ClassDeclaration cls,
     MethodDeclaration getter,
@@ -572,21 +968,21 @@
     var fieldType = new idlModel.FieldType(type.name, isList);
 
     String name = getter.name;
-    Map<String, List<String>> variantMap;
+    Map<String, idlModel.LogicalProperty> logicalProperties;
     if (variants != null) {
       var fieldsWithSameId =
           cls.allFields.where((field) => field.id == id).toList();
       if (fieldsWithSameId.isNotEmpty) {
-        var existingField = fieldsWithSameId.first;
-        if (existingField.variantMap == null) {
+        var existingField = fieldsWithSameId.single;
+        if (existingField.logicalProperties == null) {
           throw Exception('$desc: id $id is already used as a non-variant '
               'field: ${existingField.name}');
         }
 
-        var map = existingField.variantMap;
+        var map = existingField.logicalProperties;
         for (var variant in variants) {
           for (var logicalName in map.keys) {
-            if (map[logicalName].contains(variant)) {
+            if (map[logicalName].variants.contains(variant)) {
               throw Exception('$desc: id $id is already used for $logicalName');
             }
           }
@@ -598,11 +994,27 @@
           );
         }
 
-        map.putIfAbsent(getter.name, () => <String>[]).addAll(variants);
+        if (map[getter.name] != null) {
+          throw Exception(
+            '$desc: logical property ${getter.name} is already used',
+          );
+        }
+
+        map[getter.name] = idlModel.LogicalProperty(
+          isDeprecated: isDeprecated,
+          isInformative: isInformative,
+          variants: variants,
+        );
         return;
       } else {
         name = 'variantField_$id';
-        variantMap = <String, List<String>>{getter.name: variants};
+        logicalProperties = <String, idlModel.LogicalProperty>{
+          getter.name: idlModel.LogicalProperty(
+            isDeprecated: isDeprecated,
+            isInformative: isInformative,
+            variants: variants,
+          ),
+        };
       }
     }
 
@@ -614,318 +1026,46 @@
         id: id,
         isDeprecated: isDeprecated,
         isInformative: isInformative,
-        variantMap: variantMap,
+        logicalProperties: logicalProperties,
       ),
     );
   }
 
-  Iterable<String> _computeVariants(idlModel.ClassDeclaration cls) {
-    return cls.fields
-        .map((f) => f.variantMap?.values ?? [])
-        .expand((v) => v)
-        .expand((v) => v)
-        .toSet();
+  /// Return the documentation text of the given [node], or `null` if the [node]
+  /// does not have a comment.  Each line is `\n` separated.
+  String _getNodeDoc(AnnotatedNode node) {
+    Comment comment = node.documentationComment;
+    if (comment != null && comment.isDocumentation) {
+      if (comment.tokens.length == 1 &&
+          comment.tokens.first.lexeme.startsWith('/*')) {
+        Token token = comment.tokens.first;
+        return token.lexeme.split('\n').map((String line) {
+          line = line.trimLeft();
+          if (line.startsWith('*')) line = ' ' + line;
+          return line;
+        }).join('\n');
+      } else if (comment.tokens
+          .every((token) => token.lexeme.startsWith('///'))) {
+        return comment.tokens
+            .map((token) => token.lexeme.trimLeft())
+            .join('\n');
+      }
+    }
+    return null;
   }
+}
 
-  void _generateBuilder(idlModel.ClassDeclaration cls) {
-    String name = cls.name;
-    String builderName = name + 'Builder';
-    String mixinName = '_${name}Mixin';
-    List<String> constructorParams = <String>[];
-    var implementsClause =
-        cls.isDeprecated ? '' : ' implements ${idlPrefix(name)}';
-    out('class $builderName extends Object with $mixinName$implementsClause {');
-    indent(() {
-      // Generate fields.
-      for (idlModel.FieldDeclaration field in cls.fields) {
-        String fieldName = field.name;
-        idlModel.FieldType type = field.type;
-        String typeStr = encodedType(type);
-        out('$typeStr _$fieldName;');
-      }
+class _EnumReaderGenerator extends _BaseGenerator {
+  final idlModel.EnumDeclaration enum_;
 
-      // Generate getters and setters.
-      for (idlModel.FieldDeclaration field in cls.allFields) {
-        String fieldName = field.name;
-        idlModel.FieldType fieldType = field.type;
-        String typeStr = encodedType(fieldType);
-        String def = defaultValue(fieldType, true);
-        String defSuffix = def == null ? '' : ' ??= $def';
-        out();
-        if (field.isDeprecated) {
-          out('@override');
-          out('Null get $fieldName => $_throwDeprecated;');
-        } else {
-          if (field.variantMap != null) {
-            for (var logicalName in field.variantMap.keys) {
-              var variants = field.variantMap[logicalName];
-              out('@override');
-              out('$typeStr get $logicalName {');
-              indent(() {
-                out(_variantAssertStatement(cls, variants));
-                out('return _${field.name}$defSuffix;');
-              });
-              out('}');
-              out();
-            }
-          } else {
-            out('@override');
-            out('$typeStr get $fieldName => _$fieldName$defSuffix;');
-          }
-          out();
+  _EnumReaderGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.enum_)
+      : super(idl, outBuffer);
 
-          constructorParams.add('$typeStr $fieldName');
-
-          outDoc(field.documentation);
-
-          if (field.variantMap != null) {
-            for (var logicalName in field.variantMap.keys) {
-              var variants = field.variantMap[logicalName];
-              out('set $logicalName($typeStr value) {');
-              indent(() {
-                out(_variantAssertStatement(cls, variants));
-                _generateNonNegativeInt(fieldType);
-                out('_variantField_${field.id} = value;');
-              });
-              out('}');
-              out();
-            }
-          } else {
-            out('set $fieldName($typeStr value) {');
-            indent(() {
-              _generateNonNegativeInt(fieldType);
-              out('this._$fieldName = value;');
-            });
-            out('}');
-          }
-        }
-      }
-      // Generate constructor.
-      out();
-      if (cls.variantField != null) {
-        for (var variant in _computeVariants(cls)) {
-          var constructorName = variant.split('.')[1];
-          out('$builderName.$constructorName({');
-
-          for (var field in cls.fields) {
-            if (field.variantMap != null) {
-              for (var property in field.variantMap.keys) {
-                if (field.variantMap[property].contains(variant)) {
-                  out('${encodedType(field.type)} $property,');
-                }
-              }
-            }
-          }
-
-          out('}) : ');
-
-          out('_${cls.variantField} = idl.$variant');
-
-          var separator = ',';
-          for (var field in cls.fields) {
-            if (field.variantMap != null) {
-              for (var property in field.variantMap.keys) {
-                if (field.variantMap[property].contains(variant)) {
-                  out('$separator _${field.name} = $property');
-                  separator = ', ';
-                }
-              }
-            }
-          }
-
-          out(';');
-          out();
-        }
-      } else {
-        out('$builderName({${constructorParams.join(', ')}})');
-        List<idlModel.FieldDeclaration> fields = cls.fields.toList();
-        for (int i = 0; i < fields.length; i++) {
-          idlModel.FieldDeclaration field = fields[i];
-          String prefix = i == 0 ? '  : ' : '    ';
-          String suffix = i == fields.length - 1 ? ';' : ',';
-          out('${prefix}_${field.name} = ${field.name}$suffix');
-        }
-      }
-
-      // Generate flushInformative().
-      {
-        out();
-        out('/// Flush [informative] data recursively.');
-        out('void flushInformative() {');
-        indent(() {
-          for (idlModel.FieldDeclaration field in cls.fields) {
-            idlModel.FieldType fieldType = field.type;
-            String valueName = '_' + field.name;
-            if (field.isInformative) {
-              out('$valueName = null;');
-            } else if (_idl.classes.containsKey(fieldType.typeName)) {
-              if (fieldType.isList) {
-                out('$valueName?.forEach((b) => b.flushInformative());');
-              } else {
-                out('$valueName?.flushInformative();');
-              }
-            }
-          }
-        });
-        out('}');
-      }
-      // Generate collectApiSignature().
-      {
-        out();
-        out('/// Accumulate non-[informative] data into [signature].');
-        out('void collectApiSignature(api_sig.ApiSignature signature) {');
-        indent(() {
-          List<idlModel.FieldDeclaration> sortedFields = cls.fields.toList()
-            ..sort((idlModel.FieldDeclaration a, idlModel.FieldDeclaration b) =>
-                a.id.compareTo(b.id));
-          for (idlModel.FieldDeclaration field in sortedFields) {
-            if (field.isInformative) {
-              continue;
-            }
-            String ref = 'this._${field.name}';
-            if (field.type.isList) {
-              out('if ($ref == null) {');
-              indent(() {
-                out('signature.addInt(0);');
-              });
-              out('} else {');
-              indent(() {
-                out('signature.addInt($ref.length);');
-                out('for (var x in $ref) {');
-                indent(() {
-                  _generateSignatureCall(field.type.typeName, 'x', false);
-                });
-                out('}');
-              });
-              out('}');
-            } else {
-              _generateSignatureCall(field.type.typeName, ref, true);
-            }
-          }
-        });
-        out('}');
-      }
-      // Generate finish.
-      if (cls.isTopLevel) {
-        out();
-        out('List<int> toBuffer() {');
-        indent(() {
-          out('fb.Builder fbBuilder = new fb.Builder();');
-          String fileId = cls.fileIdentifier == null
-              ? ''
-              : ', ${quoted(cls.fileIdentifier)}';
-          out('return fbBuilder.finish(finish(fbBuilder)$fileId);');
-        });
-        out('}');
-      }
-      out();
-      out('fb.Offset finish(fb.Builder fbBuilder) {');
-      indent(() {
-        // Write objects and remember Offset(s).
-        for (idlModel.FieldDeclaration field in cls.fields) {
-          idlModel.FieldType fieldType = field.type;
-          String offsetName = 'offset_' + field.name;
-          if (fieldType.isList ||
-              fieldType.typeName == 'String' ||
-              _idl.classes.containsKey(fieldType.typeName)) {
-            out('fb.Offset $offsetName;');
-          }
-        }
-        for (idlModel.FieldDeclaration field in cls.fields) {
-          idlModel.FieldType fieldType = field.type;
-          String valueName = '_' + field.name;
-          String offsetName = 'offset_' + field.name;
-          String condition;
-          String writeCode;
-          if (fieldType.isList) {
-            condition = ' || $valueName.isEmpty';
-            if (_idl.classes.containsKey(fieldType.typeName)) {
-              String itemCode = 'b.finish(fbBuilder)';
-              String listCode = '$valueName.map((b) => $itemCode).toList()';
-              writeCode = '$offsetName = fbBuilder.writeList($listCode);';
-            } else if (_idl.enums.containsKey(fieldType.typeName)) {
-              String itemCode = 'b.index';
-              String listCode = '$valueName.map((b) => $itemCode).toList()';
-              writeCode = '$offsetName = fbBuilder.writeListUint8($listCode);';
-            } else if (fieldType.typeName == 'bool') {
-              writeCode = '$offsetName = fbBuilder.writeListBool($valueName);';
-            } else if (fieldType.typeName == 'int') {
-              writeCode =
-                  '$offsetName = fbBuilder.writeListUint32($valueName);';
-            } else if (fieldType.typeName == 'double') {
-              writeCode =
-                  '$offsetName = fbBuilder.writeListFloat64($valueName);';
-            } else {
-              assert(fieldType.typeName == 'String');
-              String itemCode = 'fbBuilder.writeString(b)';
-              String listCode = '$valueName.map((b) => $itemCode).toList()';
-              writeCode = '$offsetName = fbBuilder.writeList($listCode);';
-            }
-          } else if (fieldType.typeName == 'String') {
-            writeCode = '$offsetName = fbBuilder.writeString($valueName);';
-          } else if (_idl.classes.containsKey(fieldType.typeName)) {
-            writeCode = '$offsetName = $valueName.finish(fbBuilder);';
-          }
-          if (writeCode != null) {
-            if (condition == null) {
-              out('if ($valueName != null) {');
-            } else {
-              out('if (!($valueName == null$condition)) {');
-            }
-            indent(() {
-              out(writeCode);
-            });
-            out('}');
-          }
-        }
-        // Write the table.
-        out('fbBuilder.startTable();');
-        for (idlModel.FieldDeclaration field in cls.fields) {
-          int index = field.id;
-          idlModel.FieldType fieldType = field.type;
-          String valueName = '_' + field.name;
-          String condition = '$valueName != null';
-          String writeCode;
-          if (fieldType.isList ||
-              fieldType.typeName == 'String' ||
-              _idl.classes.containsKey(fieldType.typeName)) {
-            String offsetName = 'offset_' + field.name;
-            condition = '$offsetName != null';
-            writeCode = 'fbBuilder.addOffset($index, $offsetName);';
-          } else if (fieldType.typeName == 'bool') {
-            condition = '$valueName == true';
-            writeCode = 'fbBuilder.addBool($index, true);';
-          } else if (fieldType.typeName == 'double') {
-            condition += ' && $valueName != ${defaultValue(fieldType, true)}';
-            writeCode = 'fbBuilder.addFloat64($index, $valueName);';
-          } else if (fieldType.typeName == 'int') {
-            condition += ' && $valueName != ${defaultValue(fieldType, true)}';
-            writeCode = 'fbBuilder.addUint32($index, $valueName);';
-          } else if (_idl.enums.containsKey(fieldType.typeName)) {
-            condition += ' && $valueName != ${defaultValue(fieldType, true)}';
-            writeCode = 'fbBuilder.addUint8($index, $valueName.index);';
-          }
-          if (writeCode == null) {
-            throw new UnimplementedError('Writing type ${fieldType.typeName}');
-          }
-          out('if ($condition) {');
-          indent(() {
-            out(writeCode);
-          });
-          out('}');
-        }
-        out('return fbBuilder.endTable();');
-      });
-      out('}');
-    });
-    out('}');
-  }
-
-  void _generateEnumReader(idlModel.EnumDeclaration enm) {
-    String name = enm.name;
+  void generate() {
+    String name = enum_.name;
     String readerName = '_${name}Reader';
     String count = '${idlPrefix(name)}.values.length';
-    String def = '${idlPrefix(name)}.${enm.values[0].name}';
+    String def = '${idlPrefix(name)}.${enum_.values[0].name}';
     out('class $readerName extends fb.Reader<${idlPrefix(name)}> {');
     indent(() {
       out('const $readerName() : super();');
@@ -943,8 +1083,105 @@
     });
     out('}');
   }
+}
 
-  void _generateImpl(idlModel.ClassDeclaration cls) {
+class _FlatBufferSchemaGenerator extends _BaseGenerator {
+  _FlatBufferSchemaGenerator(idlModel.Idl idl, StringBuffer outBuffer)
+      : super(idl, outBuffer);
+
+  void generate() {
+    for (idlModel.EnumDeclaration enm in _idl.enums.values) {
+      out();
+      outDoc(enm.documentation);
+      out('enum ${enm.name} : byte {');
+      indent(() {
+        for (int i = 0; i < enm.values.length; i++) {
+          idlModel.EnumValueDeclaration value = enm.values[i];
+          if (i != 0) {
+            out();
+          }
+          String suffix = i < enm.values.length - 1 ? ',' : '';
+          outDoc(value.documentation);
+          out('${value.name}$suffix');
+        }
+      });
+      out('}');
+    }
+    for (idlModel.ClassDeclaration cls in _idl.classes.values) {
+      out();
+      outDoc(cls.documentation);
+      out('table ${cls.name} {');
+      indent(() {
+        for (int i = 0; i < cls.allFields.length; i++) {
+          idlModel.FieldDeclaration field = cls.allFields[i];
+          if (i != 0) {
+            out();
+          }
+          outDoc(field.documentation);
+          List<String> attributes = <String>['id: ${field.id}'];
+          if (field.isDeprecated) {
+            attributes.add('deprecated');
+          }
+          String attrText = attributes.join(', ');
+          out('${field.name}:${_fbsType(field.type)} ($attrText);');
+        }
+      });
+      out('}');
+    }
+    out();
+    // Standard flatbuffers only support one root type.  We support multiple
+    // root types.  For now work around this by forcing PackageBundle to be the
+    // root type.  TODO(paulberry): come up with a better solution.
+    idlModel.ClassDeclaration rootType = _idl.classes['PackageBundle'];
+    out('root_type ${rootType.name};');
+    if (rootType.fileIdentifier != null) {
+      out();
+      out('file_identifier ${quoted(rootType.fileIdentifier)};');
+    }
+  }
+
+  /// Generate a string representing the FlatBuffer schema type which should be
+  /// used to represent [type].
+  String _fbsType(idlModel.FieldType type) {
+    String typeStr;
+    switch (type.typeName) {
+      case 'bool':
+        typeStr = 'bool';
+        break;
+      case 'double':
+        typeStr = 'double';
+        break;
+      case 'int':
+        typeStr = 'uint';
+        break;
+      case 'String':
+        typeStr = 'string';
+        break;
+      default:
+        typeStr = type.typeName;
+        break;
+    }
+    if (type.isList) {
+      // FlatBuffers don't natively support a packed list of booleans, so we
+      // treat it as a list of unsigned bytes, which is a compatible data
+      // structure.
+      if (typeStr == 'bool') {
+        typeStr = 'ubyte';
+      }
+      return '[$typeStr]';
+    } else {
+      return typeStr;
+    }
+  }
+}
+
+class _ImplGenerator extends _BaseGenerator {
+  final idlModel.ClassDeclaration cls;
+
+  _ImplGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+      : super(idl, outBuffer);
+
+  void generate() {
     String name = cls.name;
     String implName = '_${name}Impl';
     String mixinName = '_${name}Mixin';
@@ -958,7 +1195,7 @@
       out();
       // Write cache fields.
       for (idlModel.FieldDeclaration field in cls.fields) {
-        String returnType = dartType(field.type);
+        String returnType = _dartType(field.type);
         String fieldName = field.name;
         out('$returnType _$fieldName;');
       }
@@ -1005,18 +1242,18 @@
         assert(readCode != null);
         // Write the getter implementation.
         out();
-        String returnType = dartType(type);
+        String returnType = _dartType(type);
         if (field.isDeprecated) {
           out('@override');
-          out('Null get $fieldName => $_throwDeprecated;');
+          out('Null get $fieldName => ${_BaseGenerator._throwDeprecated};');
         } else {
-          if (field.variantMap != null) {
-            for (var logicalName in field.variantMap.keys) {
-              var variants = field.variantMap[logicalName];
+          if (field.logicalProperties != null) {
+            for (var logicalName in field.logicalProperties.keys) {
+              var logicalProperty = field.logicalProperties[logicalName];
               out('@override');
               out('$returnType get $logicalName {');
               indent(() {
-                out(_variantAssertStatement(cls, variants));
+                out(_variantAssertStatement(cls, logicalProperty));
                 String readExpr =
                     '$readCode.vTableGet(_bc, _bcOffset, $index, $def)';
                 out('_$fieldName ??= $readExpr;');
@@ -1042,7 +1279,25 @@
     out('}');
   }
 
-  void _generateMixin(idlModel.ClassDeclaration cls) {
+  /// Generate a string representing the Dart type which should be used to
+  /// represent [type] when deserialized.
+  String _dartType(idlModel.FieldType type) {
+    String baseType = idlPrefix(type.typeName);
+    if (type.isList) {
+      return 'List<$baseType>';
+    } else {
+      return baseType;
+    }
+  }
+}
+
+class _MixinGenerator extends _BaseGenerator {
+  final idlModel.ClassDeclaration cls;
+
+  _MixinGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+      : super(idl, outBuffer);
+
+  void generate() {
     String name = cls.name;
     String mixinName = '_${name}Mixin';
     out('abstract class $mixinName implements ${idlPrefix(name)} {');
@@ -1088,7 +1343,7 @@
         if (cls.variantField != null) {
           indent(() {
             for (idlModel.FieldDeclaration field in cls.fields) {
-              if (field.variantMap == null) {
+              if (field.logicalProperties == null) {
                 var condition = jsonCondition(field.type, field.name);
                 var storeField = jsonStore(field.type, field.name);
                 out('if ($condition) $storeField;');
@@ -1098,9 +1353,11 @@
               out('if (${cls.variantField} == idl.$variant) {');
               indent(() {
                 for (idlModel.FieldDeclaration field in cls.fields) {
-                  if (field.variantMap != null) {
-                    for (var logicalName in field.variantMap.keys) {
-                      if (field.variantMap[logicalName].contains(variant)) {
+                  var logicalProperties = field.logicalProperties;
+                  if (logicalProperties != null) {
+                    for (var logicalName in logicalProperties.keys) {
+                      var logicalProperty = logicalProperties[logicalName];
+                      if (logicalProperty.variants.contains(variant)) {
                         var condition = jsonCondition(field.type, logicalName);
                         var storeField = jsonStore(field.type, logicalName);
                         out('if ($condition) $storeField;');
@@ -1136,9 +1393,10 @@
           indent(() {
             out('return {');
             for (idlModel.FieldDeclaration field in cls.fields) {
-              if (field.variantMap != null) {
-                for (var logicalName in field.variantMap.keys) {
-                  if (field.variantMap[logicalName].contains(variant)) {
+              if (field.logicalProperties != null) {
+                for (var logicalName in field.logicalProperties.keys) {
+                  var logicalProperty = field.logicalProperties[logicalName];
+                  if (logicalProperty.variants.contains(variant)) {
                     out('${quoted(logicalName)}: $logicalName,');
                   }
                 }
@@ -1170,18 +1428,15 @@
     });
     out('}');
   }
+}
 
-  void _generateNonNegativeInt(idlModel.FieldType fieldType) {
-    if (fieldType.typeName == 'int') {
-      if (!fieldType.isList) {
-        out('assert(value == null || value >= 0);');
-      } else {
-        out('assert(value == null || value.every((e) => e >= 0));');
-      }
-    }
-  }
+class _ReaderGenerator extends _BaseGenerator {
+  final idlModel.ClassDeclaration cls;
 
-  void _generateReader(idlModel.ClassDeclaration cls) {
+  _ReaderGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+      : super(idl, outBuffer);
+
+  void generateReader() {
     String name = cls.name;
     String readerName = '_${name}Reader';
     String implName = '_${name}Impl';
@@ -1195,7 +1450,7 @@
     out('}');
   }
 
-  void _generateReadFunction(idlModel.ClassDeclaration cls) {
+  void generateReaderFunction() {
     String name = cls.name;
     out('${idlPrefix(name)} read$name(List<int> buffer) {');
     indent(() {
@@ -1204,85 +1459,4 @@
     });
     out('}');
   }
-
-  /// Generate a call to the appropriate method of [ApiSignature] for the type
-  /// [typeName], using the data named by [ref].  If [couldBeNull] is `true`,
-  /// generate code to handle the possibility that [ref] is `null` (substituting
-  /// in the appropriate default value).
-  void _generateSignatureCall(String typeName, String ref, bool couldBeNull) {
-    if (_idl.enums.containsKey(typeName)) {
-      if (couldBeNull) {
-        out('signature.addInt($ref == null ? 0 : $ref.index);');
-      } else {
-        out('signature.addInt($ref.index);');
-      }
-    } else if (_idl.classes.containsKey(typeName)) {
-      if (couldBeNull) {
-        out('signature.addBool($ref != null);');
-      }
-      out('$ref?.collectApiSignature(signature);');
-    } else {
-      switch (typeName) {
-        case 'String':
-          if (couldBeNull) {
-            ref += " ?? ''";
-          }
-          out("signature.addString($ref);");
-          break;
-        case 'int':
-          if (couldBeNull) {
-            ref += ' ?? 0';
-          }
-          out('signature.addInt($ref);');
-          break;
-        case 'bool':
-          if (couldBeNull) {
-            ref += ' == true';
-          }
-          out('signature.addBool($ref);');
-          break;
-        case 'double':
-          if (couldBeNull) {
-            ref += ' ?? 0.0';
-          }
-          out('signature.addDouble($ref);');
-          break;
-        default:
-          throw "Don't know how to generate signature call for $typeName";
-      }
-    }
-  }
-
-  /// Return the documentation text of the given [node], or `null` if the [node]
-  /// does not have a comment.  Each line is `\n` separated.
-  String _getNodeDoc(AnnotatedNode node) {
-    Comment comment = node.documentationComment;
-    if (comment != null && comment.isDocumentation) {
-      if (comment.tokens.length == 1 &&
-          comment.tokens.first.lexeme.startsWith('/*')) {
-        Token token = comment.tokens.first;
-        return token.lexeme.split('\n').map((String line) {
-          line = line.trimLeft();
-          if (line.startsWith('*')) line = ' ' + line;
-          return line;
-        }).join('\n');
-      } else if (comment.tokens
-          .every((token) => token.lexeme.startsWith('///'))) {
-        return comment.tokens
-            .map((token) => token.lexeme.trimLeft())
-            .join('\n');
-      }
-    }
-    return null;
-  }
-
-  String _variantAssertStatement(
-    idlModel.ClassDeclaration class_,
-    List<String> variants,
-  ) {
-    var assertCondition = variants
-        ?.map((key) => '${class_.variantField} == idl.$key')
-        ?.join(' || ');
-    return 'assert($assertCondition);';
-  }
 }
diff --git a/pkg/analyzer/tool/summary/idl_model.dart b/pkg/analyzer/tool/summary/idl_model.dart
index 597e669..5354155 100644
--- a/pkg/analyzer/tool/summary/idl_model.dart
+++ b/pkg/analyzer/tool/summary/idl_model.dart
@@ -115,9 +115,9 @@
   final bool isInformative;
 
   /**
-   * Maps logical property names to variants in which this field is available.
+   * Maps logical property names to logical property.
    */
-  final Map<String, List<String>> variantMap;
+  final Map<String, LogicalProperty> logicalProperties;
 
   FieldDeclaration({
     @required String documentation,
@@ -126,7 +126,7 @@
     @required this.id,
     @required this.isDeprecated,
     @required this.isInformative,
-    @required this.variantMap,
+    @required this.logicalProperties,
   }) : super(documentation, name);
 }
 
@@ -179,3 +179,29 @@
    */
   final Map<String, EnumDeclaration> enums = <String, EnumDeclaration>{};
 }
+
+/**
+ * Information about a logical property mapped to a single data fields.
+ */
+class LogicalProperty {
+  /**
+   * Indicates whether the property is deprecated.
+   */
+  final bool isDeprecated;
+
+  /**
+   * Indicates whether the property is informative.
+   */
+  final bool isInformative;
+
+  /**
+   * Names of variants in which this property is available.
+   */
+  final List<String> variants;
+
+  LogicalProperty({
+    @required this.isDeprecated,
+    @required this.isInformative,
+    @required this.variants,
+  });
+}
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index 5bb4368..10ef17b 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -8,6 +8,7 @@
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
@@ -15,7 +16,10 @@
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
+import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -28,6 +32,10 @@
 import 'package:analyzer/src/summary/summarize_ast.dart';
 import 'package:analyzer/src/summary/summarize_elements.dart';
 import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk;
+import 'package:analyzer/src/summary2/link.dart' as summary2;
+import 'package:analyzer/src/summary2/linked_bundle_context.dart' as summary2;
+import 'package:analyzer/src/summary2/linked_element_factory.dart' as summary2;
+import 'package:analyzer/src/summary2/reference.dart' as summary2;
 import 'package:analyzer_cli/src/context_cache.dart';
 import 'package:analyzer_cli/src/driver.dart';
 import 'package:analyzer_cli/src/error_formatter.dart';
@@ -175,16 +183,23 @@
   final ContextCache contextCache;
 
   SummaryDataStore summaryDataStore;
-  AnalysisOptions analysisOptions;
+  AnalysisOptionsImpl analysisOptions;
   Map<Uri, File> uriToFileMap;
   final List<Source> explicitSources = <Source>[];
   final List<PackageBundle> unlinkedBundles = <PackageBundle>[];
 
+  SourceFactory sourceFactory;
+  DeclaredVariables declaredVariables;
   AnalysisDriver analysisDriver;
 
   PackageBundleAssembler assembler;
   final Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{};
 
+  final bool buildSummary2 = true;
+  final bool consumeSummary2 = false;
+  final Map<String, ParsedUnitResult> inputParsedUnitResults = {};
+  summary2.LinkedElementFactory elementFactory;
+
   // May be null.
   final DependencyTracker dependencyTracker;
 
@@ -275,6 +290,10 @@
             _computeLinkedLibraries(unlinkedUris);
           }
 
+          if (buildSummary2) {
+            _computeLinkedLibraries2();
+          }
+
           // Write the whole package bundle.
           PackageBundleBuilder bundle = assembler.assemble();
           if (options.buildSummaryOutput != null) {
@@ -351,6 +370,58 @@
     });
   }
 
+  /**
+   * Use [elementFactory] filled with input summaries, and link prepared
+   * [inputParsedUnitResults] to produce linked libraries in [assembler].
+   */
+  void _computeLinkedLibraries2() {
+    logger.run('Link output summary2', () {
+      var inputLibraries = <summary2.LinkInputLibrary>[];
+
+      for (var librarySource in explicitSources) {
+        var path = librarySource.fullName;
+
+        var parseResult = inputParsedUnitResults[path];
+        if (parseResult == null) {
+          throw ArgumentError('No parsed unit for $path');
+        }
+
+        var unit = parseResult.unit;
+        var isPart = unit.directives.any((d) => d is PartOfDirective);
+        if (isPart) {
+          continue;
+        }
+
+        var inputUnits = <summary2.LinkInputUnit>[];
+        inputUnits.add(
+          summary2.LinkInputUnit(librarySource, false, unit),
+        );
+
+        for (var directive in unit.directives) {
+          if (directive is PartDirective) {
+            var partUri = directive.uri.stringValue;
+            var partSource = sourceFactory.resolveUri(librarySource, partUri);
+            var partPath = partSource.fullName;
+            var partParseResult = inputParsedUnitResults[partPath];
+            if (partParseResult == null) {
+              throw ArgumentError('No parsed unit for part $partPath in $path');
+            }
+            inputUnits.add(
+              summary2.LinkInputUnit(partSource, false, partParseResult.unit),
+            );
+          }
+        }
+
+        inputLibraries.add(
+          summary2.LinkInputLibrary(librarySource, inputUnits),
+        );
+      }
+
+      var linkResult = summary2.link(elementFactory, inputLibraries);
+      assembler.setBundle2(linkResult.bundle);
+    });
+  }
+
   Future<ErrorSeverity> _computeMaxSeverity() async {
     ErrorSeverity maxSeverity = ErrorSeverity.NONE;
     if (!options.buildSuppressExitCode) {
@@ -429,7 +500,7 @@
       summaryDataStore.addBundle(null, sdkBundle);
     });
 
-    var sourceFactory = new SourceFactory(<UriResolver>[
+    sourceFactory = new SourceFactory(<UriResolver>[
       new DartUriResolver(sdk),
       new TrackingInSummaryUriResolver(
           new InSummaryUriResolver(resourceProvider, summaryDataStore),
@@ -449,14 +520,38 @@
         new FileContentOverlay(),
         null,
         sourceFactory,
-        analysisOptions as AnalysisOptionsImpl,
+        analysisOptions,
         externalSummaries: summaryDataStore);
-    analysisDriver.declaredVariables =
-        new DeclaredVariables.fromMap(options.definedVariables);
+
+    declaredVariables = new DeclaredVariables.fromMap(options.definedVariables);
+    analysisDriver.declaredVariables = declaredVariables;
+
+    if (buildSummary2) {
+      _createLinkedElementFactory();
+    }
 
     scheduler.start();
   }
 
+  void _createLinkedElementFactory() {
+    var analysisContext = RestrictedAnalysisContext(
+      SynchronousSession(analysisOptions, declaredVariables),
+      sourceFactory,
+    );
+
+    elementFactory = summary2.LinkedElementFactory(
+      analysisContext,
+      null,
+      summary2.Reference.root(),
+    );
+
+    for (var bundle in summaryDataStore.bundles) {
+      elementFactory.addBundle(
+        summary2.LinkedBundleContext(elementFactory, bundle.bundle2),
+      );
+    }
+  }
+
   /**
    * Convert [sourceEntities] (a list of file specifications of the form
    * "$uri|$path") to a map from URI to path.  If an error occurs, report the
@@ -495,13 +590,14 @@
     }
     // Parse the source and serialize its AST.
     Uri uri = Uri.parse(absoluteUri);
-    Source source = analysisDriver.sourceFactory.forUri2(uri);
+    Source source = sourceFactory.forUri2(uri);
     if (!source.exists()) {
       // TODO(paulberry): we should report a warning/error because DDC
       // compilations are unlikely to work.
       return;
     }
     var result = await analysisDriver.parseFile(source.fullName);
+    inputParsedUnitResults[result.path] = result;
     UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(result.unit);
     uriToUnit[absoluteUri] = unlinkedUnit;
     assembler.addUnlinkedUnit(source, unlinkedUnit);
@@ -513,6 +609,11 @@
    */
   Future<void> _printErrors({String outputPath}) async {
     await logger.runAsync('Compute and print analysis errors', () async {
+      var wasUseSummary2 = AnalysisDriver.useSummary2;
+      if (consumeSummary2) {
+        AnalysisDriver.useSummary2 = true;
+      }
+
       StringBuffer buffer = new StringBuffer();
       var severityProcessor = (AnalysisError error) =>
           determineProcessedSeverity(error, options, analysisOptions);
@@ -537,6 +638,8 @@
       } else {
         new io.File(outputPath).writeAsStringSync(buffer.toString());
       }
+
+      AnalysisDriver.useSummary2 = wasUseSummary2;
     });
   }
 }
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
index 2449bb7..4050a75 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
@@ -393,6 +393,34 @@
     return parameterElement?.type is FunctionType;
   }
 
+  /**
+   * Given that the [node] contains the [offset], return the [FormalParameter]
+   * that encloses the [offset], or `null`.
+   */
+  static FormalParameter findFormalParameter(
+    FormalParameterList node,
+    int offset,
+  ) {
+    assert(node.offset < offset && offset < node.end);
+    var parameters = node.parameters;
+    for (var i = 0; i < parameters.length; i++) {
+      var parameter = parameters[i];
+      if (i == 0 && offset < parameter.offset) {
+        return parameter;
+      }
+      if (parameter.offset <= offset) {
+        if (i < parameters.length - 1) {
+          if (offset < parameters[i + 1].offset) {
+            return parameter;
+          }
+        } else if (offset <= node.rightParenthesis.offset) {
+          return parameter;
+        }
+      }
+    }
+    return null;
+  }
+
   static int _computeArgIndex(AstNode containingNode, Object entity) {
     var argList = containingNode;
     if (argList is NamedExpression) {
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index 6e035ce..2b0dc59 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
@@ -82,6 +82,17 @@
   bool includeVarNameSuggestions = false;
 
   /**
+   * Indicates whether the completion location is in a field declaration.
+   */
+  bool inFieldDeclaration = false;
+
+  /**
+   * Indicates whether the completion location is in a top-level variable
+   * declaration.
+   */
+  bool inTopLevelVariableDeclaration = false;
+
+  /**
    * Indicates whether the completion location is in the body of a static method.
    */
   bool inStaticMethodBody = false;
@@ -150,6 +161,11 @@
       }
     }
 
+    optype.inFieldDeclaration =
+        targetNode.thisOrAncestorOfType<FieldDeclaration>() != null;
+    optype.inTopLevelVariableDeclaration =
+        targetNode.thisOrAncestorOfType<TopLevelVariableDeclaration>() != null;
+
     // If a value should be suggested, suggest also constructors.
     if (optype.includeReturnValueSuggestions) {
       // Careful: in angular plugin, `target.unit` may be null!
@@ -648,28 +664,27 @@
         }
       }
     }
+
+    // Find the containing parameter.
+    var parameter = CompletionTarget.findFormalParameter(node, offset);
+    if (parameter == null) return;
+
     // Handle default normal parameter just as a normal parameter.
-    if (entity is DefaultFormalParameter) {
-      entity = entity.parameter;
+    if (parameter is DefaultFormalParameter) {
+      parameter = (parameter as DefaultFormalParameter).parameter;
     }
+
     // "(^ this.field)"
-    if (entity is FieldFormalParameter) {
-      if (offset < entity.thisKeyword.offset) {
+    if (parameter is FieldFormalParameter) {
+      if (offset < parameter.thisKeyword.offset) {
         optype.includeTypeNameSuggestions = true;
       }
+      return;
     }
+
     // "(Type name)"
-    if (entity is SimpleFormalParameter) {
-      // "(Type^)" is parsed as a parameter with the _name_ "Type".
-      if (entity.type == null) {
-        optype.includeTypeNameSuggestions = true;
-      }
-      // If inside of "Type" in "(Type^ name)", then include types.
-      if (entity.type != null &&
-          entity.type.offset <= offset &&
-          offset <= entity.type.end) {
-        optype.includeTypeNameSuggestions = true;
-      }
+    if (parameter is SimpleFormalParameter) {
+      visitSimpleFormalParameter(parameter);
     }
   }
 
@@ -974,6 +989,45 @@
   }
 
   @override
+  void visitSimpleFormalParameter(SimpleFormalParameter node) {
+    var type = node.type;
+    var name = node.identifier;
+
+    // "(Type^)" is parsed as a parameter with the _name_ "Type".
+    if (type == null &&
+        name != null &&
+        name.offset <= offset &&
+        offset <= name.end) {
+      optype.includeTypeNameSuggestions = true;
+      return;
+    }
+
+    // If "(^ Type)", then include types.
+    if (type == null && offset < name.offset) {
+      optype.includeTypeNameSuggestions = true;
+      return;
+    }
+
+    // If "(Type ^)", then include parameter names.
+    if (type == null && name.end < offset && offset <= name.token.next.offset) {
+      optype.includeVarNameSuggestions = true;
+      return;
+    }
+
+    // If inside of "Type" in "(Type^ name)", then include types.
+    if (type != null && type.offset <= offset && offset <= type.end) {
+      optype.includeTypeNameSuggestions = true;
+      return;
+    }
+
+    // If "(Type name^)", then include parameter names.
+    if (type != null && name.offset <= offset && offset <= name.end) {
+      optype.includeVarNameSuggestions = true;
+      return;
+    }
+  }
+
+  @override
   void visitSimpleIdentifier(SimpleIdentifier node) {
     // This should never happen; the containingNode will always be some node
     // higher up in the parse tree, and the SimpleIdentifier will be the
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
index 8f42f89..83a16cf 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
@@ -37,7 +37,7 @@
       '',
       'b: ',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: ({a: int, b: String}) → Foo',
+      expectedExecutable: 'Foo.<init>: Foo Function({a: int, b: String})',
       expectedParameter: 'b: String',
     );
   }
@@ -55,7 +55,7 @@
       ')',
       '()',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: (int) → Foo',
+      expectedExecutable: 'Foo.<init>: Foo Function(int)',
       expectedParameter: 'a: int',
     );
   }
@@ -83,7 +83,7 @@
       ')',
       '()',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: (int, int) → Foo<int>',
+      expectedExecutable: 'Foo.<init>: Foo<int> Function(int, int)',
       expectedParameter: 'a: int',
     );
   }
@@ -102,7 +102,7 @@
       ')',
       '(false)',
       argIndex: 1,
-      expectedExecutable: 'Foo.<init>: (bool, bool) → Foo<bool>',
+      expectedExecutable: 'Foo.<init>: Foo<bool> Function(bool, bool)',
       expectedParameter: 'b: bool',
     );
   }
@@ -121,7 +121,8 @@
       '',
       'b: ',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: ({a: int, b: String, c: double}) → Foo',
+      expectedExecutable:
+          'Foo.<init>: Foo Function({a: int, b: String, c: double})',
       expectedParameter: 'b: String',
     );
   }
@@ -140,7 +141,7 @@
       '',
       'b: ',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: ({a: int}) → Foo',
+      expectedExecutable: 'Foo.<init>: Foo Function({a: int})',
     );
   }
 
@@ -158,7 +159,7 @@
       ')',
       '(0)',
       argIndex: 1,
-      expectedExecutable: 'Foo.named: (int, String, double) → Foo',
+      expectedExecutable: 'Foo.named: Foo Function(int, String, double)',
       expectedParameter: 'b: String',
     );
   }
@@ -177,7 +178,7 @@
       ')',
       '()',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: (int) → Foo',
+      expectedExecutable: 'Foo.<init>: Foo Function(int)',
       expectedParameter: 'a: int',
     );
   }
@@ -196,8 +197,8 @@
       ')',
       '()',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: ((String) → int) → Foo',
-      expectedParameter: 'f: (String) → int',
+      expectedExecutable: 'Foo.<init>: Foo Function(int Function(String))',
+      expectedParameter: 'f: int Function(String)',
       isFunctionalArgument: true,
     );
   }
@@ -214,7 +215,7 @@
       ')',
       '()',
       argIndex: 0,
-      expectedExecutable: 'Foo.<init>: () → Foo',
+      expectedExecutable: 'Foo.<init>: Foo Function()',
     );
   }
 
@@ -230,7 +231,7 @@
       ')',
       '(a)',
       argIndex: 1,
-      expectedExecutable: 'Foo.<init>: () → Foo',
+      expectedExecutable: 'Foo.<init>: Foo Function()',
     );
   }
 
@@ -246,7 +247,7 @@
       '',
       'b: ',
       argIndex: 0,
-      expectedExecutable: 'foo: ({a: int, b: String, c: double}) → int',
+      expectedExecutable: 'foo: int Function({a: int, b: String, c: double})',
       expectedParameter: 'b: String',
     );
   }
@@ -263,8 +264,8 @@
       '',
       'f: ',
       argIndex: 0,
-      expectedExecutable: 'foo: ({f: (String) → int}) → int',
-      expectedParameter: 'f: (String) → int',
+      expectedExecutable: 'foo: int Function({f: int Function(String)})',
+      expectedParameter: 'f: int Function(String)',
       isFunctionalArgument: true,
     );
   }
@@ -281,7 +282,7 @@
       '',
       'b: ',
       argIndex: 0,
-      expectedExecutable: 'foo: ({a: int}) → int',
+      expectedExecutable: 'foo: int Function({a: int})',
     );
   }
 
@@ -297,7 +298,7 @@
       ')',
       '(0)',
       argIndex: 1,
-      expectedExecutable: 'foo: (int, String) → int',
+      expectedExecutable: 'foo: int Function(int, String)',
       expectedParameter: 'b: String',
     );
   }
@@ -314,8 +315,8 @@
       ')',
       '()',
       argIndex: 0,
-      expectedExecutable: 'foo: ((String) → int) → int',
-      expectedParameter: 'f: (String) → int',
+      expectedExecutable: 'foo: int Function(int Function(String))',
+      expectedParameter: 'f: int Function(String)',
       isFunctionalArgument: true,
     );
   }
@@ -334,8 +335,8 @@
       ')',
       '()',
       argIndex: 0,
-      expectedExecutable: 'C.foo: ((String) → int) → int',
-      expectedParameter: 'f: (String) → int',
+      expectedExecutable: 'C.foo: int Function(int Function(String))',
+      expectedParameter: 'f: int Function(String)',
       isFunctionalArgument: true,
     );
   }
@@ -352,7 +353,7 @@
       'n',
       '(n)',
       argIndex: 0,
-      expectedExecutable: 'foo: (int, String) → int',
+      expectedExecutable: 'foo: int Function(int, String)',
       expectedParameter: 'a: int',
     );
   }
@@ -369,7 +370,7 @@
       ')',
       '((n))',
       argIndex: 0,
-      expectedExecutable: 'foo: (int, String) → int',
+      expectedExecutable: 'foo: int Function(int, String)',
       expectedParameter: 'a: int',
     );
   }
@@ -386,7 +387,7 @@
       'n',
       '(n)',
       argIndex: 0,
-      expectedExecutable: 'foo: (int, String) → int',
+      expectedExecutable: 'foo: int Function(int, String)',
       expectedParameter: 'a: int',
     );
   }
@@ -664,6 +665,13 @@
     assertTarget('new C();', '{var f; {var x;} new C();}');
   }
 
+  test_MapLiteral_empty() async {
+    // MapLiteral  VariableDeclaration
+    await createTarget('foo = {^');
+    // fasta scanner inserts synthetic closing '}'
+    assertTarget('}', '{}');
+  }
+
   test_MapLiteral_expression() async {
     super.setUp();
     final experimentStatus =
@@ -683,13 +691,6 @@
     }
   }
 
-  test_MapLiteral_empty() async {
-    // MapLiteral  VariableDeclaration
-    await createTarget('foo = {^');
-    // fasta scanner inserts synthetic closing '}'
-    assertTarget('}', '{}');
-  }
-
   test_MapLiteralEntry() async {
     // SimpleIdentifier  MapLiteralEntry  MapLiteral  VariableDeclaration
     await createTarget('foo = {7:T^};');
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
index caf7f39..186cfa7 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
@@ -2131,23 +2131,35 @@
     await assertOpType(functionBody: true);
   }
 
-//
   test_SimpleFormalParameter_closure() async {
     // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
     addTestSource('mth() { PNGS.sort((String a, Str^) => a.compareTo(b)); }');
     await assertOpType(typeNames: true, functionBody: true);
   }
 
-  test_SimpleFormalParameter_name1() async {
-    // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
-    addTestSource('m(String na^) {}');
-    await assertOpType(typeNames: false);
+  test_SimpleFormalParameter_name_typed() async {
+    addTestSource('f(String ^, int b) {}');
+    await assertOpType(typeNames: false, varNames: true);
   }
 
-  test_SimpleFormalParameter_name2() async {
-    // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
-    addTestSource('m(int first, String na^) {}');
-    await assertOpType(typeNames: false);
+  test_SimpleFormalParameter_name_typed_hasName() async {
+    addTestSource('f(String n^, int b) {}');
+    await assertOpType(typeNames: false, varNames: true);
+  }
+
+  test_SimpleFormalParameter_name_typed_last() async {
+    addTestSource('f(String ^) {}');
+    await assertOpType(typeNames: false, varNames: true);
+  }
+
+  test_SimpleFormalParameter_name_typed_last_hasName() async {
+    addTestSource('f(String n^) {}');
+    await assertOpType(typeNames: false, varNames: true);
+  }
+
+  test_SimpleFormalParameter_type_named() async {
+    addTestSource('f(^ name) {}');
+    await assertOpType(typeNames: true, varNames: false);
   }
 
   test_SimpleFormalParameter_type_optionalNamed() async {
@@ -2186,6 +2198,11 @@
     await assertOpType(typeNames: true);
   }
 
+  test_SimpleFormalParameter_untyped() async {
+    addTestSource('main(final ^) {}');
+    await assertOpType(typeNames: true, varNames: false);
+  }
+
   test_SwitchCase_before() async {
     // SwitchCase  SwitchStatement  Block
     addTestSource('main() {switch(k) {^case 1:}}');
diff --git a/pkg/compiler/lib/src/backend_strategy.dart b/pkg/compiler/lib/src/backend_strategy.dart
index 444937c..d9a48b1 100644
--- a/pkg/compiler/lib/src/backend_strategy.dart
+++ b/pkg/compiler/lib/src/backend_strategy.dart
@@ -5,6 +5,7 @@
 library dart2js.backend_strategy;
 
 import 'common.dart';
+import 'common/codegen.dart';
 import 'common/tasks.dart';
 import 'deferred_load.dart' show OutputUnitData;
 import 'enqueue.dart';
@@ -12,7 +13,9 @@
 import 'inferrer/types.dart';
 import 'io/source_information.dart';
 import 'js_backend/inferred_data.dart';
+import 'js_backend/interceptor_data.dart';
 import 'js_backend/native_data.dart';
+import 'serialization/serialization.dart';
 import 'ssa/ssa.dart';
 import 'universe/codegen_world_builder.dart';
 import 'universe/world_builder.dart';
@@ -35,10 +38,12 @@
   CodegenWorldBuilder createCodegenWorldBuilder(
       NativeBasicData nativeBasicData,
       JClosedWorld closedWorld,
-      SelectorConstraintsStrategy selectorConstraintsStrategy);
+      SelectorConstraintsStrategy selectorConstraintsStrategy,
+      OneShotInterceptorData oneShotInterceptorData);
 
   /// Creates the [WorkItemBuilder] used by the codegen enqueuer.
-  WorkItemBuilder createCodegenWorkItemBuilder(JClosedWorld closedWorld);
+  WorkItemBuilder createCodegenWorkItemBuilder(
+      JClosedWorld closedWorld, CodegenResults codegenResults);
 
   /// Creates the [SsaBuilder] used for the element model.
   SsaBuilder createSsaBuilder(
@@ -53,4 +58,15 @@
   /// Creates the [TypesInferrer] used by this strategy.
   TypesInferrer createTypesInferrer(
       JClosedWorld closedWorld, InferredDataBuilder inferredDataBuilder);
+
+  /// Calls [f] for every member that needs to be serialized for modular code
+  /// generation and returns an [EntityWriter] for encoding these members in
+  /// the serialized data.
+  ///
+  /// The needed members include members computed on demand during non-modular
+  /// code generation, such as constructor bodies and and generator bodies.
+  EntityWriter forEachCodegenMember(void Function(MemberEntity member) f);
+
+  /// Prepare [source] to deserialize modular code generation data.
+  void prepareCodegenReader(DataSource source);
 }
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 343d58b..beb4c95 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -261,6 +261,9 @@
   /// the closure class.
   FunctionEntity get callMethod => null;
 
+  /// The signature method for [callMethod] if needed.
+  FunctionEntity get signatureMethod => null;
+
   /// List of locals that this closure class has created corresponding field
   /// entities for.
   @deprecated
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 576cfc4..801a18f 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -84,6 +84,10 @@
   static const String dillDependencies = '--dill-dependencies';
   static const String readData = '--read-data';
   static const String writeData = '--write-data';
+  static const String readCodegen = '--read-codegen';
+  static const String writeCodegen = '--write-codegen';
+  static const String codegenShard = '--codegen-shard';
+  static const String codegenShards = '--codegen-shards';
   static const String cfeOnly = '--cfe-only';
   static const String debugGlobalInference = '--debug-global-inference';
 
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 852152d..f7c4050 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -6,18 +6,22 @@
 
 import 'package:js_ast/src/precedence.dart' as js show PRIMARY;
 
+import '../common.dart';
 import '../common_elements.dart';
 import '../constants/values.dart';
 import '../deferred_load.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart' show DartType, InterfaceType;
 import '../inferrer/abstract_value_domain.dart';
+import '../inferrer/types.dart';
 import '../io/source_information.dart';
 import '../js/js.dart' as js;
+import '../js_backend/backend.dart';
 import '../js_backend/namer.dart';
 import '../js_emitter/code_emitter_task.dart' show Emitter;
 import '../native/behavior.dart';
 import '../serialization/serialization.dart';
+import '../ssa/ssa.dart';
 import '../universe/feature.dart';
 import '../universe/selector.dart';
 import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
@@ -57,6 +61,8 @@
   Iterable<NativeBehavior> get nativeBehaviors => const [];
 
   Iterable<FunctionEntity> get nativeMethods => const [];
+
+  Iterable<Selector> get oneShotInterceptors => const [];
 }
 
 class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
@@ -70,6 +76,7 @@
   Set<GenericInstantiation> _genericInstantiations;
   List<NativeBehavior> _nativeBehaviors;
   Set<FunctionEntity> _nativeMethods;
+  Set<Selector> _oneShotInterceptors;
 
   _CodegenImpact();
 
@@ -85,7 +92,8 @@
       this._asyncMarkers,
       this._genericInstantiations,
       this._nativeBehaviors,
-      this._nativeMethods)
+      this._nativeMethods,
+      this._oneShotInterceptors)
       : super.internal(dynamicUses, staticUses, typeUses, constantUses);
 
   factory _CodegenImpact.readFromDataSource(DataSource source) {
@@ -126,6 +134,9 @@
         emptyAsNull: true);
     Set<FunctionEntity> nativeMethods =
         source.readMembers<FunctionEntity>(emptyAsNull: true)?.toSet();
+    Set<Selector> oneShotInterceptors = source
+        .readList(() => Selector.readFromDataSource(source), emptyAsNull: true)
+        ?.toSet();
     source.end(tag);
     return new _CodegenImpact.internal(
         dynamicUses,
@@ -139,7 +150,8 @@
         asyncMarkers,
         genericInstantiations,
         nativeBehaviors,
-        nativeMethods);
+        nativeMethods,
+        oneShotInterceptors);
   }
 
   @override
@@ -172,6 +184,9 @@
         (NativeBehavior behavior) => behavior.writeToDataSink(sink),
         allowNull: true);
     sink.writeMembers(_nativeMethods, allowNull: true);
+    sink.writeList(_oneShotInterceptors,
+        (Selector selector) => selector.writeToDataSink(sink),
+        allowNull: true);
     sink.end(tag);
   }
 
@@ -267,6 +282,16 @@
     return _nativeMethods ?? const [];
   }
 
+  void registerOneShotInterceptor(Selector selector) {
+    _oneShotInterceptors ??= {};
+    _oneShotInterceptors.add(selector);
+  }
+
+  @override
+  Iterable<Selector> get oneShotInterceptors {
+    return _oneShotInterceptors ?? const [];
+  }
+
   @override
   String toString() {
     StringBuffer sb = new StringBuffer();
@@ -290,6 +315,7 @@
     add('genericInstantiations', genericInstantiations);
     add('nativeBehaviors', nativeBehaviors);
     add('nativeMethods', nativeMethods);
+    add('oneShotInterceptors', oneShotInterceptors);
 
     return sb.toString();
   }
@@ -348,6 +374,10 @@
     _worldImpact.registerSpecializedGetInterceptor(classes);
   }
 
+  void registerOneShotInterceptor(Selector selector) {
+    _worldImpact.registerOneShotInterceptor(selector);
+  }
+
   void registerUseInterceptor() {
     _worldImpact.registerUseInterceptor();
   }
@@ -388,6 +418,58 @@
   }
 }
 
+/// Interface for reading the code generation results for all [MemberEntity]s.
+abstract class CodegenResults {
+  GlobalTypeInferenceResults get globalTypeInferenceResults;
+  CodegenInputs get codegenInputs;
+  CodegenResult getCodegenResults(MemberEntity member);
+}
+
+/// Code generation results computed on-demand.
+///
+/// This is used in the non-modular codegen enqueuer driving code generation.
+class OnDemandCodegenResults extends CodegenResults {
+  @override
+  final GlobalTypeInferenceResults globalTypeInferenceResults;
+  @override
+  final CodegenInputs codegenInputs;
+  final SsaFunctionCompiler _functionCompiler;
+
+  OnDemandCodegenResults(this.globalTypeInferenceResults, this.codegenInputs,
+      this._functionCompiler);
+
+  @override
+  CodegenResult getCodegenResults(MemberEntity member) {
+    return _functionCompiler.compile(member);
+  }
+}
+
+/// Deserialized code generation results.
+///
+/// This is used for modular code generation.
+class DeserializedCodegenResults extends CodegenResults {
+  @override
+  final GlobalTypeInferenceResults globalTypeInferenceResults;
+  @override
+  final CodegenInputs codegenInputs;
+
+  final Map<MemberEntity, CodegenResult> _map;
+
+  DeserializedCodegenResults(
+      this.globalTypeInferenceResults, this.codegenInputs, this._map);
+
+  @override
+  CodegenResult getCodegenResults(MemberEntity member) {
+    CodegenResult result = _map[member];
+    if (result == null) {
+      failedAt(member,
+          "No codegen results from $member (${identityHashCode(member)}).");
+    }
+    return result;
+  }
+}
+
+/// The code generation result for a single [MemberEntity].
 class CodegenResult {
   static const String tag = 'codegen-result';
 
@@ -481,8 +563,8 @@
         case ModularNameKind.nameForGetInterceptor:
           name.value = namer.nameForGetInterceptor(name.set);
           break;
-        case ModularNameKind.nameForGetOneShotInterceptor:
-          name.value = namer.nameForGetOneShotInterceptor(name.data, name.set);
+        case ModularNameKind.nameForOneShotInterceptor:
+          name.value = namer.nameForOneShotInterceptor(name.data, name.set);
           break;
         case ModularNameKind.asName:
           name.value = namer.asName(name.data);
@@ -556,7 +638,7 @@
   globalPropertyNameForType,
   globalPropertyNameForMember,
   nameForGetInterceptor,
-  nameForGetOneShotInterceptor,
+  nameForOneShotInterceptor,
   asName,
 }
 
@@ -611,7 +693,7 @@
       case ModularNameKind.nameForGetInterceptor:
         set = source.readClasses().toSet();
         break;
-      case ModularNameKind.nameForGetOneShotInterceptor:
+      case ModularNameKind.nameForOneShotInterceptor:
         data = Selector.readFromDataSource(source);
         set = source.readClasses().toSet();
         break;
@@ -663,7 +745,7 @@
       case ModularNameKind.nameForGetInterceptor:
         sink.writeClasses(set);
         break;
-      case ModularNameKind.nameForGetOneShotInterceptor:
+      case ModularNameKind.nameForOneShotInterceptor:
         Selector selector = data;
         selector.writeToDataSink(sink);
         sink.writeClasses(set);
@@ -1014,7 +1096,10 @@
   }
 
   void _writeInfo(js.Node node) {
-    SourceInformation.writeToDataSink(sink, node.sourceInformation);
+    sink.writeCached<SourceInformation>(node.sourceInformation,
+        (SourceInformation sourceInformation) {
+      SourceInformation.writeToDataSink(sink, sourceInformation);
+    });
   }
 
   @override
@@ -2009,7 +2094,9 @@
         break;
     }
     SourceInformation sourceInformation =
-        SourceInformation.readFromDataSource(source);
+        source.readCached<SourceInformation>(() {
+      return SourceInformation.readFromDataSource(source);
+    });
     if (sourceInformation != null) {
       node = node.withSourceInformation(sourceInformation);
     }
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index a0b1e01..85057ab 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -11,6 +11,7 @@
 
 import '../compiler_new.dart' as api;
 import 'backend_strategy.dart';
+import 'common/codegen.dart';
 import 'common/names.dart' show Selectors, Uris;
 import 'common/tasks.dart' show CompilerTask, GenericTask, Measurer;
 import 'common/work.dart' show WorkItem;
@@ -171,7 +172,8 @@
       enqueuer,
       dumpInfoTask = new DumpInfoTask(this),
       selfTask,
-      serializationTask = new SerializationTask(this, measurer),
+      serializationTask = new SerializationTask(
+          options, reporter, provider, outputProvider, measurer),
     ];
 
     tasks.addAll(backend.tasks);
@@ -227,13 +229,14 @@
     reporter.log('Compiling $uri (${options.buildId})');
 
     if (options.readDataUri != null) {
-      GlobalTypeInferenceResults results =
-          await serializationTask.deserialize();
+      GlobalTypeInferenceResults globalTypeInferenceResults =
+          await serializationTask.deserializeGlobalTypeInference(
+              environment, abstractValueStrategy);
       if (options.debugGlobalInference) {
-        performGlobalTypeInference(results.closedWorld);
+        performGlobalTypeInference(globalTypeInferenceResults.closedWorld);
         return;
       }
-      emitJavaScriptCode(results);
+      await generateJavaScriptCode(globalTypeInferenceResults);
     } else {
       KernelResult result = await kernelLoader.load(uri);
       reporter.log("Kernel load complete");
@@ -263,6 +266,31 @@
     }
   }
 
+  void generateJavaScriptCode(
+      GlobalTypeInferenceResults globalTypeInferenceResults) async {
+    JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
+    backendStrategy.registerJClosedWorld(closedWorld);
+    if (options.showInternalProgress) reporter.log('Compiling...');
+    phase = PHASE_COMPILING;
+    CodegenInputs codegenInputs =
+        backend.onCodegenStart(globalTypeInferenceResults);
+
+    if (options.readCodegenUri != null) {
+      CodegenResults codegenResults =
+          await serializationTask.deserializeCodegen(
+              backendStrategy, globalTypeInferenceResults, codegenInputs);
+      runCodegenEnqueuer(codegenResults);
+    } else {
+      CodegenResults codegenResults = new OnDemandCodegenResults(
+          globalTypeInferenceResults, codegenInputs, backend.functionCompiler);
+      if (options.writeCodegenUri != null) {
+        serializationTask.serializeCodegen(backendStrategy, codegenResults);
+      } else {
+        runCodegenEnqueuer(codegenResults);
+      }
+    }
+  }
+
   /// Clear the internal compiler state to prevent memory leaks when invoking
   /// the compiler multiple times (e.g. in batch mode).
   // TODO(ahe): implement a better mechanism where we can store
@@ -355,16 +383,13 @@
         mainFunction, closedWorld, inferredDataBuilder);
   }
 
-  void emitJavaScriptCode(GlobalTypeInferenceResults globalInferenceResults) {
+  void runCodegenEnqueuer(CodegenResults codegenResults) {
+    GlobalTypeInferenceResults globalInferenceResults =
+        codegenResults.globalTypeInferenceResults;
     JClosedWorld closedWorld = globalInferenceResults.closedWorld;
-    backendStrategy.registerJClosedWorld(closedWorld);
-    if (options.showInternalProgress) reporter.log('Compiling...');
-    phase = PHASE_COMPILING;
-
-    CodegenInputs codegen = backend.onCodegenStart(globalInferenceResults);
-    backend.onCodegenEnqueuerStart(globalInferenceResults, codegen);
+    CodegenInputs codegenInputs = codegenResults.codegenInputs;
     Enqueuer codegenEnqueuer = enqueuer.createCodegenEnqueuer(
-        closedWorld, globalInferenceResults, codegen);
+        closedWorld, globalInferenceResults, codegenInputs, codegenResults);
     _codegenWorldBuilder = codegenEnqueuer.worldBuilder;
 
     FunctionEntity mainFunction = closedWorld.elementEnvironment.mainFunction;
@@ -376,14 +401,14 @@
       codegenWorldForTesting = codegenWorld;
     }
     int programSize = backend.assembleProgram(closedWorld,
-        globalInferenceResults.inferredData, codegen, codegenWorld);
+        globalInferenceResults.inferredData, codegenInputs, codegenWorld);
 
     if (options.dumpInfo) {
       dumpInfoTask.reportSize(programSize);
       dumpInfoTask.dumpInfo(closedWorld, globalInferenceResults);
     }
 
-    backend.onCodegenEnd(codegen);
+    backend.onCodegenEnd(codegenInputs);
 
     checkQueue(codegenEnqueuer);
   }
@@ -398,7 +423,8 @@
         GlobalTypeInferenceResults globalInferenceResults =
             performGlobalTypeInference(closedWorld);
         if (options.writeDataUri != null) {
-          serializationTask.serialize(globalInferenceResults);
+          serializationTask
+              .serializeGlobalTypeInference(globalInferenceResults);
           return;
         }
         if (options.testMode) {
@@ -416,7 +442,7 @@
               worldData);
         }
         if (stopAfterTypeInference) return;
-        emitJavaScriptCode(globalInferenceResults);
+        generateJavaScriptCode(globalInferenceResults);
       }
     });
   }
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index c10956f..67b4c3f 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -27,7 +27,8 @@
   TYPE,
   INTERCEPTOR,
   JS_NAME,
-  ABSTRACT_VALUE,
+  DUMMY_INTERCEPTOR,
+  UNREACHABLE,
   INSTANTIATION,
   DEFERRED_GLOBAL,
   NON_CONSTANT,
@@ -50,8 +51,10 @@
   R visitType(covariant TypeConstantValue constant, covariant A arg);
   R visitInterceptor(
       covariant InterceptorConstantValue constant, covariant A arg);
-  R visitAbstractValue(
-      covariant AbstractValueConstantValue constant, covariant A arg);
+  R visitDummyInterceptor(
+      covariant DummyInterceptorConstantValue constant, covariant A arg);
+  R visitUnreachable(
+      covariant UnreachableConstantValue constant, covariant A arg);
   R visitJsName(covariant JsNameConstantValue constant, covariant A arg);
   R visitDeferredGlobal(
       covariant DeferredGlobalConstantValue constant, covariant A arg);
@@ -850,19 +853,19 @@
   String toStructuredText() => 'JsNameConstant(${name})';
 }
 
-/// An abstract value as a constant value. This is only used during code
-/// generation.
-class AbstractValueConstantValue extends ConstantValue {
+/// A constant used as the dummy interceptor value for intercepted calls with
+/// a known non-interceptor target.
+class DummyInterceptorConstantValue extends ConstantValue {
   final AbstractValue abstractValue;
 
-  AbstractValueConstantValue(this.abstractValue);
+  DummyInterceptorConstantValue(this.abstractValue);
 
   @override
   bool get isDummy => true;
 
   @override
   bool operator ==(other) {
-    return other is AbstractValueConstantValue &&
+    return other is DummyInterceptorConstantValue &&
         abstractValue == other.abstractValue;
   }
 
@@ -874,20 +877,49 @@
 
   @override
   accept(ConstantValueVisitor visitor, arg) {
-    return visitor.visitAbstractValue(this, arg);
+    return visitor.visitDummyInterceptor(this, arg);
   }
 
   @override
   DartType getType(CommonElements types) => types.dynamicType;
 
   @override
-  ConstantValueKind get kind => ConstantValueKind.ABSTRACT_VALUE;
+  ConstantValueKind get kind => ConstantValueKind.DUMMY_INTERCEPTOR;
 
   @override
-  String toDartText() => 'abstract_value($abstractValue)';
+  String toDartText() => 'dummy_interceptor($abstractValue)';
 
   @override
-  String toStructuredText() => 'AbstractValueConstant($abstractValue)';
+  String toStructuredText() => 'DummyInterceptorConstant($abstractValue)';
+}
+
+// A constant with an empty type used in [HInstruction]s of an expression
+// in an unreachable context.
+class UnreachableConstantValue extends ConstantValue {
+  const UnreachableConstantValue();
+
+  @override
+  bool get isDummy => true;
+
+  @override
+  List<ConstantValue> getDependencies() => const <ConstantValue>[];
+
+  @override
+  accept(ConstantValueVisitor visitor, arg) {
+    return visitor.visitUnreachable(this, arg);
+  }
+
+  @override
+  DartType getType(CommonElements types) => types.dynamicType;
+
+  @override
+  ConstantValueKind get kind => ConstantValueKind.UNREACHABLE;
+
+  @override
+  String toDartText() => 'unreachable()';
+
+  @override
+  String toStructuredText() => 'UnreachableConstant()';
 }
 
 class ConstructedConstantValue extends ObjectConstantValue {
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index ebdc6a0..7348d20 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -110,6 +110,10 @@
   Uri sourceMapOut;
   Uri readDataUri;
   Uri writeDataUri;
+  Uri readCodegenUri;
+  Uri writeCodegenUri;
+  int codegenShard;
+  int codegenShards;
   List<String> bazelPaths;
   Uri packageConfig = null;
   Uri packageRoot = null;
@@ -129,7 +133,8 @@
   int optimizationLevel = null;
   Uri platformBinaries;
   Map<String, String> environment = new Map<String, String>();
-  CompilationStrategy compilationStrategy = CompilationStrategy.direct;
+  ReadStrategy readStrategy = ReadStrategy.fromDart;
+  WriteStrategy writeStrategy = WriteStrategy.toJs;
 
   void passThrough(String argument) => options.add(argument);
   void ignoreOption(String argument) {}
@@ -246,13 +251,12 @@
   }
 
   void setReadData(String argument) {
-    if (compilationStrategy == CompilationStrategy.toData) {
-      fail("Cannot read and write serialized simultaneously.");
-    }
     if (argument != Flags.readData) {
       readDataUri = nativeToUri(extractPath(argument, isDirectory: false));
     }
-    compilationStrategy = CompilationStrategy.fromData;
+    if (readStrategy != ReadStrategy.fromCodegen) {
+      readStrategy = ReadStrategy.fromData;
+    }
   }
 
   void setDillDependencies(String argument) {
@@ -263,17 +267,58 @@
   }
 
   void setCfeOnly(String argument) {
-    compilationStrategy = CompilationStrategy.toKernel;
+    if (writeStrategy == WriteStrategy.toData) {
+      fail("Cannot use ${Flags.cfeOnly} "
+          "and write serialized data simultaneously.");
+    }
+    if (writeStrategy == WriteStrategy.toCodegen) {
+      fail("Cannot use ${Flags.cfeOnly} "
+          "and write serialized codegen simultaneously.");
+    }
+    writeStrategy = WriteStrategy.toKernel;
+  }
+
+  void setReadCodegen(String argument) {
+    if (argument != Flags.readCodegen) {
+      readCodegenUri = nativeToUri(extractPath(argument, isDirectory: false));
+    }
+    readStrategy = ReadStrategy.fromCodegen;
   }
 
   void setWriteData(String argument) {
-    if (compilationStrategy == CompilationStrategy.fromData) {
-      fail("Cannot read and write serialized simultaneously.");
+    if (writeStrategy == WriteStrategy.toKernel) {
+      fail("Cannot use ${Flags.cfeOnly} "
+          "and write serialized data simultaneously.");
+    }
+    if (writeStrategy == WriteStrategy.toCodegen) {
+      fail("Cannot write serialized data and codegen simultaneously.");
     }
     if (argument != Flags.writeData) {
       writeDataUri = nativeToUri(extractPath(argument, isDirectory: false));
     }
-    compilationStrategy = CompilationStrategy.toData;
+    writeStrategy = WriteStrategy.toData;
+  }
+
+  void setWriteCodegen(String argument) {
+    if (writeStrategy == WriteStrategy.toKernel) {
+      fail("Cannot use ${Flags.cfeOnly} "
+          "and write serialized codegen simultaneously.");
+    }
+    if (writeStrategy == WriteStrategy.toData) {
+      fail("Cannot write serialized data and codegen data simultaneously.");
+    }
+    if (argument != Flags.writeCodegen) {
+      writeCodegenUri = nativeToUri(extractPath(argument, isDirectory: false));
+    }
+    writeStrategy = WriteStrategy.toCodegen;
+  }
+
+  void setCodegenShard(String argument) {
+    codegenShard = int.parse(extractParameter(argument));
+  }
+
+  void setCodegenShards(String argument) {
+    codegenShards = int.parse(extractParameter(argument));
   }
 
   void setDumpInfo(String argument) {
@@ -349,6 +394,12 @@
     new OptionHandler('${Flags.dillDependencies}=.+', setDillDependencies),
     new OptionHandler('${Flags.readData}|${Flags.readData}=.+', setReadData),
     new OptionHandler('${Flags.writeData}|${Flags.writeData}=.+', setWriteData),
+    new OptionHandler(
+        '${Flags.readCodegen}|${Flags.readCodegen}=.+', setReadCodegen),
+    new OptionHandler(
+        '${Flags.writeCodegen}|${Flags.writeCodegen}=.+', setWriteCodegen),
+    new OptionHandler('${Flags.codegenShard}=.+', setCodegenShard),
+    new OptionHandler('${Flags.codegenShards}=.+', setCodegenShards),
     new OptionHandler(Flags.cfeOnly, setCfeOnly),
     new OptionHandler(Flags.debugGlobalInference, passThrough),
     new OptionHandler('--out=.+|-o.*', setOutput, multipleArguments: true),
@@ -511,28 +562,86 @@
 
   String scriptName = arguments[0];
 
-  switch (compilationStrategy) {
-    case CompilationStrategy.direct:
+  switch (writeStrategy) {
+    case WriteStrategy.toJs:
       out ??= currentDirectory.resolve('out.js');
       break;
-    case CompilationStrategy.toKernel:
+    case WriteStrategy.toKernel:
       out ??= currentDirectory.resolve('out.dill');
       options.add(Flags.cfeOnly);
+      if (readStrategy == ReadStrategy.fromData) {
+        fail("Cannot use ${Flags.cfeOnly} "
+            "and read serialized data simultaneously.");
+      } else if (readStrategy == ReadStrategy.fromCodegen) {
+        fail("Cannot use ${Flags.cfeOnly} "
+            "and read serialized codegen simultaneously.");
+      }
       break;
-    case CompilationStrategy.toData:
+    case WriteStrategy.toData:
       out ??= currentDirectory.resolve('out.dill');
       writeDataUri ??= currentDirectory.resolve('$out.data');
       options.add('${Flags.writeData}=${writeDataUri}');
+      if (readStrategy == ReadStrategy.fromData) {
+        fail("Cannot read and write serialized data simultaneously.");
+      } else if (readStrategy == ReadStrategy.fromCodegen) {
+        fail("Cannot read serialized codegen and "
+            "write serialized data simultaneously.");
+      }
       break;
-    case CompilationStrategy.fromData:
-      out ??= currentDirectory.resolve('out.js');
+    case WriteStrategy.toCodegen:
+      // TODO(johnniwinther): Avoid the need for an [out] value in this case or
+      // use [out] to pass [writeCodegenUri].
+      out ??= currentDirectory.resolve('out');
+      writeCodegenUri ??= currentDirectory.resolve('$out.code');
+      options.add('${Flags.writeCodegen}=${writeCodegenUri}');
+      if (readStrategy == ReadStrategy.fromCodegen) {
+        fail("Cannot read and write serialized codegen simultaneously.");
+      }
+      if (readStrategy != ReadStrategy.fromData) {
+        fail("Can only write serialized codegen from serialized data.");
+      }
+      if (codegenShards == null) {
+        fail("Cannot write serialized codegen without setting "
+            "${Flags.codegenShards}.");
+      } else if (codegenShards <= 0) {
+        fail("${Flags.codegenShards} must be a positive integer.");
+      }
+      if (codegenShard == null) {
+        fail("Cannot write serialized codegen without setting "
+            "${Flags.codegenShard}.");
+      } else if (codegenShard < 0 || codegenShard >= codegenShards) {
+        fail("${Flags.codegenShard} must be between 0 and "
+            "${Flags.codegenShards}.");
+      }
+      options.add('${Flags.codegenShard}=$codegenShard');
+      options.add('${Flags.codegenShards}=$codegenShards');
+      break;
+  }
+  switch (readStrategy) {
+    case ReadStrategy.fromDart:
+      break;
+    case ReadStrategy.fromData:
       readDataUri ??= currentDirectory.resolve('$scriptName.data');
       options.add('${Flags.readData}=${readDataUri}');
       break;
+    case ReadStrategy.fromCodegen:
+      readDataUri ??= currentDirectory.resolve('$scriptName.data');
+      options.add('${Flags.readData}=${readDataUri}');
+      readCodegenUri ??= currentDirectory.resolve('$scriptName.code');
+      options.add('${Flags.readCodegen}=${readCodegenUri}');
+      if (codegenShards == null) {
+        fail("Cannot write serialized codegen without setting "
+            "${Flags.codegenShards}.");
+      } else if (codegenShards <= 0) {
+        fail("${Flags.codegenShards} must be a positive integer.");
+      }
+      options.add('${Flags.codegenShards}=$codegenShards');
   }
   options.add('--out=$out');
-  sourceMapOut = Uri.parse('$out.map');
-  options.add('--source-map=${sourceMapOut}');
+  if (writeStrategy == WriteStrategy.toJs) {
+    sourceMapOut = Uri.parse('$out.map');
+    options.add('--source-map=${sourceMapOut}');
+  }
 
   RandomAccessFileOutputProvider outputProvider =
       new RandomAccessFileOutputProvider(out, sourceMapOut,
@@ -544,86 +653,98 @@
     }
     writeString(
         Uri.parse('$out.deps'), getDepsOutput(inputProvider.getSourceUris()));
-    switch (compilationStrategy) {
-      case CompilationStrategy.direct:
-        int dartCharactersRead = inputProvider.dartCharactersRead;
-        int jsCharactersWritten =
-            outputProvider.totalCharactersWrittenJavaScript;
-        int jsCharactersPrimary = outputProvider.totalCharactersWrittenPrimary;
-        print('Compiled '
-            '${_formatCharacterCount(dartCharactersRead)} characters Dart to '
-            '${_formatCharacterCount(jsCharactersWritten)} characters '
-            'JavaScript in '
-            '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
 
-        diagnosticHandler
-            .info('${_formatCharacterCount(jsCharactersPrimary)} characters '
-                'JavaScript in '
-                '${relativize(currentDirectory, out, Platform.isWindows)}');
-        if (outputSpecified || diagnosticHandler.verbose) {
-          String input = uriPathToNative(scriptName);
-          String output = relativize(currentDirectory, out, Platform.isWindows);
-          print('Dart file ($input) compiled to JavaScript: $output');
-          if (diagnosticHandler.verbose) {
-            var files = outputProvider.allOutputFiles;
-            int jsCount = files.where((f) => f.endsWith('.js')).length;
-            print('Emitted file $jsCount JavaScript files.');
-          }
-        }
+    String input = uriPathToNative(scriptName);
+    int inputSize;
+    String processName;
+    String inputName;
+
+    int outputSize;
+    int primaryOutputSize;
+    String outputName;
+
+    String summary;
+    switch (readStrategy) {
+      case ReadStrategy.fromDart:
+        inputName = 'characters Dart';
+        inputSize = inputProvider.dartCharactersRead;
+        summary = 'Dart file $input ';
         break;
-      case CompilationStrategy.toKernel:
-        int dartCharactersRead = inputProvider.dartCharactersRead;
-        int dataBytesWritten = outputProvider.totalDataWritten;
-        print('Compiled '
-            '${_formatCharacterCount(dartCharactersRead)} characters Dart to '
-            '${_formatCharacterCount(dataBytesWritten)} kernel bytes in '
-            '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
-        String input = uriPathToNative(scriptName);
-        String dillOutput =
-            relativize(currentDirectory, out, Platform.isWindows);
-        print('Dart file ($input) compiled to ${dillOutput}.');
+      case ReadStrategy.fromData:
+        inputName = 'bytes data';
+        inputSize = inputProvider.dartCharactersRead;
+        String dataInput =
+            relativize(currentDirectory, readDataUri, Platform.isWindows);
+        summary = 'Data files $input and $dataInput ';
         break;
-      case CompilationStrategy.toData:
-        int dartCharactersRead = inputProvider.dartCharactersRead;
-        int dataBytesWritten = outputProvider.totalDataWritten;
-        print('Serialized '
-            '${_formatCharacterCount(dartCharactersRead)} characters Dart to '
-            '${_formatCharacterCount(dataBytesWritten)} bytes data in '
-            '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
-        String input = uriPathToNative(scriptName);
-        String dillOutput =
-            relativize(currentDirectory, out, Platform.isWindows);
+      case ReadStrategy.fromCodegen:
+        inputName = 'bytes data';
+        inputSize = inputProvider.dartCharactersRead;
+        String dataInput =
+            relativize(currentDirectory, readDataUri, Platform.isWindows);
+        String codeInput =
+            relativize(currentDirectory, readCodegenUri, Platform.isWindows);
+        summary = 'Data files $input, $dataInput and '
+            '${codeInput}[0-${codegenShards - 1}] ';
+        break;
+    }
+
+    switch (writeStrategy) {
+      case WriteStrategy.toJs:
+        processName = 'Compiled';
+        outputName = 'characters JavaScript';
+        outputSize = outputProvider.totalCharactersWrittenJavaScript;
+        primaryOutputSize = outputProvider.totalCharactersWrittenPrimary;
+        String output = relativize(currentDirectory, out, Platform.isWindows);
+        summary += 'compiled to JavaScript: ${output}';
+        break;
+      case WriteStrategy.toKernel:
+        processName = 'Compiled';
+        outputName = 'kernel bytes';
+        outputSize = outputProvider.totalDataWritten;
+        String output = relativize(currentDirectory, out, Platform.isWindows);
+        summary += 'compiled to dill: ${output}.';
+        break;
+      case WriteStrategy.toData:
+        processName = 'Serialized';
+        outputName = 'bytes data';
+        outputSize = outputProvider.totalDataWritten;
+        String output = relativize(currentDirectory, out, Platform.isWindows);
         String dataOutput =
             relativize(currentDirectory, writeDataUri, Platform.isWindows);
-        print('Dart file ($input) serialized to '
-            '${dillOutput} and ${dataOutput}.');
+        summary += 'serialized to dill and data: ${output} and ${dataOutput}.';
         break;
-      case CompilationStrategy.fromData:
-        int dataCharactersRead = inputProvider.dartCharactersRead;
-        int jsCharactersWritten =
-            outputProvider.totalCharactersWrittenJavaScript;
-        int jsCharactersPrimary = outputProvider.totalCharactersWrittenPrimary;
-        print('Compiled '
-            '${_formatCharacterCount(dataCharactersRead)} bytes data to '
-            '${_formatCharacterCount(jsCharactersWritten)} characters '
-            'JavaScript in '
-            '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
+      case WriteStrategy.toCodegen:
+        processName = 'Serialized';
+        outputName = 'bytes data';
+        outputSize = outputProvider.totalDataWritten;
+        String codeOutput =
+            relativize(currentDirectory, writeCodegenUri, Platform.isWindows);
+        summary += 'serialized to codegen data: '
+            '${codeOutput}${codegenShard}.';
+        break;
+    }
 
-        diagnosticHandler
-            .info('${_formatCharacterCount(jsCharactersPrimary)} characters '
-                'JavaScript in '
-                '${relativize(currentDirectory, out, Platform.isWindows)}');
-        if (outputSpecified || diagnosticHandler.verbose) {
-          String input = uriPathToNative(scriptName);
-          String output = relativize(currentDirectory, out, Platform.isWindows);
-          print('Dart file ($input) compiled to JavaScript: $output');
-          if (diagnosticHandler.verbose) {
-            var files = outputProvider.allOutputFiles;
-            int jsCount = files.where((f) => f.endsWith('.js')).length;
-            print('Emitted file $jsCount JavaScript files.');
-          }
+    print('$processName '
+        '${_formatCharacterCount(inputSize)} $inputName to '
+        '${_formatCharacterCount(outputSize)} $outputName in '
+        '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
+    if (primaryOutputSize != null) {
+      diagnosticHandler
+          .info('${_formatCharacterCount(primaryOutputSize)} $outputName '
+              'in ${relativize(currentDirectory, out, Platform.isWindows)}');
+    }
+    if (writeStrategy == WriteStrategy.toJs) {
+      if (outputSpecified || diagnosticHandler.verbose) {
+        print(summary);
+        if (diagnosticHandler.verbose) {
+          var files = outputProvider.allOutputFiles;
+          int jsCount = files.where((f) => f.endsWith('.js')).length;
+          print('Emitted file $jsCount JavaScript files.');
         }
-        break;
+      }
+    } else {
+      print(summary);
     }
 
     return result;
@@ -1043,4 +1164,5 @@
   });
 }
 
-enum CompilationStrategy { direct, toKernel, toData, fromData }
+enum ReadStrategy { fromDart, fromData, fromCodegen }
+enum WriteStrategy { toKernel, toData, toCodegen, toJs }
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 5c32df6..118d4ed 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -1218,6 +1218,23 @@
   }
 }
 
+/// Interface for updating an [OutputUnitData] object with data for late
+/// members, that is, members created on demand during code generation.
+class LateOutputUnitDataBuilder {
+  final OutputUnitData _outputUnitData;
+
+  LateOutputUnitDataBuilder(this._outputUnitData);
+
+  /// Registers [newEntity] to be emitted in the same output unit as
+  /// [existingEntity];
+  void registerColocatedMembers(
+      MemberEntity existingEntity, MemberEntity newEntity) {
+    assert(_outputUnitData._memberToUnit[newEntity] == null);
+    _outputUnitData._memberToUnit[newEntity] =
+        _outputUnitData.outputUnitForMember(existingEntity);
+  }
+}
+
 /// Results of the deferred loading algorithm.
 ///
 /// Provides information about the output unit associated with entities and
@@ -1393,24 +1410,28 @@
   }
 
   /// Returns the [OutputUnit] where [cls] belongs.
-  OutputUnit outputUnitForClass(ClassEntity cls) {
+  // TODO(johnniwinther): Remove the need for [allowNull]. Dump-info currently
+  // needs it.
+  OutputUnit outputUnitForClass(ClassEntity cls, {bool allowNull: false}) {
     if (!isProgramSplit) return mainOutputUnit;
     OutputUnit unit = _classToUnit[cls];
+    assert(allowNull || unit != null, 'No output unit for class $cls');
     return unit ?? mainOutputUnit;
   }
 
+  OutputUnit outputUnitForClassForTesting(ClassEntity cls) => _classToUnit[cls];
+
   /// Returns the [OutputUnit] where [member] belongs.
   OutputUnit outputUnitForMember(MemberEntity member) {
     if (!isProgramSplit) return mainOutputUnit;
     OutputUnit unit = _memberToUnit[member];
-    if (unit != null) return unit;
-    if (member.isInstanceMember) {
-      return outputUnitForClass(member.enclosingClass);
-    }
-
-    return mainOutputUnit;
+    assert(unit != null, 'No output unit for member $member');
+    return unit ?? mainOutputUnit;
   }
 
+  OutputUnit outputUnitForMemberForTesting(MemberEntity member) =>
+      _memberToUnit[member];
+
   /// Direct access to the output-unit to constants map used for testing.
   Iterable<ConstantValue> get constantsForTesting => _constantToUnit.keys;
 
@@ -1420,6 +1441,9 @@
     return _constantToUnit[constant];
   }
 
+  OutputUnit outputUnitForConstantForTesting(ConstantValue constant) =>
+      _constantToUnit[constant];
+
   /// Indicates whether [element] is deferred.
   bool isDeferredClass(ClassEntity element) {
     return outputUnitForClass(element) != mainOutputUnit;
@@ -1456,22 +1480,14 @@
 
   /// Registers that a constant is used in the same deferred output unit as
   /// [field].
-  void registerConstantDeferredUse(
-      DeferredGlobalConstantValue constant, OutputUnit unit) {
+  void registerConstantDeferredUse(DeferredGlobalConstantValue constant) {
     if (!isProgramSplit) return;
+    OutputUnit unit = constant.unit;
     assert(
         _constantToUnit[constant] == null || _constantToUnit[constant] == unit);
     _constantToUnit[constant] = unit;
   }
 
-  /// Registers [newEntity] to be emitted in the same output unit as
-  /// [existingEntity];
-  void registerColocatedMembers(
-      MemberEntity existingEntity, MemberEntity newEntity) {
-    assert(_memberToUnit[newEntity] == null);
-    _memberToUnit[newEntity] = outputUnitForMember(existingEntity);
-  }
-
   /// Returns the unique name for the given deferred [import].
   String getImportDeferName(Spannable node, ImportEntity import) {
     String name = _importDeferName[import];
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index eec68ab..454d157 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -365,7 +365,7 @@
 
   OutputUnitInfo _unitInfoForClass(ClassEntity entity) {
     return _infoFromOutputUnit(
-        closedWorld.outputUnitData.outputUnitForClass(entity));
+        closedWorld.outputUnitData.outputUnitForClass(entity, allowNull: true));
   }
 
   OutputUnitInfo _unitInfoForConstant(ConstantValue constant) {
diff --git a/pkg/compiler/lib/src/elements/indexed.dart b/pkg/compiler/lib/src/elements/indexed.dart
index e83b8a0..6a6afc4 100644
--- a/pkg/compiler/lib/src/elements/indexed.dart
+++ b/pkg/compiler/lib/src/elements/indexed.dart
@@ -56,6 +56,8 @@
 
 /// Base implementation for an index based map of entities of type [E].
 abstract class EntityMapBase<E extends _Indexed> {
+  bool _closed = false;
+
   int _size = 0;
   List<E> _list = <E>[];
 
@@ -67,6 +69,14 @@
 
   /// Returns the number (null and non-null) entities in the map.
   int get length => _list.length;
+
+  /// Closes the entity map, prohibiting further registration.
+  ///
+  /// This is used to ensure that no new entities are added while serializing
+  /// modular code generation data.
+  void close() {
+    _closed = true;
+  }
 }
 
 /// Index based map of entities of type [E].
@@ -76,6 +86,8 @@
   /// The index of [entity] is set to match its index in the entity list in this
   /// map.
   E0 register<E0 extends E>(E0 entity) {
+    assert(
+        !_closed, "Trying to register $entity @ ${_list.length} when closed.");
     assert(entity != null);
     assert(entity._index == null);
     entity._index = _list.length;
@@ -134,6 +146,8 @@
   /// The index of [entity] is set to match its index in the entity and data
   /// lists in this map.
   E0 register<E0 extends E, D0 extends D>(E0 entity, D0 data) {
+    assert(
+        !_closed, "Trying to register $entity @ ${_list.length} when closed.");
     assert(entity != null);
     assert(entity._index == null);
     assert(
@@ -199,6 +213,8 @@
   /// environment lists in this map.
   E0 register<E0 extends E, D0 extends D, V0 extends V>(
       E0 entity, D0 data, V0 env) {
+    assert(
+        !_closed, "Trying to register $entity @ ${_list.length} when closed.");
     assert(entity != null);
     assert(entity._index == null);
     assert(
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 5439e6e..81ca07d 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -6,6 +6,7 @@
 
 import 'dart:collection' show Queue;
 
+import 'common/codegen.dart';
 import 'common/tasks.dart' show CompilerTask;
 import 'common/work.dart' show WorkItem;
 import 'common.dart';
@@ -68,9 +69,10 @@
   Enqueuer createCodegenEnqueuer(
       JClosedWorld closedWorld,
       GlobalTypeInferenceResults globalInferenceResults,
-      CodegenInputs codegen) {
-    Enqueuer enqueuer = compiler.backend.createCodegenEnqueuer(
-        this, compiler, closedWorld, globalInferenceResults, codegen)
+      CodegenInputs codegenInputs,
+      CodegenResults codegenResults) {
+    Enqueuer enqueuer = compiler.backend.createCodegenEnqueuer(this, compiler,
+        closedWorld, globalInferenceResults, codegenInputs, codegenResults)
       ..onEmptyForTesting = compiler.onCodegenQueueEmptyForTesting;
     if (retainDataForTesting) {
       codegenEnqueuerForTesting = enqueuer;
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/constants.dart b/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
index a453382..0994564 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
@@ -48,12 +48,18 @@
   }
 
   @override
-  TypeMask visitAbstractValue(
-      AbstractValueConstantValue constant, JClosedWorld closedWorld) {
+  TypeMask visitDummyInterceptor(
+      DummyInterceptorConstantValue constant, JClosedWorld closedWorld) {
     return constant.abstractValue;
   }
 
   @override
+  TypeMask visitUnreachable(
+      UnreachableConstantValue constant, JClosedWorld closedWorld) {
+    return closedWorld.abstractValueDomain.emptyType;
+  }
+
+  @override
   TypeMask visitJsName(JsNameConstantValue constant, JClosedWorld closedWorld) {
     return closedWorld.abstractValueDomain.stringType;
   }
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index a92ab7e..cb1c2a4 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -12,6 +12,7 @@
 import '../js/js_debug.dart';
 import '../js/js_source_mapping.dart';
 import '../serialization/serialization.dart';
+import '../util/util.dart';
 import 'code_output.dart' show BufferedCodeOutput;
 import 'source_information.dart';
 
@@ -34,8 +35,10 @@
 
   factory PositionSourceInformation.readFromDataSource(DataSource source) {
     source.begin(tag);
-    SourceLocation startPosition = SourceLocation.readFromDataSource(source);
-    SourceLocation innerPosition = SourceLocation.readFromDataSource(source);
+    SourceLocation startPosition = source.readCached<SourceLocation>(
+        () => SourceLocation.readFromDataSource(source));
+    SourceLocation innerPosition = source.readCached<SourceLocation>(
+        () => SourceLocation.readFromDataSource(source));
     List<FrameContext> inliningContext = source.readList(
         () => FrameContext.readFromDataSource(source),
         emptyAsNull: true);
@@ -46,8 +49,14 @@
 
   void writeToDataSinkInternal(DataSink sink) {
     sink.begin(tag);
-    SourceLocation.writeToDataSink(sink, startPosition);
-    SourceLocation.writeToDataSink(sink, innerPosition);
+    sink.writeCached(
+        startPosition,
+        (SourceLocation sourceLocation) =>
+            SourceLocation.writeToDataSink(sink, sourceLocation));
+    sink.writeCached(
+        innerPosition,
+        (SourceLocation sourceLocation) =>
+            SourceLocation.writeToDataSink(sink, sourceLocation));
     sink.writeList(inliningContext,
         (FrameContext context) => context.writeToDataSink(sink),
         allowNull: true);
@@ -77,16 +86,17 @@
 
   @override
   int get hashCode {
-    return 0x7FFFFFFF &
-        (startPosition.hashCode * 17 + innerPosition.hashCode * 19);
+    return Hashing.listHash(
+        inliningContext, Hashing.objectsHash(startPosition, innerPosition));
   }
 
   @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
-    if (other is! PositionSourceInformation) return false;
-    return startPosition == other.startPosition &&
-        innerPosition == other.innerPosition;
+    return other is PositionSourceInformation &&
+        startPosition == other.startPosition &&
+        innerPosition == other.innerPosition &&
+        equalElements(inliningContext, other.inliningContext);
   }
 
   /// Create a textual representation of the source information using [uriText]
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index bc8f6e7..0034fb5 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -84,8 +84,8 @@
 
   factory FrameContext.readFromDataSource(DataSource source) {
     source.begin(tag);
-    SourceInformation callInformation =
-        SourceInformation.readFromDataSource(source);
+    SourceInformation callInformation = source.readCached<SourceInformation>(
+        () => SourceInformation.readFromDataSource(source));
     String inlinedMethodName = source.readString();
     source.end(tag);
     return new FrameContext(callInformation, inlinedMethodName);
@@ -93,7 +93,10 @@
 
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
-    SourceInformation.writeToDataSink(sink, callInformation);
+    sink.writeCached<SourceInformation>(
+        callInformation,
+        (SourceInformation sourceInformation) =>
+            SourceInformation.writeToDataSink(sink, sourceInformation));
     sink.writeString(inlinedMethodName);
     sink.end(tag);
   }
@@ -317,8 +320,8 @@
   @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
-    if (other is! SourceLocation) return false;
-    return sourceUri == other.sourceUri &&
+    return other is SourceLocation &&
+        sourceUri == other.sourceUri &&
         offset == other.offset &&
         sourceName == other.sourceName;
   }
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index b3768c4..01cad9d 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -1385,8 +1385,9 @@
           if (clause is js.Case) {
             return new js.Case(
                 clause.expression, translateToBlock(clause.body));
-          } else if (clause is js.Default) {
-            return new js.Default(translateToBlock(clause.body));
+          } else {
+            return new js.Default(
+                translateToBlock((clause as js.Default).body));
           }
         }).toList();
         addStatement(new js.Switch(key, cases));
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 79a1ada..d187523 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -30,11 +30,9 @@
 import '../universe/class_hierarchy.dart'
     show ClassHierarchyBuilder, ClassQueries;
 import '../universe/codegen_world_builder.dart';
-import '../universe/selector.dart' show Selector;
 import '../universe/world_builder.dart';
 import '../universe/world_impact.dart'
     show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor;
-import '../util/util.dart';
 import '../world.dart' show JClosedWorld;
 import 'field_analysis.dart';
 import 'annotations.dart';
@@ -84,11 +82,12 @@
   final Map<FunctionEntity, int> _cachedDecisions =
       new Map<FunctionEntity, int>();
 
+  final Set<FunctionEntity> _noInlineFunctions = new Set<FunctionEntity>();
   final Set<FunctionEntity> _tryInlineFunctions = new Set<FunctionEntity>();
 
   FunctionInlineCache(AnnotationsData annotationsData) {
     annotationsData.forEachNoInline((FunctionEntity function) {
-      markAsNonInlinable(function);
+      markAsNoInline(function);
     });
     annotationsData.forEachTryInline((FunctionEntity function) {
       markAsTryInline(function);
@@ -174,7 +173,7 @@
         case _mustNotInline:
           throw failedAt(
               element,
-              "Can't mark a function as non-inlinable and inlinable at the "
+              "Can't mark $element as non-inlinable and inlinable at the "
               "same time.");
 
         case _unknown:
@@ -200,7 +199,7 @@
         case _canInlineInLoopMustNotOutside:
           throw failedAt(
               element,
-              "Can't mark a function as non-inlinable and inlinable at the "
+              "Can't mark $element as non-inlinable and inlinable at the "
               "same time.");
 
         case _unknown:
@@ -230,7 +229,7 @@
         case _canInline:
           throw failedAt(
               element,
-              "Can't mark a function as non-inlinable and inlinable at the "
+              "Can't mark $element as non-inlinable and inlinable at the "
               "same time.");
 
         case _mayInlineInLoopMustNotOutside:
@@ -247,7 +246,7 @@
         case _canInline:
           throw failedAt(
               element,
-              "Can't mark a function as non-inlinable and inlinable at the "
+              "Can't mark $element as non-inlinable and inlinable at the "
               "same time.");
 
         case _unknown:
@@ -272,6 +271,16 @@
     }
   }
 
+  void markAsNoInline(FunctionEntity element) {
+    assert(checkFunction(element), failedAt(element));
+    _noInlineFunctions.add(element);
+  }
+
+  bool markedAsNoInline(FunctionEntity element) {
+    assert(checkFunction(element), failedAt(element));
+    return _noInlineFunctions.contains(element);
+  }
+
   void markAsTryInline(FunctionEntity element) {
     assert(checkFunction(element), failedAt(element));
     _tryInlineFunctions.add(element);
@@ -537,7 +546,14 @@
       Compiler compiler,
       JClosedWorld closedWorld,
       GlobalTypeInferenceResults globalInferenceResults,
-      CodegenInputs codegen) {
+      CodegenInputs codegen,
+      CodegenResults codegenResults) {
+    OneShotInterceptorData oneShotInterceptorData = new OneShotInterceptorData(
+        closedWorld.interceptorData,
+        closedWorld.commonElements,
+        closedWorld.nativeData);
+    _onCodegenEnqueuerStart(
+        globalInferenceResults, codegen, oneShotInterceptorData);
     ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
     CommonElements commonElements = closedWorld.commonElements;
     BackendImpacts impacts = new BackendImpacts(commonElements);
@@ -549,8 +565,10 @@
         compiler.backendStrategy.createCodegenWorldBuilder(
             closedWorld.nativeData,
             closedWorld,
-            compiler.abstractValueStrategy.createSelectorStrategy()),
-        compiler.backendStrategy.createCodegenWorkItemBuilder(closedWorld),
+            compiler.abstractValueStrategy.createSelectorStrategy(),
+            oneShotInterceptorData),
+        compiler.backendStrategy
+            .createCodegenWorkItemBuilder(closedWorld, codegenResults),
         new CodegenEnqueuerListener(
             elementEnvironment,
             commonElements,
@@ -563,10 +581,14 @@
 
   Map<MemberEntity, WorldImpact> codegenImpactsForTesting;
 
-  WorldImpact generateCode(WorkItem work, JClosedWorld closedWorld,
-      EntityLookup entityLookup, ComponentLookup componentLookup) {
+  WorldImpact generateCode(
+      WorkItem work,
+      JClosedWorld closedWorld,
+      CodegenResults codegenResults,
+      EntityLookup entityLookup,
+      ComponentLookup componentLookup) {
     MemberEntity member = work.element;
-    CodegenResult result = functionCompiler.compile(member);
+    CodegenResult result = codegenResults.getCodegenResults(member);
     if (compiler.options.testMode) {
       bool useDataKinds = true;
       List<Object> data = [];
@@ -594,7 +616,6 @@
         _codegenImpactTransformer.transformCodegenImpact(result.impact);
     compiler.dumpInfoTask.registerImpact(member, worldImpact);
     result.applyModularState(_namer, emitterTask.emitter);
-    //print('$member:$result');
     return worldImpact;
   }
 
@@ -613,9 +634,9 @@
 
   /// Generates the output and returns the total size of the generated code.
   int assembleProgram(JClosedWorld closedWorld, InferredData inferredData,
-      CodegenInputs codegen, CodegenWorld codegenWorld) {
+      CodegenInputs codegenInputs, CodegenWorld codegenWorld) {
     int programSize = emitterTask.assembleProgram(
-        _namer, closedWorld, inferredData, codegen, codegenWorld);
+        _namer, closedWorld, inferredData, codegenInputs, codegenWorld);
     closedWorld.noSuchMethodData.emitDiagnostic(reporter);
     return programSize;
   }
@@ -646,10 +667,6 @@
         ? const MinifiedFixedNames()
         : const FixedNames();
 
-    OneShotInterceptorData oneShotInterceptorData = new OneShotInterceptorData(
-        closedWorld.interceptorData,
-        closedWorld.commonElements,
-        closedWorld.nativeData);
     Tracer tracer = new Tracer(closedWorld, compiler.outputProvider);
     RuntimeTypesEncoder rtiEncoder = new RuntimeTypesEncoderImpl(
         rtiTags,
@@ -668,7 +685,7 @@
       rtiSubstitutions = runtimeTypesImpl;
     }
 
-    CodegenInputs codegen = new CodegenInputsImpl(oneShotInterceptorData,
+    CodegenInputs codegen = new CodegenInputsImpl(
         rtiSubstitutions, rtiEncoder, tracer, rtiTags, fixedNames);
 
     functionCompiler.initialize(globalTypeInferenceResults, codegen);
@@ -676,9 +693,10 @@
   }
 
   /// Called before the compiler starts running the codegen enqueuer.
-  void onCodegenEnqueuerStart(
+  void _onCodegenEnqueuerStart(
       GlobalTypeInferenceResults globalTypeInferenceResults,
-      CodegenInputs codegen) {
+      CodegenInputs codegen,
+      OneShotInterceptorData oneShotInterceptorData) {
     JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
     RuntimeTypeTags rtiTags = codegen.rtiTags;
     FixedNames fixedNames = codegen.fixedNames;
@@ -702,6 +720,7 @@
 
     _codegenImpactTransformer = new CodegenImpactTransformer(
         compiler.options,
+        closedWorld,
         closedWorld.elementEnvironment,
         closedWorld.commonElements,
         impacts,
@@ -710,7 +729,7 @@
         closedWorld.rtiNeed,
         nativeCodegenEnqueuer,
         _namer,
-        codegen.oneShotInterceptorData,
+        oneShotInterceptorData,
         rtiChecksBuilder,
         emitterTask.nativeEmitter);
   }
@@ -771,38 +790,11 @@
   }
 }
 
-class SuperMemberData {
-  /// A set of member that are called from subclasses via `super`.
-  final Set<MemberEntity> _aliasedSuperMembers = new Setlet<MemberEntity>();
-
-  /// Record that [member] is called from a subclass via `super`.
-  bool maybeRegisterAliasedSuperMember(MemberEntity member, Selector selector) {
-    if (!canUseAliasedSuperMember(member, selector)) {
-      // Invoking a super getter isn't supported, this would require changes to
-      // compact field descriptors in the emitter.
-      return false;
-    }
-    _aliasedSuperMembers.add(member);
-    return true;
-  }
-
-  bool canUseAliasedSuperMember(MemberEntity member, Selector selector) {
-    return !selector.isGetter;
-  }
-
-  /// Returns `true` if [member] is called from a subclass via `super`.
-  bool isAliasedSuperMember(MemberEntity member) {
-    return _aliasedSuperMembers.contains(member);
-  }
-}
-
 /// Interface for resources only used during code generation.
 abstract class CodegenInputs {
   CheckedModeHelpers get checkedModeHelpers;
-  OneShotInterceptorData get oneShotInterceptorData;
   RuntimeTypesSubstitutions get rtiSubstitutions;
   RuntimeTypesEncoder get rtiEncoder;
-  SuperMemberData get superMemberData;
   Tracer get tracer;
   RuntimeTypeTags get rtiTags;
   FixedNames get fixedNames;
@@ -813,18 +805,12 @@
   final CheckedModeHelpers checkedModeHelpers = new CheckedModeHelpers();
 
   @override
-  final OneShotInterceptorData oneShotInterceptorData;
-
-  @override
   final RuntimeTypesSubstitutions rtiSubstitutions;
 
   @override
   final RuntimeTypesEncoder rtiEncoder;
 
   @override
-  final SuperMemberData superMemberData = new SuperMemberData();
-
-  @override
   final Tracer tracer;
 
   @override
@@ -833,6 +819,6 @@
   @override
   final FixedNames fixedNames;
 
-  CodegenInputsImpl(this.oneShotInterceptorData, this.rtiSubstitutions,
-      this.rtiEncoder, this.tracer, this.rtiTags, this.fixedNames);
+  CodegenInputsImpl(this.rtiSubstitutions, this.rtiEncoder, this.tracer,
+      this.rtiTags, this.fixedNames);
 }
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 290c803..256d8f1 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -699,7 +699,7 @@
   BackendImpact _noSuchMethodSupport;
 
   BackendImpact get noSuchMethodSupport {
-    return _noSuchMethodSupport ??= new BackendImpact(staticUses: [
+    return _noSuchMethodSupport ??= new BackendImpact(globalUses: [
       _commonElements.createInvocationMirror,
       _commonElements.createUnmangledInvocationMirror
     ], dynamicUses: [
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 96bc202..06ec784 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -144,12 +144,17 @@
   }
 
   @override
-  jsAst.Expression visitAbstractValue(AbstractValueConstantValue constant,
+  jsAst.Expression visitDummyInterceptor(DummyInterceptorConstantValue constant,
       [_]) {
     return new jsAst.LiteralNumber('0');
   }
 
   @override
+  jsAst.Expression visitUnreachable(UnreachableConstantValue constant, [_]) {
+    return new jsAst.LiteralNumber('0');
+  }
+
+  @override
   jsAst.Expression visitJsName(JsNameConstantValue constant, [_]) {
     return constant.name;
   }
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index d4276ff..2084a1d 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -13,6 +13,7 @@
 import '../common/resolution.dart' show ResolutionImpact;
 import '../common_elements.dart' show ElementEnvironment;
 import '../constants/expressions.dart';
+import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../js_emitter/native_emitter.dart';
@@ -20,10 +21,11 @@
 import '../native/behavior.dart';
 import '../options.dart';
 import '../universe/feature.dart';
-import '../universe/use.dart'
-    show StaticUse, StaticUseKind, TypeUse, TypeUseKind;
+import '../universe/selector.dart';
+import '../universe/use.dart';
 import '../universe/world_impact.dart' show TransformedWorldImpact, WorldImpact;
 import '../util/util.dart';
+import '../world.dart';
 import 'backend_impact.dart';
 import 'backend_usage.dart';
 import 'custom_elements_analysis.dart';
@@ -342,6 +344,7 @@
 
 class CodegenImpactTransformer {
   final CompilerOptions _options;
+  final JClosedWorld _closedWorld;
   final ElementEnvironment _elementEnvironment;
   final CommonElements _commonElements;
   final BackendImpacts _impacts;
@@ -356,6 +359,7 @@
 
   CodegenImpactTransformer(
       this._options,
+      this._closedWorld,
       this._elementEnvironment,
       this._commonElements,
       this._impacts,
@@ -395,6 +399,17 @@
       }
     }
 
+    for (ConstantUse constantUse in impact.constantUses) {
+      switch (constantUse.value.kind) {
+        case ConstantValueKind.DEFERRED_GLOBAL:
+          _closedWorld.outputUnitData
+              .registerConstantDeferredUse(constantUse.value);
+          break;
+        default:
+          break;
+      }
+    }
+
     for (Pair<DartType, DartType> check
         in impact.typeVariableBoundsSubtypeChecks) {
       _rtiChecksBuilder.registerTypeVariableBoundsSubtypeCheck(
@@ -402,12 +417,34 @@
     }
 
     for (StaticUse staticUse in impact.staticUses) {
-      if (staticUse.kind == StaticUseKind.CALL_METHOD) {
-        FunctionEntity callMethod = staticUse.element;
-        if (_rtiNeed.methodNeedsSignature(callMethod)) {
-          _impacts.computeSignature
-              .registerImpact(transformed, _elementEnvironment);
-        }
+      switch (staticUse.kind) {
+        case StaticUseKind.CALL_METHOD:
+          FunctionEntity callMethod = staticUse.element;
+          if (_rtiNeed.methodNeedsSignature(callMethod)) {
+            _impacts.computeSignature
+                .registerImpact(transformed, _elementEnvironment);
+          }
+          break;
+        case StaticUseKind.STATIC_TEAR_OFF:
+        case StaticUseKind.INSTANCE_FIELD_GET:
+        case StaticUseKind.INSTANCE_FIELD_SET:
+        case StaticUseKind.SUPER_INVOKE:
+        case StaticUseKind.STATIC_INVOKE:
+        case StaticUseKind.SUPER_FIELD_SET:
+        case StaticUseKind.SUPER_SETTER_SET:
+        case StaticUseKind.STATIC_SET:
+        case StaticUseKind.SUPER_TEAR_OFF:
+        case StaticUseKind.SUPER_GET:
+        case StaticUseKind.STATIC_GET:
+        case StaticUseKind.FIELD_INIT:
+        case StaticUseKind.FIELD_CONSTANT_INIT:
+        case StaticUseKind.CONSTRUCTOR_INVOKE:
+        case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
+        case StaticUseKind.DIRECT_INVOKE:
+        case StaticUseKind.INLINING:
+        case StaticUseKind.CLOSURE:
+        case StaticUseKind.CLOSURE_CALL:
+          break;
       }
     }
 
@@ -455,6 +492,11 @@
       _nativeEmitter.nativeMethods.add(function);
     }
 
+    for (Selector selector in impact.oneShotInterceptors) {
+      _oneShotInterceptorData.registerOneShotInterceptor(
+          selector, _namer, _closedWorld);
+    }
+
     // TODO(johnniwinther): Remove eager registration.
     return transformed;
   }
diff --git a/pkg/compiler/lib/src/js_backend/interceptor_data.dart b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
index b63dae7..db85765 100644
--- a/pkg/compiler/lib/src/js_backend/interceptor_data.dart
+++ b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
@@ -12,6 +12,7 @@
 import '../inferrer/abstract_value_domain.dart';
 import '../js/js.dart' as jsAst;
 import '../serialization/serialization.dart';
+import '../universe/class_set.dart';
 import '../universe/selector.dart';
 import '../world.dart' show JClosedWorld;
 import 'namer.dart' show ModularNamer, suffixForGetInterceptor;
@@ -252,6 +253,7 @@
           if (result == null) result = new Set<ClassEntity>();
           result.add(subclass);
         }
+        return IterationStep.CONTINUE;
       });
     }
     return result;
@@ -388,11 +390,11 @@
     String key = suffixForGetInterceptor(_commonElements, _nativeData, classes);
     Map<String, OneShotInterceptor> interceptors =
         _oneShotInterceptors[selector] ??= {};
-    OneShotInterceptor interceptor = interceptors.putIfAbsent(
-        key, () => new OneShotInterceptor(key, selector));
+    OneShotInterceptor interceptor =
+        interceptors[key] ??= new OneShotInterceptor(key, selector);
     interceptor.classes.addAll(classes);
     registerSpecializedGetInterceptor(classes, namer);
-    return namer.nameForGetOneShotInterceptor(selector, classes);
+    return namer.nameForOneShotInterceptor(selector, classes);
   }
 
   void registerSpecializedGetInterceptor(
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index c59f8f4..709ee76 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -385,7 +385,7 @@
   /// Property name used for the one-shot interceptor method for the given
   /// [selector] and return-type specialization.
   @override
-  jsAst.Name nameForGetOneShotInterceptor(
+  jsAst.Name nameForOneShotInterceptor(
       Selector selector, Iterable<ClassEntity> classes) {
     String root = selector.isOperator
         ? operatorNameToIdentifier(selector.name)
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index ee53198..c4b1477 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -1323,7 +1323,7 @@
   }
 
   @override
-  jsAst.Name nameForGetOneShotInterceptor(
+  jsAst.Name nameForOneShotInterceptor(
       Selector selector, Iterable<ClassEntity> classes) {
     // The one-shot name is a global name derived from the invocation name.  To
     // avoid instability we would like the names to be unique and not clash with
@@ -1884,8 +1884,13 @@
   }
 
   @override
-  void visitAbstractValue(AbstractValueConstantValue constant, [_]) {
-    add('dummy_receiver');
+  void visitDummyInterceptor(DummyInterceptorConstantValue constant, [_]) {
+    add('dummy_interceptor');
+  }
+
+  @override
+  void visitUnreachable(UnreachableConstantValue constant, [_]) {
+    add('unreachable');
   }
 
   @override
@@ -2012,10 +2017,18 @@
   }
 
   @override
-  int visitAbstractValue(AbstractValueConstantValue constant, [_]) {
+  int visitDummyInterceptor(DummyInterceptorConstantValue constant, [_]) {
     throw failedAt(
         NO_LOCATION_SPANNABLE,
-        'AbstractValueConstantValue should never be named and '
+        'DummyInterceptorConstantValue should never be named and '
+        'never be subconstant');
+  }
+
+  @override
+  int visitUnreachable(UnreachableConstantValue constant, [_]) {
+    throw failedAt(
+        NO_LOCATION_SPANNABLE,
+        'UnreachableConstantValue should never be named and '
         'never be subconstant');
   }
 
@@ -2352,7 +2365,7 @@
 
   /// Property name used for the one-shot interceptor method for the given
   /// [selector] and return-type specialization.
-  jsAst.Name nameForGetOneShotInterceptor(
+  jsAst.Name nameForOneShotInterceptor(
       Selector selector, Set<ClassEntity> classes);
 
   /// Returns the runtime name for [element].
@@ -2736,12 +2749,10 @@
   }
 
   @override
-  jsAst.Name nameForGetOneShotInterceptor(
+  jsAst.Name nameForOneShotInterceptor(
       Selector selector, Set<ClassEntity> classes) {
-    jsAst.Name name = new ModularName(
-        ModularNameKind.nameForGetOneShotInterceptor,
-        data: selector,
-        set: classes);
+    jsAst.Name name = new ModularName(ModularNameKind.nameForOneShotInterceptor,
+        data: selector, set: classes);
     _registry.registerModularName(name);
     return name;
   }
diff --git a/pkg/compiler/lib/src/js_backend/namer_names.dart b/pkg/compiler/lib/src/js_backend/namer_names.dart
index f74a30a..f405dc0 100644
--- a/pkg/compiler/lib/src/js_backend/namer_names.dart
+++ b/pkg/compiler/lib/src/js_backend/namer_names.dart
@@ -212,7 +212,7 @@
   @override
   String get name {
     assert(isFinalized, "TokenName($key) has not been finalized.");
-    return _name ?? key;
+    return _name;
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 3dd3633..fa7a7d1 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -22,6 +22,7 @@
 import '../options.dart';
 import '../serialization/serialization.dart';
 import '../universe/class_hierarchy.dart';
+import '../universe/class_set.dart';
 import '../universe/codegen_world_builder.dart';
 import '../universe/feature.dart';
 import '../universe/selector.dart';
@@ -1525,6 +1526,7 @@
         closedWorld.classHierarchy.forEachStrictSubtypeOf(cls,
             (ClassEntity sub) {
           potentiallyNeedTypeArguments(sub);
+          return IterationStep.CONTINUE;
         });
       } else if (entity is FunctionEntity) {
         methodsNeedingTypeArguments.add(entity);
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index f0ed8a1..5393c9b 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -107,10 +107,10 @@
       Namer namer,
       JClosedWorld closedWorld,
       InferredData inferredData,
-      CodegenInputs codegen,
+      CodegenInputs codegenInputs,
       CodegenWorld codegenWorld) {
     return measure(() {
-      _finalizeRti(codegen, codegenWorld);
+      _finalizeRti(codegenInputs, codegenWorld);
       ProgramBuilder programBuilder = new ProgramBuilder(
           _compiler.options,
           _compiler.reporter,
@@ -123,10 +123,9 @@
           closedWorld.nativeData,
           closedWorld.rtiNeed,
           closedWorld.interceptorData,
-          codegen.superMemberData,
           typeTestRegistry.rtiChecks,
-          codegen.rtiEncoder,
-          codegen.oneShotInterceptorData,
+          codegenInputs.rtiEncoder,
+          codegenWorld.oneShotInterceptorData,
           _backend.customElementsCodegenAnalysis,
           _backend.generatedCode,
           namer,
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index fb1a792..f205845 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -31,7 +31,7 @@
 
   int compareValues(ConstantValue a, ConstantValue b) {
     if (identical(a, b)) return 0;
-    int r = _KindVisitor.kind(a).compareTo(_KindVisitor.kind(b));
+    int r = a.kind.index.compareTo(b.kind.index);
     if (r != 0) return r;
     return a.accept(this, b);
   }
@@ -168,8 +168,14 @@
   }
 
   @override
-  int visitAbstractValue(
-      AbstractValueConstantValue a, AbstractValueConstantValue b) {
+  int visitDummyInterceptor(
+      DummyInterceptorConstantValue a, DummyInterceptorConstantValue b) {
+    // Never emitted.
+    return 0;
+  }
+
+  @override
+  int visitUnreachable(UnreachableConstantValue a, UnreachableConstantValue b) {
     // Never emitted.
     return 0;
   }
@@ -197,66 +203,6 @@
   }
 }
 
-class _KindVisitor implements ConstantValueVisitor<int, Null> {
-  const _KindVisitor();
-
-  static const int FUNCTION = 1;
-  static const int NULL = 2;
-  static const int INT = 3;
-  static const int DOUBLE = 4;
-  static const int BOOL = 5;
-  static const int STRING = 6;
-  static const int LIST = 7;
-  static const int SET = 8;
-  static const int MAP = 9;
-  static const int CONSTRUCTED = 10;
-  static const int TYPE = 11;
-  static const int INTERCEPTOR = 12;
-  static const int ABSTRACT_VALUE = 13;
-  static const int JS_NAME = 14;
-  static const int DEFERRED_GLOBAL = 15;
-  static const int NONCONSTANT = 16;
-  static const int INSTANTIATION = 17;
-
-  static int kind(ConstantValue constant) =>
-      constant.accept(const _KindVisitor(), null);
-
-  @override
-  int visitFunction(FunctionConstantValue a, _) => FUNCTION;
-  @override
-  int visitNull(NullConstantValue a, _) => NULL;
-  @override
-  int visitNonConstant(NonConstantValue a, _) => NONCONSTANT;
-  @override
-  int visitInt(IntConstantValue a, _) => INT;
-  @override
-  int visitDouble(DoubleConstantValue a, _) => DOUBLE;
-  @override
-  int visitBool(BoolConstantValue a, _) => BOOL;
-  @override
-  int visitString(StringConstantValue a, _) => STRING;
-  @override
-  int visitList(ListConstantValue a, _) => LIST;
-  @override
-  int visitSet(SetConstantValue a, _) => SET;
-  @override
-  int visitMap(MapConstantValue a, _) => MAP;
-  @override
-  int visitConstructed(ConstructedConstantValue a, _) => CONSTRUCTED;
-  @override
-  int visitType(TypeConstantValue a, _) => TYPE;
-  @override
-  int visitInterceptor(InterceptorConstantValue a, _) => INTERCEPTOR;
-  @override
-  int visitAbstractValue(AbstractValueConstantValue a, _) => ABSTRACT_VALUE;
-  @override
-  int visitJsName(JsNameConstantValue a, _) => JS_NAME;
-  @override
-  int visitDeferredGlobal(DeferredGlobalConstantValue a, _) => DEFERRED_GLOBAL;
-  @override
-  int visitInstantiation(InstantiationConstantValue a, _) => INSTANTIATION;
-}
-
 /// Visitor for distinguishing types by kind.
 class _DartTypeKindVisitor extends DartTypeVisitor<int, Null> {
   const _DartTypeKindVisitor();
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 10ebf1d..0cc2993 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -20,7 +20,6 @@
 import '../../js/js.dart' as js;
 import '../../js_backend/field_analysis.dart'
     show FieldAnalysisData, JFieldAnalysis;
-import '../../js_backend/backend.dart' show SuperMemberData;
 import '../../js_backend/backend_usage.dart';
 import '../../js_backend/custom_elements_analysis.dart';
 import '../../js_backend/inferred_data.dart';
@@ -68,7 +67,6 @@
   final NativeData _nativeData;
   final RuntimeTypesNeed _rtiNeed;
   final InterceptorData _interceptorData;
-  final SuperMemberData _superMemberData;
   final RuntimeTypesChecks _rtiChecks;
   final RuntimeTypesEncoder _rtiEncoder;
   final OneShotInterceptorData _oneShotInterceptorData;
@@ -111,7 +109,6 @@
       this._nativeData,
       this._rtiNeed,
       this._interceptorData,
-      this._superMemberData,
       this._rtiChecks,
       this._rtiEncoder,
       this._oneShotInterceptorData,
@@ -887,7 +884,7 @@
 
     bool canBeApplied = _methodCanBeApplied(element);
 
-    js.Name aliasName = _superMemberData.isAliasedSuperMember(element)
+    js.Name aliasName = _codegenWorld.isAliasedSuperMember(element)
         ? _namer.aliasedSuperMemberPropertyName(element)
         : null;
 
@@ -1136,7 +1133,7 @@
     Map<js.Name, OneShotInterceptor> interceptorMap = {};
     for (OneShotInterceptor interceptor
         in _oneShotInterceptorData.oneShotInterceptors) {
-      js.Name name = _namer.nameForGetOneShotInterceptor(
+      js.Name name = _namer.nameForOneShotInterceptor(
           interceptor.selector, interceptor.classes);
       names.add(name);
       assert(
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index bb595f5..9a39986 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -628,6 +628,7 @@
 
   @override
   JFunction callMethod;
+  @override
   JSignatureMethod signatureMethod;
   @override
   final Local closureEntity;
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 5356e84..cde245a 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -19,6 +19,7 @@
 import '../constants/evaluation.dart';
 import '../constants/expressions.dart';
 import '../constants/values.dart';
+import '../deferred_load.dart';
 import '../elements/entities.dart';
 import '../elements/entity_utils.dart' as utils;
 import '../elements/indexed.dart';
@@ -127,6 +128,8 @@
 
   Map<IndexedClass, List<IndexedMember>> _injectedClassMembers = {};
 
+  LateOutputUnitDataBuilder lateOutputUnitDataBuilder;
+
   JsKernelToElementMap(
       this.reporter,
       Environment environment,
@@ -441,6 +444,31 @@
     source.end(tag);
   }
 
+  /// Prepares the entity maps for codegen serialization and returns the member
+  /// index limit for early members.
+  ///
+  /// This method creates all late members, such as constructor bodies and
+  /// generator bodies, and closes the entity maps for further registration.
+  int prepareForCodegenSerialization() {
+    int length = members.length;
+    for (int memberIndex = 0; memberIndex < length; memberIndex++) {
+      MemberEntity member = members.getEntity(memberIndex);
+      if (member == null) continue;
+      if (member is JGenerativeConstructor) {
+        getConstructorBody(members.getData(member).definition.node);
+      }
+      if (member is IndexedFunction && member.asyncMarker != AsyncMarker.SYNC) {
+        getGeneratorBody(member);
+      }
+    }
+    libraries.close();
+    classes.close();
+    members.close();
+    typedefs.close();
+    typeVariables.close();
+    return length;
+  }
+
   /// Serializes this [JsToElementMap] to [sink].
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
@@ -1604,33 +1632,35 @@
   @override
   FunctionEntity getConstructorBody(ir.Constructor node) {
     ConstructorEntity constructor = getConstructor(node);
-    return _getConstructorBody(node, constructor);
+    return _getConstructorBody(constructor);
   }
 
-  FunctionEntity _getConstructorBody(
-      ir.Constructor node, covariant IndexedConstructor constructor) {
+  JConstructorBody _getConstructorBody(IndexedConstructor constructor) {
     JConstructorDataImpl data = members.getData(constructor);
     if (data.constructorBody == null) {
       /// The constructor calls the constructor body with all parameters.
       // TODO(johnniwinther): Remove parameters that are not used in the
       //  constructor body.
       ParameterStructure parameterStructure =
-          _getParameterStructureFromFunctionNode(node.function);
+          _getParameterStructureFromFunctionNode(data.node.function);
 
       JConstructorBody constructorBody =
           createConstructorBody(constructor, parameterStructure);
       members.register<IndexedFunction, FunctionData>(
           constructorBody,
           new ConstructorBodyDataImpl(
-              node,
-              node.function,
-              new SpecialMemberDefinition(node, MemberKind.constructorBody),
+              data.node,
+              data.node.function,
+              new SpecialMemberDefinition(
+                  data.node, MemberKind.constructorBody),
               data.staticTypes));
       IndexedClass cls = constructor.enclosingClass;
       JClassEnvImpl classEnv = classes.getEnv(cls);
       // TODO(johnniwinther): Avoid this by only including live members in the
       // js-model.
       classEnv.addConstructorBody(constructorBody);
+      lateOutputUnitDataBuilder.registerColocatedMembers(
+          constructor, constructorBody);
       data.constructorBody = constructorBody;
     }
     return data.constructorBody;
@@ -2079,6 +2109,9 @@
         (_injectedClassMembers[function.enclosingClass] ??= <IndexedMember>[])
             .add(generatorBody);
       }
+      lateOutputUnitDataBuilder.registerColocatedMembers(
+          generatorBody.function, generatorBody);
+      _generatorBodies[function] = generatorBody;
     }
     return generatorBody;
   }
@@ -2616,3 +2649,81 @@
     return _elementMap.libraries.getEntity(index);
   }
 }
+
+/// Enum used for serialization of 'late members', that is, members normally
+/// created on demand, like constructor bodies and generator bodies.
+enum LateMemberKind {
+  constructorBody,
+  generatorBody,
+}
+
+/// Entity reader that supports member entities normally created on-demand, like
+/// constructor bodies and generator bodies.
+///
+/// The support encoding corresponds to the encoding generated by the
+/// [ClosedEntityWriter].
+class ClosedEntityReader extends EntityReader {
+  final JsKernelToElementMap _elementMap;
+
+  ClosedEntityReader(this._elementMap);
+
+  @override
+  IndexedMember readMemberFromDataSource(
+      DataSource source, EntityLookup entityLookup) {
+    int index = source.readInt();
+    if (index == 0) {
+      return _readLateMemberFromDataSource(source, entityLookup);
+    } else {
+      return entityLookup.getMemberByIndex(index - 1);
+    }
+  }
+
+  IndexedMember _readLateMemberFromDataSource(
+      DataSource source, EntityLookup entityLookup) {
+    LateMemberKind kind = source.readEnum(LateMemberKind.values);
+    switch (kind) {
+      case LateMemberKind.constructorBody:
+        IndexedConstructor constructor = source.readMember();
+        return _elementMap._getConstructorBody(constructor);
+      case LateMemberKind.generatorBody:
+        IndexedFunction function = source.readMember();
+        return _elementMap.getGeneratorBody(function);
+    }
+    throw new UnsupportedError("Unexpected late member kind: $kind.");
+  }
+}
+
+/// Entity writer that supports member entities normally created on-demand, like
+/// constructor bodies and generator bodies.
+///
+/// The generated encoding corresponds to the encoding read by the
+/// [ClosedEntityReader].
+class ClosedEntityWriter extends EntityWriter {
+  final int _earlyMemberIndexLimit;
+
+  final JsKernelToElementMap _elementMap;
+
+  ClosedEntityWriter(this._elementMap, this._earlyMemberIndexLimit);
+
+  @override
+  void writeMemberToDataSink(DataSink sink, IndexedMember value) {
+    if (value.memberIndex >= _earlyMemberIndexLimit) {
+      sink.writeInt(0);
+      _writeLateMemberToDataSink(sink, value);
+    } else {
+      sink.writeInt(value.memberIndex + 1);
+    }
+  }
+
+  void _writeLateMemberToDataSink(DataSink sink, IndexedMember value) {
+    if (value is JConstructorBody) {
+      sink.writeEnum(LateMemberKind.constructorBody);
+      sink.writeMember(value.constructor);
+    } else if (value is JGeneratorBody) {
+      sink.writeEnum(LateMemberKind.generatorBody);
+      sink.writeMember(value.function);
+    } else {
+      throw new UnsupportedError("Unexpected late member $value.");
+    }
+  }
+}
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index ffe37e3..2a64023 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -8,7 +8,7 @@
 
 import '../backend_strategy.dart';
 import '../common.dart';
-import '../common/codegen.dart' show CodegenRegistry;
+import '../common/codegen.dart' show CodegenRegistry, CodegenResults;
 import '../common/tasks.dart';
 import '../common/work.dart';
 import '../compiler.dart';
@@ -25,6 +25,7 @@
 import '../js/js_source_mapping.dart';
 import '../js_backend/backend.dart';
 import '../js_backend/inferred_data.dart';
+import '../js_backend/interceptor_data.dart';
 import '../js_backend/native_data.dart';
 import '../js_backend/namer.dart' show ModularNamer;
 import '../js_emitter/code_emitter_task.dart' show ModularEmitter;
@@ -80,8 +81,11 @@
         closureDataBuilder,
         _compiler.options,
         _compiler.abstractValueStrategy);
-    return closedWorldBuilder.convertClosedWorld(
+    JClosedWorld jClosedWorld = closedWorldBuilder.convertClosedWorld(
         closedWorld, strategy.closureModels, outputUnitData);
+    _elementMap.lateOutputUnitDataBuilder =
+        new LateOutputUnitDataBuilder(jClosedWorld.outputUnitData);
+    return jClosedWorld;
   }
 
   @override
@@ -111,12 +115,14 @@
   }
 
   @override
-  WorkItemBuilder createCodegenWorkItemBuilder(JClosedWorld closedWorld) {
+  WorkItemBuilder createCodegenWorkItemBuilder(
+      JClosedWorld closedWorld, CodegenResults codegenResults) {
     assert(_elementMap != null,
         "JsBackendStrategy.elementMap has not been created yet.");
     return new KernelCodegenWorkItemBuilder(
         _compiler.backend,
         closedWorld,
+        codegenResults,
         new ClosedEntityLookup(_elementMap),
         // TODO(johnniwinther): Avoid the need for a [ComponentLookup]. This
         // is caused by some type masks holding a kernel node for using in
@@ -128,9 +134,10 @@
   CodegenWorldBuilder createCodegenWorldBuilder(
       NativeBasicData nativeBasicData,
       JClosedWorld closedWorld,
-      SelectorConstraintsStrategy selectorConstraintsStrategy) {
+      SelectorConstraintsStrategy selectorConstraintsStrategy,
+      OneShotInterceptorData oneShotInterceptorData) {
     return new CodegenWorldBuilderImpl(
-        closedWorld, selectorConstraintsStrategy);
+        closedWorld, selectorConstraintsStrategy, oneShotInterceptorData);
   }
 
   @override
@@ -143,40 +150,65 @@
       JClosedWorld closedWorld, InferredDataBuilder inferredDataBuilder) {
     return new TypeGraphInferrer(_compiler, closedWorld, inferredDataBuilder);
   }
+
+  @override
+  void prepareCodegenReader(DataSource source) {
+    source.registerEntityReader(new ClosedEntityReader(_elementMap));
+    source.registerEntityLookup(new ClosedEntityLookup(_elementMap));
+    source.registerComponentLookup(
+        new ComponentLookup(_elementMap.programEnv.mainComponent));
+  }
+
+  @override
+  EntityWriter forEachCodegenMember(void Function(MemberEntity member) f) {
+    int earlyMemberIndexLimit = _elementMap.prepareForCodegenSerialization();
+    ClosedEntityWriter entityWriter =
+        new ClosedEntityWriter(_elementMap, earlyMemberIndexLimit);
+    for (int memberIndex = 0;
+        memberIndex < _elementMap.members.length;
+        memberIndex++) {
+      MemberEntity member = _elementMap.members.getEntity(memberIndex);
+      if (member == null || member.isAbstract) continue;
+      f(member);
+    }
+    return entityWriter;
+  }
 }
 
 class KernelCodegenWorkItemBuilder implements WorkItemBuilder {
   final JavaScriptBackend _backend;
   final JClosedWorld _closedWorld;
+  final CodegenResults _codegenResults;
   final EntityLookup _entityLookup;
   final ComponentLookup _componentLookup;
 
   KernelCodegenWorkItemBuilder(this._backend, this._closedWorld,
-      this._entityLookup, this._componentLookup);
+      this._codegenResults, this._entityLookup, this._componentLookup);
 
   @override
   WorkItem createWorkItem(MemberEntity entity) {
     if (entity.isAbstract) return null;
-    return new KernelCodegenWorkItem(
-        _backend, _closedWorld, _entityLookup, _componentLookup, entity);
+    return new KernelCodegenWorkItem(_backend, _closedWorld, _codegenResults,
+        _entityLookup, _componentLookup, entity);
   }
 }
 
 class KernelCodegenWorkItem extends WorkItem {
   final JavaScriptBackend _backend;
   final JClosedWorld _closedWorld;
+  final CodegenResults _codegenResults;
   final EntityLookup _entityLookup;
   final ComponentLookup _componentLookup;
   @override
   final MemberEntity element;
 
-  KernelCodegenWorkItem(this._backend, this._closedWorld, this._entityLookup,
-      this._componentLookup, this.element);
+  KernelCodegenWorkItem(this._backend, this._closedWorld, this._codegenResults,
+      this._entityLookup, this._componentLookup, this.element);
 
   @override
   WorldImpact run() {
     return _backend.generateCode(
-        this, _closedWorld, _entityLookup, _componentLookup);
+        this, _closedWorld, _codegenResults, _entityLookup, _componentLookup);
   }
 }
 
@@ -189,9 +221,8 @@
   final JsToElementMap _elementMap;
   final SourceInformationStrategy _sourceInformationStrategy;
 
-  // TODO(johnniwinther,sra): Inlining decisions should not be based on the
-  // order in which ssa graphs are built.
   FunctionInlineCache _inlineCache;
+  InlineDataCache _inlineDataCache;
 
   KernelSsaBuilder(this._task, this._options, this._reporter,
       this._dumpInfoTask, this._elementMap, this._sourceInformationStrategy);
@@ -206,6 +237,9 @@
       ModularNamer namer,
       ModularEmitter emitter) {
     _inlineCache ??= new FunctionInlineCache(closedWorld.annotationsData);
+    _inlineDataCache ??= new InlineDataCache(
+        enableUserAssertions: _options.enableUserAssertions,
+        omitImplicitCasts: _options.omitImplicitChecks);
     return _task.measure(() {
       KernelSsaGraphBuilder builder = new KernelSsaGraphBuilder(
           _options,
@@ -222,7 +256,8 @@
           codegen.tracer,
           codegen.rtiEncoder,
           _sourceInformationStrategy,
-          _inlineCache);
+          _inlineCache,
+          _inlineDataCache);
       return builder.build();
     });
   }
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index 6ed9e82..3515770 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -170,6 +170,8 @@
 
     OutputUnitData outputUnitData =
         new OutputUnitData.readFromDataSource(source);
+    elementMap.lateOutputUnitDataBuilder =
+        new LateOutputUnitDataBuilder(outputUnitData);
 
     Map<MemberEntity, MemberAccess> memberAccess =
         source.readMemberMap(() => new MemberAccess.readFromDataSource(source));
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
index b3a59d2..f4d964c 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -108,6 +108,7 @@
         .getClassHierarchyNode(closedWorld.commonElements.objectClass)
         .forEachSubclass((ClassEntity cls) {
       convertClassSet(closedWorld.classHierarchy.getClassSet(cls));
+      return IterationStep.CONTINUE;
     }, ClassHierarchyNode.ALL);
 
     Set<MemberEntity> liveInstanceMembers =
@@ -485,6 +486,9 @@
         if (entity is KLocalFunction) {
           var closureInfo = closureDataLookup.getClosureInfo(entity.node);
           result[closureInfo.callMethod] = unit;
+          if (closureInfo.signatureMethod != null) {
+            result[closureInfo.signatureMethod] = unit;
+          }
         }
       });
       return result;
@@ -846,7 +850,11 @@
   @override
   ConstantValue visitString(StringConstantValue constant, _) => constant;
   @override
-  ConstantValue visitAbstractValue(AbstractValueConstantValue constant, _) =>
+  ConstantValue visitDummyInterceptor(
+          DummyInterceptorConstantValue constant, _) =>
+      constant;
+  @override
+  ConstantValue visitUnreachable(UnreachableConstantValue constant, _) =>
       constant;
   @override
   ConstantValue visitJsName(JsNameConstantValue constant, _) => constant;
diff --git a/pkg/compiler/lib/src/old_to_new_api.dart b/pkg/compiler/lib/src/old_to_new_api.dart
index 808e242..a5d7c45 100644
--- a/pkg/compiler/lib/src/old_to_new_api.dart
+++ b/pkg/compiler/lib/src/old_to_new_api.dart
@@ -23,6 +23,8 @@
 
   @override
   Future<Input> readFromUri(Uri uri, {InputKind inputKind: InputKind.UTF8}) {
+    // The switch handles all enum values, but not null.
+    // ignore: missing_return
     return _inputProvider(uri).then((/*String|List<int>*/ data) {
       switch (inputKind) {
         case InputKind.UTF8:
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 2e4ac4b..acce37c 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -76,6 +76,16 @@
   /// If this is set, the compilation stops after type inference.
   Uri writeDataUri;
 
+  /// Location from which codegen data is read.
+  ///
+  /// If this is set, the compilation starts at codegen enqueueing.
+  Uri readCodegenUri;
+
+  /// Location to which codegen data is serialized.
+  ///
+  /// If this is set, the compilation stops after code generation.
+  Uri writeCodegenUri;
+
   /// Whether to run only the CFE and emit the generated kernel file in
   /// [outputUri].
   bool cfeOnly = false;
@@ -325,6 +335,13 @@
   /// If specified, a bundle of optimizations to enable (or disable).
   int optimizationLevel = null;
 
+  /// The shard to serialize when using [writeCodegenUri].
+  int codegenShard;
+
+  /// The number of shards to serialize when using [writeCodegenUri] or to
+  /// deserialize when using [readCodegenUri].
+  int codegenShards;
+
   // -------------------------------------------------
   // Options for deprecated features
   // -------------------------------------------------
@@ -407,6 +424,10 @@
           _extractUriListOption(options, '${Flags.dillDependencies}')
       ..readDataUri = _extractUriOption(options, '${Flags.readData}=')
       ..writeDataUri = _extractUriOption(options, '${Flags.writeData}=')
+      ..readCodegenUri = _extractUriOption(options, '${Flags.readCodegen}=')
+      ..writeCodegenUri = _extractUriOption(options, '${Flags.writeCodegen}=')
+      ..codegenShard = _extractIntOption(options, '${Flags.codegenShard}=')
+      ..codegenShards = _extractIntOption(options, '${Flags.codegenShards}=')
       ..cfeOnly = _hasOption(options, Flags.cfeOnly)
       ..debugGlobalInference = _hasOption(options, Flags.debugGlobalInference);
   }
@@ -533,10 +554,15 @@
 }
 
 Uri _extractUriOption(List<String> options, String prefix) {
-  var option = _extractStringOption(options, prefix, null);
+  String option = _extractStringOption(options, prefix, null);
   return (option == null) ? null : Uri.parse(option);
 }
 
+int _extractIntOption(List<String> options, String prefix) {
+  String option = _extractStringOption(options, prefix, null);
+  return (option == null) ? null : int.parse(option);
+}
+
 bool _hasOption(List<String> options, String option) {
   return options.indexOf(option) >= 0;
 }
diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart
index ac9d487..a1af8e8 100644
--- a/pkg/compiler/lib/src/serialization/abstract_sink.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart
@@ -34,9 +34,12 @@
 
   Map<Type, IndexedSink> _generalCaches = {};
 
+  EntityWriter _entityWriter = const EntityWriter();
   CodegenWriter _codegenWriter;
 
-  AbstractDataSink({this.useDataKinds: false}) {
+  final Map<String, int> tagFrequencyMap;
+
+  AbstractDataSink({this.useDataKinds: false, this.tagFrequencyMap}) {
     _dartTypeWriter = new DartTypeWriter(this);
     _dartTypeNodeWriter = new DartTypeNodeWriter(this);
     _stringIndex = new IndexedSink<String>(this);
@@ -47,6 +50,10 @@
 
   @override
   void begin(String tag) {
+    if (tagFrequencyMap != null) {
+      tagFrequencyMap[tag] ??= 0;
+      tagFrequencyMap[tag]++;
+    }
     if (useDataKinds) {
       _tags ??= <String>[];
       _tags.add(tag);
@@ -307,22 +314,26 @@
 
   @override
   void writeLibrary(IndexedLibrary value) {
-    writeInt(value.libraryIndex);
+    _entityWriter.writeLibraryToDataSink(this, value);
   }
 
   @override
   void writeClass(IndexedClass value) {
-    writeInt(value.classIndex);
+    _entityWriter.writeClassToDataSink(this, value);
   }
 
   @override
   void writeTypedef(IndexedTypedef value) {
-    writeInt(value.typedefIndex);
+    _entityWriter.writeTypedefToDataSink(this, value);
   }
 
   @override
   void writeMember(IndexedMember value) {
-    writeInt(value.memberIndex);
+    _entityWriter.writeMemberToDataSink(this, value);
+  }
+
+  void writeTypeVariable(IndexedTypeVariable value) {
+    _entityWriter.writeTypeVariableToDataSink(this, value);
   }
 
   @override
@@ -450,10 +461,12 @@
         writeConstant(constant.referenced);
         writeOutputUnitReference(constant.unit);
         break;
-      case ConstantValueKind.ABSTRACT_VALUE:
-        AbstractValueConstantValue constant = value;
+      case ConstantValueKind.DUMMY_INTERCEPTOR:
+        DummyInterceptorConstantValue constant = value;
         writeAbstractValue(constant.abstractValue);
         break;
+      case ConstantValueKind.UNREACHABLE:
+        break;
       case ConstantValueKind.JS_NAME:
         JsNameConstantValue constant = value;
         writeJsNode(constant.name);
@@ -488,6 +501,12 @@
   }
 
   @override
+  void registerEntityWriter(EntityWriter writer) {
+    assert(writer != null);
+    _entityWriter = writer;
+  }
+
+  @override
   void registerCodegenWriter(CodegenWriter writer) {
     assert(writer != null);
     assert(_codegenWriter == null);
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index 87cb765..a2fa583 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -9,6 +9,7 @@
 abstract class AbstractDataSource extends DataSourceMixin
     implements DataSource {
   final bool useDataKinds;
+  EntityReader _entityReader = const EntityReader();
   ComponentLookup _componentLookup;
   EntityLookup _entityLookup;
   LocalLookup _localLookup;
@@ -66,6 +67,12 @@
     _localLookup = localLookup;
   }
 
+  @override
+  void registerEntityReader(EntityReader reader) {
+    assert(reader != null);
+    _entityReader = reader;
+  }
+
   LocalLookup get localLookup {
     assert(_localLookup != null);
     return _localLookup;
@@ -79,6 +86,12 @@
   }
 
   @override
+  void deregisterCodegenReader(CodegenReader reader) {
+    assert(_codegenReader == reader);
+    _codegenReader = null;
+  }
+
+  @override
   E readCached<E>(E f()) {
     IndexedSource source = _generalCaches[E] ??= new IndexedSource<E>(this);
     return source.read(f);
@@ -86,38 +99,27 @@
 
   @override
   IndexedLibrary readLibrary() {
-    return getIndexedLibrary(readInt());
+    return _entityReader.readLibraryFromDataSource(this, entityLookup);
   }
 
   @override
   IndexedClass readClass() {
-    return getIndexedClass(readInt());
+    return _entityReader.readClassFromDataSource(this, entityLookup);
   }
 
   @override
   IndexedTypedef readTypedef() {
-    return getIndexedTypedef(readInt());
+    return _entityReader.readTypedefFromDataSource(this, entityLookup);
   }
 
   @override
   IndexedMember readMember() {
-    return getIndexedMember(readInt());
+    return _entityReader.readMemberFromDataSource(this, entityLookup);
   }
 
-  IndexedLibrary getIndexedLibrary(int libraryIndex) =>
-      entityLookup.getLibraryByIndex(libraryIndex);
-
-  IndexedClass getIndexedClass(int classIndex) =>
-      entityLookup.getClassByIndex(classIndex);
-
-  IndexedTypedef getIndexedTypedef(int typedefIndex) =>
-      entityLookup.getTypedefByIndex(typedefIndex);
-
-  IndexedMember getIndexedMember(int memberIndex) =>
-      entityLookup.getMemberByIndex(memberIndex);
-
-  IndexedTypeVariable getIndexedTypeVariable(int typeVariableIndex) =>
-      entityLookup.getTypeVariableByIndex(typeVariableIndex);
+  IndexedTypeVariable readTypeVariable() {
+    return _entityReader.readTypeVariableFromDataSource(this, entityLookup);
+  }
 
   List<DartType> _readDartTypes(
       List<FunctionTypeVariable> functionTypeVariables) {
@@ -164,7 +166,7 @@
       case DartTypeKind.voidType:
         return const VoidType();
       case DartTypeKind.typeVariable:
-        return new TypeVariableType(getIndexedTypeVariable(readInt()));
+        return new TypeVariableType(readTypeVariable());
       case DartTypeKind.functionTypeVariable:
         int index = readInt();
         assert(0 <= index && index < functionTypeVariables.length);
@@ -200,11 +202,11 @@
             typeVariables);
 
       case DartTypeKind.interfaceType:
-        IndexedClass cls = getIndexedClass(readInt());
+        IndexedClass cls = readClass();
         List<DartType> typeArguments = _readDartTypes(functionTypeVariables);
         return new InterfaceType(cls, typeArguments);
       case DartTypeKind.typedef:
-        IndexedTypedef typedef = getIndexedTypedef(readInt());
+        IndexedTypedef typedef = readTypedef();
         List<DartType> typeArguments = _readDartTypes(functionTypeVariables);
         DartType unaliased = _readDartType(functionTypeVariables);
         return new TypedefType(typedef, typeArguments, unaliased);
@@ -510,9 +512,11 @@
         ConstantValue constant = readConstant();
         OutputUnit unit = readOutputUnitReference();
         return new DeferredGlobalConstantValue(constant, unit);
-      case ConstantValueKind.ABSTRACT_VALUE:
+      case ConstantValueKind.DUMMY_INTERCEPTOR:
         AbstractValue abstractValue = readAbstractValue();
-        return new AbstractValueConstantValue(abstractValue);
+        return new DummyInterceptorConstantValue(abstractValue);
+      case ConstantValueKind.UNREACHABLE:
+        return const UnreachableConstantValue();
       case ConstantValueKind.JS_NAME:
         js.LiteralString name = readJsNode();
         return new JsNameConstantValue(name);
diff --git a/pkg/compiler/lib/src/serialization/binary_sink.dart b/pkg/compiler/lib/src/serialization/binary_sink.dart
index 3f771b4..6d46fb4 100644
--- a/pkg/compiler/lib/src/serialization/binary_sink.dart
+++ b/pkg/compiler/lib/src/serialization/binary_sink.dart
@@ -12,9 +12,10 @@
   BufferedSink _bufferedSink;
   int _length = 0;
 
-  BinarySink(this.sink, {bool useDataKinds: false})
+  BinarySink(this.sink,
+      {bool useDataKinds: false, Map<String, int> tagFrequencyMap})
       : _bufferedSink = new BufferedSink(sink),
-        super(useDataKinds: useDataKinds);
+        super(useDataKinds: useDataKinds, tagFrequencyMap: tagFrequencyMap);
 
   @override
   void _begin(String tag) {
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index 40cc83d..b73a8c9 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -130,7 +130,7 @@
       List<FunctionTypeVariable> functionTypeVariables) {
     _sink.writeEnum(DartTypeKind.typeVariable);
     IndexedTypeVariable typeVariable = type.element;
-    _sink.writeInt(typeVariable.typeVariableIndex);
+    _sink.writeTypeVariable(typeVariable);
   }
 
   @override
@@ -336,6 +336,7 @@
 class IndexedSink<E> {
   final AbstractDataSink _sink;
   final Map<E, int> _cache = {};
+  Set<E> _current = {};
 
   IndexedSink(this._sink);
 
@@ -346,10 +347,14 @@
   void write(E value, void writeValue(E value)) {
     int index = _cache[value];
     if (index == null) {
+      if (!_current.add(value)) {
+        throw new ArgumentError("Cyclic dependency on cached value: $value");
+      }
       index = _cache.length;
-      _cache[value] = index;
       _sink._writeIntInternal(index);
       writeValue(value);
+      _cache[value] = index;
+      _current.remove(value);
     } else {
       _sink._writeIntInternal(index);
     }
diff --git a/pkg/compiler/lib/src/serialization/object_sink.dart b/pkg/compiler/lib/src/serialization/object_sink.dart
index 31376e3..82c8885 100644
--- a/pkg/compiler/lib/src/serialization/object_sink.dart
+++ b/pkg/compiler/lib/src/serialization/object_sink.dart
@@ -11,8 +11,8 @@
 class ObjectSink extends AbstractDataSink {
   List<dynamic> _data;
 
-  ObjectSink(this._data, {bool useDataKinds})
-      : super(useDataKinds: useDataKinds);
+  ObjectSink(this._data, {bool useDataKinds, Map<String, int> tagFrequencyMap})
+      : super(useDataKinds: useDataKinds, tagFrequencyMap: tagFrequencyMap);
 
   @override
   void _begin(String tag) {
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index d4f574c..92e6ad0 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -399,6 +399,10 @@
   /// This feature is only available a [CodegenWriter] has been registered.
   void writeJsNodeOrNull(js.Node value);
 
+  /// Register an [EntityWriter] with this data sink for non-default encoding
+  /// of entity references.
+  void registerEntityWriter(EntityWriter writer);
+
   /// Register a [CodegenWriter] with this data sink to support serialization
   /// of codegen only data.
   void registerCodegenWriter(CodegenWriter writer);
@@ -426,13 +430,21 @@
   /// deserialization of references to indexed entities.
   void registerEntityLookup(EntityLookup entityLookup);
 
+  /// Registers an [EntityReader] with this data source for non-default encoding
+  /// of entity references.
+  void registerEntityReader(EntityReader reader);
+
   /// Registers a [LocalLookup] object with this data source to support
   /// deserialization of references to locals.
   void registerLocalLookup(LocalLookup localLookup);
 
   /// Registers a [CodegenReader] with this data source to support
   /// deserialization of codegen only data.
-  void registerCodegenReader(CodegenReader read);
+  void registerCodegenReader(CodegenReader reader);
+
+  /// Unregisters the [CodegenReader] from this data source to remove support
+  /// for deserialization of codegen only data.
+  void deregisterCodegenReader(CodegenReader reader);
 
   /// Reads a reference to an [E] value from this data source. If the value has
   /// not yet been deserialized, [f] is called to deserialize the value itself.
@@ -771,6 +783,61 @@
   IndexedTypeVariable getTypeVariableByIndex(int index);
 }
 
+/// Decoding strategy for entity references.
+class EntityReader {
+  const EntityReader();
+
+  IndexedLibrary readLibraryFromDataSource(
+      DataSource source, EntityLookup entityLookup) {
+    return entityLookup.getLibraryByIndex(source.readInt());
+  }
+
+  IndexedClass readClassFromDataSource(
+      DataSource source, EntityLookup entityLookup) {
+    return entityLookup.getClassByIndex(source.readInt());
+  }
+
+  IndexedTypedef readTypedefFromDataSource(
+      DataSource source, EntityLookup entityLookup) {
+    return entityLookup.getTypedefByIndex(source.readInt());
+  }
+
+  IndexedMember readMemberFromDataSource(
+      DataSource source, EntityLookup entityLookup) {
+    return entityLookup.getMemberByIndex(source.readInt());
+  }
+
+  IndexedTypeVariable readTypeVariableFromDataSource(
+      DataSource source, EntityLookup entityLookup) {
+    return entityLookup.getTypeVariableByIndex(source.readInt());
+  }
+}
+
+/// Encoding strategy for entity references.
+class EntityWriter {
+  const EntityWriter();
+
+  void writeLibraryToDataSink(DataSink sink, IndexedLibrary value) {
+    sink.writeInt(value.libraryIndex);
+  }
+
+  void writeClassToDataSink(DataSink sink, IndexedClass value) {
+    sink.writeInt(value.classIndex);
+  }
+
+  void writeTypedefToDataSink(DataSink sink, IndexedTypedef value) {
+    sink.writeInt(value.typedefIndex);
+  }
+
+  void writeMemberToDataSink(DataSink sink, IndexedMember value) {
+    sink.writeInt(value.memberIndex);
+  }
+
+  void writeTypeVariableToDataSink(DataSink sink, IndexedTypeVariable value) {
+    sink.writeInt(value.typeVariableIndex);
+  }
+}
+
 /// Interface used for looking up locals by index during deserialization.
 abstract class LocalLookup {
   Local getLocalByIndex(MemberEntity memberContext, int index);
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 56ab4bd..61771d5 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -7,16 +7,20 @@
 import 'package:kernel/binary/ast_from_binary.dart' as ir;
 import 'package:kernel/binary/ast_to_binary.dart' as ir;
 import '../../compiler_new.dart' as api;
+import '../backend_strategy.dart';
+import '../common/codegen.dart';
 import '../common/tasks.dart';
-import '../compiler.dart';
 import '../diagnostics/diagnostic_listener.dart';
+import '../elements/entities.dart';
 import '../environment.dart';
 import '../inferrer/abstract_value_domain.dart';
 import '../inferrer/types.dart';
+import '../js_backend/backend.dart';
 import '../js_backend/inferred_data.dart';
 import '../js_model/js_world.dart';
 import '../options.dart';
 import '../util/sink_adapter.dart';
+import '../world.dart';
 import 'serialization.dart';
 
 void serializeGlobalTypeInferenceResults(
@@ -45,21 +49,26 @@
 }
 
 class SerializationTask extends CompilerTask {
-  final Compiler compiler;
+  final CompilerOptions _options;
+  final DiagnosticReporter _reporter;
+  final api.CompilerInput _provider;
+  final api.CompilerOutput _outputProvider;
 
-  SerializationTask(this.compiler, Measurer measurer) : super(measurer);
+  SerializationTask(this._options, this._reporter, this._provider,
+      this._outputProvider, Measurer measurer)
+      : super(measurer);
 
   @override
   String get name => 'Serialization';
 
-  void serialize(GlobalTypeInferenceResults results) {
+  void serializeGlobalTypeInference(GlobalTypeInferenceResults results) {
     measureSubtask('serialize dill', () {
       // TODO(sigmund): remove entirely: we will do this immediately as soon as
       // we get the component in the kernel/loader.dart task once we refactor
       // how we apply our modular kernel transformation for super mixin calls.
-      compiler.reporter.log('Writing dill to ${compiler.options.outputUri}');
+      _reporter.log('Writing dill to ${_options.outputUri}');
       api.BinaryOutputSink dillOutput =
-          compiler.outputProvider.createBinarySink(compiler.options.outputUri);
+          _outputProvider.createBinarySink(_options.outputUri);
       JsClosedWorld closedWorld = results.closedWorld;
       ir.Component component = closedWorld.elementMap.programEnv.mainComponent;
       BinaryOutputSinkAdapter irSink = new BinaryOutputSinkAdapter(dillOutput);
@@ -69,40 +78,99 @@
     });
 
     measureSubtask('serialize data', () {
-      compiler.reporter.log('Writing data to ${compiler.options.writeDataUri}');
-      api.BinaryOutputSink dataOutput = compiler.outputProvider
-          .createBinarySink(compiler.options.writeDataUri);
+      _reporter.log('Writing data to ${_options.writeDataUri}');
+      api.BinaryOutputSink dataOutput =
+          _outputProvider.createBinarySink(_options.writeDataUri);
       DataSink sink = new BinarySink(new BinaryOutputSinkAdapter(dataOutput));
       serializeGlobalTypeInferenceResults(results, sink);
     });
   }
 
-  Future<GlobalTypeInferenceResults> deserialize() async {
+  Future<GlobalTypeInferenceResults> deserializeGlobalTypeInference(
+      Environment environment,
+      AbstractValueStrategy abstractValueStrategy) async {
     ir.Component component =
         await measureIoSubtask('deserialize dill', () async {
-      compiler.reporter.log('Reading dill from ${compiler.options.entryPoint}');
-      api.Input<List<int>> dillInput = await compiler.provider.readFromUri(
-          compiler.options.entryPoint,
-          inputKind: api.InputKind.binary);
+      _reporter.log('Reading dill from ${_options.entryPoint}');
+      api.Input<List<int>> dillInput = await _provider
+          .readFromUri(_options.entryPoint, inputKind: api.InputKind.binary);
       ir.Component component = new ir.Component();
       new ir.BinaryBuilder(dillInput.data).readComponent(component);
       return component;
     });
 
     return await measureIoSubtask('deserialize data', () async {
-      compiler.reporter
-          .log('Reading data from ${compiler.options.readDataUri}');
-      api.Input<List<int>> dataInput = await compiler.provider.readFromUri(
-          compiler.options.readDataUri,
-          inputKind: api.InputKind.binary);
+      _reporter.log('Reading data from ${_options.readDataUri}');
+      api.Input<List<int>> dataInput = await _provider
+          .readFromUri(_options.readDataUri, inputKind: api.InputKind.binary);
       DataSource source = new BinarySourceImpl(dataInput.data);
-      return deserializeGlobalTypeInferenceResults(
-          compiler.options,
-          compiler.reporter,
-          compiler.environment,
-          compiler.abstractValueStrategy,
-          component,
-          source);
+      return deserializeGlobalTypeInferenceResults(_options, _reporter,
+          environment, abstractValueStrategy, component, source);
     });
   }
+
+  void serializeCodegen(
+      BackendStrategy backendStrategy, CodegenResults codegenResults) {
+    GlobalTypeInferenceResults globalTypeInferenceResults =
+        codegenResults.globalTypeInferenceResults;
+    JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
+    int shard = _options.codegenShard;
+    int shards = _options.codegenShards;
+    Map<MemberEntity, CodegenResult> results = {};
+    int index = 0;
+    EntityWriter entityWriter =
+        backendStrategy.forEachCodegenMember((MemberEntity member) {
+      if (index % shards == shard) {
+        CodegenResult codegenResult = codegenResults.getCodegenResults(member);
+        results[member] = codegenResult;
+      }
+      index++;
+    });
+    measureSubtask('serialize codegen', () {
+      Uri uri = Uri.parse('${_options.writeCodegenUri}$shard');
+      api.BinaryOutputSink dataOutput = _outputProvider.createBinarySink(uri);
+      DataSink sink = new BinarySink(new BinaryOutputSinkAdapter(dataOutput));
+      _reporter.log('Writing data to ${uri}');
+      sink.registerEntityWriter(entityWriter);
+      sink.registerCodegenWriter(new CodegenWriterImpl(closedWorld));
+      sink.writeMemberMap(
+          results, (CodegenResult result) => result.writeToDataSink(sink));
+      sink.close();
+    });
+  }
+
+  Future<CodegenResults> deserializeCodegen(
+      BackendStrategy backendStrategy,
+      GlobalTypeInferenceResults globalTypeInferenceResults,
+      CodegenInputs codegenInputs) async {
+    int shards = _options.codegenShards;
+    JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
+    Map<MemberEntity, CodegenResult> results = {};
+    for (int shard = 0; shard < shards; shard++) {
+      Uri uri = Uri.parse('${_options.readCodegenUri}$shard');
+      await measureIoSubtask('deserialize codegen', () async {
+        _reporter.log('Reading data from ${uri}');
+        api.Input<List<int>> dataInput =
+            await _provider.readFromUri(uri, inputKind: api.InputKind.binary);
+        DataSource source = new BinarySourceImpl(dataInput.data);
+        backendStrategy.prepareCodegenReader(source);
+        Map<MemberEntity, CodegenResult> codegenResults =
+            source.readMemberMap(() {
+          List<ModularName> modularNames = [];
+          List<ModularExpression> modularExpressions = [];
+          CodegenReader reader = new CodegenReaderImpl(
+              closedWorld, modularNames, modularExpressions);
+          source.registerCodegenReader(reader);
+          CodegenResult result = CodegenResult.readFromDataSource(
+              source, modularNames, modularExpressions);
+          source.deregisterCodegenReader(reader);
+          return result;
+        });
+        _reporter.log('Read ${codegenResults.length} members from ${uri}');
+        results.addAll(codegenResults);
+      });
+    }
+    return new DeserializedCodegenResults(
+        globalTypeInferenceResults, codegenInputs, results);
+  }
 }
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 67cc980..f0f64ff 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -12,6 +12,7 @@
 import '../common_elements.dart';
 import '../constants/constant_system.dart' as constant_system;
 import '../constants/values.dart';
+import '../deferred_load.dart';
 import '../dump_info.dart';
 import '../elements/entities.dart';
 import '../elements/jumps.dart';
@@ -151,6 +152,7 @@
   StackFrame _currentFrame;
 
   final FunctionInlineCache _inlineCache;
+  final InlineDataCache _inlineDataCache;
 
   KernelSsaGraphBuilder(
       this.options,
@@ -167,7 +169,8 @@
       this._tracer,
       this._rtiEncoder,
       this._sourceInformationStrategy,
-      this._inlineCache)
+      this._inlineCache,
+      this._inlineDataCache)
       : this.targetElement = _effectiveTargetElementFor(_initialTargetElement),
         this._closureDataLookup = closedWorld.closureDataLookup {
     _enterFrame(targetElement, null);
@@ -620,17 +623,11 @@
     return _elementMap.getDartType(type);
   }
 
-  /// Pops the most recent instruction from the stack and 'boolifies' it.
-  ///
-  /// Boolification is checking if the value is '=== true'.
+  /// Pops the most recent instruction from the stack and ensures that it is a
+  /// non-null bool.
   HInstruction popBoolified() {
     HInstruction value = pop();
-    if (_typeBuilder.checkOrTrustTypes) {
-      return _typeBuilder.potentiallyCheckOrTrustTypeOfCondition(value);
-    }
-    HInstruction result = new HBoolify(value, _abstractValueDomain.boolType);
-    add(result);
-    return result;
+    return _typeBuilder.potentiallyCheckOrTrustTypeOfCondition(value);
   }
 
   /// Extend current method parameters with parameters for the class type
@@ -1364,7 +1361,6 @@
     }
 
     JGeneratorBody body = _elementMap.getGeneratorBody(function);
-    closedWorld.outputUnitData.registerColocatedMembers(function, body);
     push(new HInvokeGeneratorBody(
         body,
         inputs,
@@ -1740,11 +1736,13 @@
         _sourceInformationBuilder.buildGet(node);
     if (!closedWorld.outputUnitData
         .hasOnlyNonDeferredImportPathsToConstant(targetElement, value)) {
+      OutputUnit outputUnit =
+          closedWorld.outputUnitData.outputUnitForConstant(value);
+      ConstantValue deferredConstant =
+          new DeferredGlobalConstantValue(value, outputUnit);
+      registry.registerConstantUse(new ConstantUse.deferred(deferredConstant));
       stack.add(graph.addDeferredConstant(
-          value,
-          closedWorld.outputUnitData.outputUnitForConstant(value),
-          sourceInformation,
-          closedWorld));
+          deferredConstant, sourceInformation, closedWorld));
     } else {
       stack.add(graph.addConstant(value, closedWorld,
           sourceInformation: sourceInformation));
@@ -2403,8 +2401,8 @@
           expressionInstruction,
           localsHandler.substInContext(type),
           node.isTypeError
-              ? HTypeConversion.CHECKED_MODE_CHECK
-              : HTypeConversion.CAST_TYPE_CHECK,
+              ? HTypeConversion.TYPE_CHECK
+              : HTypeConversion.CAST_CHECK,
           sourceInformation: sourceInformation);
       if (converted != expressionInstruction) {
         add(converted);
@@ -3303,15 +3301,20 @@
         push(new HStatic(field, _typeInferenceMap.getInferredTypeOf(field),
             sourceInformation));
       } else if (fieldData.isEffectivelyConstant) {
-        var unit = closedWorld.outputUnitData.outputUnitForMember(field);
+        OutputUnit outputUnit =
+            closedWorld.outputUnitData.outputUnitForMember(field);
         // TODO(sigmund): this is not equivalent to what the old FE does: if
         // there is no prefix the old FE wouldn't treat this in any special
         // way. Also, if the prefix points to a constant in the main output
         // unit, the old FE would still generate a deferred wrapper here.
         if (!closedWorld.outputUnitData
             .hasOnlyNonDeferredImportPaths(targetElement, field)) {
+          ConstantValue deferredConstant = new DeferredGlobalConstantValue(
+              fieldData.initialValue, outputUnit);
+          registry
+              .registerConstantUse(new ConstantUse.deferred(deferredConstant));
           stack.add(graph.addDeferredConstant(
-              fieldData.initialValue, unit, sourceInformation, closedWorld));
+              deferredConstant, sourceInformation, closedWorld));
         } else {
           stack.add(graph.addConstant(fieldData.initialValue, closedWorld,
               sourceInformation: sourceInformation));
@@ -3816,9 +3819,9 @@
               "Expected 1-2 argument, actual: $arguments."));
       HInstruction lengthInput = arguments.first;
       if (lengthInput.isNumber(_abstractValueDomain).isPotentiallyFalse) {
-        HTypeConversion conversion = new HTypeConversion(
+        HPrimitiveCheck conversion = new HPrimitiveCheck(
             _commonElements.numType,
-            HTypeConversion.ARGUMENT_TYPE_CHECK,
+            HPrimitiveCheck.ARGUMENT_TYPE_CHECK,
             _abstractValueDomain.numType,
             lengthInput,
             sourceInformation);
@@ -5552,6 +5555,7 @@
 
     // Bail out early if the inlining decision is in the cache and we can't
     // inline (no need to check the hard constraints).
+    if (_inlineCache.markedAsNoInline(function)) return false;
     bool cachedCanBeInlined =
         _inlineCache.canInline(function, insideLoop: insideLoop);
     if (cachedCanBeInlined == false) return false;
@@ -5612,26 +5616,22 @@
       return true;
     }
 
-    bool doesNotContainCode() {
+    bool doesNotContainCode(InlineData inlineData) {
       // A function with size 1 does not contain any code.
-      return InlineWeeder.canBeInlined(_elementMap, function, 1,
-          enableUserAssertions: options.enableUserAssertions);
+      return inlineData.canBeInlined(maxInliningNodes: 1);
     }
 
-    bool reductiveHeuristic() {
+    bool reductiveHeuristic(InlineData inlineData) {
       // The call is on a path which is executed rarely, so inline only if it
       // does not make the program larger.
       if (_isCalledOnce(function)) {
-        return InlineWeeder.canBeInlined(_elementMap, function, null,
-            enableUserAssertions: options.enableUserAssertions);
+        return inlineData.canBeInlined();
       }
-      if (InlineReductiveWeeder.canBeInlined(
-          _elementMap, function, providedArguments.length,
-          enableUserAssertions: options.enableUserAssertions,
-          omitImplicitCasts: options.omitImplicitChecks)) {
+      if (inlineData.canBeInlinedReductive(
+          argumentCount: providedArguments.length)) {
         return true;
       }
-      return doesNotContainCode();
+      return doesNotContainCode(inlineData);
     }
 
     bool heuristicSayGoodToGo() {
@@ -5645,13 +5645,16 @@
       bool hasOnlyNonDeferredImportPaths = closedWorld.outputUnitData
           .hasOnlyNonDeferredImportPaths(_initialTargetElement, function);
 
+      InlineData inlineData =
+          _inlineDataCache.getInlineData(_elementMap, function);
+
       if (!hasOnlyNonDeferredImportPaths) {
-        return doesNotContainCode();
+        return doesNotContainCode(inlineData);
       }
 
       // Do not inline code that is rarely executed unless it reduces size.
       if (_inExpressionOfThrow || _inLazyInitializerExpression) {
-        return reductiveHeuristic();
+        return reductiveHeuristic(inlineData);
       }
 
       if (cachedCanBeInlined == true) {
@@ -5659,10 +5662,7 @@
         // if we can inline this method regardless of size.
         String reason;
         assert(
-            (reason = InlineWeeder.cannotBeInlinedReason(
-                    _elementMap, function, null,
-                    allowLoops: true,
-                    enableUserAssertions: options.enableUserAssertions)) ==
+            (reason = inlineData.cannotBeInlinedReason(allowLoops: true)) ==
                 null,
             failedAt(function, "Cannot inline $function: $reason"));
         return true;
@@ -5691,10 +5691,8 @@
         allowLoops = true;
       }
 
-      bool canInline = InlineWeeder.canBeInlined(
-          _elementMap, function, maxInliningNodes,
-          allowLoops: allowLoops,
-          enableUserAssertions: options.enableUserAssertions);
+      bool canInline = inlineData.canBeInlined(
+          maxInliningNodes: maxInliningNodes, allowLoops: allowLoops);
       if (markedTryInline) {
         if (canInline) {
           _inlineCache.markAsInlinable(function, insideLoop: true);
@@ -5710,7 +5708,12 @@
         if (canInline) {
           _inlineCache.markAsInlinable(function, insideLoop: insideLoop);
         } else {
-          _inlineCache.markAsNonInlinable(function, insideLoop: insideLoop);
+          if (_isFunctionCalledOnce(function)) {
+            // TODO(34203): We can't update the decision due to imprecision in
+            // the calledOnce data, described in Issue 34203.
+          } else {
+            _inlineCache.markAsNonInlinable(function, insideLoop: insideLoop);
+          }
         }
       }
       return canInline;
@@ -6110,8 +6113,6 @@
 
   /// Generates type tests for the parameters of the inlined function.
   void _potentiallyCheckInlinedParameterTypes(FunctionEntity function) {
-    if (!_typeBuilder.checkOrTrustTypes) return;
-
     // TODO(sra): Incorporate properties of call site to help determine which
     // type parameters and value parameters need to be checked.
     bool trusted = false;
@@ -6217,517 +6218,10 @@
       this.oldLocalsHandler,
       this.inTryStatement,
       this.allFunctionsCalledOnce);
-}
-
-class InlineWeeder extends ir.Visitor {
-  // Invariant: *INSIDE_LOOP* > *OUTSIDE_LOOP*
-  static const INLINING_NODES_OUTSIDE_LOOP = 15;
-  static const INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR = 3;
-  static const INLINING_NODES_INSIDE_LOOP = 34;
-  static const INLINING_NODES_INSIDE_LOOP_ARG_FACTOR = 4;
-
-  static bool canBeInlined(
-      JsToElementMap elementMap, FunctionEntity function, int maxInliningNodes,
-      {bool allowLoops: false, bool enableUserAssertions: null}) {
-    return cannotBeInlinedReason(elementMap, function, maxInliningNodes,
-            allowLoops: allowLoops,
-            enableUserAssertions: enableUserAssertions) ==
-        null;
-  }
-
-  static String cannotBeInlinedReason(
-      JsToElementMap elementMap, FunctionEntity function, int maxInliningNodes,
-      {bool allowLoops: false, bool enableUserAssertions: null}) {
-    InlineWeeder visitor =
-        new InlineWeeder(maxInliningNodes, allowLoops, enableUserAssertions);
-    ir.FunctionNode node = getFunctionNode(elementMap, function);
-    node.accept(visitor);
-    if (function.isConstructor) {
-      MemberDefinition definition = elementMap.getMemberDefinition(function);
-      ir.Node node = definition.node;
-      if (node is ir.Constructor) {
-        node.initializers.forEach((n) => n.accept(visitor));
-      }
-    }
-    return visitor.tooDifficultReason;
-  }
-
-  final int maxInliningNodes; // `null` for unbounded.
-  final bool allowLoops;
-  final bool enableUserAssertions;
-
-  bool seenReturn = false;
-  int nodeCount = 0;
-  String tooDifficultReason;
-  bool get tooDifficult => tooDifficultReason != null;
-
-  InlineWeeder(
-      this.maxInliningNodes, this.allowLoops, this.enableUserAssertions);
-
-  bool registerNode() {
-    if (maxInliningNodes == null) return true;
-    if (nodeCount++ > maxInliningNodes) {
-      tooDifficultReason ??= 'too many nodes';
-      return false;
-    }
-    return true;
-  }
 
   @override
-  defaultNode(ir.Node node) {
-    if (tooDifficult) return;
-    if (!registerNode()) return;
-    if (seenReturn) {
-      tooDifficultReason ??= 'code after return';
-      return;
-    }
-    node.visitChildren(this);
-  }
-
-  @override
-  visitReturnStatement(ir.ReturnStatement node) {
-    if (!registerNode()) return;
-    if (seenReturn) {
-      tooDifficultReason ??= 'code after return';
-      return;
-    }
-    node.visitChildren(this);
-    seenReturn = true;
-  }
-
-  @override
-  visitThrow(ir.Throw node) {
-    if (!registerNode()) return;
-    if (seenReturn) {
-      tooDifficultReason ??= 'code after return';
-      return;
-    }
-    node.visitChildren(this);
-  }
-
-  _handleLoop(ir.Node node) {
-    // It's actually not difficult to inline a method with a loop, but our
-    // measurements show that it's currently better to not inline a method that
-    // contains a loop.
-    if (!allowLoops) tooDifficultReason ??= 'loop';
-    node.visitChildren(this);
-  }
-
-  @override
-  visitForStatement(ir.ForStatement node) {
-    _handleLoop(node);
-  }
-
-  @override
-  visitForInStatement(ir.ForInStatement node) {
-    _handleLoop(node);
-  }
-
-  @override
-  visitWhileStatement(ir.WhileStatement node) {
-    _handleLoop(node);
-  }
-
-  @override
-  visitDoStatement(ir.DoStatement node) {
-    _handleLoop(node);
-  }
-
-  @override
-  visitTryCatch(ir.TryCatch node) {
-    tooDifficultReason ??= 'try';
-  }
-
-  @override
-  visitTryFinally(ir.TryFinally node) {
-    tooDifficultReason ??= 'try';
-  }
-
-  @override
-  visitFunctionExpression(ir.FunctionExpression node) {
-    if (!registerNode()) return;
-    tooDifficultReason ??= 'closure';
-  }
-
-  @override
-  visitFunctionDeclaration(ir.FunctionDeclaration node) {
-    if (!registerNode()) return;
-    tooDifficultReason ??= 'closure';
-  }
-
-  @override
-  visitFunctionNode(ir.FunctionNode node) {
-    if (node.asyncMarker != ir.AsyncMarker.Sync) {
-      tooDifficultReason ??= 'async/await';
-      return;
-    }
-    node.visitChildren(this);
-  }
-
-  @override
-  visitConditionalExpression(ir.ConditionalExpression node) {
-    // Heuristic: In "parameter ? A : B" there is a high probability that
-    // parameter is a constant. Assuming the parameter is constant, we can
-    // compute a count that is bounded by the largest arm rather than the sum of
-    // both arms.
-    ir.Expression condition = node.condition;
-    condition.accept(this);
-    if (tooDifficult) return;
-    int commonPrefixCount = nodeCount;
-
-    node.then.accept(this);
-    if (tooDifficult) return;
-    int thenCount = nodeCount - commonPrefixCount;
-
-    nodeCount = commonPrefixCount;
-    node.otherwise.accept(this);
-    if (tooDifficult) return;
-    int elseCount = nodeCount - commonPrefixCount;
-
-    nodeCount = commonPrefixCount + thenCount + elseCount;
-    if (condition is ir.VariableGet &&
-        condition.variable.parent is ir.FunctionNode) {
-      nodeCount =
-          commonPrefixCount + (thenCount > elseCount ? thenCount : elseCount);
-    }
-    // This is last so that [tooDifficult] is always updated.
-    if (!registerNode()) return;
-  }
-
-  @override
-  visitAssertInitializer(ir.AssertInitializer node) {
-    if (!enableUserAssertions) return;
-    node.visitChildren(this);
-  }
-
-  @override
-  visitAssertStatement(ir.AssertStatement node) {
-    if (!enableUserAssertions) return;
-    defaultNode(node);
-  }
-}
-
-/// Determines if inlining a function is very likely to reduce code size.
-class InlineReductiveWeeder extends ir.Visitor {
-  // We allow the body to be a single function call that does not have any more
-  // inputs than the inlinee.
-  //
-  // We allow the body to be the return of an 'eligible' constant. A constant is
-  // 'eligible' if it is not large (e.g. a long string).
-  //
-  // We skip 'e as{TypeError} T' when the checks are omitted.
-  //
-  //
-  // TODO(sra): Consider slightly expansive simple constructors where all we
-  // gain is a 'new' keyword, e.g. `new X.Foo(a)` vs `X.Foo$(a)`.
-  //
-  // TODO(25231): Make larger string constants eligible by sharing references.
-
-  static bool canBeInlined(
-      JsToElementMap elementMap, FunctionEntity function, int argumentCount,
-      {bool enableUserAssertions: null, bool omitImplicitCasts: null}) {
-    return cannotBeInlinedReason(elementMap, function, argumentCount,
-            enableUserAssertions: enableUserAssertions,
-            omitImplicitCasts: omitImplicitCasts) ==
-        null;
-  }
-
-  static String cannotBeInlinedReason(
-      JsToElementMap elementMap, FunctionEntity function, int argumentCount,
-      {bool enableUserAssertions: null, bool omitImplicitCasts: null}) {
-    assert(enableUserAssertions != null);
-    assert(omitImplicitCasts != null);
-    var visitor = new InlineReductiveWeeder(
-        argumentCount, enableUserAssertions, omitImplicitCasts);
-    ir.FunctionNode node = getFunctionNode(elementMap, function);
-    if (function.isConstructor) {
-      return visitor.tooDifficultReason ??= 'constructor';
-    }
-    node.accept(visitor);
-    return visitor.tooDifficultReason;
-  }
-
-  final int argumentCount;
-  final bool enableUserAssertions;
-  final bool omitImplicitCasts;
-  final int maxInliningNodes;
-
-  bool seenReturn = false;
-  int nodeCount = 0;
-  int callCount = 0;
-  String tooDifficultReason;
-  bool get tooDifficult => tooDifficultReason != null;
-
-  InlineReductiveWeeder(
-      this.argumentCount, this.enableUserAssertions, this.omitImplicitCasts)
-      :
-        // Node budget that covers one call and the passed-in arguments.
-        // The +1 also allows a top-level zero-argument to be inlined if it
-        // returns a constant.
-        maxInliningNodes = argumentCount + 1;
-
-  bool registerNode() {
-    if (++nodeCount > maxInliningNodes) {
-      tooDifficultReason ??= 'too many nodes';
-      return false;
-    }
-    return true;
-  }
-
-  bool registerCall() {
-    if (++callCount > 1) {
-      tooDifficultReason ??= 'too many calls';
-      return false;
-    }
-    return true;
-  }
-
-  @override
-  defaultNode(ir.Node node) {
-    if (tooDifficult) return;
-    if (seenReturn) {
-      tooDifficultReason ??= 'code after return';
-      return;
-    }
-    if (!registerNode()) return;
-    node.visitChildren(this);
-  }
-
-  @override
-  visitReturnStatement(ir.ReturnStatement node) {
-    if (seenReturn) {
-      tooDifficultReason ??= 'code after return';
-      return;
-    }
-    node.visitChildren(this);
-    seenReturn = true;
-  }
-
-  @override
-  visitThrow(ir.Throw node) {
-    tooDifficultReason ??= 'throw';
-  }
-
-  @override
-  visitEmptyStatement(ir.EmptyStatement node) {}
-
-  @override
-  visitExpressionStatement(ir.ExpressionStatement node) {
-    node.visitChildren(this);
-  }
-
-  @override
-  visitBlock(ir.Block node) {
-    node.visitChildren(this);
-  }
-
-  @override
-  visitStringLiteral(ir.StringLiteral node) {
-    registerNode();
-    // Avoid copying long strings into call site.
-    if (node.value.length > 14) tooDifficultReason ??= 'long string';
-  }
-
-  @override
-  visitPropertyGet(ir.PropertyGet node) {
-    if (!registerCall()) return;
-    if (!registerNode()) return;
-    node.receiver.accept(this);
-  }
-
-  @override
-  visitDirectPropertyGet(ir.DirectPropertyGet node) {
-    if (!registerCall()) return;
-    if (!registerNode()) return;
-    node.receiver.accept(this);
-  }
-
-  @override
-  visitPropertySet(ir.PropertySet node) {
-    if (!registerCall()) return;
-    if (!registerNode()) return;
-    node.receiver.accept(this);
-    node.value.accept(this);
-  }
-
-  @override
-  visitDirectPropertySet(ir.DirectPropertySet node) {
-    if (!registerCall()) return;
-    if (!registerNode()) return;
-    node.receiver.accept(this);
-    node.value.accept(this);
-  }
-
-  @override
-  visitVariableGet(ir.VariableGet node) {
-    registerNode();
-  }
-
-  @override
-  visitThisExpression(ir.ThisExpression node) {
-    registerNode();
-  }
-
-  @override
-  visitStaticGet(ir.StaticGet node) {
-    // Assume lazy-init static, loaded via a call: `$.$get$foo()`.
-    if (!registerCall()) return;
-    registerNode();
-  }
-
-  @override
-  visitConstructorInvocation(ir.ConstructorInvocation node) {
-    if (node.isConst) {
-      // A const constructor call compiles to a constant pool reference.
-      registerNode();
-      return;
-    }
-    if (!registerCall()) return;
-    if (!registerNode()) return;
-    _processArguments(node.arguments, node.target?.function);
-  }
-
-  @override
-  visitStaticInvocation(ir.StaticInvocation node) {
-    if (node.isConst) {
-      tooDifficultReason ??= 'external const constructor';
-      return;
-    }
-    if (!registerCall()) return;
-    if (!registerNode()) return;
-    _processArguments(node.arguments, node.target?.function);
-  }
-
-  @override
-  visitMethodInvocation(ir.MethodInvocation node) {
-    if (!registerCall()) return;
-    if (!registerNode()) return;
-    node.receiver.accept(this);
-    _processArguments(node.arguments, null);
-  }
-
-  _processArguments(ir.Arguments arguments, ir.FunctionNode target) {
-    if (arguments.types.isNotEmpty) {
-      tooDifficultReason ??= 'type arguments';
-      return;
-    }
-    int count = arguments.positional.length + arguments.named.length;
-    if (count > argumentCount) {
-      tooDifficultReason ??= 'increasing arguments';
-      return;
-    }
-
-    if (target != null) {
-      // Disallow defaulted optional arguments since they will be passed
-      // explicitly.
-      if (target.positionalParameters.length + target.namedParameters.length >
-          count) {
-        tooDifficultReason ??= 'argument defaulting';
-        return;
-      }
-    }
-
-    for (var e in arguments.positional) {
-      e.accept(this);
-      if (tooDifficult) return;
-    }
-    for (var e in arguments.named) {
-      e.value.accept(this);
-      if (tooDifficult) return;
-    }
-  }
-
-  @override
-  visitAsExpression(ir.AsExpression node) {
-    if (node.isTypeError && omitImplicitCasts) {
-      node.operand.accept(this);
-      return;
-    }
-    tooDifficultReason ??= 'cast';
-  }
-
-  @override
-  visitVariableDeclaration(ir.VariableDeclaration node) {
-    // A local variable is an alias for the initializer expression.
-    if (node.initializer != null) {
-      --nodeCount; // discount one reference to the variable.
-      node.initializer.accept(this);
-      return;
-    }
-  }
-
-  @override
-  visitForStatement(ir.ForStatement node) {
-    tooDifficultReason ??= 'loop';
-  }
-
-  @override
-  visitForInStatement(ir.ForInStatement node) {
-    tooDifficultReason ??= 'loop';
-  }
-
-  @override
-  visitWhileStatement(ir.WhileStatement node) {
-    tooDifficultReason ??= 'loop';
-  }
-
-  @override
-  visitDoStatement(ir.DoStatement node) {
-    tooDifficultReason ??= 'loop';
-  }
-
-  @override
-  visitTryCatch(ir.TryCatch node) {
-    tooDifficultReason ??= 'try';
-  }
-
-  @override
-  visitTryFinally(ir.TryFinally node) {
-    tooDifficultReason ??= 'try';
-  }
-
-  @override
-  visitIfStatement(ir.IfStatement node) {
-    tooDifficultReason ??= 'if';
-  }
-
-  @override
-  visitFunctionExpression(ir.FunctionExpression node) {
-    tooDifficultReason ??= 'closure';
-  }
-
-  @override
-  visitFunctionDeclaration(ir.FunctionDeclaration node) {
-    tooDifficultReason ??= 'closure';
-  }
-
-  @override
-  visitFunctionNode(ir.FunctionNode node) {
-    if (node.asyncMarker != ir.AsyncMarker.Sync) {
-      tooDifficultReason ??= 'async/await';
-      return;
-    }
-    // TODO(sra): Cost of parameter checking?
-    node.body.accept(this);
-  }
-
-  @override
-  visitConditionalExpression(ir.ConditionalExpression node) {
-    if (!registerNode()) return;
-    node.visitChildren(this);
-  }
-
-  @override
-  visitAssertInitializer(ir.AssertInitializer node) {
-    if (!enableUserAssertions) return;
-    node.visitChildren(this);
-  }
-
-  @override
-  visitAssertStatement(ir.AssertStatement node) {
-    if (!enableUserAssertions) return;
-    defaultNode(node);
-  }
+  String toString() => 'KernelInliningState($function,'
+      'allFunctionsCalledOnce=$allFunctionsCalledOnce)';
 }
 
 /// Class in charge of building try, catch and/or finally blocks. This handles
@@ -7062,3 +6556,621 @@
   @override
   String toString() => 'StaticType($type,$relation)';
 }
+
+class InlineData {
+  bool isConstructor = false;
+  bool codeAfterReturn = false;
+  bool hasLoop = false;
+  bool hasClosure = false;
+  bool hasTry = false;
+  bool hasAsyncAwait = false;
+  bool hasThrow = false;
+  bool hasLongString = false;
+  bool hasExternalConstantConstructorCall = false;
+  bool hasTypeArguments = false;
+  bool hasArgumentDefaulting = false;
+  bool hasCast = false;
+  bool hasIf = false;
+  List<int> argumentCounts = [];
+  int regularNodeCount = 0;
+  int callCount = 0;
+  int reductiveNodeCount = 0;
+
+  InlineData();
+
+  InlineData.internal(
+      {this.codeAfterReturn,
+      this.hasLoop,
+      this.hasClosure,
+      this.hasTry,
+      this.hasAsyncAwait,
+      this.hasThrow,
+      this.hasLongString,
+      this.regularNodeCount,
+      this.callCount});
+
+  bool canBeInlined({int maxInliningNodes, bool allowLoops: false}) {
+    return cannotBeInlinedReason(
+            maxInliningNodes: maxInliningNodes, allowLoops: allowLoops) ==
+        null;
+  }
+
+  String cannotBeInlinedReason({int maxInliningNodes, bool allowLoops: false}) {
+    if (hasLoop && !allowLoops) {
+      return 'loop';
+    } else if (hasTry) {
+      return 'try';
+    } else if (hasClosure) {
+      return 'closure';
+    } else if (codeAfterReturn) {
+      return 'code after return';
+    } else if (hasAsyncAwait) {
+      return 'async/await';
+    } else if (maxInliningNodes != null &&
+        regularNodeCount - 1 > maxInliningNodes) {
+      return 'too many nodes (${regularNodeCount - 1}>$maxInliningNodes)';
+    }
+    return null;
+  }
+
+  bool canBeInlinedReductive({int argumentCount}) {
+    return cannotBeInlinedReductiveReason(argumentCount: argumentCount) == null;
+  }
+
+  String cannotBeInlinedReductiveReason({int argumentCount}) {
+    if (hasTry) {
+      return 'try';
+    } else if (hasClosure) {
+      return 'closure';
+    } else if (codeAfterReturn) {
+      return 'code after return';
+    } else if (hasAsyncAwait) {
+      return 'async/await';
+    } else if (callCount > 1) {
+      return 'too many calls';
+    } else if (hasThrow) {
+      return 'throw';
+    } else if (hasLongString) {
+      return 'long string';
+    } else if (hasExternalConstantConstructorCall) {
+      return 'external const constructor';
+    } else if (hasTypeArguments) {
+      return 'type arguments';
+    } else if (hasArgumentDefaulting) {
+      return 'argument defaulting';
+    } else if (hasCast) {
+      return 'cast';
+    } else if (hasIf) {
+      return 'if';
+    } else if (isConstructor) {
+      return 'constructor';
+    }
+    for (int count in argumentCounts) {
+      if (count > argumentCount) {
+        return 'increasing arguments';
+      }
+    }
+    // Node budget that covers one call and the passed-in arguments.
+    // The +1 also allows a top-level zero-argument to be inlined if it
+    // returns a constant.
+    int maxInliningNodes = argumentCount + 1;
+    if (reductiveNodeCount > maxInliningNodes) {
+      return 'too many nodes (${reductiveNodeCount}>$maxInliningNodes)';
+    }
+
+    return null;
+  }
+
+  @override
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.write('InlineData(');
+    String comma = '';
+    if (isConstructor) {
+      sb.write('isConstructor');
+      comma = ',';
+    }
+    if (codeAfterReturn) {
+      sb.write(comma);
+      sb.write('codeAfterReturn');
+      comma = ',';
+    }
+    if (hasLoop) {
+      sb.write(comma);
+      sb.write('hasLoop');
+      comma = ',';
+    }
+    if (hasClosure) {
+      sb.write(comma);
+      sb.write('hasClosure');
+      comma = ',';
+    }
+    if (hasTry) {
+      sb.write(comma);
+      sb.write('hasTry');
+      comma = ',';
+    }
+    if (hasAsyncAwait) {
+      sb.write(comma);
+      sb.write('hasAsyncAwait');
+      comma = ',';
+    }
+    if (hasThrow) {
+      sb.write(comma);
+      sb.write('hasThrow');
+      comma = ',';
+    }
+    if (hasLongString) {
+      sb.write(comma);
+      sb.write('hasLongString');
+      comma = ',';
+    }
+    if (hasExternalConstantConstructorCall) {
+      sb.write(comma);
+      sb.write('hasExternalConstantConstructorCall');
+      comma = ',';
+    }
+    if (hasTypeArguments) {
+      sb.write(comma);
+      sb.write('hasTypeArguments');
+      comma = ',';
+    }
+    if (hasArgumentDefaulting) {
+      sb.write(comma);
+      sb.write('hasArgumentDefaulting');
+      comma = ',';
+    }
+    if (hasCast) {
+      sb.write(comma);
+      sb.write('hasCast');
+      comma = ',';
+    }
+    if (hasIf) {
+      sb.write(comma);
+      sb.write('hasIf');
+      comma = ',';
+    }
+    if (argumentCounts.isNotEmpty) {
+      sb.write(comma);
+      sb.write('argumentCounts={${argumentCounts.join(',')}}');
+      comma = ',';
+    }
+    sb.write(comma);
+    sb.write('regularNodeCount=$regularNodeCount,');
+    sb.write('callCount=$callCount,');
+    sb.write('reductiveNodeCount=$reductiveNodeCount');
+    sb.write(')');
+    return sb.toString();
+  }
+}
+
+class InlineDataCache {
+  final bool enableUserAssertions;
+  final bool omitImplicitCasts;
+
+  InlineDataCache(
+      {this.enableUserAssertions: false, this.omitImplicitCasts: false});
+
+  Map<FunctionEntity, InlineData> _cache = {};
+
+  InlineData getInlineData(JsToElementMap elementMap, FunctionEntity function) {
+    return _cache[function] ??= InlineWeeder.computeInlineData(
+        elementMap, function,
+        enableUserAssertions: enableUserAssertions,
+        omitImplicitCasts: omitImplicitCasts);
+  }
+}
+
+class InlineWeeder extends ir.Visitor {
+  // Invariant: *INSIDE_LOOP* > *OUTSIDE_LOOP*
+  static const INLINING_NODES_OUTSIDE_LOOP = 15;
+  static const INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR = 3;
+  static const INLINING_NODES_INSIDE_LOOP = 34;
+  static const INLINING_NODES_INSIDE_LOOP_ARG_FACTOR = 4;
+
+  final bool enableUserAssertions;
+  final bool omitImplicitCasts;
+
+  final InlineData data = new InlineData();
+  bool seenReturn = false;
+
+  /// Whether node-count is collector to determine if a function can be
+  /// inlined.
+  bool countRegularNode = true;
+
+  /// Whether node-count is collected to determine if inlining a function is
+  /// very likely to reduce code size.
+  ///
+  /// For the reductive analysis:
+  /// We allow the body to be a single function call that does not have any more
+  /// inputs than the inlinee.
+  ///
+  /// We allow the body to be the return of an 'eligible' constant. A constant
+  /// is 'eligible' if it is not large (e.g. a long string).
+  ///
+  /// We skip 'e as{TypeError} T' when the checks are omitted.
+  //
+  // TODO(sra): Consider slightly expansive simple constructors where all we
+  // gain is a 'new' keyword, e.g. `new X.Foo(a)` vs `X.Foo$(a)`.
+  //
+  // TODO(25231): Make larger string constants eligible by sharing references.
+  bool countReductiveNode = true;
+
+  InlineWeeder(
+      {this.enableUserAssertions: false, this.omitImplicitCasts: false});
+
+  static InlineData computeInlineData(
+      JsToElementMap elementMap, FunctionEntity function,
+      {bool enableUserAssertions: false, bool omitImplicitCasts: false}) {
+    InlineWeeder visitor = new InlineWeeder(
+        enableUserAssertions: enableUserAssertions,
+        omitImplicitCasts: omitImplicitCasts);
+    ir.FunctionNode node = getFunctionNode(elementMap, function);
+    node.accept(visitor);
+    if (function.isConstructor) {
+      visitor.data.isConstructor = true;
+      MemberDefinition definition = elementMap.getMemberDefinition(function);
+      visitor.skipReductiveNodes(() {
+        ir.Node node = definition.node;
+        if (node is ir.Constructor) {
+          visitor.visitList(node.initializers);
+        }
+      });
+    }
+    return visitor.data;
+  }
+
+  void skipRegularNodes(void f()) {
+    bool oldCountRegularNode = countRegularNode;
+    countRegularNode = false;
+    f();
+    countRegularNode = oldCountRegularNode;
+  }
+
+  void skipReductiveNodes(void f()) {
+    bool oldCountReductiveNode = countReductiveNode;
+    countReductiveNode = false;
+    f();
+    countReductiveNode = oldCountReductiveNode;
+  }
+
+  void registerRegularNode() {
+    if (countRegularNode) {
+      data.regularNodeCount++;
+      if (seenReturn) {
+        data.codeAfterReturn = true;
+      }
+    }
+  }
+
+  void registerReductiveNode() {
+    if (countReductiveNode) {
+      data.reductiveNodeCount++;
+      if (seenReturn) {
+        data.codeAfterReturn = true;
+      }
+    }
+  }
+
+  void unregisterReductiveNode() {
+    if (countReductiveNode) {
+      data.reductiveNodeCount--;
+    }
+  }
+
+  void visit(ir.Node node) => node?.accept(this);
+
+  void visitList(List<ir.Node> nodes) {
+    for (ir.Node node in nodes) {
+      visit(node);
+    }
+  }
+
+  @override
+  defaultNode(ir.Node node) {
+    registerRegularNode();
+    registerReductiveNode();
+    node.visitChildren(this);
+  }
+
+  @override
+  visitReturnStatement(ir.ReturnStatement node) {
+    registerRegularNode();
+    node.visitChildren(this);
+    seenReturn = true;
+  }
+
+  @override
+  visitThrow(ir.Throw node) {
+    registerRegularNode();
+    data.hasThrow = true;
+    node.visitChildren(this);
+  }
+
+  _handleLoop(ir.Node node) {
+    // It's actually not difficult to inline a method with a loop, but our
+    // measurements show that it's currently better to not inline a method that
+    // contains a loop.
+    data.hasLoop = true;
+    node.visitChildren(this);
+  }
+
+  @override
+  visitForStatement(ir.ForStatement node) {
+    _handleLoop(node);
+  }
+
+  @override
+  visitForInStatement(ir.ForInStatement node) {
+    _handleLoop(node);
+  }
+
+  @override
+  visitWhileStatement(ir.WhileStatement node) {
+    _handleLoop(node);
+  }
+
+  @override
+  visitDoStatement(ir.DoStatement node) {
+    _handleLoop(node);
+  }
+
+  @override
+  visitTryCatch(ir.TryCatch node) {
+    data.hasTry = true;
+  }
+
+  @override
+  visitTryFinally(ir.TryFinally node) {
+    data.hasTry = true;
+  }
+
+  @override
+  visitFunctionExpression(ir.FunctionExpression node) {
+    registerRegularNode();
+    data.hasClosure = true;
+  }
+
+  @override
+  visitFunctionDeclaration(ir.FunctionDeclaration node) {
+    registerRegularNode();
+    data.hasClosure = true;
+  }
+
+  @override
+  visitFunctionNode(ir.FunctionNode node) {
+    if (node.asyncMarker != ir.AsyncMarker.Sync) {
+      data.hasAsyncAwait = true;
+    }
+    // TODO(sra): Cost of parameter checking?
+    skipReductiveNodes(() {
+      visitList(node.typeParameters);
+      visitList(node.positionalParameters);
+      visitList(node.namedParameters);
+      visit(node.returnType);
+    });
+    visit(node.body);
+  }
+
+  @override
+  visitConditionalExpression(ir.ConditionalExpression node) {
+    // Heuristic: In "parameter ? A : B" there is a high probability that
+    // parameter is a constant. Assuming the parameter is constant, we can
+    // compute a count that is bounded by the largest arm rather than the sum of
+    // both arms.
+    ir.Expression condition = node.condition;
+    visit(condition);
+    int commonPrefixCount = data.regularNodeCount;
+
+    visit(node.then);
+    int thenCount = data.regularNodeCount - commonPrefixCount;
+
+    data.regularNodeCount = commonPrefixCount;
+    visit(node.otherwise);
+    int elseCount = data.regularNodeCount - commonPrefixCount;
+
+    data.regularNodeCount = commonPrefixCount + thenCount + elseCount;
+    if (condition is ir.VariableGet &&
+        condition.variable.parent is ir.FunctionNode) {
+      data.regularNodeCount =
+          commonPrefixCount + (thenCount > elseCount ? thenCount : elseCount);
+    }
+    // This is last so that [tooDifficult] is always updated.
+    registerRegularNode();
+    registerReductiveNode();
+    skipRegularNodes(() => visit(node.staticType));
+  }
+
+  @override
+  visitAssertInitializer(ir.AssertInitializer node) {
+    if (!enableUserAssertions) return;
+    node.visitChildren(this);
+  }
+
+  @override
+  visitAssertStatement(ir.AssertStatement node) {
+    if (!enableUserAssertions) return;
+    defaultNode(node);
+  }
+
+  void registerCall() {
+    ++data.callCount;
+  }
+
+  @override
+  visitEmptyStatement(ir.EmptyStatement node) {
+    registerRegularNode();
+  }
+
+  @override
+  visitExpressionStatement(ir.ExpressionStatement node) {
+    registerRegularNode();
+    node.visitChildren(this);
+  }
+
+  @override
+  visitBlock(ir.Block node) {
+    registerRegularNode();
+    node.visitChildren(this);
+  }
+
+  @override
+  visitStringLiteral(ir.StringLiteral node) {
+    registerRegularNode();
+    registerReductiveNode();
+    // Avoid copying long strings into call site.
+    if (node.value.length > 14) {
+      data.hasLongString = true;
+    }
+  }
+
+  @override
+  visitPropertyGet(ir.PropertyGet node) {
+    registerCall();
+    registerRegularNode();
+    registerReductiveNode();
+    skipReductiveNodes(() => visit(node.name));
+    visit(node.receiver);
+  }
+
+  @override
+  visitDirectPropertyGet(ir.DirectPropertyGet node) {
+    registerCall();
+    registerRegularNode();
+    registerReductiveNode();
+    visit(node.receiver);
+  }
+
+  @override
+  visitPropertySet(ir.PropertySet node) {
+    registerCall();
+    registerRegularNode();
+    registerReductiveNode();
+    skipReductiveNodes(() => visit(node.name));
+    visit(node.receiver);
+    visit(node.value);
+  }
+
+  @override
+  visitDirectPropertySet(ir.DirectPropertySet node) {
+    registerCall();
+    registerRegularNode();
+    registerReductiveNode();
+    visit(node.receiver);
+    visit(node.value);
+  }
+
+  @override
+  visitVariableGet(ir.VariableGet node) {
+    registerRegularNode();
+    registerReductiveNode();
+    skipReductiveNodes(() => visit(node.promotedType));
+  }
+
+  @override
+  visitThisExpression(ir.ThisExpression node) {
+    registerRegularNode();
+    registerReductiveNode();
+  }
+
+  @override
+  visitStaticGet(ir.StaticGet node) {
+    // Assume lazy-init static, loaded via a call: `$.$get$foo()`.
+    registerCall();
+    registerRegularNode();
+    registerReductiveNode();
+  }
+
+  @override
+  visitConstructorInvocation(ir.ConstructorInvocation node) {
+    registerRegularNode();
+    registerReductiveNode();
+    if (node.isConst) {
+      // A const constructor call compiles to a constant pool reference.
+      skipReductiveNodes(() => node.visitChildren(this));
+    } else {
+      registerCall();
+      _processArguments(node.arguments, node.target?.function);
+    }
+  }
+
+  @override
+  visitStaticInvocation(ir.StaticInvocation node) {
+    registerRegularNode();
+    if (node.isConst) {
+      data.hasExternalConstantConstructorCall = true;
+      skipReductiveNodes(() => node.visitChildren(this));
+    } else {
+      registerCall();
+      registerReductiveNode();
+      _processArguments(node.arguments, node.target?.function);
+    }
+  }
+
+  @override
+  visitMethodInvocation(ir.MethodInvocation node) {
+    registerRegularNode();
+    registerReductiveNode();
+    registerCall();
+    visit(node.receiver);
+    skipReductiveNodes(() => visit(node.name));
+    _processArguments(node.arguments, null);
+  }
+
+  _processArguments(ir.Arguments arguments, ir.FunctionNode target) {
+    registerRegularNode();
+    if (arguments.types.isNotEmpty) {
+      data.hasTypeArguments = true;
+      skipReductiveNodes(() => visitList(arguments.types));
+    }
+    int count = arguments.positional.length + arguments.named.length;
+    data.argumentCounts.add(count);
+
+    if (target != null) {
+      // Disallow defaulted optional arguments since they will be passed
+      // explicitly.
+      if (target.positionalParameters.length + target.namedParameters.length >
+          count) {
+        data.hasArgumentDefaulting = true;
+      }
+    }
+
+    visitList(arguments.positional);
+    for (ir.NamedExpression expression in arguments.named) {
+      registerRegularNode();
+      expression.value.accept(this);
+    }
+  }
+
+  @override
+  visitAsExpression(ir.AsExpression node) {
+    registerRegularNode();
+    visit(node.operand);
+    skipReductiveNodes(() => visit(node.type));
+    if (!(node.isTypeError && omitImplicitCasts)) {
+      data.hasCast = true;
+    }
+  }
+
+  @override
+  visitVariableDeclaration(ir.VariableDeclaration node) {
+    registerRegularNode();
+    skipReductiveNodes(() {
+      visitList(node.annotations);
+      visit(node.type);
+    });
+    visit(node.initializer);
+
+    // A local variable is an alias for the initializer expression.
+    if (node.initializer != null) {
+      unregisterReductiveNode(); // discount one reference to the variable.
+    }
+  }
+
+  @override
+  visitIfStatement(ir.IfStatement node) {
+    registerRegularNode();
+    node.visitChildren(this);
+    data.hasIf = true;
+  }
+}
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 47d0de0..1b97f87 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -21,7 +21,7 @@
 import '../io/source_information.dart';
 import '../js/js.dart' as js;
 import '../js_backend/interceptor_data.dart';
-import '../js_backend/backend.dart' show CodegenInputs, SuperMemberData;
+import '../js_backend/backend.dart' show CodegenInputs;
 import '../js_backend/checked_mode_helpers.dart';
 import '../js_backend/native_data.dart';
 import '../js_backend/namer.dart' show ModularNamer;
@@ -112,11 +112,9 @@
           _options,
           emitter,
           codegen.checkedModeHelpers,
-          codegen.oneShotInterceptorData,
           codegen.rtiSubstitutions,
           codegen.rtiEncoder,
           namer,
-          codegen.superMemberData,
           codegen.tracer,
           closedWorld,
           registry);
@@ -143,11 +141,9 @@
           _options,
           emitter,
           codegen.checkedModeHelpers,
-          codegen.oneShotInterceptorData,
           codegen.rtiSubstitutions,
           codegen.rtiEncoder,
           namer,
-          codegen.superMemberData,
           codegen.tracer,
           closedWorld,
           registry);
@@ -182,11 +178,9 @@
   final CompilerOptions _options;
   final ModularEmitter _emitter;
   final CheckedModeHelpers _checkedModeHelpers;
-  final OneShotInterceptorData _oneShotInterceptorData;
   final RuntimeTypesSubstitutions _rtiSubstitutions;
   final RuntimeTypesEncoder _rtiEncoder;
   final ModularNamer _namer;
-  final SuperMemberData _superMemberData;
   final Tracer _tracer;
   final JClosedWorld _closedWorld;
   final CodegenRegistry _registry;
@@ -238,11 +232,9 @@
       this._options,
       this._emitter,
       this._checkedModeHelpers,
-      this._oneShotInterceptorData,
       this._rtiSubstitutions,
       this._rtiEncoder,
       this._namer,
-      this._superMemberData,
       this._tracer,
       this._closedWorld,
       this._registry,
@@ -389,8 +381,7 @@
     runPhase(new SsaTypeKnownRemover());
     runPhase(new SsaTrustedCheckRemover(_options));
     runPhase(new SsaAssignmentChaining(_options, _closedWorld));
-    runPhase(new SsaInstructionMerger(
-        _abstractValueDomain, generateAtUseSite, _superMemberData));
+    runPhase(new SsaInstructionMerger(_abstractValueDomain, generateAtUseSite));
     runPhase(new SsaConditionMerger(generateAtUseSite, controlFlowOperators));
     runPhase(new SsaShareRegionConstants(_options));
 
@@ -628,6 +619,9 @@
 
   js.Expression generateExpressionAssignment(String variableName,
       js.Expression value, SourceInformation sourceInformation) {
+    // TODO(johnniwinther): Introduce a DeferredVariableUse to handle this
+    // in the SSA codegen or let the JS printer handle it fully and remove it
+    // here.
     if (value is js.Binary) {
       js.Binary binary = value;
       String op = binary.op;
@@ -699,11 +693,14 @@
     // emit an assignment, because the intTypeCheck just returns its
     // argument.
     bool needsAssignment = true;
-    if (instruction is HTypeConversion) {
-      HTypeConversion typeConversion = instruction;
-      String inputName = variableNames.getName(typeConversion.checkedInput);
-      if (variableNames.getName(instruction) == inputName) {
-        needsAssignment = false;
+    if (instruction is HCheck) {
+      if (instruction is HTypeConversion ||
+          instruction is HPrimitiveCheck ||
+          instruction is HBoolConversion) {
+        String inputName = variableNames.getName(instruction.checkedInput);
+        if (variableNames.getName(instruction) == inputName) {
+          needsAssignment = false;
+        }
       }
     }
     if (instruction is HLocalValue) {
@@ -1567,15 +1564,6 @@
   visitGreaterEqual(HGreaterEqual node) => visitRelational(node, '>=');
 
   @override
-  visitBoolify(HBoolify node) {
-    assert(node.inputs.length == 1);
-    use(node.inputs[0]);
-    push(new js.Binary(
-            '===', pop(), newLiteralBool(true, node.sourceInformation))
-        .withSourceInformation(node.sourceInformation));
-  }
-
-  @override
   visitExit(HExit node) {
     // Don't do anything.
   }
@@ -1923,8 +1911,10 @@
     js.Expression isolate =
         _namer.readGlobalObjectForLibrary(_commonElements.interceptorsLibrary);
     Selector selector = node.selector;
-    js.Name methodName = _oneShotInterceptorData.registerOneShotInterceptor(
-        selector, _namer, _closedWorld);
+    Set<ClassEntity> classes =
+        _interceptorData.getInterceptedClassesOn(selector.name, _closedWorld);
+    _registry.registerOneShotInterceptor(selector);
+    js.Name methodName = _namer.nameForOneShotInterceptor(selector, classes);
     push(js
         .propertyCall(isolate, methodName, arguments)
         .withSourceInformation(node.sourceInformation));
@@ -2137,8 +2127,7 @@
     MemberEntity superElement = node.element;
     ClassEntity superClass = superElement.enclosingClass;
     Selector selector = node.selector;
-    bool useAliasedSuper = _superMemberData.maybeRegisterAliasedSuperMember(
-        superElement, selector);
+    bool useAliasedSuper = canUseAliasedSuperMember(superElement, selector);
     if (selector.isGetter) {
       if (superElement.isField || superElement.isGetter) {
         _registry.registerStaticUse(new StaticUse.superGet(superElement));
@@ -2153,8 +2142,7 @@
         _registry.registerStaticUse(new StaticUse.superSetterSet(superElement));
       }
     } else {
-      if (_superMemberData.maybeRegisterAliasedSuperMember(
-          superElement, selector)) {
+      if (useAliasedSuper) {
         _registry.registerStaticUse(new StaticUse.superInvoke(
             superElement, new CallStructure.unnamed(node.inputs.length)));
       } else {
@@ -2432,11 +2420,6 @@
         use(input.inputs[0]);
       } else if (input is HIdentity) {
         emitIdentityComparison(input, sourceInformation, inverse: true);
-      } else if (input is HBoolify) {
-        use(input.inputs[0]);
-        push(new js.Binary(
-                "!==", pop(), newLiteralBool(true, input.sourceInformation))
-            .withSourceInformation(sourceInformation));
       } else if (canGenerateOptimizedComparison(input)) {
         HRelational relational = input;
         constant_system.BinaryOperation operation = relational.operation();
@@ -3124,55 +3107,9 @@
         negative: negative);
   }
 
-  js.Expression generateReceiverOrArgumentTypeTest(HTypeConversion node) {
-    DartType type = node.typeExpression;
-    HInstruction input = node.checkedInput;
-    AbstractValue checkedType = node.checkedType;
-    // This path is no longer used for indexable primitive types.
-    assert(_abstractValueDomain.isJsIndexable(checkedType).isPotentiallyFalse);
-    // Figure out if it is beneficial to use a null check.  V8 generally prefers
-    // 'typeof' checks, but for integers we cannot compile this test into a
-    // single typeof check so the null check is cheaper.
-    if (type == _commonElements.numType) {
-      // input is !num
-      checkNum(input, '!==', input.sourceInformation);
-      return pop();
-    } else if (type == _commonElements.boolType) {
-      // input is !bool
-      checkBool(input, '!==', input.sourceInformation);
-      return pop();
-    }
-    throw failedAt(input, 'Unexpected check: $type.');
-  }
-
   @override
   void visitTypeConversion(HTypeConversion node) {
-    if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
-      js.Expression test = generateReceiverOrArgumentTypeTest(node);
-      js.Block oldContainer = currentContainer;
-      js.Statement body = new js.Block.empty();
-      currentContainer = body;
-      if (node.isArgumentTypeCheck) {
-        generateThrowWithHelper(
-            _commonElements.throwIllegalArgumentException, node.checkedInput,
-            sourceInformation: node.sourceInformation);
-      } else if (node.isReceiverTypeCheck) {
-        use(node.checkedInput);
-        js.Name methodName =
-            _namer.invocationName(node.receiverTypeCheckSelector);
-        js.Expression call = js.propertyCall(pop(), methodName,
-            []).withSourceInformation(node.sourceInformation);
-        pushStatement(
-            new js.Return(call).withSourceInformation(node.sourceInformation));
-      }
-      currentContainer = oldContainer;
-      body = unwrapStatement(body);
-      pushStatement(new js.If.noElse(test, body)
-          .withSourceInformation(node.sourceInformation));
-      return;
-    }
-
-    assert(node.isCheckedModeCheck || node.isCastTypeCheck);
+    assert(node.isTypeCheck || node.isCastCheck);
     DartType type = node.typeExpression;
     assert(!type.isTypedef);
     assert(!type.isDynamic);
@@ -3185,14 +3122,9 @@
     }
     _registry.registerTypeUse(new TypeUse.isCheck(type));
 
-    CheckedModeHelper helper;
-    if (node.isBooleanConversionCheck) {
-      helper = const CheckedModeHelper('boolConversionCheck');
-    } else {
-      helper = _checkedModeHelpers.getCheckedModeHelper(
-          type, _closedWorld.commonElements,
-          typeCast: node.isCastTypeCheck);
-    }
+    CheckedModeHelper helper = _checkedModeHelpers.getCheckedModeHelper(
+        type, _closedWorld.commonElements,
+        typeCast: node.isCastCheck);
 
     StaticUse staticUse = helper.getStaticUse(_closedWorld.commonElements);
     _registry.registerStaticUse(staticUse);
@@ -3206,6 +3138,66 @@
   }
 
   @override
+  void visitPrimitiveCheck(HPrimitiveCheck node) {
+    js.Expression test = _generateReceiverOrArgumentTypeTest(node);
+    js.Block oldContainer = currentContainer;
+    js.Statement body = new js.Block.empty();
+    currentContainer = body;
+    if (node.isArgumentTypeCheck) {
+      generateThrowWithHelper(
+          _commonElements.throwIllegalArgumentException, node.checkedInput,
+          sourceInformation: node.sourceInformation);
+    } else if (node.isReceiverTypeCheck) {
+      use(node.checkedInput);
+      js.Name methodName =
+          _namer.invocationName(node.receiverTypeCheckSelector);
+      js.Expression call = js.propertyCall(
+          pop(), methodName, []).withSourceInformation(node.sourceInformation);
+      pushStatement(
+          new js.Return(call).withSourceInformation(node.sourceInformation));
+    }
+    currentContainer = oldContainer;
+    body = unwrapStatement(body);
+    pushStatement(new js.If.noElse(test, body)
+        .withSourceInformation(node.sourceInformation));
+  }
+
+  js.Expression _generateReceiverOrArgumentTypeTest(HPrimitiveCheck node) {
+    DartType type = node.typeExpression;
+    HInstruction input = node.checkedInput;
+    AbstractValue checkedType = node.checkedType;
+    // This path is no longer used for indexable primitive types.
+    assert(_abstractValueDomain.isJsIndexable(checkedType).isPotentiallyFalse);
+    // Figure out if it is beneficial to use a null check.  V8 generally prefers
+    // 'typeof' checks, but for integers we cannot compile this test into a
+    // single typeof check so the null check is cheaper.
+    if (type == _commonElements.numType) {
+      // input is !num
+      checkNum(input, '!==', input.sourceInformation);
+      return pop();
+    }
+    if (type == _commonElements.boolType) {
+      // input is !bool
+      checkBool(input, '!==', input.sourceInformation);
+      return pop();
+    }
+    throw failedAt(input, 'Unexpected check: $type.');
+  }
+
+  @override
+  void visitBoolConversion(HBoolConversion node) {
+    _registry.registerTypeUse(new TypeUse.isCheck(_commonElements.boolType));
+    CheckedModeHelper helper = const CheckedModeHelper('boolConversionCheck');
+    StaticUse staticUse = helper.getStaticUse(_commonElements);
+    _registry.registerStaticUse(staticUse);
+    use(node.checkedInput);
+    List<js.Expression> arguments = [pop()];
+    push(
+        new js.Call(_emitter.staticFunctionAccess(staticUse.element), arguments)
+            .withSourceInformation(node.sourceInformation));
+  }
+
+  @override
   void visitTypeKnown(HTypeKnown node) {
     // [HTypeKnown] instructions are removed before generating code.
     assert(false);
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index bc388f2..8ffd0ed 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -5,7 +5,6 @@
 import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../inferrer/abstract_value_domain.dart';
-import '../js_backend/js_backend.dart' show SuperMemberData;
 import '../js_backend/interceptor_data.dart';
 import '../options.dart';
 import '../universe/selector.dart' show Selector;
@@ -13,6 +12,15 @@
 import 'codegen.dart' show CodegenPhase;
 import 'nodes.dart';
 
+/// Returns `true` if the invocation of [selector] on [member] can use an
+/// aliased member.
+///
+/// Invoking a super getter isn't supported, this would require changes to
+/// compact field descriptors in the emitter.
+bool canUseAliasedSuperMember(MemberEntity member, Selector selector) {
+  return !selector.isGetter;
+}
+
 /// Replaces some instructions with specialized versions to make codegen easier.
 /// Caches codegen information on nodes.
 class SsaInstructionSelection extends HBaseVisitor with CodegenPhase {
@@ -191,7 +199,7 @@
           !_interceptorData.isInterceptedMixinSelector(
               selector, mask, _closedWorld)) {
         ConstantValue constant =
-            new AbstractValueConstantValue(receiverArgument.instructionType);
+            new DummyInterceptorConstantValue(receiverArgument.instructionType);
         HConstant dummy = graph.addConstant(constant, _closedWorld);
         receiverArgument.usedBy.remove(node);
         node.inputs[1] = dummy;
@@ -372,6 +380,8 @@
     for (HInstruction user in instruction.usedBy) {
       if (user is HTypeConversion) {
         user.inputType = instruction.instructionType;
+      } else if (user is HPrimitiveCheck) {
+        user.inputType = instruction.instructionType;
       }
     }
     instruction.block.rewrite(instruction, instruction.checkedInput);
@@ -379,7 +389,7 @@
   }
 }
 
-/// Remove [HTypeConversion] instructions from the graph in '--trust-primitives'
+/// Remove [HPrimitiveCheck] instructions from the graph in '--trust-primitives'
 /// mode.
 class SsaTrustedCheckRemover extends HBaseVisitor with CodegenPhase {
   final CompilerOptions _options;
@@ -403,11 +413,15 @@
   }
 
   @override
-  void visitTypeConversion(HTypeConversion instruction) {
-    if (instruction.isReceiverTypeCheck || instruction.isArgumentTypeCheck) {
-      instruction.block.rewrite(instruction, instruction.checkedInput);
-      instruction.block.remove(instruction);
-    }
+  void visitPrimitiveCheck(HPrimitiveCheck instruction) {
+    instruction.block.rewrite(instruction, instruction.checkedInput);
+    instruction.block.remove(instruction);
+  }
+
+  @override
+  void visitBoolConversion(HBoolConversion instruction) {
+    instruction.block.rewrite(instruction, instruction.checkedInput);
+    instruction.block.remove(instruction);
   }
 }
 
@@ -589,7 +603,6 @@
 ///   t2 = add(4, 3);
 class SsaInstructionMerger extends HBaseVisitor with CodegenPhase {
   final AbstractValueDomain _abstractValueDomain;
-  final SuperMemberData _superMemberData;
 
   /// List of [HInstruction] that the instruction merger expects in
   /// order when visiting the inputs of an instruction.
@@ -606,8 +619,7 @@
     generateAtUseSite.add(instruction);
   }
 
-  SsaInstructionMerger(
-      this._abstractValueDomain, this.generateAtUseSite, this._superMemberData);
+  SsaInstructionMerger(this._abstractValueDomain, this.generateAtUseSite);
 
   @override
   void visitGraph(HGraph graph) {
@@ -693,7 +705,7 @@
     // after first access if we use lazy initialization.
     // In this case, we therefore don't allow the receiver (the first argument)
     // to be generated at use site, and only analyze all other arguments.
-    if (!_superMemberData.canUseAliasedSuperMember(superMethod, selector)) {
+    if (!canUseAliasedSuperMember(superMethod, selector)) {
       analyzeInputs(instruction, 1);
     } else {
       super.visitInvokeSuper(instruction);
@@ -737,16 +749,15 @@
 
   @override
   void visitTypeConversion(HTypeConversion instruction) {
-    if (!instruction.isArgumentTypeCheck && !instruction.isReceiverTypeCheck) {
-      assert(instruction.isCheckedModeCheck || instruction.isCastTypeCheck);
-      // Checked mode checks and cast checks compile to code that
-      // only use their input once, so we can safely visit them
-      // and try to merge the input.
-      visitInstruction(instruction);
-    }
+    // Type checks and cast checks compile to code that only use their input
+    // once, so we can safely visit them and try to merge the input.
+    visitInstruction(instruction);
   }
 
   @override
+  void visitPrimitiveCheck(HPrimitiveCheck instruction) {}
+
+  @override
   void visitTypeKnown(HTypeKnown instruction) {
     // [HTypeKnown] instructions are removed before code generation.
     assert(false);
diff --git a/pkg/compiler/lib/src/ssa/logging.dart b/pkg/compiler/lib/src/ssa/logging.dart
index 0a99d31..cdfb2a9 100644
--- a/pkg/compiler/lib/src/ssa/logging.dart
+++ b/pkg/compiler/lib/src/ssa/logging.dart
@@ -214,30 +214,18 @@
     _registerSpecializer(original, null, null, 'Round');
   }
 
-  void registerTypeConversion(
-      HInstruction original, HTypeConversion converted) {
+  void registerPrimitiveCheck(HInstruction original, HPrimitiveCheck check) {
     Features features = new Features();
-    switch (converted.kind) {
-      case HTypeConversion.CHECKED_MODE_CHECK:
-        features['kind'] = 'checked';
-        break;
-      case HTypeConversion.ARGUMENT_TYPE_CHECK:
-        features['kind'] = 'argument';
-        break;
-      case HTypeConversion.CAST_TYPE_CHECK:
-        features['kind'] = 'cast';
-        break;
-      case HTypeConversion.BOOLEAN_CONVERSION_CHECK:
-        features['kind'] = 'boolean';
-        break;
-      case HTypeConversion.RECEIVER_TYPE_CHECK:
-        features['kind'] = 'receiver';
-        break;
+
+    if (check.isReceiverTypeCheck) {
+      features['kind'] = 'receiver';
+    } else if (check.isArgumentTypeCheck) {
+      features['kind'] = 'argument';
     }
-    if (converted.typeExpression != null) {
-      features['type'] = '${converted.typeExpression}';
+    if (check.typeExpression != null) {
+      features['type'] = '${check.typeExpression}';
     }
-    entries.add(new OptimizationLogEntry('TypeConversion', features));
+    entries.add(new OptimizationLogEntry('PrimitiveCheck', features));
   }
 
   String getText() {
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index a893874..db7f6f6 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -8,7 +8,6 @@
 import '../common.dart';
 import '../constants/constant_system.dart' as constant_system;
 import '../constants/values.dart';
-import '../deferred_load.dart' show OutputUnit;
 import '../elements/entities.dart';
 import '../elements/jumps.dart';
 import '../elements/types.dart';
@@ -31,7 +30,6 @@
   R visitBitNot(HBitNot node);
   R visitBitOr(HBitOr node);
   R visitBitXor(HBitXor node);
-  R visitBoolify(HBoolify node);
   R visitBoundsCheck(HBoundsCheck node);
   R visitBreak(HBreak node);
   R visitConstant(HConstant node);
@@ -97,6 +95,8 @@
   R visitTruncatingDivide(HTruncatingDivide node);
   R visitTry(HTry node);
   R visitTypeConversion(HTypeConversion node);
+  R visitPrimitiveCheck(HPrimitiveCheck node);
+  R visitBoolConversion(HBoolConversion node);
   R visitTypeKnown(HTypeKnown node);
   R visitYield(HYield node);
 
@@ -284,11 +284,9 @@
     return result;
   }
 
-  HConstant addDeferredConstant(ConstantValue constant, OutputUnit unit,
+  HConstant addDeferredConstant(DeferredGlobalConstantValue constant,
       SourceInformation sourceInformation, JClosedWorld closedWorld) {
-    ConstantValue wrapper = new DeferredGlobalConstantValue(constant, unit);
-    closedWorld.outputUnitData.registerConstantDeferredUse(wrapper, unit);
-    return addConstant(wrapper, closedWorld,
+    return addConstant(constant, closedWorld,
         sourceInformation: sourceInformation);
   }
 
@@ -326,10 +324,7 @@
   HConstant addConstantUnreachable(JClosedWorld closedWorld) {
     // A constant with an empty type used as the HInstruction of an expression
     // in an unreachable context.
-    return addConstant(
-        new AbstractValueConstantValue(
-            closedWorld.abstractValueDomain.emptyType),
-        closedWorld);
+    return addConstant(const UnreachableConstantValue(), closedWorld);
   }
 
   void finalize(AbstractValueDomain domain) {
@@ -436,8 +431,6 @@
   @override
   visitBitXor(HBitXor node) => visitBinaryBitOp(node);
   @override
-  visitBoolify(HBoolify node) => visitInstruction(node);
-  @override
   visitBoundsCheck(HBoundsCheck node) => visitCheck(node);
   @override
   visitBreak(HBreak node) => visitJump(node);
@@ -576,6 +569,10 @@
   @override
   visitTypeConversion(HTypeConversion node) => visitCheck(node);
   @override
+  visitBoolConversion(HBoolConversion node) => visitCheck(node);
+  @override
+  visitPrimitiveCheck(HPrimitiveCheck node) => visitCheck(node);
+  @override
   visitTypeKnown(HTypeKnown node) => visitCheck(node);
   @override
   visitAwait(HAwait node) => visitInstruction(node);
@@ -1022,7 +1019,6 @@
 
   // Type codes.
   static const int UNDEFINED_TYPECODE = -1;
-  static const int BOOLIFY_TYPECODE = 0;
   static const int TYPE_GUARD_TYPECODE = 1;
   static const int BOUNDS_CHECK_TYPECODE = 2;
   static const int INTEGER_CHECK_TYPECODE = 3;
@@ -1065,6 +1061,8 @@
   static const int REMAINDER_TYPECODE = 42;
   static const int GET_LENGTH_TYPECODE = 43;
   static const int ABS_TYPECODE = 44;
+  static const int BOOL_CONVERSION_TYPECODE = 45;
+  static const int PRIMITIVE_CHECK_TYPECODE = 46;
 
   HInstruction(this.inputs, this.instructionType)
       : id = idCounter++,
@@ -1371,11 +1369,7 @@
           closedWorld.abstractValueDomain.dynamicType, this, sourceInformation);
     }
     assert(type.isInterfaceType);
-    if (kind == HTypeConversion.BOOLEAN_CONVERSION_CHECK) {
-      // Boolean conversion checks work on non-nullable booleans.
-      return new HTypeConversion(type, kind,
-          closedWorld.abstractValueDomain.boolType, this, sourceInformation);
-    } else if (kind == HTypeConversion.CHECKED_MODE_CHECK && !type.treatAsRaw) {
+    if (kind == HTypeConversion.TYPE_CHECK && !type.treatAsRaw) {
       throw 'creating compound check to $type (this = ${this})';
     } else {
       InterfaceType interfaceType = type;
@@ -1561,23 +1555,6 @@
       : super(inputs, type);
 }
 
-class HBoolify extends HInstruction {
-  HBoolify(HInstruction value, AbstractValue type)
-      : super(<HInstruction>[value], type) {
-    setUseGvn();
-    sourceInformation = value.sourceInformation;
-  }
-
-  @override
-  accept(HVisitor visitor) => visitor.visitBoolify(this);
-  @override
-  int typeCode() => HInstruction.BOOLIFY_TYPECODE;
-  @override
-  bool typeEquals(other) => other is HBoolify;
-  @override
-  bool dataEquals(HInstruction other) => true;
-}
-
 /// A [HCheck] instruction is an instruction that might do a dynamic
 /// check at runtime on another instruction. To have proper instruction
 /// dependencies in the graph, instructions that depend on the check
@@ -3514,58 +3491,33 @@
 
 class HTypeConversion extends HCheck {
   // Values for [kind].
-  static const int CHECKED_MODE_CHECK = 0;
-  static const int ARGUMENT_TYPE_CHECK = 1;
-  static const int CAST_TYPE_CHECK = 2;
-  static const int BOOLEAN_CONVERSION_CHECK = 3;
-  static const int RECEIVER_TYPE_CHECK = 4;
+  static const int TYPE_CHECK = 0;
+  static const int CAST_CHECK = 1;
 
   final DartType typeExpression;
   final int kind;
-  // [receiverTypeCheckSelector] is the selector used for a receiver type check
-  // on open-coded operators, e.g. the not-null check on `x` in `x + 1` would be
-  // compiled to the following, for which we need the selector `$add`.
-  //
-  //     if (typeof x != "number") x.$add();
-  //
-  final Selector receiverTypeCheckSelector;
 
   AbstractValue checkedType; // Not final because we refine it.
   AbstractValue
       inputType; // Holds input type for codegen after HTypeKnown removal.
 
   HTypeConversion(this.typeExpression, this.kind, AbstractValue type,
-      HInstruction input, SourceInformation sourceInformation,
-      {this.receiverTypeCheckSelector})
+      HInstruction input, SourceInformation sourceInformation)
       : checkedType = type,
         super(<HInstruction>[input], type) {
-    assert(!isReceiverTypeCheck || receiverTypeCheckSelector != null);
     assert(typeExpression == null || !typeExpression.isTypedef);
-    assert(!isControlFlow() || typeExpression != null);
-    sourceElement = input.sourceElement;
+    this.sourceElement = input.sourceElement;
     this.sourceInformation = sourceInformation;
   }
 
   HTypeConversion.withTypeRepresentation(this.typeExpression, this.kind,
       AbstractValue type, HInstruction input, HInstruction typeRepresentation)
       : checkedType = type,
-        receiverTypeCheckSelector = null,
         super(<HInstruction>[input, typeRepresentation], type) {
     assert(!typeExpression.isTypedef);
     sourceElement = input.sourceElement;
   }
 
-  HTypeConversion.viaMethodOnType(this.typeExpression, this.kind,
-      AbstractValue type, HInstruction reifiedType, HInstruction input)
-      : checkedType = type,
-        receiverTypeCheckSelector = null,
-        super(<HInstruction>[reifiedType, input], type) {
-    // This form is currently used only for function types.
-    assert(typeExpression.isFunctionType);
-    assert(kind == CHECKED_MODE_CHECK || kind == CAST_TYPE_CHECK);
-    sourceElement = input.sourceElement;
-  }
-
   bool get hasTypeRepresentation {
     return typeExpression != null &&
         typeExpression.isInterfaceType &&
@@ -3580,23 +3532,13 @@
   @override
   HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
     if (typeExpression == type) {
-      // Don't omit a boolean conversion (which doesn't allow `null`) unless
-      // this type conversion is already a boolean conversion.
-      if (kind != BOOLEAN_CONVERSION_CHECK || isBooleanConversionCheck) {
-        return this;
-      }
+      return this;
     }
     return super.convertType(closedWorld, type, kind);
   }
 
-  bool get isCheckedModeCheck {
-    return kind == CHECKED_MODE_CHECK || kind == BOOLEAN_CONVERSION_CHECK;
-  }
-
-  bool get isArgumentTypeCheck => kind == ARGUMENT_TYPE_CHECK;
-  bool get isReceiverTypeCheck => kind == RECEIVER_TYPE_CHECK;
-  bool get isCastTypeCheck => kind == CAST_TYPE_CHECK;
-  bool get isBooleanConversionCheck => kind == BOOLEAN_CONVERSION_CHECK;
+  bool get isTypeCheck => kind == TYPE_CHECK;
+  bool get isCastCheck => kind == CAST_CHECK;
 
   @override
   accept(HVisitor visitor) => visitor.visitTypeConversion(this);
@@ -3604,7 +3546,7 @@
   @override
   bool isJsStatement() => isControlFlow();
   @override
-  bool isControlFlow() => isArgumentTypeCheck || isReceiverTypeCheck;
+  bool isControlFlow() => false;
 
   @override
   int typeCode() => HInstruction.TYPE_CONVERSION_TYPECODE;
@@ -3617,8 +3559,7 @@
   bool dataEquals(HTypeConversion other) {
     return kind == other.kind &&
         typeExpression == other.typeExpression &&
-        checkedType == other.checkedType &&
-        receiverTypeCheckSelector == other.receiverTypeCheckSelector;
+        checkedType == other.checkedType;
   }
 
   bool isRedundant(JClosedWorld closedWorld) {
@@ -3666,6 +3607,130 @@
       'checkedInput=$checkedInput)';
 }
 
+/// Check for receiver or argument type when lowering operation to a primitive,
+/// e.g. lowering `+` to [HAdd].
+///
+/// After NNBD, `a + b` will require `a` and `b` are non-nullable and these
+/// checks will become explicit in the source (e.g. `a! + b!`). At that time,
+/// this check should be removed.  If needed, the `!` check can be optimized
+/// give the same signals to the JavaScript VM.
+class HPrimitiveCheck extends HCheck {
+  // Values for [kind].
+  static const int ARGUMENT_TYPE_CHECK = 1;
+  static const int RECEIVER_TYPE_CHECK = 3;
+
+  final DartType typeExpression;
+  final int kind;
+
+  // [receiverTypeCheckSelector] is the selector used for a receiver type check
+  // on open-coded operators, e.g. the not-null check on `x` in `x + 1` would be
+  // compiled to the following, for which we need the selector `$add`.
+  //
+  //     if (typeof x != "number") x.$add();
+  //
+  final Selector receiverTypeCheckSelector;
+
+  AbstractValue checkedType; // Not final because we refine it.
+  AbstractValue
+      inputType; // Holds input type for codegen after HTypeKnown removal.
+
+  HPrimitiveCheck(this.typeExpression, this.kind, AbstractValue type,
+      HInstruction input, SourceInformation sourceInformation,
+      {this.receiverTypeCheckSelector})
+      : checkedType = type,
+        super(<HInstruction>[input], type) {
+    assert(isReceiverTypeCheck == (receiverTypeCheckSelector != null));
+    this.sourceElement = input.sourceElement;
+    this.sourceInformation = sourceInformation;
+  }
+
+  @override
+  HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
+    if (typeExpression == type) {
+      return this;
+    }
+    return super.convertType(closedWorld, type, kind);
+  }
+
+  bool get isArgumentTypeCheck => kind == ARGUMENT_TYPE_CHECK;
+  bool get isReceiverTypeCheck => kind == RECEIVER_TYPE_CHECK;
+
+  @override
+  accept(HVisitor visitor) => visitor.visitPrimitiveCheck(this);
+
+  @override
+  bool isJsStatement() => true;
+  @override
+  bool isControlFlow() => true;
+
+  @override
+  int typeCode() => HInstruction.PRIMITIVE_CHECK_TYPECODE;
+  @override
+  bool typeEquals(HInstruction other) => other is HPrimitiveCheck;
+  @override
+  bool isCodeMotionInvariant() => false;
+
+  @override
+  bool dataEquals(HPrimitiveCheck other) {
+    return kind == other.kind &&
+        checkedType == other.checkedType &&
+        receiverTypeCheckSelector == other.receiverTypeCheckSelector;
+  }
+
+  bool isRedundant(JClosedWorld closedWorld) {
+    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
+    // Type is refined from `dynamic`, so it might become non-redundant.
+    if (abstractValueDomain.containsAll(checkedType).isPotentiallyTrue) {
+      return false;
+    }
+    AbstractValue inputType = checkedInput.instructionType;
+    return abstractValueDomain.isIn(inputType, checkedType).isDefinitelyTrue;
+  }
+
+  @override
+  String toString() => 'HPrimitiveCheck(checkedType=$checkedType, kind=$kind, '
+      'checkedInput=$checkedInput)';
+}
+
+/// A check that the input to a condition (if, ?:, while, etc) is non-null. The
+/// front-end generates 'as bool' checks, but until the transition to NNBD is
+/// complete, this allows `null` to be passed to the condition.
+///
+// TODO(sra): Once NNDB is far enough along that the front-end can generate `as
+// bool!` checks and the backend checks them correctly, this instruction will
+// become unnecessary and should be removed.
+class HBoolConversion extends HCheck {
+  HBoolConversion(HInstruction input, AbstractValue type)
+      : super(<HInstruction>[input], type);
+
+  @override
+  bool isJsStatement() => false;
+
+  @override
+  bool isCodeMotionInvariant() => false;
+
+  @override
+  accept(HVisitor visitor) => visitor.visitBoolConversion(this);
+
+  @override
+  int typeCode() => HInstruction.BOOL_CONVERSION_TYPECODE;
+  @override
+  bool typeEquals(HInstruction other) => other is HBoolConversion;
+  @override
+  bool dataEquals(HBoolConversion other) => true;
+
+  bool isRedundant(JClosedWorld closedWorld) {
+    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
+    AbstractValue inputType = checkedInput.instructionType;
+    return abstractValueDomain
+        .isIn(inputType, instructionType)
+        .isDefinitelyTrue;
+  }
+
+  @override
+  toString() => 'HBoolConversion($checkedInput)';
+}
+
 /// The [HTypeKnown] instruction marks a value with a refined type.
 class HTypeKnown extends HCheck {
   AbstractValue knownType;
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 91a06794f..249121e 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -439,33 +439,6 @@
   }
 
   @override
-  HInstruction visitBoolify(HBoolify node) {
-    List<HInstruction> inputs = node.inputs;
-    assert(inputs.length == 1);
-    HInstruction input = inputs[0];
-    if (input.isBoolean(_abstractValueDomain).isDefinitelyTrue) {
-      return input;
-    }
-
-    // If the code is unreachable, remove the HBoolify.  This can happen when
-    // there is a throw expression in a short-circuit conditional.  Removing the
-    // unreachable HBoolify makes it easier to reconstruct the short-circuit
-    // operation.
-    if (_abstractValueDomain.isEmpty(input.instructionType).isDefinitelyTrue) {
-      return input;
-    }
-
-    // All values that cannot be 'true' are boolified to false.
-    AbstractValue mask = input.instructionType;
-    if (_abstractValueDomain
-        .containsType(mask, commonElements.jsBoolClass)
-        .isPotentiallyFalse) {
-      return _graph.addConstantBool(false, _closedWorld);
-    }
-    return node;
-  }
-
-  @override
   HInstruction visitNot(HNot node) {
     List<HInstruction> inputs = node.inputs;
     assert(inputs.length == 1);
@@ -925,23 +898,8 @@
     return node;
   }
 
-  bool allUsersAreBoolifies(HInstruction instruction) {
-    List<HInstruction> users = instruction.usedBy;
-    int length = users.length;
-    for (int i = 0; i < length; i++) {
-      if (users[i] is! HBoolify) return false;
-    }
-    return true;
-  }
-
   @override
   HInstruction visitRelational(HRelational node) {
-    if (allUsersAreBoolifies(node)) {
-      // TODO(ngeoffray): Call a boolified selector.
-      // This node stays the same, but the Boolify node will go away.
-    }
-    // Note that we still have to call [super] to make sure that we end up
-    // in the remaining optimizations.
     return super.visitRelational(node);
   }
 
@@ -1161,6 +1119,18 @@
   }
 
   @override
+  HInstruction visitPrimitiveCheck(HPrimitiveCheck node) {
+    if (node.isRedundant(_closedWorld)) return node.checkedInput;
+    return node;
+  }
+
+  @override
+  HInstruction visitBoolConversion(HBoolConversion node) {
+    if (node.isRedundant(_closedWorld)) return node.checkedInput;
+    return node;
+  }
+
+  @override
   HInstruction visitTypeKnown(HTypeKnown node) {
     return node.isRedundant(_closedWorld) ? node.checkedInput : node;
   }
@@ -1364,8 +1334,8 @@
         node.needsCheck = true;
         return node;
       }
-      HInstruction other = value.convertType(
-          _closedWorld, type, HTypeConversion.CHECKED_MODE_CHECK);
+      HInstruction other =
+          value.convertType(_closedWorld, type, HTypeConversion.TYPE_CHECK);
       if (other != value) {
         node.block.addBefore(node, other);
         value = other;
@@ -1955,8 +1925,7 @@
   HInstruction get zapInstruction {
     if (zapInstructionCache == null) {
       // A constant with no type does not pollute types at phi nodes.
-      ConstantValue constant =
-          new AbstractValueConstantValue(_abstractValueDomain.emptyType);
+      ConstantValue constant = const UnreachableConstantValue();
       zapInstructionCache = analyzer.graph.addConstant(constant, closedWorld);
     }
     return zapInstructionCache;
@@ -2929,10 +2898,6 @@
             collectTargets(user, trueTargets, null);
           }
         }
-      } else if (user is HBoolify) {
-        // We collect targets for strictly boolean operations so HBoolify cannot
-        // change the result.
-        collectTargets(user, trueTargets, falseTargets);
       }
     }
   }
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index 9a5b4ca..db7b380 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -173,11 +173,6 @@
     return "LateValue: ${temporaryId(node.inputs[0])}";
   }
 
-  @override
-  String visitBoolify(HBoolify node) {
-    return "Boolify: ${temporaryId(node.inputs[0])}";
-  }
-
   String handleInvokeBinary(HInvokeBinary node, String opcode) {
     String left = temporaryId(node.left);
     String right = temporaryId(node.right);
@@ -609,22 +604,32 @@
   }
 
   String _typeConversionKind(HTypeConversion node) {
-    switch (node.kind) {
-      case HTypeConversion.CHECKED_MODE_CHECK:
-        return 'CHECKED_MODE';
-      case HTypeConversion.ARGUMENT_TYPE_CHECK:
-        return 'ARGUMENT';
-      case HTypeConversion.CAST_TYPE_CHECK:
-        return 'CAST';
-      case HTypeConversion.BOOLEAN_CONVERSION_CHECK:
-        return 'BOOLEAN_CONVERSION';
-      case HTypeConversion.RECEIVER_TYPE_CHECK:
-        return 'RECEIVER';
-    }
+    if (node.isTypeCheck) return 'TYPE_CHECK';
+    if (node.isCastCheck) return 'CAST_CHECK';
     return '?';
   }
 
   @override
+  String visitPrimitiveCheck(HPrimitiveCheck node) {
+    String checkedInput = temporaryId(node.checkedInput);
+    assert(node.inputs.length == 1);
+    String kind = _primitiveCheckKind(node);
+    return "PrimitiveCheck: $kind $checkedInput to ${node.instructionType}";
+  }
+
+  String _primitiveCheckKind(HPrimitiveCheck node) {
+    if (node.isReceiverTypeCheck) return 'RECEIVER';
+    if (node.isArgumentTypeCheck) return 'ARGUMENT';
+    return '?';
+  }
+
+  @override
+  String visitBoolConversion(HBoolConversion node) {
+    String checkedInput = temporaryId(node.checkedInput);
+    return "BoolConversion: $checkedInput";
+  }
+
+  @override
   String visitTypeKnown(HTypeKnown node) {
     assert(node.inputs.length <= 2);
     String result =
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index 710338c..0a5d8fe 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -85,6 +85,19 @@
     return other;
   }
 
+  /// Produces code that checks the runtime type is actually the type specified
+  /// by attempting a type conversion.
+  HInstruction _checkBoolConverion(HInstruction original) {
+    var checkInstruction =
+        HBoolConversion(original, _abstractValueDomain.boolType);
+    if (checkInstruction.isRedundant(_closedWorld)) {
+      return original;
+    }
+    DartType boolType = _closedWorld.commonElements.boolType;
+    builder.registry?.registerTypeUse(new TypeUse.isCheck(boolType));
+    return checkInstruction;
+  }
+
   HInstruction trustTypeOfParameter(HInstruction original, DartType type) {
     if (type == null) return original;
     HInstruction trusted = _trustType(original, type);
@@ -103,8 +116,7 @@
     if (builder.options.parameterCheckPolicy.isTrusted) {
       checkedOrTrusted = _trustType(original, type);
     } else if (builder.options.parameterCheckPolicy.isEmitted) {
-      checkedOrTrusted =
-          _checkType(original, type, HTypeConversion.CHECKED_MODE_CHECK);
+      checkedOrTrusted = _checkType(original, type, HTypeConversion.TYPE_CHECK);
     }
     if (checkedOrTrusted == original) return original;
     builder.add(checkedOrTrusted);
@@ -116,7 +128,7 @@
   /// trusts the written type.
   HInstruction potentiallyCheckOrTrustTypeOfAssignment(
       HInstruction original, DartType type,
-      {int kind: HTypeConversion.CHECKED_MODE_CHECK}) {
+      {int kind: HTypeConversion.TYPE_CHECK}) {
     if (type == null) return original;
     HInstruction checkedOrTrusted = original;
     if (builder.options.assignmentCheckPolicy.isTrusted) {
@@ -135,8 +147,7 @@
     if (builder.options.conditionCheckPolicy.isTrusted) {
       checkedOrTrusted = _trustType(original, boolType);
     } else if (builder.options.conditionCheckPolicy.isEmitted) {
-      checkedOrTrusted = _checkType(
-          original, boolType, HTypeConversion.BOOLEAN_CONVERSION_CHECK);
+      checkedOrTrusted = _checkBoolConverion(original);
     }
     if (checkedOrTrusted == original) return original;
     builder.add(checkedOrTrusted);
@@ -262,8 +273,6 @@
     return result;
   }
 
-  bool get checkOrTrustTypes => true;
-
   /// Build a [HTypeConversion] for converting [original] to type [type].
   ///
   /// Invariant: [type] must be valid in the context.
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 7079eec..257ce71 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -222,24 +222,29 @@
     HInstruction input = instruction.checkedInput;
     AbstractValue inputType = input.instructionType;
     AbstractValue checkedType = instruction.checkedType;
-    if (instruction.isArgumentTypeCheck || instruction.isReceiverTypeCheck) {
-      // We must make sure a type conversion for receiver or argument check
-      // does not try to do an int check, because an int check is not enough.
-      // We only do an int check if the input is integer or null.
-      if (abstractValueDomain.isNumberOrNull(checkedType).isDefinitelyTrue &&
-          abstractValueDomain.isDoubleOrNull(checkedType).isDefinitelyFalse &&
-          input.isIntegerOrNull(abstractValueDomain).isDefinitelyTrue) {
-        instruction.checkedType = abstractValueDomain.intType;
-      } else if (abstractValueDomain
-              .isIntegerOrNull(checkedType)
-              .isDefinitelyTrue &&
-          input.isIntegerOrNull(abstractValueDomain).isPotentiallyFalse) {
-        instruction.checkedType = abstractValueDomain.numType;
-      }
-    }
-
     AbstractValue outputType =
         abstractValueDomain.intersection(checkedType, inputType);
+    outputType = _numericFixup(outputType, inputType, checkedType);
+    if (inputType != outputType) {
+      // Replace dominated uses of input with uses of this HTypeConversion so
+      // the uses benefit from the stronger type.
+      //
+      // The dependency on the checked value also improves the generated
+      // JavaScript. Many checks are compiled to a function call expression that
+      // returns the checked result, so the check can be generated as a
+      // subexpression rather than a separate statement.
+      //
+      // Do not replace local accesses, since the local must be a HLocalValue,
+      // not a HTypeConversion.
+      if (!(input is HParameterValue && input.usedAsVariable())) {
+        input.replaceAllUsersDominatedBy(instruction.next, instruction);
+      }
+    }
+    return outputType;
+  }
+
+  AbstractValue _numericFixup(AbstractValue outputType, AbstractValue inputType,
+      AbstractValue checkedType) {
     if (abstractValueDomain.isEmpty(outputType).isDefinitelyTrue) {
       // Intersection of double and integer conflicts (is empty), but JS numbers
       // can be both int and double at the same time.  For example, the input
@@ -257,17 +262,38 @@
         }
       }
     }
+    return outputType;
+  }
+
+  @override
+  AbstractValue visitPrimitiveCheck(HPrimitiveCheck instruction) {
+    HInstruction input = instruction.checkedInput;
+    AbstractValue inputType = input.instructionType;
+    AbstractValue checkedType = instruction.checkedType;
+
+    // We must make sure a receiver or argument check does not try to do an int
+    // check, because an int check is not enough.  We only do an int check if
+    // the input is integer or null.
+    if (abstractValueDomain.isNumberOrNull(checkedType).isDefinitelyTrue &&
+        abstractValueDomain.isDoubleOrNull(checkedType).isDefinitelyFalse &&
+        input.isIntegerOrNull(abstractValueDomain).isDefinitelyTrue) {
+      instruction.checkedType = abstractValueDomain.intType;
+    } else if (abstractValueDomain
+            .isIntegerOrNull(checkedType)
+            .isDefinitelyTrue &&
+        input.isIntegerOrNull(abstractValueDomain).isPotentiallyFalse) {
+      instruction.checkedType = abstractValueDomain.numType;
+    }
+
+    AbstractValue outputType =
+        abstractValueDomain.intersection(checkedType, inputType);
+    outputType = _numericFixup(outputType, inputType, checkedType);
     if (inputType != outputType) {
-      // Replace dominated uses of input with uses of this HTypeConversion so
+      // Replace dominated uses of input with uses of this HPrimitiveCheck so
       // the uses benefit from the stronger type.
       //
-      // The dependency on the checked value also improves the generated
-      // JavaScript. Many checks are compiled to a function call expression that
-      // returns the checked result, so the check can be generated as a
-      // subexpression rather than a separate statement.
-      //
-      // Do not replace local accesses, since the local must be a HLocalValue,
-      // not a HTypeConversion.
+      // Do not replace local variable accesses, since the local must be a
+      // HLocalValue, not another kind of instruction.
       if (!(input is HParameterValue && input.usedAsVariable())) {
         input.replaceAllUsersDominatedBy(instruction.next, instruction);
       }
@@ -289,15 +315,17 @@
 
   void convertInput(HInvokeDynamic instruction, HInstruction input,
       AbstractValue type, int kind, DartType typeExpression) {
-    Selector selector = (kind == HTypeConversion.RECEIVER_TYPE_CHECK)
+    assert(kind == HPrimitiveCheck.RECEIVER_TYPE_CHECK ||
+        kind == HPrimitiveCheck.ARGUMENT_TYPE_CHECK);
+    Selector selector = (kind == HPrimitiveCheck.RECEIVER_TYPE_CHECK)
         ? instruction.selector
         : null;
-    HTypeConversion converted = new HTypeConversion(
+    HPrimitiveCheck converted = new HPrimitiveCheck(
         typeExpression, kind, type, input, instruction.sourceInformation,
         receiverTypeCheckSelector: selector);
     instruction.block.addBefore(instruction, converted);
     input.replaceAllUsersDominatedBy(instruction, converted);
-    _log?.registerTypeConversion(instruction, converted);
+    _log?.registerPrimitiveCheck(instruction, converted);
   }
 
   bool isCheckEnoughForNsmOrAe(HInstruction instruction, AbstractValue type) {
@@ -327,7 +355,7 @@
           instruction,
           receiver,
           abstractValueDomain.excludeNull(receiver.instructionType),
-          HTypeConversion.RECEIVER_TYPE_CHECK,
+          HPrimitiveCheck.RECEIVER_TYPE_CHECK,
           commonElements.numType);
       return true;
     } else if (instruction.element == null) {
@@ -353,7 +381,7 @@
         if (!isCheckEnoughForNsmOrAe(receiver, type)) return false;
         instruction.element = target;
         convertInput(instruction, receiver, type,
-            HTypeConversion.RECEIVER_TYPE_CHECK, typeExpression);
+            HPrimitiveCheck.RECEIVER_TYPE_CHECK, typeExpression);
         return true;
       }
     }
@@ -382,7 +410,7 @@
       // still add a check because it allows to GVN these operations,
       // but we should find a better way.
       convertInput(instruction, right, type,
-          HTypeConversion.ARGUMENT_TYPE_CHECK, commonElements.numType);
+          HPrimitiveCheck.ARGUMENT_TYPE_CHECK, commonElements.numType);
       return true;
     }
     return false;
diff --git a/pkg/compiler/lib/src/universe/class_hierarchy.dart b/pkg/compiler/lib/src/universe/class_hierarchy.dart
index 776b4f1..49a899e 100644
--- a/pkg/compiler/lib/src/universe/class_hierarchy.dart
+++ b/pkg/compiler/lib/src/universe/class_hierarchy.dart
@@ -195,10 +195,12 @@
         getClassHierarchyNode(_commonElements.objectClass);
     node.forEachSubclass((ClassEntity cls) {
       getClassHierarchyNode(cls).writeToDataSink(sink);
+      return null;
     }, ClassHierarchyNode.ALL);
     ClassSet set = getClassSet(_commonElements.objectClass);
     set.forEachSubclass((ClassEntity cls) {
       getClassSet(cls).writeToDataSink(sink);
+      return null;
     }, ClassHierarchyNode.ALL);
     sink.end(tag);
   }
@@ -836,6 +838,7 @@
         if (builder._isSubtypeOf(z, y)) {
           classes.add(z);
         }
+        return null;
       }, ClassHierarchyNode.ALL, strict: strict);
     }
 
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index 9b26699..afe16e0 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -10,6 +10,7 @@
 import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
+import '../js_backend/interceptor_data.dart' show OneShotInterceptorData;
 import '../js_backend/native_data.dart' show NativeBasicData;
 import '../js_model/elements.dart';
 import '../util/enumset.dart';
@@ -87,11 +88,17 @@
   /// an ordering that is less sensitive to perturbations in the source code.
   Iterable<ConstantValue> getConstantsForEmission(
       [Comparator<ConstantValue> preSortCompare]);
+
+  /// Returns `true` if [member] is called from a subclass via `super`.
+  bool isAliasedSuperMember(MemberEntity member);
+
+  OneShotInterceptorData get oneShotInterceptorData;
 }
 
 class CodegenWorldBuilderImpl extends WorldBuilderBase
     implements CodegenWorldBuilder {
   final JClosedWorld _closedWorld;
+  final OneShotInterceptorData _oneShotInterceptorData;
 
   /// The set of all directly instantiated classes, that is, classes with a
   /// generative constructor that has been called directly and not only through
@@ -154,7 +161,8 @@
   final Set<DartType> _constTypeLiterals = new Set<DartType>();
   final Set<DartType> _liveTypeArguments = new Set<DartType>();
 
-  CodegenWorldBuilderImpl(this._closedWorld, this._selectorConstraintsStrategy);
+  CodegenWorldBuilderImpl(this._closedWorld, this._selectorConstraintsStrategy,
+      this._oneShotInterceptorData);
 
   ElementEnvironment get _elementEnvironment => _closedWorld.elementEnvironment;
 
@@ -582,7 +590,8 @@
         invokedGetters: _invokedGetters,
         invokedSetters: _invokedSetters,
         staticTypeArgumentDependencies: staticTypeArgumentDependencies,
-        dynamicTypeArgumentDependencies: dynamicTypeArgumentDependencies);
+        dynamicTypeArgumentDependencies: dynamicTypeArgumentDependencies,
+        oneShotInterceptorData: _oneShotInterceptorData);
   }
 }
 
@@ -624,6 +633,9 @@
 
   final Map<Selector, Set<DartType>> _dynamicTypeArgumentDependencies;
 
+  @override
+  final OneShotInterceptorData oneShotInterceptorData;
+
   CodegenWorldImpl(this._closedWorld, this._liveMemberUsage,
       {this.constTypeLiterals,
       this.directlyInstantiatedClasses,
@@ -637,7 +649,8 @@
       Map<String, Map<Selector, SelectorConstraints>> invokedGetters,
       Map<String, Map<Selector, SelectorConstraints>> invokedSetters,
       Map<Entity, Set<DartType>> staticTypeArgumentDependencies,
-      Map<Selector, Set<DartType>> dynamicTypeArgumentDependencies})
+      Map<Selector, Set<DartType>> dynamicTypeArgumentDependencies,
+      this.oneShotInterceptorData})
       : _compiledConstants = compiledConstants,
         _invokedNames = invokedNames,
         _invokedGetters = invokedGetters,
@@ -866,4 +879,12 @@
     }
     return result;
   }
+
+  @override
+  bool isAliasedSuperMember(MemberEntity member) {
+    MemberUsage usage = _liveMemberUsage[member];
+    if (usage == null) return false;
+    return usage.invokes.contains(Access.superAccess) ||
+        usage.writes.contains(Access.superAccess);
+  }
 }
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index d062fc5..5e124f3 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -901,9 +901,12 @@
   /// Type constant used for registration of custom elements.
   ConstantUse.customElements(TypeConstantValue value) : this._(value);
 
-  /// Constant literal used on code.
+  /// Constant literal used in code.
   ConstantUse.literal(ConstantValue value) : this._(value);
 
+  /// Deferred constant used in code.
+  ConstantUse.deferred(DeferredGlobalConstantValue value) : this._(value);
+
   @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
diff --git a/pkg/compiler/tool/modular_dart2js.dart b/pkg/compiler/tool/modular_dart2js.dart
new file mode 100644
index 0000000..f8e15e3
--- /dev/null
+++ b/pkg/compiler/tool/modular_dart2js.dart
@@ -0,0 +1,180 @@
+// Copyright (c) 2019, 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:compiler/src/commandline_options.dart';
+
+main(List<String> args) async {
+  Stopwatch stopwatch = new Stopwatch();
+  String input;
+  String serializedInput;
+  String output = 'out.js';
+  List<String> arguments = [];
+  int start = 0;
+  int stop = 3;
+  int shards;
+  bool enableAssertions = false;
+  for (String arg in args) {
+    if (arg.startsWith('-')) {
+      if (arg.startsWith('--start=')) {
+        start = int.parse(arg.substring('--start='.length));
+      } else if (arg.startsWith('--stop=')) {
+        stop = int.parse(arg.substring('--stop='.length));
+      } else if (arg.startsWith('--shards=')) {
+        shards = int.parse(arg.substring('--shards='.length));
+      } else if (arg == '-ea' || arg == '--enable_asserts') {
+        enableAssertions = true;
+      } else if (arg.startsWith('--in=')) {
+        serializedInput = arg.substring('--in='.length);
+      } else if (arg.startsWith('-o')) {
+        output = arg.substring('-o'.length);
+      } else if (arg.startsWith('--out=')) {
+        output = arg.substring('--out='.length);
+      } else {
+        arguments.add(arg);
+      }
+    } else {
+      if (input != null) {
+        print("Multiple entrypoints provided: '${input}' and '${arg}'.");
+        exit(-1);
+      }
+      input = arg;
+    }
+  }
+
+  if (input == null) {
+    print("No entrypoint provided.");
+    exit(-1);
+  }
+
+  serializedInput ??= output;
+
+  String inputPrefix = serializedInput;
+  if (serializedInput.endsWith('.js')) {
+    inputPrefix = output.substring(0, output.length - '.js'.length);
+  }
+  String outputPrefix = output;
+  if (output.endsWith('.js')) {
+    outputPrefix = output.substring(0, output.length - '.js'.length);
+  }
+
+  List<String> baseOptions = ['--packages=${Platform.packageConfig}'];
+  if (enableAssertions) {
+    baseOptions.add('--enable_asserts');
+  }
+  baseOptions.add('package:compiler/src/dart2js.dart');
+  baseOptions.addAll(arguments);
+
+  String cfeOutput = '${inputPrefix}0.dill';
+  String dillOutput = '${inputPrefix}.dill';
+  String dataOutput = '${inputPrefix}.dill.data';
+  String codeOutput = '${outputPrefix}.code';
+  shards ??= 2;
+
+  stopwatch.start();
+  if (start <= 0 && stop >= 0) {
+    await subProcess(
+        baseOptions, [input, Flags.cfeOnly, '--out=$cfeOutput'], '0:\t');
+  }
+  if (start <= 1 && stop >= 1) {
+    await subProcess(
+        baseOptions,
+        [cfeOutput, '--out=$dillOutput', '${Flags.writeData}=${dataOutput}'],
+        '1:\t');
+  }
+  if (shards <= 1) {
+    await subProcess(
+        baseOptions,
+        [dillOutput, '${Flags.readData}=${dataOutput}', '--out=${output}'],
+        '3:\t');
+  } else {
+    if (start <= 2 && stop >= 2) {
+      List<List<String>> additionalArguments = [];
+      List<String> outputPrefixes = [];
+      for (int shard = 0; shard < shards; shard++) {
+        additionalArguments.add([
+          dillOutput,
+          '${Flags.readData}=${dataOutput}',
+          '${Flags.codegenShard}=$shard',
+          '${Flags.codegenShards}=$shards',
+          '${Flags.writeCodegen}=${codeOutput}'
+        ]);
+        outputPrefixes.add('2:${shard + 1}/$shards\t');
+      }
+
+      Stopwatch subwatch = new Stopwatch();
+      subwatch.start();
+      await Future.wait(new List<Future>.generate(shards, (int shard) {
+        return subProcess(
+            baseOptions, additionalArguments[shard], outputPrefixes[shard]);
+      }));
+      subwatch.stop();
+      print('2:\tTotal time: ${_formatMs(subwatch.elapsedMilliseconds)}');
+    }
+    if (start <= 3 && stop >= 3) {
+      await subProcess(
+          baseOptions,
+          [
+            dillOutput,
+            '${Flags.readData}=${dataOutput}',
+            '${Flags.readCodegen}=${codeOutput}',
+            '${Flags.codegenShards}=$shards',
+            '--out=${output}'
+          ],
+          '3:\t');
+    }
+  }
+  stopwatch.stop();
+  print('Total time: ${_formatMs(stopwatch.elapsedMilliseconds)}');
+}
+
+Future subProcess(List<String> baseOptions, List<String> additionalOptions,
+    String outputPrefix) async {
+  List<String> options = []..addAll(baseOptions)..addAll(additionalOptions);
+  print(
+      '${outputPrefix}Command: ${Platform.resolvedExecutable} ${options.join(' ')}');
+  Process process = await Process.start(Platform.resolvedExecutable, options,
+      runInShell: true);
+  _Prefixer stdoutPrefixer = new _Prefixer(outputPrefix, stdout);
+  _Prefixer stderrOutputter = new _Prefixer(outputPrefix, stderr);
+  process.stdout.transform(utf8.decoder).listen(stdoutPrefixer);
+  process.stderr.transform(utf8.decoder).listen(stderrOutputter);
+
+  int exitCode = await process.exitCode;
+  if (exitCode != 0) {
+    exit(exitCode);
+  }
+}
+
+class _Prefixer {
+  final String _prefix;
+  final Stdout _stdout;
+  bool _atNewLine = true;
+
+  _Prefixer(this._prefix, this._stdout);
+
+  void call(String text) {
+    int index = 0;
+    while (index < text.length) {
+      if (_atNewLine) {
+        _stdout.write(_prefix);
+        _atNewLine = false;
+      }
+      int pos = text.indexOf('\n', index);
+      if (pos != -1) {
+        _stdout.write(text.substring(index, pos + 1));
+        _atNewLine = true;
+        index = pos + 1;
+      } else {
+        _stdout.write(text.substring(index));
+        index = text.length;
+      }
+    }
+  }
+}
+
+String _formatMs(int ms) {
+  return (ms / 1000).toStringAsFixed(3) + 's';
+}
diff --git a/pkg/dev_compiler/analysis_options.yaml b/pkg/dev_compiler/analysis_options.yaml
index 43cfad3..29c4ac1 100644
--- a/pkg/dev_compiler/analysis_options.yaml
+++ b/pkg/dev_compiler/analysis_options.yaml
@@ -1,4 +1,6 @@
 analyzer:
+  strong-mode:
+    implicit-casts: false
   errors:
     todo: ignore
   exclude:
@@ -29,5 +31,6 @@
     - recursive_getters
     - type_init_formals
     - unnecessary_null_in_if_null_operators
+    - unrelated_type_equality_checks
     - use_rethrow_when_possible
     - valid_regexps
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index f97e1c2..3ff97b0 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -24,7 +24,6 @@
 import 'package:analyzer/src/generated/resolver.dart'
     show TypeProvider, NamespaceBuilder;
 import 'package:analyzer/src/generated/type_system.dart' show Dart2TypeSystem;
-import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/src/task/strong/ast_properties.dart';
 import 'package:path/path.dart' as path;
@@ -428,7 +427,7 @@
   String jsLibraryName(LibraryElement library) {
     var uri = library.source.uri;
     if (uri.scheme == 'dart') {
-      return uri.path;
+      return isSdkInternalRuntime(library) ? 'dart' : uri.path;
     }
     // TODO(vsm): This is not necessarily unique if '__' appears in a file name.
     var encodedSeparator = '__';
@@ -467,6 +466,10 @@
   }
 
   @override
+  Iterable<String> jsPartDebuggerNames(LibraryElement library) =>
+      library.parts.map((part) => part.uri);
+
+  @override
   String libraryToModule(LibraryElement library) {
     var source = library.source;
     // TODO(jmesserly): we need to split out HTML.
@@ -610,7 +613,7 @@
 
   @override
   visitExportDirective(ExportDirective node) {
-    ExportElement element = node.element;
+    var element = node.element as ExportElement;
     var currentLibrary = element.library;
 
     var currentNames = currentLibrary.publicNamespace.definedNames;
@@ -696,7 +699,7 @@
         // TODO(jmesserly): fuse this with notNull check.
         // TODO(jmesserly): this does not correctly distinguish user casts from
         // required-for-soundness casts.
-        return runtimeCall('asInt(#)', jsFrom);
+        return runtimeCall('asInt(#)', [jsFrom]);
       }
 
       // A no-op in JavaScript.
@@ -1544,7 +1547,7 @@
           param = covariantParams.lookup(param) as ParameterElement;
 
           if (param == null) continue;
-          if (param.kind == ParameterKind.NAMED) {
+          if (param.isNamed) {
             foundNamedParams = true;
 
             var name = propertyName(param.name);
@@ -1557,10 +1560,12 @@
             var jsParam = _emitParameter(param);
             jsParams.add(jsParam);
 
-            if (param.kind == ParameterKind.POSITIONAL) {
+            if (param.isPositional) {
               body.add(js.statement('if (# !== void 0) #;',
                   [jsParam, _emitCast(param.type, jsParam)]));
             } else {
+              //TODO(nshahan) Cleanup this logic. Do we need this else branch?
+              // https://github.com/dart-lang/sdk/issues/37123
               body.add(_emitCast(param.type, jsParam).toStatement());
             }
           }
@@ -1834,8 +1839,8 @@
       ClassElement classElem, String jsPeerName, List<JS.Statement> body) {
     var className = _emitTopLevelName(classElem);
     if (jsTypeRep.isPrimitive(classElem.type)) {
-      body.add(
-          runtimeStatement('definePrimitiveHashCode(#.prototype)', className));
+      body.add(runtimeStatement(
+          'definePrimitiveHashCode(#.prototype)', [className]));
     }
     body.add(runtimeStatement(
         'registerExtension(#, #)', [js.string(jsPeerName), className]));
@@ -2175,6 +2180,10 @@
       emitSignature('Setter', instanceSetters);
       emitSignature('StaticGetter', staticGetters);
       emitSignature('StaticSetter', staticSetters);
+      body.add(runtimeStatement('setLibraryUri(#, #)', [
+        className,
+        js.escapedString(jsLibraryDebuggerName(classElem.library))
+      ]));
     }
 
     {
@@ -2275,7 +2284,7 @@
   JS.Block _emitConstructorBody(ConstructorDeclaration node,
       List<VariableDeclaration> fields, JS.Expression className) {
     var body = <JS.Statement>[];
-    ClassDeclaration cls = node.parent;
+    var cls = node.parent as ClassDeclaration;
 
     // Generate optional/named argument value assignment. These can not have
     // side effects, and may be used by the constructor's initializers, so it's
@@ -2574,7 +2583,7 @@
     }
 
     if (node.isGetter || node.isSetter) {
-      PropertyAccessorElement element = node.declaredElement;
+      var element = node.declaredElement as PropertyAccessorElement;
       var pairAccessor = node.isGetter
           ? element.correspondingSetter
           : element.correspondingGetter;
@@ -2718,7 +2727,7 @@
 
     // Simplify `=> { return e; }` to `=> e`
     if (body is JS.Block) {
-      JS.Block block = body;
+      var block = body as JS.Block;
       if (block.statements.length == 1) {
         JS.Statement s = block.statements[0];
         if (s is JS.Return && s.value != null) body = s.value;
@@ -3044,7 +3053,7 @@
       // If the type is a type literal expression in Dart code, wrap the raw
       // runtime type in a "Type" instance.
       if (!_isInForeignJS && _isTypeLiteral(node)) {
-        typeName = runtimeCall('wrapType(#)', typeName);
+        typeName = runtimeCall('wrapType(#)', [typeName]);
       }
 
       return typeName;
@@ -3283,7 +3292,7 @@
     if (_isExternal(member)) {
       var nativeName = _extensionTypes.getNativePeers(c);
       if (nativeName.isNotEmpty) {
-        return runtimeCall('global.#', nativeName[0]);
+        return runtimeCall('global.#', [nativeName[0]]);
       }
     }
     return _emitTopLevelName(c);
@@ -3321,7 +3330,8 @@
     // Anonymous JS types do not have a corresponding concrete JS type so we
     // have to use a helper to define them.
     if (_isObjectLiteral(element)) {
-      return runtimeCall('anonymousJSType(#)', js.escapedString(element.name));
+      return runtimeCall(
+          'anonymousJSType(#)', [js.escapedString(element.name)]);
     }
     var jsName = _getJSNameWithoutGlobal(element);
     if (jsName != null) {
@@ -3772,7 +3782,8 @@
     // Handle Object methods that are supported by `null`.
     if (_isObjectMethodCall(name, argumentList.arguments) &&
         isNullable(target)) {
-      assert(typeArgs == null); // Object methods don't take type args.
+      assert(typeArgs == null ||
+          typeArgs.isEmpty); // Object methods don't take type args.
       return runtimeCall('#(#, #)', [name, jsTarget, args]);
     }
 
@@ -4142,16 +4153,26 @@
     if (conditionType is FunctionType &&
         conditionType.parameters.isEmpty &&
         conditionType.returnType == types.boolType) {
-      jsCondition = runtimeCall('test(#())', jsCondition);
+      jsCondition = runtimeCall('test(#())', [jsCondition]);
     } else if (conditionType != types.boolType) {
-      jsCondition = runtimeCall('dassert(#)', jsCondition);
+      jsCondition = runtimeCall('dassert(#)', [jsCondition]);
     } else if (isNullable(condition)) {
-      jsCondition = runtimeCall('test(#)', jsCondition);
+      jsCondition = runtimeCall('test(#)', [jsCondition]);
     }
-    return js.statement(' if (!#) #.assertFailed(#);', [
+
+    var location = _getLocation(condition.offset);
+    return js.statement(' if (!#) #.assertFailed(#, #, #, #, #);', [
       jsCondition,
       runtimeModule,
-      message != null ? [_visitExpression(message)] : []
+      if (message == null)
+        JS.LiteralNull()
+      else
+        _visitExpression(message),
+      js.escapedString(location.sourceUrl.toString()),
+      // Lines and columns are typically printed with 1 based indexing.
+      js.number(location.line + 1),
+      js.number(location.column + 1),
+      js.escapedString(condition.toSource()),
     ]);
   }
 
@@ -4552,7 +4573,7 @@
     if (expr == null) return null;
     var jsExpr = _visitExpression(expr);
     if (!isNullable(expr)) return jsExpr;
-    return runtimeCall('notNull(#)', jsExpr);
+    return runtimeCall('notNull(#)', [jsExpr]);
   }
 
   JS.Expression _emitEqualityOperator(BinaryExpression node, Token op) {
@@ -5036,6 +5057,11 @@
     var op = node.operator;
     var expr = node.operand;
 
+    if (op.type == TokenType.BANG) {
+      // If the expression is non-nullable already, this is a no-op.
+      return isNullable(expr) ? notNull(expr) : _visitExpression(expr);
+    }
+
     var dispatchType = getStaticType(expr);
     if (jsTypeRep.unaryOperationIsPrimitive(dispatchType)) {
       if (!isNullable(expr)) {
@@ -5362,12 +5388,13 @@
 
   @override
   JS.Expression visitThrowExpression(ThrowExpression node) {
-    return runtimeCall('throw(#)', _visitExpression(node.expression));
+    return runtimeCall('throw(#)', [_visitExpression(node.expression)]);
   }
 
   @override
   JS.Expression visitRethrowExpression(RethrowExpression node) {
-    return runtimeCall('rethrow(#)', _emitSimpleIdentifier(_rethrowParameter));
+    return runtimeCall(
+        'rethrow(#)', [_emitSimpleIdentifier(_rethrowParameter)]);
   }
 
   /// Visits a statement, and ensures the resulting AST handles block scope
@@ -5774,7 +5801,7 @@
         var jsExpr = _visitExpression(e);
         parts.add(e.staticType == types.stringType && !isNullable(e)
             ? jsExpr
-            : runtimeCall('str(#)', jsExpr));
+            : runtimeCall('str(#)', [jsExpr]));
       }
     }
     if (parts.isEmpty) return js.string('');
@@ -5843,8 +5870,7 @@
     /// fucntion, call it, and yield the result of [yieldType].
     /// TODO(nshahan) Move to share between compilers. Need to work out a common
     /// emitLibraryName().
-    JS.Expression detectYieldAndCall(
-        JS.Statement body, InterfaceType yieldType) {
+    JS.Expression detectYieldAndCall(JS.Block body, InterfaceType yieldType) {
       var finder = YieldFinder();
       body.accept(finder);
       if (finder.hasYield) {
@@ -5871,7 +5897,7 @@
         // a function call that returns the list.
         var functionBody = JS.Block([
           items,
-          node.accept<JS.Node>(this),
+          node.accept<JS.Node>(this) as JS.Statement,
           JS.Return(_currentCollectionVariable)
         ]);
         var functionCall = detectYieldAndCall(functionBody, arrayType);
@@ -5902,7 +5928,7 @@
       ]);
     }
 
-    return pushToCurrentCollection(node);
+    return pushToCurrentCollection(node as Expression);
   }
 
   /// Returns `true` if [node] is a UI-as-Code [CollectionElement].
@@ -6019,10 +6045,10 @@
     }
     if (node is AsExpression && CoercionReifier.isImplicit(node)) {
       assert(node.staticType == types.boolType);
-      return runtimeCall('dtest(#)', _visitExpression(node.expression));
+      return runtimeCall('dtest(#)', [_visitExpression(node.expression)]);
     }
     var result = _visitExpression(node);
-    if (isNullable(node)) result = runtimeCall('test(#)', result);
+    if (isNullable(node)) result = runtimeCall('test(#)', [result]);
     return result;
   }
 
@@ -6291,9 +6317,9 @@
   }
 
   JS.Expression _throwUnsafe(String message) => runtimeCall(
-      'throw(Error(#))', js.escapedString("compile error: $message"));
+      'throw(Error(#))', [js.escapedString("compile error: $message")]);
 
-  JS.Node _unreachable(Object node) {
+  Null _unreachable(Object node) {
     throw UnsupportedError('tried to generate an unreachable node: `$node`');
   }
 
@@ -6489,7 +6515,7 @@
   @override
   JS.Statement visitForElement(ForElement node) {
     var jsBody = _isUiAsCodeElement(node.body)
-        ? node.body.accept(this)
+        ? node.body.accept(this) as JS.Statement
         : _visitNestedCollectionElement(node.body);
     return _forAdaptor(node.forLoopParts, node.awaitKeyword, jsBody);
   }
@@ -6497,13 +6523,13 @@
   @override
   JS.Statement visitIfElement(IfElement node) {
     var thenElement = _isUiAsCodeElement(node.thenElement)
-        ? node.thenElement.accept(this)
+        ? node.thenElement.accept(this) as JS.Statement
         : _visitNestedCollectionElement(node.thenElement);
 
     JS.Statement elseElement;
     if (node.elseElement != null) {
       if (_isUiAsCodeElement(node.elseElement)) {
-        elseElement = node.elseElement.accept<JS.Node>(this);
+        elseElement = node.elseElement.accept<JS.Node>(this) as JS.Statement;
       } else {
         elseElement = _visitNestedCollectionElement(node.elseElement);
       }
@@ -6583,7 +6609,8 @@
     /// Returns [expression] wrapped in an implict cast to [castType] or
     /// [expression] as provided if [castType] is `null` signifying that
     /// no cast is needed.
-    JS.Expression wrapInImplicitCast(JS.Expression expression, castType) =>
+    JS.Expression wrapInImplicitCast(
+            JS.Expression expression, DartType castType) =>
         castType == null ? expression : _emitCast(castType, expression);
 
     /// Returns a statement spreading the elements of [expression] into
@@ -6673,6 +6700,9 @@
   @override
   visitForPartsWithExpression(ForPartsWithExpression node) =>
       _unreachable(node);
+
+  @override
+  visitExtensionDeclaration(ExtensionDeclaration node) => _unreachable(node);
 }
 
 // TODO(jacobr): we would like to do something like the following
diff --git a/pkg/dev_compiler/lib/src/analyzer/driver.dart b/pkg/dev_compiler/lib/src/analyzer/driver.dart
index 8d55999..9e9cb02 100644
--- a/pkg/dev_compiler/lib/src/analyzer/driver.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/driver.dart
@@ -81,10 +81,10 @@
     var resourceProvider = options.resourceProvider;
     var contextBuilder = options.createContextBuilder();
 
-    var analysisOptions =
-        contextBuilder.getAnalysisOptions(options.analysisRoot);
+    var analysisOptions = contextBuilder
+        .getAnalysisOptions(options.analysisRoot) as AnalysisOptionsImpl;
 
-    (analysisOptions as AnalysisOptionsImpl).enabledExperiments =
+    analysisOptions.enabledExperiments =
         experiments.entries.where((e) => e.value).map((e) => e.key).toList();
 
     var dartSdk = contextBuilder.findSdk(null, analysisOptions);
@@ -336,7 +336,7 @@
 
     var libraryFile = _fsState.getFileForUri(Uri.parse(libraryUri));
     var analyzer = LibraryAnalyzer(
-        analysisOptions,
+        analysisOptions as AnalysisOptionsImpl,
         declaredVariables,
         resynthesizer.sourceFactory,
         (uri) => _isLibraryUri('$uri'),
diff --git a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
index 45f443f..e8fe0f0 100644
--- a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
@@ -124,7 +124,7 @@
   if (node == null) return false;
   var parent = node.parent;
   while (parent is ParenthesizedExpression) {
-    node = parent;
+    node = parent as Expression;
     parent = node.parent;
   }
   return parent is InvocationExpression && identical(node, parent.function) ||
diff --git a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
index a88c582..94f1c2edb 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
@@ -59,8 +59,7 @@
     var block = toStatement();
     var s = block.statements;
     if (s.length == 1 && s.first is ExpressionStatement) {
-      ExpressionStatement es = s.first;
-      return es.expression;
+      return (s.first as ExpressionStatement).expression;
     }
 
     return _toInvokedFunction(block);
@@ -114,8 +113,7 @@
     var block = toReturn();
     var s = block.statements;
     if (s.length == 1 && s.first is Return) {
-      Return es = s.first;
-      return _expression = es.value;
+      return _expression = (s.first as Return).value;
     }
     // Wrap it in an immediately called function to get in expression context.
     return _expression = _toInvokedFunction(block);
@@ -280,7 +278,7 @@
       }
 
       assert(body.isNotEmpty);
-      Binary newBody = Expression.binary([assign]..addAll(body), ',');
+      var newBody = Expression.binary([assign]..addAll(body), ',') as Binary;
       newBody = _substitute(newBody, {result: left});
       return MetaLet(vars, newBody.commaToExpressionList(),
           statelessResult: statelessResult);
diff --git a/pkg/dev_compiler/lib/src/compiler/js_names.dart b/pkg/dev_compiler/lib/src/compiler/js_names.dart
index a5afca2..24d3dbd 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_names.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_names.dart
@@ -207,7 +207,7 @@
       if (node is FunctionExpression) {
         super.visitFunctionExpression(node);
       } else {
-        super.visitClassExpression(node);
+        super.visitClassExpression(node as ClassExpression);
       }
       _finishScopes();
       scope = scope.parent;
diff --git a/pkg/dev_compiler/lib/src/compiler/js_utils.dart b/pkg/dev_compiler/lib/src/compiler/js_utils.dart
index 74820eb..997702f 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_utils.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_utils.dart
@@ -10,7 +10,7 @@
   if (fn.body is Block && fn.body.statements.length == 1) {
     var stat = fn.body.statements.single;
     if (stat is Return && stat.value is Call) {
-      Call call = stat.value;
+      var call = stat.value as Call;
       var innerFun = call.target;
       if (innerFun is ArrowFun &&
           call.arguments.isEmpty &&
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index 05cc667..6a3182d 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -108,6 +108,10 @@
   @protected
   String jsLibraryDebuggerName(Library library);
 
+  /// Debugger friendly names for all parts in a Dart [library].
+  @protected
+  Iterable<String> jsPartDebuggerNames(Library library);
+
   /// Gets the module import URI that contains [library].
   @protected
   String libraryToModule(Library library);
@@ -142,7 +146,7 @@
     if (name == '[]=') {
       _operatorSetResultStack.add(isLastParamMutated()
           ? JS.TemporaryId((formals.last as JS.Identifier).name)
-          : formals.last);
+          : formals.last as JS.Identifier);
     } else {
       _operatorSetResultStack.add(null);
     }
@@ -202,34 +206,21 @@
   ///
   /// For example:
   ///
-  ///     runtimeCall('asInt(#)', expr)
+  ///     runtimeCall('asInt(#)', [<expr>])
   ///
   /// Generates a JS AST representing:
   ///
   ///     dart.asInt(<expr>)
   ///
   @protected
-  JS.Expression runtimeCall(String code, [args]) {
-    if (args != null) {
-      var newArgs = <Object>[runtimeModule];
-      if (args is Iterable) {
-        newArgs.addAll(args);
-      } else {
-        newArgs.add(args);
-      }
-      args = newArgs;
-    } else {
-      args = runtimeModule;
-    }
-    return js.call('#.$code', args);
-  }
+  JS.Expression runtimeCall(String code, [List<Object> args]) =>
+      js.call('#.$code', <Object>[runtimeModule, ...?args]);
 
   /// Calls [runtimeCall] and uses `toStatement()` to convert the resulting
   /// expression into a statement.
   @protected
-  JS.Statement runtimeStatement(String code, [args]) {
-    return runtimeCall(code, args).toStatement();
-  }
+  JS.Statement runtimeStatement(String code, [List<Object> args]) =>
+      runtimeCall(code, args).toStatement();
 
   /// Emits a private name JS Symbol for [name] scoped to the Dart [library].
   ///
@@ -342,7 +333,7 @@
   /// constant instance of a user-defined class stored in [expr].
   @protected
   JS.Expression canonicalizeConstObject(JS.Expression expr) =>
-      cacheConst(runtimeCall('const(#)', expr));
+      cacheConst(runtimeCall('const(#)', [expr]));
 
   /// Emits preamble for the module containing [libraries], and returns the
   /// list of module items for further items to be added.
@@ -486,19 +477,25 @@
 
   void _emitDebuggerExtensionInfo(String name) {
     var properties = <JS.Property>[];
+    var parts = <JS.Property>[];
     _libraries.forEach((library, value) {
       // TODO(jacobr): we could specify a short library name instead of the
       // full library uri if we wanted to save space.
-      properties.add(
-          JS.Property(js.escapedString(jsLibraryDebuggerName(library)), value));
+      var libraryName = js.escapedString(jsLibraryDebuggerName(library));
+      properties.add(JS.Property(libraryName, value));
+      var partNames = jsPartDebuggerNames(library);
+      if (partNames.isNotEmpty) {
+        parts.add(JS.Property(libraryName, js.stringArray(partNames)));
+      }
     });
     var module = JS.ObjectInitializer(properties, multiline: true);
+    var partMap = JS.ObjectInitializer(parts, multiline: true);
 
     // Track the module name for each library in the module.
     // This data is only required for debugging.
     moduleItems.add(js.statement(
-        '#.trackLibraries(#, #, $sourceMapLocationID);',
-        [runtimeModule, js.string(name), module]));
+        '#.trackLibraries(#, #, #, $sourceMapLocationID);',
+        [runtimeModule, js.string(name), module, partMap]));
   }
 
   /// Finishes the module created by [startModule], by combining the preable
diff --git a/pkg/dev_compiler/lib/src/js_ast/printer.dart b/pkg/dev_compiler/lib/src/js_ast/printer.dart
index 38b7fea..f4a9717 100644
--- a/pkg/dev_compiler/lib/src/js_ast/printer.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/printer.dart
@@ -133,7 +133,7 @@
   String lastAddedString;
   int get lastCharCode {
     if (lastAddedString == null) return 0;
-    assert(lastAddedString.length != "");
+    assert(lastAddedString.isNotEmpty);
     return lastAddedString.codeUnitAt(lastAddedString.length - 1);
   }
 
@@ -1284,7 +1284,7 @@
   nameSpecifierListOut(List<NameSpecifier> names, bool export) {
     if (names == null) return;
 
-    if (names.length == 1 && names[0].name == '*') {
+    if (names.length == 1 && names[0].name.name == '*') {
       nameSpecifierOut(names[0], export);
       return;
     }
@@ -1306,7 +1306,7 @@
     if (from != null) {
       out(' from');
       spaceOut();
-      visit(from);
+      out("'${from.valueWithoutQuotes}.js'");
     }
   }
 
diff --git a/pkg/dev_compiler/lib/src/js_ast/template.dart b/pkg/dev_compiler/lib/src/js_ast/template.dart
index b876e7c..6363cd6 100644
--- a/pkg/dev_compiler/lib/src/js_ast/template.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/template.dart
@@ -361,7 +361,7 @@
 
   @override
   Instantiator<Statement> visitExpressionStatement(ExpressionStatement node) {
-    Instantiator<Expression> makeExpression = visit(node.expression);
+    var makeExpression = visit(node.expression) as Instantiator<Expression>;
     return (a) => makeExpression(a).toStatement();
   }
 
@@ -385,8 +385,8 @@
 
   Instantiator<Statement> visitIfConditionalCompilation(
       If node, InterpolatedExpression condition) {
-    Instantiator<Statement> makeThen = visit(node.then);
-    Instantiator<Statement> makeOtherwise = visit(node.otherwise);
+    var makeThen = visit(node.then) as Instantiator<Statement>;
+    var makeOtherwise = visit(node.otherwise) as Instantiator<Statement>;
     return (arguments) {
       // Allow bools to be used for conditional compliation.
       var nameOrPosition = condition.nameOrPosition;
@@ -400,49 +400,50 @@
   }
 
   Instantiator<Statement> visitIfNormal(If node) {
-    Instantiator<Expression> makeCondition = visit(node.condition);
-    Instantiator<Statement> makeThen = visit(node.then);
-    Instantiator<Statement> makeOtherwise = visit(node.otherwise);
+    var makeCondition = visit(node.condition) as Instantiator<Expression>;
+    var makeThen = visit(node.then) as Instantiator<Statement>;
+    var makeOtherwise = visit(node.otherwise) as Instantiator<Statement>;
     return (a) => If(makeCondition(a), makeThen(a), makeOtherwise(a));
   }
 
   @override
   Instantiator<Statement> visitFor(For node) {
-    Instantiator<Expression> makeInit = visitNullable(node.init);
-    Instantiator<Expression> makeCondition = visitNullable(node.condition);
-    Instantiator<Expression> makeUpdate = visitNullable(node.update);
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeInit = visitNullable(node.init) as Instantiator<Expression>;
+    var makeCondition =
+        visitNullable(node.condition) as Instantiator<Expression>;
+    var makeUpdate = visitNullable(node.update) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => For(makeInit(a), makeCondition(a),
         makeUpdate(a)?.toVoidExpression(), makeBody(a));
   }
 
   @override
   Instantiator<ForIn> visitForIn(ForIn node) {
-    Instantiator<Expression> makeLeftHandSide = visit(node.leftHandSide);
-    Instantiator<Expression> makeObject = visit(node.object);
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeLeftHandSide = visit(node.leftHandSide) as Instantiator<Expression>;
+    var makeObject = visit(node.object) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => ForIn(makeLeftHandSide(a), makeObject(a), makeBody(a));
   }
 
   @override
   Instantiator<ForOf> visitForOf(ForOf node) {
-    Instantiator<Expression> makeLeftHandSide = visit(node.leftHandSide);
-    Instantiator<Expression> makeObject = visit(node.iterable);
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeLeftHandSide = visit(node.leftHandSide) as Instantiator<Expression>;
+    var makeObject = visit(node.iterable) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => ForOf(makeLeftHandSide(a), makeObject(a), makeBody(a));
   }
 
   @override
   Instantiator<While> visitWhile(While node) {
-    Instantiator<Expression> makeCondition = visit(node.condition);
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeCondition = visit(node.condition) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => While(makeCondition(a), makeBody(a));
   }
 
   @override
   Instantiator<Do> visitDo(Do node) {
-    Instantiator<Statement> makeBody = visit(node.body);
-    Instantiator<Expression> makeCondition = visit(node.condition);
+    var makeBody = visit(node.body) as Instantiator<Statement>;
+    var makeCondition = visit(node.condition) as Instantiator<Expression>;
     return (a) => Do(makeBody(a), makeCondition(a));
   }
 
@@ -456,48 +457,49 @@
   @override
   Instantiator<Statement> visitReturn(Return node) {
     if (node.value == null) return (args) => Return();
-    Instantiator<Expression> makeExpression = visit(node.value);
+    var makeExpression = visit(node.value) as Instantiator<Expression>;
     return (a) => makeExpression(a).toReturn();
   }
 
   @override
   Instantiator<DartYield> visitDartYield(DartYield node) {
-    Instantiator<Expression> makeExpression = visit(node.expression);
+    var makeExpression = visit(node.expression) as Instantiator<Expression>;
     return (a) => DartYield(makeExpression(a), node.hasStar);
   }
 
   @override
   Instantiator<Throw> visitThrow(Throw node) {
-    Instantiator<Expression> makeExpression = visit(node.expression);
+    var makeExpression = visit(node.expression) as Instantiator<Expression>;
     return (a) => Throw(makeExpression(a));
   }
 
   @override
   Instantiator<Try> visitTry(Try node) {
-    Instantiator<Block> makeBody = visit(node.body);
-    Instantiator<Catch> makeCatch = visitNullable(node.catchPart);
-    Instantiator<Block> makeFinally = visitNullable(node.finallyPart);
+    var makeBody = visit(node.body) as Instantiator<Block>;
+    var makeCatch = visitNullable(node.catchPart) as Instantiator<Catch>;
+    var makeFinally = visitNullable(node.finallyPart) as Instantiator<Block>;
     return (a) => Try(makeBody(a), makeCatch(a), makeFinally(a));
   }
 
   @override
   Instantiator<Catch> visitCatch(Catch node) {
-    Instantiator<Identifier> makeDeclaration = visit(node.declaration);
-    Instantiator<Block> makeBody = visit(node.body);
+    var makeDeclaration = visit(node.declaration) as Instantiator<Identifier>;
+    var makeBody = visit(node.body) as Instantiator<Block>;
     return (a) => Catch(makeDeclaration(a), makeBody(a));
   }
 
   @override
   Instantiator<Switch> visitSwitch(Switch node) {
-    Instantiator<Expression> makeKey = visit(node.key);
+    var makeKey = visit(node.key) as Instantiator<Expression>;
     var makeCases = node.cases.map(visitSwitchCase).toList();
     return (a) => Switch(makeKey(a), makeCases.map((m) => m(a)).toList());
   }
 
   @override
   Instantiator<SwitchCase> visitSwitchCase(SwitchCase node) {
-    Instantiator<Expression> makeExpression = visitNullable(node.expression);
-    Instantiator<Block> makeBody = visit(node.body);
+    var makeExpression =
+        visitNullable(node.expression) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Block>;
     return (arguments) {
       return SwitchCase(makeExpression(arguments), makeBody(arguments));
     };
@@ -506,14 +508,14 @@
   @override
   Instantiator<FunctionDeclaration> visitFunctionDeclaration(
       FunctionDeclaration node) {
-    Instantiator<Identifier> makeName = visit(node.name);
-    Instantiator<Fun> makeFunction = visit(node.function);
+    var makeName = visit(node.name) as Instantiator<Identifier>;
+    var makeFunction = visit(node.function) as Instantiator<Fun>;
     return (a) => FunctionDeclaration(makeName(a), makeFunction(a));
   }
 
   @override
   Instantiator<LabeledStatement> visitLabeledStatement(LabeledStatement node) {
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => LabeledStatement(node.label, makeBody(a));
   }
 
@@ -539,23 +541,24 @@
     Instantiator makeValue = visitNullable(node.value);
     return (arguments) {
       return makeValue(arguments)
-          .toAssignExpression(makeLeftHandSide(arguments), op);
+          .toAssignExpression(makeLeftHandSide(arguments), op) as Expression;
     };
   }
 
   @override
   Instantiator<VariableInitialization> visitVariableInitialization(
       VariableInitialization node) {
-    Instantiator<VariableBinding> makeDeclaration = visit(node.declaration);
-    Instantiator<Expression> makeValue = visitNullable(node.value);
+    var makeDeclaration =
+        visit(node.declaration) as Instantiator<VariableBinding>;
+    var makeValue = visitNullable(node.value) as Instantiator<Expression>;
     return (a) => VariableInitialization(makeDeclaration(a), makeValue(a));
   }
 
   @override
   Instantiator<Conditional> visitConditional(Conditional cond) {
-    Instantiator<Expression> makeCondition = visit(cond.condition);
-    Instantiator<Expression> makeThen = visit(cond.then);
-    Instantiator<Expression> makeOtherwise = visit(cond.otherwise);
+    var makeCondition = visit(cond.condition) as Instantiator<Expression>;
+    var makeThen = visit(cond.then) as Instantiator<Expression>;
+    var makeOtherwise = visit(cond.otherwise) as Instantiator<Expression>;
     return (a) => Conditional(makeCondition(a), makeThen(a), makeOtherwise(a));
   }
 
@@ -566,7 +569,7 @@
   Instantiator<Call> visitCall(Call node) => handleCallOrNew(node, false);
 
   Instantiator<Call> handleCallOrNew(Call node, bool isNew) {
-    Instantiator<Expression> makeTarget = visit(node.target);
+    var makeTarget = visit(node.target) as Instantiator<Expression>;
     var argumentMakers = node.arguments.map(visitSplayableExpression).toList();
 
     // TODO(sra): Avoid copying call arguments if no interpolation or forced
@@ -580,22 +583,22 @@
 
   @override
   Instantiator<Binary> visitBinary(Binary node) {
-    Instantiator<Expression> makeLeft = visit(node.left);
-    Instantiator<Expression> makeRight = visit(node.right);
+    var makeLeft = visit(node.left) as Instantiator<Expression>;
+    var makeRight = visit(node.right) as Instantiator<Expression>;
     String op = node.op;
     return (a) => Binary(op, makeLeft(a), makeRight(a));
   }
 
   @override
   Instantiator<Prefix> visitPrefix(Prefix node) {
-    Instantiator<Expression> makeOperand = visit(node.argument);
+    var makeOperand = visit(node.argument) as Instantiator<Expression>;
     String op = node.op;
     return (a) => Prefix(op, makeOperand(a));
   }
 
   @override
   Instantiator<Postfix> visitPostfix(Postfix node) {
-    Instantiator<Expression> makeOperand = visit(node.argument);
+    var makeOperand = visit(node.argument) as Instantiator<Expression>;
     String op = node.op;
     return (a) => Postfix(op, makeOperand(a));
   }
@@ -629,22 +632,22 @@
 
   @override
   Instantiator<PropertyAccess> visitAccess(PropertyAccess node) {
-    Instantiator<Expression> makeReceiver = visit(node.receiver);
-    Instantiator<Expression> makeSelector = visit(node.selector);
+    var makeReceiver = visit(node.receiver) as Instantiator<Expression>;
+    var makeSelector = visit(node.selector) as Instantiator<Expression>;
     return (a) => PropertyAccess(makeReceiver(a), makeSelector(a));
   }
 
   @override
   Instantiator<NamedFunction> visitNamedFunction(NamedFunction node) {
-    Instantiator<Identifier> makeDeclaration = visit(node.name);
-    Instantiator<Fun> makeFunction = visit(node.function);
+    var makeDeclaration = visit(node.name) as Instantiator<Identifier>;
+    var makeFunction = visit(node.function) as Instantiator<Fun>;
     return (a) => NamedFunction(makeDeclaration(a), makeFunction(a));
   }
 
   @override
   Instantiator<Fun> visitFun(Fun node) {
     var paramMakers = node.params.map(visitSplayable).toList();
-    Instantiator<Block> makeBody = visit(node.body);
+    var makeBody = visit(node.body) as Instantiator<Block>;
     return (a) => Fun(splayNodes(paramMakers, a), makeBody(a),
         isGenerator: node.isGenerator, asyncModifier: node.asyncModifier);
   }
@@ -653,7 +656,7 @@
   Instantiator<ArrowFun> visitArrowFun(ArrowFun node) {
     var paramMakers = node.params.map(visitSplayable).toList();
     Instantiator makeBody = visit(node.body);
-    return (a) => ArrowFun(splayNodes(paramMakers, a), makeBody(a));
+    return (a) => ArrowFun(splayNodes(paramMakers, a), makeBody(a) as Node);
   }
 
   @override
@@ -692,8 +695,8 @@
 
   @override
   Instantiator<Property> visitProperty(Property node) {
-    Instantiator<Expression> makeName = visit(node.name);
-    Instantiator<Expression> makeValue = visit(node.value);
+    var makeName = visit(node.name) as Instantiator<Expression>;
+    var makeValue = visit(node.value) as Instantiator<Expression>;
     return (a) => Property(makeName(a), makeValue(a));
   }
 
@@ -709,7 +712,7 @@
 
   @override
   Instantiator<TaggedTemplate> visitTaggedTemplate(TaggedTemplate node) {
-    Instantiator<Expression> makeTag = visit(node.tag);
+    var makeTag = visit(node.tag) as Instantiator<Expression>;
     var makeTemplate = visitTemplateString(node.template);
     return (a) => TaggedTemplate(makeTag(a), makeTemplate(a));
   }
@@ -723,8 +726,8 @@
   @override
   Instantiator<ClassExpression> visitClassExpression(ClassExpression node) {
     var makeMethods = node.methods.map(visitSplayableExpression).toList();
-    Instantiator<Identifier> makeName = visit(node.name);
-    Instantiator<Expression> makeHeritage = visit(node.heritage);
+    var makeName = visit(node.name) as Instantiator<Identifier>;
+    var makeHeritage = visit(node.heritage) as Instantiator<Expression>;
 
     return (a) => ClassExpression(
         makeName(a), makeHeritage(a), splayNodes(makeMethods, a));
@@ -732,8 +735,8 @@
 
   @override
   Instantiator<Method> visitMethod(Method node) {
-    Instantiator<Expression> makeName = visit(node.name);
-    Instantiator<Fun> makeFunction = visit(node.function);
+    var makeName = visit(node.name) as Instantiator<Expression>;
+    var makeFunction = visit(node.function) as Instantiator<Fun>;
     return (a) => Method(makeName(a), makeFunction(a),
         isGetter: node.isGetter,
         isSetter: node.isSetter,
@@ -747,13 +750,13 @@
   @override
   Instantiator<CommentExpression> visitCommentExpression(
       CommentExpression node) {
-    Instantiator<Expression> makeExpr = visit(node.expression);
+    var makeExpr = visit(node.expression) as Instantiator<Expression>;
     return (a) => CommentExpression(node.comment, makeExpr(a));
   }
 
   @override
   Instantiator<Await> visitAwait(Await node) {
-    Instantiator<Expression> makeExpr = visit(node.expression);
+    var makeExpr = visit(node.expression) as Instantiator<Expression>;
     return (a) => Await(makeExpr(a));
   }
 
@@ -779,11 +782,12 @@
   @override
   Instantiator<DestructuredVariable> visitDestructuredVariable(
       DestructuredVariable node) {
-    Instantiator<Identifier> makeName = visitNullable(node.name);
-    Instantiator<Expression> makeProperty = visitNullable(node.property);
-    Instantiator<BindingPattern> makeStructure = visitNullable(node.structure);
-    Instantiator<Expression> makeDefaultValue =
-        visitNullable(node.defaultValue);
+    var makeName = visitNullable(node.name) as Instantiator<Identifier>;
+    var makeProperty = visitNullable(node.property) as Instantiator<Expression>;
+    var makeStructure =
+        visitNullable(node.structure) as Instantiator<BindingPattern>;
+    var makeDefaultValue =
+        visitNullable(node.defaultValue) as Instantiator<Expression>;
     return (a) => DestructuredVariable(
         name: makeName(a),
         property: makeProperty(a),
diff --git a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
index 308e199..caa8b83 100644
--- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
+++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
@@ -645,7 +645,9 @@
     var f = type as a.FunctionType;
     if (f.name != null && f.name != '') {
       var ref = ensureNode
-          ? visitFunctionTypeAliasElement(f.element).reference
+          ? visitFunctionTypeAliasElement(
+                  f.element as a.FunctionTypeAliasElement)
+              .reference
           : _reference(f.element);
       return TypedefType.byReference(ref, f.typeArguments.map(visit).toList());
     }
@@ -752,8 +754,8 @@
       void Function(Expression) addAnnotation) {
     if (metadata.isEmpty) return;
 
-    for (a.ElementAnnotationImpl annotation in metadata) {
-      var ast = annotation.annotationAst;
+    for (a.ElementAnnotation annotation in metadata) {
+      var ast = (annotation as a.ElementAnnotationImpl).annotationAst;
       var arguments = ast.arguments;
       if (arguments == null) {
         var e = ast.element;
@@ -833,7 +835,8 @@
         //
         // This leads to mismatch in how we call this constructor. So we need to
         // find the redirected one.
-        for (var rc; (rc = constructor.redirectedConstructor) != null;) {
+        for (a.ConstructorElement rc;
+            (rc = constructor.redirectedConstructor) != null;) {
           constructor = rc;
         }
         constructor = constructor is a.ConstructorMember
@@ -852,7 +855,9 @@
     }
     if (obj is a.DartObjectImpl && type is a.FunctionType) {
       var e = obj.toFunctionValue();
-      e = e is a.PropertyAccessorElement && e.isSynthetic ? e.variable : e;
+      e = e is a.PropertyAccessorElement && e.isSynthetic
+          ? e.variable as a.ExecutableElement
+          : e;
       // TODO(jmesserly): support generic tear-off implicit instantiation.
       return StaticGet.byReference(_reference(e));
     }
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index 8794109..7507c3a 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -11,6 +11,7 @@
 import 'package:cli_util/cli_util.dart' show getSdkPath;
 import 'package:front_end/src/api_unstable/ddc.dart' as fe;
 import 'package:kernel/kernel.dart' hide MapEntry;
+import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/target/targets.dart';
 import 'package:kernel/text/ast_to_text.dart' as kernel show Printer;
 import 'package:kernel/binary/ast_to_binary.dart' as kernel show BinaryPrinter;
@@ -265,7 +266,7 @@
     converter.dispose();
   }
 
-  var hierarchy;
+  ClassHierarchy hierarchy;
   fe.DdcResult result;
   if (useAnalyzer || !useIncrementalCompiler) {
     result = await fe.compile(compilerState, inputs, diagnosticMessageHandler);
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 7427bbc..13f7c0b 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:collection';
+import 'dart:convert';
 import 'dart:math' show max, min;
 
 import 'package:front_end/src/api_unstable/ddc.dart' show TypeSchemaEnvironment;
@@ -316,7 +317,9 @@
   @override
   String jsLibraryName(Library library) {
     var uri = library.importUri;
-    if (uri.scheme == 'dart') return uri.path;
+    if (uri.scheme == 'dart') {
+      return isSdkInternalRuntime(library) ? 'dart' : uri.path;
+    }
 
     // TODO(vsm): This is not necessarily unique if '__' appears in a file name.
     Iterable<String> segments;
@@ -335,13 +338,11 @@
   }
 
   @override
-  String jsLibraryDebuggerName(Library library) {
-    var uri = library.importUri;
-    // For package: and dart: uris show the entire
-    if (uri.scheme == 'dart' || uri.scheme == 'package') return uri.toString();
-    // TODO(jmesserly): this is not unique typically.
-    return uri.pathSegments.last;
-  }
+  String jsLibraryDebuggerName(Library library) => '${library.importUri}';
+
+  @override
+  Iterable<String> jsPartDebuggerNames(Library library) =>
+      library.parts.map((part) => part.partUri);
 
   @override
   bool isSdkInternalRuntime(Library l) {
@@ -551,10 +552,11 @@
       className ?? JS.Identifier(name)
     ]);
 
-    var genericArgs = [typeConstructor];
-    if (deferredBaseClass != null && deferredBaseClass.isNotEmpty) {
-      genericArgs.add(js.call('(#) => { #; }', [jsFormals, deferredBaseClass]));
-    }
+    var genericArgs = [
+      typeConstructor,
+      if (deferredBaseClass != null && deferredBaseClass.isNotEmpty)
+        js.call('(#) => { #; }', [jsFormals, deferredBaseClass]),
+    ];
 
     var genericCall = runtimeCall('generic(#)', [genericArgs]);
 
@@ -723,12 +725,12 @@
         _currentUri = ctor.enclosingClass.fileUri;
         var jsParams = _emitParameters(ctor.function);
         _currentUri = savedUri;
-        var ctorBody = <JS.Statement>[];
-        if (mixinCtor != null) ctorBody.add(mixinCtor);
         var name = ctor.name.name;
-        if (name != '' || hasUnnamedSuper) {
-          ctorBody.add(_emitSuperConstructorCall(className, name, jsParams));
-        }
+        var ctorBody = [
+          if (mixinCtor != null) mixinCtor,
+          if (name != '' || hasUnnamedSuper)
+            _emitSuperConstructorCall(className, name, jsParams),
+        ];
         body.add(_addConstructorToClass(
             c, className, name, JS.Fun(jsParams, JS.Block(ctorBody))));
       }
@@ -1164,7 +1166,7 @@
     var savedClass = _classEmittingSignatures;
     _classEmittingSignatures = c;
 
-    var interfaces = List.from(c.implementedTypes)
+    var interfaces = c.implementedTypes.toList()
       ..addAll(c.superclassConstraints());
     if (interfaces.isNotEmpty) {
       body.add(js.statement('#[#.implements] = () => [#];', [
@@ -1268,6 +1270,10 @@
     emitSignature('Setter', instanceSetters);
     emitSignature('StaticGetter', staticGetters);
     emitSignature('StaticSetter', staticSetters);
+    body.add(runtimeStatement('setLibraryUri(#, #)', [
+      className,
+      js.escapedString(jsLibraryDebuggerName(c.enclosingLibrary))
+    ]));
 
     var instanceFields = <JS.Property>[];
     var staticFields = <JS.Property>[];
@@ -1288,8 +1294,10 @@
 
     if (emitMetadata) {
       var constructors = <JS.Property>[];
-      var allConstructors = List<Member>.from(c.constructors)
-        ..addAll(c.procedures.where((p) => p.isFactory));
+      var allConstructors = [
+        ...c.constructors,
+        ...c.procedures.where((p) => p.isFactory),
+      ];
       for (var ctor in allConstructors) {
         var memberName = _constructorName(ctor.name.name);
         var type = _emitAnnotatedFunctionType(
@@ -1552,7 +1560,7 @@
     if (expr == null) return null;
     var jsExpr = _visitExpression(expr);
     if (!isNullable(expr)) return jsExpr;
-    return runtimeCall('notNull(#)', jsExpr);
+    return runtimeCall('notNull(#)', [jsExpr]);
   }
 
   /// If the class has only factory constructors, and it can be mixed in,
@@ -1996,8 +2004,8 @@
       Class c, String jsPeerName, List<JS.Statement> body) {
     var className = _emitTopLevelName(c);
     if (_typeRep.isPrimitive(c.rawType)) {
-      body.add(
-          runtimeStatement('definePrimitiveHashCode(#.prototype)', className));
+      body.add(runtimeStatement(
+          'definePrimitiveHashCode(#.prototype)', [className]));
     }
     body.add(runtimeStatement(
         'registerExtension(#, #)', [js.string(jsPeerName), className]));
@@ -2437,22 +2445,22 @@
   }
 
   @override
-  defaultDartType(type) => _emitInvalidNode(type);
+  JS.Expression defaultDartType(DartType type) => _emitInvalidNode(type);
 
   @override
-  visitInvalidType(type) => defaultDartType(type);
+  JS.Expression visitInvalidType(InvalidType type) => defaultDartType(type);
 
   @override
-  visitDynamicType(type) => runtimeCall('dynamic');
+  JS.Expression visitDynamicType(DynamicType type) => runtimeCall('dynamic');
 
   @override
-  visitVoidType(type) => runtimeCall('void');
+  JS.Expression visitVoidType(VoidType type) => runtimeCall('void');
 
   @override
-  visitBottomType(type) => runtimeCall('bottom');
+  JS.Expression visitBottomType(BottomType type) => runtimeCall('bottom');
 
   @override
-  visitInterfaceType(type) {
+  JS.Expression visitInterfaceType(InterfaceType type) {
     var c = type.classNode;
     _declareBeforeUse(c);
 
@@ -2471,7 +2479,7 @@
     // have to use a helper to define them.
     if (isJSAnonymousType(c)) {
       return runtimeCall(
-          'anonymousJSType(#)', js.escapedString(getLocalClassName(c)));
+          'anonymousJSType(#)', [js.escapedString(getLocalClassName(c))]);
     }
     var jsName = _getJSNameWithoutGlobal(c);
     if (jsName != null) {
@@ -2510,7 +2518,7 @@
   }
 
   @override
-  visitFunctionType(type, {Member member, bool lazy = false}) {
+  JS.Expression visitFunctionType(type, {Member member, bool lazy = false}) {
     var requiredTypes =
         type.positionalParameters.take(type.requiredParameterCount).toList();
     var function = member?.function;
@@ -2665,14 +2673,15 @@
   }
 
   @override
-  visitTypeParameterType(type) => _emitTypeParameter(type.parameter);
+  JS.Expression visitTypeParameterType(TypeParameterType type) =>
+      _emitTypeParameter(type.parameter);
 
-  JS.Identifier _emitTypeParameter(TypeParameter t) {
-    return JS.Identifier(getTypeParameterName(t));
-  }
+  JS.Identifier _emitTypeParameter(TypeParameter t) =>
+      JS.Identifier(getTypeParameterName(t));
 
   @override
-  visitTypedefType(type) => visitFunctionType(type.unalias);
+  JS.Expression visitTypedefType(TypedefType type) =>
+      visitFunctionType(type.unalias as FunctionType);
 
   JS.Fun _emitFunction(FunctionNode f, String name) {
     // normal function (sync), vs (sync*, async, async*)
@@ -2698,11 +2707,11 @@
 
   List<JS.Parameter> _emitParameters(FunctionNode f) {
     var positional = f.positionalParameters;
-    var result = List<JS.Parameter>.from(positional.map(_emitVariableDef));
+    var result = List<JS.Parameter>.of(positional.map(_emitVariableDef));
     if (positional.isNotEmpty &&
         f.requiredParameterCount == positional.length &&
         positional.last.annotations.any(isJsRestAnnotation)) {
-      result.last = JS.RestParameter(result.last);
+      result.last = JS.RestParameter(result.last as JS.Identifier);
     }
     if (f.namedParameters.isNotEmpty) result.add(namedArgumentTemp);
     return result;
@@ -3023,9 +3032,10 @@
       // (sync*/async/async*). Our code generator assumes it can emit names for
       // named argument initialization, and sync* functions also emit locally
       // modified parameters into the function's scope.
-      var parameterNames = HashSet<String>()
-        ..addAll(f.positionalParameters.map((p) => p.name))
-        ..addAll(f.namedParameters.map((p) => p.name));
+      var parameterNames = {
+        for (var p in f.positionalParameters) p.name,
+        for (var p in f.namedParameters) p.name,
+      };
 
       return jsBody.toScopedBlock(parameterNames);
     }
@@ -3060,11 +3070,11 @@
 
     if (node is AsExpression && node.isTypeError) {
       assert(node.getStaticType(types) == types.boolType);
-      return runtimeCall('dtest(#)', _visitExpression(node.operand));
+      return runtimeCall('dtest(#)', [_visitExpression(node.operand)]);
     }
 
     var result = _visitExpression(node);
-    if (isNullable(node)) result = runtimeCall('test(#)', result);
+    if (isNullable(node)) result = runtimeCall('test(#)', [result]);
     return result;
   }
 
@@ -3133,10 +3143,11 @@
   }
 
   @override
-  defaultStatement(Statement node) => _emitInvalidNode(node).toStatement();
+  JS.Statement defaultStatement(Statement node) =>
+      _emitInvalidNode(node).toStatement();
 
   @override
-  visitExpressionStatement(ExpressionStatement node) {
+  JS.Statement visitExpressionStatement(ExpressionStatement node) {
     var expr = node.expression;
     if (expr is StaticInvocation) {
       if (isInlineJS(expr.target)) {
@@ -3150,7 +3161,7 @@
   }
 
   @override
-  visitBlock(Block node) {
+  JS.Statement visitBlock(Block node) {
     // If this is the block body of a function, don't mark it as a separate
     // scope, because the function is the scope. This avoids generating an
     // unncessary nested block.
@@ -3164,17 +3175,17 @@
   }
 
   @override
-  visitEmptyStatement(EmptyStatement node) => JS.EmptyStatement();
+  JS.Statement visitEmptyStatement(EmptyStatement node) => JS.EmptyStatement();
 
   @override
-  visitAssertBlock(AssertBlock node) {
+  JS.Statement visitAssertBlock(AssertBlock node) {
     // AssertBlocks are introduced by the VM-specific async elimination
     // transformation.  We do not expect them to arise here.
     throw UnsupportedError('compilation of an assert block');
   }
 
   @override
-  visitAssertStatement(AssertStatement node) {
+  JS.Statement visitAssertStatement(AssertStatement node) {
     if (!options.enableAsserts) return JS.EmptyStatement();
     var condition = node.condition;
     var conditionType = condition.getStaticType(types);
@@ -3184,16 +3195,30 @@
     if (conditionType is FunctionType &&
         conditionType.requiredParameterCount == 0 &&
         conditionType.returnType == boolType) {
-      jsCondition = runtimeCall('test(#())', jsCondition);
+      jsCondition = runtimeCall('test(#())', [jsCondition]);
     } else if (conditionType != boolType) {
-      jsCondition = runtimeCall('dassert(#)', jsCondition);
+      jsCondition = runtimeCall('dassert(#)', [jsCondition]);
     } else if (isNullable(condition)) {
-      jsCondition = runtimeCall('test(#)', jsCondition);
+      jsCondition = runtimeCall('test(#)', [jsCondition]);
     }
-    return js.statement(' if (!#) #.assertFailed(#);', [
+
+    var encodedConditionSource = node
+        .enclosingComponent.uriToSource[node.location.file].source
+        .sublist(node.conditionStartOffset, node.conditionEndOffset);
+    var conditionSource = utf8.decode(encodedConditionSource);
+    var location = _getLocation(node.conditionStartOffset);
+    return js.statement(' if (!#) #.assertFailed(#, #, #, #, #);', [
       jsCondition,
       runtimeModule,
-      node.message != null ? [_visitExpression(node.message)] : []
+      if (node.message == null)
+        JS.LiteralNull()
+      else
+        _visitExpression(node.message),
+      js.escapedString(location.sourceUrl.toString()),
+      // Lines and columns are typically printed with 1 based indexing.
+      js.number(location.line + 1),
+      js.number(location.column + 1),
+      js.escapedString(conditionSource),
     ]);
   }
 
@@ -3208,7 +3233,7 @@
   }
 
   @override
-  visitLabeledStatement(LabeledStatement node) {
+  JS.Statement visitLabeledStatement(LabeledStatement node) {
     List<LabeledStatement> saved;
     var target = _effectiveTargets[node];
     // If the effective target is known then this statement is either contained
@@ -3246,7 +3271,7 @@
   }
 
   @override
-  visitBreakStatement(BreakStatement node) {
+  JS.Statement visitBreakStatement(BreakStatement node) {
     // Switch statements with continue labels must explicitly break to their
     // implicit label due to their being wrapped in a loop.
     if (_inLabeledContinueSwitch &&
@@ -3433,7 +3458,7 @@
   }
 
   @override
-  visitSwitchStatement(SwitchStatement node) {
+  JS.Statement visitSwitchStatement(SwitchStatement node) {
     // Switches with labeled continues are generated as an infinite loop with
     // an explicit variable for holding the switch's next case state and an
     // explicit label. Any implicit breaks are made explicit (e.g., when break
@@ -3517,7 +3542,7 @@
   }
 
   @override
-  visitContinueSwitchStatement(ContinueSwitchStatement node) {
+  JS.Statement visitContinueSwitchStatement(ContinueSwitchStatement node) {
     var switchStmt = node.target.parent;
     if (_inLabeledContinueSwitch &&
         _switchLabelStates.containsKey(switchStmt)) {
@@ -3537,7 +3562,7 @@
   }
 
   @override
-  visitIfStatement(IfStatement node) {
+  JS.Statement visitIfStatement(IfStatement node) {
     return JS.If(_visitTest(node.condition), _visitScope(node.then),
         _visitScope(node.otherwise));
   }
@@ -3563,7 +3588,7 @@
   }
 
   @override
-  visitTryCatch(TryCatch node) {
+  JS.Statement visitTryCatch(TryCatch node) {
     return JS.Try(
         _visitStatement(node.body).toBlock(), _visitCatch(node.catches), null);
   }
@@ -3598,15 +3623,14 @@
         runtimeModule,
         _emitVariableRef(caughtError)
       ]),
+      if (stackTraceParameter != null)
+        js.statement('let # = #.stackTrace(#)', [
+          _emitVariableDef(stackTraceParameter),
+          runtimeModule,
+          _emitVariableRef(caughtError)
+        ]),
+      catchBody,
     ];
-    if (stackTraceParameter != null) {
-      catchStatements.add(js.statement('let # = #.stackTrace(#)', [
-        _emitVariableDef(stackTraceParameter),
-        runtimeModule,
-        _emitVariableRef(caughtError)
-      ]));
-    }
-    catchStatements.add(catchBody);
     _rethrowParameter = savedRethrow;
     return JS.Catch(_emitVariableDef(caughtError), JS.Block(catchStatements));
   }
@@ -3645,7 +3669,7 @@
   }
 
   @override
-  visitTryFinally(TryFinally node) {
+  JS.Statement visitTryFinally(TryFinally node) {
     var body = _visitStatement(node.body);
     var finallyBlock =
         _superDisallowed(() => _visitStatement(node.finalizer).toBlock());
@@ -3660,7 +3684,7 @@
   }
 
   @override
-  visitYieldStatement(YieldStatement node) {
+  JS.Statement visitYieldStatement(YieldStatement node) {
     var jsExpr = _visitExpression(node.expression);
     var star = node.isYieldStar;
     if (_asyncStarController != null) {
@@ -3687,7 +3711,7 @@
   }
 
   @override
-  visitVariableDeclaration(VariableDeclaration node) {
+  JS.Statement visitVariableDeclaration(VariableDeclaration node) {
     // TODO(jmesserly): casts are sometimes required here.
     // Kernel does not represent these explicitly.
     var v = _emitVariableDef(node);
@@ -3696,7 +3720,7 @@
   }
 
   @override
-  visitFunctionDeclaration(FunctionDeclaration node) {
+  JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
     var func = node.function;
     var fn = _emitFunction(func, node.variable.name);
 
@@ -3714,20 +3738,22 @@
   }
 
   @override
-  defaultExpression(Expression node) => _emitInvalidNode(node);
+  JS.Expression defaultExpression(Expression node) => _emitInvalidNode(node);
 
   @override
-  defaultBasicLiteral(BasicLiteral node) => defaultExpression(node);
+  JS.Expression defaultBasicLiteral(BasicLiteral node) =>
+      defaultExpression(node);
 
   @override
-  visitInvalidExpression(InvalidExpression node) => defaultExpression(node);
+  JS.Expression visitInvalidExpression(InvalidExpression node) =>
+      defaultExpression(node);
 
   @override
-  visitConstantExpression(ConstantExpression node) =>
-      node.constant.accept(this);
+  JS.Expression visitConstantExpression(ConstantExpression node) =>
+      node.constant.accept(this) as JS.Expression;
 
   @override
-  visitVariableGet(VariableGet node) {
+  JS.Expression visitVariableGet(VariableGet node) {
     var v = node.variable;
     var id = _emitVariableRef(v);
     if (id.name == v.name) {
@@ -3767,28 +3793,29 @@
 
   // TODO(jmesserly): resugar operators for kernel, such as ++x, x++, x+=.
   @override
-  visitVariableSet(VariableSet node) => _visitExpression(node.value)
-      .toAssignExpression(_emitVariableRef(node.variable));
+  JS.Expression visitVariableSet(VariableSet node) =>
+      _visitExpression(node.value)
+          .toAssignExpression(_emitVariableRef(node.variable));
 
   @override
-  visitPropertyGet(PropertyGet node) {
+  JS.Expression visitPropertyGet(PropertyGet node) {
     return _emitPropertyGet(
         node.receiver, node.interfaceTarget, node.name.name);
   }
 
   @override
-  visitPropertySet(PropertySet node) {
+  JS.Expression visitPropertySet(PropertySet node) {
     return _emitPropertySet(
         node.receiver, node.interfaceTarget, node.value, node.name.name);
   }
 
   @override
-  visitDirectPropertyGet(DirectPropertyGet node) {
+  JS.Expression visitDirectPropertyGet(DirectPropertyGet node) {
     return _emitPropertyGet(node.receiver, node.target);
   }
 
   @override
-  visitDirectPropertySet(DirectPropertySet node) {
+  JS.Expression visitDirectPropertySet(DirectPropertySet node) {
     return _emitPropertySet(node.receiver, node.target, node.value);
   }
 
@@ -3853,7 +3880,7 @@
   }
 
   @override
-  visitSuperPropertyGet(SuperPropertyGet node) {
+  JS.Expression visitSuperPropertyGet(SuperPropertyGet node) {
     var target = node.interfaceTarget;
     var jsTarget = _emitSuperTarget(target);
     if (_reifyTearoff(target)) {
@@ -3863,14 +3890,14 @@
   }
 
   @override
-  visitSuperPropertySet(SuperPropertySet node) {
+  JS.Expression visitSuperPropertySet(SuperPropertySet node) {
     var target = node.interfaceTarget;
     var jsTarget = _emitSuperTarget(target, setter: true);
     return _visitExpression(node.value).toAssignExpression(jsTarget);
   }
 
   @override
-  visitStaticGet(StaticGet node) => _emitStaticGet(node.target);
+  JS.Expression visitStaticGet(StaticGet node) => _emitStaticGet(node.target);
 
   JS.Expression _emitStaticGet(Member target) {
     // TODO(vsm): Re-inline constants.  See:
@@ -3886,19 +3913,19 @@
   }
 
   @override
-  visitStaticSet(StaticSet node) {
+  JS.Expression visitStaticSet(StaticSet node) {
     return _visitExpression(node.value)
         .toAssignExpression(_emitStaticTarget(node.target));
   }
 
   @override
-  visitMethodInvocation(MethodInvocation node) {
+  JS.Expression visitMethodInvocation(MethodInvocation node) {
     return _emitMethodCall(
         node.receiver, node.interfaceTarget, node.arguments, node);
   }
 
   @override
-  visitDirectMethodInvocation(DirectMethodInvocation node) {
+  JS.Expression visitDirectMethodInvocation(DirectMethodInvocation node) {
     return _emitMethodCall(node.receiver, node.target, node.arguments, node);
   }
 
@@ -4006,7 +4033,7 @@
     return null;
   }
 
-  _isDynamicOrFunction(DartType t) =>
+  bool _isDynamicOrFunction(DartType t) =>
       t == coreTypes.functionClass.rawType || t == const DynamicType();
 
   JS.Expression _emitUnaryOperator(
@@ -4362,7 +4389,7 @@
 
   // TODO(jmesserly): optimize super operators for kernel
   @override
-  visitSuperMethodInvocation(SuperMethodInvocation node) {
+  JS.Expression visitSuperMethodInvocation(SuperMethodInvocation node) {
     var target = node.interfaceTarget;
     return JS.Call(_emitSuperTarget(target),
         _emitArgumentList(node.arguments, target: target));
@@ -4396,13 +4423,12 @@
             isGetter: !setter, isSetter: setter);
       } else {
         var function = member.function;
-        var params = _emitTypeFormals(function.typeParameters);
-        for (var param in function.positionalParameters) {
-          params.add(JS.Identifier(param.name));
-        }
-        if (function.namedParameters.isNotEmpty) {
-          params.add(namedArgumentTemp);
-        }
+        var params = [
+          ..._emitTypeFormals(function.typeParameters),
+          for (var param in function.positionalParameters)
+            JS.Identifier(param.name),
+          if (function.namedParameters.isNotEmpty) namedArgumentTemp,
+        ];
 
         var fn = js.fun(
             'function(#) { return super[#](#); }', [params, jsName, params]);
@@ -4414,7 +4440,7 @@
   }
 
   @override
-  visitStaticInvocation(StaticInvocation node) {
+  JS.Expression visitStaticInvocation(StaticInvocation node) {
     var target = node.target;
     if (isInlineJS(target)) return _emitInlineJSCode(node) as JS.Expression;
     if (target.isFactory) return _emitFactoryInvocation(node);
@@ -4515,26 +4541,18 @@
   List<JS.Expression> _emitArgumentList(Arguments node,
       {bool types = true, Member target}) {
     types = types && _reifyGenericFunction(target);
-    var args = <JS.Expression>[];
-    if (types) {
-      for (var typeArg in node.types) {
-        args.add(_emitType(typeArg));
-      }
-    }
-    for (var arg in node.positional) {
-      if (arg is StaticInvocation &&
-          isJSSpreadInvocation(arg.target) &&
-          arg.arguments.positional.length == 1) {
-        args.add(JS.Spread(_visitExpression(arg.arguments.positional[0])));
-      } else {
-        args.add(_visitExpression(arg));
-      }
-    }
-    if (node.named.isNotEmpty) {
-      args.add(
-          JS.ObjectInitializer(node.named.map(_emitNamedExpression).toList()));
-    }
-    return args;
+    return [
+      if (types) for (var typeArg in node.types) _emitType(typeArg),
+      for (var arg in node.positional)
+        if (arg is StaticInvocation &&
+            isJSSpreadInvocation(arg.target) &&
+            arg.arguments.positional.length == 1)
+          JS.Spread(_visitExpression(arg.arguments.positional[0]))
+        else
+          _visitExpression(arg),
+      if (node.named.isNotEmpty)
+        JS.ObjectInitializer(node.named.map(_emitNamedExpression).toList()),
+    ];
   }
 
   JS.Property _emitNamedExpression(NamedExpression arg) {
@@ -4649,7 +4667,7 @@
   }
 
   @override
-  visitConstructorInvocation(ConstructorInvocation node) {
+  JS.Expression visitConstructorInvocation(ConstructorInvocation node) {
     var ctor = node.target;
     var args = node.arguments;
     var result = JS.New(_emitConstructorName(node.constructedType, ctor),
@@ -4672,7 +4690,9 @@
 
     if (isFromEnvironmentInvocation(coreTypes, node)) {
       var value = _constants.evaluate(node);
-      if (value is PrimitiveConstant) return value.accept(this);
+      if (value is PrimitiveConstant) {
+        return value.accept(this) as JS.Expression;
+      }
     }
 
     if (args.positional.isEmpty &&
@@ -4745,7 +4765,7 @@
   }
 
   @override
-  visitNot(Not node) {
+  JS.Expression visitNot(Not node) {
     var operand = node.operand;
     if (operand is MethodInvocation && operand.name.name == '==') {
       return _emitEqualityOperator(operand.receiver, operand.interfaceTarget,
@@ -4767,14 +4787,14 @@
   }
 
   @override
-  visitLogicalExpression(LogicalExpression node) {
+  JS.Expression visitLogicalExpression(LogicalExpression node) {
     // The operands of logical boolean operators are subject to boolean
     // conversion.
     return _visitTest(node);
   }
 
   @override
-  visitConditionalExpression(ConditionalExpression node) {
+  JS.Expression visitConditionalExpression(ConditionalExpression node) {
     return js.call('# ? # : #', [
       _visitTest(node.condition),
       _visitExpression(node.then),
@@ -4784,7 +4804,7 @@
   }
 
   @override
-  visitStringConcatenation(StringConcatenation node) {
+  JS.Expression visitStringConcatenation(StringConcatenation node) {
     var parts = <JS.Expression>[];
     for (var e in node.expressions) {
       var jsExpr = _visitExpression(e);
@@ -4793,14 +4813,14 @@
       }
       parts.add(e.getStaticType(types) == types.stringType && !isNullable(e)
           ? jsExpr
-          : runtimeCall('str(#)', jsExpr));
+          : runtimeCall('str(#)', [jsExpr]));
     }
     if (parts.isEmpty) return js.string('');
     return JS.Expression.binary(parts, '+');
   }
 
   @override
-  visitListConcatenation(ListConcatenation node) {
+  JS.Expression visitListConcatenation(ListConcatenation node) {
     // Only occurs inside unevaluated constants.
     List<JS.Expression> entries = [];
     _concatenate(Expression node) {
@@ -4822,7 +4842,7 @@
   }
 
   @override
-  visitSetConcatenation(SetConcatenation node) {
+  JS.Expression visitSetConcatenation(SetConcatenation node) {
     // Only occurs inside unevaluated constants.
     List<JS.Expression> entries = [];
     _concatenate(Expression node) {
@@ -4844,7 +4864,7 @@
   }
 
   @override
-  visitMapConcatenation(MapConcatenation node) {
+  JS.Expression visitMapConcatenation(MapConcatenation node) {
     // Only occurs inside unevaluated constants.
     List<JS.Expression> entries = [];
     _concatenate(Expression node) {
@@ -4872,13 +4892,13 @@
   }
 
   @override
-  visitInstanceCreation(InstanceCreation node) {
+  JS.Expression visitInstanceCreation(InstanceCreation node) {
     // Only occurs inside unevaluated constants.
     throw new UnsupportedError("Instance creation");
   }
 
   @override
-  visitIsExpression(IsExpression node) {
+  JS.Expression visitIsExpression(IsExpression node) {
     return _emitIsExpression(node.operand, node.type);
   }
 
@@ -4895,7 +4915,7 @@
   }
 
   @override
-  visitAsExpression(AsExpression node) {
+  JS.Expression visitAsExpression(AsExpression node) {
     Expression fromExpr = node.operand;
     var to = node.type;
     var jsFrom = _visitExpression(fromExpr);
@@ -4929,7 +4949,7 @@
         // TODO(jmesserly): fuse this with notNull check.
         // TODO(jmesserly): this does not correctly distinguish user casts from
         // required-for-soundness casts.
-        return runtimeCall('asInt(#)', jsFrom);
+        return runtimeCall('asInt(#)', [jsFrom]);
       }
 
       // A no-op in JavaScript.
@@ -4948,32 +4968,34 @@
   }
 
   @override
-  visitSymbolLiteral(SymbolLiteral node) => emitDartSymbol(node.value);
+  JS.Expression visitSymbolLiteral(SymbolLiteral node) =>
+      emitDartSymbol(node.value);
 
   @override
-  visitTypeLiteral(TypeLiteral node) => _emitTypeLiteral(node.type);
+  JS.Expression visitTypeLiteral(TypeLiteral node) =>
+      _emitTypeLiteral(node.type);
 
-  _emitTypeLiteral(DartType type) {
+  JS.Expression _emitTypeLiteral(DartType type) {
     var typeRep = _emitType(type);
     // If the type is a type literal expression in Dart code, wrap the raw
     // runtime type in a "Type" instance.
-    return _isInForeignJS ? typeRep : runtimeCall('wrapType(#)', typeRep);
+    return _isInForeignJS ? typeRep : runtimeCall('wrapType(#)', [typeRep]);
   }
 
   @override
-  visitThisExpression(ThisExpression node) => JS.This();
+  JS.Expression visitThisExpression(ThisExpression node) => JS.This();
 
   @override
-  visitRethrow(Rethrow node) {
-    return runtimeCall('rethrow(#)', _emitVariableRef(_rethrowParameter));
+  JS.Expression visitRethrow(Rethrow node) {
+    return runtimeCall('rethrow(#)', [_emitVariableRef(_rethrowParameter)]);
   }
 
   @override
-  visitThrow(Throw node) =>
-      runtimeCall('throw(#)', _visitExpression(node.expression));
+  JS.Expression visitThrow(Throw node) =>
+      runtimeCall('throw(#)', [_visitExpression(node.expression)]);
 
   @override
-  visitListLiteral(ListLiteral node) {
+  JS.Expression visitListLiteral(ListLiteral node) {
     var elementType = node.typeArgument;
     var elements = _visitExpressionList(node.expressions);
     // TODO(markzipan): remove const check when we use front-end const eval
@@ -5005,7 +5027,7 @@
   }
 
   @override
-  visitSetLiteral(SetLiteral node) {
+  JS.Expression visitSetLiteral(SetLiteral node) {
     // TODO(markzipan): remove const check when we use front-end const eval
     if (!node.isConst) {
       var setType = visitInterfaceType(
@@ -5027,12 +5049,13 @@
   }
 
   @override
-  visitMapLiteral(MapLiteral node) {
-    var entries = <JS.Expression>[];
-    for (var e in node.entries) {
-      entries.add(_visitExpression(e.key));
-      entries.add(_visitExpression(e.value));
-    }
+  JS.Expression visitMapLiteral(MapLiteral node) {
+    var entries = [
+      for (var e in node.entries) ...[
+        _visitExpression(e.key),
+        _visitExpression(e.value),
+      ],
+    ];
 
     // TODO(markzipan): remove const check when we use front-end const eval
     if (!node.isConst) {
@@ -5053,11 +5076,11 @@
   }
 
   @override
-  visitAwaitExpression(AwaitExpression node) =>
+  JS.Expression visitAwaitExpression(AwaitExpression node) =>
       JS.Yield(_visitExpression(node.operand));
 
   @override
-  visitFunctionExpression(FunctionExpression node) {
+  JS.Expression visitFunctionExpression(FunctionExpression node) {
     var fn = _emitArrowFunction(node);
     if (!_reifyFunctionType(node.function)) return fn;
     return _emitFunctionTagged(fn, node.getStaticType(types) as FunctionType);
@@ -5069,11 +5092,11 @@
 
     // Simplify `=> { return e; }` to `=> e`
     if (body is JS.Block) {
-      JS.Block block = body;
+      var block = body as JS.Block;
       if (block.statements.length == 1) {
         JS.Statement s = block.statements[0];
         if (s is JS.Block) {
-          block = s;
+          block = s as JS.Block;
           s = block.statements.length == 1 ? block.statements[0] : null;
         }
         if (s is JS.Return && s.value != null) body = s.value;
@@ -5086,22 +5109,24 @@
   }
 
   @override
-  visitStringLiteral(StringLiteral node) => js.escapedString(node.value, '"');
+  JS.Expression visitStringLiteral(StringLiteral node) =>
+      js.escapedString(node.value, '"');
 
   @override
-  visitIntLiteral(IntLiteral node) => js.uint64(node.value);
+  JS.Expression visitIntLiteral(IntLiteral node) => js.uint64(node.value);
 
   @override
-  visitDoubleLiteral(DoubleLiteral node) => js.number(node.value);
+  JS.Expression visitDoubleLiteral(DoubleLiteral node) => js.number(node.value);
 
   @override
-  visitBoolLiteral(BoolLiteral node) => JS.LiteralBool(node.value);
+  JS.Expression visitBoolLiteral(BoolLiteral node) =>
+      JS.LiteralBool(node.value);
 
   @override
-  visitNullLiteral(NullLiteral node) => JS.LiteralNull();
+  JS.Expression visitNullLiteral(NullLiteral node) => JS.LiteralNull();
 
   @override
-  visitLet(Let node) {
+  JS.Expression visitLet(Let node) {
     var v = node.variable;
     var init = _visitExpression(v.initializer);
     var body = _visitExpression(node.body);
@@ -5123,12 +5148,12 @@
   }
 
   @override
-  visitBlockExpression(BlockExpression node) {
+  JS.Expression visitBlockExpression(BlockExpression node) {
     var jsExpr = _visitExpression(node.value);
-    List<JS.Statement> jsStmts = node.body.statements
-        .map(_visitStatement)
-        .toList()
-          ..add(JS.Return(jsExpr));
+    var jsStmts = [
+      for (var s in node.body.statements) _visitStatement(s),
+      JS.Return(jsExpr),
+    ];
     var jsBlock = JS.Block(jsStmts);
     // BlockExpressions with async operations must be constructed
     // with a generator instead of a lambda.
@@ -5146,7 +5171,7 @@
   }
 
   @override
-  visitInstantiation(Instantiation node) {
+  JS.Expression visitInstantiation(Instantiation node) {
     return runtimeCall('gbind(#, #)', [
       _visitExpression(node.expression),
       node.typeArguments.map(_emitType).toList()
@@ -5154,14 +5179,16 @@
   }
 
   @override
-  visitLoadLibrary(LoadLibrary node) => runtimeCall('loadLibrary()');
+  JS.Expression visitLoadLibrary(LoadLibrary node) =>
+      runtimeCall('loadLibrary()');
 
   // TODO(jmesserly): DDC loads all libraries eagerly.
   // See
   // https://github.com/dart-lang/sdk/issues/27776
   // https://github.com/dart-lang/sdk/issues/27777
   @override
-  visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) => js.boolean(true);
+  JS.Expression visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
+      js.boolean(true);
 
   bool _reifyFunctionType(FunctionNode f) {
     if (_currentLibrary.importUri.scheme != 'dart') return true;
@@ -5204,18 +5231,19 @@
   /// Calls [findAnnotation] followed by [getNameFromAnnotation].
   String getAnnotationName(NamedNode node, bool test(Expression value)) {
     return _constants.getFieldValueFromAnnotation(
-        findAnnotation(node, test), 'name');
+        findAnnotation(node, test), 'name') as String;
   }
 
-  JS.Expression visitConstant(Constant node) => node.accept(this);
+  JS.Expression visitConstant(Constant node) =>
+      node.accept(this) as JS.Expression;
   @override
-  visitNullConstant(NullConstant node) => JS.LiteralNull();
+  JS.Expression visitNullConstant(NullConstant node) => JS.LiteralNull();
   @override
-  visitBoolConstant(BoolConstant node) => js.boolean(node.value);
+  JS.Expression visitBoolConstant(BoolConstant node) => js.boolean(node.value);
   @override
-  visitIntConstant(IntConstant node) => js.number(node.value);
+  JS.Expression visitIntConstant(IntConstant node) => js.number(node.value);
   @override
-  visitDoubleConstant(DoubleConstant node) {
+  JS.Expression visitDoubleConstant(DoubleConstant node) {
     var value = node.value;
 
     // Emit the constant as an integer, if possible.
@@ -5233,41 +5261,41 @@
   }
 
   @override
-  visitStringConstant(StringConstant node) => js.escapedString(node.value, '"');
+  JS.Expression visitStringConstant(StringConstant node) =>
+      js.escapedString(node.value, '"');
 
   // DDC does not currently use the non-primivite constant nodes; rather these
   // are emitted via their normal expression nodes.
   @override
-  defaultConstant(Constant node) => _emitInvalidNode(node);
+  JS.Expression defaultConstant(Constant node) => _emitInvalidNode(node);
 
   @override
-  visitSymbolConstant(node) => emitDartSymbol(node.name);
+  JS.Expression visitSymbolConstant(SymbolConstant node) =>
+      emitDartSymbol(node.name);
 
   @override
-  visitMapConstant(node) {
-    var entries = <JS.Expression>[];
-    for (var e in node.entries) {
-      entries.add(visitConstant(e.key));
-      entries.add(visitConstant(e.value));
-    }
-
+  JS.Expression visitMapConstant(MapConstant node) {
+    var entries = [
+      for (var e in node.entries) ...[
+        visitConstant(e.key),
+        visitConstant(e.value),
+      ],
+    ];
     return _emitConstMap(node.keyType, node.valueType, entries);
   }
 
   @override
-  visitListConstant(node) => _emitConstList(
+  JS.Expression visitListConstant(ListConstant node) => _emitConstList(
       node.typeArgument, node.entries.map(visitConstant).toList());
 
   @override
-  visitSetConstant(node) {
-    return _emitConstSet(
-        node.typeArgument, node.entries.map(visitConstant).toList());
-  }
+  JS.Expression visitSetConstant(SetConstant node) => _emitConstSet(
+      node.typeArgument, node.entries.map(visitConstant).toList());
 
   @override
-  visitInstanceConstant(node) {
+  JS.Expression visitInstanceConstant(InstanceConstant node) {
     entryToProperty(MapEntry<Reference, Constant> entry) {
-      var constant = entry.value.accept(this);
+      var constant = entry.value.accept(this) as JS.Expression;
       var member = entry.key.asField;
       return JS.Property(
           _emitMemberName(member.name.name, member: member), constant);
@@ -5275,30 +5303,33 @@
 
     var type = visitInterfaceType(node.getType(types) as InterfaceType);
     var prototype = js.call("#.prototype", [type]);
-    var properties = [JS.Property(propertyName("__proto__"), prototype)]
-      ..addAll(node.fieldValues.entries.map(entryToProperty));
+    var properties = [
+      JS.Property(propertyName("__proto__"), prototype),
+      for (var e in node.fieldValues.entries) entryToProperty(e),
+    ];
     return canonicalizeConstObject(
         JS.ObjectInitializer(properties, multiline: true));
   }
 
   @override
-  visitTearOffConstant(node) => _emitStaticGet(node.procedure);
+  JS.Expression visitTearOffConstant(TearOffConstant node) =>
+      _emitStaticGet(node.procedure);
 
   @override
-  visitTypeLiteralConstant(node) => _emitTypeLiteral(node.type);
+  JS.Expression visitTypeLiteralConstant(TypeLiteralConstant node) =>
+      _emitTypeLiteral(node.type);
 
   @override
-  visitPartialInstantiationConstant(node) {
-    return runtimeCall('gbind(#, #)', [
-      visitConstant(node.tearOffConstant),
-      node.types.map(_emitType).toList()
-    ]);
-  }
+  JS.Expression visitPartialInstantiationConstant(
+          PartialInstantiationConstant node) =>
+      runtimeCall('gbind(#, #)', [
+        visitConstant(node.tearOffConstant),
+        node.types.map(_emitType).toList()
+      ]);
 
   @override
-  visitUnevaluatedConstant(node) {
-    return _visitExpression(node.expression);
-  }
+  JS.Expression visitUnevaluatedConstant(UnevaluatedConstant node) =>
+      _visitExpression(node.expression);
 }
 
 bool _isInlineJSFunction(Statement body) {
diff --git a/pkg/dev_compiler/lib/src/kernel/constants.dart b/pkg/dev_compiler/lib/src/kernel/constants.dart
index 4fe583b..3066d8e 100644
--- a/pkg/dev_compiler/lib/src/kernel/constants.dart
+++ b/pkg/dev_compiler/lib/src/kernel/constants.dart
@@ -118,7 +118,7 @@
   final CoreTypes coreTypes;
   _ConstantVisitor(this.coreTypes);
 
-  bool isConstant(Expression e) => e.accept(this);
+  bool isConstant(Expression e) => e.accept(this) as bool;
 
   @override
   defaultExpression(node) => false;
@@ -200,6 +200,23 @@
 
   @override
   NumberSemantics get numberSemantics => NumberSemantics.js;
+
+  @override
+  bool shouldInlineConstant(ConstantExpression initializer) {
+    Constant constant = initializer.constant;
+    if (constant is StringConstant) {
+      // Only inline small string constants, not large ones.
+      // (The upper bound value is arbitrary.)
+      return constant.value.length < 32;
+    } else if (constant is PrimitiveConstant) {
+      // Inline all other primitives.
+      return true;
+    } else {
+      // Don't inline other constants, because it would take too much code size.
+      // Better to refer to them by their field/variable name.
+      return false;
+    }
+  }
 }
 
 class _ErrorReporter extends SimpleErrorReporter {
diff --git a/pkg/dev_compiler/lib/src/kernel/native_types.dart b/pkg/dev_compiler/lib/src/kernel/native_types.dart
index 99a2140..d5450f6 100644
--- a/pkg/dev_compiler/lib/src/kernel/native_types.dart
+++ b/pkg/dev_compiler/lib/src/kernel/native_types.dart
@@ -142,7 +142,7 @@
   /// field (which is also the constructor parameter).
   String _getNativeAnnotationName(Expression annotation) {
     if (!_isNativeAnnotation(annotation)) return null;
-    return constants.getFieldValueFromAnnotation(annotation, 'name');
+    return constants.getFieldValueFromAnnotation(annotation, 'name') as String;
   }
 }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
index 185d3f0..481a4e8 100644
--- a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
+++ b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
@@ -230,7 +230,7 @@
   @override
   visitConstantExpression(ConstantExpression node) {
     var c = node.constant;
-    if (c is UnevaluatedConstant) return c.expression.accept(this);
+    if (c is UnevaluatedConstant) return c.expression.accept(this) as bool;
     if (c is PrimitiveConstant) return c.value == null;
     return false;
   }
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 5738f30..e954139 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -67,8 +67,21 @@
       uri.scheme == 'dart' &&
       (uri.path == 'core' || uri.path == '_interceptors');
 
+  bool _allowedTestLibrary(Uri uri) {
+    String scriptName = uri.path;
+    return scriptName.contains('tests/compiler/dartdevc_native');
+  }
+
+  bool _allowedDartLibrary(Uri uri) => uri.scheme == 'dart';
+
   @override
-  bool enableNative(Uri uri) => uri.scheme == 'dart';
+  bool enableNative(Uri uri) =>
+      _allowedTestLibrary(uri) || _allowedDartLibrary(uri);
+
+  @override
+  bool allowPlatformPrivateLibraryAccess(Uri importer, Uri imported) =>
+      super.allowPlatformPrivateLibraryAccess(importer, imported) ||
+      _allowedTestLibrary(importer);
 
   @override
   bool get nativeExtensionExpectsString => false;
diff --git a/pkg/dev_compiler/pubspec.yaml b/pkg/dev_compiler/pubspec.yaml
index ea33a0b..7ca09fb 100644
--- a/pkg/dev_compiler/pubspec.yaml
+++ b/pkg/dev_compiler/pubspec.yaml
@@ -2,7 +2,7 @@
 publish_to: none
 
 environment:
-  sdk: '>=2.1.0 <3.0.0'
+  sdk: '>=2.3.0 <3.0.0'
 
 dependencies:
   analyzer: any
diff --git a/pkg/dev_compiler/test/modular/data/js_interop/.packages b/pkg/dev_compiler/test/modular/data/js_interop/.packages
new file mode 100644
index 0000000..68d6156
--- /dev/null
+++ b/pkg/dev_compiler/test/modular/data/js_interop/.packages
@@ -0,0 +1 @@
+js:../../../../../../pkg/js/lib
diff --git a/pkg/dev_compiler/test/modular/data/js_interop/log.dart b/pkg/dev_compiler/test/modular/data/js_interop/log.dart
new file mode 100644
index 0000000..f69bf62
--- /dev/null
+++ b/pkg/dev_compiler/test/modular/data/js_interop/log.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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.
+
+/// Calls to [console.log] and to [log] from other modules don't work if the
+/// js-interop annotations are not preserved. However, calls via [log2] and
+/// [log3] do work because the annotation is available when compiling this
+/// module.
+@JS()
+library log;
+
+import 'package:js/js.dart';
+
+@JS()
+class Console {
+  @JS()
+  external void log(arg);
+}
+
+@JS('console')
+external Console get console;
+
+@JS('console.log')
+external void log(String s);
+
+void log2(String s) => log(s);
+void log3(String s) => console.log(s);
diff --git a/pkg/dev_compiler/test/modular/data/js_interop/main.dart b/pkg/dev_compiler/test/modular/data/js_interop/main.dart
new file mode 100644
index 0000000..f0d26c2
--- /dev/null
+++ b/pkg/dev_compiler/test/modular/data/js_interop/main.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2019, 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 'log.dart';
+
+void main() {
+  log2('A');
+  log3('B');
+  log('C');
+  console.log('D');
+}
diff --git a/pkg/dev_compiler/test/modular/data/js_interop/modules.yaml b/pkg/dev_compiler/test/modular/data/js_interop/modules.yaml
new file mode 100644
index 0000000..021eddc
--- /dev/null
+++ b/pkg/dev_compiler/test/modular/data/js_interop/modules.yaml
@@ -0,0 +1,8 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+#
+# Regression test: js-interop annotations need to be preserved in outline files.
+dependencies:
+  main: log
+  log: js
diff --git a/pkg/dev_compiler/test/modular/modular_test.dart b/pkg/dev_compiler/test/modular/modular_test.dart
new file mode 100644
index 0000000..8e96f72
--- /dev/null
+++ b/pkg/dev_compiler/test/modular/modular_test.dart
@@ -0,0 +1,320 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Test the modular compilation pipeline of ddc.
+///
+/// This is a shell that runs multiple tests, one per folder under `data/`.
+import 'dart:io';
+
+import 'package:modular_test/src/io_pipeline.dart';
+import 'package:modular_test/src/pipeline.dart';
+import 'package:modular_test/src/suite.dart';
+import 'package:modular_test/src/runner.dart';
+
+Uri sdkRoot = Platform.script.resolve("../../../../");
+Options _options;
+main(List<String> args) async {
+  _options = Options.parse(args);
+  var suiteFolder = Platform.script.resolve('data/');
+  var suiteName = relativize(suiteFolder, sdkRoot).path;
+  await runSuite(
+      suiteFolder,
+      suiteName.substring(0, suiteName.length - 1), // remove trailing /
+      _options,
+      new IOPipeline([
+        SourceToSummaryDillStep(),
+        DDKStep(),
+        RunD8(),
+      ], cacheSharedModules: true));
+}
+
+const dillId = const DataId("dill");
+const jsId = const DataId("js");
+const txtId = const DataId("txt");
+
+class SourceToSummaryDillStep implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [dillId];
+
+  @override
+  bool get needsSources => true;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [dillId];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [];
+
+  @override
+  bool get onlyOnMain => false;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: source-to-dill on $module");
+
+    // We use non file-URI schemes for representing source locations in a
+    // root-agnostic way. This allows us to refer to file across modules and
+    // across steps without exposing the underlying temporary folders that are
+    // created by the framework. In build systems like bazel this is especially
+    // important because each step may be run on a different machine.
+    //
+    // Files in packages are defined in terms of `package:` URIs, while
+    // non-package URIs are defined using the `dart-dev-app` scheme.
+    String rootScheme = module.isSdk ? 'dart-dev-sdk' : 'dev-dart-app';
+    String sourceToImportUri(Uri relativeUri) =>
+        _sourceToImportUri(module, rootScheme, relativeUri);
+
+    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+    _createPackagesFile(module, root, transitiveDependencies);
+
+    List<String> sources;
+    List<String> extraArgs;
+    if (module.isSdk) {
+      sources = ['dart:core'];
+      extraArgs = ['--libraries-file', '$rootScheme:///sdk/lib/libraries.json'];
+      assert(transitiveDependencies.isEmpty);
+    } else {
+      sources = module.sources.map(sourceToImportUri).toList();
+      extraArgs = ['--packages-file', '$rootScheme:/.packages'];
+    }
+
+    List<String> args = [
+      sdkRoot.resolve("utils/bazel/kernel_worker.dart").toFilePath(),
+      '--summary-only',
+      '--target',
+      'ddc',
+      '--multi-root',
+      '$root',
+      '--multi-root-scheme',
+      rootScheme,
+      ...extraArgs,
+      '--output',
+      '${toUri(module, dillId)}',
+      ...(transitiveDependencies
+          .expand((m) => ['--input-linked', '${toUri(m, dillId)}'])),
+      ...(sources.expand((String uri) => ['--source', uri])),
+      ...(flags.expand((String flag) => ['--enable-experiment', flag])),
+    ];
+
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: source-to-dill on $module");
+  }
+}
+
+class DDKStep implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [jsId];
+
+  @override
+  bool get needsSources => true;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [dillId];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [dillId];
+
+  @override
+  bool get onlyOnMain => false;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: ddk on $module");
+    var sdkRoot = Platform.script.resolve("../../../../");
+
+    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+    _createPackagesFile(module, root, transitiveDependencies);
+
+    List<String> args;
+    if (module.isSdk) {
+      // TODO(sigmund): this produces an error because kernel_sdk doesn't have a
+      // way to provide a .packages file. Technically is not needed, but it
+      // would be nice to proceed without any error messages.
+      args = [
+        '--packages=${sdkRoot.toFilePath()}/.packages',
+        sdkRoot.resolve('pkg/dev_compiler/tool/kernel_sdk.dart').toFilePath(),
+        '--libraries',
+        'sdk/lib/libraries.json',
+        '--output',
+        '${toUri(module, jsId)}.ignored_dill',
+      ];
+      var result = await _runProcess(
+          Platform.resolvedExecutable, args, root.toFilePath());
+      _checkExitCode(result, this, module);
+      await File.fromUri(root.resolve('es6/dart_sdk.js'))
+          .copy(root.resolveUri(toUri(module, jsId)).toFilePath());
+    } else {
+      Uri output = toUri(module, jsId);
+      Module sdkModule = module.dependencies.firstWhere((m) => m.isSdk);
+      String sourceToImportUri(Uri relativeUri) =>
+          _sourceToImportUri(module, 'dev-dart-app', relativeUri);
+
+      args = [
+        '--packages=${sdkRoot.toFilePath()}/.packages',
+        sdkRoot.resolve('pkg/dev_compiler/bin/dartdevc.dart').toFilePath(),
+        '--kernel',
+        '--modules=es6',
+        '--no-summarize',
+        '--no-source-map',
+        '--multi-root-scheme',
+        'dev-dart-app',
+        '--dart-sdk-summary',
+        '${toUri(sdkModule, dillId)}',
+        '--packages',
+        '.packages',
+        ...module.sources.map(sourceToImportUri),
+        for (String flag in flags) '--enable-experiment=$flag',
+        ...(transitiveDependencies
+            .where((m) => !m.isSdk)
+            .expand((m) => ['-s', '${toUri(m, dillId)}=${m.name}'])),
+        '-o',
+        '$output',
+      ];
+      var result = await _runProcess(
+          Platform.resolvedExecutable, args, root.toFilePath());
+      _checkExitCode(result, this, module);
+    }
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: ddk on $module");
+  }
+}
+
+class RunD8 implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [txtId];
+
+  @override
+  bool get needsSources => false;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [jsId];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [jsId];
+
+  @override
+  bool get onlyOnMain => true;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: d8 on $module");
+    var sdkRoot = Platform.script.resolve("../../../../");
+
+    // Rename sdk.js to dart_sdk.js (the alternative, but more hermetic solution
+    // would be to rename the import on all other .js files, but seems
+    // overkill/unnecessary.
+    if (await File.fromUri(root.resolve('dart_sdk.js')).exists()) {
+      throw 'error: dart_sdk.js already exists.';
+    }
+
+    await File.fromUri(root.resolve('sdk.js'))
+        .copy(root.resolve('dart_sdk.js').toFilePath());
+    var runjs = '''
+    import { dart, _isolate_helper } from 'dart_sdk.js';
+    import { main } from 'main.js';
+    _isolate_helper.startRootIsolate(() => {}, []);
+    main.main();
+    ''';
+
+    var wrapper =
+        root.resolveUri(toUri(module, jsId)).toFilePath() + ".wrapper.js";
+    await File(wrapper).writeAsString(runjs);
+    List<String> d8Args = ['--module', wrapper];
+    var result = await _runProcess(
+        sdkRoot.resolve(_d8executable).toFilePath(), d8Args, root.toFilePath());
+
+    _checkExitCode(result, this, module);
+
+    await File.fromUri(root.resolveUri(toUri(module, txtId)))
+        .writeAsString(result.stdout as String);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: d8 on $module");
+  }
+}
+
+void _checkExitCode(ProcessResult result, IOModularStep step, Module module) {
+  if (result.exitCode != 0 || _options.verbose) {
+    stdout.write(result.stdout);
+    stderr.write(result.stderr);
+  }
+  if (result.exitCode != 0) {
+    throw "${step.runtimeType} failed on $module:\n\n"
+        "stdout:\n${result.stdout}\n\n"
+        "stderr:\n${result.stderr}";
+  }
+}
+
+Future<ProcessResult> _runProcess(
+    String command, List<String> arguments, String workingDirectory) {
+  if (_options.verbose) {
+    print('command:\n$command ${arguments.join(' ')} from $workingDirectory');
+  }
+  return Process.run(command, arguments, workingDirectory: workingDirectory);
+}
+
+String get _d8executable {
+  if (Platform.isWindows) {
+    return 'third_party/d8/windows/d8.exe';
+  } else if (Platform.isLinux) {
+    return 'third_party/d8/linux/d8';
+  } else if (Platform.isMacOS) {
+    return 'third_party/d8/macos/d8';
+  }
+  throw new UnsupportedError('Unsupported platform.');
+}
+
+Future<void> _createPackagesFile(
+    Module module, Uri root, Set<Module> transitiveDependencies) async {
+  // We create a .packages file which defines the location of this module if
+  // it is a package.  The CFE requires that if a `package:` URI of a
+  // dependency is used in an import, then we need that package entry in the
+  // .packages file. However, after it checks that the definition exists, the
+  // CFE will not actually use the resolved URI if a library for the import
+  // URI is already found in one of the provided .dill files of the
+  // dependencies. For that reason, and to ensure that a step only has access
+  // to the files provided in a module, we generate a .packages with invalid
+  // folders for other packages.
+  // TODO(sigmund): follow up with the CFE to see if we can remove the need
+  // for the .packages entry altogether if they won't need to read the
+  // sources.
+  var packagesContents = new StringBuffer();
+  if (module.isPackage) {
+    packagesContents.write('${module.name}:${module.packageBase}\n');
+  }
+  for (Module dependency in transitiveDependencies) {
+    if (dependency.isPackage) {
+      packagesContents.write('${dependency.name}:unused\n');
+    }
+  }
+
+  await File.fromUri(root.resolve('.packages'))
+      .writeAsString('$packagesContents');
+}
+
+String _sourceToImportUri(Module module, String rootScheme, Uri relativeUri) {
+  if (module.isPackage) {
+    var basePath = module.packageBase.path;
+    var packageRelativePath = basePath == "./"
+        ? relativeUri.path
+        : relativeUri.path.substring(basePath.length);
+    return 'package:${module.name}/$packageRelativePath';
+  } else {
+    return '$rootScheme:/$relativeUri';
+  }
+}
diff --git a/pkg/dev_compiler/test/sourcemap/ddc_common.dart b/pkg/dev_compiler/test/sourcemap/ddc_common.dart
index 74f2764..f6f4838 100644
--- a/pkg/dev_compiler/test/sourcemap/ddc_common.dart
+++ b/pkg/dev_compiler/test/sourcemap/ddc_common.dart
@@ -167,7 +167,7 @@
   var sdkFile = File(path.relative(sdkJsFile.path, from: sdkRoot.path));
   String jsRootDart = "/root_dart/${sdkFile.uri}";
   File.fromUri(outputFile.resolve("$outputFilename.html.js")).writeAsStringSync(
-      jsContent.replaceFirst("from 'dart_sdk'", "from '$jsRootDart'"));
+      jsContent.replaceFirst("from 'dart_sdk.js'", "from '$jsRootDart'"));
   File.fromUri(outputFile.resolve("$outputFilename.html.html"))
       .writeAsStringSync(getWrapperHtmlContent(
           jsRootDart, "/root_build/$outputFilename.html.js"));
diff --git a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart
index d14cc6d..3818d6f 100644
--- a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart
+++ b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart
@@ -70,7 +70,7 @@
 
     var jsContent = File.fromUri(outputFile).readAsStringSync();
     File.fromUri(outputFile).writeAsStringSync(jsContent.replaceFirst(
-        "from 'dart_sdk'", "from '${uriPathForwardSlashed(jsSdkPath)}'"));
+        "from 'dart_sdk.js'", "from '${uriPathForwardSlashed(jsSdkPath)}'"));
 
     if (debugging) {
       createHtmlWrapper(
diff --git a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
index de9c620..511c10b 100644
--- a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
+++ b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
@@ -70,7 +70,8 @@
     bool succeeded = false;
     try {
       var result = await compile(args, compilerState: context.compilerState);
-      context.compilerState = result.compilerState;
+      context.compilerState =
+          result.compilerState as fe.InitializedCompilerState;
       succeeded = result.success;
     } catch (e, s) {
       print('Unhandled exception:');
@@ -88,7 +89,7 @@
 
     var jsContent = File.fromUri(outputFile).readAsStringSync();
     File.fromUri(outputFile).writeAsStringSync(jsContent.replaceFirst(
-        "from 'dart_sdk'", "from '${uriPathForwardSlashed(jsSdkPath)}'"));
+        "from 'dart_sdk.js'", "from '${uriPathForwardSlashed(jsSdkPath)}'"));
 
     if (debugging) {
       createHtmlWrapper(
diff --git a/pkg/dev_compiler/tool/ddb b/pkg/dev_compiler/tool/ddb
index 0b3049e..6cd6de3 100755
--- a/pkg/dev_compiler/tool/ddb
+++ b/pkg/dev_compiler/tool/ddb
@@ -77,11 +77,21 @@
   var summaries = options['summary'] as List;
   var port = int.parse(options['port'] as String);
 
+  // By default (no `-d`), we use the `dartdevc` binary on the user's path to
+  // compute the SDK we use for execution.  I.e., we assume that `dart` is
+  // under `$DART_SDK/bin/dart` and use that to find `dartdevc` and related
+  // artifacts.  In this mode, this script can run against any installed SDK.
+  // If you want to run against a freshly built SDK, that must be first on
+  // your path.
   var dartBinary = Platform.resolvedExecutable;
-  var dartPath = path.dirname(dartBinary);
-  var dartSdk = path.dirname(dartPath);
+  var dartSdk = path.dirname(path.dirname(dartBinary));
+
+  // In debug mode (`-d`), we run from the `pkg/dev_compiler` sources.  We
+  // determine the location via this actual script (i.e., `-d` assumes
+  // this script remains under to `tool` sub-directory).
   var toolPath = Platform.script.normalizePath().toFilePath();
   var ddcPath = path.dirname(path.dirname(toolPath));
+  var dartCheckoutPath = path.dirname(path.dirname(ddcPath));
 
   ProcessResult runDdc(String command, List<String> args) {
     if (debug) {
@@ -91,7 +101,7 @@
       command = dartBinary;
     } else {
       // Use built snapshot.
-      command = path.join(dartPath, command);
+      command = path.join(dartSdk, 'bin', command);
     }
     return Process.runSync(command, args);
   }
@@ -236,6 +246,15 @@
         nodeBinary, ['--inspect=localhost:$port', nodeFile],
         environment: {'NODE_PATH': nodePath});
   } else if (d8) {
+    // Fix SDK import.  `d8` doesn't let us set paths, so we need a full path
+    // to the SDK.
+
+    var jsFile = File('$libRoot/$basename.js');
+    var jsContents = jsFile.readAsStringSync();
+    jsContents = jsContents.replaceFirst(
+        "from 'dart_sdk.js'", "from '$sdkJsPath/dart_sdk.js'");
+    jsFile.writeAsStringSync(jsContents);
+
     var runjs = '''
     import { dart, _isolate_helper } from '$sdkJsPath/dart_sdk.js';
     import { $basename } from '$basename.js';
@@ -248,10 +267,21 @@
       console.error(e);
     }
     ''';
-    var d8File = '$libRoot/$basename.d8.js';
+    var d8File = path.join(libRoot, '$basename.d8.js');
     new File(d8File).writeAsStringSync(runjs);
-    var d8Binary = binary ?? 'd8';
+    var d8Binary = binary ?? path.join(dartCheckoutPath, _d8executable);
     result = Process.runSync(d8Binary, ['--module', d8File]);
   }
   await echoResult(result);
 }
+
+String get _d8executable {
+  if (Platform.isWindows) {
+    return path.join('third_party', 'd8', 'windows', 'd8.exe');
+  } else if (Platform.isLinux) {
+    return path.join('third_party', 'd8', 'linux', 'd8');
+  } else if (Platform.isMacOS) {
+    return path.join('third_party', 'd8', 'macos', 'd8');
+  }
+  throw new UnsupportedError('Unsupported platform.');
+}
diff --git a/pkg/dev_compiler/tool/ddw b/pkg/dev_compiler/tool/ddw
deleted file mode 100755
index c35b2ca..0000000
--- a/pkg/dev_compiler/tool/ddw
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/bin/bash
-#
-# Compiles code with DDC and runs the resulting code in node.js.
-#
-# The first script supplied should be the one with `main()`.
-#
-# Saves the output in the same directory as the sources for convenient
-# inspection, modification or rerunning the code.
-set -e
-
-function follow_links() {
-  file="$1"
-  while [ -h "$file" ]; do
-    file="$(readlink "$file")"
-  done
-  echo "$file"
-}
-PROG_NAME="$(follow_links "$BASH_SOURCE")"
-SDK_DIR="$( cd "${PROG_NAME%/*}/../../.."; pwd -P)"
-
-if [[ `uname` == 'Darwin' ]];
-then
-  OUT_DIR="$SDK_DIR"/xcodebuild
-else
-  OUT_DIR="$SDK_DIR"/out
-fi
-
-if [ -z "$DART_CONFIGURATION" ];
-then
-  DIRS=$( ls "$OUT_DIR" )
-  # list of possible configurations in decreasing desirability
-  CONFIGS=("ReleaseX64" "ReleaseIA32" "DebugX64" "DebugIA32"
-    "ReleaseARM"    "ReleaseARM64"    "ReleaseARMV5TE"
-    "DebugARM"      "DebugARM64"      "DebugARMV5TE")
-  DART_CONFIGURATION="None"
-  for CONFIG in ${CONFIGS[*]}
-  do
-    for DIR in $DIRS;
-    do
-      if [ "$CONFIG" = "$DIR" ];
-      then
-        # choose most desirable configuration that is available and break
-        DART_CONFIGURATION="$DIR"
-        break 2
-      fi
-    done
-  done
-  if [ "$DART_CONFIGURATION" = "None" ]
-  then
-    echo "No valid dart configuration found in $OUT_DIR"
-    exit 1
-  fi
-fi
-
-GEN_DIR="$OUT_DIR"/"$DART_CONFIGURATION"/gen/utils/dartdevc
-
-KERNEL=false
-if [ "$1" = "-k" ]; then
-  KERNEL=true
-  shift
-fi
-
-BASENAME=$( basename "${1%.*}")
-LIBROOT=$(cd $( dirname "${1%.*}") && pwd)
-
-if [ "$KERNEL" = true ]; then
-
-  if [ ! -e $GEN_DIR/kernel/ddc_sdk.dill ]; then
-    echo "DDC SDK must be built first, please run:"
-    echo "    pushd $SDKDIR"
-    echo "    ./tools/build.py -m release dartdevc_kernel_sdk"
-    exit 1
-  fi
-
-  NODE_PATH=$GEN_DIR/kernel/common:$LIBROOT:$NODE_PATH
-
-  dart -c $SDK_DIR/pkg/dev_compiler/bin/dartdevc.dart --kernel --modules=node \
-      --dart-sdk-summary=$GEN_DIR/kernel/ddc_sdk.dill \
-      -o $LIBROOT/$BASENAME.js $*
-else
-
-  if [ ! -e $GEN_DIR/ddc_sdk.sum ]; then
-    echo "DDC SDK must be built first, please run:"
-    echo "    pushd $SDKDIR"
-    echo "    ./tools/build.py -m release dartdevc_sdk"
-    exit 1
-  fi
-
-  NODE_PATH=$GEN_DIR/js/common:$LIBROOT:$NODE_PATH
-
-  dart -c $SDK_DIR/pkg/dev_compiler/bin/dartdevc.dart --modules=node \
-      --library-root=$LIBROOT --dart-sdk-summary=$GEN_DIR/ddc_sdk.sum \
-      -o $LIBROOT/$BASENAME.js $*
-fi
-
-pushd $LIBROOT > /dev/null
-echo "
-    // Fix the node.js search paths that Electron cleared out.
-    const Module = require('module');
-    const originalResolveFilename = Module._resolveFilename;
-    Module._resolveFilename = function (request, parent, isMain) {
-      let paths = parent.paths;
-      const ddcPath = \"$GEN_DIR/js/common\";
-      if (paths[0] != ddcPath) {
-        paths.splice(0, 0, ddcPath, \"$LIBROOT\");
-      }
-      return originalResolveFilename(request, parent, isMain);
-    };
-    let sdk = require(\"dart_sdk\");
-    let main = require(\"$BASENAME\").$BASENAME.main;
-    sdk.dart.ignoreWhitelistedErrors(false);
-    sdk._isolate_helper.startRootIsolate(main, []);" \
-    > $LIBROOT/$BASENAME.run.js
-devtool $LIBROOT/$BASENAME.run.js
-popd > /dev/null
diff --git a/pkg/dev_compiler/tool/global_compile.dart b/pkg/dev_compiler/tool/global_compile.dart
deleted file mode 100644
index a1f96fd..0000000
--- a/pkg/dev_compiler/tool/global_compile.dart
+++ /dev/null
@@ -1,285 +0,0 @@
-#!/usr/bin/env dart
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:io';
-
-// ignore: deprecated_member_use
-import 'package:analyzer/analyzer.dart' show parseDirectives;
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:args/args.dart' show ArgParser;
-import 'package:path/path.dart' as path;
-
-const ENTRY = "main";
-
-void main(List<String> args) {
-  // Parse flags.
-  var parser = ArgParser()
-    ..addOption('out',
-        help: 'Output file (defaults to "out.js")',
-        abbr: 'o',
-        defaultsTo: 'out.js')
-    ..addFlag('unsafe-force-compile',
-        help: 'Generate code with undefined behavior', negatable: false)
-    ..addFlag('emit-metadata',
-        help: 'Preserve annotations in generated code', negatable: false)
-    ..addOption('package-root',
-        help: 'Directory containing packages',
-        abbr: 'p',
-        defaultsTo: 'packages/')
-    ..addFlag('log', help: 'Show individual build commands')
-    ..addOption('tmp',
-        help:
-            'Directory for temporary artifacts (defaults to a system tmp directory)');
-
-  var options = parser.parse(args);
-  if (options.rest.length != 1) {
-    throw 'Expected a single dart entrypoint.';
-  }
-  var entry = options.rest.first;
-  var outfile = options['out'] as String;
-  var packageRoot = options['package-root'] as String;
-  var unsafe = options['unsafe-force-compile'] as bool;
-  var log = options['log'] as bool;
-  var tmp = options['tmp'] as String;
-  var metadata = options['emit-metadata'] as bool;
-
-  // Build an invocation to dartdevc
-  var dartPath = Platform.resolvedExecutable;
-  var ddcPath = path.dirname(path.dirname(Platform.script.toFilePath()));
-  var template = [
-    '$ddcPath/bin/dartdevc.dart',
-    '--modules=legacy', // TODO(vsm): Change this to use common format.
-    '--single-out-file',
-    '--inline-source-map',
-    '-p',
-    packageRoot
-  ];
-  if (metadata) {
-    template.add('--emit-metadata');
-  }
-  if (unsafe) {
-    template.add('--unsafe-force-compile');
-  }
-
-  // Compute the transitive closure
-  var total = Stopwatch()..start();
-  var partial = Stopwatch()..start();
-
-  // TODO(vsm): We're using the analyzer just to compute the import/export/part
-  // dependence graph.  This is expensive.  Is there a lighterweight way to do
-  // this?
-  transitiveFiles(entry, Directory.current.path, packageRoot);
-  orderModules();
-  computeTransitiveDependences();
-
-  var graphTime = partial.elapsedMilliseconds / 1000;
-  print('Computed global build graph in $graphTime seconds');
-
-  // Prepend Dart runtime files to the output
-  var out = File(outfile);
-  var dartLibrary =
-      File(path.join(ddcPath, 'lib', 'js', 'legacy', 'dart_library.js'))
-          .readAsStringSync();
-  out.writeAsStringSync(dartLibrary);
-  var dartSdk = File(path.join(ddcPath, 'lib', 'js', 'legacy', 'dart_sdk.js'))
-      .readAsStringSync();
-  out.writeAsStringSync(dartSdk, mode: FileMode.append);
-
-  // Linearize module concatenation for deterministic output
-  var last = Future.value();
-  for (var module in orderedModules) {
-    linearizerMap[module] = last;
-    var completer = Completer();
-    completerMap[module] = completer;
-    last = completer.future;
-  }
-
-  // Build modules asynchronously
-  var tmpdir = (tmp == null)
-      ? Directory.systemTemp
-          .createTempSync(outfile.replaceAll(path.separator, '__'))
-      : Directory(tmp)
-    ..createSync();
-  for (var module in orderedModules) {
-    var file = tmpdir.path + path.separator + module + '.js';
-    var command = template.toList()..addAll(['-o', file]);
-    var dependences = transitiveDependenceMap[module];
-    for (var dependence in dependences) {
-      var summary = tmpdir.path + path.separator + dependence + '.sum';
-      command.addAll(['-s', summary]);
-    }
-    var infiles = fileMap[module];
-    command.addAll(infiles);
-
-    var waitList = dependenceMap.containsKey(module)
-        ? dependenceMap[module].map((dep) => readyMap[dep])
-        : <Future>[];
-    var future = Future.wait(waitList);
-    readyMap[module] = future.then((_) {
-      var ready = Process.run(dartPath, command);
-      if (log) {
-        print(command.join(' '));
-      }
-      return ready.then((result) {
-        if (result.exitCode != 0) {
-          print('ERROR: compiling $module');
-          print(result.stdout);
-          print(result.stderr);
-          out.deleteSync();
-          exit(1);
-        }
-        print('Compiled $module (${infiles.length} files)');
-        print(result.stdout);
-
-        // Schedule module append once the previous module is written
-        var codefile = File(file);
-        linearizerMap[module]
-            .then((_) => codefile.readAsString())
-            .then((code) =>
-                out.writeAsString(code, mode: FileMode.append, flush: true))
-            .then((_) => completerMap[module].complete());
-      });
-    });
-  }
-
-  last.then((_) {
-    var time = total.elapsedMilliseconds / 1000;
-    print('Successfully compiled ${inputSet.length} files in $time seconds');
-
-    // Append the entry point invocation.
-    var libraryName =
-        path.withoutExtension(entry).replaceAll(path.separator, '__');
-    out.writeAsStringSync('dart_library.start("$ENTRY", "$libraryName");\n',
-        mode: FileMode.append);
-  });
-}
-
-final inputSet = Set<String>();
-final dependenceMap = Map<String, Set<String>>();
-final transitiveDependenceMap = Map<String, Set<String>>();
-final fileMap = Map<String, Set<String>>();
-
-final readyMap = Map<String, Future>();
-final linearizerMap = Map<String, Future>();
-final completerMap = Map<String, Completer>();
-
-final orderedModules = List<String>();
-final visitedModules = Set<String>();
-
-void orderModules(
-    [String module = ENTRY, List<String> stack, Set<String> visited]) {
-  if (stack == null) {
-    assert(visited == null);
-    stack = List<String>();
-    visited = Set<String>();
-  }
-  if (visited.contains(module)) return;
-  visited.add(module);
-  if (stack.contains(module)) {
-    print(stack);
-    throw 'Circular dependence on $module';
-  }
-  stack.add(module);
-  var dependences = dependenceMap[module];
-  if (dependences != null) {
-    for (var dependence in dependences) {
-      orderModules(dependence, stack, visited);
-    }
-  }
-  orderedModules.add(module);
-  assert(module == stack.last);
-  stack.removeLast();
-}
-
-void computeTransitiveDependences() {
-  for (var module in orderedModules) {
-    var transitiveSet = Set<String>();
-    if (dependenceMap.containsKey(module)) {
-      transitiveSet.addAll(dependenceMap[module]);
-      for (var dependence in dependenceMap[module]) {
-        transitiveSet.addAll(transitiveDependenceMap[dependence]);
-      }
-    }
-    transitiveDependenceMap[module] = transitiveSet;
-  }
-}
-
-String getModule(String uri) {
-  var sourceUri = Uri.parse(uri);
-  if (sourceUri.scheme == 'dart') {
-    return 'dart';
-  } else if (sourceUri.scheme == 'package') {
-    return path.split(sourceUri.path)[0];
-  } else {
-    return ENTRY;
-  }
-}
-
-bool processFile(String file) {
-  inputSet.add(file);
-
-  var module = getModule(file);
-  fileMap.putIfAbsent(module, () => Set<String>());
-  return fileMap[module].add(file);
-}
-
-void processDependence(String from, String to) {
-  var fromModule = getModule(from);
-  var toModule = getModule(to);
-  if (fromModule == toModule || toModule == 'dart') return;
-  dependenceMap.putIfAbsent(fromModule, () => Set<String>());
-  dependenceMap[fromModule].add(toModule);
-}
-
-String canonicalize(String uri, String root) {
-  var sourceUri = Uri.parse(uri);
-  if (sourceUri.scheme == '') {
-    sourceUri = path.toUri(
-        path.isAbsolute(uri) ? path.absolute(uri) : path.join(root, uri));
-    return sourceUri.path;
-  }
-  return sourceUri.toString();
-}
-
-/// Simplified from ParseDartTask.resolveDirective.
-String _resolveDirective(UriBasedDirectiveImpl directive) {
-  StringLiteral uriLiteral = directive.uri;
-  String uriContent = uriLiteral.stringValue;
-  if (uriContent != null) {
-    uriContent = uriContent.trim();
-    directive.uriContent = uriContent;
-  }
-  return directive.validate() == null ? uriContent : null;
-}
-
-String _loadFile(String uri, String packageRoot) {
-  if (uri.startsWith('package:')) {
-    uri = path.join(packageRoot, uri.substring(8));
-  }
-  return File(uri).readAsStringSync();
-}
-
-void transitiveFiles(String entryPoint, String root, String packageRoot) {
-  entryPoint = canonicalize(entryPoint, root);
-  if (entryPoint.startsWith('dart:')) return;
-  if (processFile(entryPoint)) {
-    // Process this
-    var source = _loadFile(entryPoint, packageRoot);
-    var entryDir = path.dirname(entryPoint);
-    var unit = parseDirectives(source, name: entryPoint, suppressErrors: true);
-    for (var d in unit.directives) {
-      if (d is NamespaceDirectiveImpl) {
-        var uri = _resolveDirective(d);
-        processDependence(entryPoint, canonicalize(uri, entryDir));
-        transitiveFiles(uri, entryDir, packageRoot);
-      } else if (d is PartDirectiveImpl) {
-        var uri = _resolveDirective(d);
-        processFile(canonicalize(uri, entryDir));
-      }
-    }
-  }
-}
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart
index f9dd584..d0bbcd8 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart
@@ -303,8 +303,9 @@
   }
 }
 
-class ImmutableSet<E> extends _HashSet<E> {
-  ImmutableSet.from(JSArray entries) {
+// Used for DDC const sets.
+class _ImmutableSet<E> extends _HashSet<E> {
+  _ImmutableSet.from(JSArray entries) {
     var map = _map;
     for (Object key in entries) {
       if (key == null) {
@@ -323,7 +324,7 @@
   bool remove(Object key) => throw _unsupported();
 
   static Error _unsupported() =>
-      UnsupportedError("Cannot modify unmodifiable map");
+      UnsupportedError("Cannot modify unmodifiable set");
 }
 
 class _IdentityHashSet<E> extends _InternalSet<E>
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
index a8103b3..1c742e1 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
@@ -645,6 +645,7 @@
   final List _arguments;
   final Map<Symbol, dynamic> _namedArguments;
   final List _existingArgumentNames;
+  final Invocation _invocation;
 
   @patch
   NoSuchMethodError(Object receiver, Symbol memberName,
@@ -654,7 +655,8 @@
         _memberName = memberName,
         _arguments = positionalArguments,
         _namedArguments = namedArguments,
-        _existingArgumentNames = existingArgumentNames;
+        _existingArgumentNames = existingArgumentNames,
+        _invocation = null;
 
   @patch
   NoSuchMethodError.withInvocation(Object receiver, Invocation invocation)
@@ -662,7 +664,8 @@
         _memberName = invocation.memberName,
         _arguments = invocation.positionalArguments,
         _namedArguments = invocation.namedArguments,
-        _existingArgumentNames = null;
+        _existingArgumentNames = null,
+        _invocation = invocation;
 
   @patch
   String toString() {
@@ -687,8 +690,12 @@
     String memberName = _symbolToString(_memberName);
     String receiverText = Error.safeToString(_receiver);
     String actualParameters = '$sb';
+    var failureMessage = (_invocation is dart.InvocationImpl)
+        ? (_invocation as dart.InvocationImpl).failureMessage
+        : 'method not found';
     if (_existingArgumentNames == null) {
-      return "NoSuchMethodError: method not found: '$memberName'\n"
+      return "NoSuchMethodError: '$memberName'\n"
+          "$failureMessage\n"
           "Receiver: ${receiverText}\n"
           "Arguments: [$actualParameters]";
     } else {
@@ -2316,6 +2323,7 @@
         _rsh(uDigits, maxUsed, 1, uDigits);
         if (ac) {
           if (((aDigits[0] & 1) == 1) || ((bDigits[0] & 1) == 1)) {
+            // a += y
             if (aIsNegative) {
               if ((aDigits[maxUsed] != 0) ||
                   (_compareDigits(aDigits, maxUsed, yDigits, maxUsed)) > 0) {
@@ -2327,6 +2335,7 @@
             } else {
               _absAdd(aDigits, abcdUsed, yDigits, maxUsed, aDigits);
             }
+            // b -= x
             if (bIsNegative) {
               _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
             } else if ((bDigits[maxUsed] != 0) ||
@@ -2339,6 +2348,7 @@
           }
           _rsh(aDigits, abcdUsed, 1, aDigits);
         } else if ((bDigits[0] & 1) == 1) {
+          // b -= x
           if (bIsNegative) {
             _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
           } else if ((bDigits[maxUsed] != 0) ||
@@ -2355,6 +2365,7 @@
         _rsh(vDigits, maxUsed, 1, vDigits);
         if (ac) {
           if (((cDigits[0] & 1) == 1) || ((dDigits[0] & 1) == 1)) {
+            // c += y
             if (cIsNegative) {
               if ((cDigits[maxUsed] != 0) ||
                   (_compareDigits(cDigits, maxUsed, yDigits, maxUsed) > 0)) {
@@ -2366,6 +2377,7 @@
             } else {
               _absAdd(cDigits, abcdUsed, yDigits, maxUsed, cDigits);
             }
+            // d -= x
             if (dIsNegative) {
               _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
             } else if ((dDigits[maxUsed] != 0) ||
@@ -2378,6 +2390,7 @@
           }
           _rsh(cDigits, abcdUsed, 1, cDigits);
         } else if ((dDigits[0] & 1) == 1) {
+          // d -= x
           if (dIsNegative) {
             _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
           } else if ((dDigits[maxUsed] != 0) ||
@@ -2391,8 +2404,10 @@
         _rsh(dDigits, abcdUsed, 1, dDigits);
       }
       if (_compareDigits(uDigits, maxUsed, vDigits, maxUsed) >= 0) {
+        // u -= v
         _absSub(uDigits, maxUsed, vDigits, maxUsed, uDigits);
         if (ac) {
+          // a -= c
           if (aIsNegative == cIsNegative) {
             var a_cmp_c = _compareDigits(aDigits, abcdUsed, cDigits, abcdUsed);
             if (a_cmp_c > 0) {
@@ -2405,6 +2420,7 @@
             _absAdd(aDigits, abcdUsed, cDigits, abcdUsed, aDigits);
           }
         }
+        // b -= d
         if (bIsNegative == dIsNegative) {
           var b_cmp_d = _compareDigits(bDigits, abcdUsed, dDigits, abcdUsed);
           if (b_cmp_d > 0) {
@@ -2417,8 +2433,10 @@
           _absAdd(bDigits, abcdUsed, dDigits, abcdUsed, bDigits);
         }
       } else {
+        // v -= u
         _absSub(vDigits, maxUsed, uDigits, maxUsed, vDigits);
         if (ac) {
+          // c -= a
           if (cIsNegative == aIsNegative) {
             var c_cmp_a = _compareDigits(cDigits, abcdUsed, aDigits, abcdUsed);
             if (c_cmp_a > 0) {
@@ -2431,6 +2449,7 @@
             _absAdd(cDigits, abcdUsed, aDigits, abcdUsed, cDigits);
           }
         }
+        // d -= b
         if (dIsNegative == bIsNegative) {
           var d_cmp_b = _compareDigits(dDigits, abcdUsed, bDigits, abcdUsed);
           if (d_cmp_b > 0) {
@@ -2462,25 +2481,18 @@
     }
 
     if (dIsNegative) {
-      if ((dDigits[maxUsed] != 0) ||
+      while ((dDigits[maxUsed] != 0) ||
           (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+        // d += x, d still negative
         _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-        if ((dDigits[maxUsed] != 0) ||
-            (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-          _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-        } else {
-          _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
-          dIsNegative = false;
-        }
-      } else {
-        _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
-        dIsNegative = false;
       }
-    } else if ((dDigits[maxUsed] != 0) ||
-        (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-      _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-      if ((dDigits[maxUsed] != 0) ||
-          (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+      // d += x
+      _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
+      dIsNegative = false;
+    } else {
+      while ((dDigits[maxUsed] != 0) ||
+          (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) >= 0)) {
+        // d -= x
         _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
       }
     }
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart
index 02b8aca..704b856 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart
@@ -188,6 +188,7 @@
 final _staticGetterSig = JS('', 'Symbol("sigStaticGetter")');
 final _staticSetterSig = JS('', 'Symbol("sigStaticSetter")');
 final _genericTypeCtor = JS('', 'Symbol("genericType")');
+final _libraryUri = JS('', 'Symbol("libraryUri")');
 
 getConstructors(value) => _getMembers(value, _constructorSig);
 getMethods(value) => _getMembers(value, _methodSig);
@@ -205,6 +206,9 @@
 getType(obj) =>
     JS('', '# == null ? # : #.__proto__.constructor', obj, Object, obj);
 
+getLibraryUri(value) => JS('', '#[#]', value, _libraryUri);
+setLibraryUri(f, uri) => JS('', '#[#] = #', f, _libraryUri, uri);
+
 bool isJsInterop(obj) {
   if (obj == null) return false;
   if (JS('!', 'typeof # === "function"', obj)) {
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
index 8c8e929..d4cec70 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
@@ -33,9 +33,13 @@
   throw UnimplementedError(message);
 }
 
-assertFailed(message) {
+// TODO(nshahan) Cleanup embeded strings and extract file location at runtime
+// from the stacktrace.
+assertFailed(String message,
+    [String fileUri, int line, int column, String conditionSource]) {
   if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
-  throw AssertionErrorImpl(message);
+
+  throw AssertionErrorImpl(message, fileUri, line, column, conditionSource);
 }
 
 throwCyclicInitializationError([Object field]) {
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
index 7ab4a81..0c287ae 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
@@ -15,13 +15,15 @@
   final bool isMethod;
   final bool isGetter;
   final bool isSetter;
+  final String failureMessage;
 
   InvocationImpl(memberName, List<Object> positionalArguments,
       {namedArguments,
       List typeArguments,
       this.isMethod = false,
       this.isGetter = false,
-      this.isSetter = false})
+      this.isSetter = false,
+      this.failureMessage = 'method not found'})
       : memberName =
             isSetter ? _setterSymbol(memberName) : _dartSymbol(memberName),
         positionalArguments = List.unmodifiable(positionalArguments),
@@ -156,19 +158,27 @@
   return value;
 }
 
-/// Check that a function of a given type can be applied to
-/// actuals.
-bool _checkApply(FunctionType type, List actuals, namedActuals) {
+/// Returns an error message if function of a given [type] can't be applied to
+/// [actuals] and [namedActuals].
+///
+/// Returns `null` if all checks pass.
+String _argumentErrors(FunctionType type, List actuals, namedActuals) {
   // Check for too few required arguments.
   int actualsCount = JS('!', '#.length', actuals);
   var required = type.args;
   int requiredCount = JS('!', '#.length', required);
-  if (actualsCount < requiredCount) return false;
+  if (actualsCount < requiredCount) {
+    return 'Dynamic call with too few arguments. '
+        'Expected: $requiredCount Actual: $actualsCount';
+  }
 
   // Check for too many postional arguments.
   var extras = actualsCount - requiredCount;
   var optionals = type.optionals;
-  if (extras > JS<int>('!', '#.length', optionals)) return false;
+  if (extras > JS<int>('!', '#.length', optionals)) {
+    return 'Dynamic call with too many arguments. '
+        'Expected: $requiredCount Actual: $actualsCount';
+  }
 
   // Check if we have invalid named arguments.
   Iterable names;
@@ -176,7 +186,9 @@
   if (namedActuals != null) {
     names = getOwnPropertyNames(namedActuals);
     for (var name in names) {
-      if (!JS('!', '#.hasOwnProperty(#)', named, name)) return false;
+      if (!JS('!', '#.hasOwnProperty(#)', named, name)) {
+        return "Dynamic call with unexpected named argument '$name'.";
+      }
     }
   }
   // Now that we know the signature matches, we can perform type checks.
@@ -191,7 +203,7 @@
       JS('', '#[#]._check(#[#])', named, name, namedActuals, name);
     }
   }
-  return true;
+  return null;
 }
 
 _toSymbolName(symbol) => JS('', '''(() => {
@@ -242,14 +254,16 @@
 
   let originalTarget = obj === void 0 ? f : obj;
 
-  function callNSM() {
+  function callNSM(errorMessage) {
     return $noSuchMethod(originalTarget, new $InvocationImpl.new(
         $displayName, $args, {
           namedArguments: $named,
           typeArguments: $typeArgs,
-          isMethod: true
+          isMethod: true,
+          failureMessage: errorMessage
         }));
   }
+  if ($f == null) return callNSM('Dynamic call of null.');
   if (!($f instanceof Function)) {
     // We're not a function (and hence not a method either)
     // Grab the `call` method if it's not a function.
@@ -261,7 +275,8 @@
       $f = ${bindCall(f, _canonicalMember(f, 'call'))};
       $ftype = null;
     }
-    if ($f == null) return callNSM();
+    if ($f == null) return callNSM(
+        "Dynamic call of object has no instance method 'call'.");
   }
   // If f is a function, but not a method (no method type)
   // then it should have been a function valued field, so
@@ -291,21 +306,23 @@
     if ($typeArgs == null) {
       $typeArgs = $ftype.instantiateDefaultBounds();
     } else if ($typeArgs.length != formalCount) {
-      return callNSM();
+      return callNSM('Dynamic call with incorrect number of type arguments. ' +
+          'Expected: ' + formalCount + ' Actual: ' + $typeArgs.length);
     } else {
       $ftype.checkBounds($typeArgs);
     }
     $ftype = $ftype.instantiate($typeArgs);
   } else if ($typeArgs != null) {
-    return callNSM();
+    return callNSM('Dynamic call with unexpected type arguments. ' +
+        'Expected: 0 Actual: ' + $typeArgs.length);
   }
-
-  if ($_checkApply($ftype, $args, $named)) {
+  let errorMessage = $_argumentErrors($ftype, $args, $named);
+  if (errorMessage == null) {
     if ($typeArgs != null) $args = $typeArgs.concat($args);
     if ($named != null) $args.push($named);
     return $f.apply($obj, $args);
   }
-  return callNSM();
+  return callNSM(errorMessage);
 })()''');
 
 dcall(f, args, [@undefined named]) =>
@@ -434,9 +451,8 @@
     result =
         _ignoreTypeFailure(t1, typeFuture) || _ignoreTypeFailure(t1, typeArg);
   } else {
-    result = t1 is FunctionType && t2 is FunctionType ||
-        isSubtypeOf(t2, unwrapType(Iterable)) &&
-            isSubtypeOf(t1, unwrapType(Iterable));
+    result = isSubtypeOf(t2, unwrapType(Iterable)) &&
+        isSubtypeOf(t1, unwrapType(Iterable));
     if (result) {
       _warn('Ignoring cast fail from ${typeName(t1)} to ${typeName(t2)}');
     }
@@ -532,6 +548,14 @@
 }
 
 final constantSets = JS('', 'new Map()');
+var _immutableSetConstructor;
+
+// We cannot invoke private class constructors directly in Dart.
+Set<E> _createImmutableSet<E>(JSArray<E> elements) {
+  _immutableSetConstructor ??=
+      JS('', '#.#', getLibrary('dart:collection'), '_ImmutableSet\$');
+  return JS('', 'new (#(#)).from(#)', _immutableSetConstructor, E, elements);
+}
 
 Set<E> constSet<E>(JSArray<E> elements) {
   var count = elements.length;
@@ -541,7 +565,7 @@
   }
   var result = JS('', '#.get(#)', map, E);
   if (result != null) return result;
-  result = ImmutableSet<E>.from(elements);
+  result = _createImmutableSet<E>(elements);
   JS('', '#.set(#, #)', map, E, result);
   return result;
 }
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart
index 5e784a4..11ea1ae 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart
@@ -117,6 +117,7 @@
 String getModuleName(Object module) => JS('', '#[#]', module, _moduleName);
 
 final _loadedModules = JS('', 'new Map()');
+final _loadedPartMaps = JS('', 'new Map()');
 final _loadedSourceMaps = JS('', 'new Map()');
 
 List<String> getModuleNames() {
@@ -135,26 +136,87 @@
   return module;
 }
 
+/// Return the part map for a specific module.
+getModulePartMap(String name) => JS('', '#.get(#)', _loadedPartMaps, name);
+
 /// Track all libraries
-void trackLibraries(String moduleName, Object libraries, String sourceMap) {
+void trackLibraries(
+    String moduleName, Object libraries, Object parts, String sourceMap) {
+  if (parts is String) {
+    // Added for backwards compatibility.
+    // package:build_web_compilers currently invokes this without [parts]
+    // in its bootstrap code.
+    sourceMap = parts as String;
+    parts = JS('', '{}');
+  }
   JS('', '#.set(#, #)', _loadedSourceMaps, moduleName, sourceMap);
   JS('', '#.set(#, #)', _loadedModules, moduleName, libraries);
+  JS('', '#.set(#, #)', _loadedPartMaps, moduleName, parts);
 }
 
 List<String> _libraries;
+Map<String, Object> _libraryObjects;
+Map<String, List<String>> _parts;
+
+_computeLibraryMetadata() {
+  _libraries = [];
+  _libraryObjects = {};
+  _parts = {};
+  var modules = getModuleNames();
+  for (var name in modules) {
+    // Add libraries from each module.
+    var module = getModuleLibraries(name);
+    var libraries = getOwnPropertyNames(module).cast<String>();
+    _libraries.addAll(libraries);
+    for (var library in libraries) {
+      _libraryObjects[library] = JS('', '#.#', module, library);
+    }
+
+    // Add parts from each module.
+    var partMap = getModulePartMap(name);
+    libraries = getOwnPropertyNames(partMap).cast<String>();
+    for (var library in libraries) {
+      _parts[library] = List.from(JS('List', '#.#', partMap, library));
+    }
+  }
+}
+
+/// Returns the JS library object for a given library [uri] or
+/// undefined / null if it isn't loaded.  Top-level types and
+/// methods are available on this object.
+Object getLibrary(String uri) {
+  if (_libraryObjects == null) {
+    _computeLibraryMetadata();
+  }
+  return _libraryObjects[uri];
+}
 
 /// Returns a JSArray of library uris (e.g,
 /// ['dart:core', 'dart:_internal', ..., 'package:foo/bar.dart', ... 'main.dart'])
 /// loaded in this application.
 List<String> getLibraries() {
   if (_libraries == null) {
-    _libraries = [];
-    var modules = getModuleNames();
-    for (var name in modules) {
-      var module = getModuleLibraries(name);
-      List props = getOwnPropertyNames(module);
-      _libraries.addAll(props.whereType());
-    }
+    _computeLibraryMetadata();
   }
   return _libraries;
 }
+
+/// Returns a JSArray of part uris for a given [libraryUri].
+/// The part uris will be relative to the [libraryUri].
+///
+/// E.g., invoking `getParts('package:intl/intl.dart')` returns (as of this
+/// writing): ```
+/// ["src/intl/bidi_formatter.dart", "src/intl/bidi_utils.dart",
+///  "src/intl/compact_number_format.dart", "src/intl/date_format.dart",
+///  "src/intl/date_format_field.dart", "src/intl/date_format_helpers.dart",
+///  "src/intl/number_format.dart"]
+/// ```
+///
+/// If [libraryUri] doesn't map to a library or maps to a library with no
+/// parts, an empty list is returned.
+List<String> getParts(String libraryUri) {
+  if (_parts == null) {
+    _computeLibraryMetadata();
+  }
+  return _parts[libraryUri] ?? [];
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart b/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart
index 95b822a..2f6750e 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart
@@ -738,10 +738,28 @@
 
 /// Error thrown by DDC when an `assert()` fails (with or without a message).
 class AssertionErrorImpl extends AssertionError {
-  AssertionErrorImpl(message) : super(message);
-  String toString() =>
-      "Assertion failed: " +
-      (message != null ? Error.safeToString(message) : "is not true");
+  final String _fileUri;
+  final int _line;
+  final int _column;
+  final String _conditionSource;
+
+  AssertionErrorImpl(Object message,
+      [this._fileUri, this._line, this._column, this._conditionSource])
+      : super(message);
+
+  String toString() {
+    var failureMessage = "";
+    if (_fileUri != null &&
+        _line != null &&
+        _column != null &&
+        _conditionSource != null) {
+      failureMessage += "$_fileUri:${_line}:${_column}\n$_conditionSource\n";
+    }
+    failureMessage +=
+        message != null ? Error.safeToString(message) : "is not true";
+
+    return "Assertion failed: $failureMessage";
+  }
 }
 
 /**
diff --git a/pkg/dev_compiler/tool/patch_sdk.dart b/pkg/dev_compiler/tool/patch_sdk.dart
index d5cb090..5b9a979 100755
--- a/pkg/dev_compiler/tool/patch_sdk.dart
+++ b/pkg/dev_compiler/tool/patch_sdk.dart
@@ -271,7 +271,7 @@
   void _maybePatch(Declaration node) {
     if (node is FieldDeclaration) return;
 
-    Token externalKeyword = (node as dynamic).externalKeyword;
+    var externalKeyword = (node as dynamic).externalKeyword as Token;
     if (externalKeyword == null) return;
 
     var name = _qualifiedName(node);
@@ -361,7 +361,7 @@
     result = "${parent.name.name}.";
   }
 
-  SimpleIdentifier name = (node as dynamic).name;
+  var name = (node as dynamic).name as SimpleIdentifier;
   if (name != null) result += name.name;
 
   // Make sure setters and getters don't collide.
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
index d0615fd..f91b17d 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
@@ -7,8 +7,11 @@
 enum ExperimentalFlag {
   constantUpdate2018,
   controlFlowCollections,
+  extensionMethods,
+  nonNullable,
   setLiterals,
   spreadCollections,
+  tripleShift,
 }
 
 ExperimentalFlag parseExperimentalFlag(String flag) {
@@ -17,10 +20,16 @@
       return ExperimentalFlag.constantUpdate2018;
     case "control-flow-collections":
       return ExperimentalFlag.controlFlowCollections;
+    case "extension-methods":
+      return ExperimentalFlag.extensionMethods;
+    case "non-nullable":
+      return ExperimentalFlag.nonNullable;
     case "set-literals":
       return ExperimentalFlag.setLiterals;
     case "spread-collections":
       return ExperimentalFlag.spreadCollections;
+    case "triple-shift":
+      return ExperimentalFlag.tripleShift;
   }
   return null;
 }
@@ -28,6 +37,9 @@
 const Map<ExperimentalFlag, bool> defaultExperimentalFlags = {
   ExperimentalFlag.constantUpdate2018: false,
   ExperimentalFlag.controlFlowCollections: true,
+  ExperimentalFlag.extensionMethods: false,
+  ExperimentalFlag.nonNullable: false,
   ExperimentalFlag.setLiterals: true,
   ExperimentalFlag.spreadCollections: true,
+  ExperimentalFlag.tripleShift: false,
 };
diff --git a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
index 3606b3d..c9969c5 100644
--- a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
@@ -11,10 +11,13 @@
 
 import 'package:kernel/target/targets.dart' show Target;
 
-import '../api_prototype/compiler_options.dart' show CompilerOptions;
+import '../api_prototype/compiler_options.dart'
+    show CompilerOptions, parseExperimentalFlags;
 
 import '../api_prototype/diagnostic_message.dart' show DiagnosticMessageHandler;
 
+import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
+
 import '../api_prototype/file_system.dart' show FileSystem;
 
 import '../base/processed_options.dart' show ProcessedOptions;
@@ -41,6 +44,8 @@
 
 export 'compiler_state.dart' show InitializedCompilerState;
 
+import 'util.dart' show equalMaps;
+
 /// Initializes the compiler for a modular build.
 ///
 /// Re-uses cached components from [_workerInputCache], and reloads them
@@ -54,6 +59,7 @@
     Map<Uri, List<int>> workerInputDigests,
     Target target,
     FileSystem fileSystem,
+    Iterable<String> experiments,
     bool outlineOnly) async {
   final List<int> sdkDigest = workerInputDigests[sdkSummary];
   if (sdkDigest == null) {
@@ -66,10 +72,13 @@
   Map<Uri, WorkerInputComponent> workerInputCache =
       oldState?.workerInputCache ?? new Map<Uri, WorkerInputComponent>();
   bool startOver = false;
+  Map<ExperimentalFlag, bool> experimentalFlags =
+      parseExperimentalFlags(experiments, (e) => throw e);
 
   if (oldState == null ||
       oldState.incrementalCompiler == null ||
-      oldState.incrementalCompiler.outlineOnly != outlineOnly) {
+      oldState.incrementalCompiler.outlineOnly != outlineOnly ||
+      !equalMaps(oldState.options.experimentalFlags, experimentalFlags)) {
     // No - or immediately not correct - previous state.
     startOver = true;
 
@@ -115,7 +124,17 @@
     for (var lib in sdkComponent.libraries) {
       lib.isExternal = cachedSdkInput.externalLibs.contains(lib.importUri);
     }
+
+    // Make sure the canonical name root knows about the sdk - otherwise we
+    // won't be able to link to it when loading more outlines.
     sdkComponent.adoptChildren();
+
+    // TODO(jensj): This is - at least currently - neccessary,
+    // although it's not entirely obvious why.
+    // It likely has to do with several outlines containing the same libraries.
+    // Once that stops (and we check for it) we can probably remove this,
+    // and instead only do it when about to reuse an outline in the
+    // 'inputSummaries.add(component);' line further down.
     for (WorkerInputComponent cachedInput in workerInputCache.values) {
       cachedInput.component.adoptChildren();
     }
@@ -148,8 +167,6 @@
       for (var lib in component.libraries) {
         lib.isExternal = cachedInput.externalLibs.contains(lib.importUri);
       }
-      component.adoptChildren();
-      component.computeCanonicalNames();
       inputSummaries.add(component);
     }
   }
@@ -184,7 +201,8 @@
     List<Uri> summaryInputs,
     List<Uri> linkedInputs,
     Target target,
-    FileSystem fileSystem) async {
+    FileSystem fileSystem,
+    Iterable<String> experiments) async {
   // TODO(sigmund): use incremental compiler when it supports our use case.
   // Note: it is common for the summary worker to invoke the compiler with the
   // same input summary URIs, but with different contents, so we'd need to be
@@ -198,7 +216,8 @@
     ..linkedDependencies = linkedInputs
     ..target = target
     ..fileSystem = fileSystem
-    ..environmentDefines = const {};
+    ..environmentDefines = const {}
+    ..experimentalFlags = parseExperimentalFlags(experiments, (e) => throw e);
 
   ProcessedOptions processedOpts = new ProcessedOptions(options: options);
 
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index 8ec174d..e6f8ac6 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -32,6 +32,8 @@
 
 import 'compiler_state.dart' show InitializedCompilerState;
 
+import 'util.dart' show equalLists, equalMaps;
+
 export '../api_prototype/compiler_options.dart'
     show CompilerOptions, parseExperimentalFlags;
 
@@ -116,30 +118,13 @@
     Map<ExperimentalFlag, bool> experimentalFlags,
     bool verify: false,
     bool enableAsserts: false}) {
-  bool mapEqual(Map<ExperimentalFlag, bool> a, Map<ExperimentalFlag, bool> b) {
-    if (a == null || b == null) return a == b;
-    if (a.length != b.length) return false;
-    for (var flag in a.keys) {
-      if (!b.containsKey(flag) || a[flag] != b[flag]) return false;
-    }
-    return true;
-  }
-
-  bool listEqual(List<Uri> a, List<Uri> b) {
-    if (a.length != b.length) return false;
-    for (int i = 0; i < a.length; ++i) {
-      if (a[i] != b[i]) return false;
-    }
-    return true;
-  }
-
   linkedDependencies.sort((a, b) => a.toString().compareTo(b.toString()));
 
   if (oldState != null &&
       oldState.options.packagesFileUri == packagesFileUri &&
       oldState.options.librariesSpecificationUri == librariesSpecificationUri &&
-      listEqual(oldState.options.linkedDependencies, linkedDependencies) &&
-      mapEqual(oldState.options.experimentalFlags, experimentalFlags)) {
+      equalLists(oldState.options.linkedDependencies, linkedDependencies) &&
+      equalMaps(oldState.options.experimentalFlags, experimentalFlags)) {
     return oldState;
   }
 
diff --git a/pkg/front_end/lib/src/api_unstable/ddc.dart b/pkg/front_end/lib/src/api_unstable/ddc.dart
index 3230a6b..852cd60 100644
--- a/pkg/front_end/lib/src/api_unstable/ddc.dart
+++ b/pkg/front_end/lib/src/api_unstable/ddc.dart
@@ -29,6 +29,8 @@
 import 'compiler_state.dart'
     show InitializedCompilerState, WorkerInputComponent, digestsEqual;
 
+import 'util.dart' show equalLists, equalMaps;
+
 export '../api_prototype/compiler_options.dart' show CompilerOptions;
 
 export '../api_prototype/diagnostic_message.dart' show DiagnosticMessage;
@@ -79,29 +81,13 @@
     {FileSystem fileSystem,
     Map<ExperimentalFlag, bool> experiments}) async {
   inputSummaries.sort((a, b) => a.toString().compareTo(b.toString()));
-  bool listEqual(List<Uri> a, List<Uri> b) {
-    if (a.length != b.length) return false;
-    for (int i = 0; i < a.length; ++i) {
-      if (a[i] != b[i]) return false;
-    }
-    return true;
-  }
-
-  bool mapEqual(Map<ExperimentalFlag, bool> a, Map<ExperimentalFlag, bool> b) {
-    if (a == null || b == null) return a == b;
-    if (a.length != b.length) return false;
-    for (var flag in a.keys) {
-      if (!b.containsKey(flag) || a[flag] != b[flag]) return false;
-    }
-    return true;
-  }
 
   if (oldState != null &&
       oldState.options.sdkSummary == sdkSummary &&
       oldState.options.packagesFileUri == packagesFile &&
       oldState.options.librariesSpecificationUri == librariesSpecificationUri &&
-      listEqual(oldState.options.inputSummaries, inputSummaries) &&
-      mapEqual(oldState.options.experimentalFlags, experiments)) {
+      equalLists(oldState.options.inputSummaries, inputSummaries) &&
+      equalMaps(oldState.options.experimentalFlags, experiments)) {
     // Reuse old state.
 
     // These libraries are marked external when compiling. If not un-marking
diff --git a/pkg/front_end/lib/src/api_unstable/util.dart b/pkg/front_end/lib/src/api_unstable/util.dart
new file mode 100644
index 0000000..146ddd0
--- /dev/null
+++ b/pkg/front_end/lib/src/api_unstable/util.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, 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.
+
+bool equalLists<T>(List<T> a, List<T> b) {
+  if (identical(a, b)) return true;
+  if (a == null || b == null) return false;
+  if (a.length != b.length) return false;
+  for (int i = 0; i < a.length; ++i) {
+    if (a[i] != b[i]) return false;
+  }
+  return true;
+}
+
+bool equalMaps<K, V>(Map<K, V> a, Map<K, V> b) {
+  if (identical(a, b)) return true;
+  if (a == null || b == null) return false;
+  if (a.length != b.length) return false;
+  for (K key in a.keys) {
+    if (!b.containsKey(key) || a[key] != b[key]) return false;
+  }
+  return true;
+}
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 3746481..a3e6cbe 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -316,7 +316,6 @@
     assert(defaultExperimentalFlags.containsKey(flag),
         "No default value for $flag.");
     // TODO(askesc): Determine default flag value from specification file.
-    if (flag == ExperimentalFlag.setLiterals) return true;
     return _raw.experimentalFlags[flag] ?? defaultExperimentalFlags[flag];
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 05441e7..0ef4745 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -77,6 +77,8 @@
     return library.partOfLibrary ?? library;
   }
 
+  void buildAnnotations(LibraryBuilder library) {}
+
   /// Registers a constructor redirection for this class and returns true if
   /// this redirection gives rise to a cycle that has not been reported before.
   bool checkConstructorCyclic(String source, String target) {
@@ -124,7 +126,7 @@
     return constructors.lookup(name, charOffset, uri);
   }
 
-  void forEach(void f(String name, MemberBuilder builder)) {
+  void forEach(void f(String name, Declaration builder)) {
     scope.forEach(f);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
index f456149..33f875f 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
@@ -12,7 +12,7 @@
 }
 
 class EnumConstantInfo {
-  final List<MetadataBuilder<TypeBuilder>> metadata;
+  final List<MetadataBuilder> metadata;
   final String name;
   final int charOffset;
   final String documentationComment;
diff --git a/pkg/front_end/lib/src/fasta/builder/library_builder.dart b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
index 9dbca65..ed544d6 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -235,6 +235,8 @@
   }
 
   void recordAccess(int charOffset, int length, Uri fileUri) {}
+
+  void buildAnnotations() {}
 }
 
 class LibraryLocalDeclarationIterator implements Iterator<Declaration> {
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index 827fe5f..2dd5099 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -37,6 +37,8 @@
     }
   }
 
+  void buildAnnotations(LibraryBuilder library) {}
+
   @override
   String get fullNameForErrors => name;
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart b/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
index cb656b4..f43b4a6 100644
--- a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
@@ -4,54 +4,6 @@
 
 library fasta.metadata_builder;
 
-import 'builder.dart' show Declaration, TypeBuilder;
-
-import 'constructor_reference_builder.dart' show ConstructorReferenceBuilder;
-
-abstract class MetadataBuilder<T extends TypeBuilder> {
-  final int charOffset;
-
-  MetadataBuilder(Declaration parent, this.charOffset);
-
-  factory MetadataBuilder.fromConstructor(
-      ConstructorReferenceBuilder constructorReference,
-      List<Object> arguments,
-      Declaration parent,
-      int charOffset) {
-    return new ConstructorMetadataBuilder<T>(
-        constructorReference, arguments, parent, charOffset);
-  }
-
-  factory MetadataBuilder.fromExpression(
-      Object expression, String postfix, Declaration parent, int charOffset) {
-    return new ExpressionMetadataBuilder<T>(
-        expression, postfix, parent, charOffset);
-  }
-}
-
-class ConstructorMetadataBuilder<T extends TypeBuilder>
-    extends MetadataBuilder<T> {
-  final ConstructorReferenceBuilder constructorReference;
-
-  final List<Object> arguments;
-
-  ConstructorMetadataBuilder(this.constructorReference, this.arguments,
-      Declaration parent, int charOffset)
-      : super(parent, charOffset);
-}
-
-/// Expression metadata (without arguments).
-///
-/// Matches this grammar rule:
-///
-///    '@' qualified (‘.’ identifier)?
-class ExpressionMetadataBuilder<T extends TypeBuilder>
-    extends MetadataBuilder<T> {
-  final Object qualified;
-
-  final String identifier;
-
-  ExpressionMetadataBuilder(
-      this.qualified, this.identifier, Declaration parent, int charOffset)
-      : super(parent, charOffset);
+abstract class MetadataBuilder {
+  int get charOffset;
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
index e941212..c2e5255 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
@@ -19,7 +19,7 @@
   final List<TypeVariableBuilder<T, R>> typeVariables;
 
   TypeAliasBuilder(
-      List<MetadataBuilder<T>> metadata,
+      List<MetadataBuilder> metadata,
       String name,
       this.typeVariables,
       this.type,
diff --git a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
index b28cf9f..32a5a31 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
@@ -14,7 +14,7 @@
 
 abstract class TypeDeclarationBuilder<T extends TypeBuilder, R>
     extends ModifierBuilder {
-  final List<MetadataBuilder<T>> metadata;
+  final List<MetadataBuilder> metadata;
 
   final int modifiers;
 
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
index 6667e06..8247cbf 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
@@ -23,7 +23,7 @@
       : super(null, typedef.name, null, null, parent, typedef.fileOffset,
             typedef);
 
-  List<MetadataBuilder<KernelTypeBuilder>> get metadata {
+  List<MetadataBuilder> get metadata {
     return unimplemented("metadata", -1, null);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 991c13b..e61cf1c 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -233,16 +233,6 @@
     message: r"""`assert` can't have more than two arguments.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeAsyncAsIdentifier = messageAsyncAsIdentifier;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageAsyncAsIdentifier = const MessageCode(
-    "AsyncAsIdentifier",
-    analyzerCodes: <String>["ASYNC_KEYWORD_USED_AS_IDENTIFIER"],
-    message:
-        r"""'async' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeAwaitAsIdentifier = messageAwaitAsIdentifier;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -273,6 +263,34 @@
     message: r"""'await' can only be used in 'async' or 'async*' methods.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, String name2)>
+    templateBadTypeVariableInSupertype =
+    const Template<Message Function(String name, String name2)>(
+        messageTemplate:
+            r"""Found unsupported uses of '#name' in supertype '#name2'.""",
+        withArguments: _withArgumentsBadTypeVariableInSupertype);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2)>
+    codeBadTypeVariableInSupertype =
+    const Code<Message Function(String name, String name2)>(
+  "BadTypeVariableInSupertype",
+  templateBadTypeVariableInSupertype,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsBadTypeVariableInSupertype(String name, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeBadTypeVariableInSupertype,
+      message:
+          """Found unsupported uses of '${name}' in supertype '${name2}'.""",
+      arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
         String name,
@@ -1925,17 +1943,6 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCovariantAfterVar = messageCovariantAfterVar;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCovariantAfterVar = const MessageCode(
-    "CovariantAfterVar",
-    index: 8,
-    message:
-        r"""The modifier 'covariant' should be before the modifier 'var'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeCovariantAndStatic = messageCovariantAndStatic;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2924,27 +2931,6 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateExpectedClassBodyToSkip =
-    const Template<Message Function(Token token)>(
-        messageTemplate:
-            r"""Expected a class or mixin body, but got '#lexeme'.""",
-        withArguments: _withArgumentsExpectedClassBodyToSkip);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Token token)> codeExpectedClassBodyToSkip =
-    const Code<Message Function(Token token)>(
-        "ExpectedClassBodyToSkip", templateExpectedClassBodyToSkip,
-        analyzerCodes: <String>["MISSING_CLASS_BODY"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedClassBodyToSkip(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeExpectedClassBodyToSkip,
-      message: """Expected a class or mixin body, but got '${lexeme}'.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(Token token)> templateExpectedClassMember =
     const Template<Message Function(Token token)>(
         messageTemplate: r"""Expected a class member, but got '#lexeme'.""",
@@ -2965,24 +2951,27 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateExpectedClassOrMixinBody =
-    const Template<Message Function(Token token)>(
+const Template<Message Function(String string)>
+    templateExpectedClassOrMixinBody =
+    const Template<Message Function(String string)>(
         messageTemplate:
-            r"""Expected a class or mixin body, but got '#lexeme'.""",
+            r"""A #string must have a body, even if it is empty.""",
+        tipTemplate: r"""Try adding an empty body.""",
         withArguments: _withArgumentsExpectedClassOrMixinBody);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Token token)> codeExpectedClassOrMixinBody =
-    const Code<Message Function(Token token)>(
+const Code<Message Function(String string)> codeExpectedClassOrMixinBody =
+    const Code<Message Function(String string)>(
         "ExpectedClassOrMixinBody", templateExpectedClassOrMixinBody,
-        analyzerCodes: <String>["MISSING_CLASS_BODY"]);
+        index: 8);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedClassOrMixinBody(Token token) {
-  String lexeme = token.lexeme;
+Message _withArgumentsExpectedClassOrMixinBody(String string) {
+  if (string.isEmpty) throw 'No string provided';
   return new Message(codeExpectedClassOrMixinBody,
-      message: """Expected a class or mixin body, but got '${lexeme}'.""",
-      arguments: {'token': token});
+      message: """A ${string} must have a body, even if it is empty.""",
+      tip: """Try adding an empty body.""",
+      arguments: {'string': string});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3011,7 +3000,7 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageExpectedElseOrComma = const MessageCode(
     "ExpectedElseOrComma",
-    index: 94,
+    index: 46,
     message: r"""Expected 'else' or comma.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3224,7 +3213,7 @@
 const Code<Message Function(String string)> codeExperimentNotEnabled =
     const Code<Message Function(String string)>(
         "ExperimentNotEnabled", templateExperimentNotEnabled,
-        index: 93);
+        index: 48);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsExperimentNotEnabled(String string) {
@@ -3327,39 +3316,6 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalAfterConst = messageExternalAfterConst;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalAfterConst = const MessageCode(
-    "ExternalAfterConst",
-    index: 46,
-    message:
-        r"""The modifier 'external' should be before the modifier 'const'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalAfterFactory = messageExternalAfterFactory;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalAfterFactory = const MessageCode(
-    "ExternalAfterFactory",
-    index: 47,
-    message:
-        r"""The modifier 'external' should be before the modifier 'factory'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalAfterStatic = messageExternalAfterStatic;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalAfterStatic = const MessageCode(
-    "ExternalAfterStatic",
-    index: 48,
-    message:
-        r"""The modifier 'external' should be before the modifier 'static'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeExternalClass = messageExternalClass;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6315,7 +6271,7 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageInvalidSuperInInitializer = const MessageCode(
     "InvalidSuperInInitializer",
-    index: 95,
+    index: 47,
     message:
         r"""Can only use 'super' in an initializer for calling the superclass constructor (e.g. 'super()' or 'super.namedConstructor()')""");
 
@@ -7388,7 +7344,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageOnlyTry = const MessageCode("OnlyTry",
-    index: 92,
+    index: 20,
     message:
         r"""A try block must be followed by an 'on', 'catch', or 'finally' clause.""",
     tip:
@@ -8739,42 +8695,11 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageStackOverflow = const MessageCode("StackOverflow",
-    index: 91,
+    index: 19,
     message: r"""The file has too many nested expressions or statements.""",
     tip: r"""Try simplifying the code.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeStaticAfterConst = messageStaticAfterConst;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageStaticAfterConst = const MessageCode(
-    "StaticAfterConst",
-    index: 20,
-    message:
-        r"""The modifier 'static' should be before the modifier 'const'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeStaticAfterFinal = messageStaticAfterFinal;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageStaticAfterFinal = const MessageCode(
-    "StaticAfterFinal",
-    index: 19,
-    message:
-        r"""The modifier 'static' should be before the modifier 'final'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeStaticAfterVar = messageStaticAfterVar;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageStaticAfterVar = const MessageCode("StaticAfterVar",
-    index: 18,
-    message: r"""The modifier 'static' should be before the modifier 'var'.""",
-    tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeStaticAndInstanceConflict =
     messageStaticAndInstanceConflict;
 
@@ -8847,7 +8772,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageSuperNullAware = const MessageCode("SuperNullAware",
-    index: 90,
+    index: 18,
     message:
         r"""The operator '?.' cannot be used with 'super' because 'super' cannot be null.""",
     tip: r"""Try replacing '?.' with '.'""");
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 52264f2..16d1187 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -96,6 +96,8 @@
   final Component componentToInitializeFrom;
   bool initializedFromDill = false;
   Uri previousPackagesUri;
+  Map<String, Uri> previousPackagesMap;
+  Map<String, Uri> currentPackagesMap;
   bool hasToCheckPackageUris = false;
   Map<Uri, List<DiagnosticMessageFromJson>> remainingComponentProblems =
       new Map<Uri, List<DiagnosticMessageFromJson>>();
@@ -137,6 +139,8 @@
       hasToCheckPackageUris = hasToCheckPackageUris || bypassCache;
       UriTranslator uriTranslator =
           await c.options.getUriTranslator(bypassCache: bypassCache);
+      previousPackagesMap = currentPackagesMap;
+      currentPackagesMap = uriTranslator.packages.asMap();
       ticker.logMs("Read packages file");
 
       if (dillLoadedData == null) {
@@ -220,11 +224,19 @@
           notReused: notReusedLibraries);
       Set<Uri> reusedLibraryUris =
           new Set<Uri>.from(reusedLibraries.map((b) => b.uri));
+      bool removedBuilders = false;
       for (Uri uri in new Set<Uri>.from(dillLoadedData.loader.builders.keys)
         ..removeAll(reusedLibraryUris)) {
         LibraryBuilder builder = dillLoadedData.loader.builders.remove(uri);
         userBuilders?.remove(uri);
         CompilerContext.current.uriToSource.remove(builder.fileUri);
+        removedBuilders = true;
+      }
+      if (removedBuilders) {
+        dillLoadedData.loader.libraries.clear();
+        for (LibraryBuilder builder in dillLoadedData.loader.builders.values) {
+          dillLoadedData.loader.libraries.add(builder.target);
+        }
       }
 
       if (hasToCheckPackageUris) {
@@ -823,10 +835,21 @@
       if (importUri != fileUri && invalidatedUris.contains(fileUri)) {
         return true;
       }
-      if (hasToCheckPackageUris &&
-          importUri.scheme == "package" &&
-          uriTranslator.translate(importUri, false) != fileUri) {
-        return true;
+      if (hasToCheckPackageUris && importUri.scheme == "package") {
+        // Get package name, check if the base URI has changed for the package,
+        // if it has, translate the URI again,
+        // otherwise the URI cannot have changed.
+        String path = importUri.path;
+        int firstSlash = path.indexOf('/');
+        String packageName = path.substring(0, firstSlash);
+        if (previousPackagesMap == null ||
+            (previousPackagesMap[packageName] !=
+                currentPackagesMap[packageName])) {
+          Uri newFileUri = uriTranslator.translate(importUri, false);
+          if (newFileUri != fileUri) {
+            return true;
+          }
+        }
       }
       if (builders[importUri]?.isSynthetic ?? false) return true;
       return false;
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 46f4f5e..393be7d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -509,7 +509,8 @@
       }
 
       ConstantContext savedConstantContext = pop();
-      if (expression is! StaticAccessGenerator) {
+      if (expression is! StaticAccessGenerator &&
+          expression is! VariableUseGenerator) {
         push(wrapInProblem(
             toValue(expression), fasta.messageExpressionNotMetadata, noLength));
       } else {
@@ -600,25 +601,7 @@
       // `invalid-type`.
       buildDartType(pop()); // Type.
     }
-    List<Expression> annotations = pop();
-    // Fields with duplicate names are sorted out in the else branch of the
-    // `declaration.next == null` above.
-    if (annotations != null && fields.isNotEmpty) {
-      inferAnnotations(annotations);
-      Field field = fields.first.target;
-      // The first (and often only field) will not get a clone.
-      for (int i = 0; i < annotations.length; i++) {
-        field.addAnnotation(annotations[i]);
-      }
-      for (int i = 1; i < fields.length; i++) {
-        // We have to clone the annotations on the remaining fields.
-        field = fields[i].target;
-        cloner ??= new CloneVisitor();
-        for (Expression annotation in annotations) {
-          field.addAnnotation(cloner.clone(annotation));
-        }
-      }
-    }
+    pop(); // Annotations.
 
     resolveRedirectingFactoryTargets();
     finishVariableMetadata();
@@ -750,8 +733,8 @@
   }
 
   @override
-  void finishFunction(List<Expression> annotations, FormalParameters formals,
-      AsyncMarker asyncModifier, Statement body) {
+  void finishFunction(
+      FormalParameters formals, AsyncMarker asyncModifier, Statement body) {
     debugEvent("finishFunction");
     typePromoter?.finished();
 
@@ -902,11 +885,6 @@
           ..fileOffset = body.fileOffset;
       }
     }
-    Member target = builder.target;
-    inferAnnotations(annotations);
-    for (Expression annotation in annotations ?? const []) {
-      target.addAnnotation(annotation);
-    }
     if (builder is KernelConstructorBuilder) {
       finishConstructor(builder, asyncModifier);
     } else if (builder is KernelProcedureBuilder) {
@@ -1154,6 +1132,14 @@
     return expression;
   }
 
+  Expression parseAnnotation(Token token) {
+    Parser parser = new Parser(this);
+    token = parser.parseMetadata(parser.syntheticPreviousToken(token));
+    Expression annotation = pop();
+    checkEmpty(token.charOffset);
+    return annotation;
+  }
+
   void finishConstructor(
       KernelConstructorBuilder builder, AsyncMarker asyncModifier) {
     /// Quotes below are from [Dart Programming Language Specification, 4th
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index 51d5070..b015270 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -135,6 +135,7 @@
 }
 
 class ConstantsTransformer extends Transformer {
+  final ConstantsBackend backend;
   final ConstantEvaluator constantEvaluator;
   final TypeEnvironment typeEnvironment;
 
@@ -146,7 +147,7 @@
   final bool errorOnUnevaluatedConstant;
 
   ConstantsTransformer(
-      ConstantsBackend backend,
+      this.backend,
       Map<String, String> environmentDefines,
       this.keepFields,
       this.keepVariables,
@@ -300,18 +301,11 @@
       if (node.isConst) {
         final Constant constant = evaluateWithContext(node, node.initializer);
         constantEvaluator.env.addVariableValue(node, constant);
+        node.initializer = makeConstantExpression(constant, node.initializer)
+          ..parent = node;
 
-        if (keepVariables) {
-          // So the value of the variable is still available for debugging
-          // purposes we convert the constant variable to be a final variable
-          // initialized to the evaluated constant expression.
-          node.initializer = makeConstantExpression(constant, node.initializer)
-            ..parent = node;
-          node.isFinal = true;
-          node.isConst = false;
-        } else {
-          // Since we convert all use-sites of constants, the constant
-          // [VariableDeclaration] is unused and we'll therefore remove it.
+        // If this constant is inlined, remove it.
+        if (!keepVariables && shouldInline(node.initializer)) {
           return null;
         }
       } else {
@@ -324,20 +318,17 @@
   visitField(Field node) {
     return constantEvaluator.withNewEnvironment(() {
       if (node.isConst) {
-        // Since we convert all use-sites of constants, the constant [Field]
-        // cannot be referenced anymore.  We therefore get rid of it if
-        // [keepFields] was not specified.
-        if (!keepFields) {
-          return null;
-        }
-
-        // Otherwise we keep the constant [Field] and convert it's initializer.
         transformAnnotations(node.annotations, node);
         if (node.initializer != null) {
           node.initializer =
               evaluateAndTransformWithContext(node, node.initializer)
                 ..parent = node;
         }
+
+        // If this constant is inlined, remove it.
+        if (!keepFields && shouldInline(node.initializer)) {
+          return null;
+        }
       } else {
         transformAnnotations(node.annotations, node);
         if (node.initializer != null) {
@@ -357,7 +348,15 @@
   visitStaticGet(StaticGet node) {
     final Member target = node.target;
     if (target is Field && target.isConst) {
-      return evaluateAndTransformWithContext(node, node);
+      if (target.initializer != null) {
+        // Make sure the initializer is evaluated first.
+        target.initializer =
+            evaluateAndTransformWithContext(target, target.initializer)
+              ..parent = target;
+        if (shouldInline(target.initializer)) {
+          return evaluateAndTransformWithContext(node, node);
+        }
+      }
     } else if (target is Procedure && target.kind == ProcedureKind.Method) {
       return evaluateAndTransformWithContext(node, node);
     }
@@ -370,8 +369,14 @@
   }
 
   visitVariableGet(VariableGet node) {
-    if (node.variable.isConst) {
-      return evaluateAndTransformWithContext(node, node);
+    final VariableDeclaration variable = node.variable;
+    if (variable.isConst) {
+      variable.initializer =
+          evaluateAndTransformWithContext(variable, variable.initializer)
+            ..parent = variable;
+      if (shouldInline(variable.initializer)) {
+        return evaluateAndTransformWithContext(node, node);
+      }
     }
     return super.visitVariableGet(node);
   }
@@ -456,6 +461,13 @@
     return new ConstantExpression(constant, node.getStaticType(typeEnvironment))
       ..fileOffset = node.fileOffset;
   }
+
+  bool shouldInline(Expression initializer) {
+    if (initializer is ConstantExpression) {
+      return backend.shouldInlineConstant(initializer);
+    }
+    return true;
+  }
 }
 
 class ConstantEvaluator extends RecursiveVisitor<Constant> {
@@ -1591,6 +1603,7 @@
       } else {
         reportInvalid(
             node, 'No support for ${target.runtimeType} in a static-get.');
+        return null;
       }
     });
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
index 1886808..c37724b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
@@ -42,6 +42,27 @@
       : forest = const Fangorn(),
         super.forField(member, typeInferrer);
 
+  KernelBodyBuilder.forAnnotation(
+      KernelLibraryBuilder library,
+      KernelClassBuilder classBuilder,
+      ModifierBuilder member,
+      Scope scope,
+      Scope parameterScope,
+      Uri fileUri)
+      : forest = const Fangorn(),
+        super(
+            library,
+            member,
+            scope,
+            parameterScope,
+            library.loader.hierarchy,
+            library.loader.coreTypes,
+            classBuilder,
+            member?.isInstanceMember ?? false,
+            fileUri,
+            library.loader.typeInferenceEngine
+                ?.createLocalTypeInferrer(fileUri, null, library));
+
   @override
   void enterThenForTypePromotion(Expression condition) {
     typePromoter?.enterThen(condition);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
index afd74e5..0206595 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
@@ -34,6 +34,8 @@
 
 export 'kernel_library_builder.dart' show KernelLibraryBuilder;
 
+export 'kernel_metadata_builder.dart' show KernelMetadataBuilder;
+
 export 'kernel_mixin_application_builder.dart'
     show KernelMixinApplicationBuilder;
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index 6ad083c..31214d6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -105,6 +105,7 @@
         Declaration,
         KernelFunctionBuilder,
         KernelLibraryBuilder,
+        KernelMetadataBuilder,
         KernelNamedTypeBuilder,
         KernelProcedureBuilder,
         KernelRedirectingFactoryBuilder,
@@ -224,6 +225,19 @@
     }
   }
 
+  @override
+  void buildAnnotations(LibraryBuilder library) {
+    void build(String ignore, Declaration declaration) {
+      MemberBuilder member = declaration;
+      member.buildAnnotations(library);
+    }
+
+    KernelMetadataBuilder.buildAnnotations(
+        isPatch ? origin.target : cls, metadata, library, this, null, null);
+    constructors.forEach(build);
+    scope.forEach(build);
+  }
+
   void checkSupertypes(CoreTypes coreTypes) {
     // This method determines whether the class (that's being built) its super
     // class appears both in 'extends' and 'implements' clauses and whether any
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
index 904f47d..39c70c9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
@@ -23,7 +23,9 @@
         FieldBuilder,
         ImplicitFieldType,
         KernelLibraryBuilder,
+        KernelMetadataBuilder,
         KernelTypeBuilder,
+        LibraryBuilder,
         MetadataBuilder;
 
 import 'kernel_shadow_ast.dart' show ShadowField;
@@ -91,6 +93,13 @@
     return field;
   }
 
+  @override
+  void buildAnnotations(LibraryBuilder library) {
+    ClassBuilder classBuilder = isClassMember ? parent : null;
+    KernelMetadataBuilder.buildAnnotations(
+        field, metadata, library, classBuilder, this, null);
+  }
+
   Field get target => field;
 
   void prepareTopLevelInference() {
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 80db2c8..983b7c7 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
@@ -135,6 +135,7 @@
         KernelTypeAliasBuilder,
         KernelFunctionTypeBuilder,
         KernelInvalidTypeBuilder,
+        KernelMetadataBuilder,
         KernelMixinApplicationBuilder,
         KernelNamedTypeBuilder,
         KernelProcedureBuilder,
@@ -902,6 +903,12 @@
   }
 
   @override
+  void buildAnnotations() {
+    KernelMetadataBuilder.buildAnnotations(
+        library, metadata, this, null, null, null);
+  }
+
+  @override
   void buildBuilder(Declaration declaration, LibraryBuilder coreLibrary) {
     Class cls;
     Member member;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_metadata_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_metadata_builder.dart
new file mode 100644
index 0000000..7bc39e6
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_metadata_builder.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library fasta.kernel_metadata_builder;
+
+import 'package:kernel/ast.dart' show Annotatable, Class, Library;
+
+import 'kernel_body_builder.dart' show KernelBodyBuilder;
+
+import 'kernel_builder.dart'
+    show
+        KernelClassBuilder,
+        KernelLibraryBuilder,
+        MetadataBuilder,
+        MemberBuilder;
+
+import '../scanner.dart' show Token;
+
+import '../scope.dart' show Scope;
+
+class KernelMetadataBuilder extends MetadataBuilder {
+  final Token beginToken;
+
+  int get charOffset => beginToken.charOffset;
+
+  KernelMetadataBuilder(this.beginToken);
+
+  static void buildAnnotations(
+      Annotatable parent,
+      List<MetadataBuilder> metadata,
+      KernelLibraryBuilder library,
+      KernelClassBuilder classBuilder,
+      MemberBuilder member,
+      Scope parameterScope) {
+    if (metadata == null) return;
+    Uri fileUri = member?.fileUri ?? classBuilder?.fileUri ?? library.fileUri;
+    Scope scope = parent is Library || parent is Class || classBuilder == null
+        ? library.scope
+        : classBuilder.scope;
+    KernelBodyBuilder bodyBuilder = new KernelBodyBuilder.forAnnotation(
+        library, classBuilder, member, scope, parameterScope, fileUri);
+    for (int i = 0; i < metadata.length; ++i) {
+      KernelMetadataBuilder annotationBuilder = metadata[i];
+      parent.addAnnotation(
+          bodyBuilder.parseAnnotation(annotationBuilder.beginToken));
+    }
+    bodyBuilder.inferAnnotations(parent.annotations);
+    bodyBuilder.resolveRedirectingFactoryTargets();
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
index 2434d09..c8d217b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
@@ -65,6 +65,7 @@
         FormalParameterBuilder,
         KernelFormalParameterBuilder,
         KernelLibraryBuilder,
+        KernelMetadataBuilder,
         KernelTypeBuilder,
         KernelTypeVariableBuilder,
         LibraryBuilder,
@@ -361,6 +362,18 @@
     return procedure;
   }
 
+  @override
+  void buildAnnotations(LibraryBuilder library) {
+    ClassBuilder classBuilder = isClassMember ? parent : null;
+    KernelMetadataBuilder.buildAnnotations(
+        target,
+        metadata,
+        library,
+        classBuilder,
+        this,
+        computeFormalParameterScope(classBuilder?.scope ?? library.scope));
+  }
+
   Procedure get target => origin.procedure;
 
   @override
@@ -483,6 +496,18 @@
     return constructor;
   }
 
+  @override
+  void buildAnnotations(LibraryBuilder library) {
+    ClassBuilder classBuilder = isClassMember ? parent : null;
+    KernelMetadataBuilder.buildAnnotations(
+        target,
+        metadata,
+        library,
+        classBuilder,
+        this,
+        computeFormalParameterScope(classBuilder?.scope ?? library.scope));
+  }
+
   FunctionNode buildFunction(LibraryBuilder library) {
     // According to the specification §9.3 the return type of a constructor
     // function is its enclosing class.
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 49d0344..83e30e9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -279,6 +279,7 @@
       loader.checkRedirectingFactories(myClasses);
       loader.addNoSuchMethodForwarders(myClasses);
       loader.checkMixins(myClasses);
+      loader.buildAnnotations();
       installAllComponentProblems(loader.allComponentProblems);
       loader.allComponentProblems.clear();
       return component;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart
index e9c4064..f5daa9d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart
@@ -44,7 +44,7 @@
   DartType thisType;
 
   KernelTypeAliasBuilder(
-      List<MetadataBuilder<KernelTypeBuilder>> metadata,
+      List<MetadataBuilder> metadata,
       String name,
       List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables,
       KernelFunctionTypeBuilder type,
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
index d05e0d8..6c04afb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -19,6 +19,8 @@
 
 import 'package:kernel/type_algebra.dart' show containsTypeVariable;
 
+import 'package:kernel/src/bounds_checks.dart' show Variance;
+
 import 'package:kernel/util/graph.dart' show Graph, computeStrongComponents;
 
 import 'kernel_builder.dart'
@@ -31,6 +33,7 @@
         KernelFormalParameterBuilder,
         KernelFunctionTypeBuilder,
         KernelNamedTypeBuilder,
+        KernelTypeAliasBuilder,
         KernelTypeBuilder,
         KernelTypeVariableBuilder,
         NamedTypeBuilder,
@@ -51,6 +54,79 @@
         templateNonSimpleBoundViaReference,
         templateNonSimpleBoundViaVariable;
 
+export 'package:kernel/src/bounds_checks.dart' show Variance;
+
+// Computes the variance of a variable in a type.  The function can be run
+// before the types are resolved to compute variances of typedefs' type
+// variables.  For that case if the type has its declaration set to null and its
+// name matches that of the variable, it's interpreted as an occurrence of a
+// type variable.
+int computeVariance(
+    KernelTypeVariableBuilder variable, KernelTypeBuilder type) {
+  if (type is KernelNamedTypeBuilder) {
+    TypeDeclarationBuilder declaration = type.declaration;
+    if (declaration == null || declaration is KernelTypeVariableBuilder) {
+      if (type.name == variable.name) {
+        return Variance.covariant;
+      } else {
+        return Variance.unrelated;
+      }
+    } else {
+      if (declaration is KernelClassBuilder) {
+        int result = Variance.unrelated;
+        if (type.arguments != null) {
+          for (KernelTypeBuilder argument in type.arguments) {
+            result = Variance.meet(result, computeVariance(variable, argument));
+          }
+        }
+        return result;
+      } else if (declaration is KernelTypeAliasBuilder) {
+        int result = Variance.unrelated;
+        if (type.arguments != null) {
+          for (int i = 0; i < type.arguments.length; ++i) {
+            result = Variance.meet(
+                result,
+                Variance.combine(
+                    computeVariance(variable, type.arguments[i]),
+                    computeVariance(
+                        declaration.typeVariables[i], declaration.type)));
+          }
+        }
+        return result;
+      }
+    }
+  } else if (type is KernelFunctionTypeBuilder) {
+    int result = Variance.unrelated;
+    if (type.returnType != null) {
+      result =
+          Variance.meet(result, computeVariance(variable, type.returnType));
+    }
+    if (type.typeVariables != null) {
+      for (KernelTypeVariableBuilder typeVariable in type.typeVariables) {
+        // If [variable] is referenced in the bound at all, it makes the
+        // variance of [variable] in the entire type invariant.  The invocation
+        // of [computeVariance] below is made to simply figure out if [variable]
+        // occurs in the bound.
+        if (typeVariable.bound != null &&
+            computeVariance(variable, typeVariable.bound) !=
+                Variance.unrelated) {
+          result = Variance.invariant;
+        }
+      }
+    }
+    if (type.formals != null) {
+      for (KernelFormalParameterBuilder formal in type.formals) {
+        result = Variance.meet(
+            result,
+            Variance.combine(Variance.contravariant,
+                computeVariance(variable, formal.type)));
+      }
+    }
+    return result;
+  }
+  return Variance.unrelated;
+}
+
 KernelTypeBuilder substituteRange(
     KernelTypeBuilder type,
     Map<TypeVariableBuilder, KernelTypeBuilder> upperSubstitution,
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 bb60229..c596a7e 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -13,6 +13,11 @@
   ForwardingListener([this.listener]);
 
   @override
+  set suppressParseErrors(bool value) {
+    listener?.suppressParseErrors = value;
+  }
+
+  @override
   Uri get uri => listener?.uri;
 
   @override
@@ -61,13 +66,13 @@
   }
 
   @override
-  void beginClassOrMixinBody(Token token) {
-    listener?.beginClassOrMixinBody(token);
+  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
+    listener?.beginClassDeclaration(begin, abstractToken, name);
   }
 
   @override
-  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
-    listener?.beginClassDeclaration(begin, abstractToken, name);
+  void beginClassOrMixinBody(Token token) {
+    listener?.beginClassOrMixinBody(token);
   }
 
   @override
@@ -86,6 +91,11 @@
   }
 
   @override
+  void beginConditionalExpression(Token question) {
+    listener?.beginConditionalExpression(question);
+  }
+
+  @override
   void beginConditionalUri(Token ifKeyword) {
     listener?.beginConditionalUri(ifKeyword);
   }
@@ -136,6 +146,11 @@
   }
 
   @override
+  void beginExtensionDeclaration(Token extensionKeyword, Token name) {
+    listener?.beginExtensionDeclaration(extensionKeyword, name);
+  }
+
+  @override
   void beginFactoryMethod(
       Token lastConsumed, Token externalToken, Token constToken) {
     listener?.beginFactoryMethod(lastConsumed, externalToken, constToken);
@@ -162,16 +177,6 @@
   }
 
   @override
-  void beginForStatement(Token token) {
-    listener?.beginForStatement(token);
-  }
-
-  @override
-  void beginForStatementBody(Token token) {
-    listener?.beginForStatementBody(token);
-  }
-
-  @override
   void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
       Token covariantToken, Token varFinalOrConst) {
     listener?.beginFormalParameter(
@@ -179,13 +184,23 @@
   }
 
   @override
+  void beginFormalParameterDefaultValueExpression() {
+    listener?.beginFormalParameterDefaultValueExpression();
+  }
+
+  @override
   void beginFormalParameters(Token token, MemberKind kind) {
     listener?.beginFormalParameters(token, kind);
   }
 
   @override
-  void beginLocalFunctionDeclaration(Token token) {
-    listener?.beginLocalFunctionDeclaration(token);
+  void beginForStatement(Token token) {
+    listener?.beginForStatement(token);
+  }
+
+  @override
+  void beginForStatementBody(Token token) {
+    listener?.beginForStatementBody(token);
   }
 
   @override
@@ -224,13 +239,13 @@
   }
 
   @override
-  void beginThenControlFlow(Token token) {
-    listener?.beginThenControlFlow(token);
+  void beginIfStatement(Token token) {
+    listener?.beginIfStatement(token);
   }
 
   @override
-  void beginIfStatement(Token token) {
-    listener?.beginIfStatement(token);
+  void beginImplicitCreationExpression(Token token) {
+    listener?.beginImplicitCreationExpression(token);
   }
 
   @override
@@ -274,6 +289,11 @@
   }
 
   @override
+  void beginLocalFunctionDeclaration(Token token) {
+    listener?.beginLocalFunctionDeclaration(token);
+  }
+
+  @override
   void beginMember() {
     listener?.beginMember();
   }
@@ -367,6 +387,11 @@
   }
 
   @override
+  void beginThenControlFlow(Token token) {
+    listener?.beginThenControlFlow(token);
+  }
+
+  @override
   void beginThenStatement(Token token) {
     listener?.beginThenStatement(token);
   }
@@ -485,13 +510,13 @@
   }
 
   @override
-  void endClassOrMixinBody(int memberCount, Token beginToken, Token endToken) {
-    listener?.endClassOrMixinBody(memberCount, beginToken, endToken);
+  void endClassDeclaration(Token beginToken, Token endToken) {
+    listener?.endClassDeclaration(beginToken, endToken);
   }
 
   @override
-  void endClassDeclaration(Token beginToken, Token endToken) {
-    listener?.endClassDeclaration(beginToken, endToken);
+  void endClassOrMixinBody(int memberCount, Token beginToken, Token endToken) {
+    listener?.endClassOrMixinBody(memberCount, beginToken, endToken);
   }
 
   @override
@@ -505,6 +530,11 @@
   }
 
   @override
+  void endConditionalExpression(Token question, Token colon) {
+    listener?.endConditionalExpression(question, colon);
+  }
+
+  @override
   void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
     listener?.endConditionalUri(ifKeyword, leftParen, equalSign);
   }
@@ -557,6 +587,11 @@
   }
 
   @override
+  void endExtensionDeclaration(Token onKeyword, Token token) {
+    listener?.endExtensionDeclaration(onKeyword, token);
+  }
+
+  @override
   void endFactoryMethod(
       Token beginToken, Token factoryKeyword, Token endToken) {
     listener?.endFactoryMethod(beginToken, factoryKeyword, endToken);
@@ -580,11 +615,6 @@
   }
 
   @override
-  void endForInControlFlow(Token token) {
-    listener?.endForInControlFlow(token);
-  }
-
-  @override
   void endForIn(Token endToken) {
     listener?.endForIn(endToken);
   }
@@ -595,21 +625,16 @@
   }
 
   @override
+  void endForInControlFlow(Token token) {
+    listener?.endForInControlFlow(token);
+  }
+
+  @override
   void endForInExpression(Token token) {
     listener?.endForInExpression(token);
   }
 
   @override
-  void endForStatement(Token endToken) {
-    listener?.endForStatement(endToken);
-  }
-
-  @override
-  void endForStatementBody(Token token) {
-    listener?.endForStatementBody(token);
-  }
-
-  @override
   void endFormalParameter(Token thisKeyword, Token periodAfterThis,
       Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
     listener?.endFormalParameter(
@@ -617,14 +642,24 @@
   }
 
   @override
+  void endFormalParameterDefaultValueExpression() {
+    listener?.endFormalParameterDefaultValueExpression();
+  }
+
+  @override
   void endFormalParameters(
       int count, Token beginToken, Token endToken, MemberKind kind) {
     listener?.endFormalParameters(count, beginToken, endToken, kind);
   }
 
   @override
-  void endLocalFunctionDeclaration(Token endToken) {
-    listener?.endLocalFunctionDeclaration(endToken);
+  void endForStatement(Token endToken) {
+    listener?.endForStatement(endToken);
+  }
+
+  @override
+  void endForStatementBody(Token token) {
+    listener?.endForStatementBody(token);
   }
 
   @override
@@ -674,6 +709,11 @@
   }
 
   @override
+  void endImplicitCreationExpression(Token token) {
+    listener?.endImplicitCreationExpression(token);
+  }
+
+  @override
   void endImport(Token importKeyword, Token semicolon) {
     listener?.endImport(importKeyword, semicolon);
   }
@@ -704,25 +744,6 @@
   }
 
   @override
-  void handleLiteralMapEntry(Token colon, Token endToken) {
-    listener?.handleLiteralMapEntry(colon, endToken);
-  }
-
-  @override
-  void handleLiteralSetOrMap(
-    int count,
-    Token leftBrace,
-    Token constKeyword,
-    Token rightBrace,
-    // TODO(danrubel): hasSetEntry parameter exists for replicating existing
-    // behavior and will be removed once unified collection has been enabled
-    bool hasSetEntry,
-  ) {
-    listener?.handleLiteralSetOrMap(
-        count, leftBrace, constKeyword, rightBrace, hasSetEntry);
-  }
-
-  @override
   void endLiteralString(int interpolationCount, Token endToken) {
     listener?.endLiteralString(interpolationCount, endToken);
   }
@@ -733,6 +754,11 @@
   }
 
   @override
+  void endLocalFunctionDeclaration(Token endToken) {
+    listener?.endLocalFunctionDeclaration(endToken);
+  }
+
+  @override
   void endMember() {
     listener?.endMember();
   }
@@ -983,21 +1009,11 @@
   }
 
   @override
-  void beginConditionalExpression(Token question) {
-    listener?.beginConditionalExpression(question);
-  }
-
-  @override
   void handleConditionalExpressionColon() {
     listener?.handleConditionalExpressionColon();
   }
 
   @override
-  void endConditionalExpression(Token question, Token colon) {
-    listener?.endConditionalExpression(question, colon);
-  }
-
-  @override
   void handleContinueStatement(
       bool hasTarget, Token continueKeyword, Token endToken) {
     listener?.handleContinueStatement(hasTarget, continueKeyword, endToken);
@@ -1014,28 +1030,18 @@
   }
 
   @override
-  void beginImplicitCreationExpression(Token token) {
-    listener?.beginImplicitCreationExpression(token);
-  }
-
-  @override
-  void endImplicitCreationExpression(Token token) {
-    listener?.endImplicitCreationExpression(token);
-  }
-
-  @override
   void handleElseControlFlow(Token elseToken) {
     listener?.handleElseControlFlow(elseToken);
   }
 
   @override
-  void handleEmptyStatement(Token token) {
-    listener?.handleEmptyStatement(token);
+  void handleEmptyFunctionBody(Token semicolon) {
+    listener?.handleEmptyFunctionBody(semicolon);
   }
 
   @override
-  void handleEmptyFunctionBody(Token semicolon) {
-    listener?.handleEmptyFunctionBody(semicolon);
+  void handleEmptyStatement(Token token) {
+    listener?.handleEmptyStatement(token);
   }
 
   @override
@@ -1064,6 +1070,35 @@
   }
 
   @override
+  void handleForInitializerEmptyStatement(Token token) {
+    listener?.handleForInitializerEmptyStatement(token);
+  }
+
+  @override
+  void handleForInitializerExpressionStatement(Token token) {
+    listener?.handleForInitializerExpressionStatement(token);
+  }
+
+  @override
+  void handleForInitializerLocalVariableDeclaration(Token token) {
+    listener?.handleForInitializerLocalVariableDeclaration(token);
+  }
+
+  @override
+  void handleForInLoopParts(Token awaitToken, Token forToken,
+      Token leftParenthesis, Token inKeyword) {
+    listener?.handleForInLoopParts(
+        awaitToken, forToken, leftParenthesis, inKeyword);
+  }
+
+  @override
+  void handleForLoopParts(Token forKeyword, Token leftParen,
+      Token leftSeparator, int updateExpressionCount) {
+    listener?.handleForLoopParts(
+        forKeyword, leftParen, leftSeparator, updateExpressionCount);
+  }
+
+  @override
   void handleFormalParameterWithoutValue(Token token) {
     listener?.handleFormalParameterWithoutValue(token);
   }
@@ -1084,8 +1119,8 @@
   }
 
   @override
-  void handleRecoverImport(Token semicolon) {
-    listener?.handleRecoverImport(semicolon);
+  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+    listener?.handleImportPrefix(deferredKeyword, asKeyword);
   }
 
   @override
@@ -1120,13 +1155,8 @@
   }
 
   @override
-  void handleInvalidTypeArguments(Token token) {
-    listener?.handleInvalidTypeArguments(token);
-  }
-
-  @override
-  void handleInvalidTypeReference(Token token) {
-    listener?.handleInvalidTypeReference(token);
+  void handleInvalidStatement(Token token, Message message) {
+    listener?.handleInvalidStatement(token, message);
   }
 
   void handleInvalidTopLevelBlock(Token token) {
@@ -1139,6 +1169,16 @@
   }
 
   @override
+  void handleInvalidTypeArguments(Token token) {
+    listener?.handleInvalidTypeArguments(token);
+  }
+
+  @override
+  void handleInvalidTypeReference(Token token) {
+    listener?.handleInvalidTypeReference(token);
+  }
+
+  @override
   void handleIsOperator(Token isOperator, Token not) {
     listener?.handleIsOperator(isOperator, not);
   }
@@ -1170,11 +1210,30 @@
   }
 
   @override
+  void handleLiteralMapEntry(Token colon, Token endToken) {
+    listener?.handleLiteralMapEntry(colon, endToken);
+  }
+
+  @override
   void handleLiteralNull(Token token) {
     listener?.handleLiteralNull(token);
   }
 
   @override
+  void handleLiteralSetOrMap(
+    int count,
+    Token leftBrace,
+    Token constKeyword,
+    Token rightBrace,
+    // TODO(danrubel): hasSetEntry parameter exists for replicating existing
+    // behavior and will be removed once unified collection has been enabled
+    bool hasSetEntry,
+  ) {
+    listener?.handleLiteralSetOrMap(
+        count, leftBrace, constKeyword, rightBrace, hasSetEntry);
+  }
+
+  @override
   void handleMixinHeader(Token mixinKeyword) {
     listener?.handleMixinHeader(mixinKeyword);
   }
@@ -1230,35 +1289,6 @@
   }
 
   @override
-  void handleForInitializerEmptyStatement(Token token) {
-    listener?.handleForInitializerEmptyStatement(token);
-  }
-
-  @override
-  void handleForInitializerExpressionStatement(Token token) {
-    listener?.handleForInitializerExpressionStatement(token);
-  }
-
-  @override
-  void handleForInitializerLocalVariableDeclaration(Token token) {
-    listener?.handleForInitializerLocalVariableDeclaration(token);
-  }
-
-  @override
-  void handleForInLoopParts(Token awaitToken, Token forToken,
-      Token leftParenthesis, Token inKeyword) {
-    listener?.handleForInLoopParts(
-        awaitToken, forToken, leftParenthesis, inKeyword);
-  }
-
-  @override
-  void handleForLoopParts(Token forKeyword, Token leftParen,
-      Token leftSeparator, int updateExpressionCount) {
-    listener?.handleForLoopParts(
-        forKeyword, leftParen, leftSeparator, updateExpressionCount);
-  }
-
-  @override
   void handleNoFieldInitializer(Token token) {
     listener?.handleNoFieldInitializer(token);
   }
@@ -1279,13 +1309,13 @@
   }
 
   @override
-  void handleNonNullAssertExpression(Token bang) {
-    listener?.handleNonNullAssertExpression(bang);
+  void handleNoName(Token token) {
+    listener?.handleNoName(token);
   }
 
   @override
-  void handleNoName(Token token) {
-    listener?.handleNoName(token);
+  void handleNonNullAssertExpression(Token bang) {
+    listener?.handleNonNullAssertExpression(bang);
   }
 
   @override
@@ -1329,26 +1359,11 @@
   }
 
   @override
-  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
-    listener?.handleImportPrefix(deferredKeyword, asKeyword);
-  }
-
-  @override
   void handleQualified(Token period) {
     listener?.handleQualified(period);
   }
 
   @override
-  void handleRecoverClassHeader() {
-    listener?.handleRecoverClassHeader();
-  }
-
-  @override
-  void handleRecoverMixinHeader() {
-    listener?.handleRecoverMixinHeader();
-  }
-
-  @override
   void handleRecoverableError(
       Message message, Token startToken, Token endToken) {
     if (forwardErrors) {
@@ -1357,8 +1372,18 @@
   }
 
   @override
-  void handleInvalidStatement(Token token, Message message) {
-    listener?.handleInvalidStatement(token, message);
+  void handleRecoverClassHeader() {
+    listener?.handleRecoverClassHeader();
+  }
+
+  @override
+  void handleRecoverImport(Token semicolon) {
+    listener?.handleRecoverImport(semicolon);
+  }
+
+  @override
+  void handleRecoverMixinHeader() {
+    listener?.handleRecoverMixinHeader();
   }
 
   @override
@@ -1382,12 +1407,6 @@
   }
 
   @override
-  void handleUnescapeError(
-      Message message, Token location, int offset, int length) {
-    listener?.handleUnescapeError(message, location, offset, length);
-  }
-
-  @override
   void handleStringPart(Token token) {
     listener?.handleStringPart(token);
   }
@@ -1438,13 +1457,9 @@
   }
 
   @override
-  void beginFormalParameterDefaultValueExpression() {
-    listener?.beginFormalParameterDefaultValueExpression();
-  }
-
-  @override
-  void endFormalParameterDefaultValueExpression() {
-    listener?.endFormalParameterDefaultValueExpression();
+  void handleUnescapeError(
+      Message message, Token location, int offset, int length) {
+    listener?.handleUnescapeError(message, location, offset, length);
   }
 
   @override
@@ -1468,17 +1483,12 @@
   }
 
   @override
-  void reportNonNullAssertExpressionNotEnabled(Token bang) {
-    listener?.reportNonNullAssertExpressionNotEnabled(bang);
-  }
-
-  @override
   void reportNonNullableModifierError(Token modifierToken) {
     listener?.reportNonNullableModifierError(modifierToken);
   }
 
   @override
-  set suppressParseErrors(bool value) {
-    listener?.suppressParseErrors = value;
+  void reportNonNullAssertExpressionNotEnabled(Token bang) {
+    listener?.reportNonNullAssertExpressionNotEnabled(bang);
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
index 460fec9..460dc1b 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
@@ -98,7 +98,8 @@
   /// Identifier is the name being declared by a class declaration, a mixin
   /// declaration, or a named mixin application, for example,
   /// `Foo` in `class Foo = X with Y;`.
-  static const classOrMixinDeclaration = const ClassOrMixinIdentifierContext();
+  static const classOrMixinOrExtensionDeclaration =
+      const ClassOrMixinOrExtensionIdentifierContext();
 
   /// Identifier is the name of a type variable being declared (e.g. `Foo` in
   /// `class C<Foo extends num> {}`).
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
index 0dd6638..0d0fccb 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
@@ -43,9 +43,9 @@
   }
 }
 
-/// See [IdentifierContext.classOrMixinDeclaration].
-class ClassOrMixinIdentifierContext extends IdentifierContext {
-  const ClassOrMixinIdentifierContext()
+/// See [IdentifierContext.classOrMixinOrExtensionDeclaration].
+class ClassOrMixinOrExtensionIdentifierContext extends IdentifierContext {
+  const ClassOrMixinOrExtensionIdentifierContext()
       : super('classOrMixinDeclaration',
             inDeclaration: true, isBuiltInIdentifierAllowed: false);
 
@@ -59,8 +59,8 @@
 
     // Recovery
     if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-        isOneOfOrEof(
-            identifier, const ['<', '{', 'extends', 'with', 'implements'])) {
+        isOneOfOrEof(identifier,
+            const ['<', '{', 'extends', 'with', 'implements', 'on'])) {
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: fasta.templateExpectedIdentifier.withArguments(identifier));
     } else if (identifier.type.isBuiltIn) {
@@ -940,8 +940,6 @@
       parser.reportRecoverableError(identifier, fasta.messageAwaitAsIdentifier);
     } else if (optional('yield', identifier)) {
       parser.reportRecoverableError(identifier, fasta.messageYieldAsIdentifier);
-    } else if (optional('async', identifier)) {
-      parser.reportRecoverableError(identifier, fasta.messageAsyncAsIdentifier);
     }
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index 5239ab9..0e8f57d 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -151,7 +151,7 @@
     logEvent("MixinOn");
   }
 
-  /// Handle the header of a class declaration.  Substructures:
+  /// Handle the header of a mixin declaration.  Substructures:
   /// - metadata
   /// - mixin name
   /// - type variables
@@ -179,6 +179,20 @@
     logEvent("MixinDeclaration");
   }
 
+  /// Handle the beginning of an extension methods declaration.  Substructures:
+  /// - metadata
+  /// - extension name
+  /// - type variables
+  void beginExtensionDeclaration(Token extensionKeyword, Token name) {}
+
+  /// Handle the end of an extension methods declaration.  Substructures:
+  /// - substructures from [beginExtensionDeclaration]
+  /// - on type
+  /// - body
+  void endExtensionDeclaration(Token onKeyword, Token token) {
+    logEvent('ExtensionDeclaration');
+  }
+
   void beginCombinators(Token token) {}
 
   void endCombinators(int count) {
diff --git a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
index 0c49fb1..93e717d 100644
--- a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
@@ -271,7 +271,7 @@
       covariantToken = next;
 
       if (varToken != null) {
-        parser.reportRecoverableError(next, fasta.messageCovariantAfterVar);
+        reportModifierOutOfOrder(next, varToken.lexeme);
       } else if (finalToken != null) {
         reportModifierOutOfOrder(next, finalToken.lexeme);
       } else if (lateToken != null) {
@@ -303,11 +303,11 @@
       externalToken = next;
 
       if (afterFactory) {
-        parser.reportRecoverableError(next, fasta.messageExternalAfterFactory);
+        reportModifierOutOfOrder(next, 'factory');
       } else if (constToken != null) {
-        parser.reportRecoverableError(next, fasta.messageExternalAfterConst);
+        reportModifierOutOfOrder(next, constToken.lexeme);
       } else if (staticToken != null) {
-        parser.reportRecoverableError(next, fasta.messageExternalAfterStatic);
+        reportModifierOutOfOrder(next, staticToken.lexeme);
       } else if (lateToken != null) {
         reportModifierOutOfOrder(next, lateToken.lexeme);
       }
@@ -399,11 +399,11 @@
       staticToken = next;
 
       if (constToken != null) {
-        parser.reportRecoverableError(next, fasta.messageStaticAfterConst);
+        reportModifierOutOfOrder(next, constToken.lexeme);
       } else if (finalToken != null) {
-        parser.reportRecoverableError(next, fasta.messageStaticAfterFinal);
+        reportModifierOutOfOrder(next, finalToken.lexeme);
       } else if (varToken != null) {
-        parser.reportRecoverableError(next, fasta.messageStaticAfterVar);
+        reportModifierOutOfOrder(next, varToken.lexeme);
       } else if (lateToken != null) {
         reportModifierOutOfOrder(next, lateToken.lexeme);
       }
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 6e60793..24fe512 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -500,13 +500,8 @@
       reportRecoverableError(next, fasta.messageTopLevelOperator);
       // Insert a synthetic identifier
       // and continue parsing as a top level function.
-      rewriter.insertToken(
-          next,
-          new SyntheticStringToken(
-              TokenType.IDENTIFIER,
-              '#synthetic_function_${next.charOffset}',
-              next.next.charOffset,
-              0));
+      rewriter.insertSyntheticIdentifier(
+          next, '#synthetic_function_${next.charOffset}');
       return parseTopLevelMemberImpl(next);
     }
     // Ignore any preceding modifiers and just report the unexpected token
@@ -590,23 +585,26 @@
         return parseTopLevelMemberImpl(start);
       } else {
         parseTopLevelKeywordModifiers(start, keyword);
-        if (identical(value, 'mixin')) {
-          directiveState?.checkDeclaration();
-          return parseMixin(keyword);
-        } else if (identical(value, 'typedef')) {
-          directiveState?.checkDeclaration();
-          return parseTypedef(keyword);
-        } else if (identical(value, 'library')) {
-          directiveState?.checkLibrary(this, keyword);
-          return parseLibraryName(keyword);
-        } else if (identical(value, 'import')) {
+        if (identical(value, 'import')) {
           directiveState?.checkImport(this, keyword);
           return parseImport(keyword);
         } else if (identical(value, 'export')) {
           directiveState?.checkExport(this, keyword);
           return parseExport(keyword);
+        } else if (identical(value, 'typedef')) {
+          directiveState?.checkDeclaration();
+          return parseTypedef(keyword);
+        } else if (identical(value, 'mixin')) {
+          directiveState?.checkDeclaration();
+          return parseMixin(keyword);
+        } else if (identical(value, 'extension')) {
+          directiveState?.checkDeclaration();
+          return parseExtension(keyword);
         } else if (identical(value, 'part')) {
           return parsePartOrPartOf(keyword, directiveState);
+        } else if (identical(value, 'library')) {
+          directiveState?.checkLibrary(this, keyword);
+          return parseLibraryName(keyword);
         }
       }
     }
@@ -1109,9 +1107,7 @@
       // Recovery: Report an error and insert synthetic `with` clause.
       reportRecoverableError(
           withKeyword, fasta.templateExpectedButGot.withArguments('with'));
-      withKeyword =
-          new SyntheticKeywordToken(Keyword.WITH, withKeyword.charOffset);
-      rewriter.insertToken(token, withKeyword);
+      withKeyword = rewriter.insertSyntheticKeyword(token, Keyword.WITH);
       if (!isValidTypeReference(withKeyword.next)) {
         rewriter.insertSyntheticIdentifier(withKeyword);
       }
@@ -1658,7 +1654,7 @@
 
   Token skipBlock(Token token) {
     // The scanner ensures that `{` always has a closing `}`.
-    return ensureBlock(token, null).endGroup;
+    return ensureBlock(token, null, null).endGroup;
   }
 
   /// ```
@@ -1717,7 +1713,8 @@
         }
       }
     } else {
-      leftBrace = ensureBlock(token, fasta.templateExpectedEnumBody);
+      // TODO(danrubel): merge this error message with missing class/mixin body
+      leftBrace = ensureBlock(token, fasta.templateExpectedEnumBody, null);
       token = leftBrace.endGroup;
     }
     assert(optional('}', token));
@@ -1731,7 +1728,7 @@
     Token begin = abstractToken ?? classKeyword;
     listener.beginClassOrNamedMixinApplication(begin);
     Token name = ensureIdentifier(
-        classKeyword, IdentifierContext.classOrMixinDeclaration);
+        classKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
     Token token = computeTypeParamOrArg(name, true).parseVariables(name, this);
     if (optional('=', token.next)) {
       listener.beginNamedMixinApplication(begin, abstractToken, name);
@@ -1776,7 +1773,7 @@
     if (!optional('{', token.next)) {
       // Recovery
       token = parseClassHeaderRecovery(start, begin, classKeyword);
-      ensureBlock(token, fasta.templateExpectedClassOrMixinBody);
+      ensureBlock(token, null, 'class declaration');
     }
     token = parseClassOrMixinBody(token);
     listener.endClassDeclaration(begin, token);
@@ -1934,7 +1931,7 @@
     assert(optional('mixin', mixinKeyword));
     listener.beginClassOrNamedMixinApplication(mixinKeyword);
     Token name = ensureIdentifier(
-        mixinKeyword, IdentifierContext.classOrMixinDeclaration);
+        mixinKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
     Token headerStart =
         computeTypeParamOrArg(name, true).parseVariables(name, this);
     listener.beginMixinDeclaration(mixinKeyword, name);
@@ -1942,7 +1939,7 @@
     if (!optional('{', token.next)) {
       // Recovery
       token = parseMixinHeaderRecovery(token, mixinKeyword, headerStart);
-      ensureBlock(token, fasta.templateExpectedClassOrMixinBody);
+      ensureBlock(token, null, 'mixin declaration');
     }
     token = parseClassOrMixinBody(token);
     listener.endMixinDeclaration(mixinKeyword, token);
@@ -2055,6 +2052,64 @@
     return token;
   }
 
+  /// ```
+  /// 'extension' <identifier><typeParameters>? 'on' <type> '?'?
+  //   `{'
+  //     <memberDeclaration>*
+  //   `}'
+  /// ```
+  Token parseExtension(Token extensionKeyword) {
+    assert(optional('extension', extensionKeyword));
+    Token name = ensureIdentifier(
+        extensionKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
+    Token token = computeTypeParamOrArg(name, true).parseVariables(name, this);
+    listener.beginExtensionDeclaration(extensionKeyword, name);
+    Token onKeyword = token.next;
+    if (!optional('on', onKeyword)) {
+      // Recovery
+      if (optional('extends', onKeyword) ||
+          optional('implements', onKeyword) ||
+          optional('with', onKeyword)) {
+        reportRecoverableError(
+            onKeyword, fasta.templateExpectedInstead.withArguments('on'));
+      } else {
+        reportRecoverableError(
+            token, fasta.templateExpectedAfterButGot.withArguments('on'));
+        onKeyword = rewriter.insertSyntheticKeyword(token, Keyword.ON);
+      }
+    }
+    TypeInfo typeInfo = computeType(onKeyword, true);
+    token = typeInfo.ensureTypeNotVoid(onKeyword, this);
+    if (!optional('{', token.next)) {
+      // Recovery
+      Token next = token.next;
+      while (!next.isEof) {
+        if (optional(',', next) ||
+            optional('extends', next) ||
+            optional('implements', next) ||
+            optional('on', next) ||
+            optional('with', next)) {
+          // Report an error and skip `,` or specific keyword
+          // optionally followed by an identifier
+          reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
+          token = next;
+          next = token.next;
+          if (next.isIdentifier) {
+            token = next;
+            next = token.next;
+          }
+        } else {
+          break;
+        }
+      }
+      ensureBlock(token, null, 'extension declaration');
+    }
+    // TODO(danrubel): Do not allow fields or constructors
+    token = parseClassOrMixinBody(token);
+    listener.endExtensionDeclaration(onKeyword, token);
+    return token;
+  }
+
   Token parseStringPart(Token token) {
     Token next = token.next;
     if (next.kind != STRING_TOKEN) {
@@ -2223,13 +2278,8 @@
               token = next;
               next = token.next;
               if (optional('(', next.next)) {
-                rewriter.insertToken(
-                    next,
-                    new SyntheticStringToken(
-                        TokenType.IDENTIFIER,
-                        '#synthetic_identifier_${next.charOffset}',
-                        next.charOffset,
-                        0));
+                rewriter.insertSyntheticIdentifier(
+                    next, '#synthetic_identifier_${next.charOffset}');
               }
             }
           }
@@ -2333,7 +2383,27 @@
           name, name, lateToken, varFinalOrConst, isTopLevel);
       ++fieldCount;
     }
-    token = ensureSemicolon(token);
+    Token semicolon = token.next;
+    if (optional(';', semicolon)) {
+      token = semicolon;
+    } else {
+      // Recovery
+      if (isTopLevel &&
+          beforeType.next.isIdentifier &&
+          beforeType.next.lexeme == 'extension') {
+        // Looks like an extension method
+        // TODO(danrubel): Remove when extension methods are enabled by default
+        // because then 'extension' will be interpreted as a built-in
+        // and this code will never be executed
+        reportRecoverableError(
+            beforeType.next,
+            fasta.templateExperimentNotEnabled
+                .withArguments('extension-methods'));
+        token = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
+      } else {
+        token = ensureSemicolon(token);
+      }
+    }
     if (isTopLevel) {
       listener.endTopLevelFields(staticToken, covariantToken, lateToken,
           varFinalOrConst, fieldCount, beforeStart.next, token);
@@ -2496,8 +2566,7 @@
         // expecting one of `,` or `;` or `{`
         reportRecoverableError(
             token, fasta.templateExpectedAfterButGot.withArguments(','));
-        next = rewriter.insertToken(
-            token, new SyntheticToken(TokenType.COMMA, token.next.charOffset));
+        next = rewriter.insertSyntheticToken(token, TokenType.COMMA);
       }
     }
     mayParseFunctionExpressions = old;
@@ -2559,8 +2628,7 @@
         // `this.<fieldname>=` is expected.
         reportRecoverableError(
             next, fasta.templateExpectedButGot.withArguments('.'));
-        rewriter.insertToken(
-            token, new SyntheticToken(TokenType.PERIOD, next.offset));
+        rewriter.insertSyntheticToken(token, TokenType.PERIOD);
         token = rewriter.insertSyntheticIdentifier(token.next);
         next = token.next;
       }
@@ -2574,8 +2642,7 @@
       // then fall through to insert the LHS and `=` of the assignment,
       // otherwise insert an `=` and synthetic identifier.
       if (!next2.isOperator && !optional('.', next2)) {
-        token = rewriter.insertToken(
-            next, new SyntheticToken(TokenType.EQ, next2.offset));
+        token = rewriter.insertSyntheticToken(next, TokenType.EQ);
         token = insertSyntheticIdentifier(token, IdentifierContext.expression,
             message: fasta.messageMissingAssignmentInInitializer,
             messageOnToken: next);
@@ -2586,8 +2653,7 @@
       token = insertSyntheticIdentifier(
           token, IdentifierContext.fieldInitializer,
           message: fasta.messageExpectedAnInitializer, messageOnToken: token);
-      token = rewriter.insertToken(
-          token, new SyntheticToken(TokenType.EQ, token.offset));
+      token = rewriter.insertSyntheticToken(token, TokenType.EQ);
       token = rewriter.insertSyntheticIdentifier(token);
       return parseInitializerExpressionRest(beforeExpression);
     }
@@ -2600,7 +2666,7 @@
     token = insertSyntheticIdentifier(
         beforeExpression, IdentifierContext.fieldInitializer,
         message: fasta.messageMissingAssignmentInInitializer);
-    rewriter.insertToken(token, new SyntheticToken(TokenType.EQ, token.offset));
+    rewriter.insertSyntheticToken(token, TokenType.EQ);
     return parseInitializerExpressionRest(beforeExpression);
   }
 
@@ -2658,17 +2724,28 @@
   }
 
   /// If the next token is an opening curly brace, return it. Otherwise, use the
-  /// given [template] to report an error, insert an opening and a closing curly
-  /// brace, and return the newly inserted opening curly brace. If the
-  /// [template] is `null`, use a default error message instead.
-  Token ensureBlock(
-      Token token, Template<Message Function(Token token)> template) {
+  /// given [template] or [blockKind] to report an error, insert an opening and
+  /// a closing curly brace, and return the newly inserted opening curly brace.
+  /// If  [template] and [blockKind] are `null`, then use
+  /// a default error message instead.
+  Token ensureBlock(Token token,
+      Template<Message Function(Token token)> template, String blockKind) {
     Token next = token.next;
     if (optional('{', next)) return next;
-    Message message = template == null
-        ? fasta.templateExpectedButGot.withArguments('{')
-        : template.withArguments(next);
-    reportRecoverableError(next, message);
+    if (template == null) {
+      if (blockKind == null) {
+        // TODO(danrubel): rename ExpectedButGot to ExpectedBefore
+        reportRecoverableError(
+            next, fasta.templateExpectedButGot.withArguments('{'));
+      } else {
+        // TODO(danrubel): rename ExpectedClassOrMixinBody
+        //  to ExpectedDeclarationOrClauseBody
+        reportRecoverableError(token,
+            fasta.templateExpectedClassOrMixinBody.withArguments(blockKind));
+      }
+    } else {
+      reportRecoverableError(next, template.withArguments(next));
+    }
     return insertBlock(token);
   }
 
@@ -2745,9 +2822,7 @@
     // for users to understand and fix the error.
     reportRecoverableError(findPreviousNonZeroLengthToken(token),
         fasta.templateExpectedAfterButGot.withArguments(';'));
-
-    return rewriter.insertToken(
-        token, new SyntheticToken(TokenType.SEMICOLON, next.charOffset));
+    return rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
   }
 
   /// Report an error at the token after [token] that has the given [message].
@@ -2801,7 +2876,7 @@
 
   Token skipClassOrMixinBody(Token token) {
     // The scanner ensures that `{` always has a closing `}`.
-    return ensureBlock(token, fasta.templateExpectedClassOrMixinBody);
+    return ensureBlock(token, null, null);
   }
 
   /// ```
@@ -3515,7 +3590,7 @@
         begin = next = token.next;
         // Fall through to parse the block.
       } else {
-        token = ensureBlock(token, fasta.templateExpectedFunctionBody);
+        token = ensureBlock(token, fasta.templateExpectedFunctionBody, null);
         listener.handleInvalidFunctionBody(token);
         return token.endGroup;
       }
@@ -3637,7 +3712,8 @@
     }
     final value = token.next.stringValue;
     if (identical(value, '{')) {
-      return parseBlock(token);
+      // The scanner ensures that `{` always has a closing `}`.
+      return parseBlock(token, null);
     } else if (identical(value, 'return')) {
       return parseReturnStatement(token);
     } else if (identical(value, 'var') || identical(value, 'final')) {
@@ -3886,7 +3962,7 @@
     }
     Token next = token.next;
     TokenType type = next.type;
-    int tokenLevel = _computePrecedence(type);
+    int tokenLevel = _computePrecedence(next);
     for (int level = tokenLevel; level >= precedence; --level) {
       int lastBinaryExpressionLevel = -1;
       while (identical(tokenLevel, level)) {
@@ -3935,10 +4011,14 @@
             rewriter.replaceTokenFollowing(token, replacement);
             replacement.endToken = replacement.next;
             token = parseArgumentOrIndexStar(token, noTypeParamOrArg);
+          } else if (identical(type, TokenType.BANG)) {
+            listener.handleNonNullAssertExpression(token.next);
+            token = next;
           } else {
             // Recovery
             reportRecoverableErrorWithToken(
                 token.next, fasta.templateUnexpectedToken);
+            token = next;
           }
         } else if (identical(type, TokenType.IS)) {
           token = parseIsOperatorRest(token);
@@ -3967,20 +4047,23 @@
         }
         next = token.next;
         type = next.type;
-        tokenLevel = _computePrecedence(type);
+        tokenLevel = _computePrecedence(next);
       }
     }
     return token;
   }
 
-  int _computePrecedence(TokenType type) {
+  int _computePrecedence(Token token) {
+    TokenType type = token.type;
     if (identical(type, TokenType.BANG)) {
       // The '!' has prefix precedence but here it's being used as a
       // postfix operator to assert the expression has a non-null value.
+      if (identical(token.next.type, TokenType.PERIOD)) {
+        return SELECTOR_PRECEDENCE;
+      }
       return POSTFIX_PRECEDENCE;
-    } else {
-      return type.precedence;
     }
+    return type.precedence;
   }
 
   Token parseCascadeExpression(Token token) {
@@ -4523,7 +4606,6 @@
     token = typeParamOrArg.parseArguments(start, this);
     if (optional('{', next)) {
       if (typeParamOrArg.typeArgumentCount > 2) {
-        // TODO(danrubel): remove code in listeners which report this error
         listener.handleRecoverableError(
             fasta.messageSetOrMapLiteralTooManyTypeArguments,
             start.next,
@@ -4535,8 +4617,7 @@
       // TODO(danrubel): Improve this error message.
       reportRecoverableError(
           next, fasta.templateExpectedButGot.withArguments('['));
-      rewriter.insertToken(
-          token, new SyntheticToken(TokenType.INDEX, next.charOffset));
+      rewriter.insertSyntheticToken(token, TokenType.INDEX);
     }
     return parseLiteralListSuffix(token, constKeyword);
   }
@@ -5364,34 +5445,27 @@
       // Recovery
       reportRecoverableError(
           leftParenthesis, fasta.templateExpectedButGot.withArguments('('));
-      int offset = leftParenthesis.offset;
 
-      BeginToken openParen = forToken
-          .setNext(new SyntheticBeginToken(TokenType.OPEN_PAREN, offset));
+      BeginToken openParen = rewriter.insertToken(
+          forToken,
+          new SyntheticBeginToken(
+              TokenType.OPEN_PAREN, leftParenthesis.offset));
 
-      Token loopPart;
+      Token token;
       if (awaitToken != null) {
-        loopPart = openParen.setNext(
-            new SyntheticStringToken(TokenType.IDENTIFIER, '', offset));
-        loopPart =
-            loopPart.setNext(new SyntheticKeywordToken(Keyword.IN, offset));
-        loopPart = loopPart.setNext(
-            new SyntheticStringToken(TokenType.IDENTIFIER, '', offset));
+        token = rewriter.insertSyntheticIdentifier(openParen);
+        token = rewriter.insertSyntheticKeyword(token, Keyword.IN);
+        token = rewriter.insertSyntheticIdentifier(token);
       } else {
-        loopPart =
-            openParen.setNext(new SyntheticToken(TokenType.SEMICOLON, offset));
-        loopPart =
-            loopPart.setNext(new SyntheticToken(TokenType.SEMICOLON, offset));
+        token = rewriter.insertSyntheticToken(openParen, TokenType.SEMICOLON);
+        token = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
       }
 
-      Token closeParen =
-          loopPart.setNext(new SyntheticToken(TokenType.CLOSE_PAREN, offset));
-      openParen.endGroup = closeParen;
-      Token identifier = closeParen
-          .setNext(new SyntheticStringToken(TokenType.IDENTIFIER, '', offset));
-      Token semicolon =
-          identifier.setNext(new SyntheticToken(TokenType.SEMICOLON, offset));
-      semicolon.setNext(leftParenthesis);
+      openParen.endGroup = token = rewriter.insertToken(token,
+          new SyntheticToken(TokenType.CLOSE_PAREN, leftParenthesis.offset));
+
+      token = rewriter.insertSyntheticIdentifier(token);
+      rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
 
       leftParenthesis = openParen;
     }
@@ -5400,7 +5474,7 @@
     // parses the metadata, modifiers, and type of a local variable
     // declaration if it exists. This enables capturing [beforeIdentifier]
     // for later error reporting.
-    return parseExpressionStatementOrDeclaration(forToken.next, true);
+    return parseExpressionStatementOrDeclaration(leftParenthesis, true);
   }
 
   /// Parse the remainder of the local variable declaration
@@ -5586,8 +5660,7 @@
     if (!optional('while', whileToken)) {
       reportRecoverableError(
           whileToken, fasta.templateExpectedButGot.withArguments('while'));
-      whileToken = rewriter.insertToken(token,
-          new SyntheticKeywordToken(Keyword.WHILE, whileToken.charOffset));
+      whileToken = rewriter.insertSyntheticKeyword(token, Keyword.WHILE);
     }
     token = ensureParenthesizedCondition(whileToken);
     token = ensureSemicolon(token);
@@ -5600,8 +5673,8 @@
   ///   '{' statement* '}'
   /// ;
   /// ```
-  Token parseBlock(Token token) {
-    Token begin = token = ensureBlock(token, null);
+  Token parseBlock(Token token, String blockKind) {
+    Token begin = token = ensureBlock(token, null, blockKind);
     listener.beginBlock(begin);
     int statementCount = 0;
     Token startToken = token.next;
@@ -5630,7 +5703,8 @@
     // because an error has already been reported by the caller.
     Listener originalListener = listener;
     listener = new ForwardingListener(listener)..forwardErrors = false;
-    token = parseBlock(token);
+    // The scanner ensures that `{` always has a closing `}`.
+    token = parseBlock(token, null);
     listener = originalListener;
     listener.handleInvalidTopLevelBlock(begin);
     return token;
@@ -5745,7 +5819,7 @@
     Token tryKeyword = token.next;
     assert(optional('try', tryKeyword));
     listener.beginTryStatement(tryKeyword);
-    Token lastConsumed = parseBlock(tryKeyword);
+    Token lastConsumed = parseBlock(tryKeyword, 'try statement');
     token = lastConsumed.next;
     int catchCount = 0;
 
@@ -5813,8 +5887,8 @@
               rewriter.moveSynthetic(exceptionName, openParens.endGroup);
               comma = null;
             } else {
-              comma = rewriter.insertToken(exceptionName,
-                  new SyntheticToken(TokenType.COMMA, comma.charOffset));
+              comma =
+                  rewriter.insertSyntheticToken(exceptionName, TokenType.COMMA);
             }
           }
           if (comma != null) {
@@ -5840,7 +5914,7 @@
         token = lastConsumed.next;
       }
       listener.endCatchClause(token);
-      lastConsumed = parseBlock(lastConsumed);
+      lastConsumed = parseBlock(lastConsumed, 'catch clause');
       token = lastConsumed.next;
       ++catchCount;
       listener.handleCatchBlock(onKeyword, catchKeyword, comma);
@@ -5850,7 +5924,7 @@
     Token finallyKeyword = null;
     if (optional('finally', token)) {
       finallyKeyword = token;
-      lastConsumed = parseBlock(token);
+      lastConsumed = parseBlock(token, 'finally clause');
       token = lastConsumed.next;
       listener.handleFinallyBlock(finallyKeyword);
     } else {
@@ -5888,7 +5962,7 @@
   /// ;
   /// ```
   Token parseSwitchBlock(Token token) {
-    Token beginSwitch = token = ensureBlock(token, null);
+    Token beginSwitch = token = ensureBlock(token, null, 'switch statement');
     listener.beginSwitchBlock(beginSwitch);
     int caseCount = 0;
     Token defaultKeyword = null;
@@ -6168,8 +6242,7 @@
       next = next.next;
     } else {
       reportRecoverableError(next, fasta.messageMissingOperatorKeyword);
-      rewriter.insertToken(
-          beforeName, new SyntheticToken(Keyword.OPERATOR, next.offset));
+      rewriter.insertSyntheticKeyword(beforeName, Keyword.OPERATOR);
     }
 
     assert((next.isOperator && next.endGroup == null) ||
@@ -6265,9 +6338,7 @@
   Token recoverFromStackOverflow(Token token) {
     Token next = token.next;
     reportRecoverableError(next, fasta.messageStackOverflow);
-
-    next = new SyntheticToken(TokenType.SEMICOLON, token.offset);
-    rewriter.insertToken(token, next);
+    next = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
     listener.handleEmptyStatement(next);
 
     while (notEofOrValue('}', next)) {
diff --git a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
index 9a8b367..29ab789 100644
--- a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
+++ b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
@@ -7,8 +7,10 @@
 import '../../scanner/token.dart'
     show
         BeginToken,
+        Keyword,
         SimpleToken,
         SyntheticBeginToken,
+        SyntheticKeywordToken,
         SyntheticStringToken,
         SyntheticToken,
         Token,
@@ -17,7 +19,7 @@
 /// Provides the capability of inserting tokens into a token stream. This
 /// implementation does this by rewriting the previous token to point to the
 /// inserted token.
-class TokenStreamRewriter {
+class TokenStreamRewriter with _TokenStreamMixin {
   // TODO(brianwilkerson):
   //
   // When we get to the point of removing `token.previous`, the plan is to
@@ -59,14 +61,6 @@
     return leftParen;
   }
 
-  /// Insert a synthetic identifier after [token] and return the new identifier.
-  Token insertSyntheticIdentifier(Token token) {
-    return insertToken(
-        token,
-        new SyntheticStringToken(
-            TokenType.IDENTIFIER, '', token.next.charOffset, 0));
-  }
-
   /// Insert [newToken] after [token] and return [newToken].
   Token insertToken(Token token, Token newToken) {
     newToken.setNext(token.next);
@@ -141,7 +135,9 @@
 /// Provides the capability of adding tokens that lead into a token stream
 /// without modifying the original token stream and not setting the any token's
 /// `previous` field.
-class TokenStreamGhostWriter implements TokenStreamRewriter {
+class TokenStreamGhostWriter
+    with _TokenStreamMixin
+    implements TokenStreamRewriter {
   @override
   Token insertParens(Token token, bool includeIdentifier) {
     Token next = token.next;
@@ -161,14 +157,6 @@
     return leftParen;
   }
 
-  /// Insert a synthetic identifier after [token] and return the new identifier.
-  Token insertSyntheticIdentifier(Token token) {
-    return insertToken(
-        token,
-        new SyntheticStringToken(
-            TokenType.IDENTIFIER, '', token.next.charOffset, 0));
-  }
-
   @override
   Token insertToken(Token token, Token newToken) {
     newToken.next = token.next;
@@ -204,3 +192,28 @@
     return current;
   }
 }
+
+mixin _TokenStreamMixin {
+  /// Insert a synthetic identifier after [token] and return the new identifier.
+  Token insertSyntheticIdentifier(Token token, [String value]) {
+    return insertToken(
+        token,
+        new SyntheticStringToken(
+            TokenType.IDENTIFIER, value ?? '', token.next.charOffset, 0));
+  }
+
+  /// Insert a new synthetic [keyword] after [token] and return the new token.
+  Token insertSyntheticKeyword(Token token, Keyword keyword) => insertToken(
+      token, new SyntheticKeywordToken(keyword, token.next.charOffset));
+
+  /// Insert a new simple synthetic token of [newTokenType] after [token]
+  /// and return the new token.
+  Token insertSyntheticToken(Token token, TokenType newTokenType) {
+    assert(newTokenType is! Keyword, 'use insertSyntheticKeyword instead');
+    return insertToken(
+        token, new SyntheticToken(newTokenType, token.next.charOffset));
+  }
+
+  /// Insert [newToken] after [token] and return [newToken].
+  Token insertToken(Token token, Token newToken);
+}
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index 1125c14..cf3c27f 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -363,10 +363,8 @@
   @override
   void endLibraryName(Token libraryKeyword, Token semicolon) {
     debugEvent("endLibraryName");
-    pop(); // name
-
-    Token metadata = pop();
-    parseMetadata(library, metadata, library.target);
+    pop(); // Name.
+    pop(); // Annotations.
   }
 
   @override
@@ -537,7 +535,6 @@
 
     ProcedureBuilder builder = lookupConstructor(beginToken, name);
     if (bodyToken == null || optional("=", bodyToken.endGroup.next)) {
-      parseMetadata(builder, metadata, builder.target);
       buildRedirectingFactoryMethod(
           bodyToken, builder, MemberKind.Factory, metadata);
     } else {
@@ -709,18 +706,14 @@
     debugEvent("beginClassOrMixinBody");
     Token beginToken = pop();
     Object name = pop();
-    Token metadata = pop();
+    pop(); // Annotation begin token.
     assert(currentClass == null);
     assert(memberScope == library.scope);
     if (name is ParserRecovery) {
       currentClassIsParserRecovery = true;
       return;
     }
-
-    Declaration classBuilder = lookupBuilder(beginToken, null, name);
-    parseMetadata(classBuilder, metadata, classBuilder.target);
-
-    currentClass = classBuilder;
+    currentClass = lookupBuilder(beginToken, null, name);
     memberScope = currentClass.scope;
   }
 
@@ -747,26 +740,9 @@
   @override
   void endEnum(Token enumKeyword, Token leftBrace, int count) {
     debugEvent("Enum");
-    List<Object> metadataAndValues =
-        const FixedNullableList<Object>().pop(stack, count * 2);
-    Object name = pop();
-    Token metadata = pop();
-    checkEmpty(enumKeyword.charOffset);
-    if (name is ParserRecovery) return;
-
-    ClassBuilder enumBuilder = lookupBuilder(enumKeyword, null, name);
-    parseMetadata(enumBuilder, metadata, enumBuilder.target);
-    if (metadataAndValues != null) {
-      for (int i = 0; i < metadataAndValues.length; i += 2) {
-        Token metadata = metadataAndValues[i];
-        String valueName = metadataAndValues[i + 1];
-        Declaration declaration = enumBuilder.scope.local[valueName];
-        if (metadata != null) {
-          parseMetadata(declaration, metadata, declaration.target);
-        }
-      }
-    }
-
+    const FixedNullableList<Object>().pop(stack, count * 2);
+    pop(); // Name.
+    pop(); // Annotations begin token.
     checkEmpty(enumKeyword.charOffset);
   }
 
@@ -775,20 +751,9 @@
       Token equals, Token implementsKeyword, Token endToken) {
     debugEvent("NamedMixinApplication");
 
-    Object name = pop();
-    Token metadata = pop();
+    pop(); // Name.
+    pop(); // Annotations begin token.
     checkEmpty(beginToken.charOffset);
-    if (name is ParserRecovery) return;
-
-    Declaration classBuilder = library.scopeBuilder[name];
-    if (classBuilder != null) {
-      // TODO(ahe): We shouldn't have to check for null here. The problem is
-      // that we don't create a named mixin application if the mixins or
-      // supertype are missing. Could we create a class instead? The nested
-      // declarations wouldn't match up.
-      parseMetadata(classBuilder, metadata, classBuilder.target);
-      checkEmpty(beginToken.charOffset);
-    }
   }
 
   AsyncMarker getAsyncMarker(StackListener listener) => listener.pop();
@@ -800,13 +765,11 @@
   void listenerFinishFunction(
       StackListener listener,
       Token token,
-      Token metadata,
       MemberKind kind,
-      List metadataConstants,
       dynamic formals,
       AsyncMarker asyncModifier,
       dynamic body) {
-    listener.finishFunction(metadataConstants, formals, asyncModifier, body);
+    listener.finishFunction(formals, asyncModifier, body);
   }
 
   /// Invokes the listener's [finishFields] method.
@@ -823,10 +786,9 @@
     Token token = startToken;
     try {
       Parser parser = new Parser(listener);
-      List metadataConstants;
       if (metadata != null) {
         parser.parseMetadataStar(parser.syntheticPreviousToken(metadata));
-        metadataConstants = listener.pop();
+        listener.pop(); // Annotations.
       }
       token = parser.parseFormalParametersOpt(
           parser.syntheticPreviousToken(token), kind);
@@ -840,8 +802,8 @@
       parser.parseFunctionBody(token, isExpression, allowAbstract);
       var body = listener.pop();
       listener.checkEmpty(token.charOffset);
-      listenerFinishFunction(listener, startToken, metadata, kind,
-          metadataConstants, formals, asyncModifier, body);
+      listenerFinishFunction(
+          listener, startToken, kind, formals, asyncModifier, body);
     } on DebugAbort {
       rethrow;
     } catch (e, s) {
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 24d3a08..43536a0 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -41,6 +41,7 @@
 // TODO(ahe): The outline isn't supposed to import kernel-specific builders.
 import '../kernel/kernel_builder.dart'
     show
+        KernelMetadataBuilder,
         KernelMixinApplicationBuilder,
         KernelNamedTypeBuilder,
         KernelTypeBuilder;
@@ -137,36 +138,23 @@
   @override
   void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
     debugEvent("Metadata");
-    List arguments = pop();
-    popIfNotNull(periodBeforeName); // charOffset.
-    String postfix = popIfNotNull(periodBeforeName);
-    List<TypeBuilder> typeArguments = pop();
-    if (arguments == null) {
-      pop(); // charOffset
-      Object expression = pop();
-      push(new MetadataBuilder<KernelTypeBuilder>.fromExpression(
-          expression, postfix, library, beginToken.charOffset));
-    } else {
-      int charOffset = pop();
-      Object typeName = pop();
-      if (typeName is ParserRecovery) {
-        push(typeName);
-      } else {
-        push(new MetadataBuilder<KernelTypeBuilder>.fromConstructor(
-            library.addConstructorReference(
-                typeName, typeArguments, postfix, charOffset),
-            arguments,
-            library,
-            beginToken.charOffset));
-      }
+    pop(); // arguments
+    if (periodBeforeName != null) {
+      pop(); // offset
+      pop(); // constructor name
     }
+    pop(); // type arguments
+    pop(); // offset
+    Object sentinel = pop(); // prefix or constructor
+    push(sentinel is ParserRecovery
+        ? sentinel
+        : new KernelMetadataBuilder(beginToken));
   }
 
   @override
   void endMetadataStar(int count) {
     debugEvent("MetadataStar");
-    push(const FixedNullableList<MetadataBuilder<KernelTypeBuilder>>()
-            .pop(stack, count) ??
+    push(const FixedNullableList<MetadataBuilder>().pop(stack, count) ??
         NullValue.Metadata);
   }
 
@@ -212,7 +200,7 @@
     List<Configuration> configurations = pop();
     int uriOffset = popCharOffset();
     String uri = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     library.addExport(metadata, uri, configurations, combinators,
         exportKeyword.charOffset, uriOffset);
     checkEmpty(exportKeyword.charOffset);
@@ -240,7 +228,7 @@
     List<Configuration> configurations = pop();
     int uriOffset = popCharOffset();
     String uri = pop(); // For a conditional import, this is the default URI.
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     checkEmpty(importKeyword.charOffset);
     if (prefix is ParserRecovery) return;
     library.addImport(
@@ -304,7 +292,7 @@
     debugEvent("Part");
     int charOffset = popCharOffset();
     String uri = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     library.addPart(metadata, uri, charOffset);
     checkEmpty(partKeyword.charOffset);
   }
@@ -327,7 +315,7 @@
   void handleIdentifier(Token token, IdentifierContext context) {
     if (context == IdentifierContext.enumValueDeclaration) {
       debugEvent("handleIdentifier");
-      List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+      List<MetadataBuilder> metadata = pop();
       if (token.isSynthetic) {
         push(new ParserRecovery(token.charOffset));
       } else {
@@ -435,7 +423,7 @@
     popCharOffset();
     String documentationComment = getDocumentationComment(libraryKeyword);
     Object name = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     library.documentationComment = documentationComment;
     if (name is! ParserRecovery) {
       library.name = flattenName(name, offsetForToken(libraryKeyword), uri);
@@ -551,7 +539,7 @@
     if (typeVariables != null && supertype is MixinApplicationBuilder) {
       supertype.typeVariables = typeVariables;
     }
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery) {
       library.endNestedDeclaration("<syntax-error>");
@@ -589,7 +577,7 @@
         pop(NullValue.TypeVariables);
     int nameOffset = pop();
     Object name = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop(NullValue.Metadata);
+    List<MetadataBuilder> metadata = pop(NullValue.Metadata);
     checkEmpty(mixinToken.charOffset);
     if (name is ParserRecovery) {
       library.endNestedDeclaration("<syntax-error>");
@@ -657,7 +645,7 @@
     if (isAbstract) {
       modifiers |= abstractMask;
     }
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     checkEmpty(beginToken.charOffset);
     library
         .endNestedDeclaration("#method")
@@ -843,7 +831,7 @@
     }
     bool isConst = (modifiers & constMask) != 0;
     int varFinalOrConstOffset = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     String documentationComment = getDocumentationComment(beginToken);
     library
         .endNestedDeclaration("#method")
@@ -938,7 +926,7 @@
         pop();
     int charOffset = pop();
     Object name = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery || mixinApplication is ParserRecovery) {
       library.endNestedDeclaration("<syntax-error>");
@@ -1033,7 +1021,7 @@
     Object name = pop();
     TypeBuilder type = nullIfParserRecovery(pop());
     int modifiers = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     if (name is ParserRecovery) {
       push(name);
     } else {
@@ -1185,7 +1173,7 @@
     int charOffset = pop(); // identifier char offset.
     int startCharOffset = enumKeyword.charOffset;
     Object name = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     checkEmpty(enumKeyword.charOffset);
     if (name is ParserRecovery) return;
     library.addEnum(documentationComment, metadata, name, enumConstantInfos,
@@ -1282,7 +1270,7 @@
         addProblem(messageTypedefNotFunction, equals.charOffset, equals.length);
       }
     }
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     checkEmpty(typedefKeyword.charOffset);
     library.addFunctionTypeAlias(documentationComment, metadata, name,
         typeVariables, functionType, charOffset);
@@ -1305,7 +1293,7 @@
     int modifiers = (staticToken != null ? staticMask : 0) |
         (covariantToken != null ? covariantMask : 0) |
         Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme);
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     checkEmpty(beginToken.charOffset);
     if (fieldInfos == null) return;
     String documentationComment = getDocumentationComment(beginToken);
@@ -1331,7 +1319,7 @@
           varFinalOrConst.length);
       modifiers &= ~constMask;
     }
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     if (fieldInfos == null) return;
     String documentationComment = getDocumentationComment(beginToken);
     library.addFields(
@@ -1461,7 +1449,7 @@
     debugEvent("endPartOf");
     int charOffset = popCharOffset();
     Object containingLibrary = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     if (hasName) {
       library.addPartOf(metadata,
           flattenName(containingLibrary, charOffset, uri), null, charOffset);
@@ -1511,7 +1499,7 @@
     int charOffset = pop();
     Object name = pop();
     int modifiers = pop();
-    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+    List<MetadataBuilder> metadata = pop();
     if (name is ParserRecovery) {
       library.endNestedDeclaration("<syntax-error>");
       return;
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index e2a7840..28b8b90 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -11,7 +11,9 @@
 
 import '../fasta_codes.dart'
     show
+        Message,
         noLength,
+        templateBadTypeVariableInSupertype,
         templateConflictsWithConstructor,
         templateConflictsWithFactory,
         templateConflictsWithMember,
@@ -28,6 +30,7 @@
         KernelClassBuilder,
         KernelFieldBuilder,
         KernelFunctionBuilder,
+        KernelInvalidTypeBuilder,
         KernelLibraryBuilder,
         KernelNamedTypeBuilder,
         KernelTypeBuilder,
@@ -40,6 +43,8 @@
 
 import '../kernel/kernel_shadow_ast.dart' show ShadowClass;
 
+import '../kernel/type_algorithms.dart' show Variance, computeVariance;
+
 import '../problems.dart' show unexpected, unhandled;
 
 ShadowClass initializeClass(
@@ -144,6 +149,7 @@
 
     scope.forEach(buildBuilders);
     constructors.forEach(buildBuilders);
+    supertype = checkSupertype(supertype);
     actualCls.supertype =
         supertype?.buildSupertype(library, charOffset, fileUri);
     if (!isMixinDeclaration &&
@@ -160,6 +166,7 @@
           fileUri);
       actualCls.supertype = null;
     }
+    mixedInType = checkSupertype(mixedInType);
     actualCls.mixedInType =
         mixedInType?.buildMixedInType(library, charOffset, fileUri);
     actualCls.isMixinDeclaration = isMixinDeclaration;
@@ -167,9 +174,10 @@
     // compile-time error.
     cls.isAbstract = isAbstract;
     if (interfaces != null) {
-      for (KernelTypeBuilder interface in interfaces) {
+      for (int i = 0; i < interfaces.length; ++i) {
+        interfaces[i] = checkSupertype(interfaces[i]);
         Supertype supertype =
-            interface.buildSupertype(library, charOffset, fileUri);
+            interfaces[i].buildSupertype(library, charOffset, fileUri);
         if (supertype != null) {
           // TODO(ahe): Report an error if supertype is null.
           actualCls.implementedTypes.add(supertype);
@@ -234,6 +242,26 @@
     return cls;
   }
 
+  KernelTypeBuilder checkSupertype(KernelTypeBuilder supertype) {
+    if (typeVariables == null || supertype == null) return supertype;
+    Message message;
+    for (int i = 0; i < typeVariables.length; ++i) {
+      int variance = computeVariance(typeVariables[i], supertype);
+      if (variance == Variance.contravariant ||
+          variance == Variance.invariant) {
+        message = templateBadTypeVariableInSupertype.withArguments(
+            typeVariables[i].name, supertype.name);
+        library.addProblem(message, charOffset, noLength, fileUri);
+      }
+    }
+    if (message != null) {
+      return new KernelNamedTypeBuilder(supertype.name, null)
+        ..bind(new KernelInvalidTypeBuilder(supertype.name,
+            message.withLocation(fileUri, charOffset, noLength)));
+    }
+    return supertype;
+  }
+
   void addSyntheticConstructor(Constructor constructor) {
     String name = constructor.name.name;
     cls.constructors.add(constructor);
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index fb12c34..3323184 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -396,26 +396,18 @@
   void addFields(String documentationComment, List<MetadataBuilder> metadata,
       int modifiers, T type, List<FieldInfo> fieldInfos) {
     for (FieldInfo info in fieldInfos) {
-      String name = info.name;
-      int charOffset = info.charOffset;
-      int charEndOffset = info.charEndOffset;
-      bool hasInitializer = info.initializerTokenForInference != null;
-      Token initializerTokenForInference =
+      Token startToken =
           type != null || legacyMode ? null : info.initializerTokenForInference;
-      if (initializerTokenForInference != null) {
-        Token beforeLast = info.beforeLast;
-        beforeLast.setNext(new Token.eof(beforeLast.next.offset));
+      if (startToken != null) {
+        // Extract only the tokens for the initializer expression from the
+        // token stream.
+        Token endToken = info.beforeLast;
+        endToken.setNext(new Token.eof(endToken.next.offset));
+        new Token.eof(startToken.previous.offset).setNext(startToken);
       }
-      addField(
-          documentationComment,
-          metadata,
-          modifiers,
-          type,
-          name,
-          charOffset,
-          charEndOffset,
-          initializerTokenForInference,
-          hasInitializer);
+      bool hasInitializer = info.initializerTokenForInference != null;
+      addField(documentationComment, metadata, modifiers, type, info.name,
+          info.charOffset, info.charEndOffset, startToken, hasInitializer);
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 4c3b6c9..adffcbd 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -82,6 +82,7 @@
         KernelProcedureBuilder,
         KernelTypeBuilder,
         LibraryBuilder,
+        MemberBuilder,
         NamedTypeBuilder,
         TypeBuilder;
 
@@ -947,6 +948,23 @@
     ticker.logMs("Checked mixin declaration applications");
   }
 
+  void buildAnnotations() {
+    builders.forEach((Uri uri, LibraryBuilder library) {
+      if (library.loader == this) {
+        library.buildAnnotations();
+        Iterator<Declaration> iterator = library.iterator;
+        while (iterator.moveNext()) {
+          Declaration declaration = iterator.current;
+          if (declaration is ClassBuilder) {
+            declaration.buildAnnotations(library);
+          } else if (declaration is MemberBuilder) {
+            declaration.buildAnnotations(library);
+          }
+        }
+      }
+    });
+  }
+
   ClassHierarchyBuilder buildClassHierarchy(
       List<SourceClassBuilder> sourceClasses, ClassBuilder objectClass) {
     ClassHierarchyBuilder hierarchy = ClassHierarchyBuilder.build(
@@ -1036,17 +1054,17 @@
 
   void transformListPostInference(List<TreeNode> list,
       bool transformSetLiterals, bool transformCollections) {
-    if (transformSetLiterals) {
-      SetLiteralTransformer transformer = setLiteralTransformer ??=
-          new SetLiteralTransformer(this,
-              transformConst: !target.enableConstantUpdate2018);
+    if (transformCollections) {
+      CollectionTransformer transformer =
+          collectionTransformer ??= new CollectionTransformer(this);
       for (int i = 0; i < list.length; ++i) {
         list[i] = list[i].accept(transformer);
       }
     }
-    if (transformCollections) {
-      CollectionTransformer transformer =
-          collectionTransformer ??= new CollectionTransformer(this);
+    if (transformSetLiterals) {
+      SetLiteralTransformer transformer = setLiteralTransformer ??=
+          new SetLiteralTransformer(this,
+              transformConst: !target.enableConstantUpdate2018);
       for (int i = 0; i < list.length; ++i) {
         list[i] = list[i].accept(transformer);
       }
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener.dart b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
index db6a7cd..443b623 100644
--- a/pkg/front_end/lib/src/fasta/source/stack_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
@@ -86,8 +86,8 @@
 
   // TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart
   // and ast_builder.dart.
-  void finishFunction(covariant List<Object> annotations, covariant formals,
-      AsyncMarker asyncModifier, covariant body) {
+  void finishFunction(
+      covariant formals, AsyncMarker asyncModifier, covariant body) {
     return unsupported("finishFunction", -1, uri);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index 6e82a7d..2ca6f77 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -50,18 +50,27 @@
 
   bool enableConstantUpdate2018;
   bool enableControlFlowCollections;
+  bool enableExtensionMethods;
+  bool enableNonNullable;
   bool enableSetLiterals;
   bool enableSpreadCollections;
+  bool enableTripleShift;
 
   TargetImplementation(Ticker ticker, this.uriTranslator, this.backendTarget)
       : enableConstantUpdate2018 = CompilerContext.current.options
             .isExperimentEnabled(ExperimentalFlag.constantUpdate2018),
         enableControlFlowCollections = CompilerContext.current.options
             .isExperimentEnabled(ExperimentalFlag.controlFlowCollections),
+        enableExtensionMethods = CompilerContext.current.options
+            .isExperimentEnabled(ExperimentalFlag.extensionMethods),
+        enableNonNullable = CompilerContext.current.options
+            .isExperimentEnabled(ExperimentalFlag.nonNullable),
         enableSetLiterals = CompilerContext.current.options
             .isExperimentEnabled(ExperimentalFlag.setLiterals),
         enableSpreadCollections = CompilerContext.current.options
             .isExperimentEnabled(ExperimentalFlag.spreadCollections),
+        enableTripleShift = CompilerContext.current.options
+            .isExperimentEnabled(ExperimentalFlag.tripleShift),
         super(ticker);
 
   /// Creates a [LibraryBuilder] corresponding to [uri], if one doesn't exist
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 0229457..0fccb0c 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -21,6 +21,7 @@
 AsyncAsIdentifier/example: Fail
 AwaitAsIdentifier/example: Fail
 AwaitNotAsync/example: Fail
+BadTypeVariableInSupertype/analyzerCode: Fail
 BuiltInIdentifierAsType/example: Fail
 BuiltInIdentifierInDeclaration/example: Fail
 CannotAssignToParenthesizedExpression/example: Fail
@@ -101,7 +102,6 @@
 ContinueWithoutLabelInCase/script1: Fail
 CouldNotParseUri/analyzerCode: Fail
 CouldNotParseUri/example: Fail
-CovariantAfterVar/script1: Fail
 CovariantAndStatic/script1: Fail
 CovariantAndStatic/script2: Fail
 CovariantMember/script1: Fail
@@ -359,7 +359,6 @@
 SpreadMapEntryTypeMismatch/analyzerCode: Fail # There's no analyzer code for that error yet.
 SpreadTypeMismatch/analyzerCode: Fail # There's no analyzer code for that error yet.
 StackOverflow/example: Fail
-StaticAfterConst/script1: Fail
 SuperAsExpression/example: Fail
 SuperAsIdentifier/example: Fail
 SuperNullAware/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 42b24b6..8f1b921 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -208,7 +208,7 @@
   bytes: [255]
 
 ExperimentNotEnabled:
-  index: 93
+  index: 48
   template: "This requires the '#string' experiment to be enabled."
   tip: "Try enabling this experiment by adding it to the command line when compiling and running."
   analyzerCode: ParserErrorCode.EXPERIMENT_NOT_ENABLED
@@ -236,7 +236,7 @@
     }
 
 ExpectedElseOrComma:
-  index: 94
+  index: 46
   template: "Expected 'else' or comma."
   analyzerCode: ParserErrorCode.EXPECTED_ELSE_OR_COMMA
 
@@ -413,10 +413,10 @@
       class A implements FutureOr<int> {}
 
 ExpectedClassOrMixinBody:
-  template: "Expected a class or mixin body, but got '#lexeme'."
-  analyzerCode: MISSING_CLASS_BODY
-
-ExpectedClassBodyToSkip: ExpectedClassOrMixinBody
+  index: 8
+  template: "A #string must have a body, even if it is empty."
+  tip: "Try adding an empty body."
+  analyzerCode: ParserErrorCode.EXPECTED_BODY
 
 ExpectedDeclaration:
   template: "Expected a declaration, but got '#lexeme'."
@@ -618,6 +618,11 @@
   analyzerCode: ParserErrorCode.MODIFIER_OUT_OF_ORDER
   script:
     - "class C { factory const C() = prefix.B.foo; }"
+    - "class C { factory external C(); }"
+    - "class C { const external C(); }"
+    - "class C { static external f(); }"
+    - "class C { final static int f = 5; }"
+    - "class C { var static f; }"
 
 TypeBeforeFactory:
   index: 57
@@ -642,14 +647,6 @@
   script:
     - "class C { const m() {} }"
 
-CovariantAfterVar:
-  index: 8
-  template: "The modifier 'covariant' should be before the modifier 'var'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.COVARIANT_AFTER_VAR
-  script:
-    - "var covariant f;"
-
 CovariantAndStatic:
   index: 66
   template: "Members can't be declared to be both 'covariant' and 'static'."
@@ -671,30 +668,6 @@
     - "class C { static static var m; }"
     - "class C { var var m; }"
 
-ExternalAfterConst:
-  index: 46
-  template: "The modifier 'external' should be before the modifier 'const'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.EXTERNAL_AFTER_CONST
-  script:
-    - "class C { const external C(); }"
-
-ExternalAfterFactory:
-  index: 47
-  template: "The modifier 'external' should be before the modifier 'factory'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.EXTERNAL_AFTER_FACTORY
-  script:
-    - "class C { factory external C(); }"
-
-ExternalAfterStatic:
-  index: 48
-  template: "The modifier 'external' should be before the modifier 'static'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.EXTERNAL_AFTER_STATIC
-  script:
-    - "class C { static external f(); }"
-
 ExternalConstructorWithBody:
   index: 87
   template: "External constructors can't have a body."
@@ -809,30 +782,6 @@
     - "class C { final var x = 5; }"
     - "class C { var final x = 5; }"
 
-StaticAfterConst:
-  index: 20
-  template: "The modifier 'static' should be before the modifier 'const'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.STATIC_AFTER_CONST
-  script:
-    - "class C { const static int f; }"
-
-StaticAfterFinal:
-  index: 19
-  template: "The modifier 'static' should be before the modifier 'final'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.STATIC_AFTER_FINAL
-  script:
-    - "class C { final static int f = 5; }"
-
-StaticAfterVar:
-  index: 18
-  template: "The modifier 'static' should be before the modifier 'var'."
-  tip: "Try re-ordering the modifiers."
-  analyzerCode: ParserErrorCode.STATIC_AFTER_VAR
-  script:
-    - "class C { var static f; }"
-
 StaticConstructor:
   index: 4
   template: "Constructors can't be static."
@@ -1043,7 +992,7 @@
       }
 
 StackOverflow:
-  index: 91
+  index: 19
   template: "The file has too many nested expressions or statements."
   tip: "Try simplifying the code."
   analyzerCode: ParserErrorCode.STACK_OVERFLOW
@@ -1165,10 +1114,6 @@
   template: "Abstract methods can't use 'async', 'async*', or 'sync*'."
   analyzerCode: NON_SYNC_ABSTRACT_METHOD
 
-AsyncAsIdentifier:
-  analyzerCode: ASYNC_KEYWORD_USED_AS_IDENTIFIER
-  template: "'async' can't be used as an identifier in 'async', 'async*', or 'sync*' methods."
-
 AwaitAsIdentifier:
   template: "'await' can't be used as an identifier in 'async', 'async*', or 'sync*' methods."
   analyzerCode: ASYNC_KEYWORD_USED_AS_IDENTIFIER
@@ -1226,7 +1171,7 @@
   analyzerCode: YIELD_IN_NON_GENERATOR
 
 OnlyTry:
-  index: 92
+  index: 20
   template: "A try block must be followed by an 'on', 'catch', or 'finally' clause."
   tip: "Try adding either a catch or finally clause, or remove the try statement."
   analyzerCode: ParserErrorCode.MISSING_CATCH_OR_FINALLY
@@ -1294,7 +1239,7 @@
     - "try {} catch (e, s, x) {}"
 
 SuperNullAware:
-  index: 90
+  index: 18
   template: "The operator '?.' cannot be used with 'super' because 'super' cannot be null."
   tip: "Try replacing '?.' with '.'"
   analyzerCode: ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER
@@ -2542,7 +2487,7 @@
   tip: "Normally, the specification is a file named 'libraries.json' in the Dart SDK install location."
 
 InvalidSuperInInitializer:
-  index: 95
+  index: 47
   template: "Can only use 'super' in an initializer for calling the superclass constructor (e.g. 'super()' or 'super.namedConstructor()')"
   analyzerCode: ParserErrorCode.INVALID_SUPER_IN_INITIALIZER
 
@@ -3612,3 +3557,9 @@
     main() {
       <int>[...null];
     }
+
+BadTypeVariableInSupertype:
+  template: "Found unsupported uses of '#name' in supertype '#name2'."
+  script: >
+    class A<X> {}
+    class B<Y> extends A<Function(Y)> {}
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index 6987266..7f59d4b 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -241,5 +241,6 @@
         "offset: 4, prefixGenerator: , isInitializer: false, isSuper: false)",
         new KernelUnexpectedQualifiedUseGenerator(
             helper, token, generator, false));
+    return Future<void>.value();
   });
 }
diff --git a/pkg/front_end/test/fasta/unlinked_scope_test.dart b/pkg/front_end/test/fasta/unlinked_scope_test.dart
index e58294c..fb933f8 100644
--- a/pkg/front_end/test/fasta/unlinked_scope_test.dart
+++ b/pkg/front_end/test/fasta/unlinked_scope_test.dart
@@ -108,5 +108,6 @@
     testExpression("unresolved");
     testExpression("a + b", "a.+(b)");
     testExpression("a = b");
+    return Future<void>.value();
   });
 }
diff --git a/pkg/front_end/test/incremental_load_from_dill_test.dart b/pkg/front_end/test/incremental_load_from_dill_test.dart
index b5cffb2..a2ec791 100644
--- a/pkg/front_end/test/incremental_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_test.dart
@@ -307,7 +307,6 @@
       for (String moduleName in world["modules"]) {
         Component moduleComponent = moduleComponents[moduleName];
         if (moduleComponent != null) {
-          moduleComponent.computeCanonicalNames();
           modulesToUse.add(moduleComponent);
         }
       }
diff --git a/pkg/front_end/test/src/base/processed_options_test.dart b/pkg/front_end/test/src/base/processed_options_test.dart
index 605b5ac..0abc4cb 100644
--- a/pkg/front_end/test/src/base/processed_options_test.dart
+++ b/pkg/front_end/test/src/base/processed_options_test.dart
@@ -22,6 +22,7 @@
     defineReflectiveSuite(() {
       defineReflectiveTests(ProcessedOptionsTest);
     });
+    return Future<void>.value();
   });
 }
 
diff --git a/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect b/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect
index 319403e..a04857a 100644
--- a/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect
+++ b/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect
@@ -11,7 +11,9 @@
   final field core::int index;
   final field core::String _name;
   static const field core::List<self::Foo> values = const <self::Foo>[self::Foo::bar, self::Foo::baz, self::Foo::cafebabe];
+  @self::hest
   static const field self::Foo bar = const self::Foo::•(0, "Foo.bar");
+  @self::Fisk::fisk<dynamic>(self::hest)
   static const field self::Foo baz = const self::Foo::•(1, "Foo.baz");
   static const field self::Foo cafebabe = const self::Foo::•(2, "Foo.cafebabe");
   const constructor •(core::int index, core::String _name) → self::Foo
diff --git a/pkg/front_end/testcases/annotation_top.dart.outline.expect b/pkg/front_end/testcases/annotation_top.dart.outline.expect
index 6839b80..579ecba 100644
--- a/pkg/front_end/testcases/annotation_top.dart.outline.expect
+++ b/pkg/front_end/testcases/annotation_top.dart.outline.expect
@@ -1,3 +1,5 @@
+@test::a
+@test::A::•(1)
 library test;
 import self as self;
 import "dart:core" as core;
@@ -8,12 +10,20 @@
   const constructor •(core::int value) → self::A
     ;
 }
+@self::a
+@self::A::•(2)
 class C extends core::Object {
   synthetic constructor •() → self::C
     ;
 }
 static const field core::Object a;
+@self::a
+@self::A::•(3)
 static field core::int f1;
+@self::a
+@self::A::•(3)
 static field core::int f2;
+@self::a
+@self::A::•(4)
 static method main() → void
   ;
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart
new file mode 100644
index 0000000..3816961
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2019, 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.
+
+typedef ContravariantUse<T> = Function(T);
+
+typedef InvariantUse<T> = T Function(T);
+
+class Empty {}
+
+class A<T> {}
+
+class B<T> extends A<Function(T)> {}
+
+class Bc<T> extends A<ContravariantUse<T>> {}
+
+class Bi<T> extends A<InvariantUse<T>> {}
+
+class C<T> implements A<Function(T)> {}
+
+class Cc<T> implements A<ContravariantUse<T>> {}
+
+class Ci<T> implements A<InvariantUse<T>> {}
+
+class D<T> = Object with A<Function(T)>;
+
+class Dc<T> = Object with A<ContravariantUse<T>>;
+
+class Di<T> = Object with A<InvariantUse<T>>;
+
+class E<T> = A<Function(T)> with Empty;
+
+class Ec<T> = A<ContravariantUse<T>> with Empty;
+
+class Ei<T> = A<InvariantUse<T>> with Empty;
+
+class F<T> extends Object with A<Function(T)> {}
+
+class Fc<T> extends Object with A<ContravariantUse<T>> {}
+
+class Fi<T> extends Object with A<InvariantUse<T>> {}
+
+class G<T> extends A<Function(T)> with Empty {}
+
+class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+
+class Gi<T> extends A<InvariantUse<T>> with Empty {}
+
+class Hff<T> extends A<Function(Function(T))> {}
+
+class Hfc<T> extends A<Function(ContravariantUse<T>)> {}
+
+class Hcf<T> extends A<ContravariantUse<Function(T)>> {}
+
+class Hcc<T> extends A<ContravariantUse<ContravariantUse<T>>> {}
+
+class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+
+class Iafc<T> extends A<A<Function(ContravariantUse<T>)>> {}
+
+class Iacf<T> extends A<A<ContravariantUse<Function(T)>>> {}
+
+class Ifac<T> extends A<Function(A<ContravariantUse<T>>)> {}
+
+class Ifca<T> extends A<Function(ContravariantUse<A<T>>)> {}
+
+class Icaf<T> extends A<ContravariantUse<A<Function(T)>>> {}
+
+class Icfa<T> extends A<ContravariantUse<Function(A<T>)>> {}
+
+class Jfff<T> extends A<Function(Function(Function(T)))> {}
+
+class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+
+class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+
+class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+
+class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+
+class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+
+class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+
+class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.hierarchy.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.hierarchy.expect
new file mode 100644
index 0000000..060d1ab
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.hierarchy.expect
@@ -0,0 +1,917 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Empty:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+B:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Bc:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Bi:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+C:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Cc:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Ci:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+D:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Dc:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Di:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+E:
+  Longest path to Object: 2
+  superclasses:
+    A
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+Ec:
+  Longest path to Object: 2
+  superclasses:
+    A
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+Ei:
+  Longest path to Object: 2
+  superclasses:
+    A
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+Object with A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+F:
+  superclasses:
+    Object
+      -> _F&Object&A<T>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Object with A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Fc:
+  superclasses:
+    Object
+      -> _Fc&Object&A<T>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Object with A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Fi:
+  superclasses:
+    Object
+      -> _Fi&Object&A<T>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+A with Empty:
+  Longest path to Object: 2
+  superclasses:
+    A
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+G:
+  Longest path to Object: 3
+  superclasses:
+    A
+      -> _G&A&Empty<T>
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+A with Empty:
+  Longest path to Object: 2
+  superclasses:
+    A
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+Gc:
+  Longest path to Object: 3
+  superclasses:
+    A
+      -> _Gc&A&Empty<T>
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+A with Empty:
+  Longest path to Object: 2
+  superclasses:
+    A
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+Gi:
+  Longest path to Object: 3
+  superclasses:
+    A
+      -> _Gi&A&Empty<T>
+  interfaces: Empty, Object
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+Hff:
+  superclasses:
+    Object
+      -> A<(null) -> null>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Hfc:
+  superclasses:
+    Object
+      -> A<(null) -> null>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Hcf:
+  superclasses:
+    Object
+      -> A<ContravariantUse<(null) -> null>>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Hcc:
+  superclasses:
+    Object
+      -> A<ContravariantUse<ContravariantUse<T>>>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Hii:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Iafc:
+  superclasses:
+    Object
+      -> A<A<(null) -> null>>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Iacf:
+  superclasses:
+    Object
+      -> A<A<ContravariantUse<(null) -> null>>>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Ifac:
+  superclasses:
+    Object
+      -> A<(null) -> null>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Ifca:
+  superclasses:
+    Object
+      -> A<(null) -> null>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Icaf:
+  superclasses:
+    Object
+      -> A<ContravariantUse<A<(null) -> null>>>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Icfa:
+  superclasses:
+    Object
+      -> A<ContravariantUse<(null) -> null>>
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jfff:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jffc:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jfcf:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jfcc:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jcff:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jcfc:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jccf:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+Jccc:
+  superclasses:
+    A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.expect
new file mode 100644
index 0000000..74cdea4
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.expect
@@ -0,0 +1,343 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+  synthetic constructor •() → self::Empty
+    : super core::Object::•()
+    ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bc<self::Bc::T>
+    : super core::Object::•()
+    ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bi<self::Bi::T>
+    : super core::Object::•()
+    ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Cc<self::Cc::T>
+    : super core::Object::•()
+    ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ci<self::Ci::T>
+    : super core::Object::•()
+    ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::D<self::D::T>
+    : super core::Object::•()
+    ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Dc<self::Dc::T>
+    : super core::Object::•()
+    ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Di<self::Di::T>
+    : super core::Object::•()
+    ;
+}
+class E<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::E<self::E::T>
+    : super core::Object::•()
+    ;
+}
+class Ec<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::Ec<self::Ec::T>
+    : super core::Object::•()
+    ;
+}
+class Ei<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::Ei<self::Ei::T>
+    : super core::Object::•()
+    ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+  synthetic constructor •() → self::F<self::F::T>
+    : super self::_F&Object&A::•()
+    ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+  synthetic constructor •() → self::Fc<self::Fc::T>
+    : super self::_Fc&Object&A::•()
+    ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+  synthetic constructor •() → self::Fi<self::Fi::T>
+    : super self::_Fi&Object&A::•()
+    ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+  synthetic constructor •() → self::G<self::G::T>
+    : super self::_G&A&Empty::•()
+    ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+  synthetic constructor •() → self::Gc<self::Gc::T>
+    : super self::_Gc&A&Empty::•()
+    ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+  synthetic constructor •() → self::Gi<self::Gi::T>
+    : super self::_Gi&A&Empty::•()
+    ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hff<self::Hff::T>
+    : super self::A::•()
+    ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hfc<self::Hfc::T>
+    : super self::A::•()
+    ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcf<self::Hcf::T>
+    : super self::A::•()
+    ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcc<self::Hcc::T>
+    : super self::A::•()
+    ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Hii<self::Hii::T>
+    : super core::Object::•()
+    ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iafc<self::Iafc::T>
+    : super self::A::•()
+    ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iacf<self::Iacf::T>
+    : super self::A::•()
+    ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Ifac<self::Ifac::T>
+    : super self::A::•()
+    ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Ifca<self::Ifca::T>
+    : super self::A::•()
+    ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Icaf<self::Icaf::T>
+    : super self::A::•()
+    ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Icfa<self::Icfa::T>
+    : super self::A::•()
+    ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfff<self::Jfff::T>
+    : super core::Object::•()
+    ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jffc<self::Jffc::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+    : super core::Object::•()
+    ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcff<self::Jcff::T>
+    : super core::Object::•()
+    ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+    : super core::Object::•()
+    ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccf<self::Jccf::T>
+    : super core::Object::•()
+    ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccc<self::Jccc::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.transformed.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.transformed.expect
new file mode 100644
index 0000000..87ac80d7
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.transformed.expect
@@ -0,0 +1,343 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+  synthetic constructor •() → self::Empty
+    : super core::Object::•()
+    ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bc<self::Bc::T>
+    : super core::Object::•()
+    ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bi<self::Bi::T>
+    : super core::Object::•()
+    ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Cc<self::Cc::T>
+    : super core::Object::•()
+    ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ci<self::Ci::T>
+    : super core::Object::•()
+    ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::D<self::D::T>
+    : super core::Object::•()
+    ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Dc<self::Dc::T>
+    : super core::Object::•()
+    ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Di<self::Di::T>
+    : super core::Object::•()
+    ;
+}
+class E<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::E<self::E::T>
+    : super core::Object::•()
+    ;
+}
+class Ec<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::Ec<self::Ec::T>
+    : super core::Object::•()
+    ;
+}
+class Ei<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::Ei<self::Ei::T>
+    : super core::Object::•()
+    ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+  synthetic constructor •() → self::F<self::F::T>
+    : super self::_F&Object&A::•()
+    ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+  synthetic constructor •() → self::Fc<self::Fc::T>
+    : super self::_Fc&Object&A::•()
+    ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+  synthetic constructor •() → self::Fi<self::Fi::T>
+    : super self::_Fi&Object&A::•()
+    ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+  synthetic constructor •() → self::G<self::G::T>
+    : super self::_G&A&Empty::•()
+    ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+  synthetic constructor •() → self::Gc<self::Gc::T>
+    : super self::_Gc&A&Empty::•()
+    ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+  synthetic constructor •() → self::Gi<self::Gi::T>
+    : super self::_Gi&A&Empty::•()
+    ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hff<self::Hff::T>
+    : super self::A::•()
+    ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hfc<self::Hfc::T>
+    : super self::A::•()
+    ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcf<self::Hcf::T>
+    : super self::A::•()
+    ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcc<self::Hcc::T>
+    : super self::A::•()
+    ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Hii<self::Hii::T>
+    : super core::Object::•()
+    ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iafc<self::Iafc::T>
+    : super self::A::•()
+    ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iacf<self::Iacf::T>
+    : super self::A::•()
+    ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Ifac<self::Ifac::T>
+    : super self::A::•()
+    ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Ifca<self::Ifca::T>
+    : super self::A::•()
+    ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Icaf<self::Icaf::T>
+    : super self::A::•()
+    ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Icfa<self::Icfa::T>
+    : super self::A::•()
+    ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfff<self::Jfff::T>
+    : super core::Object::•()
+    ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jffc<self::Jffc::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+    : super core::Object::•()
+    ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcff<self::Jcff::T>
+    : super core::Object::•()
+    ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+    : super core::Object::•()
+    ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccf<self::Jccf::T>
+    : super core::Object::•()
+    ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccc<self::Jccc::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.outline.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.outline.expect
new file mode 100644
index 0000000..86bc0e3
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.outline.expect
@@ -0,0 +1,305 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+  synthetic constructor •() → self::Empty
+    ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bc<self::Bc::T>
+    ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bi<self::Bi::T>
+    ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Cc<self::Cc::T>
+    ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ci<self::Ci::T>
+    ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::D<self::D::T>
+    : super core::Object::•()
+    ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Dc<self::Dc::T>
+    : super core::Object::•()
+    ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Di<self::Di::T>
+    : super core::Object::•()
+    ;
+}
+class E<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::E<self::E::T>
+    ;
+}
+class Ec<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::Ec<self::Ec::T>
+    ;
+}
+class Ei<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::Ei<self::Ei::T>
+    ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+  synthetic constructor •() → self::F<self::F::T>
+    ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+  synthetic constructor •() → self::Fc<self::Fc::T>
+    ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+  synthetic constructor •() → self::Fi<self::Fi::T>
+    ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+    ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+  synthetic constructor •() → self::G<self::G::T>
+    ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+    ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+  synthetic constructor •() → self::Gc<self::Gc::T>
+    ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+    ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+  synthetic constructor •() → self::Gi<self::Gi::T>
+    ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hff<self::Hff::T>
+    ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hfc<self::Hfc::T>
+    ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcf<self::Hcf::T>
+    ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcc<self::Hcc::T>
+    ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Hii<self::Hii::T>
+    ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iafc<self::Iafc::T>
+    ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iacf<self::Iacf::T>
+    ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Ifac<self::Ifac::T>
+    ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Ifca<self::Ifca::T>
+    ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Icaf<self::Icaf::T>
+    ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Icfa<self::Icfa::T>
+    ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfff<self::Jfff::T>
+    ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jffc<self::Jffc::T>
+    ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+    ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+    ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcff<self::Jcff::T>
+    ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+    ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccf<self::Jccf::T>
+    ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccc<self::Jccc::T>
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.expect
new file mode 100644
index 0000000..74cdea4
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.expect
@@ -0,0 +1,343 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+  synthetic constructor •() → self::Empty
+    : super core::Object::•()
+    ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bc<self::Bc::T>
+    : super core::Object::•()
+    ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bi<self::Bi::T>
+    : super core::Object::•()
+    ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Cc<self::Cc::T>
+    : super core::Object::•()
+    ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ci<self::Ci::T>
+    : super core::Object::•()
+    ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::D<self::D::T>
+    : super core::Object::•()
+    ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Dc<self::Dc::T>
+    : super core::Object::•()
+    ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Di<self::Di::T>
+    : super core::Object::•()
+    ;
+}
+class E<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::E<self::E::T>
+    : super core::Object::•()
+    ;
+}
+class Ec<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::Ec<self::Ec::T>
+    : super core::Object::•()
+    ;
+}
+class Ei<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::Ei<self::Ei::T>
+    : super core::Object::•()
+    ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+  synthetic constructor •() → self::F<self::F::T>
+    : super self::_F&Object&A::•()
+    ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+  synthetic constructor •() → self::Fc<self::Fc::T>
+    : super self::_Fc&Object&A::•()
+    ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+  synthetic constructor •() → self::Fi<self::Fi::T>
+    : super self::_Fi&Object&A::•()
+    ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+  synthetic constructor •() → self::G<self::G::T>
+    : super self::_G&A&Empty::•()
+    ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+  synthetic constructor •() → self::Gc<self::Gc::T>
+    : super self::_Gc&A&Empty::•()
+    ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+  synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+  synthetic constructor •() → self::Gi<self::Gi::T>
+    : super self::_Gi&A&Empty::•()
+    ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hff<self::Hff::T>
+    : super self::A::•()
+    ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hfc<self::Hfc::T>
+    : super self::A::•()
+    ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcf<self::Hcf::T>
+    : super self::A::•()
+    ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcc<self::Hcc::T>
+    : super self::A::•()
+    ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Hii<self::Hii::T>
+    : super core::Object::•()
+    ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iafc<self::Iafc::T>
+    : super self::A::•()
+    ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iacf<self::Iacf::T>
+    : super self::A::•()
+    ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Ifac<self::Ifac::T>
+    : super self::A::•()
+    ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Ifca<self::Ifca::T>
+    : super self::A::•()
+    ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Icaf<self::Icaf::T>
+    : super self::A::•()
+    ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Icfa<self::Icfa::T>
+    : super self::A::•()
+    ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfff<self::Jfff::T>
+    : super core::Object::•()
+    ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jffc<self::Jffc::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+    : super core::Object::•()
+    ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcff<self::Jcff::T>
+    : super core::Object::•()
+    ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+    : super core::Object::•()
+    ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccf<self::Jccf::T>
+    : super core::Object::•()
+    ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccc<self::Jccc::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
new file mode 100644
index 0000000..87ac80d7
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
@@ -0,0 +1,343 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+//       ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+  synthetic constructor •() → self::Empty
+    : super core::Object::•()
+    ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bc<self::Bc::T>
+    : super core::Object::•()
+    ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Bi<self::Bi::T>
+    : super core::Object::•()
+    ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Cc<self::Cc::T>
+    : super core::Object::•()
+    ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Ci<self::Ci::T>
+    : super core::Object::•()
+    ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::D<self::D::T>
+    : super core::Object::•()
+    ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Dc<self::Dc::T>
+    : super core::Object::•()
+    ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::Di<self::Di::T>
+    : super core::Object::•()
+    ;
+}
+class E<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::E<self::E::T>
+    : super core::Object::•()
+    ;
+}
+class Ec<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::Ec<self::Ec::T>
+    : super core::Object::•()
+    ;
+}
+class Ei<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::Ei<self::Ei::T>
+    : super core::Object::•()
+    ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+  synthetic constructor •() → self::F<self::F::T>
+    : super self::_F&Object&A::•()
+    ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+  synthetic constructor •() → self::Fc<self::Fc::T>
+    : super self::_Fc&Object&A::•()
+    ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+    : super core::Object::•()
+    ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+  synthetic constructor •() → self::Fi<self::Fi::T>
+    : super self::_Fi&Object&A::•()
+    ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+  synthetic constructor •() → self::G<self::G::T>
+    : super self::_G&A&Empty::•()
+    ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+  synthetic constructor •() → self::Gc<self::Gc::T>
+    : super self::_Gc&A&Empty::•()
+    ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+  synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+    : super core::Object::•()
+    ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+  synthetic constructor •() → self::Gi<self::Gi::T>
+    : super self::_Gi&A&Empty::•()
+    ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hff<self::Hff::T>
+    : super self::A::•()
+    ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hfc<self::Hfc::T>
+    : super self::A::•()
+    ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcf<self::Hcf::T>
+    : super self::A::•()
+    ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Hcc<self::Hcc::T>
+    : super self::A::•()
+    ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Hii<self::Hii::T>
+    : super core::Object::•()
+    ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iafc<self::Iafc::T>
+    : super self::A::•()
+    ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+  synthetic constructor •() → self::Iacf<self::Iacf::T>
+    : super self::A::•()
+    ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Ifac<self::Ifac::T>
+    : super self::A::•()
+    ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Ifca<self::Ifca::T>
+    : super self::A::•()
+    ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+  synthetic constructor •() → self::Icaf<self::Icaf::T>
+    : super self::A::•()
+    ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+  synthetic constructor •() → self::Icfa<self::Icfa::T>
+    : super self::A::•()
+    ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfff<self::Jfff::T>
+    : super core::Object::•()
+    ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jffc<self::Jffc::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+    : super core::Object::•()
+    ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+    : super core::Object::•()
+    ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcff<self::Jcff::T>
+    : super core::Object::•()
+    ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+    : super core::Object::•()
+    ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccf<self::Jccf::T>
+    : super core::Object::•()
+    ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Jccc<self::Jccc::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bug33099.dart.outline.expect b/pkg/front_end/testcases/bug33099.dart.outline.expect
index 42a5b20..24e4823 100644
--- a/pkg/front_end/testcases/bug33099.dart.outline.expect
+++ b/pkg/front_end/testcases/bug33099.dart.outline.expect
@@ -12,6 +12,7 @@
 class MyTest extends core::Object {
   synthetic constructor •() → self::MyTest
     ;
+  @self::failingTest
   method foo() → void
     ;
 }
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
index 459d870..6ddb363 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
@@ -8,10 +8,12 @@
   const constructor named(core::List<core::String> l) → self::Foo
     ;
 }
+@self::Foo::•(const <dynamic>[])
 class Bar extends core::Object {
   synthetic constructor •() → self::Bar
     ;
 }
+@self::Foo::named(const <dynamic>[])
 class Baz extends core::Object {
   synthetic constructor •() → self::Baz
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
index b4da95f..62d5559 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
@@ -7,9 +7,12 @@
     ;
 }
 abstract class Bar extends core::Object {
+  @self::Foo::•(const <dynamic>[])
   field dynamic x;
+  @self::Foo::•(const <dynamic>[])
   constructor •() → self::Bar
     ;
+  @self::Foo::•(const <dynamic>[])
   abstract method f() → void;
 }
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/inference/override_equals.dart.outline.expect b/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
index bf42edb..41bfd6e 100644
--- a/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
@@ -5,6 +5,7 @@
 class NullEquality extends core::Object {
   synthetic constructor •() → self::NullEquality
     ;
+  @core::override
   operator ==(core::Object other) → core::Null
     ;
 }
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart b/pkg/front_end/testcases/interface_contravariant_from_class.dart
similarity index 93%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart
rename to pkg/front_end/testcases/interface_contravariant_from_class.dart
index fc4ec48..0b50e14 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/*@testedFeatures=checks*/
 library test;
 
 typedef void F<T>(T t);
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.hierarchy.expect
similarity index 79%
copy from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect
copy to pkg/front_end/testcases/interface_contravariant_from_class.dart.hierarchy.expect
index 6f7dc10..c84fdc2 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.hierarchy.expect
@@ -56,11 +56,9 @@
 
 C:
   superclasses:
-    Object
-      -> B<F<T>>
-  interfaces: I<F<T>>
+    B
+  interfaces:
   classMembers:
-    B.f
     Object.toString
     Object.runtimeType
     Object._simpleInstanceOf
@@ -72,16 +70,3 @@
     Object._simpleInstanceOfTrue
     Object.==
   classSetters:
-  interfaceMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.expect
new file mode 100644
index 0000000..cc045f3
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f(core::int x) → self::B::T {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.transformed.expect
new file mode 100644
index 0000000..cc045f3
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.transformed.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f(core::int x) → self::B::T {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.outline.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.outline.expect
new file mode 100644
index 0000000..31e0650
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.outline.expect
@@ -0,0 +1,33 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    ;
+  method f(core::int x) → self::B::T
+    ;
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    ;
+  abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    ;
+}
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.expect
new file mode 100644
index 0000000..cc045f3
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f(core::int x) → self::B::T {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.transformed.expect
new file mode 100644
index 0000000..cc045f3
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.transformed.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f(core::int x) → self::B::T {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart
similarity index 93%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart
rename to pkg/front_end/testcases/interface_covariantImpl_from_class.dart
index bf9a66b..a06fc2d 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/*@testedFeatures=checks*/
 library test;
 
 typedef void F<T>(T t);
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.hierarchy.expect
similarity index 79%
copy from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect
copy to pkg/front_end/testcases/interface_covariantImpl_from_class.dart.hierarchy.expect
index 6f7dc10..c84fdc2 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.hierarchy.expect
@@ -56,11 +56,9 @@
 
 C:
   superclasses:
-    Object
-      -> B<F<T>>
-  interfaces: I<F<T>>
+    B
+  interfaces:
   classMembers:
-    B.f
     Object.toString
     Object.runtimeType
     Object._simpleInstanceOf
@@ -72,16 +70,3 @@
     Object._simpleInstanceOfTrue
     Object.==
   classSetters:
-  interfaceMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.expect
new file mode 100644
index 0000000..b886daa
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.transformed.expect
new file mode 100644
index 0000000..b886daa
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.transformed.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.outline.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.outline.expect
new file mode 100644
index 0000000..3e3646c
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.outline.expect
@@ -0,0 +1,33 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    ;
+  method f((self::B::T) → void x, core::int y) → void
+    ;
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    ;
+}
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.expect
new file mode 100644
index 0000000..b886daa
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.transformed.expect
new file mode 100644
index 0000000..b886daa
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.transformed.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart
similarity index 94%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart
rename to pkg/front_end/testcases/interface_covariantInterface_from_class.dart
index 3b2bac1..010f354 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/*@testedFeatures=checks*/
 library test;
 
 typedef void F<T>(T t);
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.hierarchy.expect
similarity index 94%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect
rename to pkg/front_end/testcases/interface_covariantInterface_from_class.dart.hierarchy.expect
index 6f7dc10..c43a8c7 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.hierarchy.expect
@@ -18,6 +18,24 @@
     Object.==
   classSetters:
 
+A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    A.f
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
 B:
   superclasses:
     Object
@@ -56,11 +74,9 @@
 
 C:
   superclasses:
-    Object
-      -> B<F<T>>
-  interfaces: I<F<T>>
+    B
+  interfaces:
   classMembers:
-    B.f
     Object.toString
     Object.runtimeType
     Object._simpleInstanceOf
@@ -72,16 +88,3 @@
     Object._simpleInstanceOfTrue
     Object.==
   classSetters:
-  interfaceMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.expect
new file mode 100644
index 0000000..e275052
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.expect
@@ -0,0 +1,48 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+//       ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.transformed.expect
new file mode 100644
index 0000000..e275052
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.transformed.expect
@@ -0,0 +1,48 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+//       ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.outline.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.outline.expect
new file mode 100644
index 0000000..c7028ce
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.outline.expect
@@ -0,0 +1,46 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+//       ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    ;
+  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    ;
+  method f((self::B::T) → void x, core::int y) → void
+    ;
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    ;
+}
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.expect
new file mode 100644
index 0000000..e275052
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.expect
@@ -0,0 +1,48 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+//       ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.transformed.expect
new file mode 100644
index 0000000..e275052
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.transformed.expect
@@ -0,0 +1,48 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+//       ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+  method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T>
+    : super core::Object::•()
+    ;
+  abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/issue37027.dart b/pkg/front_end/testcases/issue37027.dart
new file mode 100644
index 0000000..385e2a4
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+class C {
+  final Set<int> s;
+  C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/issue37027.dart.hierarchy.expect b/pkg/front_end/testcases/issue37027.dart.hierarchy.expect
new file mode 100644
index 0000000..d7772a1
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.hierarchy.expect
@@ -0,0 +1,37 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+C:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    C.s
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
diff --git a/pkg/front_end/testcases/issue37027.dart.legacy.expect b/pkg/front_end/testcases/issue37027.dart.legacy.expect
new file mode 100644
index 0000000..653b194
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.legacy.expect
@@ -0,0 +1,22 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/issue37027.dart:6:46: Error: Unexpected token 'if'.
+//   C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+//                                              ^^
+//
+// pkg/front_end/testcases/issue37027.dart:6:27: Error: Unexpected token 'for'.
+//   C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+//                           ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  final field core::Set<core::int> s;
+  constructor •(core::List<core::int> ell) → self::C
+    : self::C::s = <dynamic, dynamic>{}, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/issue37027.dart.legacy.transformed.expect b/pkg/front_end/testcases/issue37027.dart.legacy.transformed.expect
new file mode 100644
index 0000000..653b194
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.legacy.transformed.expect
@@ -0,0 +1,22 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/issue37027.dart:6:46: Error: Unexpected token 'if'.
+//   C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+//                                              ^^
+//
+// pkg/front_end/testcases/issue37027.dart:6:27: Error: Unexpected token 'for'.
+//   C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+//                           ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  final field core::Set<core::int> s;
+  constructor •(core::List<core::int> ell) → self::C
+    : self::C::s = <dynamic, dynamic>{}, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/issue37027.dart.outline.expect b/pkg/front_end/testcases/issue37027.dart.outline.expect
new file mode 100644
index 0000000..dc4999b
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.outline.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  final field core::Set<core::int> s;
+  constructor •(core::List<core::int> ell) → self::C
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/issue37027.dart.strong.expect b/pkg/front_end/testcases/issue37027.dart.strong.expect
new file mode 100644
index 0000000..2387135
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.strong.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class C extends core::Object {
+  final field core::Set<core::int> s;
+  constructor •(core::List<core::int> ell) → self::C
+    : self::C::s = block {
+      final core::Set<core::int> #t1 = col::LinkedHashSet::•<core::int>();
+      for (core::int e in ell)
+        if(e.{core::int::isOdd})
+          #t1.{core::Set::add}(2.{core::num::*}(e));
+    } =>#t1, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/issue37027.dart.strong.transformed.expect b/pkg/front_end/testcases/issue37027.dart.strong.transformed.expect
new file mode 100644
index 0000000..2387135
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class C extends core::Object {
+  final field core::Set<core::int> s;
+  constructor •(core::List<core::int> ell) → self::C
+    : self::C::s = block {
+      final core::Set<core::int> #t1 = col::LinkedHashSet::•<core::int>();
+      for (core::int e in ell)
+        if(e.{core::int::isOdd})
+          #t1.{core::Set::add}(2.{core::num::*}(e));
+    } =>#t1, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/metadata_enum.dart.outline.expect b/pkg/front_end/testcases/metadata_enum.dart.outline.expect
index 6fd993b..1ecf0f8 100644
--- a/pkg/front_end/testcases/metadata_enum.dart.outline.expect
+++ b/pkg/front_end/testcases/metadata_enum.dart.outline.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+@self::a
 class E extends core::Object {
   final field core::int index;
   final field core::String _name;
diff --git a/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect b/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect
index cec02ba..ec64387 100644
--- a/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect
+++ b/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
+@self::a
 class C = self::D with self::E {
   synthetic constructor •() → self::C
     : super self::D::•()
diff --git a/pkg/front_end/testcases/native_as_name.dart.outline.expect b/pkg/front_end/testcases/native_as_name.dart.outline.expect
index 6c2884c..b78f8ae 100644
--- a/pkg/front_end/testcases/native_as_name.dart.outline.expect
+++ b/pkg/front_end/testcases/native_as_name.dart.outline.expect
@@ -21,6 +21,7 @@
 class Y2 extends self::Y1 {
   synthetic constructor •() → self::Y2
     ;
+  @core::override
   get native() → core::String
     ;
 }
diff --git a/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect b/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect
index 9051099..cc16f53 100644
--- a/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect
+++ b/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect
@@ -14,6 +14,7 @@
 class Hest extends core::Object implements self::Bar {
   synthetic constructor •() → self::Hest
     ;
+  @core::override
   method fisk<U extends self::Foo<self::Hest::fisk::U> = dynamic>() → void
     ;
 }
diff --git a/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect
index 6a28c0d..44fbbbc 100644
--- a/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect
@@ -1,5 +1,15 @@
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/rasta/issue_000033.dart:5:2: Warning: Method not found: 'JS'.
+// @JS()
+//  ^^
+//
 import self as self;
 
+@invalid-expression "pkg/front_end/testcases/rasta/issue_000033.dart:5:2: Error: Method not found: 'JS'.
+@JS()
+ ^^"
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect b/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect
index 5b95c2b..dc87a52 100644
--- a/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect
+++ b/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect
@@ -6,6 +6,7 @@
   static field dynamic _redirecting# = <dynamic>[self::Foo::•];
   constructor named(dynamic p) → self::Foo
     ;
+  @self::forFactoryItself
   static factory •(dynamic p) → self::Foo
     let dynamic #redirecting_factory = self::Foo::named in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_36647.dart.legacy.expect
index 9199ba0..b965c9b 100644
--- a/pkg/front_end/testcases/regress/issue_36647.dart.legacy.expect
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.legacy.expect
@@ -19,9 +19,10 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Error: Expected a class or mixin body, but got 'xx'.
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
 // class xxx xx XXX extends XXX {
-//           ^^
+//       ^^^
 //
 // pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
 // class xxx xx XXX extends XXX {
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_36647.dart.legacy.transformed.expect
index 9199ba0..b965c9b 100644
--- a/pkg/front_end/testcases/regress/issue_36647.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.legacy.transformed.expect
@@ -19,9 +19,10 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Error: Expected a class or mixin body, but got 'xx'.
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
 // class xxx xx XXX extends XXX {
-//           ^^
+//       ^^^
 //
 // pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
 // class xxx xx XXX extends XXX {
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect b/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect
index 0a38be0..69a888f 100644
--- a/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect
@@ -19,9 +19,10 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Error: Expected a class or mixin body, but got 'xx'.
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
 // class xxx xx XXX extends XXX {
-//           ^^
+//       ^^^
 //
 // pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
 // class xxx xx XXX extends XXX {
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect b/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect
index 2e470e5..b99e909 100644
--- a/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect
@@ -19,9 +19,10 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Error: Expected a class or mixin body, but got 'xx'.
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
 // class xxx xx XXX extends XXX {
-//           ^^
+//       ^^^
 //
 // pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
 // class xxx xx XXX extends XXX {
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect
index 2e470e5..b99e909 100644
--- a/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect
@@ -19,9 +19,10 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Error: Expected a class or mixin body, but got 'xx'.
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
 // class xxx xx XXX extends XXX {
-//           ^^
+//       ^^^
 //
 // pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
 // class xxx xx XXX extends XXX {
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect
index 4735cfe..69ebf3f 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect
@@ -13,6 +13,7 @@
 import "dart:core" as core;
 
 static const field core::int y = 42;
+@self::y
 static field core::int x;
 static method main() → dynamic {
   core::print(self::y);
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect
index 4735cfe..69ebf3f 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect
@@ -13,6 +13,7 @@
 import "dart:core" as core;
 
 static const field core::int y = 42;
+@self::y
 static field core::int x;
 static method main() → dynamic {
   core::print(self::y);
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect b/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
index 659526a..b13488b 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
@@ -13,6 +13,7 @@
 import "dart:core" as core;
 
 static const field core::int y;
+@self::y
 static field core::int x;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect b/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect
index 4735cfe..69ebf3f 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect
@@ -13,6 +13,7 @@
 import "dart:core" as core;
 
 static const field core::int y = 42;
+@self::y
 static field core::int x;
 static method main() → dynamic {
   core::print(self::y);
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect
index 4735cfe..69ebf3f 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect
@@ -13,6 +13,7 @@
 import "dart:core" as core;
 
 static const field core::int y = 42;
+@self::y
 static field core::int x;
 static method main() → dynamic {
   core::print(self::y);
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart
deleted file mode 100644
index 7797a4a..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/*@testedFeatures=checks*/
-library test;
-
-typedef void F<T>(T t);
-
-void expectTypeError(void callback()) {
-  try {
-    callback();
-    throw 'Expected TypeError, did not occur';
-  } on TypeError {}
-}
-
-void expect(Object value, Object expected) {
-  if (value != expected) {
-    throw 'Expected $expected, got $value';
-  }
-}
-
-class B {
-  F<int> get x {
-    throw 'Should not be reached';
-  }
-
-  void set x(Object value) {
-    throw 'Should not be reached';
-  }
-}
-
-abstract class I<T> {
-  F<T> get x;
-  void set x(Object value);
-}
-
-abstract class M<T> {
-  T get x => f();
-  void set x(Object value) {
-    throw 'Should not be reached';
-  }
-
-  T f();
-}
-
-abstract class C<T> = B with M<F<T>> implements I<T>;
-
-class D extends C<int> {
-  F<int> f() => (int i) {
-        expect(i, 1);
-      };
-}
-
-void test(I<Object> iObj, I<int> iInt) {
-  expectTypeError(() {
-    // iObj.x is expected to return type (Object) -> void, but it returns
-    // (int) -> void (which is a supertype of (Object) -> void), so that's a
-    // type error.
-    var x = iObj. /*@checkReturn=(Object) -> void*/ x;
-  });
-  // iInt.x is expected to return type (int) -> void, and it does.
-  var x = iInt. /*@checkReturn=(int) -> void*/ x;
-  x(1);
-}
-
-void main() {
-  var d = new D();
-  test(d, d);
-}
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.hierarchy.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.hierarchy.expect
deleted file mode 100644
index dc66ff9..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.hierarchy.expect
+++ /dev/null
@@ -1,150 +0,0 @@
-Object:
-  superclasses:
-  interfaces:
-  classMembers:
-    Object._haveSameRuntimeType
-    Object.toString
-    Object.runtimeType
-    Object._toString
-    Object._simpleInstanceOf
-    Object._hashCodeRnd
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._objectHashCode
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-B:
-  superclasses:
-    Object
-  interfaces:
-  classMembers:
-    Object.toString
-    B.x
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-    B.x
-
-I:
-  superclasses:
-    Object
-  interfaces:
-  classMembers:
-    Object.toString
-    I.x
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-    I.x
-
-M:
-  superclasses:
-    Object
-  interfaces:
-  classMembers:
-    M.f
-    Object.toString
-    M.x
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-    M.x
-
-C:
-  superclasses:
-    Object
-      -> B
-  interfaces: M<F<T>>, I<T>
-  classMembers:
-    M.f
-    Object.toString
-    M.x
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-    M.x
-  interfaceMembers:
-    M.f
-    Object.toString
-    M.x
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
-    M.x
-
-D:
-  superclasses:
-    Object
-      -> B
-        -> C<int>
-  interfaces: M<F<int>>, I<int>
-  classMembers:
-    D.f
-    Object.toString
-    M.x
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-    M.x
-  interfaceMembers:
-    D.f
-    Object.toString
-    M.x
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
-    M.x
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.expect
deleted file mode 100644
index 0546d0e..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.expect
+++ /dev/null
@@ -1,72 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B extends core::Object {
-  synthetic constructor •() → self::B
-    : super core::Object::•()
-    ;
-  get x() → (core::int) → void {
-    throw "Should not be reached";
-  }
-  set x(core::Object value) → void {
-    throw "Should not be reached";
-  }
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract get x() → (self::I::T) → void;
-  abstract set x(core::Object value) → void;
-}
-abstract class M<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::M<self::M::T>
-    : super core::Object::•()
-    ;
-  get x() → self::M::T
-    return this.{self::M::f}();
-  set x(core::Object value) → void {
-    throw "Should not be reached";
-  }
-  abstract method f() → self::M::T;
-}
-abstract class C<T extends core::Object = dynamic> = self::B with self::M<(self::C::T) → void> implements self::I<self::C::T> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-class D extends self::C<core::int> {
-  synthetic constructor •() → self::D
-    : super self::C::•()
-    ;
-  method f() → (core::int) → void
-    return (core::int i) → dynamic {
-      self::expect(i, 1);
-    };
-}
-static method expectTypeError(() → void callback) → void {
-  try {
-    callback.call();
-    throw "Expected TypeError, did not occur";
-  }
-  on core::TypeError catch(no-exception-var) {
-  }
-}
-static method expect(core::Object value, core::Object expected) → void {
-  if(!value.==(expected)) {
-    throw "Expected ${expected}, got ${value}";
-  }
-}
-static method test(self::I<core::Object> iObj, self::I<core::int> iInt) → void {
-  self::expectTypeError(() → dynamic {
-    dynamic x = iObj.x;
-  });
-  dynamic x = iInt.x;
-  x.call(1);
-}
-static method main() → void {
-  dynamic d = new self::D::•();
-  self::test(d, d);
-}
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.transformed.expect
deleted file mode 100644
index 839a7dc..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.transformed.expect
+++ /dev/null
@@ -1,78 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B extends core::Object {
-  synthetic constructor •() → self::B
-    : super core::Object::•()
-    ;
-  get x() → (core::int) → void {
-    throw "Should not be reached";
-  }
-  set x(core::Object value) → void {
-    throw "Should not be reached";
-  }
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract get x() → (self::I::T) → void;
-  abstract set x(core::Object value) → void;
-}
-abstract class M<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::M<self::M::T>
-    : super core::Object::•()
-    ;
-  get x() → self::M::T
-    return this.{self::M::f}();
-  set x(core::Object value) → void {
-    throw "Should not be reached";
-  }
-  abstract method f() → self::M::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B implements self::I<self::C::T>, self::M<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-  get x() → (self::C::T) → void
-    return this.{self::M::f}();
-  set x(core::Object value) → void {
-    throw "Should not be reached";
-  }
-  abstract method f() → (self::C::T) → void;
-}
-class D extends self::C<core::int> {
-  synthetic constructor •() → self::D
-    : super self::C::•()
-    ;
-  method f() → (core::int) → void
-    return (core::int i) → dynamic {
-      self::expect(i, 1);
-    };
-}
-static method expectTypeError(() → void callback) → void {
-  try {
-    callback.call();
-    throw "Expected TypeError, did not occur";
-  }
-  on core::TypeError catch(no-exception-var) {
-  }
-}
-static method expect(core::Object value, core::Object expected) → void {
-  if(!value.==(expected)) {
-    throw "Expected ${expected}, got ${value}";
-  }
-}
-static method test(self::I<core::Object> iObj, self::I<core::int> iInt) → void {
-  self::expectTypeError(() → dynamic {
-    dynamic x = iObj.x;
-  });
-  dynamic x = iInt.x;
-  x.call(1);
-}
-static method main() → void {
-  dynamic d = new self::D::•();
-  self::test(d, d);
-}
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.outline.expect
deleted file mode 100644
index e432df6..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.outline.expect
+++ /dev/null
@@ -1,47 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B extends core::Object {
-  synthetic constructor •() → self::B
-    ;
-  get x() → (core::int) → void
-    ;
-  set x(core::Object value) → void
-    ;
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    ;
-  abstract get x() → (self::I::T) → void;
-  abstract set x(core::Object value) → void;
-}
-abstract class M<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::M<self::M::T>
-    ;
-  get x() → self::M::T
-    ;
-  set x(core::Object value) → void
-    ;
-  abstract method f() → self::M::T;
-}
-abstract class C<T extends core::Object = dynamic> = self::B with self::M<(self::C::T) → void> implements self::I<self::C::T> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-class D extends self::C<core::int> {
-  synthetic constructor •() → self::D
-    ;
-  method f() → (core::int) → void
-    ;
-}
-static method expectTypeError(() → void callback) → void
-  ;
-static method expect(core::Object value, core::Object expected) → void
-  ;
-static method test(self::I<core::Object> iObj, self::I<core::int> iInt) → void
-  ;
-static method main() → void
-  ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect
deleted file mode 100644
index 450603a..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect
+++ /dev/null
@@ -1,86 +0,0 @@
-library test;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:39:9: Error: The return type of the method 'M.x' is 'void Function(T)', which does not match the return type, 'void Function(int)', of the overridden method, 'B.x'.
-// Change to a subtype of 'void Function(int)'.
-//   T get x => f();
-//         ^
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:24:14: Context: This is the overridden method ('x').
-//   F<int> get x {
-//              ^
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:47:16: Context: Override was introduced in the mixin application class 'C'.
-// abstract class C<T> = B with M<F<T>> implements I<T>;
-//                ^
-//
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B extends core::Object {
-  synthetic constructor •() → self::B
-    : super core::Object::•()
-    ;
-  get x() → (core::int) → void {
-    throw "Should not be reached";
-  }
-  set x(core::Object value) → void {
-    throw "Should not be reached";
-  }
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract get x() → (self::I::T) → void;
-  abstract set x(core::Object value) → void;
-}
-abstract class M<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::M<self::M::T>
-    : super core::Object::•()
-    ;
-  get x() → self::M::T
-    return this.{self::M::f}();
-  set x(core::Object value) → void {
-    throw "Should not be reached";
-  }
-  abstract method f() → self::M::T;
-}
-abstract class C<T extends core::Object = dynamic> = self::B with self::M<(self::C::T) → void> implements self::I<self::C::T> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-class D extends self::C<core::int> {
-  synthetic constructor •() → self::D
-    : super self::C::•()
-    ;
-  method f() → (core::int) → void
-    return (core::int i) → core::Null {
-      self::expect(i, 1);
-    };
-}
-static method expectTypeError(() → void callback) → void {
-  try {
-    callback.call();
-    throw "Expected TypeError, did not occur";
-  }
-  on core::TypeError catch(no-exception-var) {
-  }
-}
-static method expect(core::Object value, core::Object expected) → void {
-  if(!value.{core::Object::==}(expected)) {
-    throw "Expected ${expected}, got ${value}";
-  }
-}
-static method test(self::I<core::Object> iObj, self::I<core::int> iInt) → void {
-  self::expectTypeError(() → core::Null {
-    (core::Object) → void x = iObj.{self::I::x} as{TypeError} (core::Object) → void;
-  });
-  (core::int) → void x = iInt.{self::I::x} as{TypeError} (core::int) → void;
-  x.call(1);
-}
-static method main() → void {
-  self::D d = new self::D::•();
-  self::test(d, d);
-}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.expect
deleted file mode 100644
index 7d32948..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.expect
+++ /dev/null
@@ -1,23 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f(core::int x) → self::B::T {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.transformed.expect
deleted file mode 100644
index 7d32948..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.transformed.expect
+++ /dev/null
@@ -1,23 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f(core::int x) → self::B::T {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.outline.expect
deleted file mode 100644
index 6b7705e..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.outline.expect
+++ /dev/null
@@ -1,22 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    ;
-  method f(core::int x) → self::B::T
-    ;
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    ;
-  abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    ;
-}
-static method main() → void
-  ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.expect
deleted file mode 100644
index c8ec998..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.expect
+++ /dev/null
@@ -1,24 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f(core::int x) → self::B::T {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-  abstract forwarding-stub method f(core::Object x) → (self::C::T) → void;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.transformed.expect
deleted file mode 100644
index c8ec998..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.transformed.expect
+++ /dev/null
@@ -1,24 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f(core::int x) → self::B::T {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-  abstract forwarding-stub method f(core::Object x) → (self::C::T) → void;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.hierarchy.expect
deleted file mode 100644
index 6f7dc10..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.hierarchy.expect
+++ /dev/null
@@ -1,87 +0,0 @@
-Object:
-  superclasses:
-  interfaces:
-  classMembers:
-    Object._haveSameRuntimeType
-    Object.toString
-    Object.runtimeType
-    Object._toString
-    Object._simpleInstanceOf
-    Object._hashCodeRnd
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._objectHashCode
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-B:
-  superclasses:
-    Object
-  interfaces:
-  classMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-I:
-  superclasses:
-    Object
-  interfaces:
-  classMembers:
-    I.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-C:
-  superclasses:
-    Object
-      -> B<F<T>>
-  interfaces: I<F<T>>
-  classMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-  interfaceMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.expect
deleted file mode 100644
index 5e95811..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.expect
+++ /dev/null
@@ -1,23 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.transformed.expect
deleted file mode 100644
index 5e95811..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.transformed.expect
+++ /dev/null
@@ -1,23 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.outline.expect
deleted file mode 100644
index 5526106..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.outline.expect
+++ /dev/null
@@ -1,22 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    ;
-  method f((self::B::T) → void x, core::int y) → void
-    ;
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    ;
-}
-static method main() → void
-  ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.expect
deleted file mode 100644
index 14a514f..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.expect
+++ /dev/null
@@ -1,25 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-  forwarding-stub method f(generic-covariant-impl ((self::C::T) → void) → void x, core::Object y) → void
-    return super.{self::B::f}(x, y);
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.transformed.expect
deleted file mode 100644
index 14a514f..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.transformed.expect
+++ /dev/null
@@ -1,25 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-  forwarding-stub method f(generic-covariant-impl ((self::C::T) → void) → void x, core::Object y) → void
-    return super.{self::B::f}(x, y);
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.hierarchy.expect
deleted file mode 100644
index dfb9fc6..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.hierarchy.expect
+++ /dev/null
@@ -1,134 +0,0 @@
-Object:
-  superclasses:
-  interfaces:
-  classMembers:
-    Object._haveSameRuntimeType
-    Object.toString
-    Object.runtimeType
-    Object._toString
-    Object._simpleInstanceOf
-    Object._hashCodeRnd
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._objectHashCode
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-A:
-  superclasses:
-    Object
-  interfaces:
-  classMembers:
-    A.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-
-B:
-  Longest path to Object: 2
-  superclasses:
-    Object
-  interfaces: A<F<T>>
-  classMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-  interfaceMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
-
-I:
-  Longest path to Object: 2
-  superclasses:
-    Object
-  interfaces: A<F<T>>
-  classMembers:
-    I.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-  interfaceMembers:
-    I.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
-
-C:
-  Longest path to Object: 3
-  superclasses:
-    Object
-      -> B<F<T>>
-  interfaces: A<F<F<T>>>, I<F<T>>
-  classMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  classSetters:
-  interfaceMembers:
-    B.f
-    Object.toString
-    Object.runtimeType
-    Object._simpleInstanceOf
-    Object._instanceOf
-    Object.noSuchMethod
-    Object._identityHashCode
-    Object.hashCode
-    Object._simpleInstanceOfFalse
-    Object._simpleInstanceOfTrue
-    Object.==
-  interfaceSetters:
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.expect
deleted file mode 100644
index df1249c..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.expect
+++ /dev/null
@@ -1,29 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T>
-    : super core::Object::•()
-    ;
-  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.transformed.expect
deleted file mode 100644
index df1249c..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.transformed.expect
+++ /dev/null
@@ -1,29 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T>
-    : super core::Object::•()
-    ;
-  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.outline.expect
deleted file mode 100644
index c638537..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.outline.expect
+++ /dev/null
@@ -1,27 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T>
-    ;
-  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
-  synthetic constructor •() → self::B<self::B::T>
-    ;
-  method f((self::B::T) → void x, core::int y) → void
-    ;
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
-  synthetic constructor •() → self::I<self::I::T>
-    ;
-  abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    ;
-}
-static method main() → void
-  ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.expect
deleted file mode 100644
index fd2002b..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.expect
+++ /dev/null
@@ -1,30 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T>
-    : super core::Object::•()
-    ;
-  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f(generic-covariant-impl (self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f(generic-covariant-impl (self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-  abstract forwarding-stub method f(generic-covariant-impl ((self::C::T) → void) → void x, core::Object y) → void;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.transformed.expect
deleted file mode 100644
index fd2002b..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.transformed.expect
+++ /dev/null
@@ -1,30 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T>
-    : super core::Object::•()
-    ;
-  abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
-  synthetic constructor •() → self::B<self::B::T>
-    : super core::Object::•()
-    ;
-  method f(generic-covariant-impl (self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
-  synthetic constructor •() → self::I<self::I::T>
-    : super core::Object::•()
-    ;
-  abstract method f(generic-covariant-impl (self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
-  synthetic constructor •() → self::C<self::C::T>
-    : super self::B::•()
-    ;
-  abstract forwarding-stub method f(generic-covariant-impl ((self::C::T) → void) → void x, core::Object y) → void;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 0347606..a32cc66 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -25,6 +25,7 @@
 await: TextSerializationFailure # Was: Pass
 bad_setter_abstract: TextSerializationFailure # Was: Pass
 bad_store: TextSerializationFailure # Was: Pass
+bad_type_variable_uses_in_supertypes: TextSerializationFailure
 bounds_check_depends_on_inference: TextSerializationFailure # Was: Pass
 bug21938: TypeCheckError
 bug30695: TypeCheckError
@@ -670,6 +671,9 @@
 instantiate_to_bound/typedef_omitted_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_raw_in_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_super_bounded_type: TextSerializationFailure # Was: Pass
+interface_contravariant_from_class: TextSerializationFailure
+interface_covariantImpl_from_class: TextSerializationFailure
+interface_covariantInterface_from_class: TextSerializationFailure
 invalid_assignment: TextSerializationFailure # Was: Pass
 invalid_cast: TextSerializationFailure # Was: Pass
 invalid_type: TypeCheckError
@@ -677,6 +681,7 @@
 issue34515: TextSerializationFailure
 issue34899: TypeCheckError
 issue35875: TextSerializationFailure
+issue37027: TextSerializationFailure
 literals: TextSerializationFailure # Was: Pass
 local_generic_function: TextSerializationFailure # Was: Pass
 magic_const: TextSerializationFailure # Was: Pass
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index a3cd069..18b7445 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -192,6 +192,7 @@
     // TODO(ahe): Extend this entry point so it can replace
     // batchEntryPoint.
     new IncrementalCompiler(c);
+    return Future<void>.value();
   });
 }
 
diff --git a/pkg/front_end/tool/fasta_perf.dart b/pkg/front_end/tool/fasta_perf.dart
index bd1ed2c..0ba6da6 100644
--- a/pkg/front_end/tool/fasta_perf.dart
+++ b/pkg/front_end/tool/fasta_perf.dart
@@ -217,7 +217,7 @@
 
   // Note: this method converts the body to kernel, so we skip that here.
   @override
-  finishFunction(annotations, formals, asyncModifier, body) {}
+  finishFunction(formals, asyncModifier, body) {}
 }
 
 // Invoke the fasta kernel generator for the program starting in [entryUri]
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 30a5f5c..0a9e01b 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -192,6 +192,11 @@
   Uri get fileUri;
 }
 
+abstract class Annotatable {
+  List<Expression> get annotations;
+  void addAnnotation(Expression node);
+}
+
 /// Indirection between a reference and its definition.
 ///
 /// There is only one reference object per [NamedNode].
@@ -267,7 +272,8 @@
 // ------------------------------------------------------------------------
 
 @coq
-class Library extends NamedNode implements Comparable<Library>, FileUriNode {
+class Library extends NamedNode
+    implements Annotatable, Comparable<Library>, FileUriNode {
   /// An import path to this library.
   ///
   /// The [Uri] should have the `dart`, `package`, `app`, or `file` scheme.
@@ -721,7 +727,7 @@
 /// rule directly, as doing so can obstruct transformations.  It is possible to
 /// transform a mixin application to become a regular class, and vice versa.
 @coq
-class Class extends NamedNode implements FileUriNode {
+class Class extends NamedNode implements Annotatable, FileUriNode {
   /// Start offset of the class in the source file it comes from.
   ///
   /// Note that this includes annotations if any.
@@ -1086,7 +1092,7 @@
 // ------------------------------------------------------------------------
 
 @coq
-abstract class Member extends NamedNode implements FileUriNode {
+abstract class Member extends NamedNode implements Annotatable, FileUriNode {
   /// End offset in the source file it comes from.
   ///
   /// Valid values are from 0 and up, or -1 ([TreeNode.noOffset]) if the file
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 274942a..c5c5363 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -57,6 +57,15 @@
 
   /// Number semantics to use for this backend.
   NumberSemantics get numberSemantics => NumberSemantics.vm;
+
+  /// Inline control of constant variables. The given constant expression
+  /// is the initializer of a [Field] or [VariableDeclaration] node.
+  /// If this method returns `true`, the variable will be inlined at all
+  /// points of reference and the variable itself removed (unless overridden
+  /// by the `keepFields` or `keepVariables` flag to the constant transformer).
+  /// This method must be deterministic, i.e. it must always return the same
+  /// value for the same constant value and place in the AST.
+  bool shouldInlineConstant(ConstantExpression initializer) => true;
 }
 
 /// A target provides backend-specific options for generating kernel IR.
diff --git a/pkg/modular_test/lib/src/dependency_parser.dart b/pkg/modular_test/lib/src/dependency_parser.dart
deleted file mode 100644
index 51f2460..0000000
--- a/pkg/modular_test/lib/src/dependency_parser.dart
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// This library defines how to read module dependencies from a Yaml
-/// specification. We expect to find specifications written in this format:
-///
-///    dependencies:
-///      b: a
-///      main: [b, expect]
-///
-/// Where:
-///   - Each name corresponds to a module.
-///   - Module names correlate to either a file, a folder, or a package.
-///   - A map entry contains all the dependencies of a module, if any.
-///   - If a module has a single dependency, it can be written as a single
-///     value.
-///
-/// The logic in this library mostly treats these names as strings, separately
-/// `loader.dart` is responsible for validating and attaching this dependency
-/// information to a set of module definitions.
-import 'package:yaml/yaml.dart';
-
-/// Parses [contents] containing a module dependencies specification written in
-/// yaml, and returns a normalized dependency map.
-///
-/// Note: some values in the map may not have a corresponding key. That may be
-/// the case for modules that have no dependencies and modules that are not
-/// specified in [contents] (e.g. modules that are supported by default).
-Map<String, List<String>> parseDependencyMap(String contents) {
-  var spec = loadYaml(contents);
-  if (spec is! YamlMap) {
-    return _invalidSpecification("spec is not a map");
-  }
-  var dependencies = spec['dependencies'];
-  if (dependencies == null) {
-    return _invalidSpecification("no dependencies section");
-  }
-  if (dependencies is! YamlMap) {
-    return _invalidSpecification("dependencies is not a map");
-  }
-
-  Map<String, List<String>> normalizedMap = {};
-  dependencies.forEach((key, value) {
-    if (key is! String) {
-      _invalidSpecification("key: '$key' is not a string");
-    }
-    normalizedMap[key] = [];
-    if (value is String) {
-      normalizedMap[key].add(value);
-    } else if (value is List) {
-      value.forEach((entry) {
-        if (entry is! String) {
-          _invalidSpecification("entry: '$entry' is not a string");
-        }
-        normalizedMap[key].add(entry);
-      });
-    } else {
-      _invalidSpecification(
-          "entry: '$value' is not a string or a list of strings");
-    }
-  });
-  return normalizedMap;
-}
-
-_invalidSpecification(String message) {
-  throw new InvalidSpecificationError(message);
-}
-
-class InvalidSpecificationError extends Error {
-  final String message;
-  InvalidSpecificationError(this.message);
-  String toString() => "Invalid specification: $message";
-}
diff --git a/pkg/modular_test/lib/src/generic_runner.dart b/pkg/modular_test/lib/src/generic_runner.dart
new file mode 100644
index 0000000..7a3786c
--- /dev/null
+++ b/pkg/modular_test/lib/src/generic_runner.dart
@@ -0,0 +1,151 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// A generic test runner that executes a list of tests, logs test results, and
+/// adds sharding support.
+///
+/// This library contains no logic related to the modular_test framework. It is
+/// used to help integrate tests with our test infrastructure.
+// TODO(sigmund): this library should move somewhere else.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+/// A generic test.
+abstract class Test {
+  /// Unique test name.
+  String get name;
+
+  /// Run the actual test.
+  Future<void> run();
+}
+
+class RunnerOptions {
+  /// Name of the test suite being run.
+  String suiteName;
+
+  /// Configuration name to use when writing result logs.
+  String configurationName;
+
+  /// Filter used to only run tests that match the filter name.
+  String filter;
+
+  /// Where log files are emitted.
+  ///
+  /// Note that all shards currently emit the same filenames, so two shards
+  /// shouldn't be given the same [logDir] otherwise they will overwrite each
+  /// other's log files.
+  Uri logDir;
+
+  /// Of [shards], which shard is currently being executed.
+  int shard;
+
+  /// How many shards will be used to run a suite.
+  int shards;
+
+  /// Whether to print verbose information.
+  bool verbose;
+
+  /// Template used to help developers reproduce the issue.
+  ///
+  /// The following substitutions are made:
+  ///   * %executable is replaced with `Platform.executable`
+  ///   * %script is replaced with the current `Platform.script`
+  ///   * %name is replaced with the test name.
+  String reproTemplate;
+}
+
+class _TestOutcome {
+  /// Unique test name.
+  String name;
+
+  /// Whether, after running the test, the test matches its expectations. Null
+  /// before the test is executed.
+  bool matchedExpectations;
+
+  /// Additional output emitted by the test, only used when expectations don't
+  /// match and more details need to be provided.
+  String output;
+
+  /// Time used to run the test.
+  Duration elapsedTime;
+}
+
+Future<void> runSuite<T>(List<Test> tests, RunnerOptions options) async {
+  if (options.filter == null) {
+    if (options.logDir == null) {
+      print('warning: no output directory provided, logs wont be emitted.');
+    }
+    if (options.configurationName == null) {
+      print('warning: please provide a configuration name.');
+    }
+  }
+  var sortedTests = tests.toList()..sort((a, b) => a.name.compareTo(b.name));
+  List<_TestOutcome> testOutcomes = [];
+  int shard = options.shard;
+  int shards = options.shards;
+  for (int i = 0; i < sortedTests.length; i++) {
+    if (shards > 1 && i % shards != shard) continue;
+    var test = sortedTests[i];
+    var name = test.name;
+    if (options.verbose) stdout.write('$name: ');
+    if (options.filter != null && !name.contains(options.filter)) {
+      if (options.verbose) stdout.write('skipped\n');
+      continue;
+    }
+
+    var watch = new Stopwatch()..start();
+    var outcome = new _TestOutcome()..name = test.name;
+    try {
+      await test.run();
+      if (options.verbose) stdout.write('pass\n');
+      outcome.matchedExpectations = true;
+    } catch (e, st) {
+      var repro = options.reproTemplate
+          .replaceAll('%executable', Platform.resolvedExecutable)
+          .replaceAll('%script', Platform.script.path)
+          .replaceAll('%name', test.name);
+      outcome.matchedExpectations = false;
+      outcome.output = 'uncaught exception: $e\n$st\nTo repro run:\n  $repro';
+      if (options.verbose) stdout.write('fail\n${outcome.output}');
+    }
+    watch.stop();
+    outcome.elapsedTime = watch.elapsed;
+    testOutcomes.add(outcome);
+  }
+
+  if (options.logDir == null) return;
+
+  List<String> results = [];
+  List<String> logs = [];
+  for (int i = 0; i < testOutcomes.length; i++) {
+    var test = testOutcomes[i];
+    final record = jsonEncode({
+      'name': '${options.suiteName}/${test.name}',
+      'configuration': options.configurationName,
+      'suite': options.suiteName,
+      'test_name': test.name,
+      'time_ms': test.elapsedTime.inMilliseconds,
+      'expected': 'Pass',
+      'result': test.matchedExpectations ? 'Pass' : 'Fail',
+      'matches': test.matchedExpectations,
+    });
+    results.add(record);
+    if (!test.matchedExpectations) {
+      final log = jsonEncode({
+        'name': '${options.suiteName}/${test.name}',
+        'configuration': options.configurationName,
+        'result': test.matchedExpectations ? 'Pass' : 'Fail',
+        'log': test.output,
+      });
+      logs.add(log);
+    }
+  }
+
+  File.fromUri(options.logDir.resolve('results.json'))
+      .writeAsStringSync(results.map((s) => '$s\n').join());
+  File.fromUri(options.logDir.resolve('logs.json'))
+      .writeAsStringSync(logs.map((s) => '$s\n').join());
+}
diff --git a/pkg/modular_test/lib/src/io_pipeline.dart b/pkg/modular_test/lib/src/io_pipeline.dart
index ed77f2d..21c57b6 100644
--- a/pkg/modular_test/lib/src/io_pipeline.dart
+++ b/pkg/modular_test/lib/src/io_pipeline.dart
@@ -22,53 +22,110 @@
   /// Assets created on previous steps of the pipeline should be available under
   /// `root.resolveUri(toUri(module, dataId))` and the output of this step
   /// should be stored under `root.resolveUri(toUri(module, resultKind))`.
-  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri);
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags);
 }
 
 class IOPipeline extends Pipeline<IOModularStep> {
-  /// A folder per step. The key is the data id produced by a specific step.
+  /// Folder that holds the results of each step during the run of the pipeline.
   ///
-  /// This contains internal state used during the run of the pipeline, but is
-  /// expected to be null before and after the pipeline is executed.
-  Map<DataId, Uri> _tmpFolders;
-  Map<DataId, Uri> get tmpFoldersForTesting => _tmpFolders;
-  bool saveFoldersForTesting;
+  /// This value is usually null before and after the pipeline runs, but will be
+  /// non-null in two cases:
+  ///
+  ///  * for testing purposes when using [saveIntermediateResultsForTesting].
+  ///
+  ///  * to share results across pipeline runs when using [cacheSharedModules].
+  ///
+  /// When using [cacheSharedModules] the pipeline will only reuse data for
+  /// modules that are known to be shared (e.g. shared packages and sdk
+  /// libraries), and not modules that are test specific. File names will be
+  /// specific enough so that we can keep separate the artifacts created from
+  /// running tools under different configurations (with different flags).
+  Uri _resultsFolderUri;
+  Uri get resultFolderUriForTesting => _resultsFolderUri;
 
-  IOPipeline(List<IOModularStep> steps, {this.saveFoldersForTesting: false})
-      : super(steps);
+  /// A unique number to denote the current modular test configuration.
+  ///
+  /// When using [cacheSharedModules], a test can resuse the output of a
+  /// previous run of this pipeline if that output was generated with the same
+  /// configuration.
+  int _currentConfiguration;
+
+  final ConfigurationRegistry _registry;
+
+  /// Whether to keep alive the temporary folder used to store intermediate
+  /// results in order to inspect it later in test.
+  final bool saveIntermediateResultsForTesting;
+
+  IOPipeline(List<IOModularStep> steps,
+      {this.saveIntermediateResultsForTesting: false,
+      bool cacheSharedModules: false})
+      : _registry = cacheSharedModules ? new ConfigurationRegistry() : null,
+        super(steps, cacheSharedModules);
 
   @override
   Future<void> run(ModularTest test) async {
-    assert(_tmpFolders == null);
-    _tmpFolders = {};
+    var resultsDir = null;
+    if (_resultsFolderUri == null) {
+      resultsDir = await Directory.systemTemp.createTemp('modular_test_res-');
+      _resultsFolderUri = resultsDir.uri;
+    }
+    if (cacheSharedModules) {
+      _currentConfiguration = _registry.computeConfigurationId(test);
+    }
     await super.run(test);
-    if (!saveFoldersForTesting) {
-      for (var folder in _tmpFolders.values) {
-        await Directory.fromUri(folder).delete(recursive: true);
-      }
-      _tmpFolders = null;
+    if (resultsDir != null &&
+        !saveIntermediateResultsForTesting &&
+        !cacheSharedModules) {
+      await resultsDir.delete(recursive: true);
+      _resultsFolderUri = null;
+    }
+    if (!saveIntermediateResultsForTesting) {
+      _currentConfiguration = null;
+    }
+  }
+
+  /// Delete folders that were kept around either because of
+  /// [saveIntermediateResultsForTesting] or because of [cacheSharedModules].
+  Future<void> cleanup() async {
+    if (_resultsFolderUri == null) return;
+    if (saveIntermediateResultsForTesting || cacheSharedModules) {
+      await Directory.fromUri(_resultsFolderUri).delete(recursive: true);
+      _resultsFolderUri = null;
     }
   }
 
   @override
   Future<void> runStep(IOModularStep step, Module module,
-      Map<Module, Set<DataId>> visibleData) async {
-    // Since data ids are unique throughout the pipeline, we use the first
-    // result data id as a hint for the name of the temporary folder of a step.
-    var stepFolder;
-    for (var dataId in step.resultData) {
-      stepFolder ??=
-          await Directory.systemTemp.createTemp('modular_test_${dataId}-');
-      _tmpFolders[dataId] ??=
-          (await Directory.systemTemp.createTemp('modular_test_${dataId}_res-'))
-              .uri;
+      Map<Module, Set<DataId>> visibleData, List<String> flags) async {
+    if (cacheSharedModules && module.isShared) {
+      // If all expected outputs are already available, skip the step.
+      bool allCachedResultsFound = true;
+      for (var dataId in step.resultData) {
+        var cachedFile = File.fromUri(_resultsFolderUri
+            .resolve(_toFileName(module, dataId, configSpecific: true)));
+        if (!await cachedFile.exists()) {
+          allCachedResultsFound = false;
+          break;
+        }
+      }
+      if (allCachedResultsFound) {
+        step.notifyCached(module);
+        return;
+      }
     }
+
+    // Each step is executed in a separate folder.  To make it easier to debug
+    // issues, we include one of the step data ids in the name of the folder.
+    var stepId = step.resultData.first;
+    var stepFolder =
+        await Directory.systemTemp.createTemp('modular_test_${stepId}-');
     for (var module in visibleData.keys) {
       for (var dataId in visibleData[module]) {
-        var filename = "${module.name}.${dataId.name}";
-        var assetUri = _tmpFolders[dataId].resolve(filename);
-        await File.fromUri(assetUri)
-            .copy(stepFolder.uri.resolve(filename).toFilePath());
+        var assetUri = _resultsFolderUri
+            .resolve(_toFileName(module, dataId, configSpecific: true));
+        await File.fromUri(assetUri).copy(
+            stepFolder.uri.resolve(_toFileName(module, dataId)).toFilePath());
       }
     }
     if (step.needsSources) {
@@ -81,19 +138,31 @@
     }
 
     await step.execute(module, stepFolder.uri,
-        (Module m, DataId id) => Uri.parse("${m.name}.${id.name}"));
+        (Module m, DataId id) => Uri.parse(_toFileName(m, id)), flags);
 
     for (var dataId in step.resultData) {
       var outputFile =
-          File.fromUri(stepFolder.uri.resolve("${module.name}.${dataId.name}"));
+          File.fromUri(stepFolder.uri.resolve(_toFileName(module, dataId)));
       if (!await outputFile.exists()) {
         throw StateError(
             "Step '${step.runtimeType}' didn't produce an output file");
       }
-      await outputFile.copy(_tmpFolders[dataId]
-          .resolve("${module.name}.${dataId.name}")
+      await outputFile.copy(_resultsFolderUri
+          .resolve(_toFileName(module, dataId, configSpecific: true))
           .toFilePath());
     }
     await stepFolder.delete(recursive: true);
   }
+
+  String _toFileName(Module module, DataId dataId,
+      {bool configSpecific: false}) {
+    var prefix =
+        cacheSharedModules && configSpecific && _currentConfiguration != null
+            ? _currentConfiguration
+            : '';
+    return "$prefix${module.name}.${dataId.name}";
+  }
+
+  String configSpecificResultFileNameForTesting(Module module, DataId dataId) =>
+      _toFileName(module, dataId, configSpecific: true);
 }
diff --git a/pkg/modular_test/lib/src/loader.dart b/pkg/modular_test/lib/src/loader.dart
index ce00e49..b73da9b 100644
--- a/pkg/modular_test/lib/src/loader.dart
+++ b/pkg/modular_test/lib/src/loader.dart
@@ -17,11 +17,11 @@
 ///       [defaultPackagesInput]. The list of packages provided is expected to
 ///       be disjoint with those in [defaultPackagesInput].
 ///   * a modules.yaml file: a specification of dependencies between modules.
-///     The format is described in `dependencies_parser.dart`.
+///     The format is described in `test_specification_parser.dart`.
 import 'dart:io';
 import 'dart:convert';
 import 'suite.dart';
-import 'dependency_parser.dart';
+import 'test_specification_parser.dart';
 import 'find_sdk_root.dart';
 
 import 'package:package_config/packages_file.dart' as package_config;
@@ -39,16 +39,25 @@
   Uri root = await findRoot();
   Map<String, Uri> defaultPackages =
       package_config.parse(_defaultPackagesInput, root);
-  Map<String, Module> modules = {};
-  String spec;
+  Module sdkModule = await _createSdkModule(root);
+  Map<String, Module> modules = {'sdk': sdkModule};
+  String specString;
   Module mainModule;
   Map<String, Uri> packages = {};
-  await for (var entry in folder.list(recursive: false)) {
+  var entries = folder.listSync(recursive: false).toList()
+    // Sort to avoid dependency on file system order.
+    ..sort(_compareFileSystemEntity);
+  for (var entry in entries) {
     var entryUri = entry.uri;
     if (entry is File) {
       var fileName = entryUri.path.substring(testUri.path.length);
       if (fileName.endsWith('.dart')) {
         var moduleName = fileName.substring(0, fileName.indexOf('.dart'));
+        if (moduleName == 'sdk') {
+          return _invalidTest("The file '$fileName' defines a module called "
+              "'$moduleName' which conflicts with the sdk module "
+              "that is provided by default.");
+        }
         if (defaultPackages.containsKey(moduleName)) {
           return _invalidTest("The file '$fileName' defines a module called "
               "'$moduleName' which conflicts with a package by the same name "
@@ -69,12 +78,17 @@
         List<int> packagesBytes = await entry.readAsBytes();
         packages = package_config.parse(packagesBytes, entryUri);
       } else if (fileName == 'modules.yaml') {
-        spec = await entry.readAsString();
+        specString = await entry.readAsString();
       }
     } else {
       assert(entry is Directory);
       var path = entryUri.path;
       var moduleName = path.substring(testUri.path.length, path.length - 1);
+      if (moduleName == 'sdk') {
+        return _invalidTest("The folder '$moduleName' defines a module "
+            "which conflicts with the sdk module "
+            "that is provided by default.");
+      }
       if (defaultPackages.containsKey(moduleName)) {
         return _invalidTest("The folder '$moduleName' defines a module "
             "which conflicts with a package by the same name "
@@ -88,7 +102,7 @@
           packageBase: Uri.parse('$moduleName/'));
     }
   }
-  if (spec == null) {
+  if (specString == null) {
     return _invalidTest("modules.yaml file is missing");
   }
   if (mainModule == null) {
@@ -97,12 +111,16 @@
 
   _addDefaultPackageEntries(packages, defaultPackages);
   await _addModulePerPackage(packages, modules);
-  _attachDependencies(parseDependencyMap(spec), modules);
-  _attachDependencies(parseDependencyMap(_defaultPackagesSpec), modules);
+  TestSpecification spec = parseTestSpecification(specString);
+  _attachDependencies(spec.dependencies, modules);
+  _attachDependencies(
+      parseTestSpecification(_defaultPackagesSpec).dependencies, modules);
+  _addSdkDependencies(modules, sdkModule);
   _detectCyclesAndRemoveUnreachable(modules, mainModule);
   var sortedModules = modules.values.toList()
     ..sort((a, b) => a.name.compareTo(b.name));
-  return new ModularTest(sortedModules, mainModule);
+  var sortedFlags = spec.flags.toList()..sort();
+  return new ModularTest(sortedModules, mainModule, sortedFlags);
 }
 
 /// Returns all source files recursively found in a folder as relative URIs.
@@ -142,6 +160,15 @@
   });
 }
 
+/// Make every module depend on the sdk module.
+void _addSdkDependencies(Map<String, Module> modules, Module sdkModule) {
+  for (var module in modules.values) {
+    if (module != sdkModule) {
+      module.dependencies.add(sdkModule);
+    }
+  }
+}
+
 void _addDefaultPackageEntries(
     Map<String, Uri> packages, Map<String, Uri> defaultPackages) {
   for (var name in defaultPackages.keys) {
@@ -169,11 +196,35 @@
       // module that is part of the test (package name and module name should
       // match).
       modules[packageName] = Module(packageName, [], rootUri, sources,
-          isPackage: true, packageBase: Uri.parse('lib/'));
+          isPackage: true, packageBase: Uri.parse('lib/'), isShared: true);
     }
   }
 }
 
+Future<Module> _createSdkModule(Uri root) async {
+  List<Uri> sources = [Uri.parse('sdk/lib/libraries.json')];
+
+  // Include all dart2js, ddc, vm library sources and patch files.
+  // Note: we don't extract the list of files from the libraries.json because
+  // it doesn't list files that are transitively imported.
+  var sdkLibrariesAndPatchesRoots = [
+    'sdk/lib/',
+    'runtime/lib/',
+    'runtime/bin/',
+    'pkg/dev_compiler/tool/input_sdk/',
+  ];
+  for (var path in sdkLibrariesAndPatchesRoots) {
+    var dir = Directory.fromUri(root.resolve(path));
+    await for (var file in dir.list(recursive: true)) {
+      if (file is File && file.path.endsWith(".dart")) {
+        sources.add(Uri.parse(file.uri.path.substring(root.path.length)));
+      }
+    }
+  }
+  sources..sort((a, b) => a.path.compareTo(b.path));
+  return Module('sdk', [], root, sources, isSdk: true, isShared: true);
+}
+
 /// Trim the set of modules, and detect cycles while we are at it.
 _detectCyclesAndRemoveUnreachable(Map<String, Module> modules, Module main) {
   Set<Module> visiting = {};
@@ -244,3 +295,20 @@
   InvalidTestError(this.message);
   String toString() => "Invalid test: $message";
 }
+
+/// Comparator to sort directories before files.
+int _compareFileSystemEntity(FileSystemEntity a, FileSystemEntity b) {
+  if (a is Directory) {
+    if (b is Directory) {
+      return a.path.compareTo(b.path);
+    } else {
+      return -1;
+    }
+  } else {
+    if (b is Directory) {
+      return 1;
+    } else {
+      return a.path.compareTo(b.path);
+    }
+  }
+}
diff --git a/pkg/modular_test/lib/src/memory_pipeline.dart b/pkg/modular_test/lib/src/memory_pipeline.dart
index 9ad5c43..d97586c 100644
--- a/pkg/modular_test/lib/src/memory_pipeline.dart
+++ b/pkg/modular_test/lib/src/memory_pipeline.dart
@@ -13,8 +13,11 @@
 typedef SourceProvider = String Function(Uri);
 
 abstract class MemoryModularStep extends ModularStep {
-  Future<Map<DataId, Object>> execute(Module module,
-      SourceProvider sourceProvider, ModuleDataProvider dataProvider);
+  Future<Map<DataId, Object>> execute(
+      Module module,
+      SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider,
+      List<String> flags);
 }
 
 class MemoryPipeline extends Pipeline<MemoryModularStep> {
@@ -27,20 +30,60 @@
   /// A copy of [_result] at the time the pipeline last finished running.
   Map<Module, Map<DataId, Object>> resultsForTesting;
 
-  MemoryPipeline(this._sources, List<MemoryModularStep> steps) : super(steps);
+  final ConfigurationRegistry _registry;
+
+  /// Cache of results when [cacheSharedModules] is true
+  final List<Map<Module, Map<DataId, Object>>> _resultCache;
+
+  MemoryPipeline(this._sources, List<MemoryModularStep> steps,
+      {bool cacheSharedModules: false})
+      : _registry = cacheSharedModules ? new ConfigurationRegistry() : null,
+        _resultCache = cacheSharedModules ? [] : null,
+        super(steps, cacheSharedModules);
 
   @override
   Future<void> run(ModularTest test) async {
-    assert(_results == null);
     _results = {};
+    Map<Module, Map<DataId, Object>> cache = null;
+    if (cacheSharedModules) {
+      int id = _registry.computeConfigurationId(test);
+      if (id < _resultCache.length) {
+        cache = _resultCache[id];
+      } else {
+        assert(id == _resultCache.length);
+        _resultCache.add(cache = {});
+      }
+      _results.addAll(cache);
+    }
     await super.run(test);
     resultsForTesting = _results;
+    if (cacheSharedModules) {
+      for (var module in _results.keys) {
+        if (module.isShared) {
+          cache[module] = _results[module];
+        }
+      }
+    }
     _results = null;
   }
 
   @override
   Future<void> runStep(MemoryModularStep step, Module module,
-      Map<Module, Set<DataId>> visibleData) async {
+      Map<Module, Set<DataId>> visibleData, List<String> flags) async {
+    if (cacheSharedModules && module.isShared) {
+      bool allCachedResultsFound = true;
+      for (var dataId in step.resultData) {
+        if (_results[module] == null || _results[module][dataId] == null) {
+          allCachedResultsFound = false;
+          break;
+        }
+      }
+      if (allCachedResultsFound) {
+        step.notifyCached(module);
+        return;
+      }
+    }
+
     Map<Module, Map<DataId, Object>> inputData = {};
     visibleData.forEach((module, dataIdSet) {
       inputData[module] = {};
@@ -58,7 +101,8 @@
     Map<DataId, Object> result = await step.execute(
         module,
         (Uri uri) => inputSources[uri],
-        (Module m, DataId id) => inputData[m][id]);
+        (Module m, DataId id) => inputData[m][id],
+        flags);
     for (var dataId in step.resultData) {
       (_results[module] ??= {})[dataId] = result[dataId];
     }
diff --git a/pkg/modular_test/lib/src/pipeline.dart b/pkg/modular_test/lib/src/pipeline.dart
index 64e08a7..c55f2f9 100644
--- a/pkg/modular_test/lib/src/pipeline.dart
+++ b/pkg/modular_test/lib/src/pipeline.dart
@@ -48,6 +48,9 @@
       this.moduleDataNeeded: const [],
       this.resultData,
       this.onlyOnMain: false});
+
+  /// Notifies that the step was not executed, but cached instead.
+  void notifyCached(Module module) {}
 }
 
 /// An object to uniquely identify modular data produced by a modular step.
@@ -63,9 +66,13 @@
 }
 
 abstract class Pipeline<S extends ModularStep> {
+  /// Whether to cache the result of shared modules (e.g. shard packages and sdk
+  /// libraries) when multiple tests are run by this pipeline.
+  final bool cacheSharedModules;
+
   final List<S> steps;
 
-  Pipeline(this.steps) {
+  Pipeline(this.steps, this.cacheSharedModules) {
     _validate();
   }
 
@@ -114,7 +121,7 @@
     // TODO(sigmund): validate that [ModularTest] has no cycles.
     Map<Module, Set<DataId>> computedData = {};
     for (var step in steps) {
-      await _recursiveRun(step, test.mainModule, computedData, {}, {});
+      await _recursiveRun(step, test.mainModule, computedData, {}, test.flags);
     }
   }
 
@@ -122,22 +129,22 @@
       S step,
       Module module,
       Map<Module, Set<DataId>> computedData,
-      Set<Module> seen,
-      Set<Module> parentDependencies) async {
-    if (!seen.add(module)) return;
-    parentDependencies.add(module);
-    Set<Module> transitiveDependencies = {};
+      Map<Module, Set<Module>> transitiveDependencies,
+      List<String> flags) async {
+    if (transitiveDependencies.containsKey(module)) return;
+    var deps = transitiveDependencies[module] = {};
     for (var dependency in module.dependencies) {
       await _recursiveRun(
-          step, dependency, computedData, seen, transitiveDependencies);
+          step, dependency, computedData, transitiveDependencies, flags);
+      deps.add(dependency);
+      deps.addAll(transitiveDependencies[dependency]);
     }
-    parentDependencies.addAll(transitiveDependencies);
 
     if (step.onlyOnMain && !module.isMain) return;
     // Include only requested data from transitive dependencies.
     Map<Module, Set<DataId>> visibleData = {};
 
-    transitiveDependencies.forEach((dep) {
+    deps.forEach((dep) {
       visibleData[dep] = {};
       for (var dataId in step.dependencyDataNeeded) {
         if (computedData[dep].contains(dataId)) {
@@ -151,12 +158,12 @@
         visibleData[module].add(dataId);
       }
     }
-    await runStep(step, module, visibleData);
+    await runStep(step, module, visibleData, flags);
     (computedData[module] ??= {}).addAll(step.resultData);
   }
 
-  Future<void> runStep(
-      S step, Module module, Map<Module, Set<DataId>> visibleData);
+  Future<void> runStep(S step, Module module,
+      Map<Module, Set<DataId>> visibleData, List<String> flags);
 }
 
 class InvalidPipelineError extends Error {
diff --git a/pkg/modular_test/lib/src/runner.dart b/pkg/modular_test/lib/src/runner.dart
new file mode 100644
index 0000000..9c3b36f
--- /dev/null
+++ b/pkg/modular_test/lib/src/runner.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// A runner that executes a pipeline on a folder containing modular tests.
+import 'dart:io';
+
+import 'package:args/args.dart';
+import 'package:modular_test/src/io_pipeline.dart';
+import 'package:modular_test/src/loader.dart';
+import 'package:modular_test/src/suite.dart';
+
+import 'generic_runner.dart' as generic;
+
+Uri relativize(Uri uri, Uri base) {
+  return Uri.parse(uri.path.substring(base.path.length));
+}
+
+Future<void> runSuite(Uri suiteFolder, String suiteName, Options options,
+    IOPipeline pipeline) async {
+  var dir = Directory.fromUri(suiteFolder);
+  var entries = (await dir.list(recursive: false).toList())
+      .where((e) => e is Directory)
+      .map((e) => new _PipelineTest(e.uri, suiteFolder, options, pipeline))
+      .toList();
+
+  generic.runSuite(
+      entries,
+      new generic.RunnerOptions()
+        ..suiteName = suiteName
+        ..configurationName = options.configurationName
+        ..filter = options.filter
+        ..logDir = options.outputDirectory
+        ..shard = options.shard
+        ..shards = options.shards
+        ..verbose = options.verbose
+        ..reproTemplate = '%executable %script --verbose --filter %name');
+  await pipeline.cleanup();
+}
+
+class _PipelineTest implements generic.Test {
+  final String name;
+  final Uri uri;
+  final Options options;
+  final IOPipeline pipeline;
+
+  _PipelineTest(this.uri, Uri suiteFolder, this.options, this.pipeline)
+      // Use the name of the folder as the test name by trimming out the prefix
+      // from the suite and the trailing `/`.
+      : name = uri.path.substring(suiteFolder.path.length, uri.path.length - 1);
+
+  Future<void> run() async {
+    ModularTest test = await loadTest(uri);
+    if (options.verbose) print(test.debugString());
+    await pipeline.run(test);
+  }
+}
+
+class Options {
+  bool showSkipped = false;
+  bool verbose = false;
+  String filter = null;
+  int shards = 1;
+  int shard = 1;
+  String configurationName;
+  Uri outputDirectory;
+
+  static Options parse(List<String> args) {
+    var parser = new ArgParser()
+      ..addFlag('verbose',
+          abbr: 'v',
+          defaultsTo: false,
+          help: 'print detailed information about the test and modular steps')
+      ..addFlag('show-skipped',
+          defaultsTo: false,
+          help: 'print the name of the tests skipped by the filtering option')
+      ..addOption('filter',
+          help: 'only run tests containing this filter as a substring')
+      ..addOption('shards',
+          help: 'total number of shards a suite is going to be split into.',
+          defaultsTo: '1')
+      ..addOption('shard',
+          help: 'which shard this script is executing. This should be between 0'
+              ' and `shards - 1`.')
+      ..addOption('output-directory',
+          help: 'location where to emit the jsonl result and log files')
+      ..addOption('configuration-name',
+          help: 'configuration name to use for emitting jsonl result files.');
+    ArgResults argResults = parser.parse(args);
+    int shards = int.tryParse(argResults['shards']) ?? 1;
+    int shard;
+    if (shards > 1) {
+      shard = int.tryParse(argResults['shard']) ?? 1;
+      if (shard <= 0 || shard >= shards) {
+        print('Error: shard should be between 0 and ${shards - 1},'
+            ' but got $shard');
+        exit(1);
+      }
+    }
+    Uri toUri(s) => s == null ? null : Uri.base.resolve(s);
+    return Options()
+      ..showSkipped = argResults['show-skipped']
+      ..verbose = argResults['verbose']
+      ..filter = argResults['filter']
+      ..shards = shards
+      ..shard = shard
+      ..configurationName = argResults['configuration-name']
+      ..outputDirectory = toUri(argResults['output-directory']);
+  }
+}
diff --git a/pkg/modular_test/lib/src/suite.dart b/pkg/modular_test/lib/src/suite.dart
index 506349b..281c381 100644
--- a/pkg/modular_test/lib/src/suite.dart
+++ b/pkg/modular_test/lib/src/suite.dart
@@ -13,8 +13,23 @@
   /// The module containing the main entry method.
   final Module mainModule;
 
-  ModularTest(this.modules, this.mainModule)
-      : assert(mainModule != null && modules.length > 0);
+  /// Flags provided to tools that compile and execute the test.
+  final List<String> flags;
+
+  ModularTest(this.modules, this.mainModule, this.flags) {
+    if (mainModule == null) {
+      throw ArgumentError("main module was null");
+    }
+    if (flags == null) {
+      throw ArgumentError("flags was null");
+    }
+    if (modules == null || modules.length == 0) {
+      throw ArgumentError("modules cannot be null or empty");
+    }
+    for (var module in modules) {
+      module._validate();
+    }
+  }
 
   String debugString() => modules.map((m) => m.debugString()).join('\n');
 }
@@ -43,6 +58,9 @@
   /// package name matches the module name.
   bool isPackage;
 
+  /// Whether this module represents part of the sdk.
+  bool isSdk;
+
   /// When [isPackage], the base where all package URIs are resolved against.
   /// Stored as a relative [Uri] from [rootUri].
   final Uri packageBase;
@@ -50,16 +68,56 @@
   /// Whether this is the main entry module of a test.
   bool isMain;
 
+  /// Whether this module is test specific or shared across tests. Usually this
+  /// will be true only for the SDK and shared packages like `package:expect`.
+  bool isShared;
+
   Module(this.name, this.dependencies, this.rootUri, this.sources,
       {this.mainSource,
       this.isPackage: false,
       this.isMain: false,
-      this.packageBase}) {
+      this.packageBase,
+      this.isShared: false,
+      this.isSdk: false}) {
     if (!_validModuleName.hasMatch(name)) {
       throw ArgumentError("invalid module name: $name");
     }
   }
 
+  void _validate() {
+    if (!isPackage && !isShared && !isSdk) return;
+
+    // Note: we validate this now and not in the constructor because loader.dart
+    // may update `isPackage` after the module is created.
+    if (isSdk && isPackage) {
+      throw InvalidModularTestError("invalid module: $name is an sdk "
+          "module but was also marked as a package module.");
+    }
+
+    for (var dependency in dependencies) {
+      if (isPackage && !dependency.isPackage && !dependency.isSdk) {
+        throw InvalidModularTestError("invalid dependency: $name is a package "
+            "but it depends on ${dependency.name}, which is not.");
+      }
+      if (isShared && !dependency.isShared) {
+        throw InvalidModularTestError(
+            "invalid dependency: $name is a shared module "
+            "but it depends on ${dependency.name}, which is not.");
+      }
+      if (isSdk) {
+        // TODO(sigmund): we should allow to split sdk modules in smaller
+        // pieces. This requires a bit of work:
+        // - allow to compile subsets of the sdk (see #30957 regarding
+        //   extraRequiredLibraries in CFE)
+        // - add logic to specify sdk dependencies.
+        throw InvalidModularTestError(
+            "invalid dependency: $name is an sdk module that depends on  "
+            "${dependency.name}, but sdk modules are not expected to "
+            "have dependencies.");
+      }
+    }
+  }
+
   @override
   String toString() => '[module $name]';
 
@@ -70,7 +128,11 @@
     buffer.write(': ');
     buffer.write(isPackage ? 'package' : '(not package)');
     buffer.write(', deps: {${dependencies.map((d) => d.name).join(", ")}}');
-    buffer.write(', sources: {${sources.map((u) => "$u").join(', ')}}');
+    if (isSdk) {
+      buffer.write(', sources: {...omitted ${sources.length} sources...}');
+    } else {
+      buffer.write(', sources: {${sources.map((u) => "$u").join(', ')}}');
+    }
     return '$buffer';
   }
 }
@@ -87,3 +149,28 @@
   module.dependencies.forEach(helper);
   return deps;
 }
+
+/// A registry that can map a test configuration to a simple id.
+///
+/// This is used to help determine whether two tests are run with the same set
+/// of flags (the same configuration), and thus pipelines could reuse the
+/// results of shared modules from the first test when running the second test.
+class ConfigurationRegistry {
+  Map<String, int> _configurationId = {};
+
+  /// Compute an id to identify the configuration of a modular test.
+  ///
+  /// A configuration is defined in terms of the set of flags provided to a
+  /// test. If two test provided to this registry share the same set of flags,
+  /// the resulting ids are the same. Similarly, if the flags are different,
+  /// their ids will be different as well.
+  int computeConfigurationId(ModularTest test) {
+    return _configurationId[test.flags.join(' ')] ??= _configurationId.length;
+  }
+}
+
+class InvalidModularTestError extends Error {
+  final String message;
+  InvalidModularTestError(this.message);
+  String toString() => "Invalid modular test: $message";
+}
diff --git a/pkg/modular_test/lib/src/test_specification_parser.dart b/pkg/modular_test/lib/src/test_specification_parser.dart
new file mode 100644
index 0000000..d0eed3d
--- /dev/null
+++ b/pkg/modular_test/lib/src/test_specification_parser.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This library defines how to read a test specification from a Yaml
+/// file. We expect specifications written in this format:
+///
+///    dependencies:
+///      b: a
+///      main: [b, expect]
+///    flags:
+///      - constant-update-2018
+///
+/// Where the dependencies section describe how modules depend on one another,
+/// and the flags section show what flags are needed to run that specific test.
+///
+/// When defining dependencies:
+///   - Each name corresponds to a module.
+///   - Module names correlate to either a file, a folder, or a package.
+///   - A map entry contains all the dependencies of a module, if any.
+///   - If a module has a single dependency, it can be written as a single
+///     value.
+///
+/// The logic in this library mostly treats these names as strings, separately
+/// `loader.dart` is responsible for validating and attaching this dependency
+/// information to a set of module definitions.
+///
+/// The framework is agnostic of what the flags are, but at this time we only
+/// use the name of experimental language features. These are then used to
+/// decide what options to pass to the tools that compile and run the tests.
+import 'package:yaml/yaml.dart';
+
+/// Parses [contents] containing a module dependencies specification written in
+/// yaml, and returns a [TestSpecification].
+TestSpecification parseTestSpecification(String contents) {
+  var spec = loadYaml(contents);
+  if (spec is! YamlMap) {
+    return _invalidSpecification("spec is not a map");
+  }
+  var dependencies = spec['dependencies'];
+  if (dependencies == null) {
+    return _invalidSpecification("no dependencies section");
+  }
+  if (dependencies is! YamlMap) {
+    return _invalidSpecification("dependencies is not a map");
+  }
+
+  Map<String, List<String>> normalizedMap = {};
+  dependencies.forEach((key, value) {
+    if (key is! String) {
+      _invalidSpecification("key: '$key' is not a string");
+    }
+    normalizedMap[key] = [];
+    if (value is String) {
+      normalizedMap[key].add(value);
+    } else if (value is List) {
+      value.forEach((entry) {
+        if (entry is! String) {
+          _invalidSpecification("entry: '$entry' is not a string");
+        }
+        normalizedMap[key].add(entry);
+      });
+    } else {
+      _invalidSpecification(
+          "entry: '$value' is not a string or a list of strings");
+    }
+  });
+
+  List<String> normalizedFlags = [];
+  dynamic flags = spec['flags'];
+  if (flags is String) {
+    normalizedFlags.add(flags);
+  } else if (flags is List) {
+    normalizedFlags.addAll(flags.cast<String>());
+  } else if (flags != null) {
+    _invalidSpecification(
+        "flags: '$flags' expected to be string or list of strings");
+  }
+  return new TestSpecification(normalizedFlags, normalizedMap);
+}
+
+/// Data specifying details about a modular test including dependencies and
+/// flags that are necessary in order to properly run a test.
+///
+class TestSpecification {
+  /// Set of flags necessary to properly run a test.
+  ///
+  /// Usually this contains flags enabling language experiments.
+  final List<String> flags;
+
+  /// Dependencies of the modules that are expected to exist on the test.
+  ///
+  /// Note: some values in the map may not have a corresponding key. That may be
+  /// the case for modules that have no dependencies and modules that are not
+  /// specified explicitly because they are added automatically by the framework
+  /// (for instance, the module of `package:expect` or the sdk itself).
+  final Map<String, List<String>> dependencies;
+
+  TestSpecification(this.flags, this.dependencies);
+}
+
+_invalidSpecification(String message) {
+  throw new InvalidSpecificationError(message);
+}
+
+class InvalidSpecificationError extends Error {
+  final String message;
+  InvalidSpecificationError(this.message);
+  String toString() => "Invalid specification: $message";
+}
diff --git a/pkg/modular_test/test/io_pipeline_test.dart b/pkg/modular_test/test/io_pipeline_test.dart
index dd3d01f..db980f8 100644
--- a/pkg/modular_test/test/io_pipeline_test.dart
+++ b/pkg/modular_test/test/io_pipeline_test.dart
@@ -29,14 +29,17 @@
 
   @override
   Future<Pipeline<IOModularStep>> createPipeline(
-      Map<Uri, String> sources, List<IOModularStep> steps) async {
+      Map<Uri, String> sources, List<IOModularStep> steps,
+      {bool cacheSharedModules: false}) async {
     await Directory.fromUri(testRootUri).create();
     for (var uri in sources.keys) {
       var file = new File.fromUri(uri);
       await file.create(recursive: true);
       await file.writeAsStringSync(sources[uri]);
     }
-    return new IOPipeline(steps, saveFoldersForTesting: true);
+    return new IOPipeline(steps,
+        saveIntermediateResultsForTesting: true,
+        cacheSharedModules: cacheSharedModules);
   }
 
   @override
@@ -83,17 +86,15 @@
 
   @override
   String getResult(covariant IOPipeline pipeline, Module m, DataId dataId) {
-    var folderUri = pipeline.tmpFoldersForTesting[dataId];
-    var file = File.fromUri(folderUri.resolve("${m.name}.${dataId.name}"));
+    var folderUri = pipeline.resultFolderUriForTesting;
+    var file = File.fromUri(folderUri
+        .resolve(pipeline.configSpecificResultFileNameForTesting(m, dataId)));
     return file.existsSync() ? file.readAsStringSync() : null;
   }
 
   @override
-  Future<void> cleanup(Pipeline<IOModularStep> pipeline) async {
-    var folders = (pipeline as IOPipeline).tmpFoldersForTesting.values;
-    for (var folder in folders) {
-      await Directory.fromUri(folder).delete(recursive: true);
-    }
+  Future<void> cleanup(covariant IOPipeline pipeline) async {
+    pipeline.cleanup();
     await Directory.fromUri(testRootUri).delete(recursive: true);
   }
 }
@@ -110,8 +111,8 @@
   SourceOnlyStep(this.action, this.resultId, this.needsSources);
 
   @override
-  Future<void> execute(
-      Module module, Uri root, ModuleDataToRelativeUri toUri) async {
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
     Map<Uri, String> sources = {};
 
     for (var uri in module.sources) {
@@ -122,6 +123,9 @@
     await File.fromUri(root.resolveUri(toUri(module, resultId)))
         .writeAsString(action(sources));
   }
+
+  @override
+  void notifyCached(Module module) {}
 }
 
 class ModuleDataStep implements IOModularStep {
@@ -138,14 +142,17 @@
       : moduleDataNeeded = requestInput ? [inputId] : [];
 
   @override
-  Future<void> execute(
-      Module module, Uri root, ModuleDataToRelativeUri toUri) async {
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
     var inputData = await _readHelper(module, root, inputId, toUri);
     var result =
         inputData == null ? "data for $module was null" : action(inputData);
     await File.fromUri(root.resolveUri(toUri(module, resultId)))
         .writeAsString(result);
   }
+
+  @override
+  void notifyCached(Module module) {}
 }
 
 class TwoOutputStep implements IOModularStep {
@@ -164,8 +171,8 @@
       this.action1, this.action2, this.inputId, this.result1Id, this.result2Id);
 
   @override
-  Future<void> execute(
-      Module module, Uri root, ModuleDataToRelativeUri toUri) async {
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
     var inputData = await _readHelper(module, root, inputId, toUri);
     var result1 =
         inputData == null ? "data for $module was null" : action1(inputData);
@@ -176,6 +183,9 @@
     await File.fromUri(root.resolveUri(toUri(module, result2Id)))
         .writeAsString(result2);
   }
+
+  @override
+  void notifyCached(Module module) {}
 }
 
 class LinkStep implements IOModularStep {
@@ -194,8 +204,8 @@
       : dependencyDataNeeded = requestDependencies ? [depId] : [];
 
   @override
-  Future<void> execute(
-      Module module, Uri root, ModuleDataToRelativeUri toUri) async {
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
     List<String> depsData = [];
     for (var dependency in module.dependencies) {
       var depData = await _readHelper(dependency, root, depId, toUri);
@@ -205,6 +215,9 @@
     await File.fromUri(root.resolveUri(toUri(module, resultId)))
         .writeAsString(action(inputData, depsData));
   }
+
+  @override
+  void notifyCached(Module module) {}
 }
 
 class MainOnlyStep implements IOModularStep {
@@ -223,8 +236,8 @@
       : dependencyDataNeeded = requestDependencies ? [depId] : [];
 
   @override
-  Future<void> execute(
-      Module module, Uri root, ModuleDataToRelativeUri toUri) async {
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
     List<String> depsData = [];
     for (var dependency in computeTransitiveDependencies(module)) {
       var depData = await _readHelper(dependency, root, depId, toUri);
@@ -234,6 +247,9 @@
     await File.fromUri(root.resolveUri(toUri(module, resultId)))
         .writeAsString(action(inputData, depsData));
   }
+
+  @override
+  void notifyCached(Module module) {}
 }
 
 Future<String> _readHelper(Module module, Uri root, DataId dataId,
diff --git a/pkg/modular_test/test/loader/dag/expectation.txt b/pkg/modular_test/test/loader/dag/expectation.txt
index 885c41f..38220ca 100644
--- a/pkg/modular_test/test/loader/dag/expectation.txt
+++ b/pkg/modular_test/test/loader/dag/expectation.txt
@@ -2,27 +2,44 @@
 
 a
   is package? no
-  dependencies: b, c
+  is shared?  no
+  is sdk?  no
+  dependencies: b, c, sdk
   a.dart
 
 b
   is package? no
-  dependencies: d
+  is shared?  no
+  is sdk?  no
+  dependencies: d, sdk
   b.dart
 
 c
   is package? no
-  (no dependencies)
+  is shared?  no
+  is sdk?  no
+  dependencies: sdk
   c.dart
 
 d
   is package? no
-  (no dependencies)
+  is shared?  no
+  is sdk?  no
+  dependencies: sdk
   d/d.dart
   d/e.dart
 
 main
   **main module**
   is package? no
-  dependencies: a, b
+  is shared?  no
+  is sdk?  no
+  dependencies: a, b, sdk
   main.dart
+
+sdk
+  is package? no
+  is shared?  yes
+  is sdk?  yes
+  (no dependencies)
+  (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/dag_with_packages/.packages b/pkg/modular_test/test/loader/dag_with_packages/.packages
index 5f1a721..194aba9 100644
--- a/pkg/modular_test/test/loader/dag_with_packages/.packages
+++ b/pkg/modular_test/test/loader/dag_with_packages/.packages
@@ -1,2 +1,4 @@
 a:a/
+b:b/
+d:d/
 c:c/
diff --git a/pkg/modular_test/test/loader/dag_with_packages/expectation.txt b/pkg/modular_test/test/loader/dag_with_packages/expectation.txt
index df35ba5..961d6b8 100644
--- a/pkg/modular_test/test/loader/dag_with_packages/expectation.txt
+++ b/pkg/modular_test/test/loader/dag_with_packages/expectation.txt
@@ -2,27 +2,44 @@
 
 a
   is package? yes
-  dependencies: b, c
+  is shared?  no
+  is sdk?  no
+  dependencies: b, c, sdk
   a.dart
 
 b
-  is package? no
-  dependencies: d
+  is package? yes
+  is shared?  no
+  is sdk?  no
+  dependencies: d, sdk
   b.dart
 
 c
   is package? yes
-  (no dependencies)
+  is shared?  no
+  is sdk?  no
+  dependencies: sdk
   c.dart
 
 d
-  is package? no
-  (no dependencies)
+  is package? yes
+  is shared?  no
+  is sdk?  no
+  dependencies: sdk
   d/d.dart
   d/e.dart
 
 main
   **main module**
   is package? no
-  dependencies: a, b
+  is shared?  no
+  is sdk?  no
+  dependencies: a, b, sdk
   main.dart
+
+sdk
+  is package? no
+  is shared?  yes
+  is sdk?  yes
+  (no dependencies)
+  (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt b/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt
index cf449f3..48e0849 100644
--- a/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt
+++ b/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt
@@ -2,7 +2,9 @@
 
 expect
   is package? yes
-  dependencies: meta
+  is shared?  yes
+  is sdk?  no
+  dependencies: meta, sdk
   lib/expect.dart
   lib/matchers_lite.dart
   lib/minitest.dart
@@ -10,11 +12,22 @@
 main
   **main module**
   is package? no
-  dependencies: expect
+  is shared?  no
+  is sdk?  no
+  dependencies: expect, sdk
   main.dart
 
 meta
   is package? yes
-  (no dependencies)
+  is shared?  yes
+  is sdk?  no
+  dependencies: sdk
   lib/dart2js.dart
   lib/meta.dart
+
+sdk
+  is package? no
+  is shared?  yes
+  is sdk?  yes
+  (no dependencies)
+  (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/loader_test.dart b/pkg/modular_test/test/loader/loader_test.dart
index 4f5f59c..39b3081 100644
--- a/pkg/modular_test/test/loader/loader_test.dart
+++ b/pkg/modular_test/test/loader/loader_test.dart
@@ -4,34 +4,27 @@
 
 /// Tests that the logic to load, parse, and validate modular tests.
 import 'dart:io';
-import 'package:async_helper/async_helper.dart';
-import 'package:expect/expect.dart';
+
+import 'package:test/test.dart';
 import 'package:modular_test/src/loader.dart';
 import 'package:modular_test/src/suite.dart';
 
 import 'package:args/args.dart';
 
-main(List<String> args) {
+main(List<String> args) async {
   var options = _Options.parse(args);
-  asyncTest(() async {
-    var baseUri = Platform.script.resolve('./');
-    var baseDir = Directory.fromUri(baseUri);
-    await for (var entry in baseDir.list(recursive: false)) {
-      if (entry is Directory) {
-        await _runTest(entry.uri, baseUri, options);
-      }
+  var baseUri = Platform.script.resolve('./');
+  var baseDir = Directory.fromUri(baseUri);
+  await for (var entry in baseDir.list(recursive: false)) {
+    if (entry is Directory) {
+      var dirName = entry.uri.path.substring(baseDir.path.length);
+      test(dirName, () => _runTest(entry.uri, dirName, options),
+          skip: options.filter != null && !dirName.contains(options.filter));
     }
-  });
+  }
 }
 
-Future<void> _runTest(Uri uri, Uri baseDir, _Options options) async {
-  var dirName = uri.path.substring(baseDir.path.length);
-  if (options.filter != null && !dirName.contains(options.filter)) {
-    if (options.showSkipped) print("skipped: $dirName");
-    return;
-  }
-
-  print("testing: $dirName");
+Future<void> _runTest(Uri uri, String dirName, _Options options) async {
   String result;
   String header =
       "# This expectation file is generated by loader_test.dart\n\n";
@@ -44,7 +37,8 @@
 
   var file = File.fromUri(uri.resolve('expectation.txt'));
   if (!options.updateExpectations) {
-    Expect.isTrue(await file.exists(), "expectation.txt file is missing");
+    expect(await file.exists(), isTrue,
+        reason: "expectation.txt file is missing");
     var expectation = await file.readAsString();
     if (expectation != result) {
       print("expectation.txt doesn't match the result of the test. "
@@ -52,8 +46,7 @@
           "   ${Platform.executable} ${Platform.script} "
           "--update --show-update --filter $dirName");
     }
-    Expect.equals(expectation, result);
-    print("  expectation matches result.");
+    expect(expectation, result);
   } else if (await file.exists() && (await file.readAsString() == result)) {
     print("  expectation matches result and was up to date.");
   } else {
@@ -76,10 +69,12 @@
     }
     buffer.write(module.name);
     if (module.isMain) {
-      Expect.equals(test.mainModule, module);
+      expect(test.mainModule, module);
       buffer.write('\n  **main module**');
     }
     buffer.write('\n  is package? ${module.isPackage ? 'yes' : 'no'}');
+    buffer.write('\n  is shared?  ${module.isShared ? 'yes' : 'no'}');
+    buffer.write('\n  is sdk?  ${module.isSdk ? 'yes' : 'no'}');
     if (module.dependencies.isEmpty) {
       buffer.write('\n  (no dependencies)');
     } else {
@@ -89,6 +84,8 @@
 
     if (module.sources.isEmpty) {
       buffer.write('\n  (no sources)');
+    } else if (module.isSdk) {
+      buffer.write('\n  (sdk sources omitted)');
     } else {
       module.sources.forEach((uri) {
         buffer.write('\n  $uri');
@@ -103,7 +100,6 @@
 class _Options {
   bool updateExpectations = false;
   bool showResultOnUpdate = false;
-  bool showSkipped = false;
   String filter = null;
 
   static _Options parse(List<String> args) {
@@ -124,7 +120,6 @@
     return _Options()
       ..updateExpectations = argResults['update']
       ..showResultOnUpdate = argResults['show-update']
-      ..showSkipped = argResults['show-skipped']
       ..filter = argResults['filter'];
   }
 }
diff --git a/pkg/modular_test/test/loader/no_dependencies/expectation.txt b/pkg/modular_test/test/loader/no_dependencies/expectation.txt
index f19449b..8af18d5 100644
--- a/pkg/modular_test/test/loader/no_dependencies/expectation.txt
+++ b/pkg/modular_test/test/loader/no_dependencies/expectation.txt
@@ -3,5 +3,14 @@
 main
   **main module**
   is package? no
-  (no dependencies)
+  is shared?  no
+  is sdk?  no
+  dependencies: sdk
   main.dart
+
+sdk
+  is package? no
+  is shared?  yes
+  is sdk?  yes
+  (no dependencies)
+  (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/tree/expectation.txt b/pkg/modular_test/test/loader/tree/expectation.txt
index f438e22..d2c3d88 100644
--- a/pkg/modular_test/test/loader/tree/expectation.txt
+++ b/pkg/modular_test/test/loader/tree/expectation.txt
@@ -2,27 +2,44 @@
 
 a
   is package? no
-  dependencies: b, c
+  is shared?  no
+  is sdk?  no
+  dependencies: b, c, sdk
   a.dart
 
 b
   is package? no
-  dependencies: d
+  is shared?  no
+  is sdk?  no
+  dependencies: d, sdk
   b.dart
 
 c
   is package? no
-  (no dependencies)
+  is shared?  no
+  is sdk?  no
+  dependencies: sdk
   c.dart
 
 d
   is package? no
-  (no dependencies)
+  is shared?  no
+  is sdk?  no
+  dependencies: sdk
   d/d.dart
   d/e.dart
 
 main
   **main module**
   is package? no
-  dependencies: a
+  is shared?  no
+  is sdk?  no
+  dependencies: a, sdk
   main.dart
+
+sdk
+  is package? no
+  is shared?  yes
+  is sdk?  yes
+  (no dependencies)
+  (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/valid_packages/expectation.txt b/pkg/modular_test/test/loader/valid_packages/expectation.txt
index dab4163..4ef3034 100644
--- a/pkg/modular_test/test/loader/valid_packages/expectation.txt
+++ b/pkg/modular_test/test/loader/valid_packages/expectation.txt
@@ -2,14 +2,18 @@
 
 expect
   is package? yes
-  dependencies: meta
+  is shared?  yes
+  is sdk?  no
+  dependencies: meta, sdk
   lib/expect.dart
   lib/matchers_lite.dart
   lib/minitest.dart
 
 js
   is package? yes
-  (no dependencies)
+  is shared?  yes
+  is sdk?  no
+  dependencies: sdk
   lib/js.dart
   lib/js_util.dart
   lib/src/varargs.dart
@@ -17,11 +21,22 @@
 main
   **main module**
   is package? no
-  dependencies: js, expect
+  is shared?  no
+  is sdk?  no
+  dependencies: js, expect, sdk
   main.dart
 
 meta
   is package? yes
-  (no dependencies)
+  is shared?  yes
+  is sdk?  no
+  dependencies: sdk
   lib/dart2js.dart
   lib/meta.dart
+
+sdk
+  is package? no
+  is shared?  yes
+  is sdk?  yes
+  (no dependencies)
+  (sdk sources omitted)
diff --git a/pkg/modular_test/test/memory_pipeline_test.dart b/pkg/modular_test/test/memory_pipeline_test.dart
index ba406e1..1d4da36 100644
--- a/pkg/modular_test/test/memory_pipeline_test.dart
+++ b/pkg/modular_test/test/memory_pipeline_test.dart
@@ -22,8 +22,10 @@
 
   @override
   FutureOr<Pipeline<MemoryModularStep>> createPipeline(
-      Map<Uri, String> sources, List<MemoryModularStep> steps) {
-    return new MemoryPipeline(sources, steps);
+      Map<Uri, String> sources, List<MemoryModularStep> steps,
+      {bool cacheSharedModules: false}) {
+    return new MemoryPipeline(sources, steps,
+        cacheSharedModules: cacheSharedModules);
   }
 
   @override
@@ -87,14 +89,20 @@
 
   SourceOnlyStep(this.action, this.resultId, this.needsSources);
 
-  Future<Map<DataId, Object>> execute(Module module,
-      SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
+  Future<Map<DataId, Object>> execute(
+      Module module,
+      SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider,
+      List<String> flags) {
     Map<Uri, String> sources = {};
     for (var uri in module.sources) {
       sources[uri] = sourceProvider(module.rootUri.resolveUri(uri));
     }
     return Future.value({resultId: action(sources)});
   }
+
+  @override
+  void notifyCached(Module module) {}
 }
 
 class ModuleDataStep implements MemoryModularStep {
@@ -110,13 +118,19 @@
   ModuleDataStep(this.action, this.inputId, this.resultId, bool requestInput)
       : moduleDataNeeded = requestInput ? [inputId] : [];
 
-  Future<Map<DataId, Object>> execute(Module module,
-      SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
+  Future<Map<DataId, Object>> execute(
+      Module module,
+      SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider,
+      List<String> flags) {
     var inputData = dataProvider(module, inputId) as String;
     if (inputData == null)
       return Future.value({resultId: "data for $module was null"});
     return Future.value({resultId: action(inputData)});
   }
+
+  @override
+  void notifyCached(Module module) {}
 }
 
 class TwoOutputStep implements MemoryModularStep {
@@ -134,8 +148,11 @@
   TwoOutputStep(
       this.action1, this.action2, this.inputId, this.result1Id, this.result2Id);
 
-  Future<Map<DataId, Object>> execute(Module module,
-      SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
+  Future<Map<DataId, Object>> execute(
+      Module module,
+      SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider,
+      List<String> flags) {
     var inputData = dataProvider(module, inputId) as String;
     if (inputData == null)
       return Future.value({
@@ -145,6 +162,9 @@
     return Future.value(
         {result1Id: action1(inputData), result2Id: action2(inputData)});
   }
+
+  @override
+  void notifyCached(Module module) {}
 }
 
 class LinkStep implements MemoryModularStep {
@@ -162,14 +182,20 @@
       bool requestDependencies)
       : dependencyDataNeeded = requestDependencies ? [depId] : [];
 
-  Future<Map<DataId, Object>> execute(Module module,
-      SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
+  Future<Map<DataId, Object>> execute(
+      Module module,
+      SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider,
+      List<String> flags) {
     List<String> depsData = module.dependencies
         .map((d) => dataProvider(d, depId) as String)
         .toList();
     var inputData = dataProvider(module, inputId) as String;
     return Future.value({resultId: action(inputData, depsData)});
   }
+
+  @override
+  void notifyCached(Module module) {}
 }
 
 class MainOnlyStep implements MemoryModularStep {
@@ -187,12 +213,18 @@
       bool requestDependencies)
       : dependencyDataNeeded = requestDependencies ? [depId] : [];
 
-  Future<Map<DataId, Object>> execute(Module module,
-      SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
+  Future<Map<DataId, Object>> execute(
+      Module module,
+      SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider,
+      List<String> flags) {
     List<String> depsData = computeTransitiveDependencies(module)
         .map((d) => dataProvider(d, depId) as String)
         .toList();
     var inputData = dataProvider(module, inputId) as String;
     return Future.value({resultId: action(inputData, depsData)});
   }
+
+  @override
+  void notifyCached(Module module) {}
 }
diff --git a/pkg/modular_test/test/pipeline_common.dart b/pkg/modular_test/test/pipeline_common.dart
index b09e611..7bfbf77 100644
--- a/pkg/modular_test/test/pipeline_common.dart
+++ b/pkg/modular_test/test/pipeline_common.dart
@@ -28,7 +28,8 @@
   /// Creates a pipeline with the given sources and steps. Steps will be created
   /// by other methods in this strategy to ensure they are compatible with to
   /// the pipeline created here.
-  FutureOr<Pipeline<S>> createPipeline(Map<Uri, String> sources, List<S> steps);
+  FutureOr<Pipeline<S>> createPipeline(Map<Uri, String> sources, List<S> steps,
+      {bool cacheSharedModules: false});
 
   /// Create a step that applies [action] on all input files of the module, and
   /// emits a result with the given [id]
@@ -98,15 +99,16 @@
   };
 
   var m1 = Module("a", const [], testStrategy.testRootUri,
-      [Uri.parse("a1.dart"), Uri.parse("a2.dart")]);
+      [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+      isShared: true);
   var m2 = Module("b", [m1], testStrategy.testRootUri,
       [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")]);
   var m3 = Module("c", [m2], testStrategy.testRootUri, [Uri.parse("c.dart")],
       isMain: true);
 
-  var singleModuleInput = ModularTest([m1], m1);
-  var twoModuleInput = ModularTest([m1, m2], m2);
-  var threeModuleInput = ModularTest([m1, m2, m3], m3);
+  var singleModuleInput = ModularTest([m1], m1, []);
+  var twoModuleInput = ModularTest([m1, m2], m2, []);
+  var threeModuleInput = ModularTest([m1, m2, m3], m3, []);
 
   test('can read source data if requested', () async {
     var concatStep =
@@ -310,6 +312,106 @@
     expect(testStrategy.getResult(pipeline, m3, _joinId), "null\nnull\nc c0\n");
     await testStrategy.cleanup(pipeline);
   });
+
+  test('no reuse of existing results if not caching', () async {
+    int i = 1;
+    const counterId = const DataId("counter");
+    const linkId = const DataId("link");
+    // This step is not idempotent, we do this purposely to test whether caching
+    // is taking place.
+    var counterStep = testStrategy.createSourceOnlyStep(
+        action: (_) => '${i++}', resultId: counterId);
+    var linkStep = testStrategy.createLinkStep(
+        action: (String m, List<String> deps) => "${deps.join(',')},$m",
+        inputId: counterId,
+        depId: counterId,
+        resultId: linkId,
+        requestDependenciesData: true);
+    var pipeline = await testStrategy.createPipeline(
+        sources, <S>[counterStep, linkStep],
+        cacheSharedModules: false);
+    await pipeline.run(twoModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, counterId), "1");
+    expect(testStrategy.getResult(pipeline, m2, counterId), "2");
+    expect(testStrategy.getResult(pipeline, m2, linkId), "1,2");
+
+    await pipeline.run(threeModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, counterId), "3");
+    expect(testStrategy.getResult(pipeline, m2, counterId), "4");
+    expect(testStrategy.getResult(pipeline, m2, linkId), "3,4");
+    expect(testStrategy.getResult(pipeline, m3, counterId), "5");
+    expect(testStrategy.getResult(pipeline, m3, linkId), "4,5");
+
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('caching reuses existing results for the same configuration', () async {
+    int i = 1;
+    const counterId = const DataId("counter");
+    const linkId = const DataId("link");
+    var counterStep = testStrategy.createSourceOnlyStep(
+        action: (_) => '${i++}', resultId: counterId);
+    var linkStep = testStrategy.createLinkStep(
+        action: (String m, List<String> deps) => "${deps.join(',')},$m",
+        inputId: counterId,
+        depId: counterId,
+        resultId: linkId,
+        requestDependenciesData: true);
+    var pipeline = await testStrategy.createPipeline(
+        sources, <S>[counterStep, linkStep],
+        cacheSharedModules: true);
+    await pipeline.run(twoModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, counterId), "1");
+    expect(testStrategy.getResult(pipeline, m2, counterId), "2");
+    expect(testStrategy.getResult(pipeline, m2, linkId), "1,2");
+
+    await pipeline.run(threeModuleInput);
+    expect(testStrategy.getResult(pipeline, m1, counterId), "1"); // cached!
+    expect(testStrategy.getResult(pipeline, m2, counterId), "3");
+    expect(testStrategy.getResult(pipeline, m2, linkId), "1,3");
+    expect(testStrategy.getResult(pipeline, m3, counterId), "4");
+    expect(testStrategy.getResult(pipeline, m3, linkId), "3,4");
+
+    await testStrategy.cleanup(pipeline);
+  });
+
+  test('no reuse of existing results on different configurations', () async {
+    int i = 1;
+    const counterId = const DataId("counter");
+    const linkId = const DataId("link");
+    // This step is not idempotent, we do this purposely to test whether caching
+    // is taking place.
+    var counterStep = testStrategy.createSourceOnlyStep(
+        action: (_) => '${i++}', resultId: counterId);
+    var linkStep = testStrategy.createLinkStep(
+        action: (String m, List<String> deps) => "${deps.join(',')},$m",
+        inputId: counterId,
+        depId: counterId,
+        resultId: linkId,
+        requestDependenciesData: true);
+    var pipeline = await testStrategy.createPipeline(
+        sources, <S>[counterStep, linkStep],
+        cacheSharedModules: true);
+    var input1 = ModularTest([m1, m2], m2, []);
+    var input2 = ModularTest([m1, m2], m2, ['--foo']);
+    var input3 = ModularTest([m1, m2], m2, ['--foo']);
+    await pipeline.run(input1);
+    expect(testStrategy.getResult(pipeline, m1, counterId), "1");
+    expect(testStrategy.getResult(pipeline, m2, counterId), "2");
+    expect(testStrategy.getResult(pipeline, m2, linkId), "1,2");
+
+    await pipeline.run(input2);
+    expect(testStrategy.getResult(pipeline, m1, counterId), "3"); // no cache!
+    expect(testStrategy.getResult(pipeline, m2, counterId), "4");
+    expect(testStrategy.getResult(pipeline, m2, linkId), "3,4");
+
+    await pipeline.run(input3);
+    expect(testStrategy.getResult(pipeline, m1, counterId), "3"); // same config
+    expect(testStrategy.getResult(pipeline, m2, counterId), "5");
+    expect(testStrategy.getResult(pipeline, m2, linkId), "3,5");
+
+    await testStrategy.cleanup(pipeline);
+  });
 }
 
 DataId _concatId = const DataId("concat");
diff --git a/pkg/modular_test/test/dependency_parser_test.dart b/pkg/modular_test/test/specification_parser_test.dart
similarity index 63%
rename from pkg/modular_test/test/dependency_parser_test.dart
rename to pkg/modular_test/test/specification_parser_test.dart
index f536282..6940d5e9 100644
--- a/pkg/modular_test/test/dependency_parser_test.dart
+++ b/pkg/modular_test/test/specification_parser_test.dart
@@ -3,46 +3,46 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:test/test.dart';
-import 'package:modular_test/src/dependency_parser.dart';
+import 'package:modular_test/src/test_specification_parser.dart';
 
 main() {
   test('require dependencies section', () {
-    expect(() => parseDependencyMap(""),
+    expect(() => parseTestSpecification(""),
         throwsA(TypeMatcher<InvalidSpecificationError>()));
   });
 
   test('dependencies is a map', () {
-    expect(() => parseDependencyMap("dependencies: []"),
+    expect(() => parseTestSpecification("dependencies: []"),
         throwsA(TypeMatcher<InvalidSpecificationError>()));
   });
 
   test('dependencies can be a string or list of strings', () {
-    parseDependencyMap('''
+    parseTestSpecification('''
           dependencies:
             a: b
           ''');
 
-    parseDependencyMap('''
+    parseTestSpecification('''
           dependencies:
             a: [b, c]
           ''');
 
-    expect(() => parseDependencyMap('''
+    expect(() => parseTestSpecification('''
           dependencies:
             a: 1
           '''), throwsA(TypeMatcher<InvalidSpecificationError>()));
 
-    expect(() => parseDependencyMap('''
+    expect(() => parseTestSpecification('''
           dependencies:
             a: true
           '''), throwsA(TypeMatcher<InvalidSpecificationError>()));
 
-    expect(() => parseDependencyMap('''
+    expect(() => parseTestSpecification('''
           dependencies:
             a: [false]
           '''), throwsA(TypeMatcher<InvalidSpecificationError>()));
 
-    expect(() => parseDependencyMap('''
+    expect(() => parseTestSpecification('''
           dependencies:
             a:
                c: d
@@ -51,14 +51,26 @@
 
   test('result map is normalized', () {
     expect(
-        parseDependencyMap('''
+        parseTestSpecification('''
           dependencies:
             a: [b, c]
             b: d
-            '''),
+            ''').dependencies,
         equals({
           'a': ['b', 'c'],
           'b': ['d'],
         }));
   });
+
+  test('flags are normalized', () {
+    expect(parseTestSpecification('''
+          dependencies: {}
+          flags: "a"
+            ''').flags, equals(["a"]));
+
+    expect(parseTestSpecification('''
+          dependencies: {}
+          flags: ["a"]
+            ''').flags, equals(["a"]));
+  });
 }
diff --git a/pkg/modular_test/test/validate_test.dart b/pkg/modular_test/test/validate_pipeline_test.dart
similarity index 92%
rename from pkg/modular_test/test/validate_test.dart
rename to pkg/modular_test/test/validate_pipeline_test.dart
index 8394dfe..a0b5759 100644
--- a/pkg/modular_test/test/validate_test.dart
+++ b/pkg/modular_test/test/validate_pipeline_test.dart
@@ -27,7 +27,7 @@
     ]);
   });
 
-  test('circular dependency is not allowed', () {
+  test('circular step dependency is not allowed', () {
     var id1 = DataId("data_a");
     expect(
         () => validateSteps([
@@ -78,10 +78,10 @@
 /// An implementation of [Pipeline] that simply validates the steps, but doesn't
 /// do anything else.
 class _NoopPipeline extends Pipeline {
-  _NoopPipeline(List<ModularStep> steps) : super(steps);
+  _NoopPipeline(List<ModularStep> steps) : super(steps, false);
 
   @override
   Future<void> runStep(ModularStep step, Module module,
-          Map<Module, Set<DataId>> visibleData) =>
+          Map<Module, Set<DataId>> visibleData, List<String> flags) =>
       null;
 }
diff --git a/pkg/modular_test/test/validate_suite_test.dart b/pkg/modular_test/test/validate_suite_test.dart
new file mode 100644
index 0000000..f335567
--- /dev/null
+++ b/pkg/modular_test/test/validate_suite_test.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2019, 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.
+
+/// Unit test for validation of modular steps in a pipeline.
+import 'package:test/test.dart';
+import 'package:modular_test/src/suite.dart';
+
+main() {
+  test('module test is not empty', () {
+    expect(
+        () => ModularTest([], null, []), throwsA(TypeMatcher<ArgumentError>()));
+
+    var m = Module("a", [], Uri.parse("app:/"), []);
+    expect(() => ModularTest([], m, []), throwsA(TypeMatcher<ArgumentError>()));
+  });
+
+  test('module test must have a main module', () {
+    var m = Module("a", [], Uri.parse("app:/"), []);
+    expect(() => ModularTest([m], null, []),
+        throwsA(TypeMatcher<ArgumentError>()));
+  });
+
+  test('package must depend on package', () {
+    var m1a = Module("a", const [], Uri.parse("app:/"),
+        [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+        isPackage: false);
+    var m1b = Module("a", const [], Uri.parse("app:/"),
+        [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+        isPackage: true);
+
+    var m2a = Module("b", [m1a], Uri.parse("app:/"),
+        [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+        isPackage: true);
+    var m2b = Module("b", [m1b], Uri.parse("app:/"),
+        [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+        isPackage: true);
+    expect(() => ModularTest([m1a, m2a], m2a, []),
+        throwsA(TypeMatcher<InvalidModularTestError>()));
+    expect(ModularTest([m1b, m2b], m2b, []), isNotNull);
+  });
+
+  test('shared module must depend on shared modules', () {
+    var m1a = Module("a", const [], Uri.parse("app:/"),
+        [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+        isShared: false);
+    var m1b = Module("a", const [], Uri.parse("app:/"),
+        [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+        isShared: true);
+
+    var m2a = Module("b", [m1a], Uri.parse("app:/"),
+        [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+        isShared: true);
+    var m2b = Module("b", [m1b], Uri.parse("app:/"),
+        [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+        isShared: true);
+    expect(() => ModularTest([m1a, m2a], m2a, []),
+        throwsA(TypeMatcher<InvalidModularTestError>()));
+    expect(ModularTest([m1b, m2b], m2b, []), isNotNull);
+  });
+
+  test('sdk module must not have dependencies', () {
+    var m1a = Module("a", const [], Uri.parse("app:/"),
+        [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+        isSdk: false);
+    var m1b = Module("a", const [], Uri.parse("app:/"),
+        [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+        isSdk: true);
+
+    var m2a = Module("b", [m1a], Uri.parse("app:/"),
+        [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+        isSdk: true);
+    var m2b = Module("b", [m1b], Uri.parse("app:/"),
+        [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+        isSdk: true);
+    expect(() => ModularTest([m1a, m2a], m2a, []),
+        throwsA(TypeMatcher<InvalidModularTestError>()));
+    expect(() => ModularTest([m1b, m2b], m2b, []),
+        throwsA(TypeMatcher<InvalidModularTestError>()));
+  });
+
+  test('sdk module cannot be package module', () {
+    var m = Module("a", const [], Uri.parse("app:/"),
+        [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+        isSdk: true);
+    expect(ModularTest([m], m, []), isNotNull);
+
+    m.isPackage = true;
+    expect(() => ModularTest([m], m, []),
+        throwsA(TypeMatcher<InvalidModularTestError>()));
+  });
+}
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 881f093..26698f9 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -24,6 +24,7 @@
 analyzer/test/src/summary/resynthesize_kernel_test: Slow, Pass
 analyzer/test/src/task/strong/checker_test: Slow, Pass
 analyzer_plugin/test/plugin/folding_mixin_test: Slow, Pass
+dev_compiler/test/modular/*: Slow, Pass
 dev_compiler/test/options/*: Skip # test needs fixes
 dev_compiler/test/sourcemap/*: SkipByDesign # Skip sourcemap tests
 dev_compiler/test/sourcemap/testfiles/*: SkipByDesign # Skip dev_compiler codegen tests
@@ -178,10 +179,10 @@
 
 [ $compiler != dart2analyzer && $runtime != vm ]
 dev_compiler/test/*: Skip
-modular_test/test/dependency_parser_test: SkipByDesign
 modular_test/test/find_sdk_root1_test: SkipByDesign
 modular_test/test/io_pipeline_test: SkipByDesign
 modular_test/test/loader/loader_test: SkipByDesign
+modular_test/test/specification_parser_test: SkipByDesign
 modular_test/test/src/find_sdk_root2_test: SkipByDesign
 
 [ $compiler == dart2js && $runtime == chrome && $system == macos ]
diff --git a/pkg/smith/lib/configuration.dart b/pkg/smith/lib/configuration.dart
index 1b1c268..62dbee4 100644
--- a/pkg/smith/lib/configuration.dart
+++ b/pkg/smith/lib/configuration.dart
@@ -8,7 +8,7 @@
 // - "windows" -> "win".
 // - "macos" -> "mac".
 // - toString() on enum classes is just name.
-// - builderTag defaults to empty string, not null.
+// - builderTag and babel default to empty string, not null.
 // Need to migrate test.dart to not expect the above before it can use this.
 
 // READ ME! If you add a new field to this, make sure to add it to
@@ -247,6 +247,7 @@
 
     var configuration = Configuration(
         name, architecture, compiler, mode, runtime, system,
+        babel: stringOption("babel"),
         builderTag: stringOption("builder-tag"),
         vmOptions: stringListOption("vm-options"),
         dart2jsOptions: stringListOption("dart2js-options"),
@@ -260,6 +261,7 @@
         useAnalyzerCfe: boolOption("use-cfe"),
         useAnalyzerFastaParser: boolOption("analyzer-use-fasta-parser"),
         useBlobs: boolOption("use-blobs"),
+        useElf: boolOption("use-elf"),
         useHotReload: boolOption("hot-reload"),
         useHotReloadRollback: boolOption("hot-reload-rollback"),
         useSdk: boolOption("use-sdk"));
@@ -284,13 +286,15 @@
 
   final System system;
 
+  final String babel;
+
   final String builderTag;
 
   final List<String> vmOptions;
 
   final List<String> dart2jsOptions;
 
-  int timeout;
+  final int timeout;
 
   final bool enableAsserts;
 
@@ -313,6 +317,7 @@
 
   // TODO(rnystrom): What is this?
   final bool useBlobs;
+  final bool useElf;
 
   final bool useHotReload;
   final bool useHotReloadRollback;
@@ -321,7 +326,8 @@
 
   Configuration(this.name, this.architecture, this.compiler, this.mode,
       this.runtime, this.system,
-      {String builderTag,
+      {String babel,
+      String builderTag,
       List<String> vmOptions,
       List<String> dart2jsOptions,
       int timeout,
@@ -334,13 +340,15 @@
       bool useAnalyzerCfe,
       bool useAnalyzerFastaParser,
       bool useBlobs,
+      bool useElf,
       bool useHotReload,
       bool useHotReloadRollback,
       bool useSdk})
-      : builderTag = builderTag ?? "",
+      : babel = babel ?? "",
+        builderTag = builderTag ?? "",
         vmOptions = vmOptions ?? <String>[],
         dart2jsOptions = dart2jsOptions ?? <String>[],
-        timeout = timeout,
+        timeout = timeout ?? -1,
         enableAsserts = enableAsserts ?? false,
         isChecked = isChecked ?? false,
         isCsp = isCsp ?? false,
@@ -350,6 +358,7 @@
         useAnalyzerCfe = useAnalyzerCfe ?? false,
         useAnalyzerFastaParser = useAnalyzerFastaParser ?? false,
         useBlobs = useBlobs ?? false,
+        useElf = useElf ?? false,
         useHotReload = useHotReload ?? false,
         useHotReloadRollback = useHotReloadRollback ?? false,
         useSdk = useSdk ?? false;
@@ -362,6 +371,7 @@
       mode == other.mode &&
       runtime == other.runtime &&
       system == other.system &&
+      babel == other.babel &&
       builderTag == other.builderTag &&
       vmOptions.join(" & ") == other.vmOptions.join(" & ") &&
       dart2jsOptions.join(" & ") == other.dart2jsOptions.join(" & ") &&
@@ -375,6 +385,7 @@
       useAnalyzerCfe == other.useAnalyzerCfe &&
       useAnalyzerFastaParser == other.useAnalyzerFastaParser &&
       useBlobs == other.useBlobs &&
+      useElf == other.useElf &&
       useHotReload == other.useHotReload &&
       useHotReloadRollback == other.useHotReloadRollback &&
       useSdk == other.useSdk;
@@ -392,6 +403,7 @@
       mode.hashCode ^
       runtime.hashCode ^
       system.hashCode ^
+      babel.hashCode ^
       builderTag.hashCode ^
       vmOptions.join(" & ").hashCode ^
       dart2jsOptions.join(" & ").hashCode ^
@@ -406,6 +418,7 @@
         useAnalyzerCfe,
         useAnalyzerFastaParser,
         useBlobs,
+        useElf,
         useHotReload,
         useHotReloadRollback,
         useSdk
@@ -423,11 +436,13 @@
     fields.add("runtime: $runtime");
     fields.add("system: $system");
 
-    if (builderTag != "") fields.add("builder-tag: $builderTag");
-    if (vmOptions != "") fields.add("vm-options: [${vmOptions.join(", ")}]");
-    if (dart2jsOptions != "")
+    if (babel.isNotEmpty) fields.add("babel: $babel");
+    if (builderTag.isNotEmpty) fields.add("builder-tag: $builderTag");
+    if (vmOptions.isNotEmpty)
+      fields.add("vm-options: [${vmOptions.join(", ")}]");
+    if (dart2jsOptions.isNotEmpty)
       fields.add("dart2js-options: [${dart2jsOptions.join(", ")}]");
-    if (timeout != 0) fields.add("timeout: $timeout");
+    if (timeout > 0) fields.add("timeout: $timeout");
     if (enableAsserts) fields.add("enable-asserts");
     if (isChecked) fields.add("checked");
     if (isCsp) fields.add("csp");
@@ -458,20 +473,25 @@
     fields.add("runtime: $runtime ${other.runtime}");
     fields.add("system: $system ${other.system}");
 
-    if (builderTag != "" || other.builderTag != "") {
-      var tag = builderTag == "" ? "(none)" : builderTag;
-      var otherTag = other.builderTag == "" ? "(none)" : other.builderTag;
-      fields.add("builder-tag: $tag $otherTag");
+    if (babel.isNotEmpty || other.babel.isNotEmpty) {
+      var ours = babel == "" ? "(none)" : babel;
+      var theirs = other.babel == "" ? "(none)" : other.babel;
+      fields.add("babel: $ours $theirs");
     }
-    if (vmOptions != "" || other.vmOptions != "") {
-      var tag = "[${vmOptions.join(", ")}]";
-      var otherTag = "[${other.vmOptions.join(", ")}]";
-      fields.add("vm-options: $tag $otherTag");
+    if (builderTag.isNotEmpty || other.builderTag.isNotEmpty) {
+      var ours = builderTag == "" ? "(none)" : builderTag;
+      var theirs = other.builderTag == "" ? "(none)" : other.builderTag;
+      fields.add("builder-tag: $ours $theirs");
     }
-    if (dart2jsOptions != "" || other.dart2jsOptions != "") {
-      var tag = "[${dart2jsOptions.join(", ")}]";
-      var otherTag = "[${other.dart2jsOptions.join(", ")}]";
-      fields.add("dart2js-options: $tag $otherTag");
+    if (vmOptions.isNotEmpty || other.vmOptions.isNotEmpty) {
+      var ours = "[${vmOptions.join(", ")}]";
+      var theirs = "[${other.vmOptions.join(", ")}]";
+      fields.add("vm-options: $ours $theirs");
+    }
+    if (dart2jsOptions.isNotEmpty || other.dart2jsOptions.isNotEmpty) {
+      var ours = "[${dart2jsOptions.join(", ")}]";
+      var theirs = "[${other.dart2jsOptions.join(", ")}]";
+      fields.add("dart2js-options: $ours $theirs");
     }
     fields.add("timeout: $timeout ${other.timeout}");
     if (enableAsserts || other.enableAsserts) {
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 619c943..be1e4ee 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -146,7 +146,10 @@
       if (options.bytecode && errors.isEmpty) {
         await runWithFrontEndCompilerContext(script, options, component, () {
           // TODO(alexmarkov): pass environment defines
-          generateBytecode(component);
+          // TODO(alexmarkov): disable source positions and local variables
+          // in VM PRODUCT mode.
+          generateBytecode(component,
+              emitSourcePositions: true, emitLocalVarInfo: true);
         });
       }
 
diff --git a/pkg/vm/lib/bytecode/assembler.dart b/pkg/vm/lib/bytecode/assembler.dart
index b71650b..6401815 100644
--- a/pkg/vm/lib/bytecode/assembler.dart
+++ b/pkg/vm/lib/bytecode/assembler.dart
@@ -8,6 +8,7 @@
 
 import 'dbc.dart';
 import 'exceptions.dart' show ExceptionsTable;
+import 'local_variable_table.dart' show LocalVariableTable;
 import 'source_positions.dart' show SourcePositions;
 
 class Label {
@@ -53,6 +54,7 @@
   // TODO(alexmarkov): figure out more efficient storage for generated bytecode.
   final List<int> bytecode = new List<int>();
   final ExceptionsTable exceptionsTable = new ExceptionsTable();
+  final LocalVariableTable localVariableTable = new LocalVariableTable();
   final SourcePositions sourcePositions = new SourcePositions();
   bool isUnreachable = false;
   int currentSourcePosition = TreeNode.noOffset;
diff --git a/pkg/vm/lib/bytecode/bytecode_serialization.dart b/pkg/vm/lib/bytecode/bytecode_serialization.dart
index 4845307..db9fa71 100644
--- a/pkg/vm/lib/bytecode/bytecode_serialization.dart
+++ b/pkg/vm/lib/bytecode/bytecode_serialization.dart
@@ -386,15 +386,42 @@
   return buf.getFloat64(0, Endian.little);
 }
 
-class NamedEntryStatistics {
-  final String name;
-  int size = 0;
-  int count = 0;
+class PackedUInt30DeltaEncoder {
+  int _last = 0;
 
-  NamedEntryStatistics(this.name);
+  void write(BufferedWriter write, int value) {
+    write.writePackedUInt30(value - _last);
+    _last = value;
+  }
+}
 
-  String toString() => "${name.padRight(40)}:    ${size.toString().padLeft(10)}"
-      "  (count: ${count.toString().padLeft(8)})";
+class PackedUInt30DeltaDecoder {
+  int _last = 0;
+
+  int read(BufferedReader reader) {
+    int value = reader.readPackedUInt30() + _last;
+    _last = value;
+    return value;
+  }
+}
+
+class SLEB128DeltaEncoder {
+  int _last = 0;
+
+  void write(BufferedWriter writer, int value) {
+    writer.writeSLEB128(value - _last);
+    _last = value;
+  }
+}
+
+class SLEB128DeltaDecoder {
+  int _last = 0;
+
+  int read(BufferedReader reader) {
+    int value = reader.readSLEB128() + _last;
+    _last = value;
+    return value;
+  }
 }
 
 class LinkWriter {
@@ -428,6 +455,17 @@
   }
 }
 
+class NamedEntryStatistics {
+  final String name;
+  int size = 0;
+  int count = 0;
+
+  NamedEntryStatistics(this.name);
+
+  String toString() => "${name.padRight(40)}:    ${size.toString().padLeft(10)}"
+      "  (count: ${count.toString().padLeft(8)})";
+}
+
 class BytecodeSizeStatistics {
   static int componentSize = 0;
   static int objectTableSize = 0;
diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart
index 2ee6f20..351a3e7 100644
--- a/pkg/vm/lib/bytecode/dbc.dart
+++ b/pkg/vm/lib/bytecode/dbc.dart
@@ -10,7 +10,7 @@
 /// Before bumping current bytecode version format, make sure that
 /// all users have switched to a VM which is able to consume new
 /// version of bytecode.
-const int currentBytecodeFormatVersion = 7;
+const int currentBytecodeFormatVersion = 9;
 
 /// Version of experimental / bleeding edge bytecode format.
 /// Produced by bytecode generator when --use-future-bytecode-format
diff --git a/pkg/vm/lib/bytecode/declarations.dart b/pkg/vm/lib/bytecode/declarations.dart
index 5fde12c..1d8cfc5 100644
--- a/pkg/vm/lib/bytecode/declarations.dart
+++ b/pkg/vm/lib/bytecode/declarations.dart
@@ -12,6 +12,7 @@
     show currentBytecodeFormatVersion, futureBytecodeFormatVersion;
 import 'disassembler.dart' show BytecodeDisassembler;
 import 'exceptions.dart' show ExceptionsTable;
+import 'local_variable_table.dart' show LocalVariableTable;
 import 'object_table.dart' show ObjectTable, ObjectHandle, NameAndType;
 import 'source_positions.dart' show SourcePositions;
 
@@ -140,10 +141,10 @@
         ((flags & hasCustomScriptFlag) != 0) ? reader.readPackedObject() : null;
     final position = ((flags & hasSourcePositionsFlag) != 0)
         ? reader.readPackedUInt30() - 1
-        : 0;
+        : TreeNode.noOffset;
     final endPosition = ((flags & hasSourcePositionsFlag) != 0)
         ? reader.readPackedUInt30() - 1
-        : 0;
+        : TreeNode.noOffset;
     final initializerCode =
         ((flags & hasInitializerFlag) != 0 && (flags & isStaticFlag) != 0)
             ? reader.readLinkOffset<Code>()
@@ -298,10 +299,10 @@
         ((flags & hasCustomScriptFlag) != 0) ? reader.readPackedObject() : null;
     final position = ((flags & hasSourcePositionsFlag) != 0)
         ? reader.readPackedUInt30() - 1
-        : 0;
+        : TreeNode.noOffset;
     final endPosition = ((flags & hasSourcePositionsFlag) != 0)
         ? reader.readPackedUInt30() - 1
-        : 0;
+        : TreeNode.noOffset;
     final typeParameters = ((flags & hasTypeParamsFlag) != 0)
         ? new TypeParametersDeclaration.read(reader)
         : null;
@@ -491,11 +492,13 @@
   static const hasParameterFlagsFlag = 1 << 4;
   static const hasForwardingStubTargetFlag = 1 << 5;
   static const hasDefaultFunctionTypeArgsFlag = 1 << 6;
+  static const hasLocalVariablesFlag = 1 << 7;
 
   final ConstantPool constantPool;
   final List<int> bytecodes;
   final ExceptionsTable exceptionsTable;
   final SourcePositions sourcePositions;
+  final LocalVariableTable localVariables;
   final List<ObjectHandle> nullableFields;
   final List<ClosureDeclaration> closures;
   final List<int> parameterFlags;
@@ -505,6 +508,8 @@
   bool get hasExceptionsTable => exceptionsTable.blocks.isNotEmpty;
   bool get hasSourcePositions =>
       sourcePositions != null && sourcePositions.mapping.isNotEmpty;
+  bool get hasLocalVariables =>
+      localVariables != null && localVariables.isNotEmpty;
   bool get hasNullableFields => nullableFields.isNotEmpty;
   bool get hasClosures => closures.isNotEmpty;
 
@@ -517,13 +522,15 @@
       (forwardingStubTargetCpIndex != null ? hasForwardingStubTargetFlag : 0) |
       (defaultFunctionTypeArgsCpIndex != null
           ? hasDefaultFunctionTypeArgsFlag
-          : 0);
+          : 0) |
+      (hasLocalVariables ? hasLocalVariablesFlag : 0);
 
   Code(
       this.constantPool,
       this.bytecodes,
       this.exceptionsTable,
       this.sourcePositions,
+      this.localVariables,
       this.nullableFields,
       this.closures,
       this.parameterFlags,
@@ -555,6 +562,9 @@
     if (hasSourcePositions) {
       writer.writeLinkOffset(sourcePositions);
     }
+    if (hasLocalVariables) {
+      writer.writeLinkOffset(localVariables);
+    }
     if (hasNullableFields) {
       writer.writePackedList(nullableFields);
     }
@@ -590,6 +600,9 @@
     final sourcePositions = ((flags & hasSourcePositionsFlag) != 0)
         ? reader.readLinkOffset<SourcePositions>()
         : null;
+    final localVariables = ((flags & hasLocalVariablesFlag) != 0)
+        ? reader.readLinkOffset<LocalVariableTable>()
+        : null;
     final List<ObjectHandle> nullableFields =
         ((flags & hasNullableFieldsFlag) != 0)
             ? reader.readPackedList<ObjectHandle>()
@@ -602,6 +615,7 @@
         bytecodes,
         exceptionsTable,
         sourcePositions,
+        localVariables,
         nullableFields,
         closures,
         parameterFlags,
@@ -616,6 +630,9 @@
       "${new BytecodeDisassembler().disassemble(bytecodes, exceptionsTable, annotations: [
         hasSourcePositions
             ? sourcePositions.getBytecodeAnnotations()
+            : const <int, String>{},
+        hasLocalVariables
+            ? localVariables.getBytecodeAnnotations()
             : const <int, String>{}
       ])}}\n"
       "$exceptionsTable"
@@ -628,12 +645,15 @@
 }
 
 class ClosureDeclaration {
-  static const int flagHasOptionalPositionalParams = 1 << 0;
-  static const int flagHasOptionalNamedParams = 1 << 1;
-  static const int flagHasTypeParams = 1 << 2;
+  static const int hasOptionalPositionalParamsFlag = 1 << 0;
+  static const int hasOptionalNamedParamsFlag = 1 << 1;
+  static const int hasTypeParamsFlag = 1 << 2;
+  static const int hasSourcePositionsFlag = 1 << 3;
 
   final ObjectHandle parent;
   final ObjectHandle name;
+  final int position;
+  final int endPosition;
   final List<NameAndType> typeParams;
   final int numRequiredParams;
   final int numNamedParams;
@@ -644,6 +664,8 @@
   ClosureDeclaration(
       this.parent,
       this.name,
+      this.position,
+      this.endPosition,
       this.typeParams,
       this.numRequiredParams,
       this.numNamedParams,
@@ -654,19 +676,27 @@
     int flags = 0;
     if (numRequiredParams != parameters.length) {
       if (numNamedParams > 0) {
-        flags |= flagHasOptionalNamedParams;
+        flags |= hasOptionalNamedParamsFlag;
       } else {
-        flags |= flagHasOptionalPositionalParams;
+        flags |= hasOptionalPositionalParamsFlag;
       }
     }
     if (typeParams.isNotEmpty) {
-      flags |= flagHasTypeParams;
+      flags |= hasTypeParamsFlag;
+    }
+    if (position != TreeNode.noOffset) {
+      flags |= hasSourcePositionsFlag;
     }
     writer.writePackedUInt30(flags);
     writer.writePackedObject(parent);
     writer.writePackedObject(name);
 
-    if (flags & flagHasTypeParams != 0) {
+    if (flags & hasSourcePositionsFlag != 0) {
+      writer.writePackedUInt30(position + 1);
+      writer.writePackedUInt30(endPosition + 1);
+    }
+
+    if (flags & hasTypeParamsFlag != 0) {
       writer.writePackedUInt30(typeParams.length);
       for (var tp in typeParams) {
         writer.writePackedObject(tp.name);
@@ -677,7 +707,7 @@
     }
     writer.writePackedUInt30(parameters.length);
     if (flags &
-            (flagHasOptionalPositionalParams | flagHasOptionalNamedParams) !=
+            (hasOptionalPositionalParamsFlag | hasOptionalNamedParamsFlag) !=
         0) {
       writer.writePackedUInt30(numRequiredParams);
     }
@@ -692,8 +722,14 @@
     final int flags = reader.readPackedUInt30();
     final parent = reader.readPackedObject();
     final name = reader.readPackedObject();
+    final position = ((flags & hasSourcePositionsFlag) != 0)
+        ? reader.readPackedUInt30() - 1
+        : TreeNode.noOffset;
+    final endPosition = ((flags & hasSourcePositionsFlag) != 0)
+        ? reader.readPackedUInt30() - 1
+        : TreeNode.noOffset;
     List<NameAndType> typeParams;
-    if ((flags & flagHasTypeParams) != 0) {
+    if ((flags & hasTypeParamsFlag) != 0) {
       final int numTypeParams = reader.readPackedUInt30();
       List<ObjectHandle> names = new List<ObjectHandle>.generate(
           numTypeParams, (_) => reader.readPackedObject());
@@ -706,12 +742,12 @@
     }
     final numParams = reader.readPackedUInt30();
     final numRequiredParams = (flags &
-                (flagHasOptionalPositionalParams |
-                    flagHasOptionalNamedParams) !=
+                (hasOptionalPositionalParamsFlag |
+                    hasOptionalNamedParamsFlag) !=
             0)
         ? reader.readPackedUInt30()
         : numParams;
-    final numNamedParams = (flags & flagHasOptionalNamedParams != 0)
+    final numNamedParams = (flags & hasOptionalNamedParamsFlag != 0)
         ? (numParams - numRequiredParams)
         : 0;
     final List<NameAndType> parameters = new List<NameAndType>.generate(
@@ -719,14 +755,17 @@
         (_) => new NameAndType(
             reader.readPackedObject(), reader.readPackedObject()));
     final returnType = reader.readPackedObject();
-    return new ClosureDeclaration(parent, name, typeParams, numRequiredParams,
-        numNamedParams, parameters, returnType);
+    return new ClosureDeclaration(parent, name, position, endPosition,
+        typeParams, numRequiredParams, numNamedParams, parameters, returnType);
   }
 
   @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('Closure $parent::$name');
+    if (position != TreeNode.noOffset) {
+      sb.write(' pos = $position, end-pos = $endPosition');
+    }
     if (typeParams.isNotEmpty) {
       sb.write(' <${typeParams.join(', ')}>');
     }
@@ -754,19 +793,28 @@
 /// Bytecode of a nested function (closure).
 /// Closures share the constant pool of a top-level member.
 class ClosureCode {
+  static const hasExceptionsTableFlag = 1 << 0;
+  static const hasSourcePositionsFlag = 1 << 1;
+  static const hasLocalVariablesFlag = 1 << 2;
+
   final List<int> bytecodes;
   final ExceptionsTable exceptionsTable;
   final SourcePositions sourcePositions;
+  final LocalVariableTable localVariables;
 
   bool get hasExceptionsTable => exceptionsTable.blocks.isNotEmpty;
   bool get hasSourcePositions =>
       sourcePositions != null && sourcePositions.mapping.isNotEmpty;
+  bool get hasLocalVariables =>
+      localVariables != null && localVariables.isNotEmpty;
 
   int get flags =>
-      (hasExceptionsTable ? Code.hasExceptionsTableFlag : 0) |
-      (hasSourcePositions ? Code.hasSourcePositionsFlag : 0);
+      (hasExceptionsTable ? hasExceptionsTableFlag : 0) |
+      (hasSourcePositions ? hasSourcePositionsFlag : 0) |
+      (hasLocalVariables ? hasLocalVariablesFlag : 0);
 
-  ClosureCode(this.bytecodes, this.exceptionsTable, this.sourcePositions);
+  ClosureCode(this.bytecodes, this.exceptionsTable, this.sourcePositions,
+      this.localVariables);
 
   void write(BufferedWriter writer) {
     writer.writePackedUInt30(flags);
@@ -777,18 +825,25 @@
     if (hasSourcePositions) {
       writer.writeLinkOffset(sourcePositions);
     }
+    if (hasLocalVariables) {
+      writer.writeLinkOffset(localVariables);
+    }
   }
 
   factory ClosureCode.read(BufferedReader reader) {
     final int flags = reader.readPackedUInt30();
     final List<int> bytecodes = _readBytecodeInstructions(reader);
-    final exceptionsTable = ((flags & Code.hasExceptionsTableFlag) != 0)
+    final exceptionsTable = ((flags & hasExceptionsTableFlag) != 0)
         ? new ExceptionsTable.read(reader)
         : new ExceptionsTable();
-    final sourcePositions = ((flags & Code.hasSourcePositionsFlag) != 0)
+    final sourcePositions = ((flags & hasSourcePositionsFlag) != 0)
         ? reader.readLinkOffset<SourcePositions>()
         : null;
-    return new ClosureCode(bytecodes, exceptionsTable, sourcePositions);
+    final localVariables = ((flags & hasLocalVariablesFlag) != 0)
+        ? reader.readLinkOffset<LocalVariableTable>()
+        : null;
+    return new ClosureCode(
+        bytecodes, exceptionsTable, sourcePositions, localVariables);
   }
 
   @override
@@ -799,6 +854,9 @@
         .disassemble(bytecodes, exceptionsTable, annotations: [
       hasSourcePositions
           ? sourcePositions.getBytecodeAnnotations()
+          : const <int, String>{},
+      hasLocalVariables
+          ? localVariables.getBytecodeAnnotations()
           : const <int, String>{}
     ]));
     sb.writeln('}');
@@ -818,7 +876,7 @@
 
 class Component {
   static const int magicValue = 0x44424332; // 'DBC2'
-  static const int numSections = 7;
+  static const int numSections = 8;
   static const int sectionAlignment = 4;
 
   //  UInt32 magic, version, numSections x (numItems, offset)
@@ -830,6 +888,7 @@
   List<Members> members = <Members>[];
   List<Code> codes = <Code>[];
   List<SourcePositions> sourcePositions = <SourcePositions>[];
+  List<LocalVariableTable> localVariables = <LocalVariableTable>[];
   List<ObjectHandle> annotations = <ObjectHandle>[];
   ObjectHandle mainLibrary;
 
@@ -850,6 +909,13 @@
       annotationsWriter.writePackedObject(annot);
     }
 
+    final BufferedWriter localVariablesWriter =
+        new BufferedWriter.fromWriter(writer);
+    for (var lv in localVariables) {
+      writer.linkWriter.put(lv, localVariablesWriter.offset);
+      lv.write(localVariablesWriter);
+    }
+
     final BufferedWriter sourcePositionsWriter =
         new BufferedWriter.fromWriter(writer);
     for (var sp in sourcePositions) {
@@ -888,6 +954,7 @@
       new _Section(members.length, membersWriter),
       new _Section(codes.length, codesWriter),
       new _Section(sourcePositions.length, sourcePositionsWriter),
+      new _Section(localVariables.length, localVariablesWriter),
       new _Section(annotations.length, annotationsWriter),
     ];
     assert(sections.length == numSections);
@@ -956,6 +1023,9 @@
     final sourcePositionsNum = reader.readUInt32();
     final sourcePositionsOffset = reader.readUInt32();
 
+    final localVariablesNum = reader.readUInt32();
+    final localVariablesOffset = reader.readUInt32();
+
     final annotationsNum = reader.readUInt32();
     final annotationsOffset = reader.readUInt32();
 
@@ -988,6 +1058,15 @@
       sourcePositions.add(sp);
     }
 
+    final localVariablesStart = start + localVariablesOffset;
+    reader.offset = localVariablesStart;
+    for (int i = 0; i < localVariablesNum; ++i) {
+      int offset = reader.offset - localVariablesStart;
+      LocalVariableTable lv = new LocalVariableTable.read(reader);
+      reader.linkReader.setOffset(lv, offset);
+      localVariables.add(lv);
+    }
+
     final codesStart = start + codesOffset;
     reader.offset = codesStart;
     for (int i = 0; i < codesNum; ++i) {
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 216ac55..01a941d 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -35,6 +35,7 @@
         hasFreeTypeParameters,
         hasInstantiatorTypeArguments,
         isUncheckedCall;
+import 'local_variable_table.dart' show LocalVariableTable;
 import 'local_vars.dart' show LocalVariables;
 import 'nullability_detector.dart' show NullabilityDetector;
 import 'object_table.dart' show ObjectHandle, ObjectTable, NameAndType;
@@ -43,6 +44,8 @@
 import '../constants_error_reporter.dart' show ForwardConstantEvaluationErrors;
 import '../metadata/bytecode.dart';
 
+import 'dart:math' as math;
+
 // This symbol is used as the name in assert assignable's to indicate it comes
 // from an explicit 'as' check.  This will cause the runtime to throw the right
 // exception.
@@ -52,6 +55,7 @@
   ast.Component component, {
   bool enableAsserts: true,
   bool emitSourcePositions: false,
+  bool emitLocalVarInfo: false,
   bool emitAnnotations: false,
   bool omitAssertSourcePositions: false,
   bool useFutureBytecodeFormat: false,
@@ -78,6 +82,7 @@
       environmentDefines,
       enableAsserts,
       emitSourcePositions,
+      emitLocalVarInfo,
       emitAnnotations,
       omitAssertSourcePositions,
       useFutureBytecodeFormat,
@@ -95,6 +100,7 @@
   final Map<String, String> environmentDefines;
   final bool enableAsserts;
   final bool emitSourcePositions;
+  final bool emitLocalVarInfo;
   final bool emitAnnotations;
   final bool omitAssertSourcePositions;
   final bool useFutureBytecodeFormat;
@@ -134,6 +140,8 @@
   List<BytecodeAssembler> savedAssemblers;
   bool hasErrors;
   int currentLoopDepth;
+  List<int> savedMaxSourcePositions;
+  int maxSourcePosition;
 
   BytecodeGenerator(
       ast.Component component,
@@ -144,6 +152,7 @@
       this.environmentDefines,
       this.enableAsserts,
       this.emitSourcePositions,
+      this.emitLocalVarInfo,
       this.emitAnnotations,
       this.omitAssertSourcePositions,
       this.useFutureBytecodeFormat,
@@ -664,10 +673,11 @@
       _asyncAwaitCompleterGetFuture ??= libraryIndex.getMember(
           'dart:async', '_AsyncAwaitCompleter', 'get:future');
 
-  void _recordSourcePosition(TreeNode node) {
+  void _recordSourcePosition(int fileOffset) {
     if (emitSourcePositions) {
-      asm.currentSourcePosition = node.fileOffset;
+      asm.currentSourcePosition = fileOffset;
     }
+    maxSourcePosition = math.max(maxSourcePosition, fileOffset);
   }
 
   void _generateNode(TreeNode node) {
@@ -675,7 +685,7 @@
       return;
     }
     final savedSourcePosition = asm.currentSourcePosition;
-    _recordSourcePosition(node);
+    _recordSourcePosition(node.fileOffset);
     node.accept(this);
     asm.currentSourcePosition = savedSourcePosition;
   }
@@ -1149,12 +1159,14 @@
     asm = new BytecodeAssembler();
     savedAssemblers = <BytecodeAssembler>[];
     currentLoopDepth = 0;
+    savedMaxSourcePositions = <int>[];
+    maxSourcePosition = node.fileOffset;
 
     locals = new LocalVariables(node, enableAsserts);
     locals.enterScope(node);
     assert(!locals.isSyncYieldingFrame);
 
-    _recordSourcePosition(node);
+    _recordSourcePosition(node.fileOffset);
     _genPrologue(node, node.function);
     _setupInitialContext(node.function);
     if (node is Procedure && node.isInstanceMember) {
@@ -1186,6 +1198,12 @@
     if (!hasErrors) {
       Code code;
       if (hasCode) {
+        if (emitLocalVarInfo && node.function != null) {
+          // Leave the scope which was entered in _setupInitialContext.
+          asm.localVariableTable
+              .leaveScope(asm.offset, node.function.fileEndOffset);
+        }
+
         List<int> parameterFlags = null;
         int forwardingStubTargetCpIndex = null;
         int defaultFunctionTypeArgsCpIndex = null;
@@ -1208,6 +1226,7 @@
             asm.bytecode,
             asm.exceptionsTable,
             finalizeSourcePositions(),
+            finalizeLocalVariables(),
             nullableFields,
             closures,
             parameterFlags,
@@ -1257,6 +1276,16 @@
     return asm.sourcePositions;
   }
 
+  LocalVariableTable finalizeLocalVariables() {
+    final localVariables = asm.localVariableTable;
+    assert(!localVariables.hasActiveScopes);
+    if (localVariables.isEmpty) {
+      return null;
+    }
+    bytecodeComponent.localVariables.add(localVariables);
+    return localVariables;
+  }
+
   void _genPrologue(Node node, FunctionNode function) {
     if (locals.hasOptionalParameters) {
       final int numOptionalPositional = function.positionalParameters.length -
@@ -1381,6 +1410,25 @@
   void _setupInitialContext(FunctionNode function) {
     _allocateContextIfNeeded();
 
+    if (emitLocalVarInfo && function != null) {
+      // Open scope after allocating context.
+      asm.localVariableTable.enterScope(
+          asm.offset, locals.currentContextLevel, function.fileOffset);
+      if (locals.hasContextVar) {
+        asm.localVariableTable
+            .recordContextVariable(asm.offset, locals.contextVarIndexInFrame);
+      }
+      if (locals.hasReceiver) {
+        _declareLocalVariable(locals.receiverVar, function.fileOffset);
+      }
+      for (var v in function.positionalParameters) {
+        _declareLocalVariable(v, function.fileOffset);
+      }
+      for (var v in locals.sortedNamedParameters) {
+        _declareLocalVariable(v, function.fileOffset);
+      }
+    }
+
     if (locals.hasCapturedParameters) {
       // Copy captured parameters to their respective locations in the context.
       if (!isClosure) {
@@ -1408,6 +1456,22 @@
     }
   }
 
+  void _declareLocalVariable(
+      VariableDeclaration variable, int initializedPosition) {
+    assert(variable.name != null);
+    bool isCaptured = locals.isCaptured(variable);
+    asm.localVariableTable.declareVariable(
+        asm.offset,
+        isCaptured,
+        isCaptured
+            ? locals.getVarIndexInContext(variable)
+            : locals.getVarIndexInFrame(variable),
+        cp.addString(variable.name),
+        cp.addType(variable.type),
+        variable.fileOffset,
+        initializedPosition);
+  }
+
   // TODO(alexmarkov): Revise if we need to AOT-compile from bytecode.
   bool get canSkipTypeChecksForNonCovariantArguments =>
       !isClosure && enclosingMember.name.name != 'call';
@@ -1618,6 +1682,15 @@
     final savedLoopDepth = currentLoopDepth;
     currentLoopDepth = 0;
 
+    int position = TreeNode.noOffset;
+    int endPosition = TreeNode.noOffset;
+    if (emitSourcePositions) {
+      position = (node is ast.FunctionDeclaration)
+          ? node.fileOffset
+          : function.fileOffset;
+      endPosition = function.fileEndOffset;
+    }
+
     if (function.typeParameters.isNotEmpty) {
       functionTypeParameters ??= new List<TypeParameter>();
       functionTypeParameters.addAll(function.typeParameters);
@@ -1644,6 +1717,8 @@
         objectTable
             .getHandle(savedIsClosure ? parentFunction : enclosingMember),
         objectTable.getNameHandle(null, name),
+        position,
+        endPosition,
         function.typeParameters
             .map((tp) => new NameAndType(
                 objectTable.getNameHandle(null, tp.name),
@@ -1658,6 +1733,7 @@
     final int closureFunctionIndex = cp.addClosureFunction(closureIndex);
 
     _genPrologue(node, function);
+    _recordSourcePosition(function.fileOffset);
 
     Label continuationSwitchLabel;
     int continuationSwitchVar;
@@ -1678,12 +1754,18 @@
     // BytecodeAssembler eliminates this bytecode if it is unreachable.
     asm.emitPushNull();
     _genReturnTOS();
+    _recordSourcePosition(function.fileEndOffset);
 
     if (locals.isSyncYieldingFrame) {
       _genSyncYieldingEpilogue(
           function, continuationSwitchLabel, continuationSwitchVar);
     }
 
+    if (emitLocalVarInfo) {
+      // Leave the scope which was entered in _setupInitialContext.
+      asm.localVariableTable.leaveScope(asm.offset, function.fileEndOffset);
+    }
+
     cp.addEndClosureFunctionScope();
 
     if (function.typeParameters.isNotEmpty) {
@@ -1698,8 +1780,8 @@
 
     locals.leaveScope();
 
-    closure.code = new ClosureCode(
-        asm.bytecode, asm.exceptionsTable, finalizeSourcePositions());
+    closure.code = new ClosureCode(asm.bytecode, asm.exceptionsTable,
+        finalizeSourcePositions(), finalizeLocalVariables());
 
     _popAssemblerState();
     yieldPoints = savedYieldPoints;
@@ -1803,15 +1885,35 @@
   void _enterScope(TreeNode node) {
     locals.enterScope(node);
     _allocateContextIfNeeded();
+    if (emitLocalVarInfo) {
+      asm.localVariableTable
+          .enterScope(asm.offset, locals.currentContextLevel, node.fileOffset);
+      _startRecordingMaxPosition(node.fileOffset);
+    }
   }
 
   void _leaveScope() {
+    if (emitLocalVarInfo) {
+      asm.localVariableTable.leaveScope(asm.offset, _endRecordingMaxPosition());
+    }
     if (locals.currentContextSize > 0) {
       _genUnwindContext(locals.currentContextLevel - 1);
     }
     locals.leaveScope();
   }
 
+  void _startRecordingMaxPosition(int fileOffset) {
+    savedMaxSourcePositions.add(maxSourcePosition);
+    maxSourcePosition = fileOffset;
+  }
+
+  int _endRecordingMaxPosition() {
+    int localMax = maxSourcePosition;
+    maxSourcePosition =
+        math.max(localMax, savedMaxSourcePositions.removeLast());
+    return localMax;
+  }
+
   void _genUnwindContext(int targetContextLevel) {
     int currentContextLevel = locals.currentContextLevel;
     assert(currentContextLevel >= targetContextLevel);
@@ -3271,11 +3373,17 @@
       if (isCaptured) {
         _genPushContextForVariable(node);
       }
+      int maxInitializerPosition = node.fileOffset;
       if (node.initializer != null) {
+        _startRecordingMaxPosition(node.fileOffset);
         _generateNode(node.initializer);
+        maxInitializerPosition = _endRecordingMaxPosition();
       } else {
         asm.emitPushNull();
       }
+      if (emitLocalVarInfo && !asm.isUnreachable && node.name != null) {
+        _declareLocalVariable(node, maxInitializerPosition + 1);
+      }
       _genStoreVar(node);
     }
   }
diff --git a/pkg/vm/lib/bytecode/local_variable_table.dart b/pkg/vm/lib/bytecode/local_variable_table.dart
new file mode 100644
index 0000000..fc49225
--- /dev/null
+++ b/pkg/vm/lib/bytecode/local_variable_table.dart
@@ -0,0 +1,234 @@
+// Copyright (c) 2019, 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 vm.bytecode.local_variable_table;
+
+import 'bytecode_serialization.dart';
+
+enum LocalVariableEntryKind {
+  invalid,
+  scope,
+  variableDeclaration,
+  contextVariable,
+}
+
+abstract class LocalVariableEntry {
+  static const KindMask = 0x0F;
+  static const IsCapturedFlag = 1 << 4;
+
+  LocalVariableEntryKind get kind;
+  int get flags => 0;
+  final int startPC;
+  void writeContents(BufferedWriter writer);
+
+  LocalVariableEntry(this.startPC);
+}
+
+class Scope extends LocalVariableEntry {
+  int endPC;
+  int contextLevel;
+  int position;
+  int endPosition;
+  final List<VariableDeclaration> variables = <VariableDeclaration>[];
+
+  Scope(int startPC, this.endPC, this.contextLevel, this.position,
+      this.endPosition)
+      : super(startPC);
+
+  @override
+  LocalVariableEntryKind get kind => LocalVariableEntryKind.scope;
+
+  @override
+  void writeContents(BufferedWriter writer) {
+    if (endPC == null) {
+      throw '$this is not closed';
+    }
+    writer.writePackedUInt30(endPC - startPC);
+    writer.writeSLEB128(contextLevel);
+    writer.writePackedUInt30(position + 1);
+    writer.writePackedUInt30(endPosition + 1);
+  }
+
+  Scope.readContents(BufferedReader reader, int startPC) : super(startPC) {
+    endPC = startPC = reader.readPackedUInt30();
+    contextLevel = reader.readSLEB128();
+    position = reader.readPackedUInt30() - 1;
+    endPosition = reader.readPackedUInt30() - 1;
+  }
+
+  @override
+  String toString() =>
+      'scope (pc $startPC-$endPC pos $position-$endPosition context-level $contextLevel)';
+}
+
+class VariableDeclaration extends LocalVariableEntry {
+  bool isCaptured;
+  int index;
+  int name;
+  int type;
+  int position;
+  int initializedPosition;
+
+  VariableDeclaration(int startPC, this.isCaptured, this.index, this.name,
+      this.type, this.position, this.initializedPosition)
+      : super(startPC);
+
+  @override
+  LocalVariableEntryKind get kind => LocalVariableEntryKind.variableDeclaration;
+
+  @override
+  int get flags => (isCaptured ? LocalVariableEntry.IsCapturedFlag : 0);
+
+  @override
+  void writeContents(BufferedWriter writer) {
+    writer.writeSLEB128(index);
+    writer.writePackedUInt30(name);
+    writer.writePackedUInt30(type);
+    writer.writePackedUInt30(position + 1);
+    writer.writePackedUInt30(initializedPosition + 1);
+  }
+
+  VariableDeclaration.readContents(
+      BufferedReader reader, int startPC, int flags)
+      : super(startPC) {
+    isCaptured = (flags & LocalVariableEntry.IsCapturedFlag) != 0;
+    index = reader.readSLEB128();
+    name = reader.readPackedUInt30();
+    type = reader.readPackedUInt30();
+    position = reader.readPackedUInt30() - 1;
+    initializedPosition = reader.readPackedUInt30() - 1;
+  }
+
+  @override
+  String toString() =>
+      'variable $index${isCaptured ? ' (captured)' : ''} pc $startPC, name CP#$name, type CP#$type, pos $position, init-pos $initializedPosition';
+}
+
+class ContextVariable extends LocalVariableEntry {
+  int index;
+
+  ContextVariable(int startPC, this.index) : super(startPC);
+
+  @override
+  LocalVariableEntryKind get kind => LocalVariableEntryKind.contextVariable;
+
+  @override
+  void writeContents(BufferedWriter writer) {
+    writer.writeSLEB128(index);
+  }
+
+  ContextVariable.readContents(BufferedReader reader, int startPC)
+      : super(startPC) {
+    index = reader.readSLEB128();
+  }
+
+  @override
+  String toString() => 'context variable $index';
+}
+
+/// Keeps information about declared local variables.
+class LocalVariableTable {
+  final scopes = <Scope>[];
+  final activeScopes = <Scope>[];
+  ContextVariable contextVariable;
+
+  LocalVariableTable();
+
+  void enterScope(int pc, int contextLevel, int position) {
+    final scope = new Scope(pc, null, contextLevel, position, null);
+    activeScopes.add(scope);
+    scopes.add(scope);
+  }
+
+  void declareVariable(int pc, bool isCaptured, int index, int nameCpIndex,
+      int typeCpIndex, int position, int initializedPosition) {
+    final variable = new VariableDeclaration(pc, isCaptured, index, nameCpIndex,
+        typeCpIndex, position, initializedPosition);
+    activeScopes.last.variables.add(variable);
+  }
+
+  void leaveScope(int pc, int endPosition) {
+    final scope = activeScopes.removeLast();
+    scope.endPC = pc;
+    scope.endPosition = endPosition;
+    if (scope.variables.isEmpty) {
+      scopes.remove(scope);
+    }
+  }
+
+  void recordContextVariable(int pc, int index) {
+    assert(contextVariable == null);
+    contextVariable = new ContextVariable(pc, index);
+  }
+
+  bool get isEmpty => scopes.isEmpty && contextVariable == null;
+
+  bool get isNotEmpty => !isEmpty;
+
+  bool get hasActiveScopes => activeScopes.isNotEmpty;
+
+  List<LocalVariableEntry> getEntries() {
+    final entries = <LocalVariableEntry>[];
+    if (contextVariable != null) {
+      entries.add(contextVariable);
+    }
+    for (Scope scope in scopes) {
+      entries.add(scope);
+      entries.addAll(scope.variables);
+    }
+    return entries;
+  }
+
+  void write(BufferedWriter writer) {
+    final entries = getEntries();
+    writer.writePackedUInt30(entries.length);
+    final encodeStartPC = new SLEB128DeltaEncoder();
+    for (var entry in entries) {
+      writer.writeByte(entry.kind.index | entry.flags);
+      encodeStartPC.write(writer, entry.startPC);
+      entry.writeContents(writer);
+    }
+  }
+
+  LocalVariableTable.read(BufferedReader reader) {
+    final int numEntries = reader.readPackedUInt30();
+    final decodeStartPC = new SLEB128DeltaDecoder();
+    Scope scope;
+    for (int i = 0; i < numEntries; ++i) {
+      final int kindAndFlags = reader.readByte();
+      final LocalVariableEntryKind kind = LocalVariableEntryKind
+          .values[kindAndFlags & LocalVariableEntry.KindMask];
+      final int flags = kindAndFlags & ~LocalVariableEntry.KindMask;
+      final int startPC = decodeStartPC.read(reader);
+      switch (kind) {
+        case LocalVariableEntryKind.scope:
+          scope = new Scope.readContents(reader, startPC);
+          scopes.add(scope);
+          break;
+        case LocalVariableEntryKind.variableDeclaration:
+          scope.variables.add(
+              new VariableDeclaration.readContents(reader, startPC, flags));
+          break;
+        case LocalVariableEntryKind.contextVariable:
+          contextVariable = new ContextVariable.readContents(reader, startPC);
+          break;
+        default:
+          throw 'Unexpected entry kind ${kind}';
+      }
+    }
+  }
+
+  Map<int, String> getBytecodeAnnotations() {
+    final map = <int, String>{};
+    for (var entry in getEntries()) {
+      final pc = entry.startPC;
+      if (map[pc] == null) {
+        map[pc] = entry.toString();
+      } else {
+        map[pc] = "${map[pc]}; $entry";
+      }
+    }
+    return map;
+  }
+}
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart
index 178bfa1..c321b4e 100644
--- a/pkg/vm/lib/bytecode/local_vars.dart
+++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -850,6 +850,9 @@
           (_currentScope.tempsUsed + count) - _currentFrame.temporaries.length;
       int local = _currentScope.localsUsed;
       _currentScope.localsUsed += newSlots;
+      if (_currentScope.localsUsed > localVariableIndexLimit) {
+        throw new LocalVariableIndexOverflowException();
+      }
       _updateFrameSize();
       for (int i = 0; i < newSlots; i++) {
         _currentFrame.temporaries.add(local + i);
diff --git a/pkg/vm/lib/bytecode/object_table.dart b/pkg/vm/lib/bytecode/object_table.dart
index 9c3f530..80324cc 100644
--- a/pkg/vm/lib/bytecode/object_table.dart
+++ b/pkg/vm/lib/bytecode/object_table.dart
@@ -1379,7 +1379,9 @@
     ObjectHandle handle = _nodeCache[node];
     if (handle == null) {
       handle = node.accept(_nodeVisitor);
-      _nodeCache[node] = handle;
+      if (handle != null && handle.isCacheable) {
+        _nodeCache[node] = handle;
+      }
     } else {
       ++handle._useCount;
     }
diff --git a/pkg/vm/lib/bytecode/source_positions.dart b/pkg/vm/lib/bytecode/source_positions.dart
index 22ed3b1..f0bef3d 100644
--- a/pkg/vm/lib/bytecode/source_positions.dart
+++ b/pkg/vm/lib/bytecode/source_positions.dart
@@ -4,7 +4,14 @@
 
 library vm.bytecode.source_positions;
 
-import 'bytecode_serialization.dart' show BufferedWriter, BufferedReader;
+import 'bytecode_serialization.dart'
+    show
+        BufferedWriter,
+        BufferedReader,
+        PackedUInt30DeltaEncoder,
+        PackedUInt30DeltaDecoder,
+        SLEB128DeltaEncoder,
+        SLEB128DeltaDecoder;
 
 /// Maintains mapping between bytecode instructions and source positions.
 class SourcePositions {
@@ -53,41 +60,3 @@
         new MapEntry(pc, 'source position $fileOffset'));
   }
 }
-
-class PackedUInt30DeltaEncoder {
-  int _last = 0;
-
-  void write(BufferedWriter write, int value) {
-    write.writePackedUInt30(value - _last);
-    _last = value;
-  }
-}
-
-class PackedUInt30DeltaDecoder {
-  int _last = 0;
-
-  int read(BufferedReader reader) {
-    int value = reader.readPackedUInt30() + _last;
-    _last = value;
-    return value;
-  }
-}
-
-class SLEB128DeltaEncoder {
-  int _last = 0;
-
-  void write(BufferedWriter writer, int value) {
-    writer.writeSLEB128(value - _last);
-    _last = value;
-  }
-}
-
-class SLEB128DeltaDecoder {
-  int _last = 0;
-
-  int read(BufferedReader reader) {
-    int value = reader.readSLEB128() + _last;
-    _last = value;
-    return value;
-  }
-}
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index d65f56b..0dd2962 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -113,6 +113,9 @@
   args.addFlag('gen-bytecode', help: 'Generate bytecode', defaultsTo: false);
   args.addFlag('emit-bytecode-source-positions',
       help: 'Emit source positions in bytecode', defaultsTo: false);
+  args.addFlag('emit-bytecode-local-var-info',
+      help: 'Emit information about local variables in bytecode',
+      defaultsTo: false);
   args.addFlag('emit-bytecode-annotations',
       help: 'Emit Dart annotations in bytecode', defaultsTo: false);
   args.addFlag('drop-ast',
@@ -166,6 +169,7 @@
   final bool genBytecode = options['gen-bytecode'];
   final bool emitBytecodeSourcePositions =
       options['emit-bytecode-source-positions'];
+  final bool emitBytecodeLocalVarInfo = options['emit-bytecode-local-var-info'];
   final bool emitBytecodeAnnotations = options['emit-bytecode-annotations'];
   final bool dropAST = options['drop-ast'];
   final bool useFutureBytecodeFormat = options['use-future-bytecode-format'];
@@ -226,6 +230,7 @@
       environmentDefines: environmentDefines,
       genBytecode: genBytecode,
       emitBytecodeSourcePositions: emitBytecodeSourcePositions,
+      emitBytecodeLocalVarInfo: emitBytecodeLocalVarInfo,
       emitBytecodeAnnotations: emitBytecodeAnnotations,
       dropAST: dropAST && !splitOutputByPackages,
       useFutureBytecodeFormat: useFutureBytecodeFormat,
@@ -266,6 +271,7 @@
       genBytecode: genBytecode,
       enableAsserts: enableAsserts,
       emitBytecodeSourcePositions: emitBytecodeSourcePositions,
+      emitBytecodeLocalVarInfo: emitBytecodeLocalVarInfo,
       emitBytecodeAnnotations: emitBytecodeAnnotations,
       dropAST: dropAST,
       showBytecodeSizeStat: showBytecodeSizeStat,
@@ -287,6 +293,7 @@
     Map<String, String> environmentDefines,
     bool genBytecode: false,
     bool emitBytecodeSourcePositions: false,
+    bool emitBytecodeLocalVarInfo: false,
     bool emitBytecodeAnnotations: false,
     bool dropAST: false,
     bool useFutureBytecodeFormat: false,
@@ -320,6 +327,7 @@
       generateBytecode(component,
           enableAsserts: enableAsserts,
           emitSourcePositions: emitBytecodeSourcePositions,
+          emitLocalVarInfo: emitBytecodeLocalVarInfo,
           emitAnnotations: emitBytecodeAnnotations,
           useFutureBytecodeFormat: useFutureBytecodeFormat,
           environmentDefines: environmentDefines);
@@ -656,6 +664,7 @@
   bool genBytecode: false,
   bool enableAsserts: true,
   bool emitBytecodeSourcePositions: false,
+  bool emitBytecodeLocalVarInfo: false,
   bool emitBytecodeAnnotations: false,
   bool dropAST: false,
   bool showBytecodeSizeStat: false,
@@ -718,6 +727,7 @@
             hierarchy: hierarchy,
             enableAsserts: enableAsserts,
             emitSourcePositions: emitBytecodeSourcePositions,
+            emitLocalVarInfo: emitBytecodeLocalVarInfo,
             emitAnnotations: emitBytecodeAnnotations,
             useFutureBytecodeFormat: useFutureBytecodeFormat,
             environmentDefines: environmentDefines);
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index 4b40caf..d61ca95 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -275,9 +275,10 @@
   }
 
   bool _isStatic(Expression node) {
-    if (node is! StaticGet) return false;
-
-    return (node as StaticGet).target is Procedure;
+    if (node is StaticGet) {
+      return node.target is Procedure;
+    }
+    return node is ConstantExpression;
   }
 }
 
diff --git a/pkg/vm/test/frontend_server_test.dart b/pkg/vm/test/frontend_server_test.dart
index 5310517..a56d500 100644
--- a/pkg/vm/test/frontend_server_test.dart
+++ b/pkg/vm/test/frontend_server_test.dart
@@ -83,11 +83,12 @@
           new StreamController<List<int>>();
       final ReceivePort compileCalled = new ReceivePort();
       when(compiler.compile(any, any, generator: anyNamed('generator')))
-          .thenAnswer((Invocation invocation) {
+          .thenAnswer((Invocation invocation) async {
         expect(invocation.positionalArguments[0], equals('server.dart'));
         expect(
             invocation.positionalArguments[1]['sdk-root'], equals('sdkroot'));
         compileCalled.sendPort.send(true);
+        return true;
       });
 
       Future<int> result = starter(
@@ -116,11 +117,12 @@
           new StreamController<List<int>>();
       final ReceivePort compileCalled = new ReceivePort();
       when(compiler.compile(any, any, generator: anyNamed('generator')))
-          .thenAnswer((Invocation invocation) {
+          .thenAnswer((Invocation invocation) async {
         expect(invocation.positionalArguments[0], equals('server.dart'));
         expect(
             invocation.positionalArguments[1]['sdk-root'], equals('sdkroot'));
         compileCalled.sendPort.send(true);
+        return true;
       });
 
       Future<int> result = starter(
@@ -141,12 +143,13 @@
       final ReceivePort compileCalled = new ReceivePort();
       int counter = 1;
       when(compiler.compile(any, any, generator: anyNamed('generator')))
-          .thenAnswer((Invocation invocation) {
+          .thenAnswer((Invocation invocation) async {
         expect(invocation.positionalArguments[0],
             equals('server${counter++}.dart'));
         expect(
             invocation.positionalArguments[1]['sdk-root'], equals('sdkroot'));
         compileCalled.sendPort.send(true);
+        return true;
       });
 
       Future<int> result = starter(
@@ -180,7 +183,7 @@
       final ReceivePort recompileCalled = new ReceivePort();
 
       when(compiler.recompileDelta(entryPoint: null))
-          .thenAnswer((Invocation invocation) {
+          .thenAnswer((Invocation invocation) async {
         recompileCalled.sendPort.send(true);
       });
       Future<int> result = starter(
@@ -208,7 +211,7 @@
       final ReceivePort recompileCalled = new ReceivePort();
 
       when(compiler.recompileDelta(entryPoint: 'file2.dart'))
-          .thenAnswer((Invocation invocation) {
+          .thenAnswer((Invocation invocation) async {
         recompileCalled.sendPort.send(true);
       });
       Future<int> result = starter(
@@ -275,7 +278,7 @@
       final ReceivePort recompileCalled = new ReceivePort();
 
       when(compiler.recompileDelta(entryPoint: null))
-          .thenAnswer((Invocation invocation) {
+          .thenAnswer((Invocation invocation) async {
         recompileCalled.sendPort.send(true);
       });
       Future<int> result = starter(
diff --git a/pkg/vm/test/incremental_compiler_test.dart b/pkg/vm/test/incremental_compiler_test.dart
index 2b714ec..b223aaf 100644
--- a/pkg/vm/test/incremental_compiler_test.dart
+++ b/pkg/vm/test/incremental_compiler_test.dart
@@ -296,7 +296,7 @@
       await compileAndSerialize(mainDill, libDill, compiler);
 
       var list = new File(p.join(dir.path, 'myMain.dilllist'))..createSync();
-      list.writeAsStringSync("#@dill\n../main.dart.dill\n../lib.dart.dill\n");
+      list.writeAsStringSync("#@dill\nmain.dart.dill\nlib.dart.dill\n");
       Directory runFrom = new Directory(dir.path + "/runFrom")..createSync();
       vm = await Process.start(Platform.resolvedExecutable, <String>[list.path],
           workingDirectory: runFrom.path);
diff --git a/pkg/vm/tool/test_bytecode b/pkg/vm/tool/test_bytecode
deleted file mode 100755
index 9f800ab..0000000
--- a/pkg/vm/tool/test_bytecode
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/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
-# BSD-style license that can be found in the LICENSE file.
-
-# Script for generating bytecode in a kernel file using Dart 2 pipeline and
-# interpreting the resulting bytecode.
-
-# Usage
-# pkg/vm/tool/test_bytecode ~/foo.dart
-
-set -e
-
-# Pick the architecture and mode to test.
-BUILD_FLAGS="-m release -a x64"
-BUILD_SUBDIR="ReleaseX64"
-
-function follow_links() {
-  file="$1"
-  while [ -h "$file" ]; do
-    # On Mac OS, readlink -f doesn't work.
-    file="$(readlink "$file")"
-  done
-  echo "$file"
-}
-
-# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
-PROG_NAME="$(follow_links "$BASH_SOURCE")"
-
-# Handle the case where dart-sdk/bin has been symlinked to.
-CUR_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
-
-SDK_DIR="$CUR_DIR/../../.."
-BUILD_DIR="$SDK_DIR/out/$BUILD_SUBDIR"
-
-# Regenerate vm_platform_strong.dill to contain bytecode if needed:
-# $SDK_DIR/tools/gn.py $BUILD_FLAGS --bytecode
-# $SDK_DIR/tools/build.py $BUILD_FLAGS runtime
-
-# Generate dill file containing bytecode for input dart source.
-$CUR_DIR/gen_kernel --platform $BUILD_DIR/vm_platform_strong.dill \
-  --gen-bytecode $@ -o $BUILD_DIR/test_bytecode.dill
-
-# Dump bytecode in generated vm_platform_strong.dill file to platform.txt.
-# $BUILD_DIR/dart $SDK_DIR/pkg/vm/bin/dump_kernel.dart \
-#   $BUILD_DIR/vm_platform_strong.dill $BUILD_DIR/platform.txt
-
-# Dump bytecode in generated test_bytecode.dill file to test_bytecode.txt.
-# $BUILD_DIR/dart $SDK_DIR/pkg/vm/bin/dump_kernel.dart \
-#   $BUILD_DIR/test_bytecode.dill $BUILD_DIR/test_bytecode.txt
-
-# Required flag.
-DART_VM_FLAGS="--enable-interpreter $DART_VM_FLAGS"
-
-# Optional flags examples. Uncomment as needed.
-# DART_VM_FLAGS="--compilation-counter-threshold=-1 $DART_VM_FLAGS"
-# DART_VM_FLAGS="--force-log-flush --isolate-log-filter=\"\" $DART_VM_FLAGS"
-# DART_VM_FLAGS="--dump-kernel-bytecode $DART_VM_FLAGS"
-# DART_VM_FLAGS="--trace-interpreter-after=0 $DART_VM_FLAGS"
-
-# Execute dill file.
-exec $BUILD_DIR/dart $DART_VM_FLAGS $BUILD_DIR/test_bytecode.dill
-
diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc
index 03ca32b..36efb0d 100644
--- a/runtime/bin/dfe.cc
+++ b/runtime/bin/dfe.cc
@@ -407,20 +407,34 @@
   DISALLOW_COPY_AND_ASSIGN(KernelIRNode);
 };
 
+class StringPointer {
+ public:
+  explicit StringPointer(char* c_str) : c_str_(c_str) {}
+  ~StringPointer() { free(c_str_); }
+
+  const char* c_str() { return c_str_; }
+
+ private:
+  char* c_str_;
+  DISALLOW_COPY_AND_ASSIGN(StringPointer);
+};
+
 // Supports "kernel list" files as input.
 // Those are text files that start with '#@dill' on new line, followed
 // by absolute paths to kernel files or relative paths, that are relative
-// to dart process working directory.
+// to [script_uri] "kernel list" file.
 // Below is an example of valid kernel list file:
 // ```
 // #@dill
 // /projects/mytest/build/bin/main.vm.dill
 // /projects/mytest/build/packages/mytest/lib.vm.dill
 // ```
-static bool TryReadKernelListBuffer(uint8_t* buffer,
+static bool TryReadKernelListBuffer(const char* script_uri,
+                                    uint8_t* buffer,
                                     intptr_t buffer_size,
                                     uint8_t** kernel_ir,
                                     intptr_t* kernel_ir_size) {
+  const char* kernel_list_dirname = DartUtils::DirName(script_uri);
   KernelIRNode* kernel_ir_head = NULL;
   KernelIRNode* kernel_ir_tail = NULL;
   // Add all kernels to the linked list
@@ -432,7 +446,13 @@
     *tail = '\0';
     intptr_t this_kernel_size;
     uint8_t* this_buffer;
-    if (!TryReadFile(filename, &this_buffer, &this_kernel_size)) {
+
+    StringPointer absolute_filename(
+        File::IsAbsolutePath(filename)
+            ? strdup(filename)
+            : Utils::SCreate("%s%s", kernel_list_dirname, filename));
+    if (!TryReadFile(absolute_filename.c_str(), &this_buffer,
+                     &this_kernel_size)) {
       return false;
     }
 
@@ -472,8 +492,8 @@
   DartUtils::MagicNumber magic_number =
       DartUtils::SniffForMagicNumber(buffer, *kernel_ir_size);
   if (magic_number == DartUtils::kKernelListMagicNumber) {
-    return TryReadKernelListBuffer(buffer, *kernel_ir_size, kernel_ir,
-                                   kernel_ir_size);
+    return TryReadKernelListBuffer(script_uri, buffer, *kernel_ir_size,
+                                   kernel_ir, kernel_ir_size);
   }
   return TryReadSimpleKernelBuffer(buffer, kernel_ir, kernel_ir_size);
 }
diff --git a/runtime/bin/eventhandler_fuchsia.cc b/runtime/bin/eventhandler_fuchsia.cc
index 837b7a0..bae6f32 100644
--- a/runtime/bin/eventhandler_fuchsia.cc
+++ b/runtime/bin/eventhandler_fuchsia.cc
@@ -249,6 +249,7 @@
   MutexLocker ml(&mutex_);
   uint32_t events = 0;
   fdio_unsafe_wait_end(fdio_, observed, &events);
+  LOG_INFO("IOHandle::WaitEnd: fd = %ld, events = %x\n", fd_, events);
   return events;
 }
 
diff --git a/runtime/bin/ffi_test_functions.cc b/runtime/bin/ffi_test_functions.cc
index f1c418c..200d6c2 100644
--- a/runtime/bin/ffi_test_functions.cc
+++ b/runtime/bin/ffi_test_functions.cc
@@ -7,8 +7,8 @@
 #include <stddef.h>
 #include <stdlib.h>
 #include <sys/types.h>
+#include <csignal>
 
-#include "platform/assert.h"
 #include "platform/globals.h"
 #if defined(HOST_OS_WINDOWS)
 #include <psapi.h>
@@ -16,6 +16,8 @@
 #include <unistd.h>
 #endif
 
+#include <setjmp.h>
+#include <signal.h>
 #include <iostream>
 #include <limits>
 
@@ -23,6 +25,9 @@
 
 namespace dart {
 
+////////////////////////////////////////////////////////////////////////////////
+// Tests for Dart -> native calls.
+
 // Sums two ints and adds 42.
 // Simple function to test trampolines.
 // Also used for testing argument exception on passing null instead of a Dart
@@ -449,7 +454,8 @@
   return retval;
 }
 
-// Functions for stress-testing GC by returning values that require boxing.
+////////////////////////////////////////////////////////////////////////////////
+// Functions for stress-testing.
 
 DART_EXPORT int64_t MinInt64() {
   return 0x8000000000000000;
@@ -505,10 +511,222 @@
   char filename[256];
   snprintf(filename, sizeof(filename), "/tmp/captured_stderr_%d", getpid());
   FILE* f = freopen(filename, "w", stderr);
-  ASSERT(f);
+  if (f == nullptr) {
+    fprintf(stderr, "Could not open temp file.\n");
+    Dart_PrepareToAbort();
+    abort();
+  }
   printf("Got file %s\n", filename);
   return getpid();
 }
 #endif
 
+////////////////////////////////////////////////////////////////////////////////
+// Tests for callbacks.
+
+#define CHECK(X)                                                               \
+  if (!(X)) {                                                                  \
+    fprintf(stderr, "%s\n", "Check failed: " #X);                              \
+    return 1;                                                                  \
+  }
+
+#define CHECK_EQ(X, Y) CHECK((X) == (Y))
+
+// Sanity test.
+DART_EXPORT int TestSimpleAddition(int (*add)(int, int)) {
+  CHECK_EQ(add(10, 20), 30);
+  return 0;
+}
+
+//// Following tests are copied from above, with the role of Dart and C++ code
+//// reversed.
+
+DART_EXPORT int TestIntComputation(
+    int64_t (*fn)(int8_t, int16_t, int32_t, int64_t)) {
+  CHECK_EQ(fn(125, 250, 500, 1000), 625);
+  CHECK_EQ(0x7FFFFFFFFFFFFFFFLL, fn(0, 0, 0, 0x7FFFFFFFFFFFFFFFLL));
+  CHECK_EQ(((int64_t)-0x8000000000000000LL),
+           fn(0, 0, 0, -0x8000000000000000LL));
+  return 0;
+}
+
+DART_EXPORT int TestUintComputation(
+    uint64_t (*fn)(uint8_t, uint16_t, uint32_t, uint64_t)) {
+  CHECK_EQ(0x7FFFFFFFFFFFFFFFLL, fn(0, 0, 0, 0x7FFFFFFFFFFFFFFFLL));
+  CHECK_EQ(-0x8000000000000000LL, fn(0, 0, 0, -0x8000000000000000LL));
+  CHECK_EQ(-1, (int64_t)fn(0, 0, 0, -1));
+  return 0;
+}
+
+DART_EXPORT int TestSimpleMultiply(double (*fn)(double)) {
+  CHECK_EQ(fn(2.0), 2.0 * 1.337);
+  return 0;
+}
+
+DART_EXPORT int TestSimpleMultiplyFloat(float (*fn)(float)) {
+  CHECK(std::abs(fn(2.0) - 2.0 * 1.337) < 0.001);
+  return 0;
+}
+
+DART_EXPORT int TestManyInts(intptr_t (*fn)(intptr_t,
+                                            intptr_t,
+                                            intptr_t,
+                                            intptr_t,
+                                            intptr_t,
+                                            intptr_t,
+                                            intptr_t,
+                                            intptr_t,
+                                            intptr_t,
+                                            intptr_t)) {
+  CHECK_EQ(55, fn(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+  return 0;
+}
+
+DART_EXPORT int TestManyDoubles(double (*fn)(double,
+                                             double,
+                                             double,
+                                             double,
+                                             double,
+                                             double,
+                                             double,
+                                             double,
+                                             double,
+                                             double)) {
+  CHECK_EQ(55, fn(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+  return 0;
+}
+
+DART_EXPORT int TestManyArgs(double (*fn)(intptr_t a,
+                                          float b,
+                                          intptr_t c,
+                                          double d,
+                                          intptr_t e,
+                                          float f,
+                                          intptr_t g,
+                                          double h,
+                                          intptr_t i,
+                                          float j,
+                                          intptr_t k,
+                                          double l,
+                                          intptr_t m,
+                                          float n,
+                                          intptr_t o,
+                                          double p,
+                                          intptr_t q,
+                                          float r,
+                                          intptr_t s,
+                                          double t)) {
+  CHECK(210.0 == fn(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, 12.0, 13, 14.0,
+                    15, 16.0, 17, 18.0, 19, 20.0));
+  return 0;
+}
+
+DART_EXPORT int TestStore(int64_t* (*fn)(int64_t* a)) {
+  int64_t p[2] = {42, 1000};
+  int64_t* result = fn(p);
+  CHECK_EQ(*result, 1337);
+  CHECK_EQ(p[1], 1337);
+  CHECK_EQ(result, p + 1);
+  return 0;
+}
+
+DART_EXPORT int TestReturnNull(int32_t fn()) {
+  CHECK_EQ(fn(), 0);
+  return 0;
+}
+
+DART_EXPORT int TestNullPointers(int64_t* (*fn)(int64_t* ptr)) {
+  CHECK_EQ(fn(nullptr), nullptr);
+  int64_t p[2] = {0};
+  CHECK_EQ(fn(p), p + 1);
+  return 0;
+}
+
+struct CallbackTestData {
+  int success;
+  void (*callback)();
+};
+
+#if defined(TARGET_OS_LINUX)
+
+thread_local sigjmp_buf buf;
+void CallbackTestSignalHandler(int) {
+  siglongjmp(buf, 1);
+}
+
+int ExpectAbort(void (*fn)()) {
+  fprintf(stderr, "**** EXPECT STACKTRACE TO FOLLOW. THIS IS OK. ****\n");
+
+  struct sigaction old_action;
+  int result = __sigsetjmp(buf, /*savesigs=*/1);
+  if (result == 0) {
+    // Install signal handler.
+    struct sigaction handler;
+    handler.sa_handler = CallbackTestSignalHandler;
+    sigemptyset(&handler.sa_mask);
+    handler.sa_flags = 0;
+
+    sigaction(SIGABRT, &handler, &old_action);
+
+    fn();
+  } else {
+    // Caught the setjmp.
+    sigaction(SIGABRT, &old_action, NULL);
+    exit(0);
+  }
+  fprintf(stderr, "Expected abort!!!\n");
+  exit(1);
+}
+
+void* TestCallbackOnThreadOutsideIsolate(void* parameter) {
+  CallbackTestData* data = reinterpret_cast<CallbackTestData*>(parameter);
+  data->success = ExpectAbort(data->callback);
+  return NULL;
+}
+
+int TestCallbackOtherThreadHelper(void* (*tester)(void*), void (*fn)()) {
+  CallbackTestData data = {1, fn};
+  pthread_attr_t attr;
+  int result = pthread_attr_init(&attr);
+  CHECK_EQ(result, 0);
+
+  pthread_t tid;
+  result = pthread_create(&tid, &attr, tester, &data);
+  CHECK_EQ(result, 0);
+
+  result = pthread_attr_destroy(&attr);
+  CHECK_EQ(result, 0);
+
+  void* retval;
+  result = pthread_join(tid, &retval);
+
+  // Doesn't actually return because the other thread will exit when the test is
+  // finished.
+  return 1;
+}
+
+// Run a callback on another thread and verify that it triggers SIGABRT.
+DART_EXPORT int TestCallbackWrongThread(void (*fn)()) {
+  return TestCallbackOtherThreadHelper(&TestCallbackOnThreadOutsideIsolate, fn);
+}
+
+// Verify that we get SIGABRT when invoking a native callback outside an
+// isolate.
+DART_EXPORT int TestCallbackOutsideIsolate(void (*fn)()) {
+  Dart_Isolate current = Dart_CurrentIsolate();
+
+  Dart_ExitIsolate();
+  CallbackTestData data = {1, fn};
+  TestCallbackOnThreadOutsideIsolate(&data);
+  Dart_EnterIsolate(current);
+
+  return data.success;
+}
+
+DART_EXPORT int TestCallbackWrongIsolate(void (*fn)()) {
+  return ExpectAbort(fn);
+}
+
+#endif  // defined(TARGET_OS_LINUX)
+
 }  // namespace dart
diff --git a/runtime/bin/file_fuchsia.cc b/runtime/bin/file_fuchsia.cc
index 1f60fca..74e3c50 100644
--- a/runtime/bin/file_fuchsia.cc
+++ b/runtime/bin/file_fuchsia.cc
@@ -255,9 +255,8 @@
   if (NO_RETRY_EXPECTED(fstatat(ns.fd(), ns.path(), &st, 0)) == 0) {
     // Everything but a directory and a link is a file to Dart.
     return !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode);
-  } else {
-    return false;
   }
+  return false;
 }
 
 bool File::Create(Namespace* namespc, const char* name) {
@@ -265,14 +264,17 @@
   const int fd = NO_RETRY_EXPECTED(
       openat(ns.fd(), ns.path(), O_RDONLY | O_CREAT | O_CLOEXEC, 0666));
   if (fd < 0) {
+    Syslog::PrintErr("File::Create() openat(%ld, %s) failed: %s\n", ns.fd(),
+                     ns.path(), strerror(errno));
     return false;
   }
   // File.create returns a File, so we shouldn't be giving the illusion that the
   // call has created a file or that a file already exists if there is already
   // an entity at the same path that is a directory or a link.
-  bool is_file = true;
+  bool is_file = false;
   struct stat st;
   if (NO_RETRY_EXPECTED(fstat(fd, &st)) == 0) {
+    is_file = true;
     if (S_ISDIR(st.st_mode)) {
       errno = EISDIR;
       is_file = false;
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index af9741e..6af098e 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -83,6 +83,7 @@
   kAppJIT,
   kAppAOTBlobs,
   kAppAOTAssembly,
+  kAppAOTElf,
   kVMAOTAssembly,
 };
 static SnapshotKind snapshot_kind = kCore;
@@ -96,6 +97,7 @@
     "app-jit",
     "app-aot-blobs",
     "app-aot-assembly",
+    "app-aot-elf",
     "vm-aot-assembly",
     NULL,
     // clang-format on
@@ -146,7 +148,7 @@
 
 static bool IsSnapshottingForPrecompilation() {
   return (snapshot_kind == kAppAOTBlobs) ||
-         (snapshot_kind == kAppAOTAssembly) ||
+         (snapshot_kind == kAppAOTAssembly) || (snapshot_kind == kAppAOTElf) ||
          (snapshot_kind == kVMAOTAssembly);
 }
 
@@ -315,7 +317,8 @@
       }
       break;
     }
-    case kAppAOTAssembly: {
+    case kAppAOTAssembly:
+    case kAppAOTElf: {
       if (assembly_filename == NULL) {
         Syslog::PrintErr(
             "Building an AOT snapshot as assembly requires specifying "
@@ -420,10 +423,18 @@
 
   if ((load_compilation_trace_filename != NULL) &&
       ((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT))) {
+    // Finalize all classes. This ensures that there are no non-finalized
+    // classes in the gaps between cid ranges. Such classes prevent merging of
+    // cid ranges.
+    Dart_Handle result = Dart_FinalizeAllClasses();
+    CHECK_RESULT(result);
+    // Sort classes to have better cid ranges.
+    result = Dart_SortClasses();
+    CHECK_RESULT(result);
     uint8_t* buffer = NULL;
     intptr_t size = 0;
     ReadFile(load_compilation_trace_filename, &buffer, &size);
-    Dart_Handle result = Dart_LoadCompilationTrace(buffer, size);
+    result = Dart_LoadCompilationTrace(buffer, size);
     free(buffer);
     CHECK_RESULT(result);
   }
@@ -613,16 +624,17 @@
   CHECK_RESULT(result);
 
   // Create a precompiled snapshot.
-  bool as_assembly = assembly_filename != NULL;
-  if (as_assembly) {
-    ASSERT(snapshot_kind == kAppAOTAssembly);
+  if (snapshot_kind == kAppAOTAssembly) {
     File* file = OpenFile(assembly_filename);
     RefCntReleaseScope<File> rs(file);
     result = Dart_CreateAppAOTSnapshotAsAssembly(StreamingWriteCallback, file);
     CHECK_RESULT(result);
-  } else {
-    ASSERT(snapshot_kind == kAppAOTBlobs);
-
+  } else if (snapshot_kind == kAppAOTElf) {
+    File* file = OpenFile(assembly_filename);
+    RefCntReleaseScope<File> rs(file);
+    result = Dart_CreateAppAOTSnapshotAsElf(StreamingWriteCallback, file);
+    CHECK_RESULT(result);
+  } else if (snapshot_kind == kAppAOTBlobs) {
     const uint8_t* shared_data = NULL;
     const uint8_t* shared_instructions = NULL;
     std::unique_ptr<MappedMemory> mapped_shared_data;
@@ -686,6 +698,8 @@
                 isolate_snapshot_instructions_buffer,
                 isolate_snapshot_instructions_size);
     }
+  } else {
+    UNREACHABLE();
   }
 
   // Serialize obfuscation map if requested.
@@ -777,8 +791,9 @@
     case kAppJIT:
       CreateAndWriteAppJITSnapshot();
       break;
-    case kAppAOTBlobs:
     case kAppAOTAssembly:
+    case kAppAOTBlobs:
+    case kAppAOTElf:
       CreateAndWritePrecompiledSnapshot();
       break;
     case kVMAOTAssembly: {
diff --git a/runtime/bin/namespace_fuchsia.cc b/runtime/bin/namespace_fuchsia.cc
index da60ee0..6e93bcb 100644
--- a/runtime/bin/namespace_fuchsia.cc
+++ b/runtime/bin/namespace_fuchsia.cc
@@ -22,20 +22,32 @@
 
 NamespaceImpl::NamespaceImpl(fdio_ns_t* fdio_ns)
       : fdio_ns_(fdio_ns),
-        rootfd_(fdio_ns_opendir(fdio_ns)),
         cwd_(strdup("/")) {
-  ASSERT(rootfd_ > 0);
+  rootfd_ = fdio_ns_opendir(fdio_ns);
+  if (rootfd_ < 0) {
+    FATAL2("Failed to open file descriptor for namespace: errno=%d: %s", errno,
+           strerror(errno));
+  }
   cwdfd_ = dup(rootfd_);
-  ASSERT(cwdfd_ > 0);
+  if (cwdfd_ < 0) {
+    FATAL2("Failed to dup() namespace file descriptor: errno=%d: %s", errno,
+           strerror(errno));
+  }
 }
 
 NamespaceImpl::NamespaceImpl(const char* path)
       : fdio_ns_(NULL),
-        rootfd_(TEMP_FAILURE_RETRY(open(path, O_DIRECTORY))),
         cwd_(strdup("/")) {
-  ASSERT(rootfd_ > 0);
+  rootfd_ = TEMP_FAILURE_RETRY(open(path, O_DIRECTORY));
+  if (rootfd_ < 0) {
+    FATAL2("Failed to open file descriptor for namespace: errno=%d: %s", errno,
+           strerror(errno));
+  }
   cwdfd_ = dup(rootfd_);
-  ASSERT(cwdfd_ > 0);
+  if (cwdfd_ < 0) {
+    FATAL2("Failed to dup() namespace file descriptor: errno=%d: %s", errno,
+           strerror(errno));
+  }
 }
 
 NamespaceImpl::~NamespaceImpl() {
@@ -54,7 +66,7 @@
   NamespaceScope ns(namespc, new_path);
   const intptr_t new_cwdfd =
       TEMP_FAILURE_RETRY(openat(ns.fd(), ns.path(), O_DIRECTORY));
-  if (new_cwdfd != 0) {
+  if (new_cwdfd < 0) {
     return false;
   }
 
diff --git a/runtime/bin/socket_base_fuchsia.cc b/runtime/bin/socket_base_fuchsia.cc
index b2f6524..a08257d 100644
--- a/runtime/bin/socket_base_fuchsia.cc
+++ b/runtime/bin/socket_base_fuchsia.cc
@@ -181,7 +181,13 @@
 }
 
 void SocketBase::GetError(intptr_t fd, OSError* os_error) {
-  errno = ENOSYS;
+  IOHandle* handle = reinterpret_cast<IOHandle*>(fd);
+  ASSERT(handle->fd() >= 0);
+  int len = sizeof(errno);
+  int err = 0;
+  VOID_NO_RETRY_EXPECTED(getsockopt(handle->fd(), SOL_SOCKET, SO_ERROR, &err,
+                                    reinterpret_cast<socklen_t*>(&len)));
+  errno = err;
   os_error->SetCodeAndMessage(OSError::kSystem, errno);
 }
 
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 870179c..4a87275 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -504,9 +504,21 @@
           // indicate that the socket is fully connected.
           socket.setHandlers(write: () {
             timer.cancel();
+            connecting.remove(socket);
+            // From 'man 2 connect':
+            // After select(2) indicates writability, use getsockopt(2) to read
+            // the SO_ERROR option at level SOL_SOCKET to determine whether
+            // connect() completed successfully (SO_ERROR is zero) or
+            // unsuccessfully.
+            OSError osError = socket.nativeGetError();
+            if (osError.errorCode != 0) {
+              socket.close();
+              if (error == null) error = osError;
+              if (connecting.isEmpty) connectNext();
+              return;
+            }
             socket.setListening(read: false, write: false);
             completer.complete(socket);
-            connecting.remove(socket);
             connecting.forEach((s, t) {
               t.cancel();
               s.close();
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index f144ed4..7103341 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -3266,7 +3266,7 @@
  *  Running this snapshot requires a VM compiled with DART_PRECOMPILED_SNAPSHOT.
  *  The kDartVmSnapshotData and kDartVmSnapshotInstructions should be passed to
  *  Dart_Initialize. The kDartIsolateSnapshotData and
- *  kDartIsoalteSnapshotInstructions should be passed to Dart_CreateIsolate.
+ *  kDartIsolateSnapshotInstructions should be passed to Dart_CreateIsolate.
  *
  *  The callback will be invoked one or more times to provide the assembly code.
  *
@@ -3277,6 +3277,31 @@
                                     void* callback_data);
 
 /**
+ *  Creates a precompiled snapshot.
+ *   - A root library must have been loaded.
+ *   - Dart_Precompile must have been called.
+ *
+ *  Outputs an ELF shared library defining the symbols
+ *   - kDartVmSnapshotData
+ *   - kDartVmSnapshotInstructions
+ *   - kDartIsolateSnapshotData
+ *   - kDartIsolateSnapshotInstructions
+ *
+ *  The shared library should be dynamically loaded by the embedder.
+ *  Running this snapshot requires a VM compiled with DART_PRECOMPILED_SNAPSHOT.
+ *  The kDartVmSnapshotData and kDartVmSnapshotInstructions should be passed to
+ *  Dart_Initialize. The kDartIsolateSnapshotData and
+ *  kDartIsolateSnapshotInstructions should be passed to Dart_CreateIsolate.
+ *
+ *  The callback will be invoked one or more times to provide the binary output.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback,
+                               void* callback_data);
+
+/**
  *  Like Dart_CreateAppAOTSnapshotAsAssembly, but only includes
  *  kDartVmSnapshotData and kDartVmSnapshotInstructions.
  */
diff --git a/runtime/include/dart_native_api.h b/runtime/include/dart_native_api.h
index 39b29ff..3b8f4d2 100644
--- a/runtime/include/dart_native_api.h
+++ b/runtime/include/dart_native_api.h
@@ -170,4 +170,9 @@
 
 DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_ReadAllBytecode();
 
+/**
+ * Finalizes all classes.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_FinalizeAllClasses();
+
 #endif /* INCLUDE_DART_NATIVE_API_H_ */ /* NOLINT */
diff --git a/runtime/lib/bigint_patch.dart b/runtime/lib/bigint_patch.dart
index 2046284..19c1919 100644
--- a/runtime/lib/bigint_patch.dart
+++ b/runtime/lib/bigint_patch.dart
@@ -1986,6 +1986,7 @@
         _rsh(uDigits, maxUsed, 1, uDigits);
         if (ac) {
           if (((aDigits[0] & 1) == 1) || ((bDigits[0] & 1) == 1)) {
+            // a += y
             if (aIsNegative) {
               if ((aDigits[maxUsed] != 0) ||
                   (_compareDigits(aDigits, maxUsed, yDigits, maxUsed)) > 0) {
@@ -1997,6 +1998,7 @@
             } else {
               _absAdd(aDigits, abcdUsed, yDigits, maxUsed, aDigits);
             }
+            // b -= x
             if (bIsNegative) {
               _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
             } else if ((bDigits[maxUsed] != 0) ||
@@ -2009,6 +2011,7 @@
           }
           _rsh(aDigits, abcdUsed, 1, aDigits);
         } else if ((bDigits[0] & 1) == 1) {
+          // b -= x
           if (bIsNegative) {
             _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
           } else if ((bDigits[maxUsed] != 0) ||
@@ -2025,6 +2028,7 @@
         _rsh(vDigits, maxUsed, 1, vDigits);
         if (ac) {
           if (((cDigits[0] & 1) == 1) || ((dDigits[0] & 1) == 1)) {
+            // c += y
             if (cIsNegative) {
               if ((cDigits[maxUsed] != 0) ||
                   (_compareDigits(cDigits, maxUsed, yDigits, maxUsed) > 0)) {
@@ -2036,6 +2040,7 @@
             } else {
               _absAdd(cDigits, abcdUsed, yDigits, maxUsed, cDigits);
             }
+            // d -= x
             if (dIsNegative) {
               _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
             } else if ((dDigits[maxUsed] != 0) ||
@@ -2048,6 +2053,7 @@
           }
           _rsh(cDigits, abcdUsed, 1, cDigits);
         } else if ((dDigits[0] & 1) == 1) {
+          // d -= x
           if (dIsNegative) {
             _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
           } else if ((dDigits[maxUsed] != 0) ||
@@ -2061,8 +2067,10 @@
         _rsh(dDigits, abcdUsed, 1, dDigits);
       }
       if (_compareDigits(uDigits, maxUsed, vDigits, maxUsed) >= 0) {
+        // u -= v
         _absSub(uDigits, maxUsed, vDigits, maxUsed, uDigits);
         if (ac) {
+          // a -= c
           if (aIsNegative == cIsNegative) {
             var a_cmp_c = _compareDigits(aDigits, abcdUsed, cDigits, abcdUsed);
             if (a_cmp_c > 0) {
@@ -2075,6 +2083,7 @@
             _absAdd(aDigits, abcdUsed, cDigits, abcdUsed, aDigits);
           }
         }
+        // b -= d
         if (bIsNegative == dIsNegative) {
           var b_cmp_d = _compareDigits(bDigits, abcdUsed, dDigits, abcdUsed);
           if (b_cmp_d > 0) {
@@ -2087,8 +2096,10 @@
           _absAdd(bDigits, abcdUsed, dDigits, abcdUsed, bDigits);
         }
       } else {
+        // v -= u
         _absSub(vDigits, maxUsed, uDigits, maxUsed, vDigits);
         if (ac) {
+          // c -= a
           if (cIsNegative == aIsNegative) {
             var c_cmp_a = _compareDigits(cDigits, abcdUsed, aDigits, abcdUsed);
             if (c_cmp_a > 0) {
@@ -2101,6 +2112,7 @@
             _absAdd(cDigits, abcdUsed, aDigits, abcdUsed, cDigits);
           }
         }
+        // d -= b
         if (dIsNegative == bIsNegative) {
           var d_cmp_b = _compareDigits(dDigits, abcdUsed, bDigits, abcdUsed);
           if (d_cmp_b > 0) {
@@ -2132,25 +2144,18 @@
     }
 
     if (dIsNegative) {
-      if ((dDigits[maxUsed] != 0) ||
+      while ((dDigits[maxUsed] != 0) ||
           (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+        // d += x, d still negative
         _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-        if ((dDigits[maxUsed] != 0) ||
-            (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-          _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-        } else {
-          _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
-          dIsNegative = false;
-        }
-      } else {
-        _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
-        dIsNegative = false;
       }
-    } else if ((dDigits[maxUsed] != 0) ||
-        (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-      _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-      if ((dDigits[maxUsed] != 0) ||
-          (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+      // d += x
+      _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
+      dIsNegative = false;
+    } else {
+      while ((dDigits[maxUsed] != 0) ||
+          (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) >= 0)) {
+        // d -= x
         _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
       }
     }
diff --git a/runtime/lib/developer.dart b/runtime/lib/developer.dart
index 12ad8b7..cb35073 100644
--- a/runtime/lib/developer.dart
+++ b/runtime/lib/developer.dart
@@ -131,7 +131,7 @@
   assert(id != null);
   StringBuffer sb = new StringBuffer();
   sb.write('{"jsonrpc":"2.0",');
-  if (response._isError()) {
+  if (response.isError()) {
     if (trace_service) {
       print("vm-service: posting error response for request $id");
     }
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index 34a5530..5dd4367 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -9,6 +9,7 @@
 #include "vm/class_finalizer.h"
 #include "vm/compiler/assembler/assembler.h"
 #include "vm/compiler/ffi.h"
+#include "vm/compiler/jit/compiler.h"
 #include "vm/exceptions.h"
 #include "vm/log.h"
 #include "vm/native_arguments.h"
@@ -546,53 +547,68 @@
   return raw_closure;
 }
 
-// Generates assembly to trampoline from C++ back into Dart.
-static void* GenerateFfiInverseTrampoline(const Function& signature,
-                                          void* dart_entry_point) {
+// Generates assembly to trampoline from native code into Dart.
+static uword CompileNativeCallback(const Function& c_signature,
+                                   const Function& dart_target) {
 #if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
   UNREACHABLE();
-#elif !defined(TARGET_ARCH_X64)
+#elif defined(TARGET_ARCH_DBC)
   // https://github.com/dart-lang/sdk/issues/35774
-  UNREACHABLE();
-#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS) &&                \
-    !defined(TARGET_OS_WINDOWS)
-  // https://github.com/dart-lang/sdk/issues/35760 Arm32 && Android
-  // https://github.com/dart-lang/sdk/issues/35772 Arm64
-  // https://github.com/dart-lang/sdk/issues/35773 DBC
-  UNREACHABLE();
+  // FFI is supported, but callbacks are not.
+  Exceptions::ThrowUnsupportedError(
+      "FFI callbacks are not yet supported on DBC.");
 #else
+  Thread* const thread = Thread::Current();
+  const int32_t callback_id = thread->AllocateFfiCallbackId();
 
-  // TODO(dacoharkes): Implement this.
-  // https://github.com/dart-lang/sdk/issues/35761
-  // Look at StubCode::GenerateInvokeDartCodeStub.
-  UNREACHABLE();
+  // Create a new Function named 'FfiCallback' and stick it in the 'dart:ffi'
+  // library. Note that these functions will never be invoked by Dart, so it
+  // doesn't matter that they all have the same name.
+  Zone* const Z = thread->zone();
+  const String& name =
+      String::ZoneHandle(Symbols::New(Thread::Current(), "FfiCallback"));
+  const Library& lib = Library::Handle(Library::FfiLibrary());
+  const Class& owner_class = Class::Handle(lib.toplevel_class());
+  const Function& function =
+      Function::Handle(Z, Function::New(name, RawFunction::kFfiTrampoline,
+                                        /*is_static=*/true,
+                                        /*is_const=*/false,
+                                        /*is_abstract=*/false,
+                                        /*is_external=*/false,
+                                        /*is_native=*/false, owner_class,
+                                        TokenPosition::kMinSource));
+  function.set_is_debuggable(false);
+
+  // Set callback-specific fields which the flow-graph builder needs to generate
+  // the body.
+  function.SetFfiCSignature(c_signature);
+  function.SetFfiCallbackId(callback_id);
+  function.SetFfiCallbackTarget(dart_target);
+
+  // We compile the callback immediately because we need to return a pointer to
+  // the entry-point. Native calls do not use patching like Dart calls, so we
+  // cannot compile it lazily.
+  const Object& result =
+      Object::Handle(Z, Compiler::CompileOptimizedFunction(thread, function));
+  if (result.IsError()) {
+    Exceptions::PropagateError(Error::Cast(result));
+  }
+  ASSERT(result.IsCode());
+  const Code& code = Code::Cast(result);
+
+  thread->SetFfiCallbackCode(callback_id, code);
+
+  return code.EntryPoint();
 #endif
 }
 
-// TODO(dacoharkes): Implement this feature.
-// https://github.com/dart-lang/sdk/issues/35761
-// For now, it always returns Pointer with address 0.
 DEFINE_NATIVE_ENTRY(Ffi_fromFunction, 1, 1) {
   GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Closure, closure, arguments->NativeArgAt(0));
 
-  Function& c_signature = Function::Handle(((Type&)type_arg).signature());
-
+  const Function& native_signature =
+      Function::Handle(((Type&)type_arg).signature());
   Function& func = Function::Handle(closure.function());
-  Code& code = Code::Handle(func.EnsureHasCode());
-  void* entryPoint = reinterpret_cast<void*>(code.EntryPoint());
-
-  THR_Print("Ffi_fromFunction: %s\n", type_arg.ToCString());
-  THR_Print("Ffi_fromFunction: %s\n", c_signature.ToCString());
-  THR_Print("Ffi_fromFunction: %s\n", closure.ToCString());
-  THR_Print("Ffi_fromFunction: %s\n", func.ToCString());
-  THR_Print("Ffi_fromFunction: %s\n", code.ToCString());
-  THR_Print("Ffi_fromFunction: %p\n", entryPoint);
-  THR_Print("Ffi_fromFunction: %" Pd "\n", code.Size());
-
-  intptr_t address = reinterpret_cast<intptr_t>(
-      GenerateFfiInverseTrampoline(c_signature, entryPoint));
-
   TypeArguments& type_args = TypeArguments::Handle(zone);
   type_args = TypeArguments::New(1);
   type_args.SetTypeAt(Pointer::kNativeTypeArgPos, type_arg);
@@ -608,9 +624,19 @@
       ClassFinalizer::FinalizeType(Class::Handle(), native_function_type);
   native_function_type ^= native_function_type.Canonicalize();
 
-  address = 0;  // https://github.com/dart-lang/sdk/issues/35761
+  // The FE verifies that the target of a 'fromFunction' is a static method, so
+  // the value we see here must be a static tearoff. See ffi_use_sites.dart for
+  // details.
+  //
+  // TODO(36748): Define hot-reload semantics of native callbacks. We may need
+  // to look up the target by name.
+  ASSERT(func.IsImplicitClosureFunction());
+  func = func.parent_function();
+  ASSERT(func.is_static());
 
-  Pointer& result = Pointer::Handle(Pointer::New(
+  const uword address = CompileNativeCallback(native_signature, func);
+
+  const Pointer& result = Pointer::Handle(Pointer::New(
       native_function_type, Integer::Handle(zone, Integer::New(address))));
 
   return result.raw();
@@ -682,7 +708,7 @@
     } else if (loc.IsFpuRegister()) {
       descr.SetFpuRegister(loc.fpu_reg(), arg_value);
     } else {
-      ASSERT(loc.IsStackSlot());
+      ASSERT(loc.IsStackSlot() || loc.IsDoubleStackSlot());
       ASSERT(loc.stack_index() < num_stack_slots);
       descr.SetStackSlotValue(loc.stack_index(), arg_value);
     }
diff --git a/runtime/lib/ffi_patch.dart b/runtime/lib/ffi_patch.dart
index c8fde6c..6915d51 100644
--- a/runtime/lib/ffi_patch.dart
+++ b/runtime/lib/ffi_patch.dart
@@ -53,3 +53,21 @@
   @patch
   void free() native "Ffi_free";
 }
+
+// This method gets called when an exception bubbles up to the native -> Dart
+// boundary from an FFI native callback. Since native code does not have any
+// concept of exceptions, the exception cannot be propagated any further.
+// Instead, print a warning with the exception and return 0/0.0 from the
+// callback.
+//
+// TODO(36856): Iron out the story behind exceptions.
+@pragma("vm:entry-point")
+void _handleExposedException(dynamic exception, dynamic stackTrace) {
+  print(
+      "==================== UNHANDLED EXCEPTION FROM FFI CALLBACK ====================");
+  print(
+      """ ** Native callbacks should not throw exceptions because they cannot be
+    propagated into native code. **""");
+  print("EXCEPTION: $exception");
+  print(stackTrace);
+}
diff --git a/runtime/observatory/lib/src/elements/function_view.dart b/runtime/observatory/lib/src/elements/function_view.dart
index 2215806..3be3b2b 100644
--- a/runtime/observatory/lib/src/elements/function_view.dart
+++ b/runtime/observatory/lib/src/elements/function_view.dart
@@ -451,6 +451,8 @@
         return 'collected';
       case M.FunctionKind.native:
         return 'native';
+      case M.FunctionKind.ffiTrampoline:
+        return 'ffi trampoline';
       case M.FunctionKind.stub:
         return 'stub';
       case M.FunctionKind.tag:
diff --git a/runtime/observatory/lib/src/models/objects/function.dart b/runtime/observatory/lib/src/models/objects/function.dart
index 68bd5ae..098003b 100644
--- a/runtime/observatory/lib/src/models/objects/function.dart
+++ b/runtime/observatory/lib/src/models/objects/function.dart
@@ -21,6 +21,7 @@
   invokeFieldDispatcher,
   collected,
   native,
+  ffiTrampoline,
   stub,
   tag,
   signatureFunction,
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index a36dd23..dace8a9 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1225,7 +1225,7 @@
 
 /// State for a running isolate.
 class Isolate extends ServiceObjectOwner implements M.Isolate {
-  static const kLoggingStream = '_Logging';
+  static const kLoggingStream = 'Logging';
   static const kExtensionStream = 'Extension';
 
   VM get vm => owner;
@@ -2104,7 +2104,7 @@
   static const kInspect = 'Inspect';
   static const kDebuggerSettingsUpdate = '_DebuggerSettingsUpdate';
   static const kConnectionClosed = 'ConnectionClosed';
-  static const kLogging = '_Logging';
+  static const kLogging = 'Logging';
   static const kExtension = 'Extension';
   static const kServiceRegistered = 'ServiceRegistered';
   static const kServiceUnregistered = 'ServiceUnregistered';
@@ -3036,6 +3036,8 @@
       return M.FunctionKind.collected;
     case 'Native':
       return M.FunctionKind.native;
+    case 'FfiTrampoline':
+      return M.FunctionKind.ffiTrampoline;
     case 'Stub':
       return M.FunctionKind.stub;
     case 'Tag':
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index ca2028a..f5eb252 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
     var result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], equals('Version'));
     expect(result['major'], equals(3));
-    expect(result['minor'], equals(14));
+    expect(result['minor'], equals(17));
     expect(result['_privateMajor'], equals(0));
     expect(result['_privateMinor'], equals(0));
   },
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 7815569..a3632e8 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -318,6 +318,20 @@
 #endif
 #endif
 
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
+#define TARGET_ARCH_IS_32_BIT 1
+#elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
+#define TARGET_ARCH_IS_64_BIT 1
+#elif defined(TARGET_ARCH_DBC)
+#if defined(ARCH_IS_32_BIT)
+#define TARGET_ARCH_IS_32_BIT 1
+#else
+#define TARGET_ARCH_IS_64_BIT 1
+#endif
+#else
+#error Automatic target architecture detection failed.
+#endif
+
 // Verify that host and target architectures match, we cannot
 // have a 64 bit Dart VM generating 32 bit code or vice-versa.
 #if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
diff --git a/runtime/tests/vm/dart/regress36953_test.dart b/runtime/tests/vm/dart/regress36953_test.dart
new file mode 100644
index 0000000..617049b
--- /dev/null
+++ b/runtime/tests/vm/dart/regress36953_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for dartbug.com/36953: check that phi is inserted correctly
+// when try block has no normal exit.
+
+// VMOptions=--optimization_counter_threshold=10 --deterministic
+
+import "package:expect/expect.dart";
+
+void testBody() {
+  var v;
+  do {
+    try {} catch (e, st) {
+      continue;
+    }
+
+    try {
+      v = 10;
+      throw "";
+    } catch (e, st) {}
+  } while (v++ < 10);
+  Expect.equals(11, v);
+}
+
+void main() {
+  testBody();
+  testBody();
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 79a253b..143f5ca 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -259,18 +259,6 @@
 [ $compiler == dart2analyzer || $compiler == dart2js ]
 dart/data_uri*test: Skip # Data uri's not supported by dart2js or the analyzer.
 
-# Tests that use functionality not supported in Dart 2.
-[ ($compiler == dartk || $compiler == dartkb) || $compiler == dartkp ]
-cc/DartAPI_IsolateSetCheckedMode: SkipByDesign # Checked mode is not relevant for dart 2?
-cc/CompileFunction: SkipByDesign
-cc/InvokeDynamic_CompileError: SkipByDesign
-cc/InvokeStatic_CompileError: SkipByDesign
-cc/DartEntry: SkipByDesign
-cc/FindCodeObject: SkipByDesign
-cc/DartDynamicResolve: SkipByDesign
-cc/DartStaticResolve: SkipByDesign
-cc/CompileScript: SkipByDesign
-
 [ $compiler == precompiler || $mode == product ]
 cc/CoreSnapshotSize: SkipByDesign # Imports dart:mirrors
 cc/CreateMirrorSystem: SkipByDesign # Imports dart:mirrors
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index 5ccc521..6b9f82f 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -177,3 +177,15 @@
     ":vm_platform_stripped",
   ]
 }
+
+executable("offsets_extractor") {
+  configs += [
+    "..:dart_arch_config",
+    "..:dart_config",
+    ":libdart_vm_config",
+  ]
+  sources = [
+    "compiler/offsets_extractor.cc",
+  ]
+  include_dirs = [ ".." ]
+}
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index 9404617..3268bb7 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -39,14 +39,6 @@
   friend class IsolateReloadContext;  // For VisitObjectPointers.
 };
 
-#if defined(ARCH_IS_32_BIT)
-const int kSizeOfClassPairLog2 = 3;
-#else
-const int kSizeOfClassPairLog2 = 4;
-#endif
-
-COMPILE_ASSERT((1 << kSizeOfClassPairLog2) == sizeof(ClassAndSize));
-
 #ifndef PRODUCT
 template <typename T>
 class AllocStats {
@@ -261,6 +253,24 @@
   static intptr_t ClassOffsetFor(intptr_t cid);
 
 #ifndef PRODUCT
+  // Describes layout of heap stats for code generation. See offset_extractor.cc
+  struct ArrayLayout {
+    static intptr_t elements_start_offset() { return 0; }
+
+    static constexpr intptr_t kElementSize = sizeof(ClassHeapStats);
+  };
+#endif
+
+#if defined(ARCH_IS_32_BIT)
+  static constexpr int kSizeOfClassPairLog2 = 3;
+#else
+  static constexpr int kSizeOfClassPairLog2 = 4;
+#endif
+  static_assert(
+      (1 << kSizeOfClassPairLog2) == sizeof(ClassAndSize),
+      "Mismatch between sizeof(ClassAndSize) and kSizeOfClassPairLog2");
+
+#ifndef PRODUCT
   // Called whenever a class is allocated in the runtime.
   void UpdateAllocatedNew(intptr_t cid, intptr_t size) {
     ClassHeapStats* stats = PreliminaryStatsAt(cid);
@@ -286,6 +296,11 @@
   void UpdatePromoted();
 
   // Used by the generated code.
+  static intptr_t class_heap_stats_table_offset() {
+    return OFFSET_OF(ClassTable, class_heap_stats_table_);
+  }
+
+  // Used by the generated code.
   static intptr_t TableOffsetFor(intptr_t cid);
 
   // Used by the generated code.
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index dba74ea..ae78790 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -1552,6 +1552,8 @@
       WriteFromTo(bytecode);
       s->Write<int32_t>(bytecode->ptr()->instructions_binary_offset_);
       s->Write<int32_t>(bytecode->ptr()->source_positions_binary_offset_);
+      NOT_IN_PRODUCT(
+          s->Write<int32_t>(bytecode->ptr()->local_variables_binary_offset_));
     }
   }
 
@@ -1586,6 +1588,8 @@
       ReadFromTo(bytecode);
       bytecode->ptr()->instructions_binary_offset_ = d->Read<int32_t>();
       bytecode->ptr()->source_positions_binary_offset_ = d->Read<int32_t>();
+      NOT_IN_PRODUCT(bytecode->ptr()->local_variables_binary_offset_ =
+                         d->Read<int32_t>());
     }
   }
 
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 29b1fad..9fa7585 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -2172,32 +2172,9 @@
 }
 
 void Precompiler::FinalizeAllClasses() {
-  Library& lib = Library::Handle(Z);
-  Class& cls = Class::Handle(Z);
-
-  for (intptr_t i = 0; i < libraries_.Length(); i++) {
-    lib ^= libraries_.At(i);
-    if (!lib.Loaded()) {
-      String& uri = String::Handle(Z, lib.url());
-      String& msg = String::Handle(
-          Z,
-          String::NewFormatted("Library '%s' is not loaded. "
-                               "Did you forget to call Dart_FinalizeLoading?",
-                               uri.ToCString()));
-      Jump(Error::Handle(Z, ApiError::New(msg)));
-    }
-
-    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
-    while (it.HasNext()) {
-      cls = it.GetNextClass();
-      if (cls.IsDynamicClass()) {
-        continue;  // class 'dynamic' is in the read-only VM isolate.
-      }
-      error_ = cls.EnsureIsFinalized(T);
-      if (!error_.IsNull()) {
-        Jump(error_);
-      }
-    }
+  error_ = Library::FinalizeAllClasses();
+  if (!error_.IsNull()) {
+    Jump(error_);
   }
   I->set_all_classes_finalized(true);
 }
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index 9a40633..dbfc95e 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -548,10 +548,12 @@
 }
 
 void Assembler::TransitionGeneratedToNative(Register destination_address,
+                                            Register exit_frame_fp,
                                             Register addr,
                                             Register state) {
   // Save exit frame information to enable stack walking.
-  StoreToOffset(kWord, FP, THR, Thread::top_exit_frame_info_offset());
+  StoreToOffset(kWord, exit_frame_fp, THR,
+                Thread::top_exit_frame_info_offset());
 
   // Mark that the thread is executing native code.
   StoreToOffset(kWord, destination_address, THR, Thread::vm_tag_offset());
@@ -2496,6 +2498,33 @@
   }
 }
 
+void Assembler::PushNativeCalleeSavedRegisters() {
+  // Save new context and C++ ABI callee-saved registers.
+  PushList(kAbiPreservedCpuRegs);
+
+  const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg);
+  if (TargetCPUFeatures::vfp_supported()) {
+    ASSERT(2 * kAbiPreservedFpuRegCount < 16);
+    // Save FPU registers. 2 D registers per Q register.
+    vstmd(DB_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
+  } else {
+    sub(SP, SP, Operand(kAbiPreservedFpuRegCount * kFpuRegisterSize));
+  }
+}
+
+void Assembler::PopNativeCalleeSavedRegisters() {
+  const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg);
+  // Restore C++ ABI callee-saved registers.
+  if (TargetCPUFeatures::vfp_supported()) {
+    // Restore FPU registers. 2 D registers per Q register.
+    vldmd(IA_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
+  } else {
+    AddImmediate(SP, kAbiPreservedFpuRegCount * kFpuRegisterSize);
+  }
+  // Restore CPU registers.
+  PopList(kAbiPreservedCpuRegs);
+}
+
 void Assembler::MoveRegister(Register rd, Register rm, Condition cond) {
   if (rd != rm) {
     mov(rd, Operand(rm), cond);
@@ -3215,6 +3244,23 @@
   }
 }
 
+void Assembler::EmitEntryFrameVerification(Register scratch) {
+#if defined(DEBUG)
+  Label done;
+  ASSERT(!constant_pool_allowed());
+  LoadImmediate(scratch,
+                compiler::target::frame_layout.exit_link_slot_from_entry_fp *
+                    compiler::target::kWordSize);
+  add(scratch, scratch, Operand(FPREG));
+  cmp(scratch, Operand(SPREG));
+  b(&done, EQ);
+
+  Breakpoint();
+
+  Bind(&done);
+#endif
+}
+
 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) {
   Comment("EnterCallRuntimeFrame");
   // Preserve volatile CPU registers and PP.
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 7d2e40c..ceb1820 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -510,9 +510,12 @@
   void ldrex(Register rd, Register rn, Condition cond = AL);
   void strex(Register rd, Register rt, Register rn, Condition cond = AL);
 
-  // Requires two temporary registers 'scratch0' and 'scratch1' (in addition to
-  // TMP).
+  // Emit code to transition between generated and native modes.
+  //
+  // These require that CSP and SP are equal and aligned and require two scratch
+  // registers (in addition to TMP).
   void TransitionGeneratedToNative(Register destination_address,
+                                   Register exit_frame_fp,
                                    Register scratch0,
                                    Register scratch1);
   void TransitionNativeToGenerated(Register scratch0, Register scratch1);
@@ -917,6 +920,12 @@
   void PushRegisters(const RegisterSet& regs);
   void PopRegisters(const RegisterSet& regs);
 
+  // Push all registers which are callee-saved according to the ARM ABI.
+  void PushNativeCalleeSavedRegisters();
+
+  // Pop all registers which are callee-saved according to the ARM ABI.
+  void PopNativeCalleeSavedRegisters();
+
   void CompareRegisters(Register rn, Register rm) { cmp(rn, Operand(rm)); }
   void BranchIf(Condition condition, Label* label) { b(label, condition); }
 
@@ -1003,6 +1012,13 @@
   void Ret();
   void ReserveAlignedFrameSpace(intptr_t frame_space);
 
+  // In debug mode, this generates code to check that:
+  //   FP + kExitLinkSlotFromEntryFp == SP
+  // or triggers breakpoint otherwise.
+  //
+  // Requires a scratch register in addition to the assembler temporary.
+  void EmitEntryFrameVerification(Register scratch);
+
   // Create a frame for calling into runtime that preserves all volatile
   // registers.  Frame's SP is guaranteed to be correctly aligned and
   // frame_space bytes are reserved under it.
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 63775f1..d56909a 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -1164,6 +1164,23 @@
   }
 }
 
+void Assembler::EmitEntryFrameVerification() {
+#if defined(DEBUG)
+  Label done;
+  ASSERT(!constant_pool_allowed());
+  LoadImmediate(TMP,
+                compiler::target::frame_layout.exit_link_slot_from_entry_fp *
+                    compiler::target::kWordSize);
+  add(TMP, TMP, Operand(FPREG));
+  cmp(TMP, Operand(SPREG));
+  b(&done, EQ);
+
+  Breakpoint();
+
+  Bind(&done);
+#endif
+}
+
 void Assembler::RestoreCodePointer() {
   ldr(CODE_REG, Address(FP, compiler::target::frame_layout.code_from_fp *
                                 target::kWordSize));
@@ -1295,11 +1312,12 @@
 }
 
 void Assembler::TransitionGeneratedToNative(Register destination,
+                                            Register new_exit_rame,
                                             Register state) {
   Register addr = TMP2;
 
   // Save exit frame information to enable stack walking.
-  StoreToOffset(FPREG, THR,
+  StoreToOffset(new_exit_rame, THR,
                 compiler::target::Thread::top_exit_frame_info_offset());
 
   // Mark that the thread is executing native code.
@@ -1826,6 +1844,41 @@
   }
 }
 
+void Assembler::PushNativeCalleeSavedRegisters() {
+  // Save the callee-saved registers.
+  for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) {
+    const Register r = static_cast<Register>(i);
+    // We use str instead of the Push macro because we will be pushing the PP
+    // register when it is not holding a pool-pointer since we are coming from
+    // C++ code.
+    str(r, Address(SP, -1 * target::kWordSize, Address::PreIndex));
+  }
+
+  // Save the bottom 64-bits of callee-saved V registers.
+  for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) {
+    const VRegister r = static_cast<VRegister>(i);
+    PushDouble(r);
+  }
+}
+
+void Assembler::PopNativeCalleeSavedRegisters() {
+  // Restore the bottom 64-bits of callee-saved V registers.
+  for (int i = kAbiLastPreservedFpuReg; i >= kAbiFirstPreservedFpuReg; i--) {
+    const VRegister r = static_cast<VRegister>(i);
+    PopDouble(r);
+  }
+
+  // Restore C++ ABI callee-saved registers.
+  for (int i = kAbiLastPreservedCpuReg; i >= kAbiFirstPreservedCpuReg; i--) {
+    Register r = static_cast<Register>(i);
+    // We use ldr instead of the Pop macro because we will be popping the PP
+    // register when it is not holding a pool-pointer since we are returning to
+    // C++ code. We also skip the dart stack pointer SP, since we are still
+    // using it as the stack pointer.
+    ldr(r, Address(SP, 1 * target::kWordSize, Address::PostIndex));
+  }
+}
+
 }  // namespace compiler
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 1a0cfb7..cb9af12 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -438,6 +438,12 @@
   void PushRegisters(const RegisterSet& registers);
   void PopRegisters(const RegisterSet& registers);
 
+  // Push all registers which are callee-saved according to the ARM64 ABI.
+  void PushNativeCalleeSavedRegisters();
+
+  // Pop all registers which are callee-saved according to the ARM64 ABI.
+  void PopNativeCalleeSavedRegisters();
+
   void MoveRegister(Register rd, Register rn) {
     if (rd != rn) {
       mov(rd, rn);
@@ -481,6 +487,11 @@
 
   void ReserveAlignedFrameSpace(intptr_t frame_space);
 
+  // In debug mode, this generates code to check that:
+  //   FP + kExitLinkSlotFromEntryFp == SP
+  // or triggers breakpoint otherwise.
+  void EmitEntryFrameVerification();
+
   // Instruction pattern from entrypoint is used in Dart frame prologs
   // to set up the frame and save a PC which can be used to figure out the
   // RawInstruction object corresponding to the code running in the frame.
@@ -1524,9 +1535,13 @@
   void LeaveFrame();
   void Ret() { ret(LR); }
 
-  // These require that CSP and SP are equal and aligned.
-  // These require a scratch register (in addition to TMP/TMP2).
+  // Emit code to transition between generated mode and native mode.
+  //
+  // These require that CSP and SP are equal and aligned and require a scratch
+  // register (in addition to TMP/TMP2).
+
   void TransitionGeneratedToNative(Register destination_address,
+                                   Register new_exit_frame,
                                    Register scratch);
   void TransitionNativeToGenerated(Register scratch);
 
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 32656b9..a451572 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2084,10 +2084,23 @@
   }
 }
 
+void Assembler::EmitEntryFrameVerification() {
+#if defined(DEBUG)
+  Label ok;
+  leal(EAX, Address(EBP, target::frame_layout.exit_link_slot_from_entry_fp *
+                             target::kWordSize));
+  cmpl(EAX, ESP);
+  j(EQUAL, &ok);
+  Stop("target::frame_layout.exit_link_slot_from_entry_fp mismatch");
+  Bind(&ok);
+#endif
+}
+
 void Assembler::TransitionGeneratedToNative(Register destination_address,
+                                            Register new_exit_frame,
                                             Register scratch) {
   // Save exit frame information to enable stack walking.
-  movl(Address(THR, Thread::top_exit_frame_info_offset()), FPREG);
+  movl(Address(THR, Thread::top_exit_frame_info_offset()), new_exit_frame);
 
   // Mark that the thread is executing native code.
   movl(VMTagAddress(), destination_address);
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index df07d96..ad6149b 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -648,9 +648,23 @@
 
   void MonomorphicCheckedEntry() {}
 
+  // In debug mode, this generates code to check that:
+  //   FP + kExitLinkSlotFromEntryFp == SP
+  // or triggers breakpoint otherwise.
+  //
+  // Clobbers EAX.
+  void EmitEntryFrameVerification();
+
+  // Transitions safepoint and Thread state between generated and native code.
+  // Updates top-exit-frame info, VM tag and execution-state. Leaves/enters a
+  // safepoint.
+  //
   // Require a temporary register 'tmp'.
   // Clobber all non-CPU registers (e.g. XMM registers and the "FPU stack").
+  // However XMM0 is saved for convenience.
+
   void TransitionGeneratedToNative(Register destination_address,
+                                   Register new_exit_frame,
                                    Register scratch);
   void TransitionNativeToGenerated(Register scratch);
 
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 073a179..f9e725b 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -164,9 +164,10 @@
   EmitUint8(0xC0 + (dst & 0x07));
 }
 
-void Assembler::TransitionGeneratedToNative(Register destination_address) {
+void Assembler::TransitionGeneratedToNative(Register destination_address,
+                                            Register new_exit_frame) {
   // Save exit frame information to enable stack walking.
-  movq(Address(THR, Thread::top_exit_frame_info_offset()), FPREG);
+  movq(Address(THR, Thread::top_exit_frame_info_offset()), new_exit_frame);
 
   movq(Assembler::VMTagAddress(), destination_address);
   movq(Address(THR, compiler::target::Thread::execution_state_offset()),
@@ -1517,6 +1518,18 @@
   }
 }
 
+void Assembler::EmitEntryFrameVerification() {
+#if defined(DEBUG)
+  Label ok;
+  leaq(RAX, Address(RBP, target::frame_layout.exit_link_slot_from_entry_fp *
+                             target::kWordSize));
+  cmpq(RAX, RSP);
+  j(EQUAL, &ok);
+  Stop("target::frame_layout.exit_link_slot_from_entry_fp mismatch");
+  Bind(&ok);
+#endif
+}
+
 void Assembler::PushRegisters(intptr_t cpu_register_set,
                               intptr_t xmm_register_set) {
   const intptr_t xmm_regs_count = RegisterSet::RegisterCount(xmm_register_set);
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 1fe5400..4df9250 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -306,7 +306,8 @@
 
   void setcc(Condition condition, ByteRegister dst);
 
-  void TransitionGeneratedToNative(Register destination_address);
+  void TransitionGeneratedToNative(Register destination_address,
+                                   Register new_exit_frame);
   void TransitionNativeToGenerated();
 
 // Register-register, register-address and address-register instructions.
@@ -777,6 +778,13 @@
   void LeaveFrame();
   void ReserveAlignedFrameSpace(intptr_t frame_space);
 
+  // In debug mode, generates code to verify that:
+  //   FP + kExitLinkSlotFromFp == SP
+  //
+  // Triggers breakpoint otherwise.
+  // Clobbers RAX.
+  void EmitEntryFrameVerification();
+
   // Create a frame for calling into runtime that preserves all volatile
   // registers.  Frame's RSP is guaranteed to be correctly aligned and
   // frame_space bytes are reserved under it.
diff --git a/runtime/vm/compiler/assembler/disassembler_kbc.cc b/runtime/vm/compiler/assembler/disassembler_kbc.cc
index 411e1cf..edd8506 100644
--- a/runtime/vm/compiler/assembler/disassembler_kbc.cc
+++ b/runtime/vm/compiler/assembler/disassembler_kbc.cc
@@ -8,6 +8,7 @@
 #include "vm/compiler/assembler/disassembler_kbc.h"
 
 #include "platform/assert.h"
+#include "vm/compiler/frontend/bytecode_reader.h"
 #include "vm/constants_kbc.h"
 #include "vm/cpu.h"
 #include "vm/instructions.h"
@@ -330,7 +331,6 @@
                                                    uword pc) {
   const KBCInstr* instr = reinterpret_cast<const KBCInstr*>(pc);
   const KernelBytecode::Opcode opcode = KernelBytecode::DecodeOpcode(instr);
-  ASSERT(opcode < kOpcodeCount);
   const intptr_t instr_size = KernelBytecode::kInstructionSize[opcode];
 
   size_t name_size =
@@ -409,10 +409,35 @@
       PcDescriptors::Handle(zone, bytecode.pc_descriptors());
   THR_Print("%s}\n", descriptors.ToCString());
 
+  if (bytecode.HasSourcePositions()) {
+    THR_Print("Source positions for function '%s' {\n", function_fullname);
+    // 4 bits per hex digit + 2 for "0x".
+    const int addr_width = (kBitsPerWord / 4) + 2;
+    // "*" in a printf format specifier tells it to read the field width from
+    // the printf argument list.
+    THR_Print("%-*s\ttok-ix\n", addr_width, "pc");
+    kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
+    while (iter.MoveNext()) {
+      THR_Print("%#-*" Px "\t%s\n", addr_width,
+                bytecode.PayloadStart() + iter.PcOffset(),
+                iter.TokenPos().ToCString());
+    }
+    THR_Print("}\n");
+  }
+
   THR_Print("Exception Handlers for function '%s' {\n", function_fullname);
   const ExceptionHandlers& handlers =
       ExceptionHandlers::Handle(zone, bytecode.exception_handlers());
   THR_Print("%s}\n", handlers.ToCString());
+
+  if (FLAG_print_variable_descriptors) {
+    THR_Print("Local variable descriptors for function '%s' {\n",
+              function_fullname);
+    const auto& var_descriptors =
+        LocalVarDescriptors::Handle(zone, bytecode.GetLocalVarDescriptors());
+    THR_Print("%s\n}\n", var_descriptors.ToCString());
+  }
+
 #else
   UNREACHABLE();
 #endif
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 931ffa3..dc78a0e 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -142,6 +142,10 @@
   }
 }
 
+void ConstantPropagator::VisitNativeEntry(NativeEntryInstr* block) {
+  VisitFunctionEntry(block);
+}
+
 void ConstantPropagator::VisitOsrEntry(OsrEntryInstr* block) {
   for (auto def : *block->initial_definitions()) {
     def->Accept(this);
@@ -192,6 +196,10 @@
   // Nothing to do.
 }
 
+void ConstantPropagator::VisitNativeReturn(NativeReturnInstr* instr) {
+  // Nothing to do.
+}
+
 void ConstantPropagator::VisitThrow(ThrowInstr* instr) {
   // Nothing to do.
 }
@@ -365,6 +373,10 @@
   SetValue(instr, non_constant_);
 }
 
+void ConstantPropagator::VisitNativeParameter(NativeParameterInstr* instr) {
+  SetValue(instr, non_constant_);
+}
+
 void ConstantPropagator::VisitPushArgument(PushArgumentInstr* instr) {
   if (SetValue(instr, instr->value()->definition()->constant_value())) {
     // The worklist implementation breaks down around push arguments,
@@ -844,9 +856,23 @@
 }
 
 void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) {
+  // This first part duplicates the work done in LoadClassIdInstr::Canonicalize,
+  // which replaces uses of LoadClassIdInstr where the object has a concrete
+  // type with a Constant. Canonicalize runs before the ConstantPropagation
+  // pass, so if that was all, this wouldn't be needed.
+  //
+  // However, the ConstantPropagator also runs as part of OptimizeBranches, and
+  // TypePropagation runs between it and the previous Canonicalize. Thus, the
+  // type may have become concrete and we should take that into account. Not
+  // doing so led to some benchmark regressions.
+  intptr_t cid = instr->object()->Type()->ToCid();
+  if (cid != kDynamicCid) {
+    SetValue(instr, Smi::ZoneHandle(Z, Smi::New(cid)));
+    return;
+  }
   const Object& object = instr->object()->definition()->constant_value();
   if (IsConstant(object)) {
-    const intptr_t cid = object.GetClassId();
+    cid = object.GetClassId();
     SetValue(instr, Smi::ZoneHandle(Z, Smi::New(cid)));
     return;
   }
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 7761a49..0a590a3 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -756,10 +756,12 @@
     // to the kill set.
     const bool is_function_entry = block->IsFunctionEntry();
     const bool is_osr_entry = block->IsOsrEntry();
-    if (is_function_entry || is_osr_entry || block->IsCatchBlockEntry()) {
+    const bool is_catch_block_entry = block->IsCatchBlockEntry();
+    if (is_function_entry || is_osr_entry || is_catch_block_entry) {
       const intptr_t parameter_count =
-          is_osr_entry ? flow_graph_->variable_count()
-                       : flow_graph_->num_direct_parameters();
+          (is_osr_entry || is_catch_block_entry)
+              ? flow_graph_->variable_count()
+              : flow_graph_->num_direct_parameters();
       for (intptr_t i = 0; i < parameter_count; ++i) {
         live_in->Remove(i);
         kill->Add(i);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 73c21d8..eee9a38 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -42,6 +42,8 @@
             false,
             "Inlining interval diagnostics");
 
+DEFINE_FLAG(bool, enable_peephole, true, "Enable peephole optimization");
+
 #if !defined(DART_PRECOMPILED_RUNTIME)
 
 DEFINE_FLAG(bool,
@@ -511,6 +513,35 @@
                        line.ToCString());
 }
 
+#if !defined(TARGET_ARCH_DBC)
+
+static bool IsPusher(Instruction* instr) {
+  if (auto def = instr->AsDefinition()) {
+    return def->HasTemp();
+  }
+  return false;
+}
+
+static bool IsPopper(Instruction* instr) {
+  // TODO(ajcbik): even allow deopt targets by making environment aware?
+  if (!instr->CanBecomeDeoptimizationTarget()) {
+    return !instr->IsPushArgument() && instr->ArgumentCount() == 0 &&
+           instr->InputCount() > 0;
+  }
+  return false;
+}
+
+#endif
+
+bool FlowGraphCompiler::IsPeephole(Instruction* instr) const {
+#if !defined(TARGET_ARCH_DBC)
+  if (FLAG_enable_peephole && !is_optimizing()) {
+    return IsPusher(instr) && IsPopper(instr->next());
+  }
+#endif
+  return false;
+}
+
 void FlowGraphCompiler::VisitBlocks() {
   CompactBlocks();
   if (Assembler::EmittingComments()) {
@@ -585,7 +616,12 @@
         pending_deoptimization_env_ = instr->env();
         instr->EmitNativeCode(this);
         pending_deoptimization_env_ = NULL;
-        EmitInstructionEpilogue(instr);
+        if (IsPeephole(instr)) {
+          ASSERT(top_of_stack_ == nullptr);
+          top_of_stack_ = instr->AsDefinition();
+        } else {
+          EmitInstructionEpilogue(instr);
+        }
         EndCodeSourceRange(instr->token_pos());
       }
 
@@ -1075,22 +1111,19 @@
 #if defined(PRODUCT)
 // No debugger: no var descriptors.
 #else
-  // TODO(alexmarkov): revise local vars descriptors when compiling bytecode
-  if (code.is_optimized() ||
-      flow_graph().function().is_declared_in_bytecode() ||
-      flow_graph().function().HasBytecode()) {
+  if (code.is_optimized()) {
     // Optimized code does not need variable descriptors. They are
     // only stored in the unoptimized version.
     code.set_var_descriptors(Object::empty_var_descriptors());
     return;
   }
   LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle();
-  if (parsed_function().node_sequence() == NULL) {
+  if (flow_graph().IsIrregexpFunction()) {
     // Eager local var descriptors computation for Irregexp function as it is
     // complicated to factor out.
     // TODO(srdjan): Consider canonicalizing and reusing the local var
     // descriptor for IrregexpFunction.
-    ASSERT(flow_graph().IsIrregexpFunction());
+    ASSERT(parsed_function().node_sequence() == nullptr);
     var_descs = LocalVarDescriptors::New(1);
     RawLocalVarDescriptors::VarInfo info;
     info.set_kind(RawLocalVarDescriptors::kSavedCurrentContext);
@@ -1364,7 +1397,7 @@
                                : ic_data.arguments_descriptor());
   ASSERT(ArgumentsDescriptor(arguments_descriptor).TypeArgsLen() ==
          args_info.type_args_len);
-  if (is_optimizing()) {
+  if (is_optimizing() && !ForcedOptimization()) {
     EmitOptimizedStaticCall(function, arguments_descriptor,
                             args_info.count_with_type_args, deopt_id, token_pos,
                             locs, entry_kind);
@@ -1470,6 +1503,21 @@
 
   bool blocked_registers[kNumberOfCpuRegisters];
 
+  // Connect input with peephole output for some special cases. All other
+  // cases are handled by simply allocating registers and generating code.
+  if (top_of_stack_ != nullptr) {
+    const intptr_t p = locs->input_count() - 1;
+    Location peephole = top_of_stack_->locs()->out(0);
+    if (locs->in(p).IsUnallocated() || locs->in(p).IsConstant()) {
+      // If input is unallocated, match with an output register, if set. Also,
+      // if input is a direct constant, but the peephole output is a register,
+      // use that register to avoid wasting the already generated code.
+      if (peephole.IsRegister()) {
+        locs->set_in(p, Location::RegisterLocation(peephole.reg()));
+      }
+    }
+  }
+
   // Block all registers globally reserved by the assembler, etc and mark
   // the rest as free.
   for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
@@ -1518,10 +1566,17 @@
     }
     ASSERT(reg != kNoRegister || loc.IsConstant());
 
-    // Inputs are consumed from the simulated frame. In case of a call argument
-    // we leave it until the call instruction.
+    // Inputs are consumed from the simulated frame (or a peephole push/pop).
+    // In case of a call argument we leave it until the call instruction.
     if (should_pop) {
-      if (loc.IsConstant()) {
+      if (top_of_stack_ != nullptr) {
+        if (!loc.IsConstant()) {
+          // Moves top of stack location of the peephole into the required
+          // input. None of the required moves needs a temp register allocator.
+          EmitMove(locs->in(i), top_of_stack_->locs()->out(0), nullptr);
+        }
+        top_of_stack_ = nullptr;  // consumed!
+      } else if (loc.IsConstant()) {
         assembler()->Drop(1);
       } else {
         assembler()->PopRegister(reg);
@@ -2047,6 +2102,7 @@
                                         intptr_t total_ic_calls,
                                         Code::EntryKind entry_kind) {
   ASSERT(is_optimizing());
+  ASSERT(complete || (failed != nullptr));  // Complete calls can't fail.
 
   const Array& arguments_descriptor =
       Array::ZoneHandle(zone(), args_info.ToArgumentsDescriptor());
@@ -2081,8 +2137,13 @@
 
   if (smi_case != kNoCase) {
     Label after_smi_test;
-    EmitTestAndCallSmiBranch(non_smi_length == 0 ? failed : &after_smi_test,
-                             /* jump_if_smi= */ false);
+    // If the call is complete and there are no other possible receiver
+    // classes - then receiver can only be a smi value and we don't need
+    // to check if it is a smi.
+    if (!(complete && non_smi_length == 0)) {
+      EmitTestAndCallSmiBranch(non_smi_length == 0 ? failed : &after_smi_test,
+                               /* jump_if_smi= */ false);
+    }
 
     // Do not use the code from the function, but let the code be patched so
     // that we can record the outgoing edges to other code.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 8795377..28c369b 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -409,6 +409,11 @@
     return block_order_;
   }
 
+  // If 'ForcedOptimization()' returns 'true', we are compiling in optimized
+  // mode for a function which cannot deoptimize. Certain optimizations, e.g.
+  // speculative optimizations and call patching are disabled.
+  bool ForcedOptimization() const { return function().ForceOptimize(); }
+
   const FlowGraph& flow_graph() const { return flow_graph_; }
 
   BlockEntryInstr* current_block() const { return current_block_; }
@@ -1025,6 +1030,10 @@
   void FrameStateClear();
 #endif
 
+  // Returns true if instruction lookahead (window size one)
+  // is amenable to a peephole optimization.
+  bool IsPeephole(Instruction* instr) const;
+
   // This struct contains either function or code, the other one being NULL.
   class StaticCallsStruct : public ZoneAllocated {
    public:
@@ -1089,6 +1098,11 @@
   bool fully_intrinsified_ = false;
   CodeStatistics* stats_;
 
+  // The definition whose value is supposed to be at the top of the
+  // expression stack. Used by peephole optimization (window size one)
+  // to eliminate redundant push/pop pairs.
+  Definition* top_of_stack_ = nullptr;
+
   const Class& double_class_;
   const Class& mint_class_;
   const Class& float32x4_class_;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index d968031..598cc1c 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -1309,6 +1309,8 @@
 void FlowGraphCompiler::EmitMove(Location destination,
                                  Location source,
                                  TemporaryRegisterAllocator* allocator) {
+  if (destination.Equals(source)) return;
+
   if (source.IsRegister()) {
     if (destination.IsRegister()) {
       __ mov(destination.reg(), Operand(source.reg()));
@@ -1430,12 +1432,14 @@
     if (TargetCPUFeatures::neon_supported()) {
       const QRegister dst = destination.fpu_reg();
       const QRegister src = source.fpu_reg();
+      ASSERT(dst != QTMP && src != QTMP);
       __ vmovq(QTMP, src);
       __ vmovq(src, dst);
       __ vmovq(dst, QTMP);
     } else {
       const DRegister dst = EvenDRegisterOf(destination.fpu_reg());
       const DRegister src = EvenDRegisterOf(source.fpu_reg());
+      ASSERT(dst != DTMP && src != DTMP);
       __ vmovd(DTMP, src);
       __ vmovd(src, dst);
       __ vmovd(dst, DTMP);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 3eeac84..505a96a 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -1160,8 +1160,8 @@
   }
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
-  GenerateStaticDartCall(deopt_id, token_pos,
-                         RawPcDescriptors::kOther, locs, function);
+  GenerateStaticDartCall(deopt_id, token_pos, RawPcDescriptors::kOther, locs,
+                         function);
   __ Drop(count_with_type_args);
 }
 
@@ -1297,6 +1297,8 @@
 void FlowGraphCompiler::EmitMove(Location destination,
                                  Location source,
                                  TemporaryRegisterAllocator* allocator) {
+  if (destination.Equals(source)) return;
+
   if (source.IsRegister()) {
     if (destination.IsRegister()) {
       __ mov(destination.reg(), source.reg());
@@ -1309,6 +1311,10 @@
     if (destination.IsRegister()) {
       const intptr_t source_offset = source.ToStackSlotOffset();
       __ LoadFromOffset(destination.reg(), source.base_reg(), source_offset);
+    } else if (destination.IsFpuRegister()) {
+      const intptr_t src_offset = source.ToStackSlotOffset();
+      VRegister dst = destination.fpu_reg();
+      __ LoadDFromOffset(dst, source.base_reg(), src_offset);
     } else {
       ASSERT(destination.IsStackSlot());
       const intptr_t source_offset = source.ToStackSlotOffset();
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 5cf94a8..4cea80a 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -1182,6 +1182,8 @@
 void FlowGraphCompiler::EmitMove(Location destination,
                                  Location source,
                                  TemporaryRegisterAllocator* tmp) {
+  if (destination.Equals(source)) return;
+
   if (source.IsRegister()) {
     if (destination.IsRegister()) {
       __ movl(destination.reg(), source.reg());
@@ -1192,6 +1194,9 @@
   } else if (source.IsStackSlot()) {
     if (destination.IsRegister()) {
       __ movl(destination.reg(), LocationToStackSlotAddress(source));
+    } else if (destination.IsFpuRegister()) {
+      // 32-bit float
+      __ movss(destination.fpu_reg(), LocationToStackSlotAddress(source));
     } else {
       ASSERT(destination.IsStackSlot());
       Register scratch = tmp->AllocateTemporary();
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index c2aeb5e..170af1e 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -27,6 +27,7 @@
 #include "vm/regexp_assembler_ir.h"
 #include "vm/resolver.h"
 #include "vm/scopes.h"
+#include "vm/stack_frame.h"
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
 #include "vm/type_testing_stubs.h"
@@ -649,24 +650,75 @@
   return cids;
 }
 
-Cids* Cids::Create(Zone* zone, const ICData& ic_data, int argument_number) {
+Cids* Cids::CreateAndExpand(Zone* zone,
+                            const ICData& ic_data,
+                            int argument_number) {
   Cids* cids = new (zone) Cids(zone);
   cids->CreateHelper(zone, ic_data, argument_number,
                      /* include_targets = */ false);
   cids->Sort(OrderById);
 
   // Merge adjacent class id ranges.
-  int dest = 0;
-  for (int src = 1; src < cids->length(); src++) {
-    if (cids->cid_ranges_[dest]->cid_end + 1 >=
-        cids->cid_ranges_[src]->cid_start) {
-      cids->cid_ranges_[dest]->cid_end = cids->cid_ranges_[src]->cid_end;
-    } else {
-      dest++;
-      if (src != dest) cids->cid_ranges_[dest] = cids->cid_ranges_[src];
+  {
+    int dest = 0;
+    for (int src = 1; src < cids->length(); src++) {
+      if (cids->cid_ranges_[dest]->cid_end + 1 >=
+          cids->cid_ranges_[src]->cid_start) {
+        cids->cid_ranges_[dest]->cid_end = cids->cid_ranges_[src]->cid_end;
+      } else {
+        dest++;
+        if (src != dest) cids->cid_ranges_[dest] = cids->cid_ranges_[src];
+      }
+    }
+    cids->SetLength(dest + 1);
+  }
+
+  // Merging/extending cid ranges is also done in CallTargets::CreateAndExpand.
+  // If changing this code, consider also adjusting CallTargets code.
+
+  if (cids->length() > 1 && argument_number == 0 && ic_data.HasOneTarget()) {
+    // Try harder to merge ranges if method lookups in the gaps result in the
+    // same target method.
+    const Function& target = Function::Handle(zone, ic_data.GetTargetAt(0));
+    if (!MethodRecognizer::PolymorphicTarget(target)) {
+      const auto& args_desc_array =
+          Array::Handle(zone, ic_data.arguments_descriptor());
+      ArgumentsDescriptor args_desc(args_desc_array);
+      const auto& name = String::Handle(zone, ic_data.target_name());
+      auto& fn = Function::Handle(zone);
+
+      intptr_t dest = 0;
+      for (intptr_t src = 1; src < cids->length(); src++) {
+        // Inspect all cids in the gap and see if they all resolve to the same
+        // target.
+        bool can_merge = true;
+        for (intptr_t cid = cids->cid_ranges_[dest]->cid_end + 1,
+                      end = cids->cid_ranges_[src]->cid_start;
+             cid < end; ++cid) {
+          bool class_is_abstract = false;
+          if (FlowGraphCompiler::LookupMethodFor(cid, name, args_desc, &fn,
+                                                 &class_is_abstract)) {
+            if (fn.raw() == target.raw()) {
+              continue;
+            }
+            if (class_is_abstract) {
+              continue;
+            }
+          }
+          can_merge = false;
+          break;
+        }
+
+        if (can_merge) {
+          cids->cid_ranges_[dest]->cid_end = cids->cid_ranges_[src]->cid_end;
+        } else {
+          dest++;
+          if (src != dest) cids->cid_ranges_[dest] = cids->cid_ranges_[src];
+        }
+      }
+      cids->SetLength(dest + 1);
     }
   }
-  cids->SetLength(dest + 1);
 
   return cids;
 }
@@ -2727,6 +2779,11 @@
       if (call->is_known_list_constructor() &&
           IsFixedLengthArrayCid(call->Type()->ToCid())) {
         return call->ArgumentAt(1);
+      } else if (call->function().recognized_kind() ==
+                 MethodRecognizer::kByteDataFactory) {
+        // Similarly, we check for the ByteData constructor and forward its
+        // explicit length argument appropriately.
+        return call->ArgumentAt(1);
       } else if (IsTypedDataViewFactory(call->function())) {
         // Typed data view factories all take three arguments (after
         // the implicit type arguments parameter):
@@ -2769,6 +2826,11 @@
     if (StaticCallInstr* call = array->AsStaticCall()) {
       if (IsTypedDataViewFactory(call->function())) {
         return call->ArgumentAt(2);
+      } else if (call->function().recognized_kind() ==
+                 MethodRecognizer::kByteDataFactory) {
+        // A _ByteDataView returned from the ByteData constructor always
+        // has an offset of 0.
+        return flow_graph->GetConstant(Smi::Handle(Smi::New(0)));
       }
     }
   } else if (slot().IsTypeArguments()) {
@@ -2776,10 +2838,16 @@
     if (StaticCallInstr* call = array->AsStaticCall()) {
       if (call->is_known_list_constructor()) {
         return call->ArgumentAt(0);
-      } else if (call->function().recognized_kind() ==
-                 MethodRecognizer::kLinkedHashMap_getData) {
+      } else if (IsTypedDataViewFactory(call->function())) {
         return flow_graph->constant_null();
       }
+      switch (call->function().recognized_kind()) {
+        case MethodRecognizer::kByteDataFactory:
+        case MethodRecognizer::kLinkedHashMap_getData:
+          return flow_graph->constant_null();
+        default:
+          break;
+      }
     } else if (CreateArrayInstr* create_array = array->AsCreateArray()) {
       return create_array->element_type()->definition();
     } else if (LoadFieldInstr* load_array = array->AsLoadField()) {
@@ -3522,6 +3590,11 @@
   if (call->is_known_list_constructor() &&
       LoadFieldInstr::IsFixedLengthArrayCid(call->Type()->ToCid())) {
     length = call->ArgumentAt(1)->AsConstant();
+  } else if (call->function().recognized_kind() ==
+             MethodRecognizer::kByteDataFactory) {
+    length = call->ArgumentAt(1)->AsConstant();
+  } else if (LoadFieldInstr::IsTypedDataViewFactory(call->function())) {
+    length = call->ArgumentAt(3)->AsConstant();
   }
   if ((length != NULL) && length->value().IsSmi() &&
       Smi::Cast(length->value()).Value() == expected_length) {
@@ -3651,6 +3724,9 @@
 
   intptr_t length = targets.length();
 
+  // Merging/extending cid ranges is also done in Cids::CreateAndExpand.
+  // If changing this code, consider also adjusting Cids code.
+
   // Spread class-ids to preceding classes where a lookup yields the same
   // method.  A polymorphic target is not really the same method since its
   // behaviour depends on the receiver class-id, so we don't spread the
@@ -3825,7 +3901,9 @@
     __ nop();
   }
 #endif
-  __ Bind(compiler->GetJumpLabel(this));
+  if (tag() == Instruction::kFunctionEntry) {
+    __ Bind(compiler->GetJumpLabel(this));
+  }
 
 // In the AOT compiler we want to reduce code size, so generate no
 // fall-through code in [FlowGraphCompiler::CompileGraph()].
@@ -3877,6 +3955,11 @@
   }
 }
 
+LocationSummary* NativeEntryInstr::MakeLocationSummary(Zone* zone,
+                                                       bool optimizing) const {
+  UNREACHABLE();
+}
+
 LocationSummary* OsrEntryInstr::MakeLocationSummary(Zone* zone,
                                                     bool optimizing) const {
   UNREACHABLE();
@@ -3982,6 +4065,43 @@
   UNREACHABLE();
 }
 
+void NativeParameterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if !defined(TARGET_ARCH_DBC)
+  // The native entry frame has size -kExitLinkSlotFromFp. In order to access
+  // the top of stack from above the entry frame, we add a constant to account
+  // for the the two frame pointers and two return addresses of the entry frame.
+  constexpr intptr_t kEntryFramePadding = 4;
+  FrameRebase rebase(/*old_base=*/SPREG, /*new_base=*/FPREG,
+                     -kExitLinkSlotFromEntryFp + kEntryFramePadding);
+  const Location dst = locs()->out(0);
+  const Location src = rebase.Rebase(loc_);
+  NoTemporaryAllocator no_temp;
+  compiler->EmitMove(dst, src, &no_temp);
+#else
+  UNREACHABLE();
+#endif
+}
+
+LocationSummary* NativeParameterInstr::MakeLocationSummary(Zone* zone,
+                                                           bool opt) const {
+#if !defined(TARGET_ARCH_DBC)
+  ASSERT(opt);
+  Location input = Location::Any();
+  if (representation() == kUnboxedInt64 && compiler::target::kWordSize < 8) {
+    input = Location::Pair(Location::RequiresRegister(),
+                           Location::RequiresFpuRegister());
+  } else {
+    input = RegisterKindForResult() == Location::kRegister
+                ? Location::RequiresRegister()
+                : Location::RequiresFpuRegister();
+  }
+  return LocationSummary::Make(zone, /*num_inputs=*/0, input,
+                               LocationSummary::kNoCall);
+#else
+  UNREACHABLE();
+#endif
+}
+
 bool ParallelMoveInstr::IsRedundant() const {
   for (intptr_t i = 0; i < moves_.length(); i++) {
     if (!moves_[i]->IsRedundant()) {
@@ -5370,6 +5490,16 @@
   }
 }
 
+LocationSummary* NativeReturnInstr::MakeLocationSummary(Zone* zone,
+                                                        bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  locs->set_in(0, result_location_);
+  return locs;
+}
+
 #undef Z
 
 #else
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 3e91b50..012ebad 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -336,18 +336,21 @@
   M(JoinEntry, kNoGC)                                                          \
   M(TargetEntry, kNoGC)                                                        \
   M(FunctionEntry, kNoGC)                                                      \
+  M(NativeEntry, kNoGC)                                                        \
   M(OsrEntry, kNoGC)                                                           \
   M(IndirectEntry, kNoGC)                                                      \
   M(CatchBlockEntry, kNoGC)                                                    \
   M(Phi, kNoGC)                                                                \
   M(Redefinition, kNoGC)                                                       \
   M(Parameter, kNoGC)                                                          \
+  M(NativeParameter, kNoGC)                                                    \
   M(LoadIndexedUnsafe, kNoGC)                                                  \
   M(StoreIndexedUnsafe, kNoGC)                                                 \
   M(TailCall, kNoGC)                                                           \
   M(ParallelMove, kNoGC)                                                       \
   M(PushArgument, kNoGC)                                                       \
   M(Return, kNoGC)                                                             \
+  M(NativeReturn, kNoGC)                                                       \
   M(Throw, kNoGC)                                                              \
   M(ReThrow, kNoGC)                                                            \
   M(Stop, _)                                                                   \
@@ -555,7 +558,11 @@
   explicit Cids(Zone* zone) : zone_(zone) {}
   // Creates the off-heap Cids object that reflects the contents
   // of the on-VM-heap IC data.
-  static Cids* Create(Zone* zone, const ICData& ic_data, int argument_number);
+  // Ranges of Cids are merged if there is only one target function and
+  // it is used for all cids in the gaps between ranges.
+  static Cids* CreateAndExpand(Zone* zone,
+                               const ICData& ic_data,
+                               int argument_number);
   static Cids* CreateMonomorphic(Zone* zone, intptr_t cid);
 
   bool Equals(const Cids& other) const;
@@ -916,6 +923,28 @@
 
   virtual bool UseSharedSlowPathStub(bool is_optimizing) const { return false; }
 
+  // 'RegisterKindForResult()' returns the register kind necessary to hold the
+  // result.
+  //
+  // This is not virtual because instructions should override representation()
+  // instead.
+  Location::Kind RegisterKindForResult() const {
+    const Representation rep = representation();
+#if !defined(TARGET_ARCH_DBC)
+    if ((rep == kUnboxedFloat) || (rep == kUnboxedDouble) ||
+        (rep == kUnboxedFloat32x4) || (rep == kUnboxedInt32x4) ||
+        (rep == kUnboxedFloat64x2)) {
+      return Location::kFpuRegister;
+    }
+#else
+    // DBC supports only unboxed doubles and does not have distinguished FPU
+    // registers.
+    ASSERT((rep != kUnboxedFloat32x4) && (rep != kUnboxedInt32x4) &&
+           (rep != kUnboxedFloat64x2));
+#endif
+    return Location::kRegister;
+  }
+
  protected:
   // GetDeoptId and/or CopyDeoptIdFrom.
   friend class CallSiteInliner;
@@ -1614,6 +1643,33 @@
   DISALLOW_COPY_AND_ASSIGN(FunctionEntryInstr);
 };
 
+// Represents entry into a function from native code.
+//
+// Native entries are not allowed to have regular parameters. They should use
+// NativeParameter instead (which doesn't count as an initial definition).
+class NativeEntryInstr : public FunctionEntryInstr {
+ public:
+  NativeEntryInstr(const ZoneGrowableArray<Location>* argument_locations,
+                   GraphEntryInstr* graph_entry,
+                   intptr_t block_id,
+                   intptr_t try_index,
+                   intptr_t deopt_id,
+                   intptr_t callback_id)
+      : FunctionEntryInstr(graph_entry, block_id, try_index, deopt_id),
+        callback_id_(callback_id),
+        argument_locations_(argument_locations) {}
+
+  DECLARE_INSTRUCTION(NativeEntry)
+
+  PRINT_TO_SUPPORT
+
+ private:
+  void SaveArgument(FlowGraphCompiler* compiler, Location loc) const;
+
+  const intptr_t callback_id_;
+  const ZoneGrowableArray<Location>* const argument_locations_;
+};
+
 // Represents an OSR entrypoint to a function.
 //
 // The OSR entry has it's own initial definitions.
@@ -2193,6 +2249,57 @@
   DISALLOW_COPY_AND_ASSIGN(ParameterInstr);
 };
 
+// Native parameters are not treated as initial definitions because they cannot
+// be inlined and are only usable in optimized code. The location must be a
+// stack location relative to the position of the stack (SPREG) after
+// register-based arguments have been saved on entry to a native call. See
+// NativeEntryInstr::EmitNativeCode for more details.
+//
+// TOOD(33549): Unify with ParameterInstr.
+class NativeParameterInstr : public Definition {
+ public:
+  NativeParameterInstr(Location loc, Representation representation)
+      : loc_(loc), representation_(representation) {
+    if (loc.IsPairLocation()) {
+      for (intptr_t i : {0, 1}) {
+        ASSERT(loc_.Component(i).HasStackIndex() &&
+               loc_.Component(i).base_reg() == SPREG);
+      }
+    } else {
+      ASSERT(loc_.HasStackIndex() && loc_.base_reg() == SPREG);
+    }
+  }
+
+  DECLARE_INSTRUCTION(NativeParameter)
+
+  virtual Representation representation() const { return representation_; }
+
+  intptr_t InputCount() const { return 0; }
+  Value* InputAt(intptr_t i) const {
+    UNREACHABLE();
+    return NULL;
+  }
+
+  virtual bool ComputeCanDeoptimize() const { return false; }
+
+  virtual bool HasUnknownSideEffects() const { return false; }
+
+  // TODO(sjindel): We can make this more precise.
+  virtual CompileType ComputeType() const { return CompileType::Dynamic(); }
+
+  virtual bool MayThrow() const { return false; }
+
+  PRINT_OPERANDS_TO_SUPPORT
+
+ private:
+  virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
+
+  const Location loc_;
+  const Representation representation_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeParameterInstr);
+};
+
 // Stores a tagged pointer to a slot accessible from a fixed register.  It has
 // the form:
 //
@@ -2256,8 +2363,11 @@
 // the frame.  This is asserted via `inliner.cc::CalleeGraphValidator`.
 class LoadIndexedUnsafeInstr : public TemplateDefinition<1, NoThrow> {
  public:
-  LoadIndexedUnsafeInstr(Value* index, intptr_t offset, CompileType result_type)
-      : offset_(offset) {
+  LoadIndexedUnsafeInstr(Value* index,
+                         intptr_t offset,
+                         CompileType result_type,
+                         Representation representation = kTagged)
+      : offset_(offset), representation_(representation) {
     UpdateType(result_type);
     SetInputAt(0, index);
   }
@@ -2268,7 +2378,6 @@
     ASSERT(index == 0);
     return kTagged;
   }
-  virtual Representation representation() const { return kTagged; }
   virtual bool ComputeCanDeoptimize() const { return false; }
   virtual bool HasUnknownSideEffects() const { return false; }
 
@@ -2284,6 +2393,7 @@
 
  private:
   const intptr_t offset_;
+  const Representation representation_;
 
   DISALLOW_COPY_AND_ASSIGN(LoadIndexedUnsafeInstr);
 };
@@ -2393,6 +2503,40 @@
   DISALLOW_COPY_AND_ASSIGN(ReturnInstr);
 };
 
+// Represents a return from a Dart function into native code.
+class NativeReturnInstr : public ReturnInstr {
+ public:
+  NativeReturnInstr(TokenPosition token_pos,
+                    Value* value,
+                    Representation rep,
+                    Location result_location,
+                    intptr_t deopt_id)
+      : ReturnInstr(token_pos, value, deopt_id),
+        result_representation_(rep),
+        result_location_(result_location) {}
+
+  DECLARE_INSTRUCTION(NativeReturn)
+
+  PRINT_OPERANDS_TO_SUPPORT
+
+  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+    ASSERT(idx == 0);
+    return result_representation_;
+  }
+
+  virtual bool CanBecomeDeoptimizationTarget() const {
+    // Unlike ReturnInstr, NativeReturnInstr cannot be inlined (because it's
+    // returning into native code).
+    return false;
+  }
+
+ private:
+  const Representation result_representation_;
+  const Location result_location_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeReturnInstr);
+};
+
 class ThrowInstr : public TemplateInstruction<0, Throws> {
  public:
   explicit ThrowInstr(TokenPosition token_pos, intptr_t deopt_id)
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index cf86087..e833159 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -1023,7 +1023,8 @@
                                  RawPcDescriptors::Kind::kOther, locs());
 
   // Update information in the thread object and enter a safepoint.
-  __ TransitionGeneratedToNative(branch, saved_fp, locs()->temp(1).reg());
+  __ TransitionGeneratedToNative(branch, FPREG, saved_fp,
+                                 locs()->temp(1).reg());
 
   __ blx(branch);
 
@@ -1044,6 +1045,174 @@
   __ PopRegister(TMP);
 }
 
+void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ LeaveDartFrame();
+
+  // The dummy return address is in LR, no need to pop it as on Intel.
+
+  // These can be anything besides the return registers (R0 and R1) and THR
+  // (R10).
+  const Register vm_tag_reg = R2, old_exit_frame_reg = R3, tmp = R4, tmp1 = R5;
+
+  __ Pop(old_exit_frame_reg);
+
+  // Restore top_resource.
+  __ Pop(tmp);
+  __ StoreToOffset(kWord, tmp, THR,
+                   compiler::target::Thread::top_resource_offset());
+
+  __ Pop(vm_tag_reg);
+
+  // Reset the exit frame info to
+  // old_exit_frame_reg *before* entering the safepoint.
+  __ TransitionGeneratedToNative(vm_tag_reg, old_exit_frame_reg, tmp, tmp1);
+
+  __ PopNativeCalleeSavedRegisters();
+
+  // Leave the entry frame.
+  __ LeaveFrame(1 << LR | 1 << FP);
+
+  // Leave the dummy frame holding the pushed arguments.
+  __ LeaveFrame(1 << LR | 1 << FP);
+
+  __ Ret();
+
+  // For following blocks.
+  __ set_constant_pool_allowed(true);
+}
+
+void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler,
+                                    Location loc) const {
+  if (loc.IsPairLocation()) {
+    // Save higher-order component first, so bytes are in little-endian layout
+    // overall.
+    for (intptr_t i : {1, 0}) {
+      SaveArgument(compiler, loc.Component(i));
+    }
+    return;
+  }
+
+  if (loc.HasStackIndex()) return;
+
+  if (loc.IsRegister()) {
+    __ Push(loc.reg());
+  } else if (loc.IsFpuRegister()) {
+    const DRegister src = EvenDRegisterOf(loc.fpu_reg());
+    __ SubImmediateSetFlags(SPREG, SPREG, 8, AL);
+    __ StoreDToOffset(src, SPREG, 0);
+  } else {
+    UNREACHABLE();
+  }
+}
+
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (FLAG_precompiled_mode) {
+    UNREACHABLE();
+  }
+
+  // Constant pool cannot be used until we enter the actual Dart frame.
+  __ set_constant_pool_allowed(false);
+
+  __ Bind(compiler->GetJumpLabel(this));
+
+  // Create a dummy frame holding the pushed arguments. This simplifies
+  // NativeReturnInstr::EmitNativeCode.
+  __ EnterFrame((1 << FP) | (1 << LR), 0);
+
+  // Save the argument registers, in reverse order.
+  for (intptr_t i = argument_locations_->length(); i-- > 0;) {
+    SaveArgument(compiler, argument_locations_->At(i));
+  }
+
+  // Enter the entry frame.
+  __ EnterFrame((1 << FP) | (1 << LR), 0);
+
+  // Save a space for the code object.
+  __ PushImmediate(0);
+
+  __ PushNativeCalleeSavedRegisters();
+
+  // Load the thread object.
+  // TODO(35765): Fix linking issue on AOT.
+  // TOOD(35934): Exclude native callbacks from snapshots.
+  //
+  // Create another frame to align the frame before continuing in "native" code.
+  {
+    __ EnterFrame(1 << FP, 0);
+    __ ReserveAlignedFrameSpace(0);
+
+    __ LoadImmediate(
+        R0, reinterpret_cast<int64_t>(DLRT_GetThreadForNativeCallback));
+    __ blx(R0);
+    __ mov(THR, Operand(R0));
+
+    __ LeaveFrame(1 << FP);
+  }
+
+  // Save the current VMTag on the stack.
+  __ LoadFromOffset(kWord, R0, THR, compiler::target::Thread::vm_tag_offset());
+  __ Push(R0);
+
+  // Save top resource.
+  const intptr_t top_resource_offset =
+      compiler::target::Thread::top_resource_offset();
+  __ LoadFromOffset(kWord, R0, THR, top_resource_offset);
+  __ Push(R0);
+  __ LoadImmediate(R0, 0);
+  __ StoreToOffset(kWord, R0, THR, top_resource_offset);
+
+  // Save top exit frame info. Don't set it to 0 yet --
+  // TransitionNativeToGenerated will handle that *after* leaving the safepoint.
+  __ LoadFromOffset(kWord, R0, THR,
+                    compiler::target::Thread::top_exit_frame_info_offset());
+  __ Push(R0);
+
+  __ EmitEntryFrameVerification(R0);
+
+  __ TransitionNativeToGenerated(/*scratch0=*/R0, /*scratch1=*/R1);
+
+  // Now that the safepoint has ended, we can touch Dart objects without
+  // handles.
+
+  // Otherwise we'll clobber the argument sent from the caller.
+  ASSERT(CallingConventions::ArgumentRegisters[0] != TMP &&
+         CallingConventions::ArgumentRegisters[0] != TMP2 &&
+         CallingConventions::ArgumentRegisters[0] != R1);
+  __ LoadImmediate(CallingConventions::ArgumentRegisters[0], callback_id_);
+  __ LoadFromOffset(
+      kWord, R1, THR,
+      compiler::target::Thread::verify_callback_isolate_entry_point_offset());
+  __ blx(R1);
+
+  // Load the code object.
+  __ LoadFromOffset(kWord, R0, THR,
+                    compiler::target::Thread::callback_code_offset());
+  __ LoadFieldFromOffset(kWord, R0, R0,
+                         compiler::target::GrowableObjectArray::data_offset());
+  __ LoadFieldFromOffset(kWord, CODE_REG, R0,
+                         compiler::target::Array::data_offset() +
+                             callback_id_ * compiler::target::kWordSize);
+
+  // Put the code object in the reserved slot.
+  __ StoreToOffset(kWord, CODE_REG, FPREG,
+                   kPcMarkerSlotFromFp * compiler::target::kWordSize);
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    __ ldr(PP,
+           Address(THR, compiler::target::Thread::global_object_pool_offset()));
+  } else {
+    __ LoadImmediate(PP, 0);  // GC safe value into PP.
+  }
+
+  // Load a dummy return address which suggests that we are inside of
+  // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
+  __ LoadFromOffset(kWord, LR, THR,
+                    compiler::target::Thread::invoke_dart_code_stub_offset());
+  __ LoadFieldFromOffset(kWord, LR, LR,
+                         compiler::target::Code::entry_point_offset());
+
+  FunctionEntryInstr::EmitNativeCode(compiler);
+}
+
 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
@@ -1295,10 +1464,10 @@
       (representation() == kUnboxedInt32x4) ||
       (representation() == kUnboxedFloat64x2)) {
     if (class_id() == kTypedDataFloat32ArrayCid) {
-      // Need register <= Q7 for float operations.
+      // Need register < Q7 for float operations.
       // TODO(fschneider): Add a register policy to specify a subset of
       // registers.
-      locs->set_out(0, Location::FpuRegisterLocation(Q7));
+      locs->set_out(0, Location::FpuRegisterLocation(Q6));
     } else {
       locs->set_out(0, Location::RequiresFpuRegister());
     }
@@ -1599,8 +1768,8 @@
                                      Location::RequiresRegister()));
       break;
     case kTypedDataFloat32ArrayCid:
-      // Need low register (<= Q7).
-      locs->set_in(2, Location::FpuRegisterLocation(Q7));
+      // Need low register (< Q7).
+      locs->set_in(2, Location::FpuRegisterLocation(Q6));
       break;
     case kTypedDataFloat64ArrayCid:  // TODO(srdjan): Support Float64 constants.
     case kTypedDataInt32x4ArrayCid:
@@ -5396,9 +5565,9 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* result = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  // Low (<= Q7) Q registers are needed for the conversion instructions.
+  // Low (< Q7) Q registers are needed for the conversion instructions.
   result->set_in(0, Location::RequiresFpuRegister());
-  result->set_out(0, Location::FpuRegisterLocation(Q7));
+  result->set_out(0, Location::FpuRegisterLocation(Q6));
   return result;
 }
 
@@ -5415,8 +5584,8 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* result = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  // Low (<= Q7) Q registers are needed for the conversion instructions.
-  result->set_in(0, Location::FpuRegisterLocation(Q7));
+  // Low (< Q7) Q registers are needed for the conversion instructions.
+  result->set_in(0, Location::FpuRegisterLocation(Q6));
   result->set_out(0, Location::RequiresFpuRegister());
   return result;
 }
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 1bf08fc..15ae1de 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -916,7 +916,7 @@
   __ mov(CSP, SP);
 
   // Update information in the thread object and enter a safepoint.
-  __ TransitionGeneratedToNative(branch, temp);
+  __ TransitionGeneratedToNative(branch, FPREG, temp);
 
   __ blr(branch);
 
@@ -944,6 +944,177 @@
   __ set_constant_pool_allowed(true);
 }
 
+void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ LeaveDartFrame();
+
+  // The dummy return address is in LR, no need to pop it as on Intel.
+
+  // These can be anything besides the return register (R0) and THR (R26).
+  const Register vm_tag_reg = R1, old_exit_frame_reg = R2, tmp = R3;
+
+  __ Pop(old_exit_frame_reg);
+
+  // Restore top_resource.
+  __ Pop(tmp);
+  __ StoreToOffset(tmp, THR, compiler::target::Thread::top_resource_offset());
+
+  __ Pop(vm_tag_reg);
+
+  // Reset the exit frame info to
+  // old_exit_frame_reg *before* entering the safepoint.
+  __ TransitionGeneratedToNative(vm_tag_reg, old_exit_frame_reg, tmp);
+
+  __ PopNativeCalleeSavedRegisters();
+
+  // Leave the entry frame.
+  __ LeaveFrame();
+
+  // Leave the dummy frame holding the pushed arguments.
+  __ LeaveFrame();
+
+  // Restore the actual stack pointer from SPREG.
+  __ RestoreCSP();
+
+  __ Ret();
+
+  // For following blocks.
+  __ set_constant_pool_allowed(true);
+}
+
+void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler,
+                                    Location loc) const {
+  ASSERT(!loc.IsPairLocation());
+
+  if (loc.HasStackIndex()) return;
+
+  if (loc.IsRegister()) {
+    __ Push(loc.reg());
+  } else if (loc.IsFpuRegister()) {
+    __ PushDouble(loc.fpu_reg());
+  } else {
+    UNREACHABLE();
+  }
+}
+
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (FLAG_precompiled_mode) {
+    UNREACHABLE();
+  }
+
+  // Constant pool cannot be used until we enter the actual Dart frame.
+  __ set_constant_pool_allowed(false);
+
+  __ Bind(compiler->GetJumpLabel(this));
+
+  // We don't use the regular stack pointer in ARM64, so we have to copy the
+  // native stack pointer into the Dart stack pointer.
+  __ SetupDartSP();
+
+  // Create a dummy frame holding the pushed arguments. This simplifies
+  // NativeReturnInstr::EmitNativeCode.
+  __ EnterFrame(0);
+
+  // Save the argument registers, in reverse order.
+  for (intptr_t i = argument_locations_->length(); i-- > 0;) {
+    SaveArgument(compiler, argument_locations_->At(i));
+  }
+
+  // Enter the entry frame.
+  __ EnterFrame(0);
+
+  // Save a space for the code object.
+  __ PushImmediate(0);
+
+  __ PushNativeCalleeSavedRegisters();
+
+  // Load the thread object.
+  // TODO(35765): Fix linking issue on AOT.
+  // TOOD(35934): Exclude native callbacks from snapshots.
+  //
+  // Create another frame to align the frame before continuing in "native" code.
+  {
+    __ EnterFrame(0);
+    __ ReserveAlignedFrameSpace(0);
+
+    __ LoadImmediate(
+        R0, reinterpret_cast<int64_t>(DLRT_GetThreadForNativeCallback));
+    __ blr(R0);
+    __ mov(THR, R0);
+
+    __ LeaveFrame();
+  }
+
+  // Refresh write barrier mask.
+  __ ldr(BARRIER_MASK,
+         Address(THR, compiler::target::Thread::write_barrier_mask_offset()));
+
+  // Save the current VMTag on the stack.
+  __ LoadFromOffset(R0, THR, compiler::target::Thread::vm_tag_offset());
+  __ Push(R0);
+
+  // Save the top resource.
+  __ LoadFromOffset(R0, THR, compiler::target::Thread::top_resource_offset());
+  __ Push(R0);
+  __ StoreToOffset(ZR, THR, compiler::target::Thread::top_resource_offset());
+
+  // Save the top exit frame info. We don't set it to 0 yet in Thread because we
+  // need to leave the safepoint first.
+  __ LoadFromOffset(R0, THR,
+                    compiler::target::Thread::top_exit_frame_info_offset());
+  __ Push(R0);
+
+  // In debug mode, verify that we've pushed the top exit frame info at the
+  // correct offset from FP.
+  __ EmitEntryFrameVerification();
+
+  // TransitionNativeToGenerated will reset top exit frame info to 0 *after*
+  // leaving the safepoint.
+  __ TransitionNativeToGenerated(R0);
+
+  // Now that the safepoint has ended, we can touch Dart objects without
+  // handles.
+
+  // Otherwise we'll clobber the argument sent from the caller.
+  ASSERT(CallingConventions::ArgumentRegisters[0] != TMP &&
+         CallingConventions::ArgumentRegisters[0] != TMP2 &&
+         CallingConventions::ArgumentRegisters[0] != R1);
+  __ LoadImmediate(CallingConventions::ArgumentRegisters[0], callback_id_);
+  __ LoadFromOffset(
+      R1, THR,
+      compiler::target::Thread::verify_callback_isolate_entry_point_offset());
+  __ blr(R1);
+
+  // Load the code object.
+  __ LoadFromOffset(R0, THR, compiler::target::Thread::callback_code_offset());
+  __ LoadFieldFromOffset(R0, R0,
+                         compiler::target::GrowableObjectArray::data_offset());
+  __ LoadFieldFromOffset(CODE_REG, R0,
+                         compiler::target::Array::data_offset() +
+                             callback_id_ * compiler::target::kWordSize);
+
+  // Put the code object in the reserved slot.
+  __ StoreToOffset(CODE_REG, FPREG,
+                   kPcMarkerSlotFromFp * compiler::target::kWordSize);
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    __ ldr(PP,
+           Address(THR, compiler::target::Thread::global_object_pool_offset()));
+    __ sub(PP, PP, Operand(kHeapObjectTag));  // Pool in PP is untagged!
+  } else {
+    // We now load the pool pointer (PP) with a GC safe value as we are about to
+    // invoke dart code. We don't need a real object pool here.
+    // Smi zero does not work because ARM64 assumes PP to be untagged.
+    __ LoadObject(PP, compiler::NullObject());
+  }
+
+  // Load a dummy return address which suggests that we are inside of
+  // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
+  __ LoadFromOffset(LR, THR,
+                    compiler::target::Thread::invoke_dart_code_stub_offset());
+  __ LoadFieldFromOffset(LR, LR, compiler::target::Code::entry_point_offset());
+
+  FunctionEntryInstr::EmitNativeCode(compiler);
+}
+
 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc
index dad840e..c869600 100644
--- a/runtime/vm/compiler/backend/il_dbc.cc
+++ b/runtime/vm/compiler/backend/il_dbc.cc
@@ -64,7 +64,8 @@
   M(UnaryInt64Op)                                                              \
   M(CheckedSmiOp)                                                              \
   M(CheckedSmiComparison)                                                      \
-  M(SimdOp)
+  M(SimdOp)                                                                    \
+  M(NativeReturn)
 
 // Location summaries actually are not used by the unoptimizing DBC compiler
 // because we don't allocate any registers.
@@ -1002,6 +1003,10 @@
   const intptr_t sigdesc_kidx = __ AddConstant(signature_descriptor);
 
   __ FfiCall(sigdesc_kidx);
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
+                                 token_pos());
+  compiler->RecordAfterCallHelper(token_pos(), deopt_id(), 0,
+                                  FlowGraphCompiler::kHasResult, locs());
 }
 
 EMIT_NATIVE_CODE(NativeCall,
@@ -1392,18 +1397,23 @@
     case kTypedDataUint8ClampedArrayCid:
     case kExternalTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
+
     case kOneByteStringCid:
     case kTwoByteStringCid:
     case kExternalOneByteStringCid:
-    case kExternalTwoByteStringCid:
       return CompileType::FromCid(kSmiCid);
 
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
       return CompileType::Int();
 
+    // These are unsupported on DBC and will cause a bailout during
+    // EmitNativeCode.
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+    case kExternalTwoByteStringCid:
+      return CompileType::FromCid(kSmiCid);
+
     default:
       UNREACHABLE();
       return CompileType::Dynamic();
@@ -1414,18 +1424,16 @@
   switch (class_id_) {
     case kArrayCid:
     case kImmutableArrayCid:
+      return kTagged;
+    case kOneByteStringCid:
+    case kTwoByteStringCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
+    case kExternalOneByteStringCid:
     case kExternalTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
-    case kOneByteStringCid:
-    case kTwoByteStringCid:
-    case kExternalOneByteStringCid:
-    case kExternalTwoByteStringCid:
-      return kTagged;
+      return kUnboxedIntPtr;
     case kTypedDataInt32ArrayCid:
       return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
@@ -1439,6 +1447,14 @@
       return kUnboxedFloat32x4;
     case kTypedDataFloat64x2ArrayCid:
       return kUnboxedFloat64x2;
+
+    // These are unsupported on DBC and will cause a bailout during
+    // EmitNativeCode.
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+    case kExternalTwoByteStringCid:
+      return kUnboxedIntPtr;
+
     default:
       UNREACHABLE();
       return kTagged;
@@ -1457,18 +1473,13 @@
   ASSERT(idx == 2);
   switch (class_id_) {
     case kArrayCid:
+      return kTagged;
     case kOneByteStringCid:
-    case kTwoByteStringCid:
-    case kExternalOneByteStringCid:
-    case kExternalTwoByteStringCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
+    case kExternalOneByteStringCid:
     case kExternalTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
-      return kTagged;
+      return kUnboxedIntPtr;
     case kTypedDataInt32ArrayCid:
       return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
@@ -1482,6 +1493,14 @@
       return kUnboxedInt32x4;
     case kTypedDataFloat64x2ArrayCid:
       return kUnboxedFloat64x2;
+
+    // These are unsupported on DBC and will cause a bailout during
+    // EmitNativeCode.
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+      return kUnboxedIntPtr;
     default:
       UNREACHABLE();
       return kTagged;
@@ -2150,6 +2169,10 @@
                           (licm_hoisted_ ? ICData::kHoisted : 0));
 }
 
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNREACHABLE();
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 403ca00..f71bb81 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+#include "platform/globals.h"
 #include "vm/globals.h"  // Needed here to get TARGET_ARCH_IA32.
 #if defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
 
@@ -134,6 +135,65 @@
   __ ret();
 }
 
+void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  bool return_in_st0 = false;
+  if (result_representation_ == kUnboxedFloat ||
+      result_representation_ == kUnboxedDouble) {
+    ASSERT(locs()->in(0).IsFpuRegister() && locs()->in(0).fpu_reg() == XMM0);
+    return_in_st0 = true;
+  }
+
+  // Leave Dart frame.
+  __ LeaveFrame();
+
+  // EDI is the only sane choice for a temporary register here because:
+  //
+  // EDX is used for large return values.
+  // ESI == THR.
+  // Could be EBX or ECX, but that would make code below confusing.
+  const Register tmp = EDI;
+
+  // Pop dummy return address.
+  __ popl(tmp);
+
+  // Anything besides the return register(s!). Callee-saved registers will be
+  // restored later.
+  const Register vm_tag_reg = EBX, old_exit_frame_reg = ECX;
+
+  __ popl(old_exit_frame_reg);
+
+  // Restore top_resource.
+  __ popl(tmp);
+  __ movl(Address(THR, compiler::target::Thread::top_resource_offset()), tmp);
+
+  __ popl(vm_tag_reg);
+
+  // This will reset the exit frame info to old_exit_frame_reg *before* entering
+  // the safepoint.
+  __ TransitionGeneratedToNative(vm_tag_reg, old_exit_frame_reg, tmp);
+
+  // Move XMM0 into ST0 if needed.
+  if (return_in_st0) {
+    if (result_representation_ == kUnboxedDouble) {
+      __ movsd(Address(SPREG, -8), XMM0);
+      __ fldl(Address(SPREG, -8));
+    } else {
+      __ movss(Address(SPREG, -4), XMM0);
+      __ flds(Address(SPREG, -4));
+    }
+  }
+
+  // Restore C++ ABI callee-saved registers.
+  __ popl(EDI);
+  __ popl(ESI);
+  __ popl(EBX);
+
+  // Leave the entry frame.
+  __ LeaveFrame();
+
+  __ ret();
+}
+
 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone,
                                                      bool opt) const {
   const intptr_t kNumInputs = 0;
@@ -886,32 +946,22 @@
   __ popl(tmp);
   __ movl(Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), tmp);
 
-  __ TransitionGeneratedToNative(branch, tmp);
+  __ TransitionGeneratedToNative(branch, FPREG, tmp);
   __ call(branch);
 
   // The x86 calling convention requires floating point values to be returned on
   // the "floating-point stack" (aka. register ST0). We don't use the
   // floating-point stack in Dart, so we need to move the return value back into
   // an XMM register.
-  if (representation() == kUnboxedDouble || representation() == kUnboxedFloat) {
-    __ subl(SPREG, Immediate(8));
-    __ fstpl(Address(SPREG, 0));
-    __ TransitionNativeToGenerated(tmp);
-    __ fldl(Address(SPREG, 0));
-    __ addl(SPREG, Immediate(8));
-  } else {
-    __ TransitionNativeToGenerated(tmp);
+  if (representation() == kUnboxedDouble) {
+    __ fstpl(Address(SPREG, -kDoubleSize));
+    __ movsd(XMM0, Address(SPREG, -kDoubleSize));
+  } else if (representation() == kUnboxedFloat) {
+    __ fstps(Address(SPREG, -kFloatSize));
+    __ movss(XMM0, Address(SPREG, -kFloatSize));
   }
 
-  if (representation() == kUnboxedDouble) {
-    __ subl(SPREG, Immediate(8));
-    __ fstpl(Address(SPREG, 0));
-    __ movsd(XMM0, Address(SPREG, 0));
-  } else if (representation() == kUnboxedFloat) {
-    __ subl(SPREG, Immediate(4));
-    __ fstps(Address(SPREG, 0));
-    __ movss(XMM0, Address(SPREG, 0));
-  }
+  __ TransitionNativeToGenerated(tmp);
 
   // Leave dummy exit frame.
   __ LeaveFrame();
@@ -920,6 +970,113 @@
   __ popl(tmp);
 }
 
+void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler,
+                                    Location loc) const {
+  if (loc.IsPairLocation()) {
+    // Save the components in reverse order so that they will be in
+    // little-endian order on the stack.
+    for (intptr_t i : {1, 0}) {
+      SaveArgument(compiler, loc.Component(i));
+    }
+    return;
+  }
+
+  if (loc.HasStackIndex()) return;
+
+  if (loc.IsRegister()) {
+    __ pushl(loc.reg());
+  } else if (loc.IsFpuRegister()) {
+    __ subl(SPREG, Immediate(8));
+    __ movsd(Address(SPREG, 0), loc.fpu_reg());
+  } else {
+    UNREACHABLE();
+  }
+}
+
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ Bind(compiler->GetJumpLabel(this));
+
+  // Enter the entry frame.
+  __ EnterFrame(0);
+
+  // Save a space for the code object.
+  __ xorl(EAX, EAX);
+  __ pushl(EAX);
+
+  // Save ABI callee-saved registers.
+  __ pushl(EBX);
+  __ pushl(ESI);
+  __ pushl(EDI);
+
+  // Load the thread object.
+  // TOOD(35934): Exclude native callbacks from snapshots.
+  // Linking in AOT is not relevant here since we don't support AOT for IA32.
+  // Create another frame to align the frame before continuing in "native" code.
+  {
+    __ EnterFrame(0);
+    __ ReserveAlignedFrameSpace(0);
+
+    __ movl(
+        EAX,
+        Immediate(reinterpret_cast<int64_t>(DLRT_GetThreadForNativeCallback)));
+    __ call(EAX);
+    __ movl(THR, EAX);
+
+    __ LeaveFrame();
+  }
+
+  // Save the current VMTag on the stack.
+  __ movl(ECX, Assembler::VMTagAddress());
+  __ pushl(ECX);
+
+  // Save top resource.
+  __ pushl(Address(THR, compiler::target::Thread::top_resource_offset()));
+  __ movl(Address(THR, compiler::target::Thread::top_resource_offset()),
+          Immediate(0));
+
+  // Save top exit frame info. Stack walker expects it to be here.
+  __ pushl(
+      Address(THR, compiler::target::Thread::top_exit_frame_info_offset()));
+
+  // In debug mode, verify that we've pushed the top exit frame info at the
+  // correct offset from FP.
+  __ EmitEntryFrameVerification();
+
+  // TransitionNativeToGenerated will reset top exit frame info to 0 *after*
+  // leaving the safepoint.
+  __ TransitionNativeToGenerated(EAX);
+
+  // Now that the safepoint has ended, we can hold Dart objects with bare hands.
+  // TODO(35934): fix linking issue
+  __ pushl(Immediate(callback_id_));
+  __ movl(EAX, Address(THR, compiler::target::Thread::
+                                verify_callback_isolate_entry_point_offset()));
+  __ call(EAX);
+  __ popl(EAX);
+
+  // Load the code object.
+  __ movl(EAX, Address(THR, compiler::target::Thread::callback_code_offset()));
+  __ movl(EAX, FieldAddress(
+                   EAX, compiler::target::GrowableObjectArray::data_offset()));
+  __ movl(CODE_REG,
+          FieldAddress(EAX, compiler::target::Array::data_offset() +
+                                callback_id_ * compiler::target::kWordSize));
+
+  // Put the code object in the reserved slot.
+  __ movl(Address(FPREG, kPcMarkerSlotFromFp * compiler::target::kWordSize),
+          CODE_REG);
+
+  // Push a dummy return address which suggests that we are inside of
+  // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
+  __ movl(
+      EAX,
+      Address(THR, compiler::target::Thread::invoke_dart_code_stub_offset()));
+  __ pushl(FieldAddress(EAX, compiler::target::Code::entry_point_offset()));
+
+  // Continue with Dart frame setup.
+  FunctionEntryInstr::EmitNativeCode(compiler);
+}
+
 static bool CanBeImmediateIndex(Value* value, intptr_t cid) {
   ConstantInstr* constant = value->definition()->AsConstant();
   if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) {
@@ -1575,10 +1732,10 @@
 
   Label ok, fail_label;
 
-  Label* deopt =
-      compiler->is_optimizing()
-          ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField)
-          : NULL;
+  Label* deopt = nullptr;
+  if (compiler->is_optimizing()) {
+    deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField);
+  }
 
   Label* fail = (deopt != NULL) ? deopt : &fail_label;
 
@@ -3732,9 +3889,10 @@
   Register value = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
   const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister;
-  Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub(
-                                       GetDeoptId(), ICData::kDeoptUnboxInteger)
-                                 : NULL;
+  Label* deopt = nullptr;
+  if (CanDeoptimize()) {
+    deopt = compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger);
+  }
   Label* out_of_range = !is_truncating() ? deopt : NULL;
 
   const intptr_t lo_offset = Mint::value_offset();
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index fe7508f..a2f841d 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -524,12 +524,10 @@
 void FfiCallInstr::PrintOperandsTo(BufferFormatter* f) const {
   f->Print(" pointer=");
   InputAt(TargetAddressIndex())->PrintTo(f);
-  f->Print(" signature=%s",
-           Type::Handle(signature_.SignatureType()).ToCString());
   for (intptr_t i = 0, n = InputCount(); i < n - 1; ++i) {
     f->Print(", ");
     InputAt(i)->PrintTo(f);
-    f->Print(" (at %s) ", arg_locations_[i].ToCString());
+    f->Print(" (@%s)", arg_locations_[i].ToCString());
   }
 }
 
@@ -1063,6 +1061,24 @@
   BlockEntryWithInitialDefs::PrintInitialDefinitionsTo(f);
 }
 
+void NativeEntryInstr::PrintTo(BufferFormatter* f) const {
+  f->Print("B%" Pd "[native function entry]:%" Pd, block_id(), GetDeoptId());
+  if (HasParallelMove()) {
+    f->Print("\n");
+    parallel_move()->PrintTo(f);
+  }
+  BlockEntryWithInitialDefs::PrintInitialDefinitionsTo(f);
+}
+
+void NativeReturnInstr::PrintOperandsTo(BufferFormatter* f) const {
+  value()->PrintTo(f);
+}
+
+void NativeParameterInstr::PrintOperandsTo(BufferFormatter* f) const {
+  f->Print("%s as %s", loc_.ToCString(),
+           RepresentationToCString(representation_));
+}
+
 void CatchBlockEntryInstr::PrintTo(BufferFormatter* f) const {
   f->Print("B%" Pd "[target catch try_idx %" Pd " catch_try_idx %" Pd "]",
            block_id(), try_index(), catch_try_index());
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index e8bf0f8..7ffade3 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -139,6 +139,43 @@
   __ set_constant_pool_allowed(true);
 }
 
+void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ LeaveDartFrame();
+
+  // Pop dummy return address.
+  __ popq(TMP);
+
+  // Anything besides the return register.
+  const Register vm_tag_reg = RBX, old_exit_frame_reg = RCX;
+
+  __ popq(old_exit_frame_reg);
+
+  // Restore top_resource.
+  __ popq(TMP);
+  __ movq(Address(THR, compiler::target::Thread::top_resource_offset()), TMP);
+
+  __ popq(vm_tag_reg);
+
+  // TransitionGeneratedToNative will reset the exit frame info to
+  // old_exit_frame_reg *before* entering the safepoint.
+  __ TransitionGeneratedToNative(vm_tag_reg, old_exit_frame_reg);
+
+  // Restore C++ ABI callee-saved registers.
+  __ PopRegisters(CallingConventions::kCalleeSaveCpuRegisters,
+                  CallingConventions::kCalleeSaveXmmRegisters);
+
+  // Leave the entry frame.
+  __ LeaveFrame();
+
+  // Leave the dummy frame holding the pushed arguments.
+  __ LeaveFrame();
+
+  __ ret();
+
+  // For following blocks.
+  __ set_constant_pool_allowed(true);
+}
+
 static Condition NegateCondition(Condition condition) {
   switch (condition) {
     case EQUAL:
@@ -921,7 +958,7 @@
   __ movq(Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), TMP);
 
   // Update information in the thread object and enter a safepoint.
-  __ TransitionGeneratedToNative(target_address);
+  __ TransitionGeneratedToNative(target_address, FPREG);
 
   __ CallCFunction(target_address);
 
@@ -943,6 +980,132 @@
   __ popq(TMP);
 }
 
+void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler,
+                                    Location loc) const {
+  ASSERT(!loc.IsPairLocation());
+
+  if (loc.HasStackIndex()) return;
+
+  if (loc.IsRegister()) {
+    __ pushq(loc.reg());
+  } else if (loc.IsFpuRegister()) {
+    __ movq(TMP, loc.fpu_reg());
+    __ pushq(TMP);
+  } else {
+    UNREACHABLE();
+  }
+}
+
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (FLAG_precompiled_mode) {
+    UNREACHABLE();
+  }
+
+  __ Bind(compiler->GetJumpLabel(this));
+
+  // Create a dummy frame holding the pushed arguments. This simplifies
+  // NativeReturnInstr::EmitNativeCode.
+  __ EnterFrame(0);
+
+  // Save the argument registers, in reverse order.
+  for (intptr_t i = argument_locations_->length(); i-- > 0;) {
+    SaveArgument(compiler, argument_locations_->At(i));
+  }
+
+  // Enter the entry frame. Push a dummy return address for consistency with
+  // EnterFrame on ARM(64).
+  __ PushImmediate(Immediate(0));
+  __ EnterFrame(0);
+
+  // Save a space for the code object.
+  __ PushImmediate(Immediate(0));
+
+  // InvokoeDartCodeStub saves the arguments descriptor here. We don't have one,
+  // but we need to follow the same frame layout for the stack walker.
+  __ PushImmediate(Immediate(0));
+
+  // Save ABI callee-saved registers.
+  __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters,
+                   CallingConventions::kCalleeSaveXmmRegisters);
+
+  // Load the thread object.
+  // TODO(35765): Fix linking issue on AOT.
+  // TOOD(35934): Exclude native callbacks from snapshots.
+  //
+  // Create another frame to align the frame before continuing in "native" code.
+  {
+    __ EnterFrame(0);
+    __ ReserveAlignedFrameSpace(0);
+
+    __ movq(
+        RAX,
+        Immediate(reinterpret_cast<int64_t>(DLRT_GetThreadForNativeCallback)));
+    __ call(RAX);
+    __ movq(THR, RAX);
+
+    __ LeaveFrame();
+  }
+
+  // Save the current VMTag on the stack.
+  __ movq(RAX, Assembler::VMTagAddress());
+  __ pushq(RAX);
+
+  // Save top resource.
+  __ pushq(Address(THR, compiler::target::Thread::top_resource_offset()));
+  __ movq(Address(THR, compiler::target::Thread::top_resource_offset()),
+          Immediate(0));
+
+  // Save top exit frame info. Stack walker expects it to be here.
+  __ pushq(
+      Address(THR, compiler::target::Thread::top_exit_frame_info_offset()));
+
+  // In debug mode, verify that we've pushed the top exit frame info at the
+  // correct offset from FP.
+  __ EmitEntryFrameVerification();
+
+  // TransitionNativeToGenerated will reset top exit frame info to 0 *after*
+  // leaving the safepoint.
+  __ TransitionNativeToGenerated();
+
+  // Now that the safepoint has ended, we can touch Dart objects without
+  // handles.
+  // Otherwise we'll clobber the argument sent from the caller.
+  COMPILE_ASSERT(RAX != CallingConventions::kArg1Reg);
+  __ movq(CallingConventions::kArg1Reg, Immediate(callback_id_));
+  __ movq(RAX, Address(THR, compiler::target::Thread::
+                                verify_callback_isolate_entry_point_offset()));
+  __ call(RAX);
+
+  // Load the code object.
+  __ movq(RAX, Address(THR, compiler::target::Thread::callback_code_offset()));
+  __ movq(RAX, FieldAddress(
+                   RAX, compiler::target::GrowableObjectArray::data_offset()));
+  __ movq(CODE_REG,
+          FieldAddress(RAX, compiler::target::Array::data_offset() +
+                                callback_id_ * compiler::target::kWordSize));
+
+  // Put the code object in the reserved slot.
+  __ movq(Address(FPREG, kPcMarkerSlotFromFp * compiler::target::kWordSize),
+          CODE_REG);
+
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    __ movq(PP, Address(THR,
+                        compiler::target::Thread::global_object_pool_offset()));
+  } else {
+    __ xorq(PP, PP);  // GC-safe value into PP.
+  }
+
+  // Push a dummy return address which suggests that we are inside of
+  // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
+  __ movq(
+      RAX,
+      Address(THR, compiler::target::Thread::invoke_dart_code_stub_offset()));
+  __ pushq(FieldAddress(RAX, compiler::target::Code::entry_point_offset()));
+
+  // Continue with Dart frame setup.
+  FunctionEntryInstr::EmitNativeCode(compiler);
+}
+
 static bool CanBeImmediateIndex(Value* index, intptr_t cid) {
   if (!index->definition()->IsConstant()) return false;
   const Object& constant = index->definition()->AsConstant()->value();
@@ -1665,10 +1828,10 @@
 
   Label ok, fail_label;
 
-  Label* deopt =
-      compiler->is_optimizing()
-          ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField)
-          : NULL;
+  Label* deopt = NULL;
+  if (compiler->is_optimizing()) {
+    deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField);
+  }
 
   Label* fail = (deopt != NULL) ? deopt : &fail_label;
 
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index d3b03a9..7be5d0e 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -3322,10 +3322,10 @@
     // Insert receiver class or null check if needed.
     switch (check) {
       case FlowGraph::ToCheck::kCheckCid: {
-        Instruction* check_class =
-            flow_graph->CreateCheckClass(call->Receiver()->definition(),
-                                         *Cids::Create(Z, *call->ic_data(), 0),
-                                         call->deopt_id(), call->token_pos());
+        Instruction* check_class = flow_graph->CreateCheckClass(
+            call->Receiver()->definition(),
+            *Cids::CreateAndExpand(Z, *call->ic_data(), 0), call->deopt_id(),
+            call->token_pos());
         flow_graph->InsertBefore(call, check_class, call->env(),
                                  FlowGraph::kEffect);
         break;
diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc
index 4f5473c..b5fea9c 100644
--- a/runtime/vm/compiler/backend/linearscan.cc
+++ b/runtime/vm/compiler/backend/linearscan.cc
@@ -824,25 +824,6 @@
   }
 }
 
-static Location::Kind RegisterKindForResult(Instruction* instr) {
-  const Representation rep = instr->representation();
-#if !defined(TARGET_ARCH_DBC)
-  if ((rep == kUnboxedFloat) || (rep == kUnboxedDouble) ||
-      (rep == kUnboxedFloat32x4) || (rep == kUnboxedInt32x4) ||
-      (rep == kUnboxedFloat64x2)) {
-    return Location::kFpuRegister;
-  } else {
-    return Location::kRegister;
-  }
-#else
-  // DBC supports only unboxed doubles and does not have distinguished FPU
-  // registers.
-  ASSERT((rep != kUnboxedFloat32x4) && (rep != kUnboxedInt32x4) &&
-         (rep != kUnboxedFloat64x2));
-  return Location::kRegister;
-#endif
-}
-
 //
 // When describing shape of live ranges in comments below we are going to use
 // the following notation:
@@ -991,11 +972,11 @@
     // All phi resolution moves are connected. Phi's live range is
     // complete.
     AssignSafepoints(phi, range);
-    CompleteRange(range, RegisterKindForResult(phi));
+    CompleteRange(range, phi->RegisterKindForResult());
     if (is_pair_phi) {
       LiveRange* second_range = GetLiveRange(ToSecondPairVreg(vreg));
       AssignSafepoints(phi, second_range);
-      CompleteRange(second_range, RegisterKindForResult(phi));
+      CompleteRange(second_range, phi->RegisterKindForResult());
     }
 
     move_idx += is_pair_phi ? 2 : 1;
@@ -1303,7 +1284,7 @@
   }
 
   AssignSafepoints(def, range);
-  CompleteRange(range, RegisterKindForResult(def));
+  CompleteRange(range, def->RegisterKindForResult());
 }
 
 // Create and update live ranges corresponding to instruction's inputs,
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 5f12916..1c405f9 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -366,7 +366,8 @@
 void CallSpecializer::AddChecksForArgNr(InstanceCallInstr* call,
                                         Definition* instr,
                                         int argument_number) {
-  const Cids* cids = Cids::Create(Z, *call->ic_data(), argument_number);
+  const Cids* cids =
+      Cids::CreateAndExpand(Z, *call->ic_data(), argument_number);
   AddCheckClass(instr, *cids, call->deopt_id(), call->env(), call);
 }
 
@@ -1502,7 +1503,7 @@
                 new (Z) Value(call->ArgumentAt(1)), call->deopt_id(),
                 result_cid);
             const Cids* cids =
-                Cids::Create(Z, ic_data, /* argument_number =*/0);
+                Cids::CreateAndExpand(Z, ic_data, /* argument_number =*/0);
             AddCheckClass(min_max->left()->definition(), *cids,
                           call->deopt_id(), call->env(), call);
             AddCheckClass(min_max->right()->definition(), *cids,
diff --git a/runtime/vm/compiler/ffi.cc b/runtime/vm/compiler/ffi.cc
index 823e8ef..665382a 100644
--- a/runtime/vm/compiler/ffi.cc
+++ b/runtime/vm/compiler/ffi.cc
@@ -9,6 +9,8 @@
 #include "platform/globals.h"
 #include "vm/compiler/backend/locations.h"
 #include "vm/compiler/runtime_api.h"
+#include "vm/growable_array.h"
+#include "vm/stack_frame.h"
 
 namespace dart {
 
@@ -182,7 +184,7 @@
           class Location,
           class Register,
           class FpuRegister>
-class ArgumentFrameState : public ValueObject {
+class ArgumentAllocator : public ValueObject {
  public:
   Location AllocateArgument(Representation rep) {
     switch (rep) {
@@ -207,9 +209,13 @@
     }
 
     // Argument must be spilled.
-    if ((rep == kUnboxedInt64 || rep == kUnboxedDouble) &&
-        compiler::target::kWordSize == 4) {
+    if (rep == kUnboxedInt64 && compiler::target::kWordSize == 4) {
       return AllocateAlignedStackSlots(rep);
+    } else if (rep == kUnboxedDouble) {
+      // By convention, we always use DoubleStackSlot for doubles, even on
+      // 64-bit systems.
+      ASSERT(!CallingConventions::kAlignArguments);
+      return AllocateDoubleStackSlot();
     } else {
       return AllocateStackSlot();
     }
@@ -221,6 +227,13 @@
                                CallingConventions::kStackPointerRegister);
   }
 
+  Location AllocateDoubleStackSlot() {
+    const Location result = Location::DoubleStackSlot(
+        stack_height_in_slots, CallingConventions::kStackPointerRegister);
+    stack_height_in_slots += 8 / compiler::target::kWordSize;
+    return result;
+  }
+
   // Allocates a pair of stack slots where the first stack slot is aligned to an
   // 8-byte boundary, if necessary.
   Location AllocateAlignedStackSlots(Representation rep) {
@@ -287,6 +300,68 @@
   intptr_t stack_height_in_slots = 0;
 };
 
+ZoneGrowableArray<Location>*
+CallbackArgumentTranslator::TranslateArgumentLocations(
+    const ZoneGrowableArray<Location>& arg_locs) {
+  auto& pushed_locs = *(new ZoneGrowableArray<Location>(arg_locs.length()));
+
+  CallbackArgumentTranslator translator;
+  for (intptr_t i = 0, n = arg_locs.length(); i < n; i++) {
+    translator.AllocateArgument(arg_locs[i]);
+  }
+  for (intptr_t i = 0, n = arg_locs.length(); i < n; ++i) {
+    pushed_locs.Add(translator.TranslateArgument(arg_locs[i]));
+  }
+
+  return &pushed_locs;
+}
+
+void CallbackArgumentTranslator::AllocateArgument(Location arg) {
+  if (arg.IsPairLocation()) {
+    AllocateArgument(arg.Component(0));
+    AllocateArgument(arg.Component(1));
+    return;
+  }
+  if (arg.HasStackIndex()) return;
+  ASSERT(arg.IsRegister() || arg.IsFpuRegister());
+  if (arg.IsRegister()) {
+    argument_slots_required_++;
+  } else {
+    argument_slots_required_ += 8 / compiler::target::kWordSize;
+  }
+}
+
+Location CallbackArgumentTranslator::TranslateArgument(Location arg) {
+  if (arg.IsPairLocation()) {
+    const Location low = TranslateArgument(arg.Component(0));
+    const Location high = TranslateArgument(arg.Component(1));
+    return Location::Pair(low, high);
+  }
+
+  if (arg.HasStackIndex()) {
+    // Add extra slots after the saved arguments for the return address and
+    // frame pointer of the dummy arguments frame, which will be between the
+    // saved argument registers and stack arguments. Also add slots for the
+    // shadow space if present (factored into
+    // kCallbackSlotsBeforeSavedArguments).
+    FrameRebase rebase(
+        /*old_base=*/SPREG, /*new_base=*/SPREG,
+        /*stack_delta=*/argument_slots_required_ +
+            kCallbackSlotsBeforeSavedArguments);
+    return rebase.Rebase(arg);
+  }
+
+  if (arg.IsRegister()) {
+    return Location::StackSlot(argument_slots_used_++, SPREG);
+  }
+
+  ASSERT(arg.IsFpuRegister());
+  const Location result =
+      Location::DoubleStackSlot(argument_slots_used_, SPREG);
+  argument_slots_used_ += 8 / compiler::target::kWordSize;
+  return result;
+}
+
 // Takes a list of argument representations, and converts it to a list of
 // argument locations based on calling convention.
 template <class CallingConventions,
@@ -299,7 +374,7 @@
   auto result = new ZoneGrowableArray<Location>(num_arguments);
 
   // Loop through all arguments and assign a register or a stack location.
-  ArgumentFrameState<CallingConventions, Location, Register, FpuRegister>
+  ArgumentAllocator<CallingConventions, Location, Register, FpuRegister>
       frame_state;
   for (intptr_t i = 0; i < num_arguments; i++) {
     Representation rep = arg_reps[i];
diff --git a/runtime/vm/compiler/ffi.h b/runtime/vm/compiler/ffi.h
index cd8e96f..846775a 100644
--- a/runtime/vm/compiler/ffi.h
+++ b/runtime/vm/compiler/ffi.h
@@ -108,6 +108,31 @@
 
 #endif  // defined(TARGET_ARCH_DBC)
 
+// This classes translates the ABI location of arguments into the locations they
+// will inhabit after entry-frame setup in the invocation of a native callback.
+//
+// Native -> Dart callbacks must push all the arguments before executing any
+// Dart code because the reading the Thread from TLS requires calling a native
+// stub, and the argument registers are volatile on all ABIs we support.
+//
+// To avoid complicating initial definitions, all callback arguments are read
+// off the stack from their pushed locations, so this class updates the argument
+// positions to account for this.
+//
+// See 'NativeEntryInstr::EmitNativeCode' for details.
+class CallbackArgumentTranslator : public ValueObject {
+ public:
+  static ZoneGrowableArray<Location>* TranslateArgumentLocations(
+      const ZoneGrowableArray<Location>& arg_locs);
+
+ private:
+  void AllocateArgument(Location arg);
+  Location TranslateArgument(Location arg);
+
+  intptr_t argument_slots_used_ = 0;
+  intptr_t argument_slots_required_ = 0;
+};
+
 }  // namespace ffi
 
 }  // namespace compiler
diff --git a/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S b/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S
index efec2db..e8d1918 100644
--- a/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S
+++ b/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S
@@ -18,15 +18,15 @@
 /* Copy stack arguments. */
 mov   rax,  [rbx+0x78] /* Load number of stack arguments. */
 cmp   rax,  0x0        /* Check if number of stack arguments is 0. */
-jz    2f               /* Skip loop if no stack arguments. */
+jz    .done            /* Skip loop if no stack arguments. */
 add   rbx,  0x78       /* Offset RBX to point to stack arguments */
-1:                     /* Copy stack arguments loop. */
+.loop:                 /* Copy stack arguments loop. */
 push  [rbx+0x8*rax]    /* Push stack argument. */
 sub   rax,  0x1        /* Decrement stack argument iterator. */
 cmp   rax,  0x0        /* Compare iterator with 0 */
-jnz   1b               /* Loop while iterator is not 0 */
+jnz   .loop            /* Loop while iterator is not 0 */
 sub   rbx,  0x78       /* Restore RBX to original value. */
-2:                     /* End stack arguments loop. */
+.done:                 /* End stack arguments loop. */
 
 /* Copy registers and fpu registers. */
 mov   rdi,  [rbx+0x8]  /* kArg1Reg */
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index 61f37dfe..71a60b5 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -1951,7 +1951,7 @@
     }
 
     while (update_position &&
-           pc_ >= source_pos_iter.BytecodeInstructionIndex()) {
+           static_cast<uword>(pc_) >= source_pos_iter.PcOffset()) {
       position_ = source_pos_iter.TokenPos();
       update_position = source_pos_iter.MoveNext();
     }
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 690d873..e59d856 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -12,9 +12,11 @@
 #include "vm/compiler/frontend/bytecode_scope_builder.h"
 #include "vm/constants_kbc.h"
 #include "vm/dart_entry.h"
+#include "vm/debugger.h"
 #include "vm/longjump.h"
 #include "vm/object_store.h"
 #include "vm/reusable_handles.h"
+#include "vm/stack_frame_kbc.h"
 #include "vm/timeline.h"
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -244,6 +246,7 @@
       (flags & Code::kHasExceptionsTableFlag) != 0;
   const bool has_source_positions =
       (flags & Code::kHasSourcePositionsFlag) != 0;
+  const bool has_local_variables = (flags & Code::kHasLocalVariablesFlag) != 0;
   const bool has_nullable_fields = (flags & Code::kHasNullableFieldsFlag) != 0;
   const bool has_closures = (flags & Code::kHasClosuresFlag) != 0;
   const bool has_parameters_flags = (flags & Code::kHasParameterFlagsFlag) != 0;
@@ -299,6 +302,8 @@
 
   ReadSourcePositions(bytecode, has_source_positions);
 
+  ReadLocalVariables(bytecode, has_local_variables);
+
   if (FLAG_dump_kernel_bytecode) {
     KernelBytecodeDisassembler::Disassemble(function);
   }
@@ -330,9 +335,11 @@
 
       const intptr_t flags = helper_->reader_.ReadUInt();
       const bool has_exceptions_table =
-          (flags & Code::kHasExceptionsTableFlag) != 0;
+          (flags & ClosureCode::kHasExceptionsTableFlag) != 0;
       const bool has_source_positions =
-          (flags & Code::kHasSourcePositionsFlag) != 0;
+          (flags & ClosureCode::kHasSourcePositionsFlag) != 0;
+      const bool has_local_variables =
+          (flags & ClosureCode::kHasLocalVariablesFlag) != 0;
 
       // Read closure bytecode and attach to closure function.
       closure_bytecode = ReadBytecode(pool);
@@ -343,6 +350,8 @@
 
       ReadSourcePositions(closure_bytecode, has_source_positions);
 
+      ReadLocalVariables(closure_bytecode, has_local_variables);
+
       if (FLAG_dump_kernel_bytecode) {
         KernelBytecodeDisassembler::Disassemble(closure);
       }
@@ -352,9 +361,12 @@
 
 void BytecodeReaderHelper::ReadClosureDeclaration(const Function& function,
                                                   intptr_t closureIndex) {
-  const int kHasOptionalPositionalParams = 1 << 0;
-  const int kHasOptionalNamedParams = 1 << 1;
-  const int kHasTypeParams = 1 << 2;
+  // Closure flags, must be in sync with ClosureDeclaration constants in
+  // pkg/vm/lib/bytecode/declarations.dart.
+  const int kHasOptionalPositionalParamsFlag = 1 << 0;
+  const int kHasOptionalNamedParamsFlag = 1 << 1;
+  const int kHasTypeParamsFlag = 1 << 2;
+  const int kHasSourcePositionsFlag = 1 << 3;
 
   const intptr_t flags = helper_->reader_.ReadUInt();
 
@@ -369,20 +381,27 @@
   String& name = String::CheckedHandle(Z, ReadObject());
   ASSERT(name.IsSymbol());
 
+  TokenPosition position = TokenPosition::kNoSource;
+  TokenPosition end_position = TokenPosition::kNoSource;
+  if ((flags & kHasSourcePositionsFlag) != 0) {
+    position = helper_->ReadPosition();
+    end_position = helper_->ReadPosition();
+  }
+
   const Function& closure = Function::Handle(
-      Z, Function::NewClosureFunction(name, Function::Cast(parent),
-                                      TokenPosition::kNoSource));
+      Z, Function::NewClosureFunction(name, Function::Cast(parent), position));
 
   closure.set_is_declared_in_bytecode(true);
+  closure.set_end_token_pos(end_position);
 
   closures_->SetAt(closureIndex, closure);
 
-  Type& signature_type =
-      Type::Handle(Z, ReadFunctionSignature(
-                          closure, (flags & kHasOptionalPositionalParams) != 0,
-                          (flags & kHasOptionalNamedParams) != 0,
-                          (flags & kHasTypeParams) != 0,
-                          /* has_positional_param_names = */ true));
+  Type& signature_type = Type::Handle(
+      Z, ReadFunctionSignature(closure,
+                               (flags & kHasOptionalPositionalParamsFlag) != 0,
+                               (flags & kHasOptionalNamedParamsFlag) != 0,
+                               (flags & kHasTypeParamsFlag) != 0,
+                               /* has_positional_param_names = */ true));
 
   closure.SetSignatureType(signature_type);
 }
@@ -397,8 +416,6 @@
 
   if (has_type_params) {
     ReadTypeParametersDeclaration(Class::Handle(Z), func);
-    function_type_type_parameters_ =
-        &TypeArguments::Handle(Z, func.type_parameters());
   }
 
   const intptr_t kImplicitClosureParam = 1;
@@ -480,6 +497,7 @@
     // Do not set type parameters for factories, as VM uses class type
     // parameters instead.
     parameterized_function.set_type_parameters(type_parameters);
+    function_type_type_parameters_ = &type_parameters;
   }
 
   // Step b) Fill in the bounds of all [TypeParameter]s.
@@ -789,6 +807,21 @@
       bytecode_component_->GetSourcePositionsOffset() + offset);
 }
 
+void BytecodeReaderHelper::ReadLocalVariables(const Bytecode& bytecode,
+                                              bool has_local_variables) {
+  if (!has_local_variables) {
+    return;
+  }
+
+  intptr_t offset = helper_->reader_.ReadUInt();
+  USE(offset);
+
+#if !defined(PRODUCT)
+  bytecode.set_local_variables_binary_offset(
+      bytecode_component_->GetLocalVariablesOffset() + offset);
+#endif
+}
+
 RawTypedData* BytecodeReaderHelper::NativeEntry(const Function& function,
                                                 const String& external_name) {
   MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
@@ -902,6 +935,14 @@
   const intptr_t sources_positions_offset =
       start_offset + helper_->reader_.ReadUInt32();
 
+  intptr_t local_variables_offset = 0;
+  static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 9,
+                "Cleanup condition");
+  if (version >= 9) {
+    helper_->reader_.ReadUInt32();  // Skip localVariables.numItems
+    local_variables_offset = start_offset + helper_->reader_.ReadUInt32();
+  }
+
   helper_->reader_.ReadUInt32();  // Skip annotations.numItems
   const intptr_t annotations_offset =
       start_offset + helper_->reader_.ReadUInt32();
@@ -924,11 +965,11 @@
   helper_->reader_.set_offset(objects_contents_offset + objects_size);
 
   const Array& bytecode_component_array = Array::Handle(
-      Z,
-      BytecodeComponentData::New(
-          Z, version, num_objects, string_table_offset, strings_contents_offset,
-          objects_contents_offset, main_offset, members_offset, codes_offset,
-          sources_positions_offset, annotations_offset, Heap::kOld));
+      Z, BytecodeComponentData::New(
+             Z, version, num_objects, string_table_offset,
+             strings_contents_offset, objects_contents_offset, main_offset,
+             members_offset, codes_offset, sources_positions_offset,
+             local_variables_offset, annotations_offset, Heap::kOld));
 
   BytecodeComponentData bytecode_component(bytecode_component_array);
 
@@ -2084,6 +2125,10 @@
   return Smi::Value(Smi::RawCast(data_.At(kSourcePositionsOffset)));
 }
 
+intptr_t BytecodeComponentData::GetLocalVariablesOffset() const {
+  return Smi::Value(Smi::RawCast(data_.At(kLocalVariablesOffset)));
+}
+
 intptr_t BytecodeComponentData::GetAnnotationsOffset() const {
   return Smi::Value(Smi::RawCast(data_.At(kAnnotationsOffset)));
 }
@@ -2106,6 +2151,7 @@
                                      intptr_t members_offset,
                                      intptr_t codes_offset,
                                      intptr_t source_positions_offset,
+                                     intptr_t local_variables_offset,
                                      intptr_t annotations_offset,
                                      Heap::Space space) {
   const Array& data =
@@ -2136,6 +2182,9 @@
   smi_handle = Smi::New(source_positions_offset);
   data.SetAt(kSourcePositionsOffset, smi_handle);
 
+  smi_handle = Smi::New(local_variables_offset);
+  data.SetAt(kLocalVariablesOffset, smi_handle);
+
   smi_handle = Smi::New(annotations_offset);
   data.SetAt(kAnnotationsOffset, smi_handle);
 
@@ -2183,6 +2232,10 @@
 
     bytecode_metadata_helper.ReadMetadata(function);
 
+#if !defined(PRODUCT)
+    thread->isolate()->debugger()->NotifyBytecodeLoaded(function);
+#endif
+
     return Error::null();
   } else {
     return thread->StealStickyError();
@@ -2213,6 +2266,108 @@
       annotation_field.bytecode_offset());
 }
 
+#if !defined(PRODUCT)
+RawLocalVarDescriptors* BytecodeReader::ComputeLocalVarDescriptors(
+    Zone* zone,
+    const Function& function,
+    const Bytecode& bytecode) {
+  ASSERT(function.is_declared_in_bytecode());
+  ASSERT(function.HasBytecode());
+  ASSERT(!bytecode.IsNull());
+  ASSERT(function.bytecode() == bytecode.raw());
+
+  struct VarDesc {
+    const String* name;
+    RawLocalVarDescriptors::VarInfo info;
+  };
+  GrowableArray<VarDesc> vars(8);
+
+  if (function.IsLocalFunction()) {
+    const auto& parent = Function::Handle(zone, function.parent_function());
+    ASSERT(parent.is_declared_in_bytecode() && parent.HasBytecode());
+    const auto& parent_bytecode = Bytecode::Handle(zone, parent.bytecode());
+    const auto& parent_vars = LocalVarDescriptors::Handle(
+        zone, parent_bytecode.GetLocalVarDescriptors());
+    for (intptr_t i = 0; i < parent_vars.Length(); ++i) {
+      RawLocalVarDescriptors::VarInfo var_info;
+      parent_vars.GetInfo(i, &var_info);
+      // Include parent's context variable if variable's scope
+      // intersects with the local function range.
+      // It is not enough to check if local function is declared within the
+      // scope of variable, because in case of async functions closure has
+      // the same range as original function.
+      if (var_info.kind() == RawLocalVarDescriptors::kContextVar &&
+          ((var_info.begin_pos <= function.token_pos() &&
+            function.token_pos() <= var_info.end_pos) ||
+           (function.token_pos() <= var_info.begin_pos &&
+            var_info.begin_pos <= function.end_token_pos()))) {
+        vars.Add(
+            VarDesc{&String::Handle(zone, parent_vars.GetName(i)), var_info});
+      }
+    }
+  }
+
+  if (bytecode.HasLocalVariablesInfo()) {
+    intptr_t scope_id = 0;
+    intptr_t context_level = -1;
+    BytecodeLocalVariablesIterator local_vars(zone, bytecode);
+    while (local_vars.MoveNext()) {
+      switch (local_vars.Kind()) {
+        case BytecodeLocalVariablesIterator::kScope: {
+          ++scope_id;
+          context_level = local_vars.ContextLevel();
+        } break;
+        case BytecodeLocalVariablesIterator::kVariableDeclaration: {
+          VarDesc desc;
+          desc.name = &String::Handle(zone, local_vars.Name());
+          if (local_vars.IsCaptured()) {
+            desc.info.set_kind(RawLocalVarDescriptors::kContextVar);
+            desc.info.scope_id = context_level;
+            desc.info.set_index(local_vars.Index());
+          } else {
+            desc.info.set_kind(RawLocalVarDescriptors::kStackVar);
+            desc.info.scope_id = scope_id;
+            if (local_vars.Index() < 0) {
+              // Parameter
+              desc.info.set_index(-local_vars.Index() - kKBCParamEndSlotFromFp);
+            } else {
+              desc.info.set_index(-local_vars.Index());
+            }
+          }
+          desc.info.declaration_pos = local_vars.DeclarationTokenPos();
+          desc.info.begin_pos = local_vars.StartTokenPos();
+          desc.info.end_pos = local_vars.EndTokenPos();
+          vars.Add(desc);
+        } break;
+        case BytecodeLocalVariablesIterator::kContextVariable: {
+          ASSERT(local_vars.Index() >= 0);
+          const intptr_t context_variable_index = -local_vars.Index();
+          VarDesc desc;
+          desc.name = &Symbols::CurrentContextVar();
+          desc.info.set_kind(RawLocalVarDescriptors::kSavedCurrentContext);
+          desc.info.scope_id = 0;
+          desc.info.declaration_pos = TokenPosition::kMinSource;
+          desc.info.begin_pos = TokenPosition::kMinSource;
+          desc.info.end_pos = TokenPosition::kMinSource;
+          desc.info.set_index(context_variable_index);
+          vars.Add(desc);
+        } break;
+      }
+    }
+  }
+
+  if (vars.is_empty()) {
+    return Object::empty_var_descriptors().raw();
+  }
+  const LocalVarDescriptors& var_desc = LocalVarDescriptors::Handle(
+      zone, LocalVarDescriptors::New(vars.length()));
+  for (intptr_t i = 0; i < vars.length(); i++) {
+    var_desc.SetVar(i, *(vars[i].name), &vars[i].info);
+  }
+  return var_desc.raw();
+}
+#endif  // !defined(PRODUCT)
+
 static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 7,
               "Cleanup support for old bytecode format versions");
 void BytecodeReader::UseBytecodeVersion(intptr_t version) {
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.h b/runtime/vm/compiler/frontend/bytecode_reader.h
index 701cc2d..9353029 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.h
+++ b/runtime/vm/compiler/frontend/bytecode_reader.h
@@ -109,6 +109,15 @@
     static const int kHasParameterFlagsFlag = 1 << 4;
     static const int kHasForwardingStubTargetFlag = 1 << 5;
     static const int kHasDefaultFunctionTypeArgsFlag = 1 << 6;
+    static const int kHasLocalVariablesFlag = 1 << 7;
+  };
+
+  // Closure code flags, must be in sync with ClosureCode constants in
+  // pkg/vm/lib/bytecode/declarations.dart.
+  struct ClosureCode {
+    static const int kHasExceptionsTableFlag = 1 << 0;
+    static const int kHasSourcePositionsFlag = 1 << 1;
+    static const int kHasLocalVariablesFlag = 1 << 2;
   };
 
   // Parameter flags, must be in sync with ParameterDeclaration constants in
@@ -131,7 +140,7 @@
 
    private:
     BytecodeReaderHelper* bytecode_reader_;
-    TypeArguments* const saved_type_parameters_;
+    const TypeArguments* const saved_type_parameters_;
   };
 
   class FunctionScope : public ValueObject {
@@ -173,6 +182,7 @@
   RawBytecode* ReadBytecode(const ObjectPool& pool);
   void ReadExceptionsTable(const Bytecode& bytecode, bool has_exceptions_table);
   void ReadSourcePositions(const Bytecode& bytecode, bool has_source_positions);
+  void ReadLocalVariables(const Bytecode& bytecode, bool has_local_variables);
   RawTypedData* NativeEntry(const Function& function,
                             const String& external_name);
   RawString* ConstructorName(const Class& cls, const String& name);
@@ -192,7 +202,7 @@
   Zone* const zone_;
   BytecodeComponentData* const bytecode_component_;
   Array* closures_ = nullptr;
-  TypeArguments* function_type_type_parameters_ = nullptr;
+  const TypeArguments* function_type_type_parameters_ = nullptr;
   PatchClass* patch_class_ = nullptr;
   Array* functions_ = nullptr;
   intptr_t function_index_ = 0;
@@ -214,6 +224,7 @@
     kMembersOffset,
     kCodesOffset,
     kSourcePositionsOffset,
+    kLocalVariablesOffset,
     kAnnotationsOffset,
     kNumFields
   };
@@ -228,6 +239,7 @@
   intptr_t GetMembersOffset() const;
   intptr_t GetCodesOffset() const;
   intptr_t GetSourcePositionsOffset() const;
+  intptr_t GetLocalVariablesOffset() const;
   intptr_t GetAnnotationsOffset() const;
   void SetObject(intptr_t index, const Object& obj) const;
   RawObject* GetObject(intptr_t index) const;
@@ -244,6 +256,7 @@
                        intptr_t members_offset,
                        intptr_t codes_offset,
                        intptr_t source_positions_offset,
+                       intptr_t local_variables_offset,
                        intptr_t annotations_offset,
                        Heap::Space space);
 
@@ -261,21 +274,27 @@
   // Read annotation for the given annotation field.
   static RawObject* ReadAnnotation(const Field& annotation_field);
 
+#if !defined(PRODUCT)
+  // Compute local variable descriptors for [function] with [bytecode].
+  static RawLocalVarDescriptors* ComputeLocalVarDescriptors(
+      Zone* zone,
+      const Function& function,
+      const Bytecode& bytecode);
+#endif
+
   static void UseBytecodeVersion(intptr_t version);
 };
 
 class BytecodeSourcePositionsIterator : ValueObject {
  public:
   BytecodeSourcePositionsIterator(Zone* zone, const Bytecode& bytecode)
-      : reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))),
-        pairs_remaining_(0),
-        pc_shifter_(
-            Isolate::Current()->is_using_old_bytecode_instructions() ? 2 : 0),
-        cur_bci_(0),
-        cur_token_pos_(TokenPosition::kNoSource.value()) {
+      : reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))) {
     if (bytecode.HasSourcePositions()) {
       reader_.set_offset(bytecode.source_positions_binary_offset());
       pairs_remaining_ = reader_.ReadUInt();
+      if (Isolate::Current()->is_using_old_bytecode_instructions()) {
+        pc_shifter_ = 2;
+      }
     }
   }
 
@@ -290,23 +309,130 @@
     return true;
   }
 
-  intptr_t BytecodeInstructionIndex() const { return cur_bci_; }
-
-  uword PcOffset() const {
-    return KernelBytecode::BytecodePcToOffset(BytecodeInstructionIndex(),
-                                              /* is_return_address = */ true);
-  }
+  uword PcOffset() const { return cur_bci_; }
 
   TokenPosition TokenPos() const { return TokenPosition(cur_token_pos_); }
 
  private:
   Reader reader_;
-  intptr_t pairs_remaining_;
-  intptr_t pc_shifter_;
-  intptr_t cur_bci_;
-  intptr_t cur_token_pos_;
+  intptr_t pairs_remaining_ = 0;
+  intptr_t pc_shifter_ = 0;
+  intptr_t cur_bci_ = 0;
+  intptr_t cur_token_pos_ = 0;
 };
 
+#if !defined(PRODUCT)
+class BytecodeLocalVariablesIterator : ValueObject {
+ public:
+  // These constants should match corresponding constants in
+  // pkg/vm/lib/bytecode/local_variable_table.dart.
+  enum {
+    kInvalid,
+    kScope,
+    kVariableDeclaration,
+    kContextVariable,
+  };
+
+  static const intptr_t kKindMask = 0xF;
+  static const intptr_t kIsCapturedFlag = 1 << 4;
+
+  BytecodeLocalVariablesIterator(Zone* zone, const Bytecode& bytecode)
+      : reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))),
+        object_pool_(ObjectPool::Handle(zone, bytecode.object_pool())) {
+    if (bytecode.HasLocalVariablesInfo()) {
+      reader_.set_offset(bytecode.local_variables_binary_offset());
+      entries_remaining_ = reader_.ReadUInt();
+    }
+  }
+
+  bool MoveNext() {
+    if (entries_remaining_ == 0) {
+      return false;
+    }
+    ASSERT(entries_remaining_ > 0);
+    --entries_remaining_;
+    cur_kind_and_flags_ = reader_.ReadByte();
+    cur_start_pc_ += reader_.ReadSLEB128();
+    switch (Kind()) {
+      case kScope:
+        cur_end_pc_ = cur_start_pc_ + reader_.ReadUInt();
+        cur_index_ = reader_.ReadSLEB128();
+        cur_token_pos_ = reader_.ReadPosition();
+        cur_end_token_pos_ = reader_.ReadPosition();
+        break;
+      case kVariableDeclaration:
+        cur_index_ = reader_.ReadSLEB128();
+        cur_name_ = reader_.ReadUInt();
+        cur_type_ = reader_.ReadUInt();
+        cur_declaration_token_pos_ = reader_.ReadPosition();
+        cur_token_pos_ = reader_.ReadPosition();
+        break;
+      case kContextVariable:
+        cur_index_ = reader_.ReadSLEB128();
+        break;
+    }
+    return true;
+  }
+
+  intptr_t Kind() const { return cur_kind_and_flags_ & kKindMask; }
+  bool IsScope() const { return Kind() == kScope; }
+  bool IsVariableDeclaration() const { return Kind() == kVariableDeclaration; }
+  bool IsContextVariable() const { return Kind() == kContextVariable; }
+
+  intptr_t StartPC() const { return cur_start_pc_; }
+  intptr_t EndPC() const {
+    ASSERT(IsScope() || IsVariableDeclaration());
+    return cur_end_pc_;
+  }
+  intptr_t ContextLevel() const {
+    ASSERT(IsScope());
+    return cur_index_;
+  }
+  TokenPosition StartTokenPos() const {
+    ASSERT(IsScope() || IsVariableDeclaration());
+    return cur_token_pos_;
+  }
+  TokenPosition EndTokenPos() const {
+    ASSERT(IsScope() || IsVariableDeclaration());
+    return cur_end_token_pos_;
+  }
+  intptr_t Index() const {
+    ASSERT(IsVariableDeclaration() || IsContextVariable());
+    return cur_index_;
+  }
+  RawString* Name() const {
+    ASSERT(IsVariableDeclaration());
+    return String::RawCast(object_pool_.ObjectAt(cur_name_));
+  }
+  RawAbstractType* Type() const {
+    ASSERT(IsVariableDeclaration());
+    return AbstractType::RawCast(object_pool_.ObjectAt(cur_type_));
+  }
+  TokenPosition DeclarationTokenPos() const {
+    ASSERT(IsVariableDeclaration());
+    return cur_declaration_token_pos_;
+  }
+  bool IsCaptured() const {
+    ASSERT(IsVariableDeclaration());
+    return (cur_kind_and_flags_ & kIsCapturedFlag) != 0;
+  }
+
+ private:
+  Reader reader_;
+  const ObjectPool& object_pool_;
+  intptr_t entries_remaining_ = 0;
+  intptr_t cur_kind_and_flags_ = 0;
+  intptr_t cur_start_pc_ = 0;
+  intptr_t cur_end_pc_ = 0;
+  intptr_t cur_index_ = -1;
+  intptr_t cur_name_ = -1;
+  intptr_t cur_type_ = -1;
+  TokenPosition cur_token_pos_ = TokenPosition::kNoSource;
+  TokenPosition cur_declaration_token_pos_ = TokenPosition::kNoSource;
+  TokenPosition cur_end_token_pos_ = TokenPosition::kNoSource;
+};
+#endif  // !defined(PRODUCT)
+
 bool IsStaticFieldGetterGeneratedAsInitializer(const Function& function,
                                                Zone* zone);
 
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index 2ac1adf..6da7494 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -82,7 +82,6 @@
   }
   helper.SetJustRead(ConstructorHelper::kInitializers);
   BuildHash(helper.flags_);
-  BuildHash(helper.annotation_count_);
 }
 
 void KernelFingerprintHelper::CalculateArgumentsFingerprint() {
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 6049959..f3524f5 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -16,6 +16,7 @@
 #include "vm/compiler/jit/compiler.h"
 #include "vm/kernel_loader.h"
 #include "vm/longjump.h"
+#include "vm/native_entry.h"
 #include "vm/object_store.h"
 #include "vm/report.h"
 #include "vm/resolver.h"
@@ -2440,6 +2441,31 @@
   return Fragment(extend);
 }
 
+Fragment FlowGraphBuilder::FfiExceptionalReturnValue(
+    const AbstractType& result_type,
+    Representation representation) {
+  ASSERT(optimizing_);
+  Object& result = Object::ZoneHandle(Z, Object::null());
+  if (representation == kUnboxedFloat || representation == kUnboxedDouble) {
+    result = Double::New(0.0, Heap::kOld);
+  } else {
+    result = Integer::New(0, Heap::kOld);
+  }
+  Fragment code;
+  code += Constant(result);
+  code += UnboxTruncate(representation);
+  return code;
+}
+
+#if !defined(TARGET_ARCH_DBC)
+Fragment FlowGraphBuilder::NativeReturn(Representation result) {
+  auto* instr = new (Z)
+      NativeReturnInstr(TokenPosition::kNoSource, Pop(), result,
+                        compiler::ffi::ResultLocation(result), DeoptId::kNone);
+  return Fragment(instr);
+}
+#endif
+
 Fragment FlowGraphBuilder::FfiPointerFromAddress(const Type& result_type) {
   Fragment test;
   TargetEntryInstr* null_entry;
@@ -2465,6 +2491,9 @@
   Fragment box(not_null_entry);
   {
     Class& result_class = Class::ZoneHandle(Z, result_type.type_class());
+    // This class might only be instantiated as a return type of ffi calls.
+    result_class.EnsureIsFinalized(thread_);
+
     TypeArguments& args = TypeArguments::ZoneHandle(Z, result_type.arguments());
 
     // A kernel transform for FFI in the front-end ensures that type parameters
@@ -2498,8 +2527,69 @@
   return Fragment(instr);
 }
 
+Fragment FlowGraphBuilder::FfiConvertArgumentToDart(
+    const AbstractType& ffi_type,
+    const Representation native_representation) {
+  Fragment body;
+  if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+    body += Box(kUnboxedFfiIntPtr);
+    body += FfiPointerFromAddress(Type::Cast(ffi_type));
+  } else if (compiler::ffi::NativeTypeIsVoid(ffi_type)) {
+    body += Drop();
+    body += NullConstant();
+  } else {
+    const Representation from_rep = native_representation;
+    const Representation to_rep = compiler::ffi::TypeRepresentation(ffi_type);
+    if (from_rep != to_rep) {
+      body += BitCast(from_rep, to_rep);
+    } else {
+      body += FfiUnboxedExtend(from_rep, ffi_type);
+    }
+    body += Box(to_rep);
+  }
+  return body;
+}
+
+Fragment FlowGraphBuilder::FfiConvertArgumentToNative(
+    const Function& function,
+    const AbstractType& ffi_type,
+    const Representation native_representation) {
+  Fragment body;
+  // Check for 'null'. Only ffi.Pointers are allowed to be null.
+  if (!compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+    body += LoadLocal(MakeTemporary());
+    body <<=
+        new (Z) CheckNullInstr(Pop(), String::ZoneHandle(Z, function.name()),
+                               GetNextDeoptId(), TokenPosition::kNoSource);
+  }
+
+  if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+    body += LoadAddressFromFfiPointer();
+    body += UnboxTruncate(kUnboxedFfiIntPtr);
+  } else {
+    Representation from_rep = compiler::ffi::TypeRepresentation(ffi_type);
+    body += UnboxTruncate(from_rep);
+
+    Representation to_rep = native_representation;
+    if (from_rep != to_rep) {
+      body += BitCast(from_rep, to_rep);
+    } else {
+      body += FfiUnboxedExtend(from_rep, ffi_type);
+    }
+  }
+  return body;
+}
+
 FlowGraph* FlowGraphBuilder::BuildGraphOfFfiTrampoline(
     const Function& function) {
+  if (function.FfiCallbackTarget() != Function::null()) {
+    return BuildGraphOfFfiCallback(function);
+  } else {
+    return BuildGraphOfFfiNative(function);
+  }
+}
+
+FlowGraph* FlowGraphBuilder::BuildGraphOfFfiNative(const Function& function) {
   graph_entry_ =
       new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
 
@@ -2532,29 +2622,7 @@
   for (intptr_t pos = 1; pos < function.num_fixed_parameters(); pos++) {
     body += LoadLocal(parsed_function_->ParameterVariable(pos));
     ffi_type = signature.ParameterTypeAt(pos);
-
-    // Check for 'null'. Only ffi.Pointers are allowed to be null.
-    if (!compiler::ffi::NativeTypeIsPointer(ffi_type)) {
-      body += LoadLocal(parsed_function_->ParameterVariable(pos));
-      body <<=
-          new (Z) CheckNullInstr(Pop(), String::ZoneHandle(Z, function.name()),
-                                 GetNextDeoptId(), TokenPosition::kNoSource);
-    }
-
-    if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
-      body += LoadAddressFromFfiPointer();
-      body += UnboxTruncate(kUnboxedFfiIntPtr);
-    } else {
-      Representation from_rep = compiler::ffi::TypeRepresentation(ffi_type);
-      body += UnboxTruncate(from_rep);
-
-      Representation to_rep = arg_reps[pos - 1];
-      if (from_rep != to_rep) {
-        body += BitCast(from_rep, to_rep);
-      } else {
-        body += FfiUnboxedExtend(from_rep, ffi_type);
-      }
-    }
+    body += FfiConvertArgumentToNative(function, ffi_type, arg_reps[pos - 1]);
   }
 
   // Push the function pointer, which is stored (boxed) in the first slot of the
@@ -2569,34 +2637,109 @@
   body += FfiCall(signature, arg_reps, arg_locs, arg_host_locs);
 
   ffi_type = signature.result_type();
-  if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
-    body += Box(kUnboxedFfiIntPtr);
-    body += FfiPointerFromAddress(Type::Cast(ffi_type));
-  } else if (compiler::ffi::NativeTypeIsVoid(ffi_type)) {
-    body += Drop();
-    body += NullConstant();
-  } else {
 #if !defined(TARGET_ARCH_DBC)
-    Representation from_rep = compiler::ffi::ResultRepresentation(signature);
+  const Representation from_rep =
+      compiler::ffi::ResultRepresentation(signature);
 #else
-    Representation from_rep =
-        compiler::ffi::ResultHostRepresentation(signature);
+  const Representation from_rep =
+      compiler::ffi::ResultHostRepresentation(signature);
 #endif  // !defined(TARGET_ARCH_DBC)
-    Representation to_rep = compiler::ffi::TypeRepresentation(ffi_type);
-    if (from_rep != to_rep) {
-      body += BitCast(from_rep, to_rep);
-    } else {
-      body += FfiUnboxedExtend(from_rep, ffi_type);
-    }
-    body += Box(to_rep);
-  }
-
+  body += FfiConvertArgumentToDart(ffi_type, from_rep);
   body += Return(TokenPosition::kNoSource);
 
   return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
                            prologue_info);
 }
 
+FlowGraph* FlowGraphBuilder::BuildGraphOfFfiCallback(const Function& function) {
+#if !defined(TARGET_ARCH_DBC)
+  const Function& signature = Function::ZoneHandle(Z, function.FfiCSignature());
+  const auto& arg_reps = *compiler::ffi::ArgumentRepresentations(signature);
+  const auto& arg_locs = *compiler::ffi::ArgumentLocations(arg_reps);
+  const auto& callback_locs =
+      *compiler::ffi::CallbackArgumentTranslator::TranslateArgumentLocations(
+          arg_locs);
+
+  graph_entry_ =
+      new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
+
+  auto* const native_entry = new (Z) NativeEntryInstr(
+      &arg_locs, graph_entry_, AllocateBlockId(), CurrentTryIndex(),
+      GetNextDeoptId(), function.FfiCallbackId());
+
+  graph_entry_->set_normal_entry(native_entry);
+
+  Fragment function_body(native_entry);
+  function_body += CheckStackOverflowInPrologue(function.token_pos());
+
+  // Wrap the entire method in a big try/catch. This is important to ensure that
+  // the VM does not crash if the callback throws an exception.
+  const intptr_t try_handler_index = AllocateTryIndex();
+  Fragment body = TryCatch(try_handler_index);
+  ++try_depth_;
+
+  // Box and push the arguments.
+  AbstractType& ffi_type = AbstractType::Handle(Z);
+  for (intptr_t i = 0, n = callback_locs.length(); i < n; ++i) {
+    ffi_type = signature.ParameterTypeAt(i + 1);
+    auto* parameter =
+        new (Z) NativeParameterInstr(callback_locs[i], arg_reps[i]);
+    Push(parameter);
+    body <<= parameter;
+    body += FfiConvertArgumentToDart(ffi_type, arg_reps[i]);
+    body += PushArgument();
+  }
+
+  // Call the target.
+  //
+  // TODO(36748): Determine the hot-reload semantics of callbacks and update the
+  // rebind-rule accordingly.
+  body += StaticCall(TokenPosition::kNoSource,
+                     Function::ZoneHandle(Z, function.FfiCallbackTarget()),
+                     callback_locs.length(), Array::empty_array(),
+                     ICData::kNoRebind);
+
+  ffi_type = signature.result_type();
+  const Representation result_rep =
+      compiler::ffi::ResultRepresentation(signature);
+  body += FfiConvertArgumentToNative(function, ffi_type, result_rep);
+  body += NativeReturn(result_rep);
+
+  --try_depth_;
+  function_body += body;
+
+  ++catch_depth_;
+  Fragment catch_body =
+      CatchBlockEntry(Array::empty_array(), try_handler_index,
+                      /*needs_stacktrace=*/true, /*is_synthesized=*/true);
+
+  catch_body += LoadLocal(CurrentException());
+  catch_body += PushArgument();
+  catch_body += LoadLocal(CurrentStackTrace());
+  catch_body += PushArgument();
+
+  // Find '_handleExposedException(e, st)' from ffi_patch.dart and call it.
+  const Library& ffi_lib =
+      Library::Handle(Z, Library::LookupLibrary(thread_, Symbols::DartFfi()));
+  const Function& handler = Function::ZoneHandle(
+      Z, ffi_lib.LookupFunctionAllowPrivate(Symbols::HandleExposedException()));
+  ASSERT(!handler.IsNull());
+  catch_body += StaticCall(TokenPosition::kNoSource, handler, /*num_args=*/2,
+                           /*arg_names=*/Array::empty_array(), ICData::kStatic);
+  catch_body += Drop();
+
+  catch_body += FfiExceptionalReturnValue(ffi_type, result_rep);
+  catch_body += NativeReturn(result_rep);
+  --catch_depth_;
+
+  PrologueInfo prologue_info(-1, -1);
+  return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
+                           prologue_info);
+#else
+  UNREACHABLE();
+#endif
+}
+
 void FlowGraphBuilder::SetCurrentTryCatchBlock(TryCatchBlock* try_catch_block) {
   try_catch_block_ = try_catch_block;
   SetCurrentTryIndex(try_catch_block == nullptr ? kInvalidTryIndex
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 1e34e13..9ccc1a94 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -101,6 +101,8 @@
   FlowGraph* BuildGraphOfNoSuchMethodDispatcher(const Function& function);
   FlowGraph* BuildGraphOfInvokeFieldDispatcher(const Function& function);
   FlowGraph* BuildGraphOfFfiTrampoline(const Function& function);
+  FlowGraph* BuildGraphOfFfiCallback(const Function& function);
+  FlowGraph* BuildGraphOfFfiNative(const Function& function);
 
   Fragment NativeFunctionBody(const Function& function,
                               LocalVariable* first_parameter);
@@ -236,6 +238,26 @@
   // the pointer.
   Fragment FfiPointerFromAddress(const Type& result_type);
 
+  // Pushes an (unboxed) bogus value returned when a native -> Dart callback
+  // throws an exception.
+  Fragment FfiExceptionalReturnValue(const AbstractType& result_type,
+                                     const Representation target);
+
+  // Pops a Dart object and push the unboxed native version, according to the
+  // semantics of FFI argument translation.
+  Fragment FfiConvertArgumentToNative(
+      const Function& function,
+      const AbstractType& ffi_type,
+      const Representation native_representation);
+
+  // Reverse of 'FfiConvertArgumentToNative'.
+  Fragment FfiConvertArgumentToDart(const AbstractType& ffi_type,
+                                    const Representation native_representation);
+
+  // Return from a native -> Dart callback. Can only be used in conjunction with
+  // NativeEntry and NativeParameter are used.
+  Fragment NativeReturn(Representation result);
+
   // Bit-wise cast between representations.
   // Pops the input and pushes the converted result.
   // Currently only works with equal sizes and floating point <-> integer.
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 26f5476..fcd1734 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -1367,6 +1367,55 @@
   }
 }
 
+#if defined(DEBUG)
+
+void MetadataHelper::VerifyMetadataMappings(
+    const ExternalTypedData& metadata_mappings) {
+  const intptr_t kUInt32Size = 4;
+  Reader reader(metadata_mappings);
+  if (reader.size() == 0) {
+    return;
+  }
+
+  // Scan through metadata mappings in reverse direction.
+
+  // Read metadataMappings length.
+  intptr_t offset = reader.size() - kUInt32Size;
+  const intptr_t metadata_num = reader.ReadUInt32At(offset);
+
+  if (metadata_num == 0) {
+    ASSERT(metadata_mappings.LengthInBytes() == kUInt32Size);
+    return;
+  }
+
+  // Read metadataMappings elements.
+  for (intptr_t i = 0; i < metadata_num; ++i) {
+    // Read nodeOffsetToMetadataOffset length.
+    offset -= kUInt32Size;
+    const intptr_t mappings_num = reader.ReadUInt32At(offset);
+
+    // Skip nodeOffsetToMetadataOffset.
+    offset -= mappings_num * 2 * kUInt32Size;
+
+    // Verify that node offsets are sorted.
+    intptr_t prev_node_offset = -1;
+    reader.set_offset(offset);
+    for (intptr_t j = 0; j < mappings_num; ++j) {
+      const intptr_t node_offset = reader.ReadUInt32();
+      const intptr_t md_offset = reader.ReadUInt32();
+
+      ASSERT(node_offset >= 0 && md_offset >= 0);
+      ASSERT(node_offset > prev_node_offset);
+      prev_node_offset = node_offset;
+    }
+
+    // Skip tag.
+    offset -= kUInt32Size;
+  }
+}
+
+#endif  // defined(DEBUG)
+
 MetadataHelper::MetadataHelper(KernelReaderHelper* helper,
                                const char* tag,
                                bool precompiler_only)
@@ -1386,25 +1435,6 @@
   ASSERT((mappings_offset != 0) && (mappings_num != 0));
   mappings_offset_ = mappings_offset;
   mappings_num_ = mappings_num;
-
-#ifdef DEBUG
-  // Verify that node offsets are sorted.
-  {
-    Reader reader(H.metadata_mappings());
-    reader.set_offset(mappings_offset);
-
-    intptr_t prev_node_offset = -1;
-    for (intptr_t i = 0; i < mappings_num; ++i) {
-      intptr_t node_offset = reader.ReadUInt32();
-      intptr_t md_offset = reader.ReadUInt32();
-
-      ASSERT((node_offset >= 0) && (md_offset >= 0));
-      ASSERT(node_offset > prev_node_offset);
-      prev_node_offset = node_offset;
-    }
-  }
-#endif  // DEBUG
-
   last_node_offset_ = kIntptrMax;
   last_mapping_index_ = 0;
 }
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 9508b70..4ca7a14 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -262,8 +262,8 @@
   TokenPosition end_position_;
   AsyncMarker async_marker_;
   AsyncMarker dart_async_marker_;
-  intptr_t total_parameter_count_;
-  intptr_t required_parameter_count_;
+  intptr_t total_parameter_count_ = 0;
+  intptr_t required_parameter_count_ = 0;
 
  private:
   KernelReaderHelper* helper_;
@@ -314,7 +314,7 @@
   }
 
   TokenPosition position_;
-  uint8_t flags_;
+  uint8_t flags_ = 0;
   StringIndex name_index_;
 
  private:
@@ -373,9 +373,9 @@
 
   TokenPosition position_;
   TokenPosition equals_position_;
-  uint8_t flags_;
+  uint8_t flags_ = 0;
   StringIndex name_index_;
-  intptr_t annotation_count_;
+  intptr_t annotation_count_ = 0;
 
  private:
   KernelReaderHelper* helper_;
@@ -452,9 +452,9 @@
   NameIndex canonical_name_;
   TokenPosition position_;
   TokenPosition end_position_;
-  uint8_t flags_;
-  intptr_t source_uri_index_;
-  intptr_t annotation_count_;
+  uint8_t flags_ = 0;
+  intptr_t source_uri_index_ = 0;
+  intptr_t annotation_count_ = 0;
 
  private:
   KernelReaderHelper* helper_;
@@ -542,9 +542,9 @@
   TokenPosition position_;
   TokenPosition end_position_;
   Kind kind_;
-  uint8_t flags_;
-  intptr_t source_uri_index_;
-  intptr_t annotation_count_;
+  uint8_t flags_ = 0;
+  intptr_t source_uri_index_ = 0;
+  intptr_t annotation_count_ = 0;
 
   // Only valid if the 'isForwardingStub' flag is set.
   NameIndex forwarding_stub_super_target_;
@@ -606,9 +606,9 @@
   TokenPosition start_position_;
   TokenPosition position_;
   TokenPosition end_position_;
-  uint8_t flags_;
-  intptr_t source_uri_index_;
-  intptr_t annotation_count_;
+  uint8_t flags_ = 0;
+  intptr_t source_uri_index_ = 0;
+  intptr_t annotation_count_ = 0;
 
  private:
   KernelReaderHelper* helper_;
@@ -679,10 +679,10 @@
   TokenPosition position_;
   TokenPosition end_position_;
   StringIndex name_index_;
-  intptr_t source_uri_index_;
-  intptr_t annotation_count_;
-  intptr_t procedure_count_;
-  uint8_t flags_;
+  intptr_t source_uri_index_ = 0;
+  intptr_t annotation_count_ = 0;
+  intptr_t procedure_count_ = 0;
+  uint8_t flags_ = 0;
 
  private:
   KernelReaderHelper* helper_;
@@ -741,10 +741,10 @@
   bool IsExternal() const { return (flags_ & kExternal) != 0; }
   bool IsSynthetic() const { return (flags_ & kSynthetic) != 0; }
 
-  uint8_t flags_;
+  uint8_t flags_ = 0;
   NameIndex canonical_name_;
   StringIndex name_index_;
-  intptr_t source_uri_index_;
+  intptr_t source_uri_index_ = 0;
 
  private:
   KernelReaderHelper* helper_;
@@ -775,7 +775,7 @@
   };
 
   explicit LibraryDependencyHelper(KernelReaderHelper* helper)
-      : annotation_count_(0), helper_(helper), next_read_(kFileOffset) {}
+      : helper_(helper), next_read_(kFileOffset) {}
 
   void ReadUntilIncluding(Field field) {
     ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1));
@@ -783,10 +783,10 @@
 
   void ReadUntilExcluding(Field field);
 
-  uint8_t flags_;
+  uint8_t flags_ = 0;
   StringIndex name_index_;
   NameIndex target_library_canonical_name_;
-  intptr_t annotation_count_;
+  intptr_t annotation_count_ = 0;
 
  private:
   KernelReaderHelper* helper_;
@@ -803,6 +803,11 @@
                  const char* tag,
                  bool precompiler_only);
 
+#if defined(DEBUG)
+  static void VerifyMetadataMappings(
+      const ExternalTypedData& metadata_mappings);
+#endif
+
  protected:
   // Look for metadata mapping with node offset greater or equal than the given.
   intptr_t FindMetadataMapping(intptr_t node_offset);
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index dde3667..10f5dd6 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -390,6 +390,18 @@
                                             : Object::dynamic_type().raw()));
         scope_->InsertParameterAt(i, variable);
       }
+      // Callbacks need try/catch variables.
+      if (function.IsFfiTrampoline() &&
+          function.FfiCallbackTarget() != Function::null()) {
+        current_function_async_marker_ = FunctionNodeHelper::kSync;
+        ++depth_.try_;
+        AddTryVariables();
+        --depth_.try_;
+        ++depth_.catch_;
+        AddCatchVariables();
+        FinalizeCatchVariables();
+        --depth_.catch_;
+      }
       break;
     case RawFunction::kSignatureFunction:
     case RawFunction::kIrregexpFunction:
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index da82ceb..d42a3cc 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -258,9 +258,7 @@
 
 bool Compiler::CanOptimizeFunction(Thread* thread, const Function& function) {
 #if !defined(PRODUCT)
-  Isolate* isolate = thread->isolate();
-  if (isolate->debugger()->IsStepping() ||
-      isolate->debugger()->HasBreakpoint(function, thread->zone())) {
+  if (Debugger::IsDebugging(thread, function)) {
     // We cannot set breakpoints and single step in optimized code,
     // so do not optimize the function. Bump usage counter down to avoid
     // repeatedly entering the runtime for an optimization attempt.
@@ -1110,16 +1108,27 @@
 void Compiler::ComputeLocalVarDescriptors(const Code& code) {
   ASSERT(!code.is_optimized());
   const Function& function = Function::Handle(code.function());
-  ParsedFunction* parsed_function = new ParsedFunction(
-      Thread::Current(), Function::ZoneHandle(function.raw()));
   ASSERT(code.var_descriptors() == Object::null());
   // IsIrregexpFunction have eager var descriptors generation.
   ASSERT(!function.IsIrregexpFunction());
+  if (function.is_declared_in_bytecode()) {
+    auto& var_descs = LocalVarDescriptors::Handle();
+    if (function.HasBytecode()) {
+      const auto& bytecode = Bytecode::Handle(function.bytecode());
+      var_descs = bytecode.GetLocalVarDescriptors();
+    } else {
+      var_descs = Object::empty_var_descriptors().raw();
+    }
+    code.set_var_descriptors(var_descs);
+    return;
+  }
   // In background compilation, parser can produce 'errors": bailouts
   // if state changed while compiling in background.
   CompilerState state(Thread::Current());
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
+    ParsedFunction* parsed_function = new ParsedFunction(
+        Thread::Current(), Function::ZoneHandle(function.raw()));
     ZoneGrowableArray<const ICData*>* ic_data_array =
         new ZoneGrowableArray<const ICData*>();
     ZoneGrowableArray<intptr_t>* context_level_array =
diff --git a/runtime/vm/compiler/offsets_extractor.cc b/runtime/vm/compiler/offsets_extractor.cc
new file mode 100644
index 0000000..ec0c866
--- /dev/null
+++ b/runtime/vm/compiler/offsets_extractor.cc
@@ -0,0 +1,103 @@
+// Copyright (c) 2019, 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 <iostream>
+
+#include "vm/compiler/runtime_api.h"
+#include "vm/compiler/runtime_offsets_list.h"
+#include "vm/dart_entry.h"
+#include "vm/longjump.h"
+#include "vm/native_arguments.h"
+#include "vm/native_entry.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+#include "vm/runtime_entry.h"
+#include "vm/symbols.h"
+#include "vm/timeline.h"
+
+#if defined(TARGET_ARCH_ARM)
+#define ARCH_DEF "defined(TARGET_ARCH_ARM)"
+#elif defined(TARGET_ARCH_X64)
+#define ARCH_DEF "defined(TARGET_ARCH_X64)"
+#elif defined(TARGET_ARCH_IA32)
+#define ARCH_DEF "defined(TARGET_ARCH_IA32)"
+#elif defined(TARGET_ARCH_ARM64)
+#define ARCH_DEF "defined(TARGET_ARCH_ARM64)"
+#elif defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)
+#define ARCH_DEF "defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)"
+#elif defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)
+#define ARCH_DEF "defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)"
+#else
+#error Unknown architecture
+#endif
+
+namespace dart {
+
+void Assert::Fail(const char* format, ...) {
+  abort();
+}
+
+class OffsetsExtractor : public AllStatic {
+ public:
+  static void DumpOffsets() {
+#define PRINT_FIELD_OFFSET(Class, Name)                                        \
+  std::cout << "static constexpr dart::word " #Class "_" #Name " = "           \
+            << Class::Name() << ";\n";
+
+#define PRINT_ARRAY_LAYOUT(Class, Name)                                        \
+  std::cout << "static constexpr dart::word " #Class                           \
+               "_elements_start_offset = "                                     \
+            << Class::ArrayLayout::elements_start_offset() << ";\n";           \
+  std::cout << "static constexpr dart::word " #Class "_element_size = "        \
+            << Class::ArrayLayout::kElementSize << ";\n";
+
+#define PRINT_ARRAY_STRUCTFIELD_OFFSET(Class, Name, ElementOffsetName,         \
+                                       FieldOffset)
+
+#define PRINT_SIZEOF(Class, Name, What)                                        \
+  std::cout << "static constexpr dart::word " #Class "_" #Name " = "           \
+            << sizeof(What) << ";\n";
+
+#define PRINT_RANGE(Class, Name, Type, First, Last, Filter)                    \
+  {                                                                            \
+    auto filter = Filter;                                                      \
+    bool comma = false;                                                        \
+    std::cout << "static dart::word " #Class "_" #Name "[] = {";               \
+    for (intptr_t i = static_cast<intptr_t>(First);                            \
+         i <= static_cast<intptr_t>(Last); i++) {                              \
+      auto v = static_cast<Type>(i);                                           \
+      std::cout << (comma ? ", " : "") << (filter(v) ? Class::Name(v) : -1);   \
+      comma = true;                                                            \
+    }                                                                          \
+    std::cout << "};\n";                                                       \
+  }
+
+#define PRINT_CONSTANT(Class, Name)                                            \
+  std::cout << "static constexpr dart::word " #Class "_" #Name " = "           \
+            << Class::Name << ";\n";
+
+#define PRECOMP_NO_CHECK(Code) Code
+
+    OFFSETS_LIST(PRINT_FIELD_OFFSET, PRINT_ARRAY_LAYOUT,
+                 PRINT_ARRAY_STRUCTFIELD_OFFSET, PRINT_SIZEOF, PRINT_RANGE,
+                 PRINT_CONSTANT, PRECOMP_NO_CHECK)
+
+#undef PRINT_FIELD_OFFSET
+#undef PRINT_ARRAY_LAYOUT
+#undef PRINT_ARRAY_STRUCTFIELD_OFFSET
+#undef PRINT_SIZEOF
+#undef PRINT_RANGE
+#undef PRINT_CONSTANT
+#undef PRECOMP_NO_CHECK
+  }
+};
+
+}  // namespace dart
+
+int main(int argc, char* argv[]) {
+  std::cout << "#if " << ARCH_DEF << std::endl;
+  dart::OffsetsExtractor::DumpOffsets();
+  std::cout << "#endif  // " << ARCH_DEF << std::endl;
+  return 0;
+}
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 6fc48f4..ffd7255 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -42,6 +42,7 @@
   V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 0x38a80b0d)              \
   V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 0x40052c4e)          \
   V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 0x07b89f54)              \
+  V(ByteData, ., ByteDataFactory, 0x0)                                         \
   V(_ByteDataView, get:offsetInBytes, ByteDataViewOffsetInBytes, 0x0)          \
   V(_ByteDataView, get:_typedData, ByteDataViewTypedData, 0x0)                 \
   V(_TypedListView, get:offsetInBytes, TypedDataViewOffsetInBytes, 0x0)        \
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 758e065..c5a4a53 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -500,6 +500,7 @@
   V(Thread, top_resource_offset)                                               \
   V(Thread, vm_tag_offset)                                                     \
   V(Thread, safepoint_state_offset)                                            \
+  V(Thread, callback_code_offset)                                              \
   V(TimelineStream, enabled_offset)                                            \
   V(TwoByteString, data_offset)                                                \
   V(Type, arguments_offset)                                                    \
@@ -582,6 +583,10 @@
 word Thread::array_write_barrier_entry_point_offset() {
   return dart::Thread::array_write_barrier_entry_point_offset();
 }
+
+word Thread::verify_callback_isolate_entry_point_offset() {
+  return dart::Thread::verify_callback_entry_offset();
+}
 #endif  // !defined(TARGET_ARCH_DBC)
 
 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
@@ -723,7 +728,8 @@
 }
 #endif  // !defined(PRODUCT)
 
-const word ClassTable::kSizeOfClassPairLog2 = dart::kSizeOfClassPairLog2;
+const word ClassTable::kSizeOfClassPairLog2 =
+    dart::ClassTable::kSizeOfClassPairLog2;
 
 const intptr_t Instructions::kPolymorphicEntryOffset =
     dart::Instructions::kPolymorphicEntryOffset;
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 29ff5ba..24ce301 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -572,6 +572,7 @@
   static word write_barrier_wrappers_thread_offset(intptr_t regno);
   static word array_write_barrier_entry_point_offset();
   static word write_barrier_entry_point_offset();
+  static word verify_callback_isolate_entry_point_offset();
   static word vm_tag_offset();
   static uword vm_tag_compiled_id();
 
@@ -583,6 +584,8 @@
   static uword native_execution_state();
   static uword generated_execution_state();
 
+  static word callback_code_offset();
+
 #if !defined(TARGET_ARCH_DBC)
   static word write_barrier_code_offset();
   static word array_write_barrier_code_offset();
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
new file mode 100644
index 0000000..4540195
--- /dev/null
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -0,0 +1,1343 @@
+// Copyright (c) 2019, 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_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_
+#define RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_
+
+#include "platform/globals.h"
+
+// The constants below correspond to the macros in runtime_offsets_list.h.
+
+// This file was generated by run_offsets_extractor.sh. It's checked in, rather
+// than being generated as part of the build, because simarm_x64 needs 32-bit
+// arm offsets, but is built on a 64-bit machine and offsets_extractor only
+// extracts offsets for the host architecture. This file needs to be regenerated
+// when the offsets change, which is usually detected by CheckOffsets() in
+// dart.cc.
+
+#if defined(TARGET_ARCH_ARM)
+static constexpr dart::word ObjectPool_elements_start_offset = 8;
+static constexpr dart::word ObjectPool_element_size = 4;
+static constexpr dart::word Array_kMaxElements = 268435455;
+static constexpr dart::word Array_kMaxNewSpaceElements = 65533;
+static constexpr dart::word ClassTable_kSizeOfClassPairLog2 = 3;
+static constexpr dart::word Instructions_kMonomorphicEntryOffset = 20;
+static constexpr dart::word Instructions_kPolymorphicEntryOffset = 0;
+static constexpr dart::word HeapPage_kBytesPerCardLog2 = 9;
+static constexpr dart::word NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::word String_kMaxElements = 536870911;
+static constexpr dart::word SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::word SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::word SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::word SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::word SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::word AbstractType_type_test_stub_entry_point_offset = 4;
+static constexpr dart::word ArgumentsDescriptor_count_offset = 16;
+static constexpr dart::word ArgumentsDescriptor_first_named_entry_offset = 24;
+static constexpr dart::word ArgumentsDescriptor_named_entry_size = 8;
+static constexpr dart::word ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::word ArgumentsDescriptor_position_offset = 4;
+static constexpr dart::word ArgumentsDescriptor_positional_count_offset = 20;
+static constexpr dart::word ArgumentsDescriptor_type_args_len_offset = 12;
+static constexpr dart::word Array_data_offset = 12;
+static constexpr dart::word Array_length_offset = 8;
+static constexpr dart::word Array_tags_offset = 0;
+static constexpr dart::word Array_type_arguments_offset = 4;
+static constexpr dart::word Class_declaration_type_offset = 56;
+static constexpr dart::word Class_num_type_arguments_offset = 102;
+static constexpr dart::word Class_super_type_offset = 44;
+static constexpr dart::word Class_type_arguments_field_offset_in_words_offset =
+    92;
+static constexpr dart::word ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::word ClassHeapStats_allocated_since_gc_new_space_offset =
+    48;
+static constexpr dart::word
+    ClassHeapStats_allocated_size_since_gc_new_space_offset = 52;
+static constexpr dart::word ClassHeapStats_state_offset = 160;
+static constexpr dart::word ClassTable_table_offset = 8;
+static constexpr dart::word Closure_context_offset = 20;
+static constexpr dart::word Closure_delayed_type_arguments_offset = 12;
+static constexpr dart::word Closure_function_offset = 16;
+static constexpr dart::word Closure_function_type_arguments_offset = 8;
+static constexpr dart::word Closure_hash_offset = 24;
+static constexpr dart::word Closure_instantiator_type_arguments_offset = 4;
+static constexpr dart::word Code_object_pool_offset = 20;
+static constexpr dart::word Code_saved_instructions_offset = 24;
+static constexpr dart::word Code_owner_offset = 28;
+static constexpr dart::word Context_num_variables_offset = 4;
+static constexpr dart::word Context_parent_offset = 8;
+static constexpr dart::word Double_value_offset = 8;
+static constexpr dart::word ExternalOneByteString_external_data_offset = 12;
+static constexpr dart::word ExternalTwoByteString_external_data_offset = 12;
+static constexpr dart::word Float32x4_value_offset = 8;
+static constexpr dart::word Float64x2_value_offset = 8;
+static constexpr dart::word Field_guarded_cid_offset = 48;
+static constexpr dart::word Field_guarded_list_length_in_object_offset_offset =
+    56;
+static constexpr dart::word Field_guarded_list_length_offset = 28;
+static constexpr dart::word Field_is_nullable_offset = 50;
+static constexpr dart::word Field_static_value_offset = 16;
+static constexpr dart::word Field_kind_bits_offset = 58;
+static constexpr dart::word Function_code_offset = 44;
+static constexpr dart::word Function_entry_point_offset = 4;
+static constexpr dart::word Function_unchecked_entry_point_offset = 8;
+static constexpr dart::word Function_usage_counter_offset = 76;
+static constexpr dart::word GrowableObjectArray_data_offset = 12;
+static constexpr dart::word GrowableObjectArray_length_offset = 8;
+static constexpr dart::word GrowableObjectArray_type_arguments_offset = 4;
+static constexpr dart::word HeapPage_card_table_offset = 20;
+static constexpr dart::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::word ICData_arguments_descriptor_offset = 12;
+static constexpr dart::word ICData_entries_offset = 4;
+static constexpr dart::word ICData_owner_offset = 20;
+static constexpr dart::word ICData_state_bits_offset = 28;
+static constexpr dart::word ICData_receivers_static_type_offset = 16;
+static constexpr dart::word Isolate_class_table_offset = 24;
+static constexpr dart::word Isolate_current_tag_offset = 8;
+static constexpr dart::word Isolate_default_tag_offset = 12;
+static constexpr dart::word Isolate_ic_miss_code_offset = 16;
+static constexpr dart::word Isolate_object_store_offset = 20;
+static constexpr dart::word Isolate_single_step_offset = 44;
+static constexpr dart::word Isolate_user_tag_offset = 4;
+static constexpr dart::word LinkedHashMap_data_offset = 16;
+static constexpr dart::word LinkedHashMap_deleted_keys_offset = 24;
+static constexpr dart::word LinkedHashMap_hash_mask_offset = 12;
+static constexpr dart::word LinkedHashMap_index_offset = 8;
+static constexpr dart::word LinkedHashMap_used_data_offset = 20;
+static constexpr dart::word MarkingStackBlock_pointers_offset = 8;
+static constexpr dart::word MarkingStackBlock_top_offset = 4;
+static constexpr dart::word MegamorphicCache_arguments_descriptor_offset = 16;
+static constexpr dart::word MegamorphicCache_buckets_offset = 4;
+static constexpr dart::word MegamorphicCache_mask_offset = 8;
+static constexpr dart::word Mint_value_offset = 8;
+static constexpr dart::word NativeArguments_argc_tag_offset = 4;
+static constexpr dart::word NativeArguments_argv_offset = 8;
+static constexpr dart::word NativeArguments_retval_offset = 12;
+static constexpr dart::word NativeArguments_thread_offset = 0;
+static constexpr dart::word ObjectStore_double_type_offset = 64;
+static constexpr dart::word ObjectStore_int_type_offset = 32;
+static constexpr dart::word ObjectStore_string_type_offset = 80;
+static constexpr dart::word OneByteString_data_offset = 12;
+static constexpr dart::word Pointer_c_memory_address_offset = 8;
+static constexpr dart::word SingleTargetCache_entry_point_offset = 8;
+static constexpr dart::word SingleTargetCache_lower_limit_offset = 12;
+static constexpr dart::word SingleTargetCache_target_offset = 4;
+static constexpr dart::word SingleTargetCache_upper_limit_offset = 14;
+static constexpr dart::word StoreBufferBlock_pointers_offset = 8;
+static constexpr dart::word StoreBufferBlock_top_offset = 4;
+static constexpr dart::word String_hash_offset = 8;
+static constexpr dart::word String_length_offset = 4;
+static constexpr dart::word SubtypeTestCache_cache_offset = 4;
+static constexpr dart::word Thread_AllocateArray_entry_point_offset = 284;
+static constexpr dart::word Thread_active_exception_offset = 612;
+static constexpr dart::word Thread_active_stacktrace_offset = 616;
+static constexpr dart::word Thread_array_write_barrier_code_offset = 112;
+static constexpr dart::word Thread_array_write_barrier_entry_point_offset = 196;
+static constexpr dart::word Thread_async_stack_trace_offset = 84;
+static constexpr dart::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 244;
+static constexpr dart::word Thread_bool_false_offset = 104;
+static constexpr dart::word Thread_bool_true_offset = 100;
+static constexpr dart::word Thread_call_to_runtime_entry_point_offset = 200;
+static constexpr dart::word Thread_call_to_runtime_stub_offset = 132;
+static constexpr dart::word Thread_dart_stream_offset = 644;
+static constexpr dart::word Thread_deoptimize_entry_offset = 232;
+static constexpr dart::word Thread_deoptimize_stub_offset = 164;
+static constexpr dart::word Thread_double_abs_address_offset = 264;
+static constexpr dart::word Thread_double_negate_address_offset = 260;
+static constexpr dart::word Thread_end_offset = 60;
+static constexpr dart::word Thread_enter_safepoint_stub_offset = 184;
+static constexpr dart::word Thread_execution_state_offset = 628;
+static constexpr dart::word Thread_exit_safepoint_stub_offset = 188;
+static constexpr dart::word Thread_fix_allocation_stub_code_offset = 120;
+static constexpr dart::word Thread_fix_callers_target_code_offset = 116;
+static constexpr dart::word Thread_float_absolute_address_offset = 276;
+static constexpr dart::word Thread_float_negate_address_offset = 272;
+static constexpr dart::word Thread_float_not_address_offset = 268;
+static constexpr dart::word Thread_float_zerow_address_offset = 280;
+static constexpr dart::word Thread_global_object_pool_offset = 620;
+static constexpr dart::word Thread_ic_lookup_through_code_stub_offset = 156;
+static constexpr dart::word Thread_interpret_call_entry_point_offset = 248;
+static constexpr dart::word Thread_invoke_dart_code_from_bytecode_stub_offset =
+    128;
+static constexpr dart::word Thread_invoke_dart_code_stub_offset = 124;
+static constexpr dart::word Thread_isolate_offset = 48;
+static constexpr dart::word Thread_lazy_deopt_from_return_stub_offset = 168;
+static constexpr dart::word Thread_lazy_deopt_from_throw_stub_offset = 172;
+static constexpr dart::word Thread_lazy_specialize_type_test_stub_offset = 180;
+static constexpr dart::word Thread_marking_stack_block_offset = 72;
+static constexpr dart::word Thread_megamorphic_call_checked_entry_offset = 220;
+static constexpr dart::word Thread_monomorphic_miss_entry_offset = 224;
+static constexpr dart::word Thread_monomorphic_miss_stub_offset = 152;
+static constexpr dart::word Thread_no_scope_native_wrapper_entry_point_offset =
+    240;
+static constexpr dart::word
+    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 208;
+static constexpr dart::word Thread_null_error_shared_with_fpu_regs_stub_offset =
+    140;
+static constexpr dart::word
+    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 204;
+static constexpr dart::word
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 136;
+static constexpr dart::word Thread_object_null_offset = 96;
+static constexpr dart::word Thread_predefined_symbols_address_offset = 252;
+static constexpr dart::word Thread_resume_pc_offset = 624;
+static constexpr dart::word Thread_safepoint_state_offset = 632;
+static constexpr dart::word Thread_slow_type_test_stub_offset = 176;
+static constexpr dart::word Thread_stack_limit_offset = 36;
+static constexpr dart::word Thread_stack_overflow_flags_offset = 40;
+static constexpr dart::word
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 216;
+static constexpr dart::word
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 148;
+static constexpr dart::word
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 212;
+static constexpr dart::word
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 144;
+static constexpr dart::word Thread_store_buffer_block_offset = 68;
+static constexpr dart::word Thread_top_exit_frame_info_offset = 64;
+static constexpr dart::word Thread_top_offset = 56;
+static constexpr dart::word Thread_top_resource_offset = 24;
+static constexpr dart::word Thread_unboxed_int64_runtime_arg_offset = 88;
+static constexpr dart::word Thread_vm_tag_offset = 80;
+static constexpr dart::word Thread_write_barrier_code_offset = 108;
+static constexpr dart::word Thread_write_barrier_entry_point_offset = 192;
+static constexpr dart::word Thread_write_barrier_mask_offset = 44;
+static constexpr dart::word Thread_verify_callback_entry_offset = 236;
+static constexpr dart::word Thread_callback_code_offset = 636;
+static constexpr dart::word TimelineStream_enabled_offset = 8;
+static constexpr dart::word TwoByteString_data_offset = 12;
+static constexpr dart::word Type_arguments_offset = 16;
+static constexpr dart::word Type_hash_offset = 20;
+static constexpr dart::word Type_signature_offset = 24;
+static constexpr dart::word Type_type_class_id_offset = 12;
+static constexpr dart::word Type_type_state_offset = 32;
+static constexpr dart::word TypeArguments_instantiations_offset = 4;
+static constexpr dart::word TypeRef_type_offset = 12;
+static constexpr dart::word TypedDataBase_data_field_offset = 4;
+static constexpr dart::word TypedDataBase_length_offset = 8;
+static constexpr dart::word TypedDataView_data_offset = 12;
+static constexpr dart::word TypedDataView_offset_in_bytes_offset = 16;
+static constexpr dart::word TypedData_data_offset = 12;
+static constexpr dart::word UserTag_tag_offset = 8;
+static constexpr dart::word Array_elements_start_offset = 12;
+static constexpr dart::word Array_element_size = 4;
+static constexpr dart::word TypeArguments_elements_start_offset = 16;
+static constexpr dart::word TypeArguments_element_size = 4;
+static constexpr dart::word ClassTable_elements_start_offset = 0;
+static constexpr dart::word ClassTable_element_size = 168;
+static constexpr dart::word ClassTable_class_heap_stats_table_offset = 16;
+static dart::word Code_entry_point_offset[] = {4, 12, 8, 16};
+static dart::word Code_function_entry_point_offset[] = {4, 8};
+static dart::word Thread_write_barrier_wrappers_thread_offset[] = {
+    576, 580, 584, 588, 592, -1, 596, 600, 604, 608, -1, -1, -1, -1, -1, -1};
+static constexpr dart::word Array_header_size = 12;
+static constexpr dart::word Context_header_size = 12;
+static constexpr dart::word Double_InstanceSize = 16;
+static constexpr dart::word Float32x4_InstanceSize = 24;
+static constexpr dart::word Float64x2_InstanceSize = 24;
+static constexpr dart::word Instructions_UnalignedHeaderSize = 16;
+static constexpr dart::word Int32x4_InstanceSize = 24;
+static constexpr dart::word Mint_InstanceSize = 16;
+static constexpr dart::word NativeArguments_StructSize = 16;
+static constexpr dart::word String_InstanceSize = 12;
+static constexpr dart::word TypedData_InstanceSize = 12;
+#endif  // defined(TARGET_ARCH_ARM)
+
+#if defined(TARGET_ARCH_X64)
+static constexpr dart::word ObjectPool_elements_start_offset = 16;
+static constexpr dart::word ObjectPool_element_size = 8;
+static constexpr dart::word Array_kMaxElements = 576460752303423487;
+static constexpr dart::word Array_kMaxNewSpaceElements = 32765;
+static constexpr dart::word ClassTable_kSizeOfClassPairLog2 = 4;
+static constexpr dart::word Instructions_kMonomorphicEntryOffset = 32;
+static constexpr dart::word Instructions_kPolymorphicEntryOffset = 8;
+static constexpr dart::word HeapPage_kBytesPerCardLog2 = 10;
+static constexpr dart::word NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::word String_kMaxElements = 2305843009213693951;
+static constexpr dart::word SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::word SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::word SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::word SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::word SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::word AbstractType_type_test_stub_entry_point_offset = 8;
+static constexpr dart::word ArgumentsDescriptor_count_offset = 32;
+static constexpr dart::word ArgumentsDescriptor_first_named_entry_offset = 48;
+static constexpr dart::word ArgumentsDescriptor_named_entry_size = 16;
+static constexpr dart::word ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::word ArgumentsDescriptor_position_offset = 8;
+static constexpr dart::word ArgumentsDescriptor_positional_count_offset = 40;
+static constexpr dart::word ArgumentsDescriptor_type_args_len_offset = 24;
+static constexpr dart::word Array_data_offset = 24;
+static constexpr dart::word Array_length_offset = 16;
+static constexpr dart::word Array_tags_offset = 0;
+static constexpr dart::word Array_type_arguments_offset = 8;
+static constexpr dart::word Class_declaration_type_offset = 112;
+static constexpr dart::word Class_num_type_arguments_offset = 186;
+static constexpr dart::word Class_super_type_offset = 88;
+static constexpr dart::word Class_type_arguments_field_offset_in_words_offset =
+    176;
+static constexpr dart::word ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::word ClassHeapStats_allocated_since_gc_new_space_offset =
+    96;
+static constexpr dart::word
+    ClassHeapStats_allocated_size_since_gc_new_space_offset = 104;
+static constexpr dart::word ClassHeapStats_state_offset = 272;
+static constexpr dart::word ClassTable_table_offset = 16;
+static constexpr dart::word Closure_context_offset = 40;
+static constexpr dart::word Closure_delayed_type_arguments_offset = 24;
+static constexpr dart::word Closure_function_offset = 32;
+static constexpr dart::word Closure_function_type_arguments_offset = 16;
+static constexpr dart::word Closure_hash_offset = 48;
+static constexpr dart::word Closure_instantiator_type_arguments_offset = 8;
+static constexpr dart::word Code_object_pool_offset = 40;
+static constexpr dart::word Code_saved_instructions_offset = 48;
+static constexpr dart::word Code_owner_offset = 56;
+static constexpr dart::word Context_num_variables_offset = 8;
+static constexpr dart::word Context_parent_offset = 16;
+static constexpr dart::word Double_value_offset = 8;
+static constexpr dart::word ExternalOneByteString_external_data_offset = 16;
+static constexpr dart::word ExternalTwoByteString_external_data_offset = 16;
+static constexpr dart::word Float32x4_value_offset = 8;
+static constexpr dart::word Float64x2_value_offset = 8;
+static constexpr dart::word Field_guarded_cid_offset = 88;
+static constexpr dart::word Field_guarded_list_length_in_object_offset_offset =
+    96;
+static constexpr dart::word Field_guarded_list_length_offset = 56;
+static constexpr dart::word Field_is_nullable_offset = 90;
+static constexpr dart::word Field_static_value_offset = 32;
+static constexpr dart::word Field_kind_bits_offset = 98;
+static constexpr dart::word Function_code_offset = 88;
+static constexpr dart::word Function_entry_point_offset = 8;
+static constexpr dart::word Function_unchecked_entry_point_offset = 16;
+static constexpr dart::word Function_usage_counter_offset = 132;
+static constexpr dart::word GrowableObjectArray_data_offset = 24;
+static constexpr dart::word GrowableObjectArray_length_offset = 16;
+static constexpr dart::word GrowableObjectArray_type_arguments_offset = 8;
+static constexpr dart::word HeapPage_card_table_offset = 40;
+static constexpr dart::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::word ICData_arguments_descriptor_offset = 24;
+static constexpr dart::word ICData_entries_offset = 8;
+static constexpr dart::word ICData_owner_offset = 40;
+static constexpr dart::word ICData_state_bits_offset = 52;
+static constexpr dart::word ICData_receivers_static_type_offset = 32;
+static constexpr dart::word Isolate_class_table_offset = 48;
+static constexpr dart::word Isolate_current_tag_offset = 16;
+static constexpr dart::word Isolate_default_tag_offset = 24;
+static constexpr dart::word Isolate_ic_miss_code_offset = 32;
+static constexpr dart::word Isolate_object_store_offset = 40;
+static constexpr dart::word Isolate_single_step_offset = 88;
+static constexpr dart::word Isolate_user_tag_offset = 8;
+static constexpr dart::word LinkedHashMap_data_offset = 32;
+static constexpr dart::word LinkedHashMap_deleted_keys_offset = 48;
+static constexpr dart::word LinkedHashMap_hash_mask_offset = 24;
+static constexpr dart::word LinkedHashMap_index_offset = 16;
+static constexpr dart::word LinkedHashMap_used_data_offset = 40;
+static constexpr dart::word MarkingStackBlock_pointers_offset = 16;
+static constexpr dart::word MarkingStackBlock_top_offset = 8;
+static constexpr dart::word MegamorphicCache_arguments_descriptor_offset = 32;
+static constexpr dart::word MegamorphicCache_buckets_offset = 8;
+static constexpr dart::word MegamorphicCache_mask_offset = 16;
+static constexpr dart::word Mint_value_offset = 8;
+static constexpr dart::word NativeArguments_argc_tag_offset = 8;
+static constexpr dart::word NativeArguments_argv_offset = 16;
+static constexpr dart::word NativeArguments_retval_offset = 24;
+static constexpr dart::word NativeArguments_thread_offset = 0;
+static constexpr dart::word ObjectStore_double_type_offset = 128;
+static constexpr dart::word ObjectStore_int_type_offset = 64;
+static constexpr dart::word ObjectStore_string_type_offset = 160;
+static constexpr dart::word OneByteString_data_offset = 16;
+static constexpr dart::word Pointer_c_memory_address_offset = 16;
+static constexpr dart::word SingleTargetCache_entry_point_offset = 16;
+static constexpr dart::word SingleTargetCache_lower_limit_offset = 24;
+static constexpr dart::word SingleTargetCache_target_offset = 8;
+static constexpr dart::word SingleTargetCache_upper_limit_offset = 26;
+static constexpr dart::word StoreBufferBlock_pointers_offset = 16;
+static constexpr dart::word StoreBufferBlock_top_offset = 8;
+static constexpr dart::word String_hash_offset = 4;
+static constexpr dart::word String_length_offset = 8;
+static constexpr dart::word SubtypeTestCache_cache_offset = 8;
+static constexpr dart::word Thread_AllocateArray_entry_point_offset = 560;
+static constexpr dart::word Thread_active_exception_offset = 1232;
+static constexpr dart::word Thread_active_stacktrace_offset = 1240;
+static constexpr dart::word Thread_array_write_barrier_code_offset = 216;
+static constexpr dart::word Thread_array_write_barrier_entry_point_offset = 384;
+static constexpr dart::word Thread_async_stack_trace_offset = 168;
+static constexpr dart::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 480;
+static constexpr dart::word Thread_bool_false_offset = 200;
+static constexpr dart::word Thread_bool_true_offset = 192;
+static constexpr dart::word Thread_call_to_runtime_entry_point_offset = 392;
+static constexpr dart::word Thread_call_to_runtime_stub_offset = 256;
+static constexpr dart::word Thread_dart_stream_offset = 1296;
+static constexpr dart::word Thread_deoptimize_entry_offset = 456;
+static constexpr dart::word Thread_deoptimize_stub_offset = 320;
+static constexpr dart::word Thread_double_abs_address_offset = 520;
+static constexpr dart::word Thread_double_negate_address_offset = 512;
+static constexpr dart::word Thread_end_offset = 120;
+static constexpr dart::word Thread_enter_safepoint_stub_offset = 360;
+static constexpr dart::word Thread_execution_state_offset = 1264;
+static constexpr dart::word Thread_exit_safepoint_stub_offset = 368;
+static constexpr dart::word Thread_fix_allocation_stub_code_offset = 232;
+static constexpr dart::word Thread_fix_callers_target_code_offset = 224;
+static constexpr dart::word Thread_float_absolute_address_offset = 544;
+static constexpr dart::word Thread_float_negate_address_offset = 536;
+static constexpr dart::word Thread_float_not_address_offset = 528;
+static constexpr dart::word Thread_float_zerow_address_offset = 552;
+static constexpr dart::word Thread_global_object_pool_offset = 1248;
+static constexpr dart::word Thread_ic_lookup_through_code_stub_offset = 304;
+static constexpr dart::word Thread_interpret_call_entry_point_offset = 488;
+static constexpr dart::word Thread_invoke_dart_code_from_bytecode_stub_offset =
+    248;
+static constexpr dart::word Thread_invoke_dart_code_stub_offset = 240;
+static constexpr dart::word Thread_isolate_offset = 96;
+static constexpr dart::word Thread_lazy_deopt_from_return_stub_offset = 328;
+static constexpr dart::word Thread_lazy_deopt_from_throw_stub_offset = 336;
+static constexpr dart::word Thread_lazy_specialize_type_test_stub_offset = 352;
+static constexpr dart::word Thread_marking_stack_block_offset = 144;
+static constexpr dart::word Thread_megamorphic_call_checked_entry_offset = 432;
+static constexpr dart::word Thread_monomorphic_miss_entry_offset = 440;
+static constexpr dart::word Thread_monomorphic_miss_stub_offset = 296;
+static constexpr dart::word Thread_no_scope_native_wrapper_entry_point_offset =
+    472;
+static constexpr dart::word
+    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 408;
+static constexpr dart::word Thread_null_error_shared_with_fpu_regs_stub_offset =
+    272;
+static constexpr dart::word
+    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 400;
+static constexpr dart::word
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 264;
+static constexpr dart::word Thread_object_null_offset = 184;
+static constexpr dart::word Thread_predefined_symbols_address_offset = 496;
+static constexpr dart::word Thread_resume_pc_offset = 1256;
+static constexpr dart::word Thread_safepoint_state_offset = 1272;
+static constexpr dart::word Thread_slow_type_test_stub_offset = 344;
+static constexpr dart::word Thread_stack_limit_offset = 72;
+static constexpr dart::word Thread_stack_overflow_flags_offset = 80;
+static constexpr dart::word
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 424;
+static constexpr dart::word
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 288;
+static constexpr dart::word
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 416;
+static constexpr dart::word
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 280;
+static constexpr dart::word Thread_store_buffer_block_offset = 136;
+static constexpr dart::word Thread_top_exit_frame_info_offset = 128;
+static constexpr dart::word Thread_top_offset = 112;
+static constexpr dart::word Thread_top_resource_offset = 48;
+static constexpr dart::word Thread_unboxed_int64_runtime_arg_offset = 176;
+static constexpr dart::word Thread_vm_tag_offset = 160;
+static constexpr dart::word Thread_write_barrier_code_offset = 208;
+static constexpr dart::word Thread_write_barrier_entry_point_offset = 376;
+static constexpr dart::word Thread_write_barrier_mask_offset = 88;
+static constexpr dart::word Thread_verify_callback_entry_offset = 464;
+static constexpr dart::word Thread_callback_code_offset = 1280;
+static constexpr dart::word TimelineStream_enabled_offset = 16;
+static constexpr dart::word TwoByteString_data_offset = 16;
+static constexpr dart::word Type_arguments_offset = 32;
+static constexpr dart::word Type_hash_offset = 40;
+static constexpr dart::word Type_signature_offset = 48;
+static constexpr dart::word Type_type_class_id_offset = 24;
+static constexpr dart::word Type_type_state_offset = 60;
+static constexpr dart::word TypeArguments_instantiations_offset = 8;
+static constexpr dart::word TypeRef_type_offset = 24;
+static constexpr dart::word TypedDataBase_data_field_offset = 8;
+static constexpr dart::word TypedDataBase_length_offset = 16;
+static constexpr dart::word TypedDataView_data_offset = 24;
+static constexpr dart::word TypedDataView_offset_in_bytes_offset = 32;
+static constexpr dart::word TypedData_data_offset = 24;
+static constexpr dart::word UserTag_tag_offset = 16;
+static constexpr dart::word Array_elements_start_offset = 24;
+static constexpr dart::word Array_element_size = 8;
+static constexpr dart::word TypeArguments_elements_start_offset = 32;
+static constexpr dart::word TypeArguments_element_size = 8;
+static constexpr dart::word ClassTable_elements_start_offset = 0;
+static constexpr dart::word ClassTable_element_size = 288;
+static constexpr dart::word ClassTable_class_heap_stats_table_offset = 32;
+static dart::word Code_entry_point_offset[] = {8, 24, 16, 32};
+static dart::word Code_function_entry_point_offset[] = {8, 16};
+static dart::word Thread_write_barrier_wrappers_thread_offset[] = {
+    1144, 1152, 1160, 1168, -1,   -1,   1176, 1184,
+    1192, 1200, 1208, -1,   1216, 1224, -1,   -1};
+static constexpr dart::word Array_header_size = 24;
+static constexpr dart::word Context_header_size = 24;
+static constexpr dart::word Double_InstanceSize = 16;
+static constexpr dart::word Float32x4_InstanceSize = 24;
+static constexpr dart::word Float64x2_InstanceSize = 24;
+static constexpr dart::word Instructions_UnalignedHeaderSize = 24;
+static constexpr dart::word Int32x4_InstanceSize = 24;
+static constexpr dart::word Mint_InstanceSize = 16;
+static constexpr dart::word NativeArguments_StructSize = 32;
+static constexpr dart::word String_InstanceSize = 16;
+static constexpr dart::word TypedData_InstanceSize = 24;
+#endif  // defined(TARGET_ARCH_X64)
+
+#if defined(TARGET_ARCH_IA32)
+static constexpr dart::word ObjectPool_elements_start_offset = 8;
+static constexpr dart::word ObjectPool_element_size = 4;
+static constexpr dart::word Array_kMaxElements = 268435455;
+static constexpr dart::word Array_kMaxNewSpaceElements = 65533;
+static constexpr dart::word ClassTable_kSizeOfClassPairLog2 = 3;
+static constexpr dart::word Instructions_kMonomorphicEntryOffset = 0;
+static constexpr dart::word Instructions_kPolymorphicEntryOffset = 0;
+static constexpr dart::word HeapPage_kBytesPerCardLog2 = 9;
+static constexpr dart::word NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::word String_kMaxElements = 536870911;
+static constexpr dart::word SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::word SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::word SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::word SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::word SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::word AbstractType_type_test_stub_entry_point_offset = 4;
+static constexpr dart::word ArgumentsDescriptor_count_offset = 16;
+static constexpr dart::word ArgumentsDescriptor_first_named_entry_offset = 24;
+static constexpr dart::word ArgumentsDescriptor_named_entry_size = 8;
+static constexpr dart::word ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::word ArgumentsDescriptor_position_offset = 4;
+static constexpr dart::word ArgumentsDescriptor_positional_count_offset = 20;
+static constexpr dart::word ArgumentsDescriptor_type_args_len_offset = 12;
+static constexpr dart::word Array_data_offset = 12;
+static constexpr dart::word Array_length_offset = 8;
+static constexpr dart::word Array_tags_offset = 0;
+static constexpr dart::word Array_type_arguments_offset = 4;
+static constexpr dart::word Class_declaration_type_offset = 56;
+static constexpr dart::word Class_num_type_arguments_offset = 102;
+static constexpr dart::word Class_super_type_offset = 44;
+static constexpr dart::word Class_type_arguments_field_offset_in_words_offset =
+    92;
+static constexpr dart::word ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::word ClassHeapStats_allocated_since_gc_new_space_offset =
+    48;
+static constexpr dart::word
+    ClassHeapStats_allocated_size_since_gc_new_space_offset = 52;
+static constexpr dart::word ClassHeapStats_state_offset = 160;
+static constexpr dart::word ClassTable_table_offset = 8;
+static constexpr dart::word Closure_context_offset = 20;
+static constexpr dart::word Closure_delayed_type_arguments_offset = 12;
+static constexpr dart::word Closure_function_offset = 16;
+static constexpr dart::word Closure_function_type_arguments_offset = 8;
+static constexpr dart::word Closure_hash_offset = 24;
+static constexpr dart::word Closure_instantiator_type_arguments_offset = 4;
+static constexpr dart::word Code_object_pool_offset = 20;
+static constexpr dart::word Code_saved_instructions_offset = 24;
+static constexpr dart::word Code_owner_offset = 28;
+static constexpr dart::word Context_num_variables_offset = 4;
+static constexpr dart::word Context_parent_offset = 8;
+static constexpr dart::word Double_value_offset = 8;
+static constexpr dart::word ExternalOneByteString_external_data_offset = 12;
+static constexpr dart::word ExternalTwoByteString_external_data_offset = 12;
+static constexpr dart::word Float32x4_value_offset = 8;
+static constexpr dart::word Float64x2_value_offset = 8;
+static constexpr dart::word Field_guarded_cid_offset = 48;
+static constexpr dart::word Field_guarded_list_length_in_object_offset_offset =
+    56;
+static constexpr dart::word Field_guarded_list_length_offset = 28;
+static constexpr dart::word Field_is_nullable_offset = 50;
+static constexpr dart::word Field_static_value_offset = 16;
+static constexpr dart::word Field_kind_bits_offset = 58;
+static constexpr dart::word Function_code_offset = 44;
+static constexpr dart::word Function_entry_point_offset = 4;
+static constexpr dart::word Function_unchecked_entry_point_offset = 8;
+static constexpr dart::word Function_usage_counter_offset = 76;
+static constexpr dart::word GrowableObjectArray_data_offset = 12;
+static constexpr dart::word GrowableObjectArray_length_offset = 8;
+static constexpr dart::word GrowableObjectArray_type_arguments_offset = 4;
+static constexpr dart::word HeapPage_card_table_offset = 20;
+static constexpr dart::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::word ICData_arguments_descriptor_offset = 12;
+static constexpr dart::word ICData_entries_offset = 4;
+static constexpr dart::word ICData_owner_offset = 20;
+static constexpr dart::word ICData_state_bits_offset = 28;
+static constexpr dart::word ICData_receivers_static_type_offset = 16;
+static constexpr dart::word Isolate_class_table_offset = 24;
+static constexpr dart::word Isolate_current_tag_offset = 8;
+static constexpr dart::word Isolate_default_tag_offset = 12;
+static constexpr dart::word Isolate_ic_miss_code_offset = 16;
+static constexpr dart::word Isolate_object_store_offset = 20;
+static constexpr dart::word Isolate_single_step_offset = 44;
+static constexpr dart::word Isolate_user_tag_offset = 4;
+static constexpr dart::word LinkedHashMap_data_offset = 16;
+static constexpr dart::word LinkedHashMap_deleted_keys_offset = 24;
+static constexpr dart::word LinkedHashMap_hash_mask_offset = 12;
+static constexpr dart::word LinkedHashMap_index_offset = 8;
+static constexpr dart::word LinkedHashMap_used_data_offset = 20;
+static constexpr dart::word MarkingStackBlock_pointers_offset = 8;
+static constexpr dart::word MarkingStackBlock_top_offset = 4;
+static constexpr dart::word MegamorphicCache_arguments_descriptor_offset = 16;
+static constexpr dart::word MegamorphicCache_buckets_offset = 4;
+static constexpr dart::word MegamorphicCache_mask_offset = 8;
+static constexpr dart::word Mint_value_offset = 8;
+static constexpr dart::word NativeArguments_argc_tag_offset = 4;
+static constexpr dart::word NativeArguments_argv_offset = 8;
+static constexpr dart::word NativeArguments_retval_offset = 12;
+static constexpr dart::word NativeArguments_thread_offset = 0;
+static constexpr dart::word ObjectStore_double_type_offset = 64;
+static constexpr dart::word ObjectStore_int_type_offset = 32;
+static constexpr dart::word ObjectStore_string_type_offset = 80;
+static constexpr dart::word OneByteString_data_offset = 12;
+static constexpr dart::word Pointer_c_memory_address_offset = 8;
+static constexpr dart::word SingleTargetCache_entry_point_offset = 8;
+static constexpr dart::word SingleTargetCache_lower_limit_offset = 12;
+static constexpr dart::word SingleTargetCache_target_offset = 4;
+static constexpr dart::word SingleTargetCache_upper_limit_offset = 14;
+static constexpr dart::word StoreBufferBlock_pointers_offset = 8;
+static constexpr dart::word StoreBufferBlock_top_offset = 4;
+static constexpr dart::word String_hash_offset = 8;
+static constexpr dart::word String_length_offset = 4;
+static constexpr dart::word SubtypeTestCache_cache_offset = 4;
+static constexpr dart::word Thread_AllocateArray_entry_point_offset = 284;
+static constexpr dart::word Thread_active_exception_offset = 576;
+static constexpr dart::word Thread_active_stacktrace_offset = 580;
+static constexpr dart::word Thread_array_write_barrier_code_offset = 112;
+static constexpr dart::word Thread_array_write_barrier_entry_point_offset = 196;
+static constexpr dart::word Thread_async_stack_trace_offset = 84;
+static constexpr dart::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 244;
+static constexpr dart::word Thread_bool_false_offset = 104;
+static constexpr dart::word Thread_bool_true_offset = 100;
+static constexpr dart::word Thread_call_to_runtime_entry_point_offset = 200;
+static constexpr dart::word Thread_call_to_runtime_stub_offset = 132;
+static constexpr dart::word Thread_dart_stream_offset = 608;
+static constexpr dart::word Thread_deoptimize_entry_offset = 232;
+static constexpr dart::word Thread_deoptimize_stub_offset = 164;
+static constexpr dart::word Thread_double_abs_address_offset = 264;
+static constexpr dart::word Thread_double_negate_address_offset = 260;
+static constexpr dart::word Thread_end_offset = 60;
+static constexpr dart::word Thread_enter_safepoint_stub_offset = 184;
+static constexpr dart::word Thread_execution_state_offset = 592;
+static constexpr dart::word Thread_exit_safepoint_stub_offset = 188;
+static constexpr dart::word Thread_fix_allocation_stub_code_offset = 120;
+static constexpr dart::word Thread_fix_callers_target_code_offset = 116;
+static constexpr dart::word Thread_float_absolute_address_offset = 276;
+static constexpr dart::word Thread_float_negate_address_offset = 272;
+static constexpr dart::word Thread_float_not_address_offset = 268;
+static constexpr dart::word Thread_float_zerow_address_offset = 280;
+static constexpr dart::word Thread_global_object_pool_offset = 584;
+static constexpr dart::word Thread_ic_lookup_through_code_stub_offset = 156;
+static constexpr dart::word Thread_interpret_call_entry_point_offset = 248;
+static constexpr dart::word Thread_invoke_dart_code_from_bytecode_stub_offset =
+    128;
+static constexpr dart::word Thread_invoke_dart_code_stub_offset = 124;
+static constexpr dart::word Thread_isolate_offset = 48;
+static constexpr dart::word Thread_lazy_deopt_from_return_stub_offset = 168;
+static constexpr dart::word Thread_lazy_deopt_from_throw_stub_offset = 172;
+static constexpr dart::word Thread_lazy_specialize_type_test_stub_offset = 180;
+static constexpr dart::word Thread_marking_stack_block_offset = 72;
+static constexpr dart::word Thread_megamorphic_call_checked_entry_offset = 220;
+static constexpr dart::word Thread_monomorphic_miss_entry_offset = 224;
+static constexpr dart::word Thread_monomorphic_miss_stub_offset = 152;
+static constexpr dart::word Thread_no_scope_native_wrapper_entry_point_offset =
+    240;
+static constexpr dart::word
+    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 208;
+static constexpr dart::word Thread_null_error_shared_with_fpu_regs_stub_offset =
+    140;
+static constexpr dart::word
+    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 204;
+static constexpr dart::word
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 136;
+static constexpr dart::word Thread_object_null_offset = 96;
+static constexpr dart::word Thread_predefined_symbols_address_offset = 252;
+static constexpr dart::word Thread_resume_pc_offset = 588;
+static constexpr dart::word Thread_safepoint_state_offset = 596;
+static constexpr dart::word Thread_slow_type_test_stub_offset = 176;
+static constexpr dart::word Thread_stack_limit_offset = 36;
+static constexpr dart::word Thread_stack_overflow_flags_offset = 40;
+static constexpr dart::word
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 216;
+static constexpr dart::word
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 148;
+static constexpr dart::word
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 212;
+static constexpr dart::word
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 144;
+static constexpr dart::word Thread_store_buffer_block_offset = 68;
+static constexpr dart::word Thread_top_exit_frame_info_offset = 64;
+static constexpr dart::word Thread_top_offset = 56;
+static constexpr dart::word Thread_top_resource_offset = 24;
+static constexpr dart::word Thread_unboxed_int64_runtime_arg_offset = 88;
+static constexpr dart::word Thread_vm_tag_offset = 80;
+static constexpr dart::word Thread_write_barrier_code_offset = 108;
+static constexpr dart::word Thread_write_barrier_entry_point_offset = 192;
+static constexpr dart::word Thread_write_barrier_mask_offset = 44;
+static constexpr dart::word Thread_verify_callback_entry_offset = 236;
+static constexpr dart::word Thread_callback_code_offset = 600;
+static constexpr dart::word TimelineStream_enabled_offset = 8;
+static constexpr dart::word TwoByteString_data_offset = 12;
+static constexpr dart::word Type_arguments_offset = 16;
+static constexpr dart::word Type_hash_offset = 20;
+static constexpr dart::word Type_signature_offset = 24;
+static constexpr dart::word Type_type_class_id_offset = 12;
+static constexpr dart::word Type_type_state_offset = 32;
+static constexpr dart::word TypeArguments_instantiations_offset = 4;
+static constexpr dart::word TypeRef_type_offset = 12;
+static constexpr dart::word TypedDataBase_data_field_offset = 4;
+static constexpr dart::word TypedDataBase_length_offset = 8;
+static constexpr dart::word TypedDataView_data_offset = 12;
+static constexpr dart::word TypedDataView_offset_in_bytes_offset = 16;
+static constexpr dart::word TypedData_data_offset = 12;
+static constexpr dart::word UserTag_tag_offset = 8;
+static constexpr dart::word Array_elements_start_offset = 12;
+static constexpr dart::word Array_element_size = 4;
+static constexpr dart::word TypeArguments_elements_start_offset = 16;
+static constexpr dart::word TypeArguments_element_size = 4;
+static constexpr dart::word ClassTable_elements_start_offset = 0;
+static constexpr dart::word ClassTable_element_size = 168;
+static constexpr dart::word ClassTable_class_heap_stats_table_offset = 16;
+static dart::word Code_entry_point_offset[] = {4, 12, 8, 16};
+static dart::word Code_function_entry_point_offset[] = {4, 8};
+static constexpr dart::word Array_header_size = 12;
+static constexpr dart::word Context_header_size = 12;
+static constexpr dart::word Double_InstanceSize = 16;
+static constexpr dart::word Float32x4_InstanceSize = 24;
+static constexpr dart::word Float64x2_InstanceSize = 24;
+static constexpr dart::word Instructions_UnalignedHeaderSize = 16;
+static constexpr dart::word Int32x4_InstanceSize = 24;
+static constexpr dart::word Mint_InstanceSize = 16;
+static constexpr dart::word NativeArguments_StructSize = 16;
+static constexpr dart::word String_InstanceSize = 12;
+static constexpr dart::word TypedData_InstanceSize = 12;
+#endif  // defined(TARGET_ARCH_IA32)
+
+#if defined(TARGET_ARCH_ARM64)
+static constexpr dart::word ObjectPool_elements_start_offset = 16;
+static constexpr dart::word ObjectPool_element_size = 8;
+static constexpr dart::word Array_kMaxElements = 576460752303423487;
+static constexpr dart::word Array_kMaxNewSpaceElements = 32765;
+static constexpr dart::word ClassTable_kSizeOfClassPairLog2 = 4;
+static constexpr dart::word Instructions_kMonomorphicEntryOffset = 28;
+static constexpr dart::word Instructions_kPolymorphicEntryOffset = 8;
+static constexpr dart::word HeapPage_kBytesPerCardLog2 = 10;
+static constexpr dart::word NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::word String_kMaxElements = 2305843009213693951;
+static constexpr dart::word SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::word SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::word SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::word SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::word SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::word AbstractType_type_test_stub_entry_point_offset = 8;
+static constexpr dart::word ArgumentsDescriptor_count_offset = 32;
+static constexpr dart::word ArgumentsDescriptor_first_named_entry_offset = 48;
+static constexpr dart::word ArgumentsDescriptor_named_entry_size = 16;
+static constexpr dart::word ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::word ArgumentsDescriptor_position_offset = 8;
+static constexpr dart::word ArgumentsDescriptor_positional_count_offset = 40;
+static constexpr dart::word ArgumentsDescriptor_type_args_len_offset = 24;
+static constexpr dart::word Array_data_offset = 24;
+static constexpr dart::word Array_length_offset = 16;
+static constexpr dart::word Array_tags_offset = 0;
+static constexpr dart::word Array_type_arguments_offset = 8;
+static constexpr dart::word Class_declaration_type_offset = 112;
+static constexpr dart::word Class_num_type_arguments_offset = 186;
+static constexpr dart::word Class_super_type_offset = 88;
+static constexpr dart::word Class_type_arguments_field_offset_in_words_offset =
+    176;
+static constexpr dart::word ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::word ClassHeapStats_allocated_since_gc_new_space_offset =
+    96;
+static constexpr dart::word
+    ClassHeapStats_allocated_size_since_gc_new_space_offset = 104;
+static constexpr dart::word ClassHeapStats_state_offset = 272;
+static constexpr dart::word ClassTable_table_offset = 16;
+static constexpr dart::word Closure_context_offset = 40;
+static constexpr dart::word Closure_delayed_type_arguments_offset = 24;
+static constexpr dart::word Closure_function_offset = 32;
+static constexpr dart::word Closure_function_type_arguments_offset = 16;
+static constexpr dart::word Closure_hash_offset = 48;
+static constexpr dart::word Closure_instantiator_type_arguments_offset = 8;
+static constexpr dart::word Code_object_pool_offset = 40;
+static constexpr dart::word Code_saved_instructions_offset = 48;
+static constexpr dart::word Code_owner_offset = 56;
+static constexpr dart::word Context_num_variables_offset = 8;
+static constexpr dart::word Context_parent_offset = 16;
+static constexpr dart::word Double_value_offset = 8;
+static constexpr dart::word ExternalOneByteString_external_data_offset = 16;
+static constexpr dart::word ExternalTwoByteString_external_data_offset = 16;
+static constexpr dart::word Float32x4_value_offset = 8;
+static constexpr dart::word Float64x2_value_offset = 8;
+static constexpr dart::word Field_guarded_cid_offset = 88;
+static constexpr dart::word Field_guarded_list_length_in_object_offset_offset =
+    96;
+static constexpr dart::word Field_guarded_list_length_offset = 56;
+static constexpr dart::word Field_is_nullable_offset = 90;
+static constexpr dart::word Field_static_value_offset = 32;
+static constexpr dart::word Field_kind_bits_offset = 98;
+static constexpr dart::word Function_code_offset = 88;
+static constexpr dart::word Function_entry_point_offset = 8;
+static constexpr dart::word Function_unchecked_entry_point_offset = 16;
+static constexpr dart::word Function_usage_counter_offset = 132;
+static constexpr dart::word GrowableObjectArray_data_offset = 24;
+static constexpr dart::word GrowableObjectArray_length_offset = 16;
+static constexpr dart::word GrowableObjectArray_type_arguments_offset = 8;
+static constexpr dart::word HeapPage_card_table_offset = 40;
+static constexpr dart::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::word ICData_arguments_descriptor_offset = 24;
+static constexpr dart::word ICData_entries_offset = 8;
+static constexpr dart::word ICData_owner_offset = 40;
+static constexpr dart::word ICData_state_bits_offset = 52;
+static constexpr dart::word ICData_receivers_static_type_offset = 32;
+static constexpr dart::word Isolate_class_table_offset = 48;
+static constexpr dart::word Isolate_current_tag_offset = 16;
+static constexpr dart::word Isolate_default_tag_offset = 24;
+static constexpr dart::word Isolate_ic_miss_code_offset = 32;
+static constexpr dart::word Isolate_object_store_offset = 40;
+static constexpr dart::word Isolate_single_step_offset = 88;
+static constexpr dart::word Isolate_user_tag_offset = 8;
+static constexpr dart::word LinkedHashMap_data_offset = 32;
+static constexpr dart::word LinkedHashMap_deleted_keys_offset = 48;
+static constexpr dart::word LinkedHashMap_hash_mask_offset = 24;
+static constexpr dart::word LinkedHashMap_index_offset = 16;
+static constexpr dart::word LinkedHashMap_used_data_offset = 40;
+static constexpr dart::word MarkingStackBlock_pointers_offset = 16;
+static constexpr dart::word MarkingStackBlock_top_offset = 8;
+static constexpr dart::word MegamorphicCache_arguments_descriptor_offset = 32;
+static constexpr dart::word MegamorphicCache_buckets_offset = 8;
+static constexpr dart::word MegamorphicCache_mask_offset = 16;
+static constexpr dart::word Mint_value_offset = 8;
+static constexpr dart::word NativeArguments_argc_tag_offset = 8;
+static constexpr dart::word NativeArguments_argv_offset = 16;
+static constexpr dart::word NativeArguments_retval_offset = 24;
+static constexpr dart::word NativeArguments_thread_offset = 0;
+static constexpr dart::word ObjectStore_double_type_offset = 128;
+static constexpr dart::word ObjectStore_int_type_offset = 64;
+static constexpr dart::word ObjectStore_string_type_offset = 160;
+static constexpr dart::word OneByteString_data_offset = 16;
+static constexpr dart::word Pointer_c_memory_address_offset = 16;
+static constexpr dart::word SingleTargetCache_entry_point_offset = 16;
+static constexpr dart::word SingleTargetCache_lower_limit_offset = 24;
+static constexpr dart::word SingleTargetCache_target_offset = 8;
+static constexpr dart::word SingleTargetCache_upper_limit_offset = 26;
+static constexpr dart::word StoreBufferBlock_pointers_offset = 16;
+static constexpr dart::word StoreBufferBlock_top_offset = 8;
+static constexpr dart::word String_hash_offset = 4;
+static constexpr dart::word String_length_offset = 8;
+static constexpr dart::word SubtypeTestCache_cache_offset = 8;
+static constexpr dart::word Thread_AllocateArray_entry_point_offset = 560;
+static constexpr dart::word Thread_active_exception_offset = 1320;
+static constexpr dart::word Thread_active_stacktrace_offset = 1328;
+static constexpr dart::word Thread_array_write_barrier_code_offset = 216;
+static constexpr dart::word Thread_array_write_barrier_entry_point_offset = 384;
+static constexpr dart::word Thread_async_stack_trace_offset = 168;
+static constexpr dart::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 480;
+static constexpr dart::word Thread_bool_false_offset = 200;
+static constexpr dart::word Thread_bool_true_offset = 192;
+static constexpr dart::word Thread_call_to_runtime_entry_point_offset = 392;
+static constexpr dart::word Thread_call_to_runtime_stub_offset = 256;
+static constexpr dart::word Thread_dart_stream_offset = 1384;
+static constexpr dart::word Thread_deoptimize_entry_offset = 456;
+static constexpr dart::word Thread_deoptimize_stub_offset = 320;
+static constexpr dart::word Thread_double_abs_address_offset = 520;
+static constexpr dart::word Thread_double_negate_address_offset = 512;
+static constexpr dart::word Thread_end_offset = 120;
+static constexpr dart::word Thread_enter_safepoint_stub_offset = 360;
+static constexpr dart::word Thread_execution_state_offset = 1352;
+static constexpr dart::word Thread_exit_safepoint_stub_offset = 368;
+static constexpr dart::word Thread_fix_allocation_stub_code_offset = 232;
+static constexpr dart::word Thread_fix_callers_target_code_offset = 224;
+static constexpr dart::word Thread_float_absolute_address_offset = 544;
+static constexpr dart::word Thread_float_negate_address_offset = 536;
+static constexpr dart::word Thread_float_not_address_offset = 528;
+static constexpr dart::word Thread_float_zerow_address_offset = 552;
+static constexpr dart::word Thread_global_object_pool_offset = 1336;
+static constexpr dart::word Thread_ic_lookup_through_code_stub_offset = 304;
+static constexpr dart::word Thread_interpret_call_entry_point_offset = 488;
+static constexpr dart::word Thread_invoke_dart_code_from_bytecode_stub_offset =
+    248;
+static constexpr dart::word Thread_invoke_dart_code_stub_offset = 240;
+static constexpr dart::word Thread_isolate_offset = 96;
+static constexpr dart::word Thread_lazy_deopt_from_return_stub_offset = 328;
+static constexpr dart::word Thread_lazy_deopt_from_throw_stub_offset = 336;
+static constexpr dart::word Thread_lazy_specialize_type_test_stub_offset = 352;
+static constexpr dart::word Thread_marking_stack_block_offset = 144;
+static constexpr dart::word Thread_megamorphic_call_checked_entry_offset = 432;
+static constexpr dart::word Thread_monomorphic_miss_entry_offset = 440;
+static constexpr dart::word Thread_monomorphic_miss_stub_offset = 296;
+static constexpr dart::word Thread_no_scope_native_wrapper_entry_point_offset =
+    472;
+static constexpr dart::word
+    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 408;
+static constexpr dart::word Thread_null_error_shared_with_fpu_regs_stub_offset =
+    272;
+static constexpr dart::word
+    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 400;
+static constexpr dart::word
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 264;
+static constexpr dart::word Thread_object_null_offset = 184;
+static constexpr dart::word Thread_predefined_symbols_address_offset = 496;
+static constexpr dart::word Thread_resume_pc_offset = 1344;
+static constexpr dart::word Thread_safepoint_state_offset = 1360;
+static constexpr dart::word Thread_slow_type_test_stub_offset = 344;
+static constexpr dart::word Thread_stack_limit_offset = 72;
+static constexpr dart::word Thread_stack_overflow_flags_offset = 80;
+static constexpr dart::word
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 424;
+static constexpr dart::word
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 288;
+static constexpr dart::word
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 416;
+static constexpr dart::word
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 280;
+static constexpr dart::word Thread_store_buffer_block_offset = 136;
+static constexpr dart::word Thread_top_exit_frame_info_offset = 128;
+static constexpr dart::word Thread_top_offset = 112;
+static constexpr dart::word Thread_top_resource_offset = 48;
+static constexpr dart::word Thread_unboxed_int64_runtime_arg_offset = 176;
+static constexpr dart::word Thread_vm_tag_offset = 160;
+static constexpr dart::word Thread_write_barrier_code_offset = 208;
+static constexpr dart::word Thread_write_barrier_entry_point_offset = 376;
+static constexpr dart::word Thread_write_barrier_mask_offset = 88;
+static constexpr dart::word Thread_verify_callback_entry_offset = 464;
+static constexpr dart::word Thread_callback_code_offset = 1368;
+static constexpr dart::word TimelineStream_enabled_offset = 16;
+static constexpr dart::word TwoByteString_data_offset = 16;
+static constexpr dart::word Type_arguments_offset = 32;
+static constexpr dart::word Type_hash_offset = 40;
+static constexpr dart::word Type_signature_offset = 48;
+static constexpr dart::word Type_type_class_id_offset = 24;
+static constexpr dart::word Type_type_state_offset = 60;
+static constexpr dart::word TypeArguments_instantiations_offset = 8;
+static constexpr dart::word TypeRef_type_offset = 24;
+static constexpr dart::word TypedDataBase_data_field_offset = 8;
+static constexpr dart::word TypedDataBase_length_offset = 16;
+static constexpr dart::word TypedDataView_data_offset = 24;
+static constexpr dart::word TypedDataView_offset_in_bytes_offset = 32;
+static constexpr dart::word TypedData_data_offset = 24;
+static constexpr dart::word UserTag_tag_offset = 16;
+static constexpr dart::word Array_elements_start_offset = 24;
+static constexpr dart::word Array_element_size = 8;
+static constexpr dart::word TypeArguments_elements_start_offset = 32;
+static constexpr dart::word TypeArguments_element_size = 8;
+static constexpr dart::word ClassTable_elements_start_offset = 0;
+static constexpr dart::word ClassTable_element_size = 288;
+static constexpr dart::word ClassTable_class_heap_stats_table_offset = 32;
+static dart::word Code_entry_point_offset[] = {8, 24, 16, 32};
+static dart::word Code_function_entry_point_offset[] = {8, 16};
+static dart::word Thread_write_barrier_wrappers_thread_offset[] = {
+    1144, 1152, 1160, 1168, 1176, 1184, 1192, 1200, 1208, 1216, 1224,
+    1232, 1240, 1248, 1256, -1,   -1,   -1,   -1,   1264, 1272, 1280,
+    1288, 1296, 1304, 1312, -1,   -1,   -1,   -1,   -1,   -1};
+static constexpr dart::word Array_header_size = 24;
+static constexpr dart::word Context_header_size = 24;
+static constexpr dart::word Double_InstanceSize = 16;
+static constexpr dart::word Float32x4_InstanceSize = 24;
+static constexpr dart::word Float64x2_InstanceSize = 24;
+static constexpr dart::word Instructions_UnalignedHeaderSize = 24;
+static constexpr dart::word Int32x4_InstanceSize = 24;
+static constexpr dart::word Mint_InstanceSize = 16;
+static constexpr dart::word NativeArguments_StructSize = 32;
+static constexpr dart::word String_InstanceSize = 16;
+static constexpr dart::word TypedData_InstanceSize = 24;
+#endif  // defined(TARGET_ARCH_ARM64)
+
+#if defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)
+static constexpr dart::word ObjectPool_elements_start_offset = 16;
+static constexpr dart::word ObjectPool_element_size = 8;
+static constexpr dart::word Array_kMaxElements = 576460752303423487;
+static constexpr dart::word Array_kMaxNewSpaceElements = 32765;
+static constexpr dart::word ClassTable_kSizeOfClassPairLog2 = 4;
+static constexpr dart::word Instructions_kMonomorphicEntryOffset = 0;
+static constexpr dart::word Instructions_kPolymorphicEntryOffset = 0;
+static constexpr dart::word HeapPage_kBytesPerCardLog2 = 10;
+static constexpr dart::word NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::word String_kMaxElements = 2305843009213693951;
+static constexpr dart::word SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::word SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::word SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::word SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::word SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::word AbstractType_type_test_stub_entry_point_offset = 8;
+static constexpr dart::word ArgumentsDescriptor_count_offset = 32;
+static constexpr dart::word ArgumentsDescriptor_first_named_entry_offset = 48;
+static constexpr dart::word ArgumentsDescriptor_named_entry_size = 16;
+static constexpr dart::word ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::word ArgumentsDescriptor_position_offset = 8;
+static constexpr dart::word ArgumentsDescriptor_positional_count_offset = 40;
+static constexpr dart::word ArgumentsDescriptor_type_args_len_offset = 24;
+static constexpr dart::word Array_data_offset = 24;
+static constexpr dart::word Array_length_offset = 16;
+static constexpr dart::word Array_tags_offset = 0;
+static constexpr dart::word Array_type_arguments_offset = 8;
+static constexpr dart::word Class_declaration_type_offset = 112;
+static constexpr dart::word Class_num_type_arguments_offset = 186;
+static constexpr dart::word Class_super_type_offset = 88;
+static constexpr dart::word Class_type_arguments_field_offset_in_words_offset =
+    176;
+static constexpr dart::word ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::word ClassHeapStats_allocated_since_gc_new_space_offset =
+    96;
+static constexpr dart::word
+    ClassHeapStats_allocated_size_since_gc_new_space_offset = 104;
+static constexpr dart::word ClassHeapStats_state_offset = 272;
+static constexpr dart::word ClassTable_table_offset = 16;
+static constexpr dart::word Closure_context_offset = 40;
+static constexpr dart::word Closure_delayed_type_arguments_offset = 24;
+static constexpr dart::word Closure_function_offset = 32;
+static constexpr dart::word Closure_function_type_arguments_offset = 16;
+static constexpr dart::word Closure_hash_offset = 48;
+static constexpr dart::word Closure_instantiator_type_arguments_offset = 8;
+static constexpr dart::word Code_object_pool_offset = 40;
+static constexpr dart::word Code_saved_instructions_offset = 48;
+static constexpr dart::word Code_owner_offset = 56;
+static constexpr dart::word Context_num_variables_offset = 8;
+static constexpr dart::word Context_parent_offset = 16;
+static constexpr dart::word Double_value_offset = 8;
+static constexpr dart::word ExternalOneByteString_external_data_offset = 16;
+static constexpr dart::word ExternalTwoByteString_external_data_offset = 16;
+static constexpr dart::word Float32x4_value_offset = 8;
+static constexpr dart::word Float64x2_value_offset = 8;
+static constexpr dart::word Field_guarded_cid_offset = 88;
+static constexpr dart::word Field_guarded_list_length_in_object_offset_offset =
+    96;
+static constexpr dart::word Field_guarded_list_length_offset = 56;
+static constexpr dart::word Field_is_nullable_offset = 90;
+static constexpr dart::word Field_static_value_offset = 32;
+static constexpr dart::word Field_kind_bits_offset = 98;
+static constexpr dart::word Function_code_offset = 88;
+static constexpr dart::word Function_entry_point_offset = 8;
+static constexpr dart::word Function_unchecked_entry_point_offset = 16;
+static constexpr dart::word Function_usage_counter_offset = 132;
+static constexpr dart::word GrowableObjectArray_data_offset = 24;
+static constexpr dart::word GrowableObjectArray_length_offset = 16;
+static constexpr dart::word GrowableObjectArray_type_arguments_offset = 8;
+static constexpr dart::word HeapPage_card_table_offset = 40;
+static constexpr dart::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::word ICData_arguments_descriptor_offset = 24;
+static constexpr dart::word ICData_entries_offset = 8;
+static constexpr dart::word ICData_owner_offset = 40;
+static constexpr dart::word ICData_state_bits_offset = 52;
+static constexpr dart::word ICData_receivers_static_type_offset = 32;
+static constexpr dart::word Isolate_class_table_offset = 48;
+static constexpr dart::word Isolate_current_tag_offset = 16;
+static constexpr dart::word Isolate_default_tag_offset = 24;
+static constexpr dart::word Isolate_ic_miss_code_offset = 32;
+static constexpr dart::word Isolate_object_store_offset = 40;
+static constexpr dart::word Isolate_single_step_offset = 88;
+static constexpr dart::word Isolate_user_tag_offset = 8;
+static constexpr dart::word LinkedHashMap_data_offset = 32;
+static constexpr dart::word LinkedHashMap_deleted_keys_offset = 48;
+static constexpr dart::word LinkedHashMap_hash_mask_offset = 24;
+static constexpr dart::word LinkedHashMap_index_offset = 16;
+static constexpr dart::word LinkedHashMap_used_data_offset = 40;
+static constexpr dart::word MarkingStackBlock_pointers_offset = 16;
+static constexpr dart::word MarkingStackBlock_top_offset = 8;
+static constexpr dart::word MegamorphicCache_arguments_descriptor_offset = 32;
+static constexpr dart::word MegamorphicCache_buckets_offset = 8;
+static constexpr dart::word MegamorphicCache_mask_offset = 16;
+static constexpr dart::word Mint_value_offset = 8;
+static constexpr dart::word NativeArguments_argc_tag_offset = 8;
+static constexpr dart::word NativeArguments_argv_offset = 16;
+static constexpr dart::word NativeArguments_retval_offset = 24;
+static constexpr dart::word NativeArguments_thread_offset = 0;
+static constexpr dart::word ObjectStore_double_type_offset = 128;
+static constexpr dart::word ObjectStore_int_type_offset = 64;
+static constexpr dart::word ObjectStore_string_type_offset = 160;
+static constexpr dart::word OneByteString_data_offset = 16;
+static constexpr dart::word Pointer_c_memory_address_offset = 16;
+static constexpr dart::word SingleTargetCache_entry_point_offset = 16;
+static constexpr dart::word SingleTargetCache_lower_limit_offset = 24;
+static constexpr dart::word SingleTargetCache_target_offset = 8;
+static constexpr dart::word SingleTargetCache_upper_limit_offset = 26;
+static constexpr dart::word StoreBufferBlock_pointers_offset = 16;
+static constexpr dart::word StoreBufferBlock_top_offset = 8;
+static constexpr dart::word String_hash_offset = 4;
+static constexpr dart::word String_length_offset = 8;
+static constexpr dart::word SubtypeTestCache_cache_offset = 8;
+static constexpr dart::word Thread_AllocateArray_entry_point_offset = 296;
+static constexpr dart::word Thread_active_exception_offset = 880;
+static constexpr dart::word Thread_active_stacktrace_offset = 888;
+static constexpr dart::word Thread_async_stack_trace_offset = 168;
+static constexpr dart::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 216;
+static constexpr dart::word Thread_bool_false_offset = 200;
+static constexpr dart::word Thread_bool_true_offset = 192;
+static constexpr dart::word Thread_dart_stream_offset = 944;
+static constexpr dart::word Thread_double_abs_address_offset = 256;
+static constexpr dart::word Thread_double_negate_address_offset = 248;
+static constexpr dart::word Thread_end_offset = 120;
+static constexpr dart::word Thread_execution_state_offset = 912;
+static constexpr dart::word Thread_float_absolute_address_offset = 280;
+static constexpr dart::word Thread_float_negate_address_offset = 272;
+static constexpr dart::word Thread_float_not_address_offset = 264;
+static constexpr dart::word Thread_float_zerow_address_offset = 288;
+static constexpr dart::word Thread_global_object_pool_offset = 896;
+static constexpr dart::word Thread_isolate_offset = 96;
+static constexpr dart::word Thread_marking_stack_block_offset = 144;
+static constexpr dart::word Thread_no_scope_native_wrapper_entry_point_offset =
+    208;
+static constexpr dart::word Thread_object_null_offset = 184;
+static constexpr dart::word Thread_predefined_symbols_address_offset = 232;
+static constexpr dart::word Thread_resume_pc_offset = 904;
+static constexpr dart::word Thread_safepoint_state_offset = 920;
+static constexpr dart::word Thread_stack_limit_offset = 72;
+static constexpr dart::word Thread_stack_overflow_flags_offset = 80;
+static constexpr dart::word Thread_store_buffer_block_offset = 136;
+static constexpr dart::word Thread_top_exit_frame_info_offset = 128;
+static constexpr dart::word Thread_top_offset = 112;
+static constexpr dart::word Thread_top_resource_offset = 48;
+static constexpr dart::word Thread_unboxed_int64_runtime_arg_offset = 176;
+static constexpr dart::word Thread_vm_tag_offset = 160;
+static constexpr dart::word Thread_write_barrier_mask_offset = 88;
+static constexpr dart::word Thread_callback_code_offset = 928;
+static constexpr dart::word TimelineStream_enabled_offset = 16;
+static constexpr dart::word TwoByteString_data_offset = 16;
+static constexpr dart::word Type_arguments_offset = 32;
+static constexpr dart::word Type_hash_offset = 40;
+static constexpr dart::word Type_signature_offset = 48;
+static constexpr dart::word Type_type_class_id_offset = 24;
+static constexpr dart::word Type_type_state_offset = 60;
+static constexpr dart::word TypeArguments_instantiations_offset = 8;
+static constexpr dart::word TypeRef_type_offset = 24;
+static constexpr dart::word TypedDataBase_data_field_offset = 8;
+static constexpr dart::word TypedDataBase_length_offset = 16;
+static constexpr dart::word TypedDataView_data_offset = 24;
+static constexpr dart::word TypedDataView_offset_in_bytes_offset = 32;
+static constexpr dart::word TypedData_data_offset = 24;
+static constexpr dart::word UserTag_tag_offset = 16;
+static constexpr dart::word Array_elements_start_offset = 24;
+static constexpr dart::word Array_element_size = 8;
+static constexpr dart::word TypeArguments_elements_start_offset = 32;
+static constexpr dart::word TypeArguments_element_size = 8;
+static constexpr dart::word ClassTable_elements_start_offset = 0;
+static constexpr dart::word ClassTable_element_size = 288;
+static constexpr dart::word ClassTable_class_heap_stats_table_offset = 32;
+static dart::word Code_entry_point_offset[] = {8, 24, 16, 32};
+static dart::word Code_function_entry_point_offset[] = {8, 16};
+static constexpr dart::word Array_header_size = 24;
+static constexpr dart::word Context_header_size = 24;
+static constexpr dart::word Double_InstanceSize = 16;
+static constexpr dart::word Float32x4_InstanceSize = 24;
+static constexpr dart::word Float64x2_InstanceSize = 24;
+static constexpr dart::word Instructions_UnalignedHeaderSize = 24;
+static constexpr dart::word Int32x4_InstanceSize = 24;
+static constexpr dart::word Mint_InstanceSize = 16;
+static constexpr dart::word NativeArguments_StructSize = 32;
+static constexpr dart::word String_InstanceSize = 16;
+static constexpr dart::word TypedData_InstanceSize = 24;
+#endif  // defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)
+
+#if defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)
+static constexpr dart::word ObjectPool_elements_start_offset = 8;
+static constexpr dart::word ObjectPool_element_size = 4;
+static constexpr dart::word Array_kMaxElements = 268435455;
+static constexpr dart::word Array_kMaxNewSpaceElements = 65533;
+static constexpr dart::word ClassTable_kSizeOfClassPairLog2 = 3;
+static constexpr dart::word Instructions_kMonomorphicEntryOffset = 0;
+static constexpr dart::word Instructions_kPolymorphicEntryOffset = 0;
+static constexpr dart::word HeapPage_kBytesPerCardLog2 = 9;
+static constexpr dart::word NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::word String_kMaxElements = 536870911;
+static constexpr dart::word SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::word SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::word SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::word SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::word SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::word AbstractType_type_test_stub_entry_point_offset = 4;
+static constexpr dart::word ArgumentsDescriptor_count_offset = 16;
+static constexpr dart::word ArgumentsDescriptor_first_named_entry_offset = 24;
+static constexpr dart::word ArgumentsDescriptor_named_entry_size = 8;
+static constexpr dart::word ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::word ArgumentsDescriptor_position_offset = 4;
+static constexpr dart::word ArgumentsDescriptor_positional_count_offset = 20;
+static constexpr dart::word ArgumentsDescriptor_type_args_len_offset = 12;
+static constexpr dart::word Array_data_offset = 12;
+static constexpr dart::word Array_length_offset = 8;
+static constexpr dart::word Array_tags_offset = 0;
+static constexpr dart::word Array_type_arguments_offset = 4;
+static constexpr dart::word Class_declaration_type_offset = 56;
+static constexpr dart::word Class_num_type_arguments_offset = 102;
+static constexpr dart::word Class_super_type_offset = 44;
+static constexpr dart::word Class_type_arguments_field_offset_in_words_offset =
+    92;
+static constexpr dart::word ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::word ClassHeapStats_allocated_since_gc_new_space_offset =
+    48;
+static constexpr dart::word
+    ClassHeapStats_allocated_size_since_gc_new_space_offset = 52;
+static constexpr dart::word ClassHeapStats_state_offset = 160;
+static constexpr dart::word ClassTable_table_offset = 8;
+static constexpr dart::word Closure_context_offset = 20;
+static constexpr dart::word Closure_delayed_type_arguments_offset = 12;
+static constexpr dart::word Closure_function_offset = 16;
+static constexpr dart::word Closure_function_type_arguments_offset = 8;
+static constexpr dart::word Closure_hash_offset = 24;
+static constexpr dart::word Closure_instantiator_type_arguments_offset = 4;
+static constexpr dart::word Code_object_pool_offset = 20;
+static constexpr dart::word Code_saved_instructions_offset = 24;
+static constexpr dart::word Code_owner_offset = 28;
+static constexpr dart::word Context_num_variables_offset = 4;
+static constexpr dart::word Context_parent_offset = 8;
+static constexpr dart::word Double_value_offset = 8;
+static constexpr dart::word ExternalOneByteString_external_data_offset = 12;
+static constexpr dart::word ExternalTwoByteString_external_data_offset = 12;
+static constexpr dart::word Float32x4_value_offset = 8;
+static constexpr dart::word Float64x2_value_offset = 8;
+static constexpr dart::word Field_guarded_cid_offset = 48;
+static constexpr dart::word Field_guarded_list_length_in_object_offset_offset =
+    56;
+static constexpr dart::word Field_guarded_list_length_offset = 28;
+static constexpr dart::word Field_is_nullable_offset = 50;
+static constexpr dart::word Field_static_value_offset = 16;
+static constexpr dart::word Field_kind_bits_offset = 58;
+static constexpr dart::word Function_code_offset = 44;
+static constexpr dart::word Function_entry_point_offset = 4;
+static constexpr dart::word Function_unchecked_entry_point_offset = 8;
+static constexpr dart::word Function_usage_counter_offset = 76;
+static constexpr dart::word GrowableObjectArray_data_offset = 12;
+static constexpr dart::word GrowableObjectArray_length_offset = 8;
+static constexpr dart::word GrowableObjectArray_type_arguments_offset = 4;
+static constexpr dart::word HeapPage_card_table_offset = 20;
+static constexpr dart::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::word ICData_arguments_descriptor_offset = 12;
+static constexpr dart::word ICData_entries_offset = 4;
+static constexpr dart::word ICData_owner_offset = 20;
+static constexpr dart::word ICData_state_bits_offset = 28;
+static constexpr dart::word ICData_receivers_static_type_offset = 16;
+static constexpr dart::word Isolate_class_table_offset = 24;
+static constexpr dart::word Isolate_current_tag_offset = 8;
+static constexpr dart::word Isolate_default_tag_offset = 12;
+static constexpr dart::word Isolate_ic_miss_code_offset = 16;
+static constexpr dart::word Isolate_object_store_offset = 20;
+static constexpr dart::word Isolate_single_step_offset = 44;
+static constexpr dart::word Isolate_user_tag_offset = 4;
+static constexpr dart::word LinkedHashMap_data_offset = 16;
+static constexpr dart::word LinkedHashMap_deleted_keys_offset = 24;
+static constexpr dart::word LinkedHashMap_hash_mask_offset = 12;
+static constexpr dart::word LinkedHashMap_index_offset = 8;
+static constexpr dart::word LinkedHashMap_used_data_offset = 20;
+static constexpr dart::word MarkingStackBlock_pointers_offset = 8;
+static constexpr dart::word MarkingStackBlock_top_offset = 4;
+static constexpr dart::word MegamorphicCache_arguments_descriptor_offset = 16;
+static constexpr dart::word MegamorphicCache_buckets_offset = 4;
+static constexpr dart::word MegamorphicCache_mask_offset = 8;
+static constexpr dart::word Mint_value_offset = 8;
+static constexpr dart::word NativeArguments_argc_tag_offset = 4;
+static constexpr dart::word NativeArguments_argv_offset = 8;
+static constexpr dart::word NativeArguments_retval_offset = 12;
+static constexpr dart::word NativeArguments_thread_offset = 0;
+static constexpr dart::word ObjectStore_double_type_offset = 64;
+static constexpr dart::word ObjectStore_int_type_offset = 32;
+static constexpr dart::word ObjectStore_string_type_offset = 80;
+static constexpr dart::word OneByteString_data_offset = 12;
+static constexpr dart::word Pointer_c_memory_address_offset = 8;
+static constexpr dart::word SingleTargetCache_entry_point_offset = 8;
+static constexpr dart::word SingleTargetCache_lower_limit_offset = 12;
+static constexpr dart::word SingleTargetCache_target_offset = 4;
+static constexpr dart::word SingleTargetCache_upper_limit_offset = 14;
+static constexpr dart::word StoreBufferBlock_pointers_offset = 8;
+static constexpr dart::word StoreBufferBlock_top_offset = 4;
+static constexpr dart::word String_hash_offset = 8;
+static constexpr dart::word String_length_offset = 4;
+static constexpr dart::word SubtypeTestCache_cache_offset = 4;
+static constexpr dart::word Thread_AllocateArray_entry_point_offset = 152;
+static constexpr dart::word Thread_active_exception_offset = 444;
+static constexpr dart::word Thread_active_stacktrace_offset = 448;
+static constexpr dart::word Thread_async_stack_trace_offset = 84;
+static constexpr dart::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 112;
+static constexpr dart::word Thread_bool_false_offset = 104;
+static constexpr dart::word Thread_bool_true_offset = 100;
+static constexpr dart::word Thread_dart_stream_offset = 476;
+static constexpr dart::word Thread_double_abs_address_offset = 132;
+static constexpr dart::word Thread_double_negate_address_offset = 128;
+static constexpr dart::word Thread_end_offset = 60;
+static constexpr dart::word Thread_execution_state_offset = 460;
+static constexpr dart::word Thread_float_absolute_address_offset = 144;
+static constexpr dart::word Thread_float_negate_address_offset = 140;
+static constexpr dart::word Thread_float_not_address_offset = 136;
+static constexpr dart::word Thread_float_zerow_address_offset = 148;
+static constexpr dart::word Thread_global_object_pool_offset = 452;
+static constexpr dart::word Thread_isolate_offset = 48;
+static constexpr dart::word Thread_marking_stack_block_offset = 72;
+static constexpr dart::word Thread_no_scope_native_wrapper_entry_point_offset =
+    108;
+static constexpr dart::word Thread_object_null_offset = 96;
+static constexpr dart::word Thread_predefined_symbols_address_offset = 120;
+static constexpr dart::word Thread_resume_pc_offset = 456;
+static constexpr dart::word Thread_safepoint_state_offset = 464;
+static constexpr dart::word Thread_stack_limit_offset = 36;
+static constexpr dart::word Thread_stack_overflow_flags_offset = 40;
+static constexpr dart::word Thread_store_buffer_block_offset = 68;
+static constexpr dart::word Thread_top_exit_frame_info_offset = 64;
+static constexpr dart::word Thread_top_offset = 56;
+static constexpr dart::word Thread_top_resource_offset = 24;
+static constexpr dart::word Thread_unboxed_int64_runtime_arg_offset = 88;
+static constexpr dart::word Thread_vm_tag_offset = 80;
+static constexpr dart::word Thread_write_barrier_mask_offset = 44;
+static constexpr dart::word Thread_callback_code_offset = 468;
+static constexpr dart::word TimelineStream_enabled_offset = 8;
+static constexpr dart::word TwoByteString_data_offset = 12;
+static constexpr dart::word Type_arguments_offset = 16;
+static constexpr dart::word Type_hash_offset = 20;
+static constexpr dart::word Type_signature_offset = 24;
+static constexpr dart::word Type_type_class_id_offset = 12;
+static constexpr dart::word Type_type_state_offset = 32;
+static constexpr dart::word TypeArguments_instantiations_offset = 4;
+static constexpr dart::word TypeRef_type_offset = 12;
+static constexpr dart::word TypedDataBase_data_field_offset = 4;
+static constexpr dart::word TypedDataBase_length_offset = 8;
+static constexpr dart::word TypedDataView_data_offset = 12;
+static constexpr dart::word TypedDataView_offset_in_bytes_offset = 16;
+static constexpr dart::word TypedData_data_offset = 12;
+static constexpr dart::word UserTag_tag_offset = 8;
+static constexpr dart::word Array_elements_start_offset = 12;
+static constexpr dart::word Array_element_size = 4;
+static constexpr dart::word TypeArguments_elements_start_offset = 16;
+static constexpr dart::word TypeArguments_element_size = 4;
+static constexpr dart::word ClassTable_elements_start_offset = 0;
+static constexpr dart::word ClassTable_element_size = 168;
+static constexpr dart::word ClassTable_class_heap_stats_table_offset = 16;
+static dart::word Code_entry_point_offset[] = {4, 12, 8, 16};
+static dart::word Code_function_entry_point_offset[] = {4, 8};
+static constexpr dart::word Array_header_size = 12;
+static constexpr dart::word Context_header_size = 12;
+static constexpr dart::word Double_InstanceSize = 16;
+static constexpr dart::word Float32x4_InstanceSize = 24;
+static constexpr dart::word Float64x2_InstanceSize = 24;
+static constexpr dart::word Instructions_UnalignedHeaderSize = 16;
+static constexpr dart::word Int32x4_InstanceSize = 24;
+static constexpr dart::word Mint_InstanceSize = 16;
+static constexpr dart::word NativeArguments_StructSize = 16;
+static constexpr dart::word String_InstanceSize = 12;
+static constexpr dart::word TypedData_InstanceSize = 12;
+#endif  // defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)
+
+#endif  // RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
new file mode 100644
index 0000000..6882e1c
--- /dev/null
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -0,0 +1,267 @@
+// Copyright (c) 2019, 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_COMPILER_RUNTIME_OFFSETS_LIST_H_
+#define RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_LIST_H_
+
+// Macro list of all constants that differ based on whether the architecture is
+// 32-bit or 64-bit. They are used to allow the target architecture to differ
+// from the host, like this:
+// 1) The macros correspond to constants defined throughout the VM that are
+//    sized based on the *host* architecture.
+// 2) offsets_extractor.cc prints these values to runtime_offsets_extracted.h,
+//    for both 32 and 64 bit architectures.
+// 3) runtime_api.h presents the runtime_offsets_extracted.h constants in a way
+//    designed to look like the original constants from 1), but now namespaced
+//    to dart::compiler::target, and sized based on the *target* architecture.
+// 4) Users of the constants from 1) can now just add the namespace from 3) to
+//    get all their constants sized based on the target rather than the host.
+
+// FIELD(Class, Name) Offset of a field within a class.
+// ARRAY(Class, Name) Offset of the first element and the size of the elements
+//     in an array of this class.
+// ARRAY_STRUCTFIELD(Class, Name, Element, Field) Offset of a field within a
+//     struct in an array of that struct, relative to the start of the array.
+// SIZEOF(Class, Name, What) Size of an object.
+// RANGE(Class, Name, Type, First, Last, Filter) An array of offsets generated
+//     by passing a value of the given Type in the range from First to Last to
+//     Class::Name() if Filter returns true for that value.
+// CONSTANT(Class, Name) Miscellaneous constant.
+// PRECOMP_NO_CHECK(Code) Don't check this offset in the precompiled runtime.
+#define OFFSETS_LIST(FIELD, ARRAY, ARRAY_STRUCTFIELD, SIZEOF, RANGE, CONSTANT, \
+                     PRECOMP_NO_CHECK)                                         \
+  ARRAY(ObjectPool, element_offset)                                            \
+  CONSTANT(Array, kMaxElements)                                                \
+  CONSTANT(Array, kMaxNewSpaceElements)                                        \
+  CONSTANT(ClassTable, kSizeOfClassPairLog2)                                   \
+  CONSTANT(Instructions, kMonomorphicEntryOffset)                              \
+  CONSTANT(Instructions, kPolymorphicEntryOffset)                              \
+  CONSTANT(HeapPage, kBytesPerCardLog2)                                        \
+  CONSTANT(NativeEntry, kNumCallWrapperArguments)                              \
+  CONSTANT(String, kMaxElements)                                               \
+  CONSTANT(SubtypeTestCache, kFunctionTypeArguments)                           \
+  CONSTANT(SubtypeTestCache, kInstanceClassIdOrFunction)                       \
+  CONSTANT(SubtypeTestCache, kInstanceDelayedFunctionTypeArguments)            \
+  CONSTANT(SubtypeTestCache, kInstanceParentFunctionTypeArguments)             \
+  CONSTANT(SubtypeTestCache, kInstanceTypeArguments)                           \
+  CONSTANT(SubtypeTestCache, kInstantiatorTypeArguments)                       \
+  CONSTANT(SubtypeTestCache, kTestEntryLength)                                 \
+  CONSTANT(SubtypeTestCache, kTestResult)                                      \
+  FIELD(AbstractType, type_test_stub_entry_point_offset)                       \
+  FIELD(ArgumentsDescriptor, count_offset)                                     \
+  FIELD(ArgumentsDescriptor, first_named_entry_offset)                         \
+  FIELD(ArgumentsDescriptor, named_entry_size)                                 \
+  FIELD(ArgumentsDescriptor, name_offset)                                      \
+  FIELD(ArgumentsDescriptor, position_offset)                                  \
+  FIELD(ArgumentsDescriptor, positional_count_offset)                          \
+  FIELD(ArgumentsDescriptor, type_args_len_offset)                             \
+  FIELD(Array, data_offset)                                                    \
+  FIELD(Array, length_offset)                                                  \
+  FIELD(Array, tags_offset)                                                    \
+  FIELD(Array, type_arguments_offset)                                          \
+  FIELD(Class, declaration_type_offset)                                        \
+  FIELD(Class, num_type_arguments_offset)                                      \
+  FIELD(Class, super_type_offset)                                              \
+  FIELD(Class, type_arguments_field_offset_in_words_offset)                    \
+  NOT_IN_PRODUCT(FIELD(ClassHeapStats, TraceAllocationMask))                   \
+  NOT_IN_PRODUCT(FIELD(ClassHeapStats, allocated_since_gc_new_space_offset))   \
+  NOT_IN_PRODUCT(                                                              \
+      FIELD(ClassHeapStats, allocated_size_since_gc_new_space_offset))         \
+  NOT_IN_PRODUCT(FIELD(ClassHeapStats, state_offset))                          \
+  FIELD(ClassTable, table_offset)                                              \
+  FIELD(Closure, context_offset)                                               \
+  FIELD(Closure, delayed_type_arguments_offset)                                \
+  FIELD(Closure, function_offset)                                              \
+  FIELD(Closure, function_type_arguments_offset)                               \
+  FIELD(Closure, hash_offset)                                                  \
+  FIELD(Closure, instantiator_type_arguments_offset)                           \
+  FIELD(Code, object_pool_offset)                                              \
+  FIELD(Code, saved_instructions_offset)                                       \
+  FIELD(Code, owner_offset)                                                    \
+  FIELD(Context, num_variables_offset)                                         \
+  FIELD(Context, parent_offset)                                                \
+  FIELD(Double, value_offset)                                                  \
+  FIELD(ExternalOneByteString, external_data_offset)                           \
+  FIELD(ExternalTwoByteString, external_data_offset)                           \
+  FIELD(Float32x4, value_offset)                                               \
+  FIELD(Float64x2, value_offset)                                               \
+  PRECOMP_NO_CHECK(FIELD(Field, guarded_cid_offset))                           \
+  PRECOMP_NO_CHECK(FIELD(Field, guarded_list_length_in_object_offset_offset))  \
+  PRECOMP_NO_CHECK(FIELD(Field, guarded_list_length_offset))                   \
+  PRECOMP_NO_CHECK(FIELD(Field, is_nullable_offset))                           \
+  FIELD(Field, static_value_offset)                                            \
+  PRECOMP_NO_CHECK(FIELD(Field, kind_bits_offset))                             \
+  FIELD(Function, code_offset)                                                 \
+  FIELD(Function, entry_point_offset)                                          \
+  FIELD(Function, unchecked_entry_point_offset)                                \
+  PRECOMP_NO_CHECK(FIELD(Function, usage_counter_offset))                      \
+  FIELD(GrowableObjectArray, data_offset)                                      \
+  FIELD(GrowableObjectArray, length_offset)                                    \
+  FIELD(GrowableObjectArray, type_arguments_offset)                            \
+  FIELD(HeapPage, card_table_offset)                                           \
+  FIELD(ICData, NumArgsTestedMask)                                             \
+  FIELD(ICData, NumArgsTestedShift)                                            \
+  FIELD(ICData, arguments_descriptor_offset)                                   \
+  FIELD(ICData, entries_offset)                                                \
+  PRECOMP_NO_CHECK(FIELD(ICData, owner_offset))                                \
+  PRECOMP_NO_CHECK(FIELD(ICData, state_bits_offset))                           \
+  NOT_IN_PRECOMPILED_RUNTIME(FIELD(ICData, receivers_static_type_offset))      \
+  FIELD(Isolate, class_table_offset)                                           \
+  FIELD(Isolate, current_tag_offset)                                           \
+  FIELD(Isolate, default_tag_offset)                                           \
+  FIELD(Isolate, ic_miss_code_offset)                                          \
+  FIELD(Isolate, object_store_offset)                                          \
+  NOT_IN_PRODUCT(FIELD(Isolate, single_step_offset))                           \
+  FIELD(Isolate, user_tag_offset)                                              \
+  FIELD(LinkedHashMap, data_offset)                                            \
+  FIELD(LinkedHashMap, deleted_keys_offset)                                    \
+  FIELD(LinkedHashMap, hash_mask_offset)                                       \
+  FIELD(LinkedHashMap, index_offset)                                           \
+  FIELD(LinkedHashMap, used_data_offset)                                       \
+  FIELD(MarkingStackBlock, pointers_offset)                                    \
+  FIELD(MarkingStackBlock, top_offset)                                         \
+  FIELD(MegamorphicCache, arguments_descriptor_offset)                         \
+  FIELD(MegamorphicCache, buckets_offset)                                      \
+  FIELD(MegamorphicCache, mask_offset)                                         \
+  FIELD(Mint, value_offset)                                                    \
+  FIELD(NativeArguments, argc_tag_offset)                                      \
+  FIELD(NativeArguments, argv_offset)                                          \
+  FIELD(NativeArguments, retval_offset)                                        \
+  FIELD(NativeArguments, thread_offset)                                        \
+  FIELD(ObjectStore, double_type_offset)                                       \
+  FIELD(ObjectStore, int_type_offset)                                          \
+  FIELD(ObjectStore, string_type_offset)                                       \
+  FIELD(OneByteString, data_offset)                                            \
+  FIELD(Pointer, c_memory_address_offset)                                      \
+  FIELD(SingleTargetCache, entry_point_offset)                                 \
+  FIELD(SingleTargetCache, lower_limit_offset)                                 \
+  FIELD(SingleTargetCache, target_offset)                                      \
+  FIELD(SingleTargetCache, upper_limit_offset)                                 \
+  FIELD(StoreBufferBlock, pointers_offset)                                     \
+  FIELD(StoreBufferBlock, top_offset)                                          \
+  FIELD(String, hash_offset)                                                   \
+  FIELD(String, length_offset)                                                 \
+  FIELD(SubtypeTestCache, cache_offset)                                        \
+  FIELD(Thread, AllocateArray_entry_point_offset)                              \
+  FIELD(Thread, active_exception_offset)                                       \
+  FIELD(Thread, active_stacktrace_offset)                                      \
+  NOT_IN_DBC(FIELD(Thread, array_write_barrier_code_offset))                   \
+  NOT_IN_DBC(FIELD(Thread, array_write_barrier_entry_point_offset))            \
+  FIELD(Thread, async_stack_trace_offset)                                      \
+  FIELD(Thread, auto_scope_native_wrapper_entry_point_offset)                  \
+  FIELD(Thread, bool_false_offset)                                             \
+  FIELD(Thread, bool_true_offset)                                              \
+  NOT_IN_DBC(FIELD(Thread, call_to_runtime_entry_point_offset))                \
+  NOT_IN_DBC(FIELD(Thread, call_to_runtime_stub_offset))                       \
+  FIELD(Thread, dart_stream_offset)                                            \
+  NOT_IN_DBC(FIELD(Thread, deoptimize_entry_offset))                           \
+  NOT_IN_DBC(FIELD(Thread, deoptimize_stub_offset))                            \
+  FIELD(Thread, double_abs_address_offset)                                     \
+  FIELD(Thread, double_negate_address_offset)                                  \
+  FIELD(Thread, end_offset)                                                    \
+  NOT_IN_DBC(FIELD(Thread, enter_safepoint_stub_offset))                       \
+  FIELD(Thread, execution_state_offset)                                        \
+  NOT_IN_DBC(FIELD(Thread, exit_safepoint_stub_offset))                        \
+  NOT_IN_DBC(FIELD(Thread, fix_allocation_stub_code_offset))                   \
+  NOT_IN_DBC(FIELD(Thread, fix_callers_target_code_offset))                    \
+  FIELD(Thread, float_absolute_address_offset)                                 \
+  FIELD(Thread, float_negate_address_offset)                                   \
+  FIELD(Thread, float_not_address_offset)                                      \
+  FIELD(Thread, float_zerow_address_offset)                                    \
+  FIELD(Thread, global_object_pool_offset)                                     \
+  NOT_IN_DBC(FIELD(Thread, ic_lookup_through_code_stub_offset))                \
+  NOT_IN_DBC(FIELD(Thread, interpret_call_entry_point_offset))                 \
+  NOT_IN_DBC(FIELD(Thread, invoke_dart_code_from_bytecode_stub_offset))        \
+  NOT_IN_DBC(FIELD(Thread, invoke_dart_code_stub_offset))                      \
+  FIELD(Thread, isolate_offset)                                                \
+  NOT_IN_DBC(FIELD(Thread, lazy_deopt_from_return_stub_offset))                \
+  NOT_IN_DBC(FIELD(Thread, lazy_deopt_from_throw_stub_offset))                 \
+  NOT_IN_DBC(FIELD(Thread, lazy_specialize_type_test_stub_offset))             \
+  FIELD(Thread, marking_stack_block_offset)                                    \
+  NOT_IN_DBC(FIELD(Thread, megamorphic_call_checked_entry_offset))             \
+  NOT_IN_DBC(FIELD(Thread, monomorphic_miss_entry_offset))                     \
+  NOT_IN_DBC(FIELD(Thread, monomorphic_miss_stub_offset))                      \
+  FIELD(Thread, no_scope_native_wrapper_entry_point_offset)                    \
+  NOT_IN_DBC(                                                                  \
+      FIELD(Thread, null_error_shared_with_fpu_regs_entry_point_offset))       \
+  NOT_IN_DBC(FIELD(Thread, null_error_shared_with_fpu_regs_stub_offset))       \
+  NOT_IN_DBC(                                                                  \
+      FIELD(Thread, null_error_shared_without_fpu_regs_entry_point_offset))    \
+  NOT_IN_DBC(FIELD(Thread, null_error_shared_without_fpu_regs_stub_offset))    \
+  FIELD(Thread, object_null_offset)                                            \
+  FIELD(Thread, predefined_symbols_address_offset)                             \
+  FIELD(Thread, resume_pc_offset)                                              \
+  FIELD(Thread, safepoint_state_offset)                                        \
+  NOT_IN_DBC(FIELD(Thread, slow_type_test_stub_offset))                        \
+  FIELD(Thread, stack_limit_offset)                                            \
+  FIELD(Thread, stack_overflow_flags_offset)                                   \
+  NOT_IN_DBC(                                                                  \
+      FIELD(Thread, stack_overflow_shared_with_fpu_regs_entry_point_offset))   \
+  NOT_IN_DBC(FIELD(Thread, stack_overflow_shared_with_fpu_regs_stub_offset))   \
+  NOT_IN_DBC(FIELD(Thread,                                                     \
+                   stack_overflow_shared_without_fpu_regs_entry_point_offset)) \
+  NOT_IN_DBC(                                                                  \
+      FIELD(Thread, stack_overflow_shared_without_fpu_regs_stub_offset))       \
+  FIELD(Thread, store_buffer_block_offset)                                     \
+  FIELD(Thread, top_exit_frame_info_offset)                                    \
+  FIELD(Thread, top_offset)                                                    \
+  FIELD(Thread, top_resource_offset)                                           \
+  FIELD(Thread, unboxed_int64_runtime_arg_offset)                              \
+  FIELD(Thread, vm_tag_offset)                                                 \
+  NOT_IN_DBC(FIELD(Thread, write_barrier_code_offset))                         \
+  NOT_IN_DBC(FIELD(Thread, write_barrier_entry_point_offset))                  \
+  FIELD(Thread, write_barrier_mask_offset)                                     \
+  NOT_IN_DBC(FIELD(Thread, verify_callback_entry_offset))                      \
+  FIELD(Thread, callback_code_offset)                                          \
+  FIELD(TimelineStream, enabled_offset)                                        \
+  FIELD(TwoByteString, data_offset)                                            \
+  FIELD(Type, arguments_offset)                                                \
+  FIELD(Type, hash_offset)                                                     \
+  FIELD(Type, signature_offset)                                                \
+  FIELD(Type, type_class_id_offset)                                            \
+  FIELD(Type, type_state_offset)                                               \
+  FIELD(TypeArguments, instantiations_offset)                                  \
+  FIELD(TypeRef, type_offset)                                                  \
+  FIELD(TypedDataBase, data_field_offset)                                      \
+  FIELD(TypedDataBase, length_offset)                                          \
+  FIELD(TypedDataView, data_offset)                                            \
+  FIELD(TypedDataView, offset_in_bytes_offset)                                 \
+  FIELD(TypedData, data_offset)                                                \
+  FIELD(UserTag, tag_offset)                                                   \
+  ARRAY(Array, element_offset)                                                 \
+  ARRAY(TypeArguments, type_at_offset)                                         \
+  NOT_IN_PRODUCT(ARRAY(ClassTable, ClassOffsetFor))                            \
+  NOT_IN_PRODUCT(ARRAY_STRUCTFIELD(                                            \
+      ClassTable, NewSpaceCounterOffsetFor, ClassOffsetFor,                    \
+      ClassHeapStats::allocated_since_gc_new_space_offset()))                  \
+  NOT_IN_PRODUCT(ARRAY_STRUCTFIELD(                                            \
+      ClassTable, StateOffsetFor, ClassOffsetFor,                              \
+      ClassHeapStats::allocated_since_gc_new_space_offset()))                  \
+  NOT_IN_PRODUCT(ARRAY_STRUCTFIELD(                                            \
+      ClassTable, NewSpaceSizeOffsetFor, ClassOffsetFor,                       \
+      ClassHeapStats::allocated_size_since_gc_new_space_offset()))             \
+  NOT_IN_PRODUCT(FIELD(ClassTable, class_heap_stats_table_offset))             \
+  RANGE(Code, entry_point_offset, CodeEntryKind, CodeEntryKind::kNormal,       \
+        CodeEntryKind::kMonomorphicUnchecked,                                  \
+        [](CodeEntryKind value) { return true; })                              \
+  RANGE(Code, function_entry_point_offset, CodeEntryKind,                      \
+        CodeEntryKind::kNormal, CodeEntryKind::kUnchecked,                     \
+        [](CodeEntryKind value) { return true; })                              \
+  ONLY_IN_ARM_ARM64_X64(RANGE(                                                 \
+      Thread, write_barrier_wrappers_thread_offset, Register, 0,               \
+      kNumberOfCpuRegisters - 1,                                               \
+      [](Register reg) { return (kDartAvailableCpuRegs & (1 << reg)) != 0; })) \
+  SIZEOF(Array, header_size, RawArray)                                         \
+  SIZEOF(Context, header_size, RawContext)                                     \
+  SIZEOF(Double, InstanceSize, RawDouble)                                      \
+  SIZEOF(Float32x4, InstanceSize, RawFloat32x4)                                \
+  SIZEOF(Float64x2, InstanceSize, RawFloat64x2)                                \
+  SIZEOF(Instructions, UnalignedHeaderSize, RawInstructions)                   \
+  SIZEOF(Int32x4, InstanceSize, RawInt32x4)                                    \
+  SIZEOF(Mint, InstanceSize, RawMint)                                          \
+  SIZEOF(NativeArguments, StructSize, NativeArguments)                         \
+  SIZEOF(String, InstanceSize, RawString)                                      \
+  SIZEOF(TypedData, InstanceSize, RawTypedData)
+
+#endif  // RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_LIST_H_
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index e82fa9f..7f4f9e2 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -274,8 +274,13 @@
   RegisterSet all_registers;
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers);
+
+  __ EnterFrame((1 << FP) | (1 << LR), 0);
+  __ ReserveAlignedFrameSpace(0);
   __ ldr(R0, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
   __ blx(R0);
+  __ LeaveFrame((1 << FP) | (1 << LR), 0);
+
   __ PopRegisters(all_registers);
   __ Ret();
 }
@@ -284,12 +289,35 @@
   RegisterSet all_registers;
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers);
+
+  __ EnterFrame((1 << FP) | (1 << LR), 0);
+  __ ReserveAlignedFrameSpace(0);
   __ ldr(R0, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
   __ blx(R0);
+  __ LeaveFrame((1 << FP) | (1 << LR), 0);
+
   __ PopRegisters(all_registers);
   __ Ret();
 }
 
+void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
+  __ EnterFrame(1 << FP | 1 << LR, 0);
+  __ ReserveAlignedFrameSpace(0);
+
+  // First argument is already set up by the caller.
+  //
+  // Second argument is the return address of the caller.
+  __ mov(CallingConventions::ArgumentRegisters[1], Operand(LR));
+  ASSERT(R2 != CallingConventions::ArgumentRegisters[0] &&
+         R2 != CallingConventions::ArgumentRegisters[1]);
+  __ LoadFromOffset(kWord, R2, THR,
+                    kVerifyCallbackIsolateRuntimeEntry.OffsetFromThread());
+  __ blx(R2);
+
+  __ LeaveFrame(1 << FP | 1 << LR);
+  __ Ret();
+}
+
 void StubCodeCompiler::GenerateNullErrorSharedWithoutFPURegsStub(
     Assembler* assembler) {
   GenerateSharedStub(
@@ -1031,17 +1059,7 @@
   __ ldr(IP, Address(R3, target::Thread::invoke_dart_code_stub_offset()));
   __ Push(IP);
 
-  // Save new context and C++ ABI callee-saved registers.
-  __ PushList(kAbiPreservedCpuRegs);
-
-  const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg);
-  if (TargetCPUFeatures::vfp_supported()) {
-    ASSERT(2 * kAbiPreservedFpuRegCount < 16);
-    // Save FPU registers. 2 D registers per Q register.
-    __ vstmd(DB_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
-  } else {
-    __ sub(SP, SP, Operand(kAbiPreservedFpuRegCount * kFpuRegisterSize));
-  }
+  __ PushNativeCalleeSavedRegisters();
 
   // Set up THR, which caches the current thread in Dart code.
   if (THR != R3) {
@@ -1072,6 +1090,8 @@
 #endif
   __ Push(R9);
 
+  __ EmitEntryFrameVerification(R9);
+
   // Mark that the thread is executing Dart code. Do this after initializing the
   // exit link for the profiler.
   __ LoadImmediate(R9, VMTag::kDartCompiledTagId);
@@ -1135,15 +1155,8 @@
   __ Pop(R4);
   __ StoreToOffset(kWord, R4, THR, target::Thread::vm_tag_offset());
 
-  // Restore C++ ABI callee-saved registers.
-  if (TargetCPUFeatures::vfp_supported()) {
-    // Restore FPU registers. 2 D registers per Q register.
-    __ vldmd(IA_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
-  } else {
-    __ AddImmediate(SP, kAbiPreservedFpuRegCount * kFpuRegisterSize);
-  }
-  // Restore CPU registers.
-  __ PopList(kAbiPreservedCpuRegs);
+  __ PopNativeCalleeSavedRegisters();
+
   __ set_constant_pool_allowed(false);
 
   // Restore the frame pointer and return.
@@ -1748,7 +1761,7 @@
     EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
   }
 
-  __ LeaveDartFrameAndReturn();         // Restores correct SP.
+  __ LeaveDartFrameAndReturn();  // Restores correct SP.
 }
 
 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 9bee589..c431835 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -209,12 +209,14 @@
   RegisterSet all_registers;
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers);
-  __ mov(CallingConventions::kFirstCalleeSavedCpuReg, SP);
+
+  __ EnterFrame(0);
   __ ReserveAlignedFrameSpace(0);
   __ mov(CSP, SP);
   __ ldr(R0, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
   __ blr(R0);
-  __ mov(SP, CallingConventions::kFirstCalleeSavedCpuReg);
+  __ LeaveFrame();
+
   __ PopRegisters(all_registers);
   __ mov(CSP, SP);
   __ Ret();
@@ -224,17 +226,37 @@
   RegisterSet all_registers;
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers);
-  __ mov(CallingConventions::kFirstCalleeSavedCpuReg, SP);
+
+  __ EnterFrame(0);
   __ ReserveAlignedFrameSpace(0);
   __ mov(CSP, SP);
   __ ldr(R0, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
   __ blr(R0);
-  __ mov(SP, CallingConventions::kFirstCalleeSavedCpuReg);
+  __ LeaveFrame();
+
   __ PopRegisters(all_registers);
   __ mov(CSP, SP);
   __ Ret();
 }
 
+void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
+  __ EnterFrame(0);
+  __ ReserveAlignedFrameSpace(0);
+
+  // First argument is already set up by the caller.
+  //
+  // Second argument is the return address of the caller.
+  __ mov(CallingConventions::ArgumentRegisters[1], LR);
+  __ LoadFromOffset(R2, THR,
+                    kVerifyCallbackIsolateRuntimeEntry.OffsetFromThread());
+  __ mov(CSP, SP);
+  __ blr(R2);
+  __ mov(SP, CSP);
+
+  __ LeaveFrame();
+  __ Ret();
+}
+
 // R1: The extracted method.
 // R4: The type_arguments_field_offset (or 0)
 void StubCodeCompiler::GenerateBuildMethodExtractorStub(
@@ -1111,20 +1133,7 @@
   __ ldr(TMP, Address(R3, target::Thread::invoke_dart_code_stub_offset()));
   __ Push(TMP);
 
-  // Save the callee-saved registers.
-  for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) {
-    const Register r = static_cast<Register>(i);
-    // We use str instead of the Push macro because we will be pushing the PP
-    // register when it is not holding a pool-pointer since we are coming from
-    // C++ code.
-    __ str(r, Address(SP, -1 * target::kWordSize, Address::PreIndex));
-  }
-
-  // Save the bottom 64-bits of callee-saved V registers.
-  for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) {
-    const VRegister r = static_cast<VRegister>(i);
-    __ PushDouble(r);
-  }
+  __ PushNativeCalleeSavedRegisters();
 
   // Set up THR, which caches the current thread in Dart code.
   if (THR != R3) {
@@ -1218,21 +1227,7 @@
   __ Pop(R4);
   __ StoreToOffset(R4, THR, target::Thread::vm_tag_offset());
 
-  // Restore the bottom 64-bits of callee-saved V registers.
-  for (int i = kAbiLastPreservedFpuReg; i >= kAbiFirstPreservedFpuReg; i--) {
-    const VRegister r = static_cast<VRegister>(i);
-    __ PopDouble(r);
-  }
-
-  // Restore C++ ABI callee-saved registers.
-  for (int i = kAbiLastPreservedCpuReg; i >= kAbiFirstPreservedCpuReg; i--) {
-    Register r = static_cast<Register>(i);
-    // We use ldr instead of the Pop macro because we will be popping the PP
-    // register when it is not holding a pool-pointer since we are returning to
-    // C++ code. We also skip the dart stack pointer SP, since we are still
-    // using it as the stack pointer.
-    __ ldr(r, Address(SP, 1 * target::kWordSize, Address::PostIndex));
-  }
+  __ PopNativeCalleeSavedRegisters();
 
   // Restore the frame pointer and C stack pointer and return.
   __ LeaveFrame();
@@ -1806,7 +1801,7 @@
     // ensure that the object is in new-space or has remembered bit set.
     EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
   }
-  __ LeaveStubFrame();                  // Restores correct SP.
+  __ LeaveStubFrame();  // Restores correct SP.
   __ ret();
 }
 
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index 806c130..f7fdf98 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -140,20 +140,61 @@
 
 void StubCodeCompiler::GenerateEnterSafepointStub(Assembler* assembler) {
   __ pushal();
+  __ subl(SPREG, Immediate(8));
+  __ movsd(Address(SPREG, 0), XMM0);
+
+  __ EnterFrame(0);
+  __ ReserveAlignedFrameSpace(0);
   __ movl(EAX, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
   __ call(EAX);
+  __ LeaveFrame();
+
+  __ movsd(XMM0, Address(SPREG, 0));
+  __ addl(SPREG, Immediate(8));
   __ popal();
   __ ret();
 }
 
 void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
   __ pushal();
+  __ subl(SPREG, Immediate(8));
+  __ movsd(Address(SPREG, 0), XMM0);
+
+  __ EnterFrame(0);
+  __ ReserveAlignedFrameSpace(0);
   __ movl(EAX, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
   __ call(EAX);
+  __ LeaveFrame();
+
+  __ movsd(XMM0, Address(SPREG, 0));
+  __ addl(SPREG, Immediate(8));
   __ popal();
   __ ret();
 }
 
+void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
+  __ EnterFrame(0);
+  __ ReserveAlignedFrameSpace(0);
+
+  // The return address needs to be the second argument to
+  // VerifyCallbackIsolate.
+  __ movl(EAX, Address(FPREG, 4));
+  __ pushl(EAX);
+
+  // Argument to the stub is callback ID, which is also the first argument to
+  // VerifyCallbackIsolate.
+  __ movl(EAX, Address(FPREG, 8));
+  __ pushl(EAX);
+
+  // Call the VerifyCallbackIsolate runtime entry.
+  __ movl(EAX,
+          Address(THR, kVerifyCallbackIsolateRuntimeEntry.OffsetFromThread()));
+  __ call(EAX);
+
+  __ LeaveFrame();
+  __ ret();
+}
+
 void StubCodeCompiler::GenerateNullErrorSharedWithoutFPURegsStub(
     Assembler* assembler) {
   __ Breakpoint();
@@ -858,6 +899,10 @@
   __ movl(Address(THR, target::Thread::top_exit_frame_info_offset()),
           Immediate(0));
 
+  // In debug mode, verify that we've pushed the top exit frame info at the
+  // correct offset from FP.
+  __ EmitEntryFrameVerification();
+
   // Mark that the thread is executing Dart code. Do this after initializing the
   // exit link for the profiler.
   __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index 91728ca..92836b2 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -204,8 +204,13 @@
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers.cpu_registers(),
                    all_registers.fpu_registers());
+
+  __ EnterFrame(0);
+  __ ReserveAlignedFrameSpace(0);
   __ movq(RAX, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
   __ CallCFunction(RAX);
+  __ LeaveFrame();
+
   __ PopRegisters(all_registers.cpu_registers(), all_registers.fpu_registers());
   __ ret();
 }
@@ -215,12 +220,31 @@
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers.cpu_registers(),
                    all_registers.fpu_registers());
+
+  __ EnterFrame(0);
+  __ ReserveAlignedFrameSpace(0);
   __ movq(RAX, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
   __ CallCFunction(RAX);
+  __ LeaveFrame();
+
   __ PopRegisters(all_registers.cpu_registers(), all_registers.fpu_registers());
   __ ret();
 }
 
+void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
+  // SP points to return address, which needs to be the second argument to
+  // VerifyCallbackIsolate.
+  __ movq(CallingConventions::kArg2Reg, Address(SPREG, 0));
+
+  __ EnterFrame(0);
+  __ ReserveAlignedFrameSpace(0);
+  __ movq(RAX,
+          Address(THR, kVerifyCallbackIsolateRuntimeEntry.OffsetFromThread()));
+  __ CallCFunction(RAX);
+  __ LeaveFrame();
+  __ ret();
+}
+
 // RBX: The extracted method.
 // RDX: The type_arguments_field_offset (or 0)
 void StubCodeCompiler::GenerateBuildMethodExtractorStub(
@@ -1086,19 +1110,8 @@
   __ pushq(RAX);
 
   // The constant target::frame_layout.exit_link_slot_from_entry_fp must be kept
-  // in sync with the code below.
-#if defined(DEBUG)
-  {
-    Label ok;
-    __ leaq(RAX,
-            Address(RBP, target::frame_layout.exit_link_slot_from_entry_fp *
-                             target::kWordSize));
-    __ cmpq(RAX, RSP);
-    __ j(EQUAL, &ok);
-    __ Stop("target::frame_layout.exit_link_slot_from_entry_fp mismatch");
-    __ Bind(&ok);
-  }
-#endif
+  // in sync with the code above.
+  __ EmitEntryFrameVerification();
 
   __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()),
           Immediate(0));
@@ -1762,7 +1775,7 @@
   // Create a stub frame.
   __ EnterStubFrame();  // Uses PP to access class object.
 
-  __ pushq(R9);         // Setup space on stack for return value.
+  __ pushq(R9);  // Setup space on stack for return value.
   __ PushObject(
       CastHandle<Object>(cls));  // Push class of object to be allocated.
   if (is_cls_parameterized) {
diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc
index d10c8c4..8bf0e39 100644
--- a/runtime/vm/compiler_test.cc
+++ b/runtime/vm/compiler_test.cc
@@ -16,19 +16,6 @@
 
 namespace dart {
 
-ISOLATE_UNIT_TEST_CASE(CompileScript) {
-  const char* kScriptChars =
-      "class A {\n"
-      "  static foo() { return 42; }\n"
-      "}\n";
-  String& url = String::Handle(String::New("dart-test:CompileScript"));
-  String& source = String::Handle(String::New(kScriptChars));
-  Script& script =
-      Script::Handle(Script::New(url, source, RawScript::kScriptTag));
-  Library& lib = Library::Handle(Library::CoreLibrary());
-  EXPECT(CompilerTest::TestCompileScript(lib, script));
-}
-
 ISOLATE_UNIT_TEST_CASE(CompileFunction) {
   const char* kScriptChars =
       "class A {\n"
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index 8a26be6..529d96c 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -749,7 +749,7 @@
   // Maximum bytecode format version supported by VM.
   // The range of supported versions should include version produced by bytecode
   // generator (currentBytecodeFormatVersion in pkg/vm/lib/bytecode/dbc.dart).
-  static const intptr_t kMaxSupportedBytecodeFormatVersion = 7;
+  static const intptr_t kMaxSupportedBytecodeFormatVersion = 9;
 
   enum Opcode {
 #define DECLARE_BYTECODE(name, encoding, kind, op1, op2, op3) k##name,
@@ -971,20 +971,12 @@
     }
   }
 
-  DART_FORCE_INLINE static bool IsCallOpcode(const KBCInstr* instr) {
+  DART_FORCE_INLINE static bool IsCallOpcode_Old(const KBCInstr* instr) {
     switch (DecodeOpcode(instr)) {
       case KernelBytecode::kDirectCall_Old:
       case KernelBytecode::kInterfaceCall_Old:
       case KernelBytecode::kUncheckedInterfaceCall_Old:
       case KernelBytecode::kDynamicCall_Old:
-      case KernelBytecode::kDirectCall:
-      case KernelBytecode::kDirectCall_Wide:
-      case KernelBytecode::kInterfaceCall:
-      case KernelBytecode::kInterfaceCall_Wide:
-      case KernelBytecode::kUncheckedInterfaceCall:
-      case KernelBytecode::kUncheckedInterfaceCall_Wide:
-      case KernelBytecode::kDynamicCall:
-      case KernelBytecode::kDynamicCall_Wide:
         return true;
 
       default:
@@ -1014,7 +1006,7 @@
       // to new _GrowableList<E>(0).
       return kNativeCallToGrowableListArgc;
     }
-    ASSERT(IsCallOpcode(call));
+    ASSERT(IsCallOpcode_Old(call));
     return DecodeA(call);
   }
 
@@ -1030,6 +1022,7 @@
 
   // Converts bytecode PC into an offset.
   // For return addresses used in PcDescriptors, PC is also augmented by 1.
+  // TODO(regis): Eliminate this correction.
   static intptr_t BytecodePcToOffset(uint32_t pc, bool is_return_address) {
     return pc + (is_return_address ? 1 : 0);
   }
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 822cab8..bf929e9 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -6,6 +6,8 @@
 
 #include "vm/clustered_snapshot.h"
 #include "vm/code_observers.h"
+#include "vm/compiler/runtime_offsets_extracted.h"
+#include "vm/compiler/runtime_offsets_list.h"
 #include "vm/cpu.h"
 #include "vm/dart_api_state.h"
 #include "vm/dart_entry.h"
@@ -22,6 +24,7 @@
 #include "vm/malloc_hooks.h"
 #include "vm/message_handler.h"
 #include "vm/metrics.h"
+#include "vm/native_entry.h"
 #include "vm/object.h"
 #include "vm/object_id_ring.h"
 #include "vm/object_store.h"
@@ -84,36 +87,40 @@
 };
 
 static void CheckOffsets() {
+  // These offsets are embedded in precompiled instructions. We need the
+  // compiler and the runtime to agree.
   bool ok = true;
 #define CHECK_OFFSET(expr, offset)                                             \
   if ((expr) != (offset)) {                                                    \
-    OS::PrintErr("%s got %" Pd " expected %" Pd "\n", #expr, (expr),           \
+    OS::PrintErr("%s got %" Pd ", %s expected %" Pd "\n", #expr,               \
+                 static_cast<intptr_t>(expr), #offset,                         \
                  static_cast<intptr_t>(offset));                               \
     ok = false;                                                                \
   }
 
-#if defined(TARGET_ARCH_ARM)
-  // These offsets are embedded in precompiled instructions. We need simarm
-  // (compiler) and arm (runtime) to agree.
-  CHECK_OFFSET(Thread::stack_limit_offset(), 36);
-  CHECK_OFFSET(Thread::object_null_offset(), 96);
-  CHECK_OFFSET(SingleTargetCache::upper_limit_offset(), 14);
-  CHECK_OFFSET(Isolate::object_store_offset(), 20);
-  NOT_IN_PRODUCT(CHECK_OFFSET(sizeof(ClassHeapStats), 168));
-#endif
-#if defined(TARGET_ARCH_ARM64)
-  // These offsets are embedded in precompiled instructions. We need simarm64
-  // (compiler) and arm64 (runtime) to agree.
-  CHECK_OFFSET(Thread::stack_limit_offset(), 72);
-  CHECK_OFFSET(Thread::object_null_offset(), 184);
-  CHECK_OFFSET(SingleTargetCache::upper_limit_offset(), 26);
-  CHECK_OFFSET(Isolate::object_store_offset(), 40);
-  NOT_IN_PRODUCT(CHECK_OFFSET(sizeof(ClassHeapStats), 288));
-#endif
+#define CHECK_FIELD(Class, Name) CHECK_OFFSET(Class::Name(), Class##_##Name)
+#define CHECK_ARRAY(Class, Name)                                               \
+  CHECK_OFFSET(Class::ArrayLayout::elements_start_offset(),                    \
+               Class##_elements_start_offset)                                  \
+  CHECK_OFFSET(Class::ArrayLayout::kElementSize, Class##_element_size)
+#define CHECK_ARRAY_STRUCTFIELD(Class, Name, ElementOffsetName, FieldOffset)
+#define CHECK_SIZEOF(Class, Name, What)                                        \
+  CHECK_OFFSET(sizeof(What), Class##_##Name)
+#define CHECK_RANGE(Class, Name, Type, First, Last, Filter)
+#define CHECK_CONSTANT(Class, Name) CHECK_OFFSET(Class::Name, Class##_##Name)
+
+  OFFSETS_LIST(CHECK_FIELD, CHECK_ARRAY, CHECK_ARRAY_STRUCTFIELD, CHECK_SIZEOF,
+               CHECK_RANGE, CHECK_CONSTANT, NOT_IN_PRECOMPILED_RUNTIME)
 
   if (!ok) {
     FATAL("CheckOffsets failed.");
   }
+#undef CHECK_FIELD
+#undef CHECK_ARRAY
+#undef CHECK_ARRAY_STRUCTFIELD
+#undef CHECK_SIZEOF
+#undef CHECK_RANGE
+#undef CHECK_CONSTANT
 #undef CHECK_OFFSET
 }
 
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 7f7a646..55eb9ba 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -17,6 +17,8 @@
 #include "vm/dart_api_state.h"
 #include "vm/dart_entry.h"
 #include "vm/debugger.h"
+#include "vm/dwarf.h"
+#include "vm/elf.h"
 #if !defined(DART_PRECOMPILED_RUNTIME)
 #include "vm/kernel_loader.h"
 #endif
@@ -5532,7 +5534,7 @@
                      const char* package_config) {
   API_TIMELINE_DURATION(Thread::Current());
 
-  Dart_KernelCompilationResult result;
+  Dart_KernelCompilationResult result = {};
 #if defined(DART_PRECOMPILED_RUNTIME)
   result.status = Dart_KernelCompilationStatus_Unknown;
   result.error = strdup("Dart_CompileToKernel is unsupported.");
@@ -5564,7 +5566,7 @@
                             const char* package_config,
                             const char* multiroot_filepaths,
                             const char* multiroot_scheme) {
-  Dart_KernelCompilationResult result;
+  Dart_KernelCompilationResult result = {};
 #if defined(DART_PRECOMPILED_RUNTIME)
   result.status = Dart_KernelCompilationStatus_Unknown;
   result.error = strdup("Dart_CompileSourcesToKernel is unsupported.");
@@ -5586,7 +5588,7 @@
 }
 
 DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies() {
-  Dart_KernelCompilationResult result;
+  Dart_KernelCompilationResult result = {};
 #if defined(DART_PRECOMPILED_RUNTIME)
   result.status = Dart_KernelCompilationStatus_Unknown;
   result.error = strdup("Dart_KernelListDependencies is unsupported.");
@@ -6050,10 +6052,11 @@
   CHECK_NULL(callback);
 
   TIMELINE_DURATION(T, Isolate, "WriteVMAOTSnapshot");
-  AssemblyImageWriter image_writer(T, callback, callback_data, NULL, NULL);
-  uint8_t* vm_snapshot_data_buffer = NULL;
-  FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer, NULL,
-                            ApiReallocate, &image_writer, NULL);
+  AssemblyImageWriter image_writer(T, callback, callback_data, nullptr,
+                                   nullptr);
+  uint8_t* vm_snapshot_data_buffer = nullptr;
+  FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
+                            nullptr, ApiReallocate, &image_writer, nullptr);
 
   writer.WriteFullSnapshot();
 
@@ -6062,6 +6065,60 @@
 }
 
 DART_EXPORT Dart_Handle
+Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback,
+                               void* callback_data) {
+#if defined(TARGET_ARCH_IA32)
+  return Api::NewError("AOT compilation is not supported on IA32.");
+#elif defined(TARGET_ARCH_DBC)
+  return Api::NewError("AOT compilation is not supported on DBC.");
+#elif defined(TARGET_OS_WINDOWS)
+  return Api::NewError("Windows cannot load ELF.");
+#elif defined(TARGET_OS_MACOS)
+  return Api::NewError("macOS/iOS cannot load ELF.");
+#elif !defined(DART_PRECOMPILER)
+  return Api::NewError(
+      "This VM was built without support for AOT compilation.");
+#else
+  DARTSCOPE(Thread::Current());
+  API_TIMELINE_DURATION(T);
+
+  uint8_t* vm_snapshot_data_buffer = nullptr;
+  uint8_t* vm_snapshot_instructions_buffer = nullptr;
+  uint8_t* isolate_snapshot_data_buffer = nullptr;
+  uint8_t* isolate_snapshot_instructions_buffer = nullptr;
+
+  NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
+                                            "WriteAppAOTSnapshot"));
+  StreamingWriteStream elf_stream(2 * MB, callback, callback_data);
+  Elf* elf = new (Z) Elf(Z, &elf_stream);
+  Dwarf* dwarf = new (Z) Dwarf(Z, nullptr, elf);
+
+  BlobImageWriter vm_image_writer(T, &vm_snapshot_instructions_buffer,
+                                  ApiReallocate, /* initial_size= */ 2 * MB,
+                                  nullptr, nullptr, nullptr, elf, dwarf);
+  BlobImageWriter isolate_image_writer(
+      T, &isolate_snapshot_instructions_buffer, ApiReallocate,
+      /* initial_size= */ 2 * MB, /* shared_data_image= */ nullptr,
+      /* shared_instructions_image= */ nullptr, nullptr, elf, dwarf);
+  FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
+                            &isolate_snapshot_data_buffer, ApiReallocate,
+                            &vm_image_writer, &isolate_image_writer);
+
+  writer.WriteFullSnapshot();
+  elf->AddROData("_kDartVmSnapshotData", vm_snapshot_data_buffer,
+                 writer.VmIsolateSnapshotSize());
+  elf->AddROData("_kDartIsolateSnapshotData", isolate_snapshot_data_buffer,
+                 writer.IsolateSnapshotSize());
+  // TODO(rmacnak): Generate .debug_frame / .eh_frame / .arm.exidx to
+  // providing unwinding information.
+  dwarf->Write();
+  elf->Finalize();
+
+  return Api::Success();
+#endif
+}
+
+DART_EXPORT Dart_Handle
 Dart_CreateAppAOTSnapshotAsBlobs(uint8_t** vm_snapshot_data_buffer,
                                  intptr_t* vm_snapshot_data_size,
                                  uint8_t** vm_snapshot_instructions_buffer,
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 0682bb9..a8c490b 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -3629,56 +3629,6 @@
   return Dart_LoadScriptFromKernel(kernel_buffer, kernel_buffer_size);
 }
 
-VM_UNIT_TEST_CASE(DartAPI_IsolateSetCheckedMode) {
-  const char* kScriptChars =
-      "int bad1() {\n"
-      "  int foo = 'string';\n"
-      "  return foo;\n"
-      "}\n"
-      "\n"
-      "int good1() {\n"
-      "  int five = 5;\n"
-      "  return five;"
-      "}\n";
-
-  // Create an isolate with checked mode flags.
-  Dart_IsolateFlags api_flags;
-  Isolate::FlagsInitialize(&api_flags);
-  api_flags.enable_asserts = true;
-  char* err;
-  Dart_Isolate isolate =
-      Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data,
-                         bin::core_isolate_snapshot_instructions, NULL, NULL,
-                         &api_flags, NULL, &err);
-  if (isolate == NULL) {
-    OS::PrintErr("Creation of isolate failed '%s'\n", err);
-    free(err);
-  }
-  EXPECT(isolate != NULL);
-
-  {
-    Dart_Handle result;
-    Dart_EnterScope();
-    Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
-    EXPECT_VALID(lib);
-    result = Dart_FinalizeLoading(false);
-    EXPECT_VALID(result);
-    result = Dart_Invoke(lib, NewString("bad1"), 0, NULL);
-    EXPECT_ERROR(result,
-                 "Unhandled exception:\n"
-                 "type 'String' is not a subtype of type 'int' of 'foo'");
-
-    result = Dart_Invoke(lib, NewString("good1"), 0, NULL);
-    EXPECT_VALID(result);
-    Dart_ExitScope();
-  }
-
-  EXPECT(isolate != NULL);
-
-  // Shutdown the isolate.
-  Dart_ShutdownIsolate();
-}
-
 TEST_CASE(DartAPI_DebugName) {
   Dart_Handle debug_name = Dart_DebugName();
   EXPECT_VALID(debug_name);
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index a4c22c3..4bd384c 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -377,22 +377,6 @@
   return names.raw();
 }
 
-intptr_t ArgumentsDescriptor::type_args_len_offset() {
-  return Array::element_offset(kTypeArgsLenIndex);
-}
-
-intptr_t ArgumentsDescriptor::count_offset() {
-  return Array::element_offset(kCountIndex);
-}
-
-intptr_t ArgumentsDescriptor::positional_count_offset() {
-  return Array::element_offset(kPositionalCountIndex);
-}
-
-intptr_t ArgumentsDescriptor::first_named_entry_offset() {
-  return Array::element_offset(kFirstNamedEntryIndex);
-}
-
 RawArray* ArgumentsDescriptor::New(intptr_t type_args_len,
                                    intptr_t num_arguments,
                                    const Array& optional_arguments_names) {
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 23342d3..94764a3 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -49,10 +49,20 @@
   RawArray* GetArgumentNames() const;
 
   // Generated code support.
-  static intptr_t type_args_len_offset();
-  static intptr_t count_offset();
-  static intptr_t positional_count_offset();
-  static intptr_t first_named_entry_offset();
+  static intptr_t type_args_len_offset() {
+    return Array::element_offset(kTypeArgsLenIndex);
+  }
+
+  static intptr_t count_offset() { return Array::element_offset(kCountIndex); }
+
+  static intptr_t positional_count_offset() {
+    return Array::element_offset(kPositionalCountIndex);
+  }
+
+  static intptr_t first_named_entry_offset() {
+    return Array::element_offset(kFirstNamedEntryIndex);
+  }
+
   static intptr_t name_offset() { return kNameOffset * kWordSize; }
   static intptr_t position_offset() { return kPositionOffset * kWordSize; }
   static intptr_t named_entry_size() { return kNamedEntrySize * kWordSize; }
diff --git a/runtime/vm/dart_entry_test.cc b/runtime/vm/dart_entry_test.cc
deleted file mode 100644
index 496c1a0..0000000
--- a/runtime/vm/dart_entry_test.cc
+++ /dev/null
@@ -1,107 +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.
-
-#include "platform/globals.h"
-
-#include "platform/assert.h"
-#include "vm/class_finalizer.h"
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/dart_entry.h"
-#include "vm/object.h"
-#include "vm/resolver.h"
-#include "vm/symbols.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-ISOLATE_UNIT_TEST_CASE(DartEntry) {
-  const char* kScriptChars =
-      "class A {\n"
-      "  static foo() { return 42; }\n"
-      "}\n";
-  String& url = String::Handle(String::New("dart-test:DartEntry"));
-  String& source = String::Handle(String::New(kScriptChars));
-  Script& script =
-      Script::Handle(Script::New(url, source, RawScript::kScriptTag));
-  Library& lib = Library::Handle(Library::CoreLibrary());
-  EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
-  EXPECT(ClassFinalizer::ProcessPendingClasses());
-  Class& cls =
-      Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
-  EXPECT(!cls.IsNull());  // No ambiguity error expected.
-  String& name = String::Handle(String::New("foo"));
-  Function& function = Function::Handle(cls.LookupStaticFunction(name));
-  EXPECT(!function.IsNull());
-
-  EXPECT(CompilerTest::TestCompileFunction(function));
-  EXPECT(function.HasCode());
-  const Smi& retval = Smi::Handle(reinterpret_cast<RawSmi*>(
-      DartEntry::InvokeFunction(function, Object::empty_array())));
-  EXPECT_EQ(Smi::New(42), retval.raw());
-}
-
-ISOLATE_UNIT_TEST_CASE(InvokeStatic_CompileError) {
-  const char* kScriptChars =
-      "class A {\n"
-      "  static foo() { return ++++; }\n"
-      "}\n";
-  String& url = String::Handle(String::New("dart-test:DartEntry"));
-  String& source = String::Handle(String::New(kScriptChars));
-  Script& script =
-      Script::Handle(Script::New(url, source, RawScript::kScriptTag));
-  Library& lib = Library::Handle(Library::CoreLibrary());
-  EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
-  EXPECT(ClassFinalizer::ProcessPendingClasses());
-  Class& cls =
-      Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
-  EXPECT(!cls.IsNull());  // No ambiguity error expected.
-  String& name = String::Handle(String::New("foo"));
-  Function& function = Function::Handle(cls.LookupStaticFunction(name));
-  EXPECT(!function.IsNull());
-  const Object& retval = Object::Handle(
-      DartEntry::InvokeFunction(function, Object::empty_array()));
-  EXPECT(retval.IsError());
-  EXPECT_SUBSTRING("++++", Error::Cast(retval).ToErrorCString());
-}
-
-ISOLATE_UNIT_TEST_CASE(InvokeDynamic_CompileError) {
-  const char* kScriptChars =
-      "class A {\n"
-      "  foo() { return ++++; }\n"
-      "}\n";
-  String& url = String::Handle(String::New("dart-test:DartEntry"));
-  String& source = String::Handle(String::New(kScriptChars));
-  Script& script =
-      Script::Handle(Script::New(url, source, RawScript::kScriptTag));
-  Library& lib = Library::Handle(Library::CoreLibrary());
-  EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
-  EXPECT(ClassFinalizer::ProcessPendingClasses());
-  Class& cls =
-      Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
-  EXPECT(!cls.IsNull());  // No ambiguity error expected.
-
-  // Invoke the constructor.
-  const Instance& instance = Instance::Handle(Instance::New(cls));
-  const Array& constructor_arguments = Array::Handle(Array::New(1));
-  constructor_arguments.SetAt(0, instance);
-  String& constructor_name = String::Handle(Symbols::New(thread, "A."));
-  Function& constructor =
-      Function::Handle(cls.LookupConstructor(constructor_name));
-  ASSERT(!constructor.IsNull());
-  DartEntry::InvokeFunction(constructor, constructor_arguments);
-
-  // Call foo.
-  String& name = String::Handle(String::New("foo"));
-  Function& function = Function::Handle(cls.LookupDynamicFunction(name));
-  EXPECT(!function.IsNull());
-  const Array& args = Array::Handle(Array::New(1));
-  args.SetAt(0, instance);
-  const Object& retval =
-      Object::Handle(DartEntry::InvokeFunction(function, args));
-  EXPECT(retval.IsError());
-  EXPECT_SUBSTRING("++++", Error::Cast(retval).ToErrorCString());
-}
-
-}  // namespace dart
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 13e4621..639314f 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -10,6 +10,7 @@
 
 #include "vm/code_patcher.h"
 #include "vm/compiler/assembler/disassembler.h"
+#include "vm/compiler/frontend/bytecode_reader.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/dart_entry.h"
 #include "vm/deopt_instructions.h"
@@ -66,14 +67,13 @@
       url_(script.url()),
       token_pos_(token_pos),
       end_token_pos_(end_token_pos),
-      is_resolved_(false),
       next_(NULL),
       conditions_(NULL),
       requested_line_number_(requested_line_number),
       requested_column_number_(requested_column_number),
       function_(Function::null()),
-      line_number_(-1),
-      column_number_(-1) {
+      bytecode_token_pos_(TokenPosition::kNoSource),
+      code_token_pos_(TokenPosition::kNoSource) {
   ASSERT(!script.IsNull());
   ASSERT(token_pos_.IsReal());
 }
@@ -86,14 +86,13 @@
       url_(url.raw()),
       token_pos_(TokenPosition::kNoSource),
       end_token_pos_(TokenPosition::kNoSource),
-      is_resolved_(false),
       next_(NULL),
       conditions_(NULL),
       requested_line_number_(requested_line_number),
       requested_column_number_(requested_column_number),
       function_(Function::null()),
-      line_number_(-1),
-      column_number_(-1) {
+      bytecode_token_pos_(TokenPosition::kNoSource),
+      code_token_pos_(TokenPosition::kNoSource) {
   ASSERT(requested_line_number_ >= 0);
 }
 
@@ -110,7 +109,8 @@
   return breakpoints() != NULL;
 }
 
-void BreakpointLocation::SetResolved(const Function& func,
+void BreakpointLocation::SetResolved(bool in_bytecode,
+                                     const Function& func,
                                      TokenPosition token_pos) {
   ASSERT(!IsLatent());
   ASSERT(func.script() == script_);
@@ -120,53 +120,25 @@
   function_ = func.raw();
   token_pos_ = token_pos;
   end_token_pos_ = token_pos;
-  is_resolved_ = true;
+  if (in_bytecode) {
+    bytecode_token_pos_ = token_pos;
+  } else {
+    code_token_pos_ = token_pos;
+  }
 }
 
-// TODO(hausner): Get rid of library parameter. A source breakpoint location
-// does not imply a library, since the same source code can be included
-// in more than one library, e.g. the text location of mixin functions.
-void BreakpointLocation::GetCodeLocation(Library* lib,
-                                         Script* script,
+// Returned resolved pos is either in code or in bytecode.
+void BreakpointLocation::GetCodeLocation(Script* script,
                                          TokenPosition* pos) const {
   if (IsLatent()) {
-    *lib = Library::null();
     *script = Script::null();
     *pos = TokenPosition::kNoSource;
   } else {
     *script = this->script();
     *pos = token_pos_;
-    if (IsResolved()) {
-      const Function& func = Function::Handle(function_);
-      ASSERT(!func.IsNull());
-      const Class& cls = Class::Handle(func.origin());
-      *lib = cls.library();
-    } else {
-      *lib = Library::null();
-    }
   }
 }
 
-intptr_t BreakpointLocation::LineNumber() {
-  ASSERT(IsResolved());
-  // Compute line number lazily since it causes scanning of the script.
-  if (line_number_ < 0) {
-    const Script& script = Script::Handle(this->script());
-    script.GetTokenLocation(token_pos_, &line_number_, NULL);
-  }
-  return line_number_;
-}
-
-intptr_t BreakpointLocation::ColumnNumber() {
-  ASSERT(IsResolved());
-  // Compute column number lazily since it causes scanning of the script.
-  if (column_number_ < 0) {
-    const Script& script = Script::Handle(this->script());
-    script.GetTokenLocation(token_pos_, &line_number_, &column_number_);
-  }
-  return column_number_;
-}
-
 void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) {
   // Only latent breakpoints can be moved.
   ASSERT((new_bpt_location == NULL) || bpt_location_->IsLatent());
@@ -208,6 +180,7 @@
 
 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_));
+  visitor->VisitPointer(reinterpret_cast<RawObject**>(&bytecode_));
 #if !defined(TARGET_ARCH_DBC)
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&saved_value_));
 #endif
@@ -225,6 +198,7 @@
       sp_(sp),
       ctx_(Context::ZoneHandle()),
       code_(Code::ZoneHandle(code.raw())),
+      bytecode_(Bytecode::ZoneHandle()),
       function_(Function::ZoneHandle(code.function())),
       live_frame_((kind == kRegular) || (kind == kAsyncActivation)),
       token_pos_initialized_(false),
@@ -237,11 +211,44 @@
       deopt_frame_(Array::ZoneHandle(deopt_frame.raw())),
       deopt_frame_offset_(deopt_frame_offset),
       kind_(kind),
-      is_interpreted_(false),  // TODO(regis): No bytecode debugging support.
       vars_initialized_(false),
       var_descriptors_(LocalVarDescriptors::ZoneHandle()),
       desc_indices_(8),
-      pc_desc_(PcDescriptors::ZoneHandle()) {}
+      pc_desc_(PcDescriptors::ZoneHandle()) {
+  ASSERT(!function_.IsNull());
+}
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ActivationFrame::ActivationFrame(uword pc,
+                                 uword fp,
+                                 uword sp,
+                                 const Bytecode& bytecode,
+                                 ActivationFrame::Kind kind)
+    : pc_(pc),
+      fp_(fp),
+      sp_(sp),
+      ctx_(Context::ZoneHandle()),
+      code_(Code::ZoneHandle()),
+      bytecode_(Bytecode::ZoneHandle(bytecode.raw())),
+      function_(Function::ZoneHandle(bytecode.function())),
+      live_frame_((kind == kRegular) || (kind == kAsyncActivation)),
+      token_pos_initialized_(false),
+      token_pos_(TokenPosition::kNoSource),
+      try_index_(-1),
+      deopt_id_(DeoptId::kNone),
+      line_number_(-1),
+      column_number_(-1),
+      context_level_(-1),
+      deopt_frame_(Array::ZoneHandle()),
+      deopt_frame_offset_(0),
+      kind_(kind),
+      vars_initialized_(false),
+      var_descriptors_(LocalVarDescriptors::ZoneHandle()),
+      desc_indices_(8),
+      pc_desc_(PcDescriptors::ZoneHandle()) {
+  ASSERT(!function_.IsNull());  // Frames with bytecode stubs should be skipped.
+}
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 ActivationFrame::ActivationFrame(Kind kind)
     : pc_(0),
@@ -249,6 +256,7 @@
       sp_(0),
       ctx_(Context::ZoneHandle()),
       code_(Code::ZoneHandle()),
+      bytecode_(Bytecode::ZoneHandle()),
       function_(Function::ZoneHandle()),
       live_frame_(kind == kRegular),
       token_pos_initialized_(false),
@@ -260,7 +268,6 @@
       deopt_frame_(Array::ZoneHandle()),
       deopt_frame_offset_(0),
       kind_(kind),
-      is_interpreted_(false),
       vars_initialized_(false),
       var_descriptors_(LocalVarDescriptors::ZoneHandle()),
       desc_indices_(8),
@@ -272,6 +279,7 @@
       sp_(0),
       ctx_(Context::ZoneHandle()),
       code_(Code::ZoneHandle()),
+      bytecode_(Bytecode::ZoneHandle()),
       function_(Function::ZoneHandle()),
       live_frame_(false),
       token_pos_initialized_(false),
@@ -283,15 +291,21 @@
       deopt_frame_(Array::ZoneHandle()),
       deopt_frame_offset_(0),
       kind_(kAsyncActivation),
-      is_interpreted_(false),
       vars_initialized_(false),
       var_descriptors_(LocalVarDescriptors::ZoneHandle()),
       desc_indices_(8),
       pc_desc_(PcDescriptors::ZoneHandle()) {
   // Extract the function and the code from the asynchronous activation.
   function_ = async_activation.function();
-  function_.EnsureHasCompiledUnoptimizedCode();
-  code_ = function_.unoptimized_code();
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  if (!function_.HasCode() && function_.HasBytecode()) {
+    bytecode_ = function_.bytecode();
+  }
+#endif
+  if (bytecode_.IsNull()) {
+    function_.EnsureHasCompiledUnoptimizedCode();
+    code_ = function_.unoptimized_code();
+  }
   ctx_ = async_activation.context();
   ASSERT(fp_ == 0);
   ASSERT(!ctx_.IsNull());
@@ -462,7 +476,7 @@
 }
 
 bool Debugger::HasBreakpoint(const Function& func, Zone* zone) {
-  if (!func.HasCode()) {
+  if (!func.HasCode() && !func.HasBytecode()) {
     // If the function is not compiled yet, just check whether there
     // is a user-defined breakpoint that falls into the token
     // range of the function. This may be a false positive: the breakpoint
@@ -553,20 +567,26 @@
 }
 
 void ActivationFrame::GetPcDescriptors() {
+  ASSERT(!IsInterpreted());  // We need to set try_index_ simultaneously.
   if (pc_desc_.IsNull()) {
     pc_desc_ = code().pc_descriptors();
     ASSERT(!pc_desc_.IsNull());
   }
 }
 
-// Compute token_pos_ and try_index_ and token_pos_initialized_.
+// Compute token_pos_ and token_pos_initialized_.
+// If not IsInterpreted(), then also compute try_index_ and deopt_id_.
 TokenPosition ActivationFrame::TokenPos() {
   if (!token_pos_initialized_) {
     token_pos_initialized_ = true;
+    if (IsInterpreted()) {
+      token_pos_ = bytecode().GetTokenIndexOfPC(pc_);
+      return token_pos_;
+    }
     token_pos_ = TokenPosition::kNoSource;
     GetPcDescriptors();
     PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind);
-    uword pc_offset = pc_ - code().PayloadStart();
+    const uword pc_offset = pc_ - code().PayloadStart();
     while (iter.MoveNext()) {
       if (iter.PcOffset() == pc_offset) {
         try_index_ = iter.TryIndex();
@@ -580,6 +600,16 @@
 }
 
 intptr_t ActivationFrame::TryIndex() {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  if (IsInterpreted()) {
+    if (pc_desc_.IsNull()) {
+      ASSERT(try_index_ == -1);
+      pc_desc_ = bytecode().pc_descriptors();
+      try_index_ = bytecode().GetTryIndexAtPc(pc_);
+    }
+    return try_index_;
+  }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
   if (!token_pos_initialized_) {
     TokenPos();  // Side effect: computes token_pos_initialized_, try_index_.
   }
@@ -587,6 +617,7 @@
 }
 
 intptr_t ActivationFrame::DeoptId() {
+  ASSERT(!IsInterpreted());
   if (!token_pos_initialized_) {
     TokenPos();  // Side effect: computes token_pos_initialized_, try_index_.
   }
@@ -619,7 +650,7 @@
 
 void ActivationFrame::GetVarDescriptors() {
   if (var_descriptors_.IsNull()) {
-    if (is_interpreted()) {
+    if (IsInterpreted()) {
       // TODO(regis): Kernel bytecode does not yet provide var descriptors.
       var_descriptors_ = Object::empty_var_descriptors().raw();
       return;
@@ -652,8 +683,13 @@
   OS::PrintErr("deopt_id_ %" Px "\n", deopt_id_);
   OS::PrintErr("context_level_ %" Px "\n", context_level_);
   DisassembleToStdout formatter;
-  code().Disassemble(&formatter);
-  PcDescriptors::Handle(code().pc_descriptors()).Print();
+  if (IsInterpreted()) {
+    bytecode().Disassemble(&formatter);
+    PcDescriptors::Handle(bytecode().pc_descriptors()).Print();
+  } else {
+    code().Disassemble(&formatter);
+    PcDescriptors::Handle(code().pc_descriptors()).Print();
+  }
   StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
                             Thread::Current(),
                             StackFrameIterator::kNoCrossThreadIteration);
@@ -667,6 +703,9 @@
 
 // Calculate the context level at the current token index of the frame.
 intptr_t ActivationFrame::ContextLevel() {
+  // TODO(regis): get context level information using
+  //  BytecodeLocalVariablesIterator for interpreted frames and compiled frames
+  //  with a function coming from bytecode (function.is_declared_in_bytecode())
   const Context& ctx = GetSavedCurrentContext();
   if (context_level_ < 0 && !ctx.IsNull()) {
     ASSERT(!code_.is_optimized());
@@ -808,7 +847,11 @@
   AbstractType& type = Type::Handle();
   const bool is_async =
       function().IsAsyncClosure() || function().IsAsyncGenClosure();
-  handlers = code().exception_handlers();
+  if (IsInterpreted()) {
+    handlers = bytecode().exception_handlers();
+  } else {
+    handlers = code().exception_handlers();
+  }
   ASSERT(!handlers.IsNull());
   intptr_t num_handlers_checked = 0;
   while (try_index != kInvalidTryIndex) {
@@ -840,6 +883,10 @@
 
 void ActivationFrame::ExtractTokenPositionFromAsyncClosure() {
   // Attempt to determine the token position from the async closure.
+  if (IsInterpreted()) {
+    // TODO(regis): Implement.
+    return;
+  }
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   const Script& script = Script::Handle(zone, function().script());
@@ -1436,7 +1483,11 @@
   const TokenPosition pos = TokenPos().SourcePosition();
   jsobj->AddLocation(script, pos);
   jsobj->AddProperty("function", function());
-  jsobj->AddProperty("code", code());
+  if (IsInterpreted()) {
+    jsobj->AddProperty("bytecode", bytecode());
+  } else {
+    jsobj->AddProperty("code", code());
+  }
   {
     JSONArray jsvars(jsobj, "vars");
     const int num_vars = NumLocalVariables();
@@ -1476,7 +1527,11 @@
   const TokenPosition pos = TokenPos().SourcePosition();
   jsobj->AddLocation(script, pos);
   jsobj->AddProperty("function", function());
-  jsobj->AddProperty("code", code());
+  if (IsInterpreted()) {
+    jsobj->AddProperty("bytecode", bytecode());
+  } else {
+    jsobj->AddProperty("code", code());
+  }
 }
 
 void ActivationFrame::PrintToJSONObjectAsyncSuspensionMarker(
@@ -1493,7 +1548,11 @@
   const TokenPosition pos = TokenPos().SourcePosition();
   jsobj->AddLocation(script, pos);
   jsobj->AddProperty("function", function());
-  jsobj->AddProperty("code", code());
+  if (IsInterpreted()) {
+    jsobj->AddProperty("bytecode", bytecode());
+  } else {
+    jsobj->AddProperty("code", code());
+  }
 }
 
 static bool IsFunctionVisible(const Function& function) {
@@ -1516,6 +1575,14 @@
                                  ActivationFrame::kAsyncCausal));
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+void DebuggerStackTrace::AddAsyncCausalFrame(uword pc,
+                                             const Bytecode& bytecode) {
+  trace_.Add(
+      new ActivationFrame(pc, 0, 0, bytecode, ActivationFrame::kAsyncCausal));
+}
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
 const uint8_t kSafepointKind = RawPcDescriptors::kIcCall |
                                RawPcDescriptors::kUnoptStaticCall |
                                RawPcDescriptors::kRuntimeCall;
@@ -1525,6 +1592,7 @@
                                uword pc,
                                RawPcDescriptors::Kind kind)
     : code_(code.raw()),
+      bytecode_(Bytecode::null()),
       token_pos_(token_pos),
       pc_(pc),
       line_number_(-1),
@@ -1545,12 +1613,37 @@
   ASSERT((breakpoint_kind_ & kSafepointKind) != 0);
 }
 
+CodeBreakpoint::CodeBreakpoint(const Bytecode& bytecode,
+                               TokenPosition token_pos,
+                               uword pc)
+    : code_(Code::null()),
+      bytecode_(bytecode.raw()),
+      token_pos_(token_pos),
+      pc_(pc),
+      line_number_(-1),
+      is_enabled_(false),
+      bpt_location_(NULL),
+      next_(NULL),
+      breakpoint_kind_(RawPcDescriptors::kAnyKind),
+#if !defined(TARGET_ARCH_DBC)
+      saved_value_(Code::null())
+#else
+      saved_value_(SimulatorBytecode::kTrap),
+      saved_value_fastsmi_(SimulatorBytecode::kTrap)
+#endif
+{
+  ASSERT(!bytecode.IsNull());
+  ASSERT(token_pos_.IsReal());
+  ASSERT(pc_ != 0);
+}
+
 CodeBreakpoint::~CodeBreakpoint() {
   // Make sure we don't leave patched code behind.
   ASSERT(!IsEnabled());
 // Poison the data so we catch use after free errors.
 #ifdef DEBUG
   code_ = Code::null();
+  bytecode_ = Bytecode::null();
   pc_ = 0ul;
   bpt_location_ = NULL;
   next_ = NULL;
@@ -1559,7 +1652,12 @@
 }
 
 RawFunction* CodeBreakpoint::function() const {
-  return Code::Handle(code_).function();
+  if (IsInterpreted()) {
+    ASSERT(Bytecode::Handle(bytecode_).function() != Function::null());
+    return Bytecode::Handle(bytecode_).function();
+  } else {
+    return Code::Handle(code_).function();
+  }
 }
 
 RawScript* CodeBreakpoint::SourceCode() {
@@ -1583,14 +1681,30 @@
 
 void CodeBreakpoint::Enable() {
   if (!is_enabled_) {
-    PatchCode();
+    if (IsInterpreted()) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+      SetBytecodeBreak();
+#else
+      UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+    } else {
+      PatchCode();
+    }
   }
   ASSERT(is_enabled_);
 }
 
 void CodeBreakpoint::Disable() {
   if (is_enabled_) {
-    RestoreCode();
+    if (IsInterpreted()) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+      UnsetBytecodeBreak();
+#else
+      UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+    } else {
+      RestoreCode();
+    }
   }
   ASSERT(!is_enabled_);
 }
@@ -1818,6 +1932,24 @@
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
+ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
+                                            uword pc,
+                                            StackFrame* frame,
+                                            const Bytecode& bytecode,
+                                            ActivationFrame::Kind kind) {
+  ASSERT(bytecode.ContainsInstructionAt(pc));
+  ActivationFrame* activation =
+      new ActivationFrame(pc, frame->fp(), frame->sp(), bytecode, kind);
+  if (FLAG_trace_debugger_stacktrace) {
+    const Context& ctx = activation->GetSavedCurrentContext();
+    OS::PrintErr("\tUsing saved context: %s\n", ctx.ToCString());
+  }
+  if (FLAG_trace_debugger_stacktrace) {
+    OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber());
+  }
+  return activation;
+}
+
 RawArray* Debugger::DeoptimizeToArray(Thread* thread,
                                       StackFrame* frame,
                                       const Code& code) {
@@ -1850,6 +1982,9 @@
                               Thread::Current(),
                               StackFrameIterator::kNoCrossThreadIteration);
   Code& code = Code::Handle(zone);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  Bytecode& bytecode = Bytecode::Handle(zone);
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
   Code& inlined_code = Code::Handle(zone);
   Array& deopt_frame = Array::Handle(zone);
 
@@ -1862,14 +1997,21 @@
     }
     if (frame->IsDartFrame()) {
       if (frame->is_interpreted()) {
-        // TODO(regis): Support debugging of interpreted frames.
-        // For now, do not abort, but skip the frame, as this code is run
-        // while handling a stack overflow. See HandleStackOverflowTestCases.
-        continue;
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        bytecode = frame->LookupDartBytecode();
+        if (bytecode.function() == Function::null()) {
+          continue;  // Skip bytecode stub frame.
+        }
+        stack_trace->AddActivation(
+            CollectDartFrame(isolate, frame->pc(), frame, bytecode));
+#else
+        UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+      } else {
+        code = frame->LookupDartCode();
+        AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
+                         &inlined_code, &deopt_frame);
       }
-      code = frame->LookupDartCode();
-      AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
-                       &inlined_code, &deopt_frame);
     }
   }
   return stack_trace;
@@ -1917,7 +2059,11 @@
   Isolate* isolate = thread->isolate();
   DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
 
+  Object& code_obj = Object::Handle(zone);
   Code& code = Code::Handle(zone);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  Bytecode& bytecode = Bytecode::Handle(zone);
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
   Smi& offset = Smi::Handle();
   Code& inlined_code = Code::Handle(zone);
   Array& deopt_frame = Array::Handle(zone);
@@ -1949,12 +2095,21 @@
     ASSERT(frame != NULL);
     if (frame->IsDartFrame()) {
       if (frame->is_interpreted()) {
-        // TODO(regis): Support debugging of interpreted frames.
-        UNIMPLEMENTED();
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        bytecode = frame->LookupDartBytecode();
+        if (bytecode.function() == Function::null()) {
+          continue;  // Skip bytecode stub frame.
+        }
+        stack_trace->AddActivation(
+            CollectDartFrame(isolate, frame->pc(), frame, bytecode));
+#else
+        UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+      } else {
+        code = frame->LookupDartCode();
+        AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
+                         &inlined_code, &deopt_frame);
       }
-      code = frame->LookupDartCode();
-      AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
-                       &inlined_code, &deopt_frame);
       synchronous_stack_trace_length--;
     }
     frame = iterator.NextFrame();
@@ -1965,19 +2120,27 @@
   // activated.
   while (!async_stack_trace.IsNull()) {
     for (intptr_t i = 0; i < async_stack_trace.Length(); i++) {
-      if (async_stack_trace.CodeAtFrame(i) == Code::null()) {
+      code_obj = async_stack_trace.CodeAtFrame(i);
+      if (code_obj.IsNull()) {
         break;
       }
-      if (async_stack_trace.CodeAtFrame(i) ==
-          StubCode::AsynchronousGapMarker().raw()) {
+      if (code_obj.raw() == 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
         // the readability of the trace.
         i++;
       } else {
-        code = Code::RawCast(async_stack_trace.CodeAtFrame(i));
         offset = Smi::RawCast(async_stack_trace.PcOffsetAtFrame(i));
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        if (code_obj.IsBytecode()) {
+          bytecode ^= code_obj.raw();
+          uword pc = bytecode.PayloadStart() + offset.Value();
+          stack_trace->AddAsyncCausalFrame(pc, bytecode);
+          continue;
+        }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+        code ^= code_obj.raw();
         uword pc = code.PayloadStart() + offset.Value();
         if (code.is_optimized()) {
           for (InlinedFunctionsIterator it(code, pc); !it.Done();
@@ -2027,6 +2190,7 @@
                               StackFrameIterator::kNoCrossThreadIteration);
 
   Code& code = Code::Handle(zone);
+  Bytecode& bytecode = Bytecode::Handle(zone);
   Smi& offset = Smi::Handle(zone);
   Function& function = Function::Handle(zone);
   Code& inlined_code = Code::Handle(zone);
@@ -2048,73 +2212,11 @@
     }
     if (frame->IsDartFrame()) {
       if (frame->is_interpreted()) {
-        // TODO(regis): Support debugging of interpreted frames.
-        UNIMPLEMENTED();
-      }
-      code = frame->LookupDartCode();
-      if (code.is_optimized()) {
-        deopt_frame = DeoptimizeToArray(thread, frame, code);
-        bool found_async_awaiter = false;
-        bool abort_attempt_to_navigate_through_sync_async = false;
-        for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
-             it.Advance()) {
-          inlined_code = it.code();
-          function = it.function();
-
-          if (skip_sync_async_frames_count > 0) {
-            function_name = function.QualifiedScrubbedName();
-            if (CheckAndSkipAsync(skip_sync_async_frames_count,
-                                  function_name)) {
-              skip_sync_async_frames_count--;
-            } else {
-              // Unexpected function in sync async call
-              skip_sync_async_frames_count = -1;
-              abort_attempt_to_navigate_through_sync_async = true;
-              break;
-            }
-          }
-
-          if (FLAG_trace_debugger_stacktrace) {
-            ASSERT(!function.IsNull());
-            OS::PrintErr(
-                "CollectAwaiterReturnStackTrace: visiting inlined function: "
-                "%s\n",
-                function.ToFullyQualifiedCString());
-          }
-          intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
-          if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
-            ActivationFrame* activation = CollectDartFrame(
-                isolate, it.pc(), frame, inlined_code, deopt_frame,
-                deopt_frame_offset, ActivationFrame::kAsyncActivation);
-            ASSERT(activation != NULL);
-            stack_trace->AddActivation(activation);
-            stack_has_async_function = true;
-            // Grab the awaiter.
-            async_activation ^= activation->GetAsyncAwaiter();
-            found_async_awaiter = true;
-            // async function might have been called synchronously, in which
-            // case we need to keep going down the stack.
-            // To determine how we are called we peek few more frames further
-            // expecting to see Closure_call followed by
-            // AsyncAwaitCompleter_start.
-            // If we are able to see those functions we continue going down
-            // thestack, if we are not, we break out of the loop as we are
-            // not interested in exploring rest of the stack - there is only
-            // dart-internal code left.
-            skip_sync_async_frames_count = 2;
-          } else {
-            stack_trace->AddActivation(
-                CollectDartFrame(isolate, it.pc(), frame, inlined_code,
-                                 deopt_frame, deopt_frame_offset));
-          }
+        bytecode = frame->LookupDartBytecode();
+        function = bytecode.function();
+        if (function.IsNull()) {
+          continue;  // Skip bytecode stub frame.
         }
-        // Break out of outer loop.
-        if (found_async_awaiter ||
-            abort_attempt_to_navigate_through_sync_async) {
-          break;
-        }
-      } else {
-        function = code.function();
 
         if (skip_sync_async_frames_count > 0) {
           function_name = function.QualifiedScrubbedName();
@@ -2127,9 +2229,9 @@
         }
 
         if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
-          ActivationFrame* activation = CollectDartFrame(
-              isolate, frame->pc(), frame, code, Object::null_array(), 0,
-              ActivationFrame::kAsyncActivation);
+          ActivationFrame* activation =
+              CollectDartFrame(isolate, frame->pc(), frame, bytecode,
+                               ActivationFrame::kAsyncActivation);
           ASSERT(activation != NULL);
           stack_trace->AddActivation(activation);
           stack_has_async_function = true;
@@ -2140,8 +2242,103 @@
           // synchronously above.
           skip_sync_async_frames_count = 2;
         } else {
-          stack_trace->AddActivation(CollectDartFrame(
-              isolate, frame->pc(), frame, code, Object::null_array(), 0));
+          stack_trace->AddActivation(
+              CollectDartFrame(isolate, frame->pc(), frame, bytecode));
+        }
+      } else {
+        code = frame->LookupDartCode();
+        if (code.is_optimized()) {
+          deopt_frame = DeoptimizeToArray(thread, frame, code);
+          bool found_async_awaiter = false;
+          bool abort_attempt_to_navigate_through_sync_async = false;
+          for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
+               it.Advance()) {
+            inlined_code = it.code();
+            function = it.function();
+
+            if (skip_sync_async_frames_count > 0) {
+              function_name ^= function.QualifiedScrubbedName();
+              if (CheckAndSkipAsync(skip_sync_async_frames_count,
+                                    function_name)) {
+                skip_sync_async_frames_count--;
+              } else {
+                // Unexpected function in sync async call
+                skip_sync_async_frames_count = -1;
+                abort_attempt_to_navigate_through_sync_async = true;
+                break;
+              }
+            }
+
+            if (FLAG_trace_debugger_stacktrace) {
+              ASSERT(!function.IsNull());
+              OS::PrintErr(
+                  "CollectAwaiterReturnStackTrace: visiting inlined function: "
+                  "%s\n",
+                  function.ToFullyQualifiedCString());
+            }
+            intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
+            if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
+              ActivationFrame* activation = CollectDartFrame(
+                  isolate, it.pc(), frame, inlined_code, deopt_frame,
+                  deopt_frame_offset, ActivationFrame::kAsyncActivation);
+              ASSERT(activation != NULL);
+              stack_trace->AddActivation(activation);
+              stack_has_async_function = true;
+              // Grab the awaiter.
+              async_activation ^= activation->GetAsyncAwaiter();
+              found_async_awaiter = true;
+              // async function might have been called synchronously, in which
+              // case we need to keep going down the stack.
+              // To determine how we are called we peek few more frames further
+              // expecting to see Closure_call followed by
+              // AsyncAwaitCompleter_start.
+              // If we are able to see those functions we continue going down
+              // thestack, if we are not, we break out of the loop as we are
+              // not interested in exploring rest of the stack - there is only
+              // dart-internal code left.
+              skip_sync_async_frames_count = 2;
+            } else {
+              stack_trace->AddActivation(
+                  CollectDartFrame(isolate, it.pc(), frame, inlined_code,
+                                   deopt_frame, deopt_frame_offset));
+            }
+          }
+          // Break out of outer loop.
+          if (found_async_awaiter ||
+              abort_attempt_to_navigate_through_sync_async) {
+            break;
+          }
+        } else {
+          function = code.function();
+
+          if (skip_sync_async_frames_count > 0) {
+            function_name ^= function.QualifiedScrubbedName();
+            if (CheckAndSkipAsync(skip_sync_async_frames_count,
+                                  function_name)) {
+              skip_sync_async_frames_count--;
+            } else {
+              // Unexpected function in synchronous call of async function.
+              break;
+            }
+          }
+
+          if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
+            ActivationFrame* activation = CollectDartFrame(
+                isolate, frame->pc(), frame, code, Object::null_array(), 0,
+                ActivationFrame::kAsyncActivation);
+            ASSERT(activation != NULL);
+            stack_trace->AddActivation(activation);
+            stack_has_async_function = true;
+            // Grab the awaiter.
+            async_activation ^= activation->GetAsyncAwaiter();
+            async_stack_trace ^= activation->GetCausalStack();
+            // see comment regarding skipping frames of async functions called
+            // synchronously above.
+            skip_sync_async_frames_count = 2;
+          } else {
+            stack_trace->AddActivation(CollectDartFrame(
+                isolate, frame->pc(), frame, code, Object::null_array(), 0));
+          }
         }
       }
     }
@@ -2214,11 +2411,14 @@
     frame = iterator.NextFrame();
   }
   ASSERT(frame != NULL);
+#if !defined(DART_PRECOMPILED_RUNTIME)
   if (frame->is_interpreted()) {
-    // TODO(regis): Support debugging of interpreted frames.
-    UNIMPLEMENTED();
-    return NULL;
+    Bytecode& bytecode = Bytecode::Handle(frame->LookupDartBytecode());
+    ActivationFrame* activation =
+        new ActivationFrame(frame->pc(), frame->fp(), frame->sp(), bytecode);
+    return activation;
   }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
   Code& code = Code::Handle(frame->LookupDartCode());
   ActivationFrame* activation = new ActivationFrame(
       frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0);
@@ -2256,6 +2456,9 @@
   Function& function = Function::Handle();
   Object& code_object = Object::Handle();
   Code& code = Code::Handle();
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  Bytecode& bytecode = Bytecode::Handle();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
   const uword fp = 0;
   const uword sp = 0;
@@ -2271,36 +2474,50 @@
     // a shallow stack).
     if (!code_object.IsNull()) {
       if (code_object.IsBytecode()) {
-        // TODO(regis): Support debugging of interpreted frames.
-        UNIMPLEMENTED();
-      }
-      code ^= code_object.raw();
-      ASSERT(code.IsFunctionCode());
-      function = code.function();
-      if (function.is_visible()) {
-        ASSERT(function.raw() == code.function());
-        uword pc =
-            code.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
-        if (code.is_optimized() && ex_trace.expand_inlined()) {
-          // Traverse inlined frames.
-          for (InlinedFunctionsIterator it(code, pc); !it.Done();
-               it.Advance()) {
-            function = it.function();
-            code = it.code();
-            ASSERT(function.raw() == code.function());
-            uword pc = it.pc();
-            ASSERT(pc != 0);
-            ASSERT(code.PayloadStart() <= pc);
-            ASSERT(pc < (code.PayloadStart() + code.Size()));
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        bytecode ^= code_object.raw();
+        function = bytecode.function();
+        // Skip bytecode stub frames and frames with invisible function.
+        if (!function.IsNull() && function.is_visible()) {
+          ASSERT(function.raw() == bytecode.function());
+          uword pc =
+              bytecode.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
+          ActivationFrame* activation =
+              new ActivationFrame(pc, fp, sp, bytecode);
+          stack_trace->AddActivation(activation);
+        }
+#else
+        UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+      } else {
+        code ^= code_object.raw();
+        ASSERT(code.IsFunctionCode());
+        function = code.function();
+        if (function.is_visible()) {
+          ASSERT(function.raw() == code.function());
+          uword pc =
+              code.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
+          if (code.is_optimized() && ex_trace.expand_inlined()) {
+            // Traverse inlined frames.
+            for (InlinedFunctionsIterator it(code, pc); !it.Done();
+                 it.Advance()) {
+              function = it.function();
+              code = it.code();
+              ASSERT(function.raw() == code.function());
+              uword pc = it.pc();
+              ASSERT(pc != 0);
+              ASSERT(code.PayloadStart() <= pc);
+              ASSERT(pc < (code.PayloadStart() + code.Size()));
 
+              ActivationFrame* activation = new ActivationFrame(
+                  pc, fp, sp, code, deopt_frame, deopt_frame_offset);
+              stack_trace->AddActivation(activation);
+            }
+          } else {
             ActivationFrame* activation = new ActivationFrame(
                 pc, fp, sp, code, deopt_frame, deopt_frame_offset);
             stack_trace->AddActivation(activation);
           }
-        } else {
-          ActivationFrame* activation = new ActivationFrame(
-              pc, fp, sp, code, deopt_frame, deopt_frame_offset);
-          stack_trace->AddActivation(activation);
         }
       }
     }
@@ -2431,12 +2648,12 @@
 // algorithm, which would be simpler.  I believe that it only needs
 // two passes to support the recursive try-the-whole-function case.
 // Rewrite this later, once there are more tests in place.
-TokenPosition Debugger::ResolveBreakpointPos(const Function& func,
+TokenPosition Debugger::ResolveBreakpointPos(bool in_bytecode,
+                                             const Function& func,
                                              TokenPosition requested_token_pos,
                                              TokenPosition last_token_pos,
                                              intptr_t requested_column,
                                              TokenPosition exact_token_pos) {
-  ASSERT(func.HasCode());
   ASSERT(!func.HasOptimizedCode());
 
   if (requested_token_pos < func.token_pos()) {
@@ -2448,9 +2665,25 @@
 
   Zone* zone = Thread::Current()->zone();
   Script& script = Script::Handle(zone, func.script());
-  Code& code = Code::Handle(zone, func.unoptimized_code());
-  ASSERT(!code.IsNull());
-  PcDescriptors& desc = PcDescriptors::Handle(zone, code.pc_descriptors());
+  Code& code = Code::Handle(zone);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  Bytecode& bytecode = Bytecode::Handle(zone);
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  PcDescriptors& desc = PcDescriptors::Handle(zone);
+  if (in_bytecode) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    ASSERT(func.HasBytecode());
+    bytecode = func.bytecode();
+    ASSERT(!bytecode.IsNull());
+#else
+    UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  } else {
+    ASSERT(func.HasCode());
+    code = func.unoptimized_code();
+    ASSERT(!code.IsNull());
+    desc = code.pc_descriptors();
+  }
 
   // First pass: find the safe point which is closest to the beginning
   // of the given token range.
@@ -2460,53 +2693,109 @@
   // best_token_pos and exact_token_pos are only used
   // if column number is provided.
   TokenPosition best_token_pos = TokenPosition::kNoSource;
-  PcDescriptors::Iterator iter(desc, kSafepointKind);
-  while (iter.MoveNext()) {
-    const TokenPosition pos = iter.TokenPos();
-    if ((!pos.IsReal()) || (pos < requested_token_pos) ||
-        (pos > last_token_pos)) {
-      // Token is not in the target range.
-      continue;
-    }
 
-    intptr_t token_start_column = -1;
-    intptr_t token_line = -1;
-    if (requested_column >= 0) {
-      // Find next closest safepoint
-      PcDescriptors::Iterator iter2(desc, kSafepointKind);
-      TokenPosition next_closest_token_position = TokenPosition::kMaxSource;
-      while (iter2.MoveNext()) {
-        const TokenPosition next = iter2.TokenPos();
-        if (next < next_closest_token_position && next > pos) {
-          next_closest_token_position = next;
+  if (in_bytecode) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
+    while (iter.MoveNext()) {
+      const TokenPosition pos = iter.TokenPos();
+      if ((!pos.IsReal()) || (pos < requested_token_pos) ||
+          (pos > last_token_pos)) {
+        // Token is not in the target range.
+        continue;
+      }
+
+      intptr_t token_start_column = -1;
+      intptr_t token_line = -1;
+      if (requested_column >= 0) {
+        kernel::BytecodeSourcePositionsIterator iter2(zone, bytecode);
+        TokenPosition next_closest_token_position = TokenPosition::kMaxSource;
+        while (iter2.MoveNext()) {
+          const TokenPosition next = iter2.TokenPos();
+          if (next < next_closest_token_position && next > pos) {
+            next_closest_token_position = next;
+          }
+        }
+
+        TokenPosition ignored;
+        TokenPosition end_of_line_pos;
+        script.GetTokenLocation(pos, &token_line, &token_start_column);
+        script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
+        TokenPosition token_end_pos =
+            (end_of_line_pos < next_closest_token_position)
+                ? end_of_line_pos
+                : next_closest_token_position;
+
+        if ((token_end_pos < exact_token_pos) ||
+            (token_start_column > best_column)) {
+          // Prefer the token with the lowest column number compatible
+          // with the requested column.
+          continue;
         }
       }
 
-      TokenPosition ignored;
-      TokenPosition end_of_line_pos;
-      script.GetTokenLocation(pos, &token_line, &token_start_column);
-      script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
-      TokenPosition token_end_pos =
-          (end_of_line_pos < next_closest_token_position)
-              ? end_of_line_pos
-              : next_closest_token_position;
-
-      if ((token_end_pos < exact_token_pos) ||
-          (token_start_column > best_column)) {
-        // Prefer the token with the lowest column number compatible
-        // with the requested column.
-        continue;
+      // Prefer the lowest (first) token pos.
+      if (pos < best_fit_pos) {
+        best_fit_pos = pos;
+        best_line = token_line;
+        best_column = token_start_column;
+        // best_token_pos is only used when column number is specified.
+        best_token_pos = TokenPosition(exact_token_pos.value() -
+                                       (requested_column - best_column));
       }
     }
+#else
+    UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  } else {
+    PcDescriptors::Iterator iter(desc, kSafepointKind);
+    while (iter.MoveNext()) {
+      const TokenPosition pos = iter.TokenPos();
+      if ((!pos.IsReal()) || (pos < requested_token_pos) ||
+          (pos > last_token_pos)) {
+        // Token is not in the target range.
+        continue;
+      }
 
-    // Prefer the lowest (first) token pos.
-    if (pos < best_fit_pos) {
-      best_fit_pos = pos;
-      best_line = token_line;
-      best_column = token_start_column;
-      // best_token_pos is only used when column number is specified.
-      best_token_pos = TokenPosition(exact_token_pos.value() -
-                                     (requested_column - best_column));
+      intptr_t token_start_column = -1;
+      intptr_t token_line = -1;
+      if (requested_column >= 0) {
+        // Find next closest safepoint
+        PcDescriptors::Iterator iter2(desc, kSafepointKind);
+        TokenPosition next_closest_token_position = TokenPosition::kMaxSource;
+        while (iter2.MoveNext()) {
+          const TokenPosition next = iter2.TokenPos();
+          if (next < next_closest_token_position && next > pos) {
+            next_closest_token_position = next;
+          }
+        }
+
+        TokenPosition ignored;
+        TokenPosition end_of_line_pos;
+        script.GetTokenLocation(pos, &token_line, &token_start_column);
+        script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
+        TokenPosition token_end_pos =
+            (end_of_line_pos < next_closest_token_position)
+                ? end_of_line_pos
+                : next_closest_token_position;
+
+        if ((token_end_pos < exact_token_pos) ||
+            (token_start_column > best_column)) {
+          // Prefer the token with the lowest column number compatible
+          // with the requested column.
+          continue;
+        }
+      }
+
+      // Prefer the lowest (first) token pos.
+      if (pos < best_fit_pos) {
+        best_fit_pos = pos;
+        best_line = token_line;
+        best_column = token_start_column;
+        // best_token_pos is only used when column number is specified.
+        best_token_pos = TokenPosition(exact_token_pos.value() -
+                                       (requested_column - best_column));
+      }
     }
   }
 
@@ -2534,24 +2823,51 @@
     }
 
     uword lowest_pc_offset = kUwordMax;
-    PcDescriptors::Iterator iter(desc, kSafepointKind);
-    while (iter.MoveNext()) {
-      const TokenPosition pos = iter.TokenPos();
-      if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
-        // Token is not on same line as best fit.
-        continue;
-      }
-
-      if (requested_column >= 0) {
-        if (pos != best_token_pos) {
+    if (in_bytecode) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+      kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
+      while (iter.MoveNext()) {
+        const TokenPosition pos = iter.TokenPos();
+        if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
+          // Token is not on same line as best fit.
           continue;
         }
-      }
 
-      // Prefer the lowest pc offset.
-      if (iter.PcOffset() < lowest_pc_offset) {
-        lowest_pc_offset = iter.PcOffset();
-        best_fit_pos = pos;
+        if (requested_column >= 0) {
+          if (pos != best_token_pos) {
+            continue;
+          }
+        }
+
+        // Prefer the lowest pc offset.
+        if (iter.PcOffset() < lowest_pc_offset) {
+          lowest_pc_offset = iter.PcOffset();
+          best_fit_pos = pos;
+        }
+      }
+#else
+      UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+    } else {
+      PcDescriptors::Iterator iter(desc, kSafepointKind);
+      while (iter.MoveNext()) {
+        const TokenPosition pos = iter.TokenPos();
+        if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
+          // Token is not on same line as best fit.
+          continue;
+        }
+
+        if (requested_column >= 0) {
+          if (pos != best_token_pos) {
+            continue;
+          }
+        }
+
+        // Prefer the lowest pc offset.
+        if (iter.PcOffset() < lowest_pc_offset) {
+          lowest_pc_offset = iter.PcOffset();
+          best_fit_pos = pos;
+        }
       }
     }
     return best_fit_pos;
@@ -2562,8 +2878,9 @@
   // Since we have moved to the next line of the function, we no
   // longer are requesting a specific column number.
   if (last_token_pos < func.end_token_pos()) {
-    return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(),
-                                -1 /* no column */, TokenPosition::kNoSource);
+    return ResolveBreakpointPos(in_bytecode, func, last_token_pos,
+                                func.end_token_pos(), -1 /* no column */,
+                                TokenPosition::kNoSource);
   }
   return TokenPosition::kNoSource;
 }
@@ -2573,43 +2890,78 @@
   ASSERT(loc->token_pos_.IsReal());
   ASSERT((loc != NULL) && loc->IsResolved());
   ASSERT(!func.HasOptimizedCode());
-  Code& code = Code::Handle(func.unoptimized_code());
-  ASSERT(!code.IsNull());
-  PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
-  uword lowest_pc_offset = kUwordMax;
-  RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind;
-  // Find the safe point with the lowest compiled code address
-  // that maps to the token position of the source breakpoint.
-  PcDescriptors::Iterator iter(desc, kSafepointKind);
-  while (iter.MoveNext()) {
-    if (iter.TokenPos() == loc->token_pos_) {
-      if (iter.PcOffset() < lowest_pc_offset) {
-        lowest_pc_offset = iter.PcOffset();
-        lowest_kind = iter.Kind();
+  ASSERT(func.HasCode() || func.HasBytecode());
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  if (func.HasBytecode()) {
+    Bytecode& bytecode = Bytecode::Handle(func.bytecode());
+    ASSERT(!bytecode.IsNull());
+    uword lowest_pc_offset = kUwordMax;
+    if (bytecode.HasSourcePositions()) {
+      kernel::BytecodeSourcePositionsIterator iter(Thread::Current()->zone(),
+                                                   bytecode);
+      while (iter.MoveNext()) {
+        if (iter.TokenPos() == loc->token_pos_) {
+          if (iter.PcOffset() < lowest_pc_offset) {
+            lowest_pc_offset = iter.PcOffset();
+          }
+        }
+      }
+    }
+    if (lowest_pc_offset != kUwordMax) {
+      uword lowest_pc = bytecode.PayloadStart() + lowest_pc_offset;
+      CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc);
+      if (code_bpt == NULL) {
+        // No code breakpoint for this code exists; create one.
+        code_bpt = new CodeBreakpoint(bytecode, loc->token_pos_, lowest_pc);
+        RegisterCodeBreakpoint(code_bpt);
+      }
+      code_bpt->set_bpt_location(loc);
+      if (loc->AnyEnabled()) {
+        code_bpt->Enable();
       }
     }
   }
-  if (lowest_pc_offset == kUwordMax) {
-    return;
-  }
-  uword lowest_pc = code.PayloadStart() + lowest_pc_offset;
-  CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc);
-  if (code_bpt == NULL) {
-    // No code breakpoint for this code exists; create one.
-    code_bpt =
-        new CodeBreakpoint(code, loc->token_pos_, lowest_pc, lowest_kind);
-    RegisterCodeBreakpoint(code_bpt);
-  }
-  code_bpt->set_bpt_location(loc);
-  if (loc->AnyEnabled()) {
-    code_bpt->Enable();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  if (func.HasCode()) {
+    Code& code = Code::Handle(func.unoptimized_code());
+    ASSERT(!code.IsNull());
+    PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
+    uword lowest_pc_offset = kUwordMax;
+    RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind;
+    // Find the safe point with the lowest compiled code address
+    // that maps to the token position of the source breakpoint.
+    PcDescriptors::Iterator iter(desc, kSafepointKind);
+    while (iter.MoveNext()) {
+      if (iter.TokenPos() == loc->token_pos_) {
+        if (iter.PcOffset() < lowest_pc_offset) {
+          lowest_pc_offset = iter.PcOffset();
+          lowest_kind = iter.Kind();
+        }
+      }
+    }
+    if (lowest_pc_offset != kUwordMax) {
+      uword lowest_pc = code.PayloadStart() + lowest_pc_offset;
+      CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc);
+      if (code_bpt == NULL) {
+        // No code breakpoint for this code exists; create one.
+        code_bpt =
+            new CodeBreakpoint(code, loc->token_pos_, lowest_pc, lowest_kind);
+        RegisterCodeBreakpoint(code_bpt);
+      }
+      code_bpt->set_bpt_location(loc);
+      if (loc->AnyEnabled()) {
+        code_bpt->Enable();
+      }
+    }
   }
 }
 
-void Debugger::FindCompiledFunctions(const Script& script,
-                                     TokenPosition start_pos,
-                                     TokenPosition end_pos,
-                                     GrowableObjectArray* function_list) {
+void Debugger::FindCompiledFunctions(
+    const Script& script,
+    TokenPosition start_pos,
+    TokenPosition end_pos,
+    GrowableObjectArray* bytecode_function_list,
+    GrowableObjectArray* code_function_list) {
   Zone* zone = Thread::Current()->zone();
   Class& cls = Class::Handle(zone);
   Array& functions = Array::Handle(zone);
@@ -2624,13 +2976,23 @@
     if ((function.token_pos() == start_pos) &&
         (function.end_token_pos() == end_pos) &&
         (function.script() == script.raw())) {
-      if (function.HasCode() && function.is_debuggable()) {
-        function_list->Add(function);
+      if (function.is_debuggable()) {
+        if (function.HasBytecode()) {
+          bytecode_function_list->Add(function);
+        }
+        if (function.HasCode()) {
+          code_function_list->Add(function);
+        }
       }
       if (function.HasImplicitClosureFunction()) {
         function = function.ImplicitClosureFunction();
-        if (function.HasCode() && function.is_debuggable()) {
-          function_list->Add(function);
+        if (function.is_debuggable()) {
+          if (function.HasBytecode()) {
+            bytecode_function_list->Add(function);
+          }
+          if (function.HasCode()) {
+            code_function_list->Add(function);
+          }
         }
       }
     }
@@ -2662,13 +3024,23 @@
           if ((function.token_pos() == start_pos) &&
               (function.end_token_pos() == end_pos) &&
               (function.script() == script.raw())) {
-            if (function.HasCode() && function.is_debuggable()) {
-              function_list->Add(function);
+            if (function.is_debuggable()) {
+              if (function.HasBytecode()) {
+                bytecode_function_list->Add(function);
+              }
+              if (function.HasCode()) {
+                code_function_list->Add(function);
+              }
             }
             if (function.HasImplicitClosureFunction()) {
               function = function.ImplicitClosureFunction();
-              if (function.HasCode() && function.is_debuggable()) {
-                function_list->Add(function);
+              if (function.is_debuggable()) {
+                if (function.HasBytecode()) {
+                  bytecode_function_list->Add(function);
+                }
+                if (function.HasCode()) {
+                  code_function_list->Add(function);
+                }
               }
             }
           }
@@ -2800,6 +3172,71 @@
   return false;
 }
 
+BreakpointLocation* Debugger::SetCodeBreakpoints(
+    bool in_bytecode,
+    BreakpointLocation* loc,
+    const Script& script,
+    TokenPosition token_pos,
+    TokenPosition last_token_pos,
+    intptr_t requested_line,
+    intptr_t requested_column,
+    TokenPosition exact_token_pos,
+    const GrowableObjectArray& functions) {
+  Function& function = Function::Handle();
+  function ^= functions.At(0);
+  TokenPosition breakpoint_pos =
+      ResolveBreakpointPos(in_bytecode, function, token_pos, last_token_pos,
+                           requested_column, exact_token_pos);
+  if (!breakpoint_pos.IsReal()) {
+    return NULL;
+  }
+  if (loc == NULL) {
+    // Find an existing resolved breakpoint location.
+    loc = GetBreakpointLocation(
+        script, TokenPosition::kNoSource,
+        /* requested_line = */ -1,
+        /* requested_column = */ -1,
+        in_bytecode ? breakpoint_pos : TokenPosition::kNoSource,
+        !in_bytecode ? breakpoint_pos : TokenPosition::kNoSource);
+  }
+  if (loc == NULL) {
+    // Find an existing unresolved breakpoint location.
+    loc = GetBreakpointLocation(script, token_pos, requested_line,
+                                requested_column);
+  }
+  if (loc == NULL) {
+    loc = new BreakpointLocation(script, breakpoint_pos, breakpoint_pos,
+                                 requested_line, requested_column);
+    RegisterBreakpointLocation(loc);
+  }
+  // A source breakpoint for this location may already exists, but it may
+  // not yet be resolved in both bytecode and code.
+  if (loc->IsResolved(in_bytecode)) {
+    return loc;
+  }
+  loc->SetResolved(in_bytecode, function, breakpoint_pos);
+
+  // Create code breakpoints for all compiled functions we found.
+  Function& func = Function::Handle();
+  const intptr_t num_functions = functions.Length();
+  for (intptr_t i = 0; i < num_functions; i++) {
+    func ^= functions.At(i);
+    ASSERT((in_bytecode && func.HasBytecode()) ||
+           (!in_bytecode && func.HasCode()));
+    MakeCodeBreakpointAt(func, loc);
+  }
+  if (FLAG_verbose_debug) {
+    intptr_t line_number;
+    intptr_t column_number;
+    script.GetTokenLocation(breakpoint_pos, &line_number, &column_number);
+    OS::PrintErr(
+        "Resolved BP for "
+        "function '%s' at line %" Pd " col %" Pd "\n",
+        func.ToFullyQualifiedCString(), line_number, column_number);
+  }
+  return loc;
+}
+
 BreakpointLocation* Debugger::SetBreakpoint(const Script& script,
                                             TokenPosition token_pos,
                                             TokenPosition last_token_pos,
@@ -2811,65 +3248,53 @@
     if (!FindBestFit(script, token_pos, last_token_pos, &func)) {
       return NULL;
     }
+    // If func was not set (still Null), the best fit is a field.
   } else {
     func = function.raw();
+    if (!func.token_pos().IsReal()) {
+      return NULL;  // Missing source positions in bytecode?
+    }
   }
-
   if (!func.IsNull()) {
     // There may be more than one function object for a given function
     // in source code. There may be implicit closure functions, and
     // there may be copies of mixin functions. Collect all compiled
     // functions whose source code range matches exactly the best fit
     // function we found.
-    GrowableObjectArray& functions =
+    GrowableObjectArray& bytecode_functions =
+        GrowableObjectArray::Handle(GrowableObjectArray::New());
+    GrowableObjectArray& code_functions =
         GrowableObjectArray::Handle(GrowableObjectArray::New());
     FindCompiledFunctions(script, func.token_pos(), func.end_token_pos(),
-                          &functions);
+                          &bytecode_functions, &code_functions);
 
-    if (functions.Length() > 0) {
+    if (bytecode_functions.Length() > 0 || code_functions.Length() > 0) {
       // One or more function object containing this breakpoint location
       // have already been compiled. We can resolve the breakpoint now.
-      DeoptimizeWorld();
-      func ^= functions.At(0);
-      TokenPosition exact_token_pos = TokenPosition(-1);
-      // if requested_column is larger than zero, [token_pos, last_token_pos]
+      // If requested_column is larger than zero, [token_pos, last_token_pos]
       // governs one single line of code.
+      TokenPosition exact_token_pos = TokenPosition(-1);
       if (token_pos != last_token_pos && requested_column >= 0) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
         exact_token_pos =
             FindExactTokenPosition(script, token_pos, requested_column);
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
       }
-      TokenPosition breakpoint_pos = ResolveBreakpointPos(
-          func, token_pos, last_token_pos, requested_column, exact_token_pos);
-      if (breakpoint_pos.IsReal()) {
-        BreakpointLocation* loc = GetBreakpointLocation(script, breakpoint_pos,
-                                                        requested_column, true);
-        if (loc != NULL) {
-          // A source breakpoint for this location already exists.
-          return loc;
-        }
-        loc = new BreakpointLocation(script, breakpoint_pos, breakpoint_pos,
-                                     requested_line, requested_column);
-        loc->SetResolved(func, breakpoint_pos);
-        RegisterBreakpointLocation(loc);
-
-        // Create code breakpoints for all compiled functions we found.
-        const intptr_t num_functions = functions.Length();
-        for (intptr_t i = 0; i < num_functions; i++) {
-          func ^= functions.At(i);
-          ASSERT(func.HasCode());
-          MakeCodeBreakpointAt(func, loc);
-        }
-        if (FLAG_verbose_debug) {
-          intptr_t line_number;
-          intptr_t column_number;
-          script.GetTokenLocation(breakpoint_pos, &line_number, &column_number);
-          OS::PrintErr(
-              "Resolved BP for "
-              "function '%s' at line %" Pd " col %" Pd "\n",
-              func.ToFullyQualifiedCString(), line_number, column_number);
-        }
+      // Since source positions may differ in code and bytecode, process
+      // breakpoints in bytecode and code separately.
+      BreakpointLocation* loc = NULL;
+      if (bytecode_functions.Length() > 0) {
+        loc = SetCodeBreakpoints(true, loc, script, token_pos, last_token_pos,
+                                 requested_line, requested_column,
+                                 exact_token_pos, bytecode_functions);
+      }
+      if (code_functions.Length() > 0) {
+        DeoptimizeWorld();
+        loc = SetCodeBreakpoints(false, loc, script, token_pos, last_token_pos,
+                                 requested_line, requested_column,
+                                 exact_token_pos, code_functions);
+      }
+      if (loc != NULL) {
         return loc;
       }
     }
@@ -2894,7 +3319,7 @@
     }
   }
   BreakpointLocation* loc =
-      GetBreakpointLocation(script, token_pos, requested_column);
+      GetBreakpointLocation(script, token_pos, -1, requested_column);
   if (loc == NULL) {
     loc = new BreakpointLocation(script, token_pos, last_token_pos,
                                  requested_line, requested_column);
@@ -3525,6 +3950,12 @@
   return lib.IsDebuggable();
 }
 
+bool Debugger::IsDebugging(Thread* thread, const Function& func) {
+  Debugger* debugger = thread->isolate()->debugger();
+  return debugger->IsStepping() ||
+         debugger->HasBreakpoint(func, thread->zone());
+}
+
 void Debugger::SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt) {
   resume_action_ = kContinue;
   ResetSteppingFramePointers();
@@ -3836,7 +4267,7 @@
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-void Debugger::NotifyCompilation(const Function& func) {
+void Debugger::HandleCodeChange(bool bytecode_loaded, const Function& func) {
   if (breakpoint_locations_ == NULL) {
     // Return with minimal overhead if there are no breakpoints.
     return;
@@ -3868,6 +4299,8 @@
                                            loc->requested_column_number());
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
       }
+      // TODO(regis): Bytecode closures are not currently added to
+      // object_store()->closure_functions(). Should they? Revisit.
       inner_function = FindInnermostClosure(func, token_pos);
       if (!inner_function.IsNull()) {
         // The local function of a function we just compiled cannot
@@ -3887,11 +4320,11 @@
       // There is no local function within func that contains the
       // breakpoint token position. Resolve the breakpoint if necessary
       // and set the code breakpoints.
-      if (!loc->IsResolved()) {
+      if (!loc->IsResolved(bytecode_loaded)) {
         // Resolve source breakpoint in the newly compiled function.
-        TokenPosition bp_pos =
-            ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(),
-                                 loc->requested_column_number(), token_pos);
+        TokenPosition bp_pos = ResolveBreakpointPos(
+            bytecode_loaded, func, loc->token_pos(), loc->end_token_pos(),
+            loc->requested_column_number(), token_pos);
         if (!bp_pos.IsDebugPause()) {
           if (FLAG_verbose_debug) {
             OS::PrintErr("Failed resolving breakpoint for function '%s'\n",
@@ -3901,34 +4334,28 @@
         }
         TokenPosition requested_pos = loc->token_pos();
         TokenPosition requested_end_pos = loc->end_token_pos();
-        loc->SetResolved(func, bp_pos);
+        loc->SetResolved(bytecode_loaded, func, bp_pos);
         Breakpoint* bpt = loc->breakpoints();
         while (bpt != NULL) {
           if (FLAG_verbose_debug) {
             OS::PrintErr(
                 "Resolved BP %" Pd
                 " to pos %s, "
-                "line %" Pd " col %" Pd
-                ", "
                 "function '%s' (requested range %s-%s, "
                 "requested col %" Pd ")\n",
-                bpt->id(), loc->token_pos().ToCString(), loc->LineNumber(),
-                loc->ColumnNumber(), func.ToFullyQualifiedCString(),
-                requested_pos.ToCString(), requested_end_pos.ToCString(),
-                loc->requested_column_number());
+                bpt->id(), loc->token_pos().ToCString(),
+                func.ToFullyQualifiedCString(), requested_pos.ToCString(),
+                requested_end_pos.ToCString(), loc->requested_column_number());
           }
           SendBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt);
           bpt = bpt->next();
         }
       }
-      ASSERT(loc->IsResolved());
+      ASSERT(loc->IsResolved(bytecode_loaded));
       if (FLAG_verbose_debug) {
         Breakpoint* bpt = loc->breakpoints();
         while (bpt != NULL) {
-          OS::PrintErr("Setting breakpoint %" Pd " at line %" Pd " col %" Pd
-                       ""
-                       " for %s '%s'\n",
-                       bpt->id(), loc->LineNumber(), loc->ColumnNumber(),
+          OS::PrintErr("Setting breakpoint %" Pd " for %s '%s'\n", bpt->id(),
                        func.IsClosureFunction() ? "closure" : "function",
                        String::Handle(func.name()).ToCString());
           bpt = bpt->next();
@@ -3998,7 +4425,7 @@
           // If there is one, assert in debug build but silently drop
           // the latent breakpoint in release build.
           BreakpointLocation* existing_loc =
-              GetBreakpointLocation(script, first_token_pos, column_number);
+              GetBreakpointLocation(script, first_token_pos, -1, column_number);
           ASSERT(existing_loc == NULL);
           if (existing_loc == NULL) {
             // Create and register a new source breakpoint for the
@@ -4201,21 +4628,25 @@
   needs_breakpoint_cleanup_ = false;
 }
 
-BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script,
-                                                    TokenPosition token_pos,
-                                                    intptr_t requested_column,
-                                                    bool is_resolved) {
+BreakpointLocation* Debugger::GetBreakpointLocation(
+    const Script& script,
+    TokenPosition token_pos,
+    intptr_t requested_line,
+    intptr_t requested_column,
+    TokenPosition bytecode_token_pos,
+    TokenPosition code_token_pos) {
   BreakpointLocation* loc = breakpoint_locations_;
   while (loc != NULL) {
-    // When BreakpointLocation has been resolved BreakpointLocation
-    // should check only token position. Whether column or line
-    // breakpoint should be the same once resolved into the
-    // same token position.
-    bool column_match =
-        (is_resolved) ? true
-                      : (loc->requested_column_number_ == requested_column);
-    if ((loc->script_ == script.raw()) && (loc->token_pos_ == token_pos) &&
-        column_match) {
+    if (loc->script_ == script.raw() &&
+        (!token_pos.IsReal() || (loc->token_pos_ == token_pos)) &&
+        ((requested_line == -1) ||
+         (loc->requested_line_number_ == requested_line)) &&
+        ((requested_column == -1) ||
+         (loc->requested_column_number_ == requested_column)) &&
+        (!bytecode_token_pos.IsReal() ||
+         (loc->bytecode_token_pos_ == bytecode_token_pos)) &&
+        (!code_token_pos.IsReal() ||
+         (loc->code_token_pos_ == code_token_pos))) {
       return loc;
     }
     loc = loc->next();
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index 05230cd..e186720 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -7,6 +7,7 @@
 
 #include "include/dart_tools_api.h"
 
+#include "vm/constants_kbc.h"
 #include "vm/kernel_isolate.h"
 #include "vm/object.h"
 #include "vm/port.h"
@@ -140,12 +141,7 @@
   intptr_t requested_line_number() const { return requested_line_number_; }
   intptr_t requested_column_number() const { return requested_column_number_; }
 
-  intptr_t LineNumber();
-  intptr_t ColumnNumber();
-
-  void GetCodeLocation(Library* lib,
-                       Script* script,
-                       TokenPosition* token_pos) const;
+  void GetCodeLocation(Script* script, TokenPosition* token_pos) const;
 
   Breakpoint* AddRepeated(Debugger* dbg);
   Breakpoint* AddSingleShot(Debugger* dbg);
@@ -154,13 +150,21 @@
                             bool for_over_await);
 
   bool AnyEnabled() const;
-  bool IsResolved() const { return is_resolved_; }
+  bool IsResolved() const {
+    return bytecode_token_pos_.IsReal() || code_token_pos_.IsReal();
+  }
+  bool IsResolved(bool in_bytecode) const {
+    return in_bytecode ? bytecode_token_pos_.IsReal()
+                       : code_token_pos_.IsReal();
+  }
   bool IsLatent() const { return !token_pos_.IsReal(); }
 
  private:
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
 
-  void SetResolved(const Function& func, TokenPosition token_pos);
+  void SetResolved(bool in_bytecode,
+                   const Function& func,
+                   TokenPosition token_pos);
 
   BreakpointLocation* next() const { return this->next_; }
   void set_next(BreakpointLocation* value) { next_ = value; }
@@ -174,7 +178,6 @@
   RawString* url_;
   TokenPosition token_pos_;
   TokenPosition end_token_pos_;
-  bool is_resolved_;
   BreakpointLocation* next_;
   Breakpoint* conditions_;
   intptr_t requested_line_number_;
@@ -182,22 +185,23 @@
 
   // Valid for resolved breakpoints:
   RawFunction* function_;
-  intptr_t line_number_;
-  intptr_t column_number_;
+  TokenPosition bytecode_token_pos_;
+  TokenPosition code_token_pos_;
 
   friend class Debugger;
   DISALLOW_COPY_AND_ASSIGN(BreakpointLocation);
 };
 
-// CodeBreakpoint represents a location in compiled code. There may be
-// more than one CodeBreakpoint for one BreakpointLocation, e.g. when a
-// function gets compiled as a regular function and as a closure.
+// CodeBreakpoint represents a location in compiled or interpreted code.
+// There may be more than one CodeBreakpoint for one BreakpointLocation,
+// e.g. when a function gets compiled as a regular function and as a closure.
 class CodeBreakpoint {
  public:
   CodeBreakpoint(const Code& code,
                  TokenPosition token_pos,
                  uword pc,
                  RawPcDescriptors::Kind kind);
+  CodeBreakpoint(const Bytecode& bytecode, TokenPosition token_pos, uword pc);
   ~CodeBreakpoint();
 
   RawFunction* function() const;
@@ -211,6 +215,7 @@
   void Enable();
   void Disable();
   bool IsEnabled() const { return is_enabled_; }
+  bool IsInterpreted() const { return bytecode_ != Bytecode::null(); }
 
   RawCode* OrigStubAddress() const;
 
@@ -225,8 +230,11 @@
 
   void PatchCode();
   void RestoreCode();
+  void SetBytecodeBreak();
+  void UnsetBytecodeBreak();
 
   RawCode* code_;
+  RawBytecode* bytecode_;
   TokenPosition token_pos_;
   uword pc_;
   intptr_t line_number_;
@@ -271,6 +279,16 @@
 
   ActivationFrame(uword pc, const Code& code);
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  ActivationFrame(uword pc,
+                  uword fp,
+                  uword sp,
+                  const Bytecode& bytecode,
+                  Kind kind = kRegular);
+
+  ActivationFrame(uword pc, const Bytecode& bytecode);
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
   explicit ActivationFrame(Kind kind);
 
   explicit ActivationFrame(const Closure& async_activation);
@@ -286,7 +304,11 @@
     ASSERT(!code_.IsNull());
     return code_;
   }
-  bool is_interpreted() const { return is_interpreted_; }
+  const Bytecode& bytecode() const {
+    ASSERT(!bytecode_.IsNull());
+    return bytecode_;
+  }
+  bool IsInterpreted() const { return !bytecode_.IsNull(); }
 
   RawString* QualifiedFunctionName();
   RawString* SourceUrl();
@@ -399,6 +421,7 @@
   // The anchor of the context chain for this function.
   Context& ctx_;
   Code& code_;
+  Bytecode& bytecode_;
   Function& function_;
   bool live_frame_;  // Is this frame a live frame?
   bool token_pos_initialized_;
@@ -416,7 +439,6 @@
 
   Kind kind_;
 
-  bool is_interpreted_;  // Running under kernel bytecode interpreter.
   bool vars_initialized_;
   LocalVarDescriptors& var_descriptors_;
   ZoneGrowableArray<intptr_t> desc_indices_;
@@ -442,6 +464,7 @@
   void AddActivation(ActivationFrame* frame);
   void AddMarker(ActivationFrame::Kind marker);
   void AddAsyncCausalFrame(uword pc, const Code& code);
+  void AddAsyncCausalFrame(uword pc, const Bytecode& bytecode);
 
   ZoneGrowableArray<ActivationFrame*> trace_;
 
@@ -476,7 +499,12 @@
 
   void OnIsolateRunnable();
 
-  void NotifyCompilation(const Function& func);
+  void NotifyCompilation(const Function& func) {
+    HandleCodeChange(/* bytecode_loaded = */ false, func);
+  }
+  void NotifyBytecodeLoaded(const Function& func) {
+    HandleCodeChange(/* bytecode_loaded = */ true, func);
+  }
   void NotifyDoneLoading();
 
   RawFunction* ResolveFunction(const Library& library,
@@ -547,6 +575,7 @@
   // debugger's zone.
   bool HasBreakpoint(const Function& func, Zone* zone);
   bool HasBreakpoint(const Code& code);
+  // A Bytecode version of HasBreakpoint is not needed.
 
   // Returns true if the call at address pc is patched to point to
   // a debugger stub.
@@ -598,6 +627,7 @@
   void PrintSettingsToJSONObject(JSONObject* jsobj) const;
 
   static bool IsDebuggable(const Function& func);
+  static bool IsDebugging(Thread* thread, const Function& func);
 
   intptr_t limitBreakpointId() { return next_id_; }
 
@@ -626,19 +656,30 @@
   void FindCompiledFunctions(const Script& script,
                              TokenPosition start_pos,
                              TokenPosition end_pos,
-                             GrowableObjectArray* function_list);
+                             GrowableObjectArray* bytecode_function_list,
+                             GrowableObjectArray* code_function_list);
   bool FindBestFit(const Script& script,
                    TokenPosition token_pos,
                    TokenPosition last_token_pos,
                    Function* best_fit);
   RawFunction* FindInnermostClosure(const Function& function,
                                     TokenPosition token_pos);
-  TokenPosition ResolveBreakpointPos(const Function& func,
+  TokenPosition ResolveBreakpointPos(bool in_bytecode,
+                                     const Function& func,
                                      TokenPosition requested_token_pos,
                                      TokenPosition last_token_pos,
                                      intptr_t requested_column,
                                      TokenPosition exact_token_pos);
   void DeoptimizeWorld();
+  BreakpointLocation* SetCodeBreakpoints(bool in_bytecode,
+                                         BreakpointLocation* loc,
+                                         const Script& script,
+                                         TokenPosition token_pos,
+                                         TokenPosition last_token_pos,
+                                         intptr_t requested_line,
+                                         intptr_t requested_column,
+                                         TokenPosition exact_token_pos,
+                                         const GrowableObjectArray& functions);
   BreakpointLocation* SetBreakpoint(const Script& script,
                                     TokenPosition token_pos,
                                     TokenPosition last_token_pos,
@@ -654,10 +695,13 @@
                                           intptr_t column);
   void RegisterBreakpointLocation(BreakpointLocation* bpt);
   void RegisterCodeBreakpoint(CodeBreakpoint* bpt);
-  BreakpointLocation* GetBreakpointLocation(const Script& script,
-                                            TokenPosition token_pos,
-                                            intptr_t requested_column,
-                                            bool is_resolved = false);
+  BreakpointLocation* GetBreakpointLocation(
+      const Script& script,
+      TokenPosition token_pos,
+      intptr_t requested_line,
+      intptr_t requested_column,
+      TokenPosition bytecode_token_pos = TokenPosition::kNoSource,
+      TokenPosition code_token_pos = TokenPosition::kNoSource);
   void MakeCodeBreakpointAt(const Function& func, BreakpointLocation* bpt);
   // Returns NULL if no breakpoint exists for the given address.
   CodeBreakpoint* GetCodeBreakpoint(uword breakpoint_address);
@@ -666,6 +710,8 @@
   void PrintBreakpointsListToJSONArray(BreakpointLocation* sbpt,
                                        JSONArray* jsarr) const;
 
+  void HandleCodeChange(bool bytecode_loaded, const Function& func);
+
   ActivationFrame* TopDartFrame() const;
   static ActivationFrame* CollectDartFrame(
       Isolate* isolate,
@@ -676,6 +722,12 @@
       intptr_t deopt_frame_offset,
       ActivationFrame::Kind kind = ActivationFrame::kRegular);
 #if !defined(DART_PRECOMPILED_RUNTIME)
+  static ActivationFrame* CollectDartFrame(
+      Isolate* isolate,
+      uword pc,
+      StackFrame* frame,
+      const Bytecode& bytecode,
+      ActivationFrame::Kind kind = ActivationFrame::kRegular);
   static RawArray* DeoptimizeToArray(Thread* thread,
                                      StackFrame* frame,
                                      const Code& code);
diff --git a/runtime/vm/debugger_kbc.cc b/runtime/vm/debugger_kbc.cc
new file mode 100644
index 0000000..2bfbb65
--- /dev/null
+++ b/runtime/vm/debugger_kbc.cc
@@ -0,0 +1,33 @@
+// Copyright (c) 2019, 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)
+
+#include "vm/debugger.h"
+#include "vm/instructions_kbc.h"
+
+namespace dart {
+
+#ifndef PRODUCT
+
+void CodeBreakpoint::SetBytecodeBreak() {
+  ASSERT(!is_enabled_);
+  ASSERT(!Isolate::Current()->is_using_old_bytecode_instructions());
+  // TODO(regis): Register pc_ (or the token pos range including pc_) with the
+  // interpreter as a debug break address.
+  is_enabled_ = true;
+}
+
+void CodeBreakpoint::UnsetBytecodeBreak() {
+  ASSERT(is_enabled_);
+  // TODO(regis): Unregister pc_ (or the token pos range including pc_) with the
+  // interpreter as a debug break address.
+  is_enabled_ = false;
+}
+#endif  // !PRODUCT
+
+}  // namespace dart
+
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/dwarf.cc b/runtime/vm/dwarf.cc
index 1165836..29e5488 100644
--- a/runtime/vm/dwarf.cc
+++ b/runtime/vm/dwarf.cc
@@ -5,6 +5,7 @@
 #include "vm/dwarf.h"
 
 #include "vm/code_descriptors.h"
+#include "vm/elf.h"
 #include "vm/object_store.h"
 
 namespace dart {
@@ -51,26 +52,37 @@
   InliningNode* children_next;
 };
 
-Dwarf::Dwarf(Zone* zone, StreamingWriteStream* stream)
+Dwarf::Dwarf(Zone* zone, StreamingWriteStream* stream, Elf* elf)
     : zone_(zone),
-      stream_(stream),
+      elf_(elf),
+      asm_stream_(stream),
+      bin_stream_(nullptr),
       codes_(zone, 1024),
       code_to_index_(zone),
       functions_(zone, 1024),
       function_to_index_(zone),
       scripts_(zone, 1024),
       script_to_index_(zone),
-      temp_(0) {}
+      abstract_origins_(nullptr),
+      temp_(0) {
+  // Either assembler or direct to ELF.
+  RELEASE_ASSERT((stream == nullptr) != (elf == nullptr));
+}
 
 intptr_t Dwarf::AddCode(const Code& code) {
+  intptr_t index = codes_.length();
+  AddCode(code, index);
+  return index;
+}
+
+void Dwarf::AddCode(const Code& code, intptr_t offset) {
   RELEASE_ASSERT(!code.IsNull());
   CodeIndexPair* pair = code_to_index_.Lookup(&code);
   if (pair != NULL) {
-    return pair->index_;
+    return;  // UNREACHABLE?
   }
-  intptr_t index = codes_.length();
   const Code& zone_code = Code::ZoneHandle(zone_, code.raw());
-  code_to_index_.Insert(CodeIndexPair(&zone_code, index));
+  code_to_index_.Insert(CodeIndexPair(&zone_code, offset));
   codes_.Add(&zone_code);
   if (code.IsFunctionCode()) {
     const Function& function = Function::Handle(zone_, code.function());
@@ -85,7 +97,6 @@
       AddFunction(function);
     }
   }
-  return index;
 }
 
 intptr_t Dwarf::AddFunction(const Function& function) {
@@ -140,23 +151,36 @@
 void Dwarf::Print(const char* format, ...) {
   va_list args;
   va_start(args, format);
-  stream_->VPrint(format, args);
+  asm_stream_->VPrint(format, args);
   va_end(args);
 }
 
-void Dwarf::WriteAbbreviations() {
-// Dwarf data mostly takes the form of a tree, whose nodes are called
-// DIEs. Each DIE begins with an abbreviation code, and the abbreviation
-// describes the attributes of that DIE and their representation.
+static uint8_t* ZoneReallocate(uint8_t* ptr,
+                               intptr_t old_size,
+                               intptr_t new_size) {
+  return Thread::Current()->zone()->Realloc<uint8_t>(ptr, old_size, new_size);
+}
 
+void Dwarf::WriteAbbreviations() {
+  // Dwarf data mostly takes the form of a tree, whose nodes are called
+  // DIEs. Each DIE begins with an abbreviation code, and the abbreviation
+  // describes the attributes of that DIE and their representation.
+
+  uint8_t* buffer = nullptr;
+  WriteStream stream(&buffer, ZoneReallocate, 64 * KB);
+
+  if (asm_stream_) {
 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
-  Print(".section __DWARF,__debug_abbrev,regular,debug\n");
+    Print(".section __DWARF,__debug_abbrev,regular,debug\n");
 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) ||                \
     defined(TARGET_OS_FUCHSIA)
-  Print(".section .debug_abbrev,\"\"\n");
+    Print(".section .debug_abbrev,\"\"\n");
 #else
-  UNIMPLEMENTED();
+    UNIMPLEMENTED();
 #endif
+  } else {
+    bin_stream_ = &stream;
+  }
 
   uleb128(kCompilationUnit);     // Abbrev code.
   uleb128(DW_TAG_compile_unit);  // Type.
@@ -219,25 +243,44 @@
   uleb128(0);  // End of attributes.
 
   uleb128(0);  // End of abbreviations.
+
+  if (elf_) {
+    elf_->AddDebug(".debug_abbrev", buffer, stream.bytes_written());
+    bin_stream_ = nullptr;
+  }
 }
 
 void Dwarf::WriteCompilationUnit() {
-// 7.5.1.1 Compilation Unit Header
+  uint8_t* buffer = nullptr;
+  WriteStream stream(&buffer, ZoneReallocate, 64 * KB);
 
+  if (asm_stream_) {
 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
-  Print(".section __DWARF,__debug_info,regular,debug\n");
+    Print(".section __DWARF,__debug_info,regular,debug\n");
 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) ||                \
     defined(TARGET_OS_FUCHSIA)
-  Print(".section .debug_info,\"\"\n");
+    Print(".section .debug_info,\"\"\n");
 #else
-  UNIMPLEMENTED();
+    UNIMPLEMENTED();
 #endif
-  Print(".Ldebug_info:\n");
+    Print(".Ldebug_info:\n");
+  } else {
+    bin_stream_ = &stream;
+  }
+
+  // 7.5.1.1 Compilation Unit Header
 
   // Unit length. Assignment to temp works around buggy Mac assembler.
-  Print("Lcu_size = .Lcu_end - .Lcu_start\n");
-  Print(".4byte Lcu_size\n");
-  Print(".Lcu_start:\n");
+  intptr_t cu_size_fixup = 0;
+  intptr_t cu_start = 0;
+  if (asm_stream_) {
+    Print("Lcu_size = .Lcu_end - .Lcu_start\n");
+    Print(".4byte Lcu_size\n");
+    Print(".Lcu_start:\n");
+  } else {
+    cu_size_fixup = u4(0);
+    cu_start = position();
+  }
 
   u2(2);              // DWARF version 2
   u4(0);              // debug_abbrev_offset
@@ -250,24 +293,32 @@
   const Library& root_library = Library::Handle(
       zone_, Isolate::Current()->object_store()->root_library());
   const String& root_uri = String::Handle(zone_, root_library.url());
-  Print(".string \"%s\"\n", root_uri.ToCString());  // DW_AT_name
-  Print(".string \"Dart VM\"\n");                   // DW_AT_producer
-  Print(".string \"\"\n");                          // DW_AT_comp_dir
+  string(root_uri.ToCString());  // DW_AT_name
+  string("Dart VM");             // DW_AT_producer
+  string("");                    // DW_AT_comp_dir
 
   // DW_AT_low_pc
   // The lowest instruction address in this object file that is part of our
   // compilation unit. Dwarf consumers use this to quickly decide which
   // compilation unit DIE to consult for a given pc.
-  Print(FORM_ADDR " _kDartIsolateSnapshotInstructions\n");
+  if (asm_stream_) {
+    Print(FORM_ADDR " _kDartIsolateSnapshotInstructions\n");
+  } else {
+    addr(0);
+  }
 
   // DW_AT_high_pc
   // The highest instruction address in this object file that is part of our
   // compilation unit. Dwarf consumers use this to quickly decide which
   // compilation unit DIE to consult for a given pc.
-  intptr_t last_code_index = codes_.length() - 1;
-  const Code& last_code = *(codes_[last_code_index]);
-  Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", last_code_index,
-        last_code.Size());
+  if (asm_stream_) {
+    intptr_t last_code_index = codes_.length() - 1;
+    const Code& last_code = *(codes_[last_code_index]);
+    Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", last_code_index,
+          last_code.Size());
+  } else {
+    addr(elf_->NextMemoryOffset());
+  }
 
   // DW_AT_stmt_list (offset into .debug_line)
   // Indicates which line number program is associated with this compilation
@@ -280,12 +331,23 @@
   uleb128(0);  // End of children.
 
   uleb128(0);  // End of entries.
-  Print(".Lcu_end:\n");
+
+  if (asm_stream_) {
+    Print(".Lcu_end:\n");
+  } else {
+    fixup_u4(cu_size_fixup, position() - cu_start);
+
+    elf_->AddDebug(".debug_info", buffer, stream.bytes_written());
+    bin_stream_ = nullptr;
+  }
 }
 
 void Dwarf::WriteAbstractFunctions() {
   Script& script = Script::Handle(zone_);
   String& name = String::Handle(zone_);
+  if (!asm_stream_) {
+    abstract_origins_ = zone_->Alloc<uint32_t>(functions_.length());
+  }
   for (intptr_t i = 0; i < functions_.length(); i++) {
     const Function& function = *(functions_[i]);
     name = function.QualifiedUserVisibleName();
@@ -293,13 +355,18 @@
     intptr_t file = LookupScript(script);
     intptr_t line = 0;  // Not known. Script has already lost its token stream.
 
-    Print(".Lfunc%" Pd ":\n", i);  // Label for DW_AT_abstract_origin references
+    if (asm_stream_) {
+      Print(".Lfunc%" Pd ":\n",
+            i);  // Label for DW_AT_abstract_origin references
+    } else {
+      abstract_origins_[i] = position();
+    }
     uleb128(kAbstractFunction);
-    Print(".string \"%s\"\n", name.ToCString());  // DW_AT_name
-    uleb128(file);                                // DW_AT_decl_file
-    uleb128(line);                                // DW_AT_decl_line
-    uleb128(DW_INL_inlined);                      // DW_AT_inline
-    uleb128(0);                                   // End of children.
+    string(name.ToCString());  // DW_AT_name
+    uleb128(file);             // DW_AT_decl_file
+    uleb128(line);             // DW_AT_decl_line
+    uleb128(DW_INL_inlined);   // DW_AT_inline
+    uleb128(0);                // End of children.
   }
 }
 
@@ -312,6 +379,11 @@
     if (!code.IsFunctionCode()) {
       continue;
     }
+
+    CodeIndexPair* pair = code_to_index_.Lookup(&code);
+    RELEASE_ASSERT(pair != NULL);
+    intptr_t code_offset = pair->index_;
+
     function = code.function();
     intptr_t function_index = LookupFunction(function);
     script = function.script();
@@ -320,15 +392,27 @@
     // DW_AT_abstract_origin
     // References a node written above in WriteAbstractFunctions.
     // Assignment to temp works around buggy Mac assembler.
-    intptr_t temp = temp_++;
-    Print("Ltemp%" Pd " = .Lfunc%" Pd " - .Ldebug_info\n", temp,
-          function_index);
-    Print(".4byte Ltemp%" Pd "\n", temp);
+    if (asm_stream_) {
+      intptr_t temp = temp_++;
+      Print("Ltemp%" Pd " = .Lfunc%" Pd " - .Ldebug_info\n", temp,
+            function_index);
+      Print(".4byte Ltemp%" Pd "\n", temp);
+    } else {
+      u4(abstract_origins_[function_index]);
+    }
 
     // DW_AT_low_pc
-    Print(FORM_ADDR " .Lcode%" Pd "\n", i);
+    if (asm_stream_) {
+      Print(FORM_ADDR " .Lcode%" Pd "\n", i);
+    } else {
+      addr(code_offset);
+    }
     // DW_AT_high_pc
-    Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", i, code.Size());
+    if (asm_stream_) {
+      Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", i, code.Size());
+    } else {
+      addr(code_offset + code.Size());
+    }
 
     InliningNode* node = ExpandInliningTree(code);
     if (node != NULL) {
@@ -435,15 +519,28 @@
   // DW_AT_abstract_origin
   // References a node written above in WriteAbstractFunctions.
   // Assignment to temp works around buggy Mac assembler.
-  intptr_t temp = temp_++;
-  Print("Ltemp%" Pd " = .Lfunc%" Pd " - .Ldebug_info\n", temp, function_index);
-  Print(".4byte Ltemp%" Pd "\n", temp);
+  if (asm_stream_) {
+    intptr_t temp = temp_++;
+    Print("Ltemp%" Pd " = .Lfunc%" Pd " - .Ldebug_info\n", temp,
+          function_index);
+    Print(".4byte Ltemp%" Pd "\n", temp);
+  } else {
+    u4(abstract_origins_[function_index]);
+  }
   // DW_AT_low_pc
-  Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
-        node->start_pc_offset);
+  if (asm_stream_) {
+    Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
+          node->start_pc_offset);
+  } else {
+    addr(root_code_index + node->start_pc_offset);
+  }
   // DW_AT_high_pc
-  Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
-        node->end_pc_offset);
+  if (asm_stream_) {
+    Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
+          node->end_pc_offset);
+  } else {
+    addr(root_code_index + node->end_pc_offset);
+  }
   // DW_AT_call_file
   uleb128(file);
   // DW_AT_call_line
@@ -458,30 +555,50 @@
 }
 
 void Dwarf::WriteLines() {
+  uint8_t* buffer = nullptr;
+  WriteStream stream(&buffer, ZoneReallocate, 64 * KB);
+
+  if (asm_stream_) {
 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
-  Print(".section __DWARF,__debug_line,regular,debug\n");
+    Print(".section __DWARF,__debug_line,regular,debug\n");
 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) ||                \
     defined(TARGET_OS_FUCHSIA)
-  Print(".section .debug_line,\"\"\n");
+    Print(".section .debug_line,\"\"\n");
 #else
-  UNIMPLEMENTED();
+    UNIMPLEMENTED();
 #endif
+  } else {
+    bin_stream_ = &stream;
+  }
 
   // 6.2.4 The Line Number Program Header
 
   // 1. unit_length. This encoding implies 32-bit DWARF.
-  Print("Lline_size = .Lline_end - .Lline_start\n");
-  Print(".4byte Lline_size\n");
-
-  Print(".Lline_start:\n");
+  intptr_t line_size_fixup = 0;
+  intptr_t line_start = 0;
+  if (asm_stream_) {
+    Print("Lline_size = .Lline_end - .Lline_start\n");
+    Print(".4byte Lline_size\n");
+    Print(".Lline_start:\n");
+  } else {
+    line_size_fixup = u4(0);
+    line_start = position();
+  }
 
   u2(2);  // 2. DWARF version 2
 
   // 3. header_length
   // Assignment to temp works around buggy Mac assembler.
-  Print("Llineheader_size = .Llineheader_end - .Llineheader_start\n");
-  Print(".4byte Llineheader_size\n");
-  Print(".Llineheader_start:\n");
+  intptr_t lineheader_size_fixup = 0;
+  intptr_t lineheader_start = 0;
+  if (asm_stream_) {
+    Print("Llineheader_size = .Llineheader_end - .Llineheader_start\n");
+    Print(".4byte Llineheader_size\n");
+    Print(".Llineheader_start:\n");
+  } else {
+    lineheader_size_fixup = u4(0);
+    lineheader_start = position();
+  }
 
   u1(1);   // 4. minimum_instruction_length
   u1(1);   // 5. default_is_stmt (true for compatibility with dsymutil).
@@ -512,20 +629,24 @@
   for (intptr_t i = 0; i < scripts_.length(); i++) {
     const Script& script = *(scripts_[i]);
     uri = script.url();
-    Print(".string \"%s\"\n", uri.ToCString());
+    string(uri.ToCString());  // NOLINT
     uleb128(0);  // Include directory index.
     uleb128(0);  // File modification time.
     uleb128(0);  // File length.
   }
   u1(0);  // End of file names.
 
-  Print(".Llineheader_end:\n");
+  if (asm_stream_) {
+    Print(".Llineheader_end:\n");
+  } else {
+    fixup_u4(lineheader_size_fixup, position() - lineheader_start);
+  }
 
   // 6.2.5 The Line Number Program
 
   intptr_t previous_file = 1;
   intptr_t previous_line = 1;
-  intptr_t previous_code_index = -1;
+  intptr_t previous_code_offset = -1;
   intptr_t previous_pc_offset = 0;
 
   Function& root_function = Function::Handle(zone_);
@@ -537,6 +658,11 @@
 
   for (intptr_t i = 0; i < codes_.length(); i++) {
     const Code& code = *(codes_[i]);
+
+    CodeIndexPair* pair = code_to_index_.Lookup(&code);
+    RELEASE_ASSERT(pair != NULL);
+    intptr_t current_code_offset = pair->index_;
+
     map = code.code_source_map();
     if (map.IsNull()) {
       continue;
@@ -591,18 +717,30 @@
           u1(DW_LNS_copy);
 
           // 4. Update LNP pc.
-          if (previous_code_index == -1) {
+          if (previous_code_offset == -1) {
             // This variant is relocatable.
             u1(0);                  // This is an extended opcode
             u1(1 + sizeof(void*));  // that is 5 or 9 bytes long
             u1(DW_LNE_set_address);
-            Print(FORM_ADDR " .Lcode%" Pd " + %d\n", i, current_pc_offset);
+            if (asm_stream_) {
+              Print(FORM_ADDR " .Lcode%" Pd " + %d\n", i, current_pc_offset);
+            } else {
+              addr(current_code_offset + current_pc_offset);
+            }
           } else {
             u1(DW_LNS_advance_pc);
-            Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", i,
-                  previous_code_index, current_pc_offset - previous_pc_offset);
+            if (asm_stream_) {
+              Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", i,
+                    previous_code_offset,
+                    current_pc_offset - previous_pc_offset);
+            } else {
+              intptr_t delta = current_code_offset - previous_code_offset +
+                               current_pc_offset - previous_pc_offset;
+              RELEASE_ASSERT(delta > 0);
+              uleb128(delta);
+            }
           }
-          previous_code_index = i;
+          previous_code_offset = current_code_offset;
           previous_pc_offset = current_pc_offset;
           break;
         }
@@ -635,16 +773,35 @@
   // Advance pc to end of the compilation unit.
   intptr_t last_code_index = codes_.length() - 1;
   const Code& last_code = *(codes_[last_code_index]);
+
+  CodeIndexPair* pair = code_to_index_.Lookup(&last_code);
+  RELEASE_ASSERT(pair != NULL);
+  intptr_t last_code_offset = pair->index_;
+
   u1(DW_LNS_advance_pc);
-  Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", last_code_index,
-        previous_code_index, last_code.Size() - previous_pc_offset);
+  if (asm_stream_) {
+    Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", last_code_index,
+          previous_code_offset, last_code.Size() - previous_pc_offset);
+  } else {
+    intptr_t delta = last_code_offset - previous_code_offset +
+                     last_code.Size() - previous_pc_offset;
+    RELEASE_ASSERT(delta >= 0);
+    uleb128(delta);
+  }
 
   // End of contiguous machine code.
   u1(0);  // This is an extended opcode
   u1(1);  // that is 1 byte long
   u1(DW_LNE_end_sequence);
 
-  Print(".Lline_end:\n");
+  if (asm_stream_) {
+    Print(".Lline_end:\n");
+  } else {
+    fixup_u4(line_size_fixup, position() - line_start);
+
+    elf_->AddDebug(".debug_line", buffer, stream.bytes_written());
+    bin_stream_ = nullptr;
+  }
 }
 
 #endif  // DART_PRECOMPILER
diff --git a/runtime/vm/dwarf.h b/runtime/vm/dwarf.h
index cd68542..7d4f5b7 100644
--- a/runtime/vm/dwarf.h
+++ b/runtime/vm/dwarf.h
@@ -14,6 +14,7 @@
 
 #ifdef DART_PRECOMPILER
 
+class Elf;
 class InliningNode;
 
 struct ScriptIndexPair {
@@ -117,8 +118,9 @@
 
 class Dwarf : public ZoneAllocated {
  public:
-  Dwarf(Zone* zone, StreamingWriteStream* stream);
+  Dwarf(Zone* zone, StreamingWriteStream* stream, Elf* elf);
 
+  void AddCode(const Code& code, intptr_t offset);
   intptr_t AddCode(const Code& code);
   intptr_t AddFunction(const Function& function);
   intptr_t AddScript(const Script& script);
@@ -181,11 +183,100 @@
   };
 
   void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
-  void sleb128(intptr_t value) { Print(".sleb128 %" Pd "\n", value); }
-  void uleb128(uintptr_t value) { Print(".uleb128 %" Pd "\n", value); }
-  void u1(uint8_t value) { Print(".byte %d\n", value); }
-  void u2(uint16_t value) { Print(".2byte %d\n", value); }
-  void u4(uint32_t value) { Print(".4byte %d\n", value); }
+  void sleb128(intptr_t value) {
+    if (asm_stream_) {
+      Print(".sleb128 %" Pd "\n", value);
+    } else {
+      bool is_last_part = false;
+      while (!is_last_part) {
+        uint8_t part = value & 0x7F;
+        value >>= 7;
+        if ((value == 0 && (part & 0x40) == 0) ||
+            (value == static_cast<intptr_t>(-1) && (part & 0x40) != 0)) {
+          is_last_part = true;
+        } else {
+          part |= 0x80;
+        }
+        bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&part),
+                                sizeof(part));
+      }
+    }
+  }
+  void uleb128(uintptr_t value) {
+    if (asm_stream_) {
+      Print(".uleb128 %" Pd "\n", value);
+    } else {
+      bool is_last_part = false;
+      while (!is_last_part) {
+        uint8_t part = value & 0x7F;
+        value >>= 7;
+        if (value == 0) {
+          is_last_part = true;
+        } else {
+          part |= 0x80;
+        }
+        bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&part),
+                                sizeof(part));
+      }
+    }
+  }
+  void u1(uint8_t value) {
+    if (asm_stream_) {
+      Print(".byte %d\n", value);
+    } else {
+      bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&value),
+                              sizeof(value));
+    }
+  }
+  void u2(uint16_t value) {
+    if (asm_stream_) {
+      Print(".2byte %d\n", value);
+    } else {
+      bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&value),
+                              sizeof(value));
+    }
+  }
+  intptr_t u4(uint32_t value) {
+    if (asm_stream_) {
+      Print(".4byte %d\n", value);
+      return -1;
+    } else {
+      intptr_t fixup = position();
+      bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&value),
+                              sizeof(value));
+      return fixup;
+    }
+  }
+  void fixup_u4(intptr_t position, uint32_t value) {
+    if (asm_stream_) {
+      UNREACHABLE();
+    } else {
+      memmove(bin_stream_->buffer() + position, &value, sizeof(value));
+    }
+  }
+  void addr(uword value) {
+    if (asm_stream_) {
+      UNREACHABLE();
+    } else {
+      bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&value),
+                              sizeof(value));
+    }
+  }
+  void string(const char* cstr) {  // NOLINT
+    if (asm_stream_) {
+      Print(".string \"%s\"\n", cstr);  // NOLINT
+    } else {
+      bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(cstr),
+                              strlen(cstr) + 1);
+    }
+  }
+  intptr_t position() {
+    if (asm_stream_) {
+      UNREACHABLE();
+    } else {
+      return bin_stream_->Position();
+    }
+  }
 
   void WriteAbbreviations();
   void WriteCompilationUnit();
@@ -198,13 +289,16 @@
   void WriteLines();
 
   Zone* const zone_;
-  StreamingWriteStream* stream_;
+  Elf* const elf_;
+  StreamingWriteStream* asm_stream_;
+  WriteStream* bin_stream_;
   ZoneGrowableArray<const Code*> codes_;
   CodeIndexMap code_to_index_;
   ZoneGrowableArray<const Function*> functions_;
   FunctionIndexMap function_to_index_;
   ZoneGrowableArray<const Script*> scripts_;
   ScriptIndexMap script_to_index_;
+  uint32_t* abstract_origins_;
   intptr_t temp_;
 };
 
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
new file mode 100644
index 0000000..206ead1
--- /dev/null
+++ b/runtime/vm/elf.cc
@@ -0,0 +1,750 @@
+// Copyright (c) 2019, 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/elf.h"
+
+#include "platform/text_buffer.h"
+#include "vm/cpu.h"
+#include "vm/thread.h"
+
+namespace dart {
+
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+
+static const intptr_t ELFDATA2LSB = 1;
+
+static const intptr_t ELFOSABI_SYSV = 0;
+
+#define EF_ARM_ABI_FLOAT_HARD 0x00000400
+#define EF_ARM_ABI_FLOAT_SOFT 0x00000200
+#define EF_ARM_ABI 0x05000000
+
+static const intptr_t ET_DYN = 3;
+
+#define EM_386 3
+#define EM_ARM 40
+#define EM_X86_64 62
+#define EM_AARCH64 183
+
+static const intptr_t EV_CURRENT = 1;
+
+static const intptr_t SHT_PROGBITS = 1;
+static const intptr_t SHT_STRTAB = 3;
+static const intptr_t SHT_HASH = 5;
+static const intptr_t SHT_DYNSYM = 11;
+static const intptr_t SHT_DYNAMIC = 6;
+
+static const intptr_t SHF_WRITE = 0x1;
+static const intptr_t SHF_ALLOC = 0x2;
+static const intptr_t SHF_EXECINSTR = 0x4;
+
+static const intptr_t SHN_UNDEF = 0;
+
+static const intptr_t STN_UNDEF = 0;
+
+static const intptr_t PT_LOAD = 1;
+static const intptr_t PT_DYNAMIC = 2;
+static const intptr_t PT_PHDR = 6;
+
+static const intptr_t PF_X = 1;
+static const intptr_t PF_W = 2;
+static const intptr_t PF_R = 4;
+
+static const intptr_t STB_GLOBAL = 1;
+
+static const intptr_t STT_OBJECT = 1;  // I.e., data.
+static const intptr_t STT_FUNC = 2;
+
+static const intptr_t DT_HASH = 4;
+static const intptr_t DT_STRTAB = 5;
+static const intptr_t DT_SYMTAB = 6;
+static const intptr_t DT_STRSZ = 10;
+static const intptr_t DT_SYMENT = 11;
+
+#if defined(TARGET_ARCH_IS_32_BIT)
+static const intptr_t kElfHeaderSize = 52;
+static const intptr_t kElfSectionTableEntrySize = 40;
+static const intptr_t kElfProgramTableEntrySize = 32;
+static const intptr_t kElfSymbolTableEntrySize = 16;
+static const intptr_t kElfDynamicTableEntrySize = 8;
+#else
+static const intptr_t kElfHeaderSize = 64;
+static const intptr_t kElfSectionTableEntrySize = 64;
+static const intptr_t kElfProgramTableEntrySize = 56;
+static const intptr_t kElfSymbolTableEntrySize = 24;
+static const intptr_t kElfDynamicTableEntrySize = 16;
+#endif
+
+static const intptr_t kPageSize = 4096;
+
+class Section : public ZoneAllocated {
+ public:
+  Section() {}
+
+  virtual ~Section() {}
+  virtual void Write(Elf* stream) = 0;
+
+  // Linker view.
+  intptr_t section_name = 0;  // Index into string table.
+  intptr_t section_type = 0;
+  intptr_t section_flags = 0;
+  intptr_t section_index = -1;
+  intptr_t section_link = SHN_UNDEF;
+  intptr_t section_info = 0;
+  intptr_t section_entry_size = 0;
+  intptr_t file_size = 0;
+  intptr_t file_offset = -1;
+
+  intptr_t alignment = 1;
+
+  // Loader view.
+  intptr_t segment_type = -1;
+  intptr_t segment_flags = 0;
+  intptr_t memory_size = 0;
+  intptr_t memory_offset = -1;
+};
+
+class ProgramBits : public Section {
+ public:
+  ProgramBits(bool allocate,
+              bool executable,
+              const uint8_t* bytes,
+              intptr_t size) {
+    section_type = SHT_PROGBITS;
+    if (allocate) {
+      section_flags = SHF_ALLOC;
+      if (executable) section_flags |= SHF_EXECINSTR;
+
+      segment_type = PT_LOAD;
+      segment_flags = PF_R;
+      if (executable) segment_flags |= PF_X;
+    }
+
+    bytes_ = bytes;
+    file_size = memory_size = size;
+  }
+
+  void Write(Elf* stream) { stream->WriteBytes(bytes_, memory_size); }
+
+  const uint8_t* bytes_;
+};
+
+class StringTable : public Section {
+ public:
+  StringTable() : text_(128) {
+    section_type = SHT_STRTAB;
+    section_flags = SHF_ALLOC;
+    segment_type = PT_LOAD;
+    segment_flags = PF_R;
+
+    text_.AddChar('\0');
+    memory_size = file_size = text_.length();
+  }
+
+  intptr_t AddString(const char* str) {
+    intptr_t offset = text_.length();
+    text_.AddString(str);
+    text_.AddChar('\0');
+    memory_size = file_size = text_.length();
+    return offset;
+  }
+
+  void Write(Elf* stream) {
+    stream->WriteBytes(reinterpret_cast<const uint8_t*>(text_.buf()),
+                       text_.length());
+  }
+
+  TextBuffer text_;
+};
+
+class Symbol : public ZoneAllocated {
+ public:
+  const char* cstr;
+  intptr_t name;
+  intptr_t info;
+  intptr_t section;
+  intptr_t offset;
+  intptr_t size;
+};
+
+class SymbolTable : public Section {
+ public:
+  SymbolTable() {
+    section_type = SHT_DYNSYM;
+    section_flags = SHF_ALLOC;
+    segment_type = PT_LOAD;
+    segment_flags = PF_R;
+
+    section_entry_size = kElfSymbolTableEntrySize;
+    AddSymbol(NULL);
+    section_info = 1;  // One "local" symbol, the reserved first entry.
+  }
+
+  void AddSymbol(Symbol* symbol) {
+    symbols_.Add(symbol);
+    memory_size += kElfSymbolTableEntrySize;
+    file_size += kElfSymbolTableEntrySize;
+  }
+
+  void Write(Elf* stream) {
+    // The first symbol table entry is reserved and must be all zeros.
+    {
+      const intptr_t start = stream->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+      stream->WriteWord(0);
+      stream->WriteAddr(0);
+      stream->WriteWord(0);
+      stream->WriteByte(0);
+      stream->WriteByte(0);
+      stream->WriteHalf(0);
+#else
+      stream->WriteWord(0);
+      stream->WriteByte(0);
+      stream->WriteByte(0);
+      stream->WriteHalf(0);
+      stream->WriteAddr(0);
+      stream->WriteXWord(0);
+#endif
+      const intptr_t end = stream->position();
+      ASSERT((end - start) == kElfSymbolTableEntrySize);
+    }
+
+    for (intptr_t i = 1; i < symbols_.length(); i++) {
+      Symbol* symbol = symbols_[i];
+      const intptr_t start = stream->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+      stream->WriteWord(symbol->name);
+      stream->WriteAddr(symbol->offset);
+      stream->WriteWord(symbol->size);
+      stream->WriteByte(symbol->info);
+      stream->WriteByte(0);
+      stream->WriteHalf(symbol->section);
+#else
+      stream->WriteWord(symbol->name);
+      stream->WriteByte(symbol->info);
+      stream->WriteByte(0);
+      stream->WriteHalf(symbol->section);
+      stream->WriteAddr(symbol->offset);
+      stream->WriteXWord(symbol->size);
+#endif
+      const intptr_t end = stream->position();
+      ASSERT((end - start) == kElfSymbolTableEntrySize);
+    }
+  }
+
+  intptr_t length() const { return symbols_.length(); }
+  Symbol* at(intptr_t i) const { return symbols_[i]; }
+
+  GrowableArray<Symbol*> symbols_;
+};
+
+static uint32_t ElfHash(const unsigned char* name) {
+  uint32_t h = 0;
+  while (*name) {
+    h = (h << 4) + *name++;
+    uint32_t g = h & 0xf0000000;
+    h ^= g;
+    h ^= g >> 24;
+  }
+  return h;
+}
+
+class SymbolHashTable : public Section {
+ public:
+  SymbolHashTable(StringTable* strtab, SymbolTable* symtab) {
+    section_type = SHT_HASH;
+    section_flags = SHF_ALLOC;
+    section_link = symtab->section_index;
+    segment_type = PT_LOAD;
+    segment_flags = PF_R;
+
+    nchain_ = symtab->length();
+    nbucket_ = symtab->length();
+
+    bucket_ = Thread::Current()->zone()->Alloc<int32_t>(nbucket_);
+    for (intptr_t i = 0; i < nbucket_; i++) {
+      bucket_[i] = STN_UNDEF;
+    }
+
+    chain_ = Thread::Current()->zone()->Alloc<int32_t>(nchain_);
+    for (intptr_t i = 0; i < nchain_; i++) {
+      chain_[i] = STN_UNDEF;
+    }
+
+    for (intptr_t i = 1; i < symtab->length(); i++) {
+      Symbol* symbol = symtab->at(i);
+      uint32_t hash = ElfHash((const unsigned char*)symbol->cstr);
+      uint32_t probe = hash % nbucket_;
+      chain_[i] = bucket_[probe];  // next = head
+      bucket_[probe] = i;          // head = symbol
+    }
+
+    memory_size = file_size = 4 * (nbucket_ + nchain_ + 2);
+  }
+
+  void Write(Elf* stream) {
+    stream->WriteWord(nbucket_);
+    stream->WriteWord(nchain_);
+    for (intptr_t i = 0; i < nbucket_; i++) {
+      stream->WriteWord(bucket_[i]);
+    }
+    for (intptr_t i = 0; i < nchain_; i++) {
+      stream->WriteWord(chain_[i]);
+    }
+  }
+
+ private:
+  int32_t nbucket_;
+  int32_t nchain_;
+  int32_t* bucket_;  // "Head"
+  int32_t* chain_;   // "Next"
+};
+
+class DynamicTable : public Section {
+ public:
+  DynamicTable(StringTable* strtab,
+               SymbolTable* symtab,
+               SymbolHashTable* hash) {
+    section_type = SHT_DYNAMIC;
+    section_link = strtab->section_index;
+    section_flags = SHF_ALLOC | SHF_WRITE;
+    section_entry_size = kElfDynamicTableEntrySize;
+
+    segment_type = PT_LOAD;
+    segment_flags = PF_R | PF_W;
+
+    AddEntry(DT_HASH, hash->memory_offset);
+    AddEntry(DT_STRTAB, strtab->memory_offset);
+    AddEntry(DT_STRSZ, strtab->memory_size);
+    AddEntry(DT_SYMTAB, symtab->memory_offset);
+    AddEntry(DT_SYMENT, kElfSymbolTableEntrySize);
+  }
+
+  void Write(Elf* stream) {
+    for (intptr_t i = 0; i < entries_.length(); i++) {
+      const intptr_t start = stream->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+      stream->WriteWord(entries_[i]->tag);
+      stream->WriteAddr(entries_[i]->value);
+#else
+      stream->WriteXWord(entries_[i]->tag);
+      stream->WriteAddr(entries_[i]->value);
+#endif
+      const intptr_t end = stream->position();
+      ASSERT((end - start) == kElfDynamicTableEntrySize);
+    }
+  }
+
+  class Entry {
+   public:
+    intptr_t tag;
+    intptr_t value;
+  };
+
+  void AddEntry(intptr_t tag, intptr_t value) {
+    Entry* entry = new Entry();
+    entry->tag = tag;
+    entry->value = value;
+    entries_.Add(entry);
+
+    memory_size += kElfDynamicTableEntrySize;
+    file_size += kElfDynamicTableEntrySize;
+  }
+
+ private:
+  GrowableArray<Entry*> entries_;
+};
+
+static uint8_t kNothing = 0;
+
+// The first section must be written out and contains only zeros.
+static const intptr_t kNumInvalidSections = 1;
+
+// Extra segments put in the program table that aren't reified in
+// Elf::segments_.
+static const intptr_t kNumImplicitSegments = 3;
+
+Elf::Elf(Zone* zone, StreamingWriteStream* stream)
+    : zone_(zone), stream_(stream), memory_offset_(0) {
+  // Assumed by various offset logic in this file.
+  ASSERT(stream_->position() == 0);
+
+  // We don't bother with a separate .shstrtab since all our strings will fit
+  // in a single page.
+  strtab_ = new (zone_) StringTable();
+  strtab_->section_name = strtab_->AddString(".dynstr");
+  AddSection(strtab_);
+
+  symtab_ = new (zone_) SymbolTable();
+  symtab_->section_name = strtab_->AddString(".dynsym");
+  symtab_->section_link = strtab_->section_index;
+  AddSection(symtab_);
+
+  // dlsym gets confused if a symbol's value is dso offset 0, treating this as a
+  // failed lookup instead of answering dso base + 0. dladdr answers the wrong
+  // dso base if we don't start allocating from 0 (answering the address of
+  // either the first or lowest PT_LOAD). Sacrifice the first page to work
+  // around these issues. (gcc places build metadata in the first page.)
+  AddROData("nothing", &kNothing, sizeof(kNothing));
+}
+
+void Elf::AddSection(Section* section) {
+  section->section_index = sections_.length() + kNumInvalidSections;
+  sections_.Add(section);
+}
+
+void Elf::AddSegment(Section* section) {
+  if (section->alignment < kPageSize) {
+    section->alignment = kPageSize;
+  }
+
+  memory_offset_ = Utils::RoundUp(memory_offset_, section->alignment);
+  section->memory_offset = memory_offset_;
+  memory_offset_ += section->memory_size;
+  segments_.Add(section);
+  memory_offset_ = Utils::RoundUp(memory_offset_, kPageSize);
+}
+
+intptr_t Elf::NextMemoryOffset() {
+  return memory_offset_;
+}
+
+intptr_t Elf::AddText(const char* name, const uint8_t* bytes, intptr_t size) {
+  ProgramBits* image = new (zone_) ProgramBits(true, true, bytes, size);
+  image->section_name = strtab_->AddString(".text");
+  AddSection(image);
+  AddSegment(image);
+
+  Symbol* symbol = new (zone_) Symbol();
+  symbol->cstr = name;
+  symbol->name = strtab_->AddString(name);
+  symbol->info = (STB_GLOBAL << 4) | STT_FUNC;
+  symbol->section = image->section_index;
+  // For shared libraries, this is the offset from the DSO base. For static
+  // libraries, this is section relative.
+  symbol->offset = image->memory_offset;
+  symbol->size = size;
+  symtab_->AddSymbol(symbol);
+
+  return symbol->offset;
+}
+
+intptr_t Elf::AddROData(const char* name, const uint8_t* bytes, intptr_t size) {
+  ProgramBits* image = new (zone_) ProgramBits(true, false, bytes, size);
+  image->section_name = strtab_->AddString(".rodata");
+  AddSection(image);
+  AddSegment(image);
+
+  Symbol* symbol = new (zone_) Symbol();
+  symbol->cstr = name;
+  symbol->name = strtab_->AddString(name);
+  symbol->info = (STB_GLOBAL << 4) | STT_OBJECT;
+  symbol->section = image->section_index;
+  // For shared libraries, this is the offset from the DSO base. For static
+  // libraries, this is section relative.
+  symbol->offset = image->memory_offset;
+  symbol->size = size;
+  symtab_->AddSymbol(symbol);
+
+  return symbol->offset;
+}
+
+void Elf::AddDebug(const char* name, const uint8_t* bytes, intptr_t size) {
+  ProgramBits* image = new (zone_) ProgramBits(false, false, bytes, size);
+  image->section_name = strtab_->AddString(name);
+  AddSection(image);
+}
+
+void Elf::Finalize() {
+  SymbolHashTable* hash = new (zone_) SymbolHashTable(strtab_, symtab_);
+  hash->section_name = strtab_->AddString(".hash");
+  AddSection(hash);
+  AddSegment(hash);
+
+  // Before finalizing the string table's memory size:
+  intptr_t name_dynamic = strtab_->AddString(".dynamic");
+
+  // Finalizes memory size of string and symbol tables.
+  AddSegment(strtab_);
+  AddSegment(symtab_);
+
+  dynamic_ = new (zone_) DynamicTable(strtab_, symtab_, hash);
+  dynamic_->section_name = name_dynamic;
+  AddSection(dynamic_);
+  AddSegment(dynamic_);
+
+  ComputeFileOffsets();
+
+  WriteHeader();
+  WriteProgramTable();
+  WriteSectionTable();
+  WriteSections();
+}
+
+void Elf::ComputeFileOffsets() {
+  intptr_t file_offset = kElfHeaderSize;
+
+  file_offset = Utils::RoundUp(file_offset, kPageSize);
+  program_table_file_offset_ = file_offset;
+  program_table_file_size_ =
+      (segments_.length() + kNumImplicitSegments) * kElfProgramTableEntrySize;
+  file_offset += program_table_file_size_;
+
+  section_table_file_offset_ = file_offset;
+  section_table_file_size_ =
+      (sections_.length() + kNumInvalidSections) * kElfSectionTableEntrySize;
+  file_offset += section_table_file_size_;
+
+  for (intptr_t i = 0; i < sections_.length(); i++) {
+    Section* section = sections_[i];
+    file_offset = Utils::RoundUp(file_offset, section->alignment);
+    section->file_offset = file_offset;
+    file_offset += section->file_size;
+    file_offset = Utils::RoundUp(file_offset, section->alignment);
+  }
+}
+
+void Elf::WriteHeader() {
+#if defined(TARGET_ARCH_IS_32_BIT)
+  uint8_t size = ELFCLASS32;
+#else
+  uint8_t size = ELFCLASS64;
+#endif
+  uint8_t e_ident[16] = {
+      0x7f, 'E', 'L', 'F', size, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV,
+      0,    0,   0,   0,   0,    0,           0,          0};
+  stream_->WriteBytes(e_ident, 16);
+
+  WriteHalf(ET_DYN);  // Shared library.
+
+#if defined(TARGET_ARCH_IA32)
+  WriteHalf(EM_386);
+#elif defined(TARGET_ARCH_X64)
+  WriteHalf(EM_X86_64);
+#elif defined(TARGET_ARCH_ARM)
+  WriteHalf(EM_ARM);
+#elif defined(TARGET_ARCH_ARM64)
+  WriteHalf(EM_AARCH64);
+#else
+  // E.g., DBC.
+  FATAL("Unknown ELF architecture");
+#endif
+
+  WriteWord(EV_CURRENT);  // Version
+  WriteAddr(0);           // "Entry point"
+  WriteOff(program_table_file_offset_);
+  WriteOff(section_table_file_offset_);
+
+#if defined(TARGET_ARCH_ARM)
+  uword flags = EF_ARM_ABI |
+                (TargetCPUFeatures::hardfp_supported() ? EF_ARM_ABI_FLOAT_HARD
+                                                       : EF_ARM_ABI_FLOAT_SOFT);
+#else
+  uword flags = 0;
+#endif
+  WriteWord(flags);
+
+  WriteHalf(kElfHeaderSize);
+  WriteHalf(kElfProgramTableEntrySize);
+  WriteHalf(segments_.length() + kNumImplicitSegments);
+  WriteHalf(kElfSectionTableEntrySize);
+  WriteHalf(sections_.length() + kNumInvalidSections);
+  WriteHalf(strtab_->section_index);
+
+  ASSERT(stream_->position() == kElfHeaderSize);
+}
+
+void Elf::WriteProgramTable() {
+  stream_->Align(kPageSize);
+
+  ASSERT(stream_->position() == program_table_file_offset_);
+
+  // Self-reference to program header table that Android wants for some reason.
+  // Must appear before any PT_LOAD entries.
+  {
+    ASSERT(kNumImplicitSegments == 3);
+    const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+    WriteWord(PT_PHDR);
+    WriteOff(program_table_file_offset_);
+    WriteAddr(memory_offset_);
+    WriteAddr(0);  // Physical address, not used.
+    WriteWord(program_table_file_size_);
+    WriteWord(program_table_file_size_);
+    WriteWord(PF_R);
+    WriteWord(kPageSize);
+#else
+    WriteWord(PT_PHDR);
+    WriteWord(PF_R);
+    WriteOff(program_table_file_offset_);
+    WriteAddr(memory_offset_);
+    WriteAddr(0);  // Physical address, not used.
+    WriteXWord(program_table_file_size_);
+    WriteXWord(program_table_file_size_);
+    WriteXWord(kPageSize);
+#endif
+    const intptr_t end = stream_->position();
+    ASSERT((end - start) == kElfProgramTableEntrySize);
+  }
+
+  for (intptr_t i = 0; i < segments_.length(); i++) {
+    Section* section = segments_[i];
+    const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+    WriteWord(section->segment_type);
+    WriteOff(section->file_offset);
+    WriteAddr(section->memory_offset);
+    WriteAddr(0);  // Physical address, not used.
+    WriteWord(section->file_size);
+    WriteWord(section->memory_size);
+    WriteWord(section->segment_flags);
+    WriteWord(section->alignment);
+#else
+    WriteWord(section->segment_type);
+    WriteWord(section->segment_flags);
+    WriteOff(section->file_offset);
+    WriteAddr(section->memory_offset);
+    WriteAddr(0);  // Physical address, not used.
+    WriteXWord(section->file_size);
+    WriteXWord(section->memory_size);
+    WriteXWord(section->alignment);
+#endif
+    const intptr_t end = stream_->position();
+    ASSERT((end - start) == kElfProgramTableEntrySize);
+  }
+
+  // Special case: the dynamic section requires both LOAD and DYNAMIC program
+  // header table entries.
+  {
+    ASSERT(kNumImplicitSegments == 3);
+    const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+    WriteWord(PT_DYNAMIC);
+    WriteOff(dynamic_->file_offset);
+    WriteAddr(dynamic_->memory_offset);
+    WriteAddr(0);  // Physical address, not used.
+    WriteWord(dynamic_->file_size);
+    WriteWord(dynamic_->memory_size);
+    WriteWord(dynamic_->segment_flags);
+    WriteWord(dynamic_->alignment);
+#else
+    WriteWord(PT_DYNAMIC);
+    WriteWord(dynamic_->segment_flags);
+    WriteOff(dynamic_->file_offset);
+    WriteAddr(dynamic_->memory_offset);
+    WriteAddr(0);  // Physical address, not used.
+    WriteXWord(dynamic_->file_size);
+    WriteXWord(dynamic_->memory_size);
+    WriteXWord(dynamic_->alignment);
+#endif
+    const intptr_t end = stream_->position();
+    ASSERT((end - start) == kElfProgramTableEntrySize);
+  }
+
+  // Self-reference to program header table that Android wants for some reason.
+  {
+    ASSERT(kNumImplicitSegments == 3);
+    const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+    WriteWord(PT_LOAD);
+    WriteOff(program_table_file_offset_);
+    WriteAddr(memory_offset_);
+    WriteAddr(0);  // Physical address, not used.
+    WriteWord(program_table_file_size_);
+    WriteWord(program_table_file_size_);
+    WriteWord(PF_R);
+    WriteWord(kPageSize);
+#else
+    WriteWord(PT_LOAD);
+    WriteWord(PF_R);
+    WriteOff(program_table_file_offset_);
+    WriteAddr(memory_offset_);
+    WriteAddr(0);  // Physical address, not used.
+    WriteXWord(program_table_file_size_);
+    WriteXWord(program_table_file_size_);
+    WriteXWord(kPageSize);
+#endif
+    const intptr_t end = stream_->position();
+    ASSERT((end - start) == kElfProgramTableEntrySize);
+  }
+}
+
+void Elf::WriteSectionTable() {
+  ASSERT(stream_->position() == section_table_file_offset_);
+
+  {
+    // The first entry in the section table is reserved and must be all zeros.
+    ASSERT(kNumInvalidSections == 1);
+    const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+    WriteWord(0);
+    WriteWord(0);
+    WriteWord(0);
+    WriteAddr(0);
+    WriteOff(0);
+    WriteWord(0);
+    WriteWord(0);
+    WriteWord(0);
+    WriteWord(0);
+    WriteWord(0);
+#else
+    WriteWord(0);
+    WriteWord(0);
+    WriteXWord(0);
+    WriteAddr(0);
+    WriteOff(0);
+    WriteXWord(0);
+    WriteWord(0);
+    WriteWord(0);
+    WriteXWord(0);
+    WriteXWord(0);
+#endif
+    const intptr_t end = stream_->position();
+    ASSERT((end - start) == kElfSectionTableEntrySize);
+  }
+
+  for (intptr_t i = 0; i < sections_.length(); i++) {
+    Section* section = sections_[i];
+    const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+    WriteWord(section->section_name);
+    WriteWord(section->section_type);
+    WriteWord(section->section_flags);
+    WriteAddr(section->memory_offset);
+    WriteOff(section->file_offset);
+    WriteWord(section->file_size);  // Has different meaning for BSS.
+    WriteWord(section->section_link);
+    WriteWord(section->section_info);
+    WriteWord(section->alignment);
+    WriteWord(section->section_entry_size);
+#else
+    WriteWord(section->section_name);
+    WriteWord(section->section_type);
+    WriteXWord(section->section_flags);
+    WriteAddr(section->memory_offset);
+    WriteOff(section->file_offset);
+    WriteXWord(section->file_size);  // Has different meaning for BSS.
+    WriteWord(section->section_link);
+    WriteWord(section->section_info);
+    WriteXWord(section->alignment);
+    WriteXWord(section->section_entry_size);
+#endif
+    const intptr_t end = stream_->position();
+    ASSERT((end - start) == kElfSectionTableEntrySize);
+  }
+}
+
+void Elf::WriteSections() {
+  for (intptr_t i = 0; i < sections_.length(); i++) {
+    Section* section = sections_[i];
+    stream_->Align(section->alignment);
+    ASSERT(stream_->position() == section->file_offset);
+    section->Write(this);
+    ASSERT(stream_->position() == section->file_offset + section->file_size);
+    stream_->Align(section->alignment);
+  }
+}
+
+}  // namespace dart
diff --git a/runtime/vm/elf.h b/runtime/vm/elf.h
new file mode 100644
index 0000000..d49fd62
--- /dev/null
+++ b/runtime/vm/elf.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2019, 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_ELF_H_
+#define RUNTIME_VM_ELF_H_
+
+#include "vm/allocation.h"
+#include "vm/datastream.h"
+#include "vm/growable_array.h"
+#include "vm/zone.h"
+
+namespace dart {
+
+class DynamicTable;
+class Section;
+class StringTable;
+class Symbol;
+class SymbolTable;
+
+class Elf : public ZoneAllocated {
+ public:
+  Elf(Zone* zone, StreamingWriteStream* stream);
+
+  intptr_t NextMemoryOffset();
+  intptr_t AddText(const char* name, const uint8_t* bytes, intptr_t size);
+  intptr_t AddROData(const char* name, const uint8_t* bytes, intptr_t size);
+  void AddDebug(const char* name, const uint8_t* bytes, intptr_t size);
+
+  void Finalize();
+
+  intptr_t position() const { return stream_->position(); }
+  void WriteBytes(const uint8_t* b, intptr_t size) {
+    stream_->WriteBytes(b, size);
+  }
+  void WriteByte(uint8_t value) {
+    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+  }
+  void WriteHalf(uint16_t value) {
+    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+  }
+  void WriteWord(uint32_t value) {
+    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+  }
+  void WriteAddr(uword value) {
+    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+  }
+  void WriteOff(uword value) {
+    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+  }
+#if defined(TARGET_ARCH_IS_64_BIT)
+  void WriteXWord(uint64_t value) {
+    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+  }
+#endif
+
+ private:
+  void AddSection(Section* section);
+  void AddSegment(Section* section);
+
+  void ComputeFileOffsets();
+  void WriteHeader();
+  void WriteSectionTable();
+  void WriteProgramTable();
+  void WriteSections();
+
+  Zone* const zone_;
+  StreamingWriteStream* stream_;
+  GrowableArray<Section*> sections_;
+  GrowableArray<Section*> segments_;
+
+  intptr_t memory_offset_;
+  intptr_t section_table_file_offset_;
+  intptr_t section_table_file_size_;
+  intptr_t program_table_file_offset_;
+  intptr_t program_table_file_size_;
+  StringTable* strtab_;
+  SymbolTable* symtab_;
+  DynamicTable* dynamic_;
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_ELF_H_
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 73a41f0..79361ba 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -995,6 +995,12 @@
   Exceptions::ThrowByType(Exceptions::kRange, args);
 }
 
+void Exceptions::ThrowUnsupportedError(const char* msg) {
+  const Array& args = Array::Handle(Array::New(1));
+  args.SetAt(0, String::Handle(String::New(msg)));
+  Exceptions::ThrowByType(Exceptions::kUnsupported, args);
+}
+
 void Exceptions::ThrowRangeErrorMsg(const char* msg) {
   const Array& args = Array::Handle(Array::New(1));
   args.SetAt(0, String::Handle(String::New(msg)));
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 894f374..46b4d68 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -84,6 +84,7 @@
                                             intptr_t expected_from,
                                             intptr_t expected_to);
   DART_NORETURN static void ThrowRangeErrorMsg(const char* msg);
+  DART_NORETURN static void ThrowUnsupportedError(const char* msg);
   DART_NORETURN static void ThrowCompileTimeError(const LanguageError& error);
 
   // Returns a RawInstance if the exception is successfully created,
diff --git a/runtime/vm/find_code_object_test.cc b/runtime/vm/find_code_object_test.cc
deleted file mode 100644
index 1fe3662..0000000
--- a/runtime/vm/find_code_object_test.cc
+++ /dev/null
@@ -1,151 +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.
-
-#include "platform/assert.h"
-#include "vm/class_finalizer.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/heap/pages.h"
-#include "vm/object.h"
-#include "vm/stack_frame.h"
-#include "vm/symbols.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
-static const int kScriptSize = 512 * KB;
-static const int kLoopCount = 50000;
-#elif defined(TARGET_ARCH_DBC)
-static const int kScriptSize = 1 * MB;
-static const int kLoopCount = 60000;
-#else
-static const int kScriptSize = 512 * KB;
-static const int kLoopCount = 25000;
-#endif
-static char scriptChars[kScriptSize];
-
-ISOLATE_UNIT_TEST_CASE(FindCodeObject) {
-  const int kNumFunctions = 1024;
-
-  // Get access to the code index table.
-  Isolate* isolate = Isolate::Current();
-  ASSERT(isolate != NULL);
-
-  StackZone zone(thread);
-  String& url = String::Handle(String::New("dart-test:FindCodeObject"));
-  String& source = String::Handle();
-  Script& script = Script::Handle();
-  Library& lib = Library::Handle();
-  Class& clsA = Class::Handle();
-  Class& clsB = Class::Handle();
-  String& function_name = String::Handle();
-  Function& function = Function::Handle();
-  char buffer[256];
-
-  lib = Library::CoreLibrary();
-
-  // Load up class A with 1024 functions.
-  int written = Utils::SNPrint(scriptChars, kScriptSize, "class A {");
-  for (int i = 0; i < kNumFunctions; i++) {
-    Utils::SNPrint(buffer, 256,
-                   "static foo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
-    written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
-                              "%s", buffer);
-  }
-  Utils::SNPrint((scriptChars + written), (kScriptSize - written), "}");
-  source = String::New(scriptChars);
-  script = Script::New(url, source, RawScript::kScriptTag);
-  EXPECT(CompilerTest::TestCompileScript(lib, script));
-  clsA = lib.LookupClass(String::Handle(Symbols::New(thread, "A")));
-  EXPECT(!clsA.IsNull());
-  ClassFinalizer::ProcessPendingClasses();
-  for (int i = 0; i < kNumFunctions; i++) {
-    Utils::SNPrint(buffer, 256, "foo%d", i);
-    function_name = String::New(buffer);
-    function = clsA.LookupStaticFunction(function_name);
-    EXPECT(!function.IsNull());
-    EXPECT(CompilerTest::TestCompileFunction(function));
-    const Code& code = Code::ZoneHandle(function.CurrentCode());
-    EXPECT(!code.IsNull())
-    EXPECT(function.HasCode());
-  }
-
-  // Now load up class B with 1024 functions.
-  written = Utils::SNPrint(scriptChars, kScriptSize, "class B {");
-  // Create one large function.
-  Utils::SNPrint(buffer, sizeof(buffer), "static moo0([var i=1]) { ");
-  written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
-                            "%s", buffer);
-  // Generate a large function so that the code for this function when
-  // compiled will reside in a large page.
-  for (int i = 0; i < kLoopCount; i++) {
-    Utils::SNPrint(buffer, sizeof(buffer), "i = i+i;");
-    written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
-                              "%s", buffer);
-  }
-  Utils::SNPrint(buffer, sizeof(buffer), "return i; }");
-  written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
-                            "%s", buffer);
-  for (int i = 1; i < kNumFunctions; i++) {
-    Utils::SNPrint(buffer, 256,
-                   "static moo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
-    written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
-                              "%s", buffer);
-  }
-  Utils::SNPrint((scriptChars + written), (kScriptSize - written), "}");
-  url = String::New("dart-test:FindCodeObject");
-  source = String::New(scriptChars);
-  script = Script::New(url, source, RawScript::kScriptTag);
-  EXPECT(CompilerTest::TestCompileScript(lib, script));
-  clsB = lib.LookupClass(String::Handle(Symbols::New(thread, "B")));
-  EXPECT(!clsB.IsNull());
-  ClassFinalizer::ProcessPendingClasses();
-  for (int i = 0; i < kNumFunctions; i++) {
-    Utils::SNPrint(buffer, 256, "moo%d", i);
-    function_name = String::New(buffer);
-    function = clsB.LookupStaticFunction(function_name);
-    EXPECT(!function.IsNull());
-    EXPECT(CompilerTest::TestCompileFunction(function));
-    const Code& code = Code::ZoneHandle(function.CurrentCode());
-    EXPECT(!code.IsNull());
-    EXPECT(function.HasCode());
-  }
-
-  // Now try and access these functions using the code index table.
-  Code& code = Code::Handle();
-  uword pc;
-  Utils::SNPrint(buffer, 256, "foo%d", 123);
-  function_name = String::New(buffer);
-  function = clsA.LookupStaticFunction(function_name);
-  EXPECT(!function.IsNull());
-  code = function.CurrentCode();
-  EXPECT(code.Size() > 16);
-  pc = code.PayloadStart() + 16;
-  EXPECT(Code::LookupCode(pc) == code.raw());
-
-  Utils::SNPrint(buffer, 256, "moo%d", 54);
-  function_name = String::New(buffer);
-  function = clsB.LookupStaticFunction(function_name);
-  EXPECT(!function.IsNull());
-  code = function.CurrentCode();
-  EXPECT(code.Size() > 16);
-  pc = code.PayloadStart() + 16;
-  EXPECT(Code::LookupCode(pc) == code.raw());
-
-  // Lookup the large function
-  Utils::SNPrint(buffer, 256, "moo%d", 0);
-  function_name = String::New(buffer);
-  function = clsB.LookupStaticFunction(function_name);
-  EXPECT(!function.IsNull());
-  code = function.CurrentCode();
-  EXPECT(code.Size() > 16);
-  pc = code.PayloadStart() + 16;
-  EXPECT(code.Size() > kPageSize);
-  EXPECT(Code::LookupCode(pc) == code.raw());
-  EXPECT(code.Size() > (1 * MB));
-  pc = code.PayloadStart() + (1 * MB);
-  EXPECT(Code::LookupCode(pc) == code.raw());
-}
-
-}  // namespace dart
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index 7336f1f..1734984c 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -73,6 +73,25 @@
 #define NOT_IN_PRECOMPILED(code) code
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
+#if defined(TARGET_ARCH_DBC)
+#define NOT_IN_DBC(code)
+#else
+#define NOT_IN_DBC(code) code
+#endif  // defined(TARGET_ARCH_DBC)
+
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
+    defined(TARGET_ARCH_X64)
+#define ONLY_IN_ARM_ARM64_X64(code) code
+#else
+#define ONLY_IN_ARM_ARM64_X64(code)
+#endif
+
+#if defined(DART_PRECOMPILED_RUNTIME)
+#define NOT_IN_PRECOMPILED_RUNTIME(code)
+#else
+#define NOT_IN_PRECOMPILED_RUNTIME(code) code
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+
 #if !defined(PRODUCT) || defined(HOST_OS_FUCHSIA) || defined(TARGET_OS_FUCHSIA)
 #define SUPPORT_TIMELINE 1
 #endif
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 34ede80..b3d16c8 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -7,6 +7,7 @@
 #include "platform/assert.h"
 #include "vm/compiler/backend/code_statistics.h"
 #include "vm/dwarf.h"
+#include "vm/elf.h"
 #include "vm/hash.h"
 #include "vm/hash_map.h"
 #include "vm/heap/heap.h"
@@ -359,10 +360,10 @@
                                          const void* shared_instructions)
     : ImageWriter(thread->heap(), shared_objects, shared_instructions, nullptr),
       assembly_stream_(512 * KB, callback, callback_data),
-      dwarf_(NULL) {
+      dwarf_(nullptr) {
 #if defined(DART_PRECOMPILER)
   Zone* zone = Thread::Current()->zone();
-  dwarf_ = new (zone) Dwarf(zone, &assembly_stream_);
+  dwarf_ = new (zone) Dwarf(zone, &assembly_stream_, /* elf= */ nullptr);
 #endif
 }
 
@@ -676,12 +677,20 @@
                                  intptr_t initial_size,
                                  const void* shared_objects,
                                  const void* shared_instructions,
-                                 const void* reused_instructions)
+                                 const void* reused_instructions,
+                                 Elf* elf,
+                                 Dwarf* dwarf)
     : ImageWriter(thread->heap(),
                   shared_objects,
                   shared_instructions,
                   reused_instructions),
-      instructions_blob_stream_(instructions_blob_buffer, alloc, initial_size) {
+      instructions_blob_stream_(instructions_blob_buffer, alloc, initial_size),
+      elf_(elf),
+      dwarf_(dwarf) {
+#ifndef DART_PRECOMPILER
+  RELEASE_ASSERT(elf_ == nullptr);
+  RELEASE_ASSERT(dwarf_ == nullptr);
+#endif
 }
 
 intptr_t BlobImageWriter::WriteByteSequence(uword start, uword end) {
@@ -693,6 +702,13 @@
 }
 
 void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
+#ifdef DART_PRECOMPILER
+  intptr_t segment_base = 0;
+  if (elf_ != nullptr) {
+    segment_base = elf_->NextMemoryOffset();
+  }
+#endif
+
   // This header provides the gap to make the instructions snapshot look like a
   // HeapPage.
   intptr_t instructions_length = next_text_offset_;
@@ -733,6 +749,15 @@
     ASSERT(Utils::IsAligned(beginning, sizeof(uword)));
     ASSERT(Utils::IsAligned(entry, sizeof(uword)));
 
+#ifdef DART_PRECOMPILER
+    const Code& code = *instructions_[i].code_;
+    if ((elf_ != nullptr) && !code.IsNull()) {
+      intptr_t segment_offset = instructions_blob_stream_.bytes_written() +
+                                Instructions::HeaderSize();
+      dwarf_->AddCode(code, segment_base + segment_offset);
+    }
+#endif
+
     // Write Instructions with the mark and read-only bits set.
     uword marked_tags = insns.raw_ptr()->tags_;
     marked_tags = RawObject::OldBit::update(true, marked_tags);
@@ -752,6 +777,17 @@
 
     ASSERT((text_offset - instr_start) == insns.raw()->HeapSize());
   }
+
+#ifdef DART_PRECOMPILER
+  if (elf_ != nullptr) {
+    const char* instructions_symbol = vm ? "_kDartVmSnapshotInstructions"
+                                         : "_kDartIsolateSnapshotInstructions";
+    intptr_t segment_base2 =
+        elf_->AddText(instructions_symbol, instructions_blob_stream_.buffer(),
+                      instructions_blob_stream_.bytes_written());
+    ASSERT(segment_base == segment_base2);
+  }
+#endif
 }
 
 ImageReader::ImageReader(const uint8_t* data_image,
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index 1bc4260..720d855 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -23,6 +23,7 @@
 // Forward declarations.
 class Code;
 class Dwarf;
+class Elf;
 class Instructions;
 class Object;
 class RawApiError;
@@ -333,7 +334,9 @@
                   intptr_t initial_size,
                   const void* shared_objects,
                   const void* shared_instructions,
-                  const void* reused_instructions);
+                  const void* reused_instructions,
+                  Elf* elf = nullptr,
+                  Dwarf* dwarf = nullptr);
 
   virtual void WriteText(WriteStream* clustered_stream, bool vm);
 
@@ -345,6 +348,8 @@
   intptr_t WriteByteSequence(uword start, uword end);
 
   WriteStream instructions_blob_stream_;
+  Elf* elf_;
+  Dwarf* dwarf_;
 
   DISALLOW_COPY_AND_ASSIGN(BlobImageWriter);
 };
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index a0ba01e..e815a7f 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -896,7 +896,7 @@
   } while (0)
 #endif
 
-// Fetch next operation from PC, increment program counter and dispatch.
+// Fetch next operation from PC and dispatch.
 #define DISPATCH() DISPATCH_OP(*pc)
 
 // Load target of a jump instruction into PC.
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index ba66dcd..028c1bc 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -2,6 +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.
 
+#include <utility>
+
 #include "vm/isolate.h"
 
 #include "include/dart_api.h"
@@ -2107,8 +2109,8 @@
   }
   JSONObject jsobj(stream);
   jsobj.AddProperty("type", (ref ? "@Isolate" : "Isolate"));
-  jsobj.AddFixedServiceId(ISOLATE_SERVICE_ID_FORMAT_STRING,
-                          static_cast<int64_t>(main_port()));
+  jsobj.AddServiceId(ISOLATE_SERVICE_ID_FORMAT_STRING,
+                     static_cast<int64_t>(main_port()));
 
   jsobj.AddProperty("name", name());
   jsobj.AddPropertyF("number", "%" Pd64 "", static_cast<int64_t>(main_port()));
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 2cd529b..b153644 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -616,7 +616,7 @@
       p_num_received_classes = &num_received_classes_;
       p_num_received_procedures = &num_received_procedures_;
     } else {
-      Dart_KernelCompilationResult retval;
+      Dart_KernelCompilationResult retval = {};
       if (kernel_buffer != NULL && kernel_buffer_size != 0) {
         retval.kernel = const_cast<uint8_t*>(kernel_buffer);
         retval.kernel_size = kernel_buffer_size;
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index 05f474e..aeaa9d0 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -500,6 +500,14 @@
   va_end(args);
 }
 
+void JSONObject::AddServiceId(const char* format, ...) const {
+  // Add the id property.
+  va_list args;
+  va_start(args, format);
+  stream_->VPrintfProperty("id", format, args);
+  va_end(args);
+}
+
 void JSONObject::AddLocation(const Script& script,
                              TokenPosition token_pos,
                              TokenPosition end_token_pos) const {
@@ -516,10 +524,9 @@
   ASSERT(bpt_loc->IsResolved());
 
   Zone* zone = Thread::Current()->zone();
-  Library& library = Library::Handle(zone);
   Script& script = Script::Handle(zone);
   TokenPosition token_pos = TokenPosition::kNoSource;
-  bpt_loc->GetCodeLocation(&library, &script, &token_pos);
+  bpt_loc->GetCodeLocation(&script, &token_pos);
   AddLocation(script, token_pos);
 }
 
@@ -528,10 +535,9 @@
   ASSERT(!bpt_loc->IsResolved());
 
   Zone* zone = Thread::Current()->zone();
-  Library& library = Library::Handle(zone);
   Script& script = Script::Handle(zone);
   TokenPosition token_pos = TokenPosition::kNoSource;
-  bpt_loc->GetCodeLocation(&library, &script, &token_pos);
+  bpt_loc->GetCodeLocation(&script, &token_pos);
 
   JSONObject location(this, "location");
   location.AddProperty("type", "UnresolvedSourceLocation");
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index c44a5f6..98d39f3 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -307,6 +307,7 @@
   void AddServiceId(const Object& o) const { stream_->PrintServiceId(o); }
 
   void AddFixedServiceId(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3);
+  void AddServiceId(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3);
 
   void AddLocation(
       const Script& script,
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index a4a6eea..703a495 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -256,7 +256,7 @@
   return array_object.raw();
 }
 
-static void ProcessTokenPositionsEntry(
+static void CollectKernelDataTokenPositions(
     const ExternalTypedData& kernel_data,
     const Script& script,
     const Script& entry_script,
@@ -278,6 +278,64 @@
   token_position_collector.CollectTokenPositions(kernel_offset);
 }
 
+static void CollectBytecodeTokenPositions(
+    const Bytecode& bytecode,
+    Zone* zone,
+    GrowableArray<intptr_t>* token_positions,
+    GrowableArray<intptr_t>* yield_positions) {
+  ASSERT(bytecode.HasSourcePositions());
+  BytecodeSourcePositionsIterator iter(zone, bytecode);
+  while (iter.MoveNext()) {
+    const TokenPosition pos = iter.TokenPos();
+    if (pos.IsReal()) {
+      // TODO(alexmarkov): collect yield positions from bytecode.
+      token_positions->Add(pos.value());
+    }
+  }
+}
+
+static void CollectBytecodeFunctionTokenPositions(
+    const Function& function,
+    GrowableArray<intptr_t>* token_positions,
+    GrowableArray<intptr_t>* yield_positions) {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  ASSERT(function.is_declared_in_bytecode());
+  if (!function.HasBytecode()) {
+    const Object& result = Object::Handle(
+        zone, BytecodeReader::ReadFunctionBytecode(thread, function));
+    if (!result.IsNull()) {
+      Exceptions::PropagateError(Error::Cast(result));
+    }
+  }
+  Bytecode& bytecode = Bytecode::Handle(zone, function.bytecode());
+  ASSERT(!bytecode.IsNull());
+  if (bytecode.HasSourcePositions()) {
+    CollectBytecodeTokenPositions(bytecode, zone, token_positions,
+                                  yield_positions);
+    // Find closure functions in the object pool.
+    const ObjectPool& pool = ObjectPool::Handle(zone, bytecode.object_pool());
+    Object& object = Object::Handle(zone);
+    Function& closure = Function::Handle(zone);
+    for (intptr_t i = 0; i < pool.Length(); i++) {
+      ObjectPool::EntryType entry_type = pool.TypeAt(i);
+      if (entry_type != ObjectPool::EntryType::kTaggedObject) {
+        continue;
+      }
+      object = pool.ObjectAt(i);
+      if (object.IsFunction()) {
+        closure ^= object.raw();
+        if ((closure.kind() == RawFunction::kClosureFunction) &&
+            (closure.raw() != function.raw())) {
+          bytecode = closure.bytecode();
+          CollectBytecodeTokenPositions(bytecode, zone, token_positions,
+                                        yield_positions);
+        }
+      }
+    }
+  }
+}
+
 void CollectTokenPositionsFor(const Script& interesting_script) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
@@ -325,29 +383,30 @@
               continue;
             }
             data = temp_field.KernelData();
-            ProcessTokenPositionsEntry(data, interesting_script, entry_script,
-                                       temp_field.kernel_offset(),
-                                       temp_field.KernelDataProgramOffset(),
-                                       zone, &helper, &token_positions,
-                                       &yield_positions);
+            CollectKernelDataTokenPositions(
+                data, interesting_script, entry_script,
+                temp_field.kernel_offset(),
+                temp_field.KernelDataProgramOffset(), zone, &helper,
+                &token_positions, &yield_positions);
           }
           temp_array = klass.functions();
           for (intptr_t i = 0; i < temp_array.Length(); ++i) {
             temp_function ^= temp_array.At(i);
             entry_script = temp_function.script();
-            // TODO(alexmarkov): collect token positions from bytecode
-            if (temp_function.is_declared_in_bytecode()) {
-              continue;
-            }
             if (entry_script.raw() != interesting_script.raw()) {
               continue;
             }
-            data = temp_function.KernelData();
-            ProcessTokenPositionsEntry(data, interesting_script, entry_script,
-                                       temp_function.kernel_offset(),
-                                       temp_function.KernelDataProgramOffset(),
-                                       zone, &helper, &token_positions,
-                                       &yield_positions);
+            if (temp_function.is_declared_in_bytecode()) {
+              CollectBytecodeFunctionTokenPositions(
+                  temp_function, &token_positions, &yield_positions);
+            } else {
+              data = temp_function.KernelData();
+              CollectKernelDataTokenPositions(
+                  data, interesting_script, entry_script,
+                  temp_function.kernel_offset(),
+                  temp_function.KernelDataProgramOffset(), zone, &helper,
+                  &token_positions, &yield_positions);
+            }
           }
         } else {
           // Class isn't finalized yet: read the data attached to it.
@@ -362,27 +421,28 @@
           if (entry_script.raw() != interesting_script.raw()) {
             continue;
           }
-          ProcessTokenPositionsEntry(data, interesting_script, entry_script,
-                                     class_offset, library_kernel_offset, zone,
-                                     &helper, &token_positions,
-                                     &yield_positions);
+          CollectKernelDataTokenPositions(data, interesting_script,
+                                          entry_script, class_offset,
+                                          library_kernel_offset, zone, &helper,
+                                          &token_positions, &yield_positions);
         }
       } else if (entry.IsFunction()) {
         temp_function ^= entry.raw();
-        // TODO(alexmarkov): collect token positions from bytecode
-        if (temp_function.is_declared_in_bytecode()) {
-          continue;
-        }
         entry_script = temp_function.script();
         if (entry_script.raw() != interesting_script.raw()) {
           continue;
         }
-        data = temp_function.KernelData();
-        ProcessTokenPositionsEntry(data, interesting_script, entry_script,
-                                   temp_function.kernel_offset(),
-                                   temp_function.KernelDataProgramOffset(),
-                                   zone, &helper, &token_positions,
-                                   &yield_positions);
+        if (temp_function.is_declared_in_bytecode()) {
+          CollectBytecodeFunctionTokenPositions(temp_function, &token_positions,
+                                                &yield_positions);
+        } else {
+          data = temp_function.KernelData();
+          CollectKernelDataTokenPositions(
+              data, interesting_script, entry_script,
+              temp_function.kernel_offset(),
+              temp_function.KernelDataProgramOffset(), zone, &helper,
+              &token_positions, &yield_positions);
+        }
       } else if (entry.IsField()) {
         const Field& field = Field::Cast(entry);
         // TODO(alexmarkov): collect token positions from bytecode
@@ -395,10 +455,10 @@
           continue;
         }
         data = field.KernelData();
-        ProcessTokenPositionsEntry(data, interesting_script, entry_script,
-                                   field.kernel_offset(),
-                                   field.KernelDataProgramOffset(), zone,
-                                   &helper, &token_positions, &yield_positions);
+        CollectKernelDataTokenPositions(
+            data, interesting_script, entry_script, field.kernel_offset(),
+            field.KernelDataProgramOffset(), zone, &helper, &token_positions,
+            &yield_positions);
       }
     }
   }
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index ef25d78..abf5036 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -828,7 +828,7 @@
   KernelCompilationRequest* next_;
   KernelCompilationRequest* prev_;
 
-  Dart_KernelCompilationResult result_;
+  Dart_KernelCompilationResult result_ = {};
 };
 
 Monitor* KernelCompilationRequest::requests_monitor_ = new Monitor();
@@ -848,7 +848,7 @@
   // to finish initialization.
   Dart_Port kernel_port = WaitForKernelPort();
   if (kernel_port == ILLEGAL_PORT) {
-    Dart_KernelCompilationResult result;
+    Dart_KernelCompilationResult result = {};
     result.status = Dart_KernelCompilationStatus_Unknown;
     result.error = strdup("Error while initializing Kernel isolate");
     return result;
@@ -865,7 +865,7 @@
 Dart_KernelCompilationResult KernelIsolate::ListDependencies() {
   Dart_Port kernel_port = WaitForKernelPort();
   if (kernel_port == ILLEGAL_PORT) {
-    Dart_KernelCompilationResult result;
+    Dart_KernelCompilationResult result = {};
     result.status = Dart_KernelCompilationStatus_Unknown;
     result.error = strdup("Error while initializing Kernel isolate");
     return result;
@@ -882,7 +882,7 @@
   // to finish initialization.
   Dart_Port kernel_port = WaitForKernelPort();
   if (kernel_port == ILLEGAL_PORT) {
-    Dart_KernelCompilationResult result;
+    Dart_KernelCompilationResult result = {};
     result.status = Dart_KernelCompilationStatus_Unknown;
     result.error = strdup("Error while initializing Kernel isolate");
     return result;
@@ -903,7 +903,7 @@
     bool is_static) {
   Dart_Port kernel_port = WaitForKernelPort();
   if (kernel_port == ILLEGAL_PORT) {
-    Dart_KernelCompilationResult result;
+    Dart_KernelCompilationResult result = {};
     result.status = Dart_KernelCompilationStatus_Unknown;
     result.error = strdup("Error while initializing Kernel isolate");
     return result;
@@ -923,7 +923,7 @@
   // to finish initialization.
   Dart_Port kernel_port = WaitForKernelPort();
   if (kernel_port == ILLEGAL_PORT) {
-    Dart_KernelCompilationResult result;
+    Dart_KernelCompilationResult result = {};
     result.status = Dart_KernelCompilationStatus_Unknown;
     result.error = strdup("Error while initializing Kernel isolate");
     return result;
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 962d878..4186f23 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -404,6 +404,10 @@
       Z, reader.ExternalDataFromTo(program_->metadata_mappings_offset(),
                                    program_->string_table_offset()));
 
+#if defined(DEBUG)
+  MetadataHelper::VerifyMetadataMappings(metadata_mappings);
+#endif
+
   const Array& libraries_cache =
       Array::Handle(Z, HashTables::New<UnorderedHashMap<SmiTraits>>(
                            program_->library_count(), Heap::kOld));
diff --git a/runtime/vm/message.cc b/runtime/vm/message.cc
index 542ccc0..0bfca6d 100644
--- a/runtime/vm/message.cc
+++ b/runtime/vm/message.cc
@@ -4,6 +4,8 @@
 
 #include "vm/message.h"
 
+#include <utility>
+
 #include "vm/dart_entry.h"
 #include "vm/json_stream.h"
 #include "vm/object.h"
@@ -11,7 +13,7 @@
 
 namespace dart {
 
-const Dart_Port Message::kIllegalPort;
+const Dart_Port Message::kIllegalPort = 0;
 
 Message::Message(Dart_Port dest_port,
                  uint8_t* snapshot,
diff --git a/runtime/vm/message.h b/runtime/vm/message.h
index 4bf2303..03f3074 100644
--- a/runtime/vm/message.h
+++ b/runtime/vm/message.h
@@ -6,6 +6,7 @@
 #define RUNTIME_VM_MESSAGE_H_
 
 #include <memory>
+#include <utility>
 
 #include "platform/assert.h"
 #include "vm/allocation.h"
@@ -42,7 +43,7 @@
   } OOBMsgTag;
 
   // A port number which is never used.
-  static const Dart_Port kIllegalPort = 0;
+  static const Dart_Port kIllegalPort;
 
   // A new message to be sent between two isolates. The data handed to this
   // message will be disposed by calling free() once the message object is
diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc
index 9bf957d..df1859d 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -217,4 +217,24 @@
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
+DART_EXPORT Dart_Handle Dart_FinalizeAllClasses() {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  return Api::NewError("%s: All classes are already finalized in AOT runtime.",
+                       CURRENT_FUNC);
+#else
+  DARTSCOPE(Thread::Current());
+  API_TIMELINE_DURATION(T);
+  Dart_Handle result = Api::CheckAndFinalizePendingClasses(T);
+  if (Api::IsError(result)) {
+    return result;
+  }
+  CHECK_CALLBACK_STATE(T);
+  const Error& error = Error::Handle(T->zone(), Library::FinalizeAllClasses());
+  if (!error.IsNull()) {
+    return Api::NewHandle(T, error.raw());
+  }
+  return Api::Success();
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+}
+
 }  // namespace dart
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 73cf977..08b8a5f 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -5730,9 +5730,10 @@
   StorePointer(&raw_ptr()->bytecode_, value.raw());
 
   // We should not have loaded the bytecode if the function had code.
-  ASSERT(!HasCode());
-
-  if (FLAG_enable_interpreter) {
+  // However, we may load the bytecode to access source positions (see
+  // ProcessBytecodeTokenPositionsEntry in kernel.cc).
+  // In that case, do not install InterpretCall stub below.
+  if (FLAG_enable_interpreter && !HasCode()) {
     // Set the code entry_point to InterpretCall stub.
     SetInstructions(StubCode::InterpretCall());
   }
@@ -6065,6 +6066,34 @@
   return FfiTrampolineData::Cast(obj).c_signature();
 }
 
+int32_t Function::FfiCallbackId() const {
+  ASSERT(IsFfiTrampoline());
+  const Object& obj = Object::Handle(raw_ptr()->data_);
+  ASSERT(!obj.IsNull());
+  return FfiTrampolineData::Cast(obj).callback_id();
+}
+
+void Function::SetFfiCallbackId(int32_t value) const {
+  ASSERT(IsFfiTrampoline());
+  const Object& obj = Object::Handle(raw_ptr()->data_);
+  ASSERT(!obj.IsNull());
+  FfiTrampolineData::Cast(obj).set_callback_id(value);
+}
+
+RawFunction* Function::FfiCallbackTarget() const {
+  ASSERT(IsFfiTrampoline());
+  const Object& obj = Object::Handle(raw_ptr()->data_);
+  ASSERT(!obj.IsNull());
+  return FfiTrampolineData::Cast(obj).callback_target();
+}
+
+void Function::SetFfiCallbackTarget(const Function& target) const {
+  ASSERT(IsFfiTrampoline());
+  const Object& obj = Object::Handle(raw_ptr()->data_);
+  ASSERT(!obj.IsNull());
+  FfiTrampolineData::Cast(obj).set_callback_target(target);
+}
+
 RawType* Function::SignatureType() const {
   Type& type = Type::Handle(ExistingSignatureType());
   if (type.IsNull()) {
@@ -6185,10 +6214,18 @@
       break;
     case RawFunction::kDynamicInvocationForwarder:
       return "DynamicInvocationForwarder";
-    default:
-      UNREACHABLE();
-      return NULL;
+      break;
+    case RawFunction::kFfiTrampoline:
+      return "FfiTrampoline";
+      break;
   }
+  // When you add a case to this switch, please also update the observatory.
+  // - runtime/observatory/lib/src/models/objects/function.dart (FunctionKind)
+  // - runtime/observatory/lib/src/elements/function_view.dart
+  //   (_functionKindToString)
+  // - runtime/observatory/lib/src/service/object.dart (stringToFunctionKind)
+  UNREACHABLE();
+  return NULL;
 }
 
 void Function::SetRedirectionType(const Type& type) const {
@@ -7787,7 +7824,8 @@
 
 bool Function::ShouldCompilerOptimize() const {
   return !FLAG_enable_interpreter ||
-         ((unoptimized_code() != Object::null()) && WasCompiled());
+         ((unoptimized_code() != Object::null()) && WasCompiled()) ||
+         ForceOptimize();
 }
 
 RawString* Function::UserVisibleName() const {
@@ -8221,12 +8259,22 @@
   StorePointer(&raw_ptr()->c_signature_, value.raw());
 }
 
+void FfiTrampolineData::set_callback_target(const Function& value) const {
+  StorePointer(&raw_ptr()->callback_target_, value.raw());
+}
+
+void FfiTrampolineData::set_callback_id(int32_t callback_id) const {
+  StoreNonPointer(&raw_ptr()->callback_id_, callback_id);
+}
+
 RawFfiTrampolineData* FfiTrampolineData::New() {
   ASSERT(Object::ffi_trampoline_data_class() != Class::null());
   RawObject* raw =
       Object::Allocate(FfiTrampolineData::kClassId,
                        FfiTrampolineData::InstanceSize(), Heap::kOld);
-  return reinterpret_cast<RawFfiTrampolineData*>(raw);
+  RawFfiTrampolineData* data = reinterpret_cast<RawFfiTrampolineData*>(raw);
+  data->ptr()->callback_id_ = -1;
+  return data;
 }
 
 const char* FfiTrampolineData::ToCString() const {
@@ -12236,6 +12284,39 @@
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
+
+RawError* Library::FinalizeAllClasses() {
+  Thread* thread = Thread::Current();
+  ASSERT(thread->IsMutatorThread());
+  Zone* zone = thread->zone();
+  Error& error = Error::Handle(zone);
+  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
+      Isolate::Current()->object_store()->libraries());
+  Library& lib = Library::Handle(zone);
+  Class& cls = Class::Handle(zone);
+  for (int i = 0; i < libs.Length(); i++) {
+    lib ^= libs.At(i);
+    if (!lib.Loaded()) {
+      String& uri = String::Handle(zone, lib.url());
+      String& msg = String::Handle(
+          zone,
+          String::NewFormatted("Library '%s' is not loaded. "
+                               "Did you forget to call Dart_FinalizeLoading?",
+                               uri.ToCString()));
+      return ApiError::New(msg);
+    }
+    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+    while (it.HasNext()) {
+      cls = it.GetNextClass();
+      error = cls.EnsureIsFinalized(thread);
+      if (!error.IsNull()) {
+        return error.raw();
+      }
+    }
+  }
+  return Error::null();
+}
+
 RawError* Library::ReadAllBytecode() {
   Thread* thread = Thread::Current();
   ASSERT(thread->IsMutatorThread());
@@ -15122,6 +15203,9 @@
     result.set_pc_descriptors(Object::empty_descriptors());
     result.set_instructions_binary_offset(instructions_offset);
     result.set_source_positions_binary_offset(0);
+#if !defined(PRODUCT)
+    result.set_local_variables_binary_offset(0);
+#endif
   }
   return result.raw();
 }
@@ -15160,6 +15244,35 @@
 #endif
 }
 
+intptr_t Bytecode::GetTryIndexAtPc(uword return_address) const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  UNREACHABLE();
+#else
+  intptr_t try_index = -1;
+  const uword pc_offset = return_address - PayloadStart();
+  const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
+  PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind);
+  while (iter.MoveNext()) {
+    // PC descriptors for try blocks in bytecode are generated in pairs,
+    // marking start and end of a try block.
+    // See BytecodeMetadataHelper::ReadExceptionsTable for details.
+    const intptr_t current_try_index = iter.TryIndex();
+    const uword start_pc = iter.PcOffset();
+    if (pc_offset < start_pc) {
+      break;
+    }
+    const bool has_next = iter.MoveNext();
+    ASSERT(has_next);
+    const uword end_pc = iter.PcOffset();
+    if (start_pc <= pc_offset && pc_offset < end_pc) {
+      ASSERT(try_index < current_try_index);
+      try_index = current_try_index;
+    }
+  }
+  return try_index;
+#endif
+}
+
 const char* Bytecode::ToCString() const {
   return Thread::Current()->zone()->PrintToString("Bytecode(%s)",
                                                   QualifiedName());
@@ -15221,6 +15334,25 @@
   return Bytecode::null();
 }
 
+RawLocalVarDescriptors* Bytecode::GetLocalVarDescriptors() const {
+#if defined(PRODUCT) || defined(DART_PRECOMPILED_RUNTIME)
+  UNREACHABLE();
+  return LocalVarDescriptors::null();
+#else
+  Zone* zone = Thread::Current()->zone();
+  auto& var_descs = LocalVarDescriptors::Handle(zone, var_descriptors());
+  if (var_descs.IsNull()) {
+    const auto& func = Function::Handle(zone, function());
+    ASSERT(!func.IsNull());
+    var_descs =
+        kernel::BytecodeReader::ComputeLocalVarDescriptors(zone, func, *this);
+    ASSERT(!var_descs.IsNull());
+    set_var_descriptors(var_descs);
+  }
+  return var_descs.raw();
+#endif
+}
+
 RawContext* Context::New(intptr_t num_variables, Heap::Space space) {
   ASSERT(num_variables >= 0);
   ASSERT(Object::context_class() != Class::null());
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 725bc63..453e847 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2000,6 +2000,20 @@
   // Can only be used on FFI trampolines.
   RawFunction* FfiCSignature() const;
 
+  // Can only be called on FFI trampolines.
+  // -1 for Dart -> native calls.
+  int32_t FfiCallbackId() const;
+
+  // Can only be called on FFI trampolines.
+  void SetFfiCallbackId(int32_t value) const;
+
+  // Can only be called on FFI trampolines.
+  // Null for Dart -> native calls.
+  RawFunction* FfiCallbackTarget() const;
+
+  // Can only be called on FFI trampolines.
+  void SetFfiCallbackTarget(const Function& target) const;
+
   // Return a new function with instantiated result and parameter types.
   RawFunction* InstantiateSignatureFrom(
       const TypeArguments& instantiator_type_arguments,
@@ -2169,6 +2183,8 @@
   void AttachBytecode(const Bytecode& bytecode) const;
   RawBytecode* bytecode() const { return raw_ptr()->bytecode_; }
   inline bool HasBytecode() const;
+#else
+  inline bool HasBytecode() const { return false; }
 #endif
 
   virtual intptr_t Hash() const;
@@ -3131,6 +3147,12 @@
   RawFunction* c_signature() const { return raw_ptr()->c_signature_; }
   void set_c_signature(const Function& value) const;
 
+  RawFunction* callback_target() const { return raw_ptr()->callback_target_; }
+  void set_callback_target(const Function& value) const;
+
+  int32_t callback_id() const { return raw_ptr()->callback_id_; }
+  void set_callback_id(int32_t value) const;
+
   static RawFfiTrampolineData* New();
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData, Object);
@@ -4027,6 +4049,8 @@
   // Eagerly compile all classes and functions in the library.
   static RawError* CompileAll(bool ignore_error = false);
 #if !defined(DART_PRECOMPILED_RUNTIME)
+  // Finalize all classes in all libraries.
+  static RawError* FinalizeAllClasses();
   // Eagerly read all bytecode.
   static RawError* ReadAllBytecode();
 #endif
@@ -4294,6 +4318,14 @@
            sizeof(RawObjectPool::Entry) * index;
   }
 
+  struct ArrayLayout {
+    static intptr_t elements_start_offset() {
+      return ObjectPool::data_offset();
+    }
+
+    static constexpr intptr_t kElementSize = sizeof(RawObjectPool::Entry);
+  };
+
   EntryType TypeAt(intptr_t index) const {
     return TypeBits::decode(raw_ptr()->entry_bits()[index]);
   }
@@ -5001,7 +5033,7 @@
     return ContainsInstructionAt(raw(), addr);
   }
 
-  static bool ContainsInstructionAt(RawCode* code, uword addr) {
+  static bool ContainsInstructionAt(const RawCode* code, uword addr) {
     return Instructions::ContainsPc(code->ptr()->instructions_, addr);
   }
 
@@ -5201,7 +5233,7 @@
 #endif
   }
 
-  // Will compute local var descriptors is necessary.
+  // Will compute local var descriptors if necessary.
   RawLocalVarDescriptors* GetLocalVarDescriptors() const;
 
   RawExceptionHandlers* exception_handlers() const {
@@ -5474,6 +5506,7 @@
   RawExternalTypedData* GetBinary(Zone* zone) const;
 
   TokenPosition GetTokenIndexOfPC(uword pc) const;
+  intptr_t GetTryIndexAtPc(uword return_address) const;
 
   intptr_t instructions_binary_offset() const {
     return raw_ptr()->instructions_binary_offset_;
@@ -5492,6 +5525,38 @@
     return (source_positions_binary_offset() != 0);
   }
 
+#if !defined(PRODUCT)
+  intptr_t local_variables_binary_offset() const {
+    return raw_ptr()->local_variables_binary_offset_;
+  }
+  void set_local_variables_binary_offset(intptr_t value) const {
+    StoreNonPointer(&raw_ptr()->local_variables_binary_offset_, value);
+  }
+  bool HasLocalVariablesInfo() const {
+    return (local_variables_binary_offset() != 0);
+  }
+#endif  // !defined(PRODUCT)
+
+  RawLocalVarDescriptors* var_descriptors() const {
+#if defined(PRODUCT)
+    UNREACHABLE();
+    return nullptr;
+#else
+    return raw_ptr()->var_descriptors_;
+#endif
+  }
+  void set_var_descriptors(const LocalVarDescriptors& value) const {
+#if defined(PRODUCT)
+    UNREACHABLE();
+#else
+    ASSERT(value.IsOld());
+    StorePointer(&raw_ptr()->var_descriptors_, value.raw());
+#endif
+  }
+
+  // Will compute local var descriptors if necessary.
+  RawLocalVarDescriptors* GetLocalVarDescriptors() const;
+
   const char* Name() const;
   const char* QualifiedName() const;
 
@@ -6208,6 +6273,14 @@
   }
   void SetTypeAt(intptr_t index, const AbstractType& value) const;
 
+  struct ArrayLayout {
+    static intptr_t elements_start_offset() {
+      return TypeArguments::type_at_offset(0);
+    }
+
+    static constexpr intptr_t kElementSize = kWordSize;
+  };
+
   // The name of this type argument vector, e.g. "<T, dynamic, List<T>, Smi>".
   RawString* Name() const { return SubvectorName(0, Length(), kInternalName); }
 
@@ -7989,6 +8062,12 @@
     return OFFSET_OF_RETURNED_VALUE(RawArray, data) + kWordSize * index;
   }
 
+  struct ArrayLayout {
+    static intptr_t elements_start_offset() { return Array::data_offset(); }
+
+    static constexpr intptr_t kElementSize = kWordSize;
+  };
+
   static bool Equals(RawArray* a, RawArray* b) {
     if (a == b) return true;
     if (a->IsRawNull() || b->IsRawNull()) return false;
@@ -8268,6 +8347,14 @@
   static RawGrowableObjectArray* New(const Array& array,
                                      Heap::Space space = Heap::kNew);
 
+  static RawSmi* NoSafepointLength(const RawGrowableObjectArray* array) {
+    return array->ptr()->length_;
+  }
+
+  static RawArray* NoSafepointData(const RawGrowableObjectArray* array) {
+    return array->ptr()->data_;
+  }
+
  private:
   RawArray* DataArray() const { return data()->ptr(); }
   RawObject** ObjectAddr(intptr_t index) const {
diff --git a/runtime/vm/os_thread_macos.cc b/runtime/vm/os_thread_macos.cc
index 50a2952..a0d050e 100644
--- a/runtime/vm/os_thread_macos.cc
+++ b/runtime/vm/os_thread_macos.cc
@@ -88,20 +88,6 @@
   DISALLOW_COPY_AND_ASSIGN(ThreadStartData);
 };
 
-// Spawned threads inherit their spawner's signal mask. We sometimes spawn
-// threads for running Dart code from a thread that is blocking SIGPROF.
-// This function explicitly unblocks SIGPROF so the profiler continues to
-// sample this thread.
-static void UnblockSIGPROF() {
-  sigset_t set;
-  sigemptyset(&set);
-  sigaddset(&set, SIGPROF);
-  int r = pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-  USE(r);
-  ASSERT(r == 0);
-  ASSERT(!CHECK_IS_BLOCKING(SIGPROF));
-}
-
 // Dispatch to the thread start function provided by the caller. This trampoline
 // is used to ensure that the thread is properly destroyed if the thread just
 // exits.
@@ -121,7 +107,6 @@
   if (thread != NULL) {
     OSThread::SetCurrent(thread);
     thread->set_name(name);
-    UnblockSIGPROF();
     // Call the supplied thread start function handing it its parameters.
     function(parameter);
   }
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 27d808f..eb5d39a 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -537,7 +537,7 @@
     RawBytecode* raw_bytecode = static_cast<RawBytecode*>(raw_obj);
     uword start = raw_bytecode->ptr()->instructions_;
     uword size = raw_bytecode->ptr()->instructions_size_;
-    return (pc - start) < size;
+    return (pc - start) <= size;  // pc may point past last instruction.
   }
   return false;
 }
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 75e7a92..355cb6b 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1013,7 +1013,19 @@
   VISIT_FROM(RawObject*, signature_type_);
   RawType* signature_type_;
   RawFunction* c_signature_;
-  VISIT_TO(RawObject*, c_signature_);
+
+  // Target Dart method for callbacks, otherwise null.
+  RawFunction* callback_target_;
+
+  VISIT_TO(RawObject*, callback_target_);
+
+  // Callback id for callbacks, otherwise 0.
+  //
+  // The callbacks ids are used so that native callbacks can lookup their own
+  // code objects, since native code doesn't pass code objects into function
+  // calls. The callback id is also used to for verifying that callbacks are
+  // called on the correct isolate. See DLRT_VerifyCallbackIsolate for details.
+  uint32_t callback_id_;
 };
 
 class RawField : public RawObject {
@@ -1337,13 +1349,21 @@
   VISIT_FROM(RawObject*, object_pool_);
   RawObjectPool* object_pool_;
   RawFunction* function_;
+  RawArray* closures_;
   RawExceptionHandlers* exception_handlers_;
   RawPcDescriptors* pc_descriptors_;
+  NOT_IN_PRODUCT(RawLocalVarDescriptors* var_descriptors_);
+#if defined(PRODUCT)
   VISIT_TO(RawObject*, pc_descriptors_);
+#else
+  VISIT_TO(RawObject*, var_descriptors_);
+#endif
+
   RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 
   int32_t instructions_binary_offset_;
   int32_t source_positions_binary_offset_;
+  NOT_IN_PRODUCT(int32_t local_variables_binary_offset_);
 
   static bool ContainsPC(RawObject* raw_obj, uword pc);
 
@@ -1384,15 +1404,14 @@
   uint32_t size_and_flags_;
   uint32_t unchecked_entrypoint_pc_offset_;
 
-#if defined(DART_PRECOMPILER)
   // There is a gap between size_and_flags_ and the entry point
   // because we align entry point by 4 words on all platforms.
   // This allows us to have a free field here without affecting
   // the aligned size of the Instructions object header.
   // This also means that entry point offset is the same
   // whether this field is included or excluded.
+  // TODO(37103): This field should be removed.
   CodeStatistics* stats_;
-#endif
 
   // Variable length data follows here.
   uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
diff --git a/runtime/vm/resolver_test.cc b/runtime/vm/resolver_test.cc
deleted file mode 100644
index 6624b49..0000000
--- a/runtime/vm/resolver_test.cc
+++ /dev/null
@@ -1,194 +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.
-
-#include "vm/resolver.h"
-#include "platform/assert.h"
-#include "vm/class_finalizer.h"
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/dart_entry.h"
-#include "vm/object.h"
-#include "vm/symbols.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-// Setup function for invocation.
-static void SetupFunction(const char* test_library_name,
-                          const char* test_class_name,
-                          const char* test_static_function_name,
-                          bool is_static) {
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-
-  // Setup a dart class and function.
-  char script_chars[1024];
-  Utils::SNPrint(script_chars, sizeof(script_chars),
-                 "class Base {\n"
-                 "  dynCall() { return 3; }\n"
-                 "  static statCall() { return 4; }\n"
-                 "\n"
-                 "}\n"
-                 "class %s extends Base {\n"
-                 "  %s %s(String s, int i) { return i; }\n"
-                 "}\n",
-                 test_class_name, is_static ? "static" : "",
-                 test_static_function_name);
-
-  String& url = String::Handle(
-      zone, is_static ? String::New("dart-test:DartStaticResolve")
-                      : String::New("dart-test:DartDynamicResolve"));
-  String& source = String::Handle(zone, String::New(script_chars));
-  Script& script =
-      Script::Handle(zone, Script::New(url, source, RawScript::kScriptTag));
-  const String& lib_name = String::Handle(zone, String::New(test_library_name));
-  Library& lib = Library::Handle(zone, Library::New(lib_name));
-  lib.Register(thread);
-  EXPECT(CompilerTest::TestCompileScript(lib, script));
-  EXPECT(ClassFinalizer::ProcessPendingClasses());
-}
-
-// Setup a static function for invocation.
-static void SetupStaticFunction(const char* test_library_name,
-                                const char* test_class_name,
-                                const char* test_static_function_name) {
-  // Setup a static dart class and function.
-  SetupFunction(test_library_name, test_class_name, test_static_function_name,
-                true);
-}
-
-// Setup an instance  function for invocation.
-static void SetupInstanceFunction(const char* test_library_name,
-                                  const char* test_class_name,
-                                  const char* test_function_name) {
-  // Setup a static dart class and function.
-  SetupFunction(test_library_name, test_class_name, test_function_name, false);
-}
-
-ISOLATE_UNIT_TEST_CASE(DartStaticResolve) {
-  const char* test_library_name = "ResolverApp";
-  const char* test_class_name = "A";
-  const char* test_static_function_name = "static_foo";
-  const int kTestValue = 42;
-
-  // Setup a static function which can be invoked.
-  SetupStaticFunction(test_library_name, test_class_name,
-                      test_static_function_name);
-
-  const String& library_name = String::Handle(String::New(test_library_name));
-  const Library& library =
-      Library::Handle(Library::LookupLibrary(thread, library_name));
-  const String& class_name = String::Handle(String::New(test_class_name));
-  const String& static_function_name =
-      String::Handle(String::New(test_static_function_name));
-
-  // Now try to resolve and invoke the static function in this class.
-  {
-    const int kTypeArgsLen = 0;
-    const int kNumArguments = 2;
-    const Function& function = Function::Handle(Resolver::ResolveStatic(
-        library, class_name, static_function_name, kTypeArgsLen, kNumArguments,
-        Object::empty_array()));
-    EXPECT(!function.IsNull());  // No ambiguity error expected.
-    const Array& args = Array::Handle(Array::New(kNumArguments));
-    const String& arg0 = String::Handle(String::New("junk"));
-    args.SetAt(0, arg0);
-    const Smi& arg1 = Smi::Handle(Smi::New(kTestValue));
-    args.SetAt(1, arg1);
-    const Smi& retval = Smi::Handle(
-        reinterpret_cast<RawSmi*>(DartEntry::InvokeFunction(function, args)));
-    EXPECT_EQ(kTestValue, retval.Value());
-  }
-
-  // Now try to resolve a static function with invalid argument count.
-  {
-    const int kTypeArgsLen = 0;
-    const int kNumArguments = 1;
-    const Function& bad_function = Function::Handle(Resolver::ResolveStatic(
-        library, class_name, static_function_name, kTypeArgsLen, kNumArguments,
-        Object::empty_array()));
-    EXPECT(bad_function.IsNull());  // No ambiguity error expected.
-  }
-
-  // Hierarchy walking.
-  {
-    const String& super_static_function_name =
-        String::Handle(String::New("statCall"));
-    const String& super_class_name = String::Handle(String::New("Base"));
-    const int kTypeArgsLen = 0;
-    const int kNumArguments = 0;
-    const Function& super_function = Function::Handle(Resolver::ResolveStatic(
-        library, super_class_name, super_static_function_name, kTypeArgsLen,
-        kNumArguments, Object::empty_array()));
-    EXPECT(!super_function.IsNull());  // No ambiguity error expected.
-  }
-}
-
-ISOLATE_UNIT_TEST_CASE(DartDynamicResolve) {
-  const char* test_library_name = "ResolverApp";
-  const char* test_class_name = "A";
-  const char* test_function_name = "foo";
-  const int kTestValue = 42;
-
-  // Setup a function which can be invoked.
-  SetupInstanceFunction(test_library_name, test_class_name, test_function_name);
-
-  // Now create an instance object of the class and try to
-  // resolve a function in it.
-  const String& lib_name = String::Handle(String::New(test_library_name));
-  const Library& lib =
-      Library::Handle(Library::LookupLibrary(thread, lib_name));
-  ASSERT(!lib.IsNull());
-  const Class& cls = Class::Handle(
-      lib.LookupClass(String::Handle(Symbols::New(thread, test_class_name))));
-  EXPECT(!cls.IsNull());  // No ambiguity error expected.
-
-  Instance& receiver = Instance::Handle(Instance::New(cls));
-  const String& function_name = String::Handle(String::New(test_function_name));
-
-  // Now try to resolve and invoke the instance function in this class.
-  {
-    const int kTypeArgsLen = 0;
-    const int kNumArguments = 3;
-    ArgumentsDescriptor args_desc(
-        Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
-    const Function& function = Function::Handle(
-        Resolver::ResolveDynamic(receiver, function_name, args_desc));
-    EXPECT(!function.IsNull());
-    const Array& args = Array::Handle(Array::New(kNumArguments));
-    args.SetAt(0, receiver);
-    const String& arg0 = String::Handle(String::New("junk"));
-    args.SetAt(1, arg0);
-    const Smi& arg1 = Smi::Handle(Smi::New(kTestValue));
-    args.SetAt(2, arg1);
-    const Smi& retval = Smi::Handle(
-        reinterpret_cast<RawSmi*>(DartEntry::InvokeFunction(function, args)));
-    EXPECT_EQ(kTestValue, retval.Value());
-  }
-
-  // Now try to resolve an instance function with invalid argument count.
-  {
-    const int kTypeArgsLen = 0;
-    const int kNumArguments = 1;
-    ArgumentsDescriptor args_desc(
-        Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
-    const Function& bad_function = Function::Handle(
-        Resolver::ResolveDynamic(receiver, function_name, args_desc));
-    EXPECT(bad_function.IsNull());
-  }
-
-  // Hierarchy walking.
-  {
-    const int kTypeArgsLen = 0;
-    const int kNumArguments = 1;
-    ArgumentsDescriptor args_desc(
-        Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
-    const String& super_function_name = String::Handle(String::New("dynCall"));
-    const Function& super_function = Function::Handle(
-        Resolver::ResolveDynamic(receiver, super_function_name, args_desc));
-    EXPECT(!super_function.IsNull());
-  }
-}
-
-}  // namespace dart
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 1a7ba2e..cac4d22 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -26,6 +26,7 @@
 #include "vm/service_isolate.h"
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
+#include "vm/thread.h"
 #include "vm/thread_registry.h"
 #include "vm/type_testing_stubs.h"
 
@@ -975,6 +976,7 @@
                              StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* caller_frame = iterator.NextFrame();
   ASSERT(caller_frame != NULL);
+  ASSERT(!caller_frame->is_interpreted());
   const Code& orig_stub = Code::Handle(
       zone, isolate->debugger()->GetPatchedStubAddress(caller_frame->pc()));
   const Error& error =
@@ -1963,13 +1965,13 @@
     for (intptr_t i = 0; i < num_frames; i++) {
       ActivationFrame* frame = stack->FrameAt(i);
 #ifndef DART_PRECOMPILED_RUNTIME
-      if (!frame->is_interpreted()) {
+      if (!frame->IsInterpreted()) {
         // Ensure that we have unoptimized code.
         frame->function().EnsureHasCompiledUnoptimizedCode();
       }
       // TODO(regis): Provide var descriptors in kernel bytecode.
       const int num_vars =
-          frame->is_interpreted() ? 0 : frame->NumLocalVariables();
+          frame->IsInterpreted() ? 0 : frame->NumLocalVariables();
 #else
       // Variable locations and number are unknown when precompiling.
       const int num_vars = 0;
@@ -2129,8 +2131,14 @@
   ASSERT(FLAG_enable_interpreter || optimizing_compilation);
   ASSERT((!optimizing_compilation) || function.HasCode());
 
-  if ((!optimizing_compilation) ||
+#if defined(PRODUCT)
+  if (!optimizing_compilation ||
       Compiler::CanOptimizeFunction(thread, function)) {
+#else
+  if ((!optimizing_compilation && !Debugger::IsDebugging(thread, function)) ||
+      (optimizing_compilation &&
+       Compiler::CanOptimizeFunction(thread, function))) {
+#endif  // defined(PRODUCT)
     if (FLAG_background_compilation) {
       if (FLAG_enable_inlining_annotations) {
         FATAL("Cannot enable inlining annotations and background compilation");
@@ -2765,4 +2773,29 @@
 }
 DEFINE_RAW_LEAF_RUNTIME_ENTRY(ExitSafepoint, 0, false, &DFLRT_ExitSafepoint);
 
+// Not registered as a runtime entry because we can't use Thread to look it up.
+extern "C" Thread* DLRT_GetThreadForNativeCallback() {
+  Thread* const thread = Thread::Current();
+  if (thread == nullptr) {
+    FATAL("Cannot invoke native callback outside an isolate.");
+  }
+  if (thread->no_callback_scope_depth() != 0) {
+    FATAL("Cannot invoke native callback when API callbacks are prohibited.");
+  }
+  if (!thread->IsMutatorThread()) {
+    FATAL("Native callbacks must be invoked on the mutator thread.");
+  }
+  return thread;
+}
+
+extern "C" void DLRT_VerifyCallbackIsolate(int32_t callback_id,
+                                           uword return_address) {
+  Thread::Current()->VerifyCallbackIsolate(callback_id, return_address);
+}
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(
+    VerifyCallbackIsolate,
+    1,
+    false /* is_float */,
+    reinterpret_cast<RuntimeFunction>(&DLRT_VerifyCallbackIsolate));
+
 }  // namespace dart
diff --git a/runtime/vm/runtime_entry.h b/runtime/vm/runtime_entry.h
index 85e9d7f2..f072c14 100644
--- a/runtime/vm/runtime_entry.h
+++ b/runtime/vm/runtime_entry.h
@@ -145,6 +145,9 @@
 RUNTIME_ENTRY_LIST(DECLARE_RUNTIME_ENTRY)
 LEAF_RUNTIME_ENTRY_LIST(DECLARE_LEAF_RUNTIME_ENTRY)
 
+// Expected to be called inside a safepoint.
+extern "C" Thread* DLRT_GetThreadForNativeCallback();
+
 const char* DeoptReasonToCString(ICData::DeoptReasonId deopt_reason);
 
 void DeoptimizeAt(const Code& optimized_code, StackFrame* frame);
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index dd4159d..b0c241e 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -84,7 +84,8 @@
   V(RawBool*, CaseInsensitiveCompareUTF16, RawString*, RawSmi*, RawSmi*,       \
     RawSmi*)                                                                   \
   V(void, EnterSafepoint)                                                      \
-  V(void, ExitSafepoint)
+  V(void, ExitSafepoint)                                                       \
+  V(void, VerifyCallbackIsolate, int32_t, uword)
 
 }  // namespace dart
 
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 50ba1c5..1db81b5 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -117,7 +117,7 @@
 StreamInfo Service::gc_stream("GC");
 StreamInfo Service::echo_stream("_Echo");
 StreamInfo Service::graph_stream("_Graph");
-StreamInfo Service::logging_stream("_Logging");
+StreamInfo Service::logging_stream("Logging");
 StreamInfo Service::extension_stream("Extension");
 StreamInfo Service::timeline_stream("Timeline");
 
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index 4b05099..3d2cb73 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -15,7 +15,7 @@
 namespace dart {
 
 #define SERVICE_PROTOCOL_MAJOR_VERSION 3
-#define SERVICE_PROTOCOL_MINOR_VERSION 14
+#define SERVICE_PROTOCOL_MINOR_VERSION 17
 
 class Array;
 class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index a04b348..e993091 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.16
+# Dart VM Service Protocol 3.17
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.16_ of the Dart VM Service Protocol. This
+This document describes of _version 3.17_ of the Dart VM Service Protocol. This
 protocol is used to communicate with a running Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
@@ -75,6 +75,7 @@
   - [Isolate](#isolate)
   - [Library](#library)
   - [LibraryDependency](#librarydependency)
+  - [LogRecord](#logrecord)
   - [MapAssociation](#mapassociation)
   - [MemoryUsage](#memoryusage)
   - [Message](#message)
@@ -546,7 +547,7 @@
 If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
 result of this evaluation are ignored. Defaults to false if not provided.
 
-If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+If the expression fails to parse and compile, then [rpc error](#rpc-error) 113
 "Expression compilation error" is returned.
 
 If an error occurs while evaluating the expression, an [@Error](#error)
@@ -579,7 +580,7 @@
 If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
 result of this evaluation are ignored. Defaults to false if not provided.
 
-If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+If the expression fails to parse and compile, then [rpc error](#rpc-error) 113
 "Expression compilation error" is returned.
 
 If an error occurs while evaluating the expression, an [@Error](#error)
@@ -947,6 +948,7 @@
 GC | GC
 Extension | Extension
 Timeline | TimelineEvents
+Logging | Logging
 
 Additionally, some embedders provide the _Stdout_ and _Stderr_
 streams.  These streams allow the client to subscribe to writes to
@@ -1424,6 +1426,11 @@
   //   IsolateReloaded
   //   IsolateSpawn
   string status [optional];
+
+  // LogRecord data.
+  //
+  // This is provided for the Logging event.
+  LogRecord logRecord [optional];
 }
 ```
 
@@ -1506,6 +1513,9 @@
 
   // Event from dart:developer.postEvent.
   Extension
+
+  // Event from dart:developer.log.
+  Logging
 }
 ```
 
@@ -2214,6 +2224,39 @@
 
 A _LibraryDependency_ provides information about an import or export.
 
+### LogRecord
+
+```
+class LogRecord extends Response {
+  // The log message.
+  @Instance message;
+
+  // The timestamp.
+  int time;
+
+  // The severity level (a value between 0 and 2000).
+  //
+  // See the package:logging `Level` class for an overview of the possible
+  // values.
+  int level;
+
+  // A monotonically increasing sequence number.
+  int sequenceNumber;
+
+  // The name of the source of the log message.
+  @Instance loggerName;
+
+  // The zone where the log was emitted.
+  @Instance zone;
+
+  // An error object associated with this log event.
+  @Instance error;
+
+  // A stack trace associated with this log event.
+  @Instance stackTrace;
+}
+```
+
 ### MapAssociation
 
 ```
@@ -2811,5 +2854,6 @@
 3.14 | Flag 'profile_period' can now be set at runtime, allowing for the profiler sample rate to be changed while the program is running.
 3.15 | Added `disableBreakpoints` parameter to `invoke`, `evaluate`, and `evaluateInFrame`.
 3.16 | Add 'getMemoryUsage' RPC and 'MemoryUsage' object.
+3.17 | Add 'Logging' event kind and the LogRecord class.
 
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service/service_dev.md b/runtime/vm/service/service_dev.md
index 2b4edd8..5daf941 100644
--- a/runtime/vm/service/service_dev.md
+++ b/runtime/vm/service/service_dev.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.17-dev
+# Dart VM Service Protocol 3.18-dev
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.17-dev_ of the Dart VM Service Protocol. This
+This document describes of _version 3.18-dev_ of the Dart VM Service Protocol. This
 protocol is used to communicate with a running Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
@@ -75,6 +75,7 @@
   - [Isolate](#isolate)
   - [Library](#library)
   - [LibraryDependency](#librarydependency)
+  - [LogRecord](#logrecord)
   - [MapAssociation](#mapassociation)
   - [MemoryUsage](#memoryusage)
   - [Message](#message)
@@ -546,7 +547,7 @@
 If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
 result of this evaluation are ignored. Defaults to false if not provided.
 
-If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+If the expression fails to parse and compile, then [rpc error](#rpc-error) 113
 "Expression compilation error" is returned.
 
 If an error occurs while evaluating the expression, an [@Error](#error)
@@ -579,7 +580,7 @@
 If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
 result of this evaluation are ignored. Defaults to false if not provided.
 
-If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+If the expression fails to parse and compile, then [rpc error](#rpc-error) 113
 "Expression compilation error" is returned.
 
 If an error occurs while evaluating the expression, an [@Error](#error)
@@ -947,6 +948,7 @@
 GC | GC
 Extension | Extension
 Timeline | TimelineEvents
+Logging | Logging
 
 Additionally, some embedders provide the _Stdout_ and _Stderr_
 streams.  These streams allow the client to subscribe to writes to
@@ -1424,6 +1426,11 @@
   //   IsolateReloaded
   //   IsolateSpawn
   string status [optional];
+
+  // LogRecord data.
+  //
+  // This is provided for the Logging event.
+  LogRecord logRecord [optional];
 }
 ```
 
@@ -1506,6 +1513,9 @@
 
   // Event from dart:developer.postEvent.
   Extension
+
+  // Event from dart:developer.log.
+  Logging
 }
 ```
 
@@ -2214,6 +2224,39 @@
 
 A _LibraryDependency_ provides information about an import or export.
 
+### LogRecord
+
+```
+class LogRecord extends Response {
+  // The log message.
+  @Instance message;
+
+  // The timestamp.
+  int time;
+
+  // The severity level (a value between 0 and 2000).
+  //
+  // See the package:logging `Level` class for an overview of the possible
+  // values.
+  int level;
+
+  // A monotonically increasing sequence number.
+  int sequenceNumber;
+
+  // The name of the source of the log message.
+  @Instance loggerName;
+
+  // The zone where the log was emitted.
+  @Instance zone;
+
+  // An error object associated with this log event.
+  @Instance error;
+
+  // A stack trace associated with this log event.
+  @Instance stackTrace;
+}
+```
+
 ### MapAssociation
 
 ```
@@ -2811,5 +2854,6 @@
 3.14 | Flag 'profile_period' can now be set at runtime, allowing for the profiler sample rate to be changed while the program is running.
 3.15 | Added `disableBreakpoints` parameter to `invoke`, `evaluate`, and `evaluateInFrame`.
 3.16 | Add 'getMemoryUsage' RPC and 'MemoryUsage' object.
+3.17 | Add 'Logging' event kind and the LogRecord class.
 
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index 5822378..66ee578 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -95,7 +95,7 @@
     case kEmbedder:
       return embedder_kind();
     case kLogging:
-      return "_Logging";
+      return "Logging";
     case kDebuggerSettingsUpdate:
       return "_DebuggerSettingsUpdate";
     case kIllegal:
@@ -239,6 +239,7 @@
   }
   if (kind() == kLogging) {
     JSONObject logRecord(&jsobj, "logRecord");
+    logRecord.AddProperty("type", "LogRecord");
     logRecord.AddProperty64("sequenceNumber", log_record_.sequence_number);
     logRecord.AddPropertyTimeMillis("time", log_record_.timestamp);
     logRecord.AddProperty64("level", log_record_.level);
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 21c3382..99726ee 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -3852,7 +3852,7 @@
   {
     BYTECODE(StoreIndexedUint8, A_B_C);
     uint8_t* data = SimulatorHelpers::GetTypedData(FP[rA], FP[rB]);
-    *data = Smi::Value(RAW_CAST(Smi, FP[rC]));
+    *data = static_cast<uint8_t>(reinterpret_cast<word>(FP[rC]));
     DISPATCH();
   }
 
@@ -3860,8 +3860,8 @@
     BYTECODE(StoreIndexedUntaggedUint8, A_B_C);
     uint8_t* array = reinterpret_cast<uint8_t*>(FP[rA]);
     RawSmi* index = RAW_CAST(Smi, FP[rB]);
-    RawSmi* value = RAW_CAST(Smi, FP[rC]);
-    array[Smi::Value(index)] = Smi::Value(value);
+    array[Smi::Value(index)] =
+        static_cast<uint8_t>(reinterpret_cast<word>(FP[rC]));
     DISPATCH();
   }
 
@@ -3896,9 +3896,9 @@
     BYTECODE(StoreIndexedOneByteString, A_B_C);
     RawOneByteString* array = RAW_CAST(OneByteString, FP[rA]);
     RawSmi* index = RAW_CAST(Smi, FP[rB]);
-    RawSmi* value = RAW_CAST(Smi, FP[rC]);
     ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    array->ptr()->data()[Smi::Value(index)] = Smi::Value(value);
+    array->ptr()->data()[Smi::Value(index)] =
+        static_cast<uint8_t>(reinterpret_cast<word>(FP[rC]));
     DISPATCH();
   }
 
@@ -4007,14 +4007,15 @@
   {
     BYTECODE(LoadIndexedUint8, A_B_C);
     uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]);
-    FP[rA] = Smi::New(*data);
+    FP[rA] = reinterpret_cast<RawObject*>(static_cast<word>(*data));
     DISPATCH();
   }
 
   {
     BYTECODE(LoadIndexedInt8, A_B_C);
-    uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]);
-    FP[rA] = Smi::New(*reinterpret_cast<int8_t*>(data));
+    int8_t* data = reinterpret_cast<int8_t*>(
+        SimulatorHelpers::GetTypedData(FP[rB], FP[rC]));
+    FP[rA] = reinterpret_cast<RawObject*>(static_cast<word>(*data));
     DISPATCH();
   }
 
@@ -4036,9 +4037,10 @@
 
   {
     BYTECODE(LoadIndexedUntaggedInt8, A_B_C);
-    uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
+    int8_t* data = reinterpret_cast<int8_t*>(FP[rB]);
     RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    FP[rA] = Smi::New(*reinterpret_cast<int8_t*>(data + Smi::Value(index)));
+    FP[rA] = reinterpret_cast<RawObject*>(
+        static_cast<word>(data[Smi::Value(index)]));
     DISPATCH();
   }
 
@@ -4046,7 +4048,8 @@
     BYTECODE(LoadIndexedUntaggedUint8, A_B_C);
     uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
     RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    FP[rA] = Smi::New(*reinterpret_cast<uint8_t*>(data + Smi::Value(index)));
+    FP[rA] = reinterpret_cast<RawObject*>(
+        static_cast<word>(data[Smi::Value(index)]));
     DISPATCH();
   }
 
@@ -4092,7 +4095,8 @@
     RawOneByteString* array = RAW_CAST(OneByteString, FP[rB]);
     RawSmi* index = RAW_CAST(Smi, FP[rC]);
     ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    FP[rA] = Smi::New(array->ptr()->data()[Smi::Value(index)]);
+    FP[rA] = reinterpret_cast<RawObject*>(
+        static_cast<word>(array->ptr()->data()[Smi::Value(index)]));
     DISPATCH();
   }
 
@@ -4101,7 +4105,8 @@
     RawTwoByteString* array = RAW_CAST(TwoByteString, FP[rB]);
     RawSmi* index = RAW_CAST(Smi, FP[rC]);
     ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    FP[rA] = Smi::New(array->ptr()->data()[Smi::Value(index)]);
+    FP[rA] = reinterpret_cast<RawObject*>(
+        static_cast<word>(array->ptr()->data()[Smi::Value(index)]));
     DISPATCH();
   }
 
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 8f0e9cf..019cb7c 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -191,6 +191,10 @@
 void SourceReport::PrintCallSitesData(JSONObject* jsobj,
                                       const Function& function,
                                       const Code& code) {
+  if (code.IsNull()) {
+    // TODO(regis): implement for bytecode.
+    return;
+  }
   const TokenPosition begin_pos = function.token_pos();
   const TokenPosition end_pos = function.end_token_pos();
 
@@ -230,6 +234,10 @@
 void SourceReport::PrintCoverageData(JSONObject* jsobj,
                                      const Function& function,
                                      const Code& code) {
+  if (code.IsNull()) {
+    // TODO(regis): implement for bytecode.
+    return;
+  }
   const TokenPosition begin_pos = function.token_pos();
   const TokenPosition end_pos = function.end_token_pos();
 
@@ -312,15 +320,8 @@
 void SourceReport::PrintPossibleBreakpointsData(JSONObject* jsobj,
                                                 const Function& func,
                                                 const Code& code) {
-  const uint8_t kSafepointKind =
-      (RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall |
-       RawPcDescriptors::kRuntimeCall);
   const TokenPosition begin_pos = func.token_pos();
   const TokenPosition end_pos = func.end_token_pos();
-
-  const PcDescriptors& descriptors =
-      PcDescriptors::Handle(zone(), code.pc_descriptors());
-
   intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1;
   GrowableArray<char> possible(func_length);
   possible.SetLength(func_length);
@@ -328,15 +329,37 @@
     possible[i] = false;
   }
 
-  PcDescriptors::Iterator iter(descriptors, kSafepointKind);
-  while (iter.MoveNext()) {
-    const TokenPosition token_pos = iter.TokenPos();
-    if ((token_pos < begin_pos) || (token_pos > end_pos)) {
-      // Does not correspond to a valid source position.
-      continue;
+  if (code.IsNull()) {
+    const Bytecode& bytecode = Bytecode::Handle(func.bytecode());
+    ASSERT(!bytecode.IsNull());
+    kernel::BytecodeSourcePositionsIterator iter(zone(), bytecode);
+    while (iter.MoveNext()) {
+      const TokenPosition token_pos = iter.TokenPos();
+      if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+        // Does not correspond to a valid source position.
+        continue;
+      }
+      intptr_t token_offset = token_pos.Pos() - begin_pos.Pos();
+      possible[token_offset] = true;
     }
-    intptr_t token_offset = token_pos.Pos() - begin_pos.Pos();
-    possible[token_offset] = true;
+  } else {
+    const uint8_t kSafepointKind =
+        (RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall |
+         RawPcDescriptors::kRuntimeCall);
+
+    const PcDescriptors& descriptors =
+        PcDescriptors::Handle(zone(), code.pc_descriptors());
+
+    PcDescriptors::Iterator iter(descriptors, kSafepointKind);
+    while (iter.MoveNext()) {
+      const TokenPosition token_pos = iter.TokenPos();
+      if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+        // Does not correspond to a valid source position.
+        continue;
+      }
+      intptr_t token_offset = token_pos.Pos() - begin_pos.Pos();
+      possible[token_offset] = true;
+    }
   }
 
   JSONArray bpts(jsobj, "possibleBreakpoints");
@@ -465,14 +488,8 @@
   range.AddProperty("scriptIndex", GetScriptIndex(script));
   range.AddProperty("startPos", begin_pos);
   range.AddProperty("endPos", end_pos);
-  // TODO(regis): What is the meaning of 'compiled' in the presence of bytecode?
-  // If it means 'called', it should say 'true' if bytecode is present.
-  range.AddProperty("compiled", !code.IsNull());
+  range.AddProperty("compiled", true);  // bytecode or code.
 
-  // TODO(regis): Do we want a report covering interpreted functions too?
-  if (code.IsNull()) {
-    return;
-  }
   if (IsReportRequested(kCallSites)) {
     PrintCallSitesData(&range, func, code);
   }
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index b1d4b79..4d97d94 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -180,11 +180,9 @@
     if (is_interpreted()) {
       const Bytecode& bytecode = Bytecode::Handle(zone, LookupDartBytecode());
       ASSERT(!bytecode.IsNull());
-      const Function& function = Function::Handle(zone, bytecode.function());
-      ASSERT(!function.IsNull());
-      return zone->PrintToString(
-          "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") bytecode %s ]",
-          GetName(), sp(), fp(), pc(), function.ToFullyQualifiedCString());
+      return zone->PrintToString("[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px
+                                 ") %s ]",
+                                 GetName(), sp(), fp(), pc(), bytecode.Name());
     }
     const Code& code = Code::Handle(zone, LookupDartCode());
     ASSERT(!code.IsNull());
@@ -501,7 +499,6 @@
     ASSERT(!bytecode.IsNull());
     start = bytecode.PayloadStart();
     handlers = bytecode.exception_handlers();
-    descriptors = bytecode.pc_descriptors();
   } else {
     code = LookupDartCode();
     if (code.IsNull()) {
@@ -520,33 +517,17 @@
     *has_catch_all = info->has_catch_all;
     return true;
   }
-  uword pc_offset = pc() - start;
 
   if (handlers.num_entries() == 0) {
     return false;
   }
 
-  PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind);
   intptr_t try_index = -1;
   if (is_interpreted()) {
-    while (iter.MoveNext()) {
-      // PC descriptors for try blocks in bytecode are generated in pairs,
-      // marking start and end of a try block.
-      // See BytecodeMetadataHelper::ReadExceptionsTable for details.
-      const intptr_t current_try_index = iter.TryIndex();
-      const uword start_pc = iter.PcOffset();
-      if (pc_offset < start_pc) {
-        break;
-      }
-      const bool has_next = iter.MoveNext();
-      ASSERT(has_next);
-      const uword end_pc = iter.PcOffset();
-      if (start_pc <= pc_offset && pc_offset < end_pc) {
-        ASSERT(try_index < current_try_index);
-        try_index = current_try_index;
-      }
-    }
+    try_index = bytecode.GetTryIndexAtPc(pc());
   } else {
+    uword pc_offset = pc() - code.PayloadStart();
+    PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind);
     while (iter.MoveNext()) {
       const intptr_t current_try_index = iter.TryIndex();
       if ((iter.PcOffset() == pc_offset) && (current_try_index != -1)) {
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index bf67520..7753a4f 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -134,8 +134,7 @@
 
  protected:
   explicit StackFrame(Thread* thread)
-      : fp_(0), sp_(0), pc_(0), thread_(thread), is_interpreted_(false) {
-  }
+      : fp_(0), sp_(0), pc_(0), thread_(thread), is_interpreted_(false) {}
 
   // Name of the frame, used for generic frame printing functionality.
   virtual const char* GetName() const {
diff --git a/runtime/vm/stack_frame_arm.h b/runtime/vm/stack_frame_arm.h
index 2b5dc3e..cf95a67 100644
--- a/runtime/vm/stack_frame_arm.h
+++ b/runtime/vm/stack_frame_arm.h
@@ -55,6 +55,12 @@
 COMPILE_ASSERT(kAbiPreservedFpuRegCount == 4);
 #endif
 
+// For FFI native -> Dart callbacks, the number of stack slots between arguments
+// passed on stack and arguments saved in callback prologue.
+//
+// 2 = return adddress (1) + saved frame pointer (1).
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments = 2;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STACK_FRAME_ARM_H_
diff --git a/runtime/vm/stack_frame_arm64.h b/runtime/vm/stack_frame_arm64.h
index 3b8c726..b1b2288 100644
--- a/runtime/vm/stack_frame_arm64.h
+++ b/runtime/vm/stack_frame_arm64.h
@@ -49,6 +49,12 @@
 COMPILE_ASSERT(kAbiPreservedCpuRegCount == 10);
 COMPILE_ASSERT(kAbiPreservedFpuRegCount == 8);
 
+// For FFI native -> Dart callbacks, this is the number of stack slots between
+// arguments passed on stack and arguments saved in callback prologue.
+//
+// 2 = return adddress (1) + saved frame pointer (1).
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments = 2;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STACK_FRAME_ARM64_H_
diff --git a/runtime/vm/stack_frame_dbc.h b/runtime/vm/stack_frame_dbc.h
index 632f68c..e3d8395 100644
--- a/runtime/vm/stack_frame_dbc.h
+++ b/runtime/vm/stack_frame_dbc.h
@@ -81,6 +81,10 @@
 // on all other architectures.
 static const uword kInterruptStackLimit = 0;
 
+// TODO(37140): For FFI native -> Dart callbacks, the number of stack slots
+// between arguments passed on stack and arguments saved in callback prologue.
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments = -1;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STACK_FRAME_DBC_H_
diff --git a/runtime/vm/stack_frame_ia32.h b/runtime/vm/stack_frame_ia32.h
index b770cf7..70717c2 100644
--- a/runtime/vm/stack_frame_ia32.h
+++ b/runtime/vm/stack_frame_ia32.h
@@ -46,6 +46,10 @@
 // Entry and exit frame layout.
 static const int kExitLinkSlotFromEntryFp = -7;
 
+// All arguments are passed on the stack, so none need to be saved. Therefore
+// there is no frame for holding the saved arguments.
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments = 0;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STACK_FRAME_IA32_H_
diff --git a/runtime/vm/stack_frame_x64.h b/runtime/vm/stack_frame_x64.h
index 00d0059..193db62 100644
--- a/runtime/vm/stack_frame_x64.h
+++ b/runtime/vm/stack_frame_x64.h
@@ -5,6 +5,8 @@
 #ifndef RUNTIME_VM_STACK_FRAME_X64_H_
 #define RUNTIME_VM_STACK_FRAME_X64_H_
 
+#include "vm/constants_x64.h"
+
 namespace dart {
 
 /* X64 Dart Frame Layout
@@ -52,6 +54,13 @@
 static const int kExitLinkSlotFromEntryFp = -10;
 #endif  // defined(_WIN64)
 
+// For FFI native -> Dart callbacks, the number of stack slots between arguments
+// passed on stack and arguments saved in callback prologue. 2 = return adddress
+// (1) + saved frame pointer (1). Also add slots for the shadow space, if
+// present.
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments =
+    2 + CallingConventions::kShadowSpaceBytes / kWordSize;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STACK_FRAME_X64_H_
diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h
index 7f93f5b8..248c455 100644
--- a/runtime/vm/stub_code_list.h
+++ b/runtime/vm/stub_code_list.h
@@ -77,7 +77,8 @@
   V(OneArgCheckInlineCacheWithExactnessCheck)                                  \
   V(OneArgOptimizedCheckInlineCacheWithExactnessCheck)                         \
   V(EnterSafepoint)                                                            \
-  V(ExitSafepoint)
+  V(ExitSafepoint)                                                             \
+  V(VerifyCallback)
 
 #else
 #define VM_STUB_CODE_LIST(V)                                                   \
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 845d780..f265e3e 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -179,6 +179,7 @@
   V(GetterPrefix, "get:")                                                      \
   V(GreaterEqualOperator, ">=")                                                \
   V(GrowRegExpStack, "_growRegExpStack")                                       \
+  V(HandleExposedException, "_handleExposedException")                         \
   V(HaveSameRuntimeType, "_haveSameRuntimeType")                               \
   V(Hide, "hide")                                                              \
   V(ICData, "ICData")                                                          \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 6b48726..71a9b2d 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -6,6 +6,7 @@
 
 #include "vm/dart_api_state.h"
 #include "vm/growable_array.h"
+#include "vm/heap/safepoint.h"
 #include "vm/isolate.h"
 #include "vm/json_stream.h"
 #include "vm/lockers.h"
@@ -76,6 +77,7 @@
       resume_pc_(0),
       execution_state_(kThreadInNative),
       safepoint_state_(0),
+      ffi_callback_code_(GrowableObjectArray::null()),
       task_kind_(kUnknownTask),
       dart_stream_(NULL),
       thread_lock_(),
@@ -668,6 +670,7 @@
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&active_stacktrace_));
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&sticky_error_));
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&async_stack_trace_));
+  visitor->VisitPointer(reinterpret_cast<RawObject**>(&ffi_callback_code_));
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   if (interpreter() != NULL) {
@@ -936,4 +939,45 @@
   }
 }
 
+const intptr_t kInitialCallbackIdsReserved = 1024;
+int32_t Thread::AllocateFfiCallbackId() {
+  Zone* Z = isolate()->current_zone();
+  if (ffi_callback_code_ == GrowableObjectArray::null()) {
+    ffi_callback_code_ = GrowableObjectArray::New(kInitialCallbackIdsReserved);
+  }
+  const auto& array = GrowableObjectArray::Handle(Z, ffi_callback_code_);
+  array.Add(Code::Handle(Z, Code::null()));
+  return array.Length() - 1;
+}
+
+void Thread::SetFfiCallbackCode(int32_t callback_id, const Code& code) {
+  Zone* Z = isolate()->current_zone();
+  const auto& array = GrowableObjectArray::Handle(Z, ffi_callback_code_);
+  array.SetAt(callback_id, code);
+}
+
+void Thread::VerifyCallbackIsolate(int32_t callback_id, uword entry) {
+  NoSafepointScope _;
+
+  const RawGrowableObjectArray* const array = ffi_callback_code_;
+  if (array == GrowableObjectArray::null()) {
+    FATAL("Cannot invoke callback on incorrect isolate.");
+  }
+
+  const RawSmi* const length_smi =
+      GrowableObjectArray::NoSafepointLength(array);
+  const intptr_t length = Smi::Value(length_smi);
+
+  if (callback_id < 0 || callback_id >= length) {
+    FATAL("Cannot invoke callback on incorrect isolate.");
+  }
+
+  RawObject** const code_array =
+      Array::DataOf(GrowableObjectArray::NoSafepointData(array));
+  const RawCode* const code = Code::RawCast(code_array[callback_id]);
+  if (!Code::ContainsInstructionAt(code, entry)) {
+    FATAL("Cannot invoke callback on incorrect isolate.");
+  }
+}
+
 }  // namespace dart
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index c9d81bb..44bb9e6 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -168,8 +168,8 @@
   V(uword, monomorphic_miss_entry_, StubCode::MonomorphicMiss().EntryPoint(),  \
     0)                                                                         \
   V(uword, optimize_entry_, StubCode::OptimizeFunction().EntryPoint(), 0)      \
-  V(uword, deoptimize_entry_, StubCode::Deoptimize().EntryPoint(), 0)
-
+  V(uword, deoptimize_entry_, StubCode::Deoptimize().EntryPoint(), 0)          \
+  V(uword, verify_callback_entry_, StubCode::VerifyCallback().EntryPoint(), 0)
 #endif
 
 #define CACHED_ADDRESSES_LIST(V)                                               \
@@ -315,6 +315,10 @@
     return OFFSET_OF(Thread, safepoint_state_);
   }
 
+  static intptr_t callback_code_offset() {
+    return OFFSET_OF(Thread, ffi_callback_code_);
+  }
+
   TaskKind task_kind() const { return task_kind_; }
 
   // Retrieves and clears the stack overflow flags.  These are set by
@@ -768,6 +772,13 @@
     }
   }
 
+  int32_t AllocateFfiCallbackId();
+  void SetFfiCallbackCode(int32_t callback_id, const Code& code);
+
+  // Ensure that 'entry' points within the code of the callback identified by
+  // 'callback_id'. Aborts otherwise.
+  void VerifyCallbackIsolate(int32_t callback_id, uword entry);
+
   Thread* next() const { return next_; }
 
   // Visit all object pointers.
@@ -861,6 +872,7 @@
   uword resume_pc_;
   uword execution_state_;
   uword safepoint_state_;
+  RawGrowableObjectArray* ffi_callback_code_;
 
   // ---- End accessed from generated code. ----
 
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 398ecc8..168f264 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -685,8 +685,6 @@
     val = lib.EvaluateCompiledExpression(kernel_bytes, kernel_length,
                                          Array::empty_array(), param_values,
                                          TypeArguments::null_type_arguments());
-
-    free(const_cast<uint8_t*>(kernel_bytes));
   }
   return Api::NewHandle(thread, val.raw());
 }
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index e646a21..a1f20bf 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -85,6 +85,7 @@
   "debugger_arm64.cc",
   "debugger_dbc.cc",
   "debugger_ia32.cc",
+  "debugger_kbc.cc",
   "debugger_x64.cc",
   "deferred_objects.cc",
   "deferred_objects.h",
@@ -95,6 +96,8 @@
   "double_internals.h",
   "dwarf.cc",
   "dwarf.h",
+  "elf.cc",
+  "elf.h",
   "exceptions.cc",
   "exceptions.h",
   "finalizable_data.h",
@@ -388,10 +391,8 @@
   "cpuinfo_test.cc",
   "custom_isolate_test.cc",
   "dart_api_impl_test.cc",
-  "dart_entry_test.cc",
   "debugger_api_impl_test.cc",
   "exceptions_test.cc",
-  "find_code_object_test.cc",
   "fixed_cache_test.cc",
   "flags_test.cc",
   "growable_array_test.cc",
@@ -430,7 +431,6 @@
   "port_test.cc",
   "profiler_test.cc",
   "regexp_test.cc",
-  "resolver_test.cc",
   "ring_buffer_test.cc",
   "scopes_test.cc",
   "service_test.cc",
diff --git a/runtime/vm/zone.cc b/runtime/vm/zone.cc
index 595871a..cdb8ba4 100644
--- a/runtime/vm/zone.cc
+++ b/runtime/vm/zone.cc
@@ -331,19 +331,20 @@
   return OS::VSCreate(this, format, args);
 }
 
-StackZone::StackZone(ThreadState* thread) : StackResource(thread), zone_() {
+StackZone::StackZone(ThreadState* thread)
+    : StackResource(thread), zone_(new Zone()) {
   if (FLAG_trace_zones) {
     OS::PrintErr("*** Starting a new Stack zone 0x%" Px "(0x%" Px ")\n",
                  reinterpret_cast<intptr_t>(this),
-                 reinterpret_cast<intptr_t>(&zone_));
+                 reinterpret_cast<intptr_t>(zone_));
   }
 
   // This thread must be preventing safepoints or the GC could be visiting the
   // chain of handle blocks we're about the mutate.
   ASSERT(Thread::Current()->MayAllocateHandles());
 
-  zone_.Link(thread->zone());
-  thread->set_zone(&zone_);
+  zone_->Link(thread->zone());
+  thread->set_zone(zone_);
 }
 
 StackZone::~StackZone() {
@@ -351,13 +352,15 @@
   // chain of handle blocks we're about the mutate.
   ASSERT(Thread::Current()->MayAllocateHandles());
 
-  ASSERT(thread()->zone() == &zone_);
-  thread()->set_zone(zone_.previous_);
+  ASSERT(thread()->zone() == zone_);
+  thread()->set_zone(zone_->previous_);
   if (FLAG_trace_zones) {
     OS::PrintErr("*** Deleting Stack zone 0x%" Px "(0x%" Px ")\n",
                  reinterpret_cast<intptr_t>(this),
-                 reinterpret_cast<intptr_t>(&zone_));
+                 reinterpret_cast<intptr_t>(zone_));
   }
+
+  delete zone_;
 }
 
 }  // namespace dart
diff --git a/runtime/vm/zone.h b/runtime/vm/zone.h
index b4aba7f..88e1ef9 100644
--- a/runtime/vm/zone.h
+++ b/runtime/vm/zone.h
@@ -177,19 +177,19 @@
   explicit StackZone(ThreadState* thread);
 
   // Delete all memory associated with the zone.
-  ~StackZone();
+  virtual ~StackZone();
 
   // Compute the total size of this zone. This includes wasted space that is
   // due to internal fragmentation in the segments.
-  uintptr_t SizeInBytes() const { return zone_.SizeInBytes(); }
+  uintptr_t SizeInBytes() const { return zone_->SizeInBytes(); }
 
   // Computes the used space in the zone.
-  intptr_t CapacityInBytes() const { return zone_.CapacityInBytes(); }
+  intptr_t CapacityInBytes() const { return zone_->CapacityInBytes(); }
 
-  Zone* GetZone() { return &zone_; }
+  Zone* GetZone() { return zone_; }
 
  private:
-  Zone zone_;
+  Zone* zone_;
 
   template <typename T>
   friend class GrowableArray;
diff --git a/sdk/lib/_http/http.dart b/sdk/lib/_http/http.dart
index f1e72be..4e7d636 100644
--- a/sdk/lib/_http/http.dart
+++ b/sdk/lib/_http/http.dart
@@ -1958,6 +1958,14 @@
    */
   int get contentLength;
 
+  /// The compression state of the response.
+  ///
+  /// This specifies whether the response bytes were compressed when they were
+  /// received across the wire and whether callers will receive compressed
+  /// or uncompressed bytes when they listed to this response's byte stream.
+  @Since("2.3.2")
+  HttpClientResponseCompressionState get compressionState;
+
   /**
    * Gets the persistent connection state returned by the server.
    *
@@ -2037,6 +2045,49 @@
   HttpConnectionInfo get connectionInfo;
 }
 
+/// Enum that specifies the compression state of the byte stream of an
+/// [HttpClientResponse].
+///
+/// The values herein allow callers to answer the following questions as they
+/// pertain to an [HttpClientResponse]:
+///
+///  * Can the value of the response's `Content-Length` HTTP header be trusted?
+///  * Does the caller need to manually decompress the response's byte stream?
+///
+/// This enum is accessed via the [HttpClientResponse.compressionState] value.
+@Since("2.3.2")
+enum HttpClientResponseCompressionState {
+  /// The body of the HTTP response was received and remains in an uncompressed
+  /// state.
+  ///
+  /// In this state, the value of the `Content-Length` HTTP header, if
+  /// specified (non-negative), should match the number of bytes produced by
+  /// the response's byte stream.
+  notCompressed,
+
+  /// The body of the HTTP response was originally compressed, but by virtue of
+  /// the [HttpClient.autoUncompress] configuration option, it has been
+  /// automatically uncompressed.
+  ///
+  /// HTTP headers are not modified, so when a response has been uncompressed
+  /// in this way, the value of the `Content-Length` HTTP header cannot be
+  /// trusted, as it will contain the compressed content length, whereas the
+  /// stream of bytes produced by the response will contain uncompressed bytes.
+  decompressed,
+
+  /// The body of the HTTP response contains compressed bytes.
+  ///
+  /// In this state, the value of the `Content-Length` HTTP header, if
+  /// specified (non-negative), should match the number of bytes produced by
+  /// the response's byte stream.
+  ///
+  /// If the caller wishes to manually uncompress the body of the response,
+  /// it should consult the value of the `Content-Encoding` HTTP header to see
+  /// what type of compression has been applied. See
+  /// <https://tools.ietf.org/html/rfc2616#section-14.11> for more information.
+  compressed,
+}
+
 abstract class HttpClientCredentials {}
 
 /**
diff --git a/sdk/lib/_http/http_headers.dart b/sdk/lib/_http/http_headers.dart
index ea5eaff..dc9ff84 100644
--- a/sdk/lib/_http/http_headers.dart
+++ b/sdk/lib/_http/http_headers.dart
@@ -982,14 +982,24 @@
           codeUnit >= 127 ||
           separators.indexOf(name[i]) >= 0) {
         throw new FormatException(
-            "Invalid character in cookie name, code unit: '$codeUnit'");
+            "Invalid character in cookie name, code unit: '$codeUnit'",
+            name,
+            i);
       }
     }
 
-    if (value[0] == '"' && value[value.length - 1] == '"') {
-      value = value.substring(1, value.length - 1);
+    // Per RFC 6265, consider surrounding "" as part of the value, but otherwise
+    // double quotes are not allowed.
+    int start = 0;
+    int end = value.length;
+    if (2 <= value.length &&
+        value.codeUnits[start] == 0x22 &&
+        value.codeUnits[end - 1] == 0x22) {
+      start++;
+      end--;
     }
-    for (int i = 0; i < value.length; i++) {
+
+    for (int i = start; i < end; i++) {
       int codeUnit = value.codeUnits[i];
       if (!(codeUnit == 0x21 ||
           (codeUnit >= 0x23 && codeUnit <= 0x2B) ||
@@ -997,7 +1007,9 @@
           (codeUnit >= 0x3C && codeUnit <= 0x5B) ||
           (codeUnit >= 0x5D && codeUnit <= 0x7E))) {
         throw new FormatException(
-            "Invalid character in cookie value, code unit: '$codeUnit'");
+            "Invalid character in cookie value, code unit: '$codeUnit'",
+            value,
+            i);
       }
     }
   }
diff --git a/sdk/lib/_http/http_impl.dart b/sdk/lib/_http/http_impl.dart
index a70ca82..497516c 100644
--- a/sdk/lib/_http/http_impl.dart
+++ b/sdk/lib/_http/http_impl.dart
@@ -292,24 +292,35 @@
   // The HttpClientRequest of this response.
   final _HttpClientRequest _httpRequest;
 
-  // Whether this response is configured to auto uncompress.
-  final bool autoUncompress;
+  // The compression state of this response.
+  final HttpClientResponseCompressionState compressionState;
 
   _HttpClientResponse(
       _HttpIncoming _incoming, this._httpRequest, this._httpClient)
-      : autoUncompress = _httpClient.autoUncompress,
+      : compressionState = _getCompressionState(_httpClient, _incoming.headers),
         super(_incoming) {
     // Set uri for potential exceptions.
     _incoming.uri = _httpRequest.uri;
   }
 
+  static HttpClientResponseCompressionState _getCompressionState(
+      _HttpClient httpClient, _HttpHeaders headers) {
+    if (headers.value(HttpHeaders.contentEncodingHeader) == "gzip") {
+      return httpClient.autoUncompress
+          ? HttpClientResponseCompressionState.decompressed
+          : HttpClientResponseCompressionState.compressed;
+    } else {
+      return HttpClientResponseCompressionState.notCompressed;
+    }
+  }
+
   int get statusCode => _incoming.statusCode;
   String get reasonPhrase => _incoming.reasonPhrase;
 
   X509Certificate get certificate {
     var socket = _httpRequest._httpClientConnection._socket;
     if (socket is SecureSocket) return socket.peerCertificate;
-    throw new UnsupportedError("Socket is not a SecureSocket");
+    return null;
   }
 
   List<Cookie> get cookies {
@@ -381,8 +392,7 @@
       return new Stream<List<int>>.empty().listen(null, onDone: onDone);
     }
     Stream<List<int>> stream = _incoming;
-    if (autoUncompress &&
-        headers.value(HttpHeaders.contentEncodingHeader) == "gzip") {
+    if (compressionState == HttpClientResponseCompressionState.decompressed) {
       stream = stream.transform(gzip.decoder);
     }
     return stream.listen(onData,
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index 998f42b..d0a1215 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -2352,6 +2352,7 @@
         _rsh(uDigits, maxUsed, 1, uDigits);
         if (ac) {
           if (((aDigits[0] & 1) == 1) || ((bDigits[0] & 1) == 1)) {
+            // a += y
             if (aIsNegative) {
               if ((aDigits[maxUsed] != 0) ||
                   (_compareDigits(aDigits, maxUsed, yDigits, maxUsed)) > 0) {
@@ -2363,6 +2364,7 @@
             } else {
               _absAdd(aDigits, abcdUsed, yDigits, maxUsed, aDigits);
             }
+            // b -= x
             if (bIsNegative) {
               _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
             } else if ((bDigits[maxUsed] != 0) ||
@@ -2375,6 +2377,7 @@
           }
           _rsh(aDigits, abcdUsed, 1, aDigits);
         } else if ((bDigits[0] & 1) == 1) {
+          // b -= x
           if (bIsNegative) {
             _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
           } else if ((bDigits[maxUsed] != 0) ||
@@ -2391,6 +2394,7 @@
         _rsh(vDigits, maxUsed, 1, vDigits);
         if (ac) {
           if (((cDigits[0] & 1) == 1) || ((dDigits[0] & 1) == 1)) {
+            // c += y
             if (cIsNegative) {
               if ((cDigits[maxUsed] != 0) ||
                   (_compareDigits(cDigits, maxUsed, yDigits, maxUsed) > 0)) {
@@ -2402,6 +2406,7 @@
             } else {
               _absAdd(cDigits, abcdUsed, yDigits, maxUsed, cDigits);
             }
+            // d -= x
             if (dIsNegative) {
               _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
             } else if ((dDigits[maxUsed] != 0) ||
@@ -2414,6 +2419,7 @@
           }
           _rsh(cDigits, abcdUsed, 1, cDigits);
         } else if ((dDigits[0] & 1) == 1) {
+          // d -= x
           if (dIsNegative) {
             _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
           } else if ((dDigits[maxUsed] != 0) ||
@@ -2427,8 +2433,10 @@
         _rsh(dDigits, abcdUsed, 1, dDigits);
       }
       if (_compareDigits(uDigits, maxUsed, vDigits, maxUsed) >= 0) {
+        // u -= v
         _absSub(uDigits, maxUsed, vDigits, maxUsed, uDigits);
         if (ac) {
+          // a -= c
           if (aIsNegative == cIsNegative) {
             var a_cmp_c = _compareDigits(aDigits, abcdUsed, cDigits, abcdUsed);
             if (a_cmp_c > 0) {
@@ -2441,6 +2449,7 @@
             _absAdd(aDigits, abcdUsed, cDigits, abcdUsed, aDigits);
           }
         }
+        // b -= d
         if (bIsNegative == dIsNegative) {
           var b_cmp_d = _compareDigits(bDigits, abcdUsed, dDigits, abcdUsed);
           if (b_cmp_d > 0) {
@@ -2453,8 +2462,10 @@
           _absAdd(bDigits, abcdUsed, dDigits, abcdUsed, bDigits);
         }
       } else {
+        // v -= u
         _absSub(vDigits, maxUsed, uDigits, maxUsed, vDigits);
         if (ac) {
+          // c -= a
           if (cIsNegative == aIsNegative) {
             var c_cmp_a = _compareDigits(cDigits, abcdUsed, aDigits, abcdUsed);
             if (c_cmp_a > 0) {
@@ -2467,6 +2478,7 @@
             _absAdd(cDigits, abcdUsed, aDigits, abcdUsed, cDigits);
           }
         }
+        // d -= b
         if (dIsNegative == bIsNegative) {
           var d_cmp_b = _compareDigits(dDigits, abcdUsed, bDigits, abcdUsed);
           if (d_cmp_b > 0) {
@@ -2498,25 +2510,18 @@
     }
 
     if (dIsNegative) {
-      if ((dDigits[maxUsed] != 0) ||
+      while ((dDigits[maxUsed] != 0) ||
           (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+        // d += x, d still negative
         _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-        if ((dDigits[maxUsed] != 0) ||
-            (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-          _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-        } else {
-          _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
-          dIsNegative = false;
-        }
-      } else {
-        _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
-        dIsNegative = false;
       }
-    } else if ((dDigits[maxUsed] != 0) ||
-        (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
-      _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
-      if ((dDigits[maxUsed] != 0) ||
-          (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+      // d += x
+      _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
+      dIsNegative = false;
+    } else {
+      while ((dDigits[maxUsed] != 0) ||
+        (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) >= 0)) {
+        // d -= x
         _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
       }
     }
diff --git a/sdk/lib/developer/extension.dart b/sdk/lib/developer/extension.dart
index c6f4cce..3cc4ede 100644
--- a/sdk/lib/developer/extension.dart
+++ b/sdk/lib/developer/extension.dart
@@ -9,19 +9,24 @@
 /// If the RPC was successful, use [ServiceExtensionResponse.result], otherwise
 /// use [ServiceExtensionResponse.error].
 class ServiceExtensionResponse {
-  final String _result;
-  final int _errorCode;
-  final String _errorDetail;
+  /// The result of a successful service protocol extension RPC.
+  final String result;
+
+  /// The error code associated with a failed service protocol extension RPC.
+  final int errorCode;
+
+  /// The details of a failed service protocol extension RPC.
+  final String errorDetail;
 
   /// Creates a successful response to a service protocol extension RPC.
   ///
   /// Requires [result] to be a JSON object encoded as a string. When forming
   /// the JSON-RPC message [result] will be inlined directly.
   ServiceExtensionResponse.result(String result)
-      : _result = result,
-        _errorCode = null,
-        _errorDetail = null {
-    ArgumentError.checkNotNull(_result, "result");
+      : result = result,
+        errorCode = null,
+        errorDetail = null {
+    ArgumentError.checkNotNull(result, "result");
   }
 
   /// Creates an error response to a service protocol extension RPC.
@@ -31,11 +36,11 @@
   /// encoded as a string. When forming the JSON-RPC message [errorDetail] will
   /// be inlined directly.
   ServiceExtensionResponse.error(int errorCode, String errorDetail)
-      : _result = null,
-        _errorCode = errorCode,
-        _errorDetail = errorDetail {
-    _validateErrorCode(_errorCode);
-    ArgumentError.checkNotNull(_errorDetail, "errorDetail");
+      : result = null,
+        errorCode = errorCode,
+        errorDetail = errorDetail {
+    _validateErrorCode(errorCode);
+    ArgumentError.checkNotNull(errorDetail, "errorDetail");
   }
 
   /// Invalid method parameter(s) error code.
@@ -83,20 +88,20 @@
     throw new ArgumentError.value(errorCode, "errorCode", "Out of range");
   }
 
-  // ignore: unused_element, called from runtime/lib/developer.dart
-  bool _isError() => (_errorCode != null) && (_errorDetail != null);
+  /// Determines if this response represents an error.
+  bool isError() => (errorCode != null) && (errorDetail != null);
 
   // ignore: unused_element, called from runtime/lib/developer.dart
   String _toString() {
-    if (_result != null) {
-      return _result;
+    if (result != null) {
+      return result;
     } else {
-      assert(_errorCode != null);
-      assert(_errorDetail != null);
+      assert(errorCode != null);
+      assert(errorDetail != null);
       return json.encode({
-        'code': _errorCode,
-        'message': _errorCodeMessage(_errorCode),
-        'data': {'details': _errorDetail}
+        'code': errorCode,
+        'message': _errorCodeMessage(errorCode),
+        'data': {'details': errorDetail}
       });
     }
   }
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 656fa6b..eb75be5 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -13944,6 +13944,8 @@
   @JSName('innerHTML')
   String _innerHtml;
 
+  String innerText;
+
   @JSName('localName')
   final String _localName;
 
diff --git a/tests/co19_2/co19_2-dart2js.status b/tests/co19_2/co19_2-dart2js.status
index c4f2692..5321ddf 100644
--- a/tests/co19_2/co19_2-dart2js.status
+++ b/tests/co19_2/co19_2-dart2js.status
@@ -10,6 +10,17 @@
 LibTest/html/*: SkipByDesign # d8 is not a browser
 WebPlatformTest/*: SkipByDesign # d8 is not a browser
 
+[ $compiler == dart2js && $runtime == ie11 ]
+LibTest/collection/ListBase/ListBase_class_A01_t04: SkipSlow # slow babeljs transformation
+LibTest/collection/ListBase/ListBase_class_A01_t05: SkipSlow # slow babeljs transformation
+LibTest/collection/ListBase/ListBase_class_A01_t06: SkipSlow # slow babeljs transformation
+LibTest/collection/ListMixin/ListMixin_class_A01_t04: SkipSlow # slow babeljs transformation
+LibTest/collection/ListMixin/ListMixin_class_A01_t05: SkipSlow # slow babeljs transformation
+LibTest/collection/ListMixin/ListMixin_class_A01_t06: SkipSlow # slow babeljs transformation
+LibTest/core/List/List_class_A01_t04: SkipSlow # slow babeljs transformation
+LibTest/core/List/List_class_A01_t05: SkipSlow # slow babeljs transformation
+LibTest/core/List/List_class_A01_t06: SkipSlow # slow babeljs transformation
+
 [ $compiler == dart2js || $compiler == dartdevc || $compiler == dartdevk ]
 Language/Expressions/Spawning_an_Isolate/new_isolate_t01: SkipByDesign
 LibTest/io/*: SkipByDesign # dart:io not supported.
diff --git a/tests/compiler/dart2js/analyses/api_allowed.json b/tests/compiler/dart2js/analyses/api_allowed.json
index a7a08a3..cec99f0 100644
--- a/tests/compiler/dart2js/analyses/api_allowed.json
+++ b/tests/compiler/dart2js/analyses/api_allowed.json
@@ -28,10 +28,10 @@
     "Dynamic invocation of '_js_helper::_execGlobal'.": 1,
     "Dynamic access of 'start'.": 1,
     "Dynamic access of 'end'.": 1,
-    "Dynamic access of 'length'.": 3,
-    "Dynamic invocation of '[]'.": 1,
     "Dynamic invocation of 'call'.": 13,
+    "Dynamic access of 'length'.": 3,
     "Dynamic invocation of 'codeUnitAt'.": 2,
+    "Dynamic invocation of '[]'.": 1,
     "Dynamic access of 'iterator'.": 2,
     "Dynamic invocation of 'replaceRange'.": 2
   },
@@ -184,7 +184,7 @@
   "org-dartlang-sdk:///sdk/lib/_internal/js_runtime/lib/core_patch.dart": {
     "Dynamic access of 'dart.core::_digits'.": 2,
     "Dynamic invocation of '<'.": 2,
-    "Dynamic invocation of '[]'.": 19,
+    "Dynamic invocation of '[]'.": 17,
     "Dynamic invocation of '+'.": 2,
     "Dynamic invocation of 'dart.core::_absSubSetSign'.": 3,
     "Dynamic invocation of 'dart.core::_absAndNotSetSign'.": 2,
@@ -244,4 +244,4 @@
     "Dynamic access of 'port'.": 1,
     "Dynamic invocation of 'dart._http::_toJSON'.": 1
   }
-}
+}
\ No newline at end of file
diff --git a/tests/compiler/dart2js/codegen/model_test.dart b/tests/compiler/dart2js/codegen/model_test.dart
index 61f5c27..47d0c5c 100644
--- a/tests/compiler/dart2js/codegen/model_test.dart
+++ b/tests/compiler/dart2js/codegen/model_test.dart
@@ -6,6 +6,7 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/closure.dart';
 import 'package:compiler/src/common.dart';
+import 'package:compiler/src/common/codegen.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/elements/entities.dart';
@@ -89,9 +90,9 @@
   void registerCalls(Features features, String tag, js.Node node,
       {String prefix = '', Set<js.PropertyAccess> handledAccesses}) {
     forEachNode(node, onCall: (js.Call node) {
-      js.Node target = node.target;
+      js.Node target = undefer(node.target);
       if (target is js.PropertyAccess) {
-        js.Node selector = target.selector;
+        js.Node selector = undefer(target.selector);
         bool fixedNameCall = false;
         String name;
         if (selector is js.Name) {
@@ -125,7 +126,7 @@
         return;
       }
 
-      js.Node receiver = node.receiver;
+      js.Node receiver = undefer(node.receiver);
       String receiverName;
       if (receiver is js.VariableUse) {
         receiverName = receiver.name;
@@ -138,7 +139,7 @@
         receiverName = 'this';
       }
 
-      js.Node selector = node.selector;
+      js.Node selector = undefer(node.selector);
       String name;
       if (selector is js.Name) {
         name = selector.key;
@@ -229,9 +230,9 @@
         }
 
         forEachNode(code, onAssignment: (js.Assignment node) {
-          js.Expression leftHandSide = node.leftHandSide;
+          js.Expression leftHandSide = undefer(node.leftHandSide);
           if (leftHandSide is js.PropertyAccess) {
-            js.Node selector = leftHandSide.selector;
+            js.Node selector = undefer(leftHandSide.selector);
             String name;
             if (selector is js.Name) {
               name = selector.key;
@@ -272,3 +273,9 @@
     return null;
   }
 }
+
+js.Node undefer(js.Node node) {
+  if (node is js.DeferredExpression) return undefer(node.value);
+  if (node is ModularName) return undefer(node.value);
+  return node;
+}
diff --git a/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart b/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
index e79853c..b23c178 100644
--- a/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
+++ b/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
@@ -105,7 +105,7 @@
       {bool verbose: false}) {
     JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     OutputUnitData data = closedWorld.outputUnitData;
-    String value = outputUnitString(data.outputUnitForClass(cls));
+    String value = outputUnitString(data.outputUnitForClassForTesting(cls));
 
     JsToElementMap elementMap = closedWorld.elementMap;
     ClassDefinition definition = elementMap.getClassDefinition(cls);
@@ -141,7 +141,7 @@
 
   String getMemberValue(MemberEntity member, Set<String> constants) {
     StringBuffer sb = new StringBuffer();
-    sb.write(outputUnitString(_data.outputUnitForMember(member)));
+    sb.write(outputUnitString(_data.outputUnitForMemberForTesting(member)));
     if (constants.isNotEmpty) {
       List<String> text = constants.toList()..sort();
       sb.write(',constants=[${text.join(',')}]');
@@ -166,7 +166,7 @@
         }
         _registerValue(
             new NodeId(span.begin, IdKind.node),
-            outputUnitString(_data.outputUnitForConstant(constant)),
+            outputUnitString(_data.outputUnitForConstantForTesting(constant)),
             node,
             span,
             actualMap,
diff --git a/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart b/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart
index 545c685..a207e12 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart
@@ -17,7 +17,7 @@
 /*strong.element: C2b:OutputUnit(1, {lib1})*/
 const C2b = /*strong.OutputUnit(1, {lib1})*/ const C(1010);
 
-/*class: D:OutputUnit(main, {})*/
+/*class: D:null*/
 class D {
   /*strong.element: D.C3:OutputUnit(1, {lib1})*/
   static const C3 = "string2";
diff --git a/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart b/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart
index 18f9ec3..4707d65 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart
@@ -38,7 +38,7 @@
   }
 }
 
-/*class: C1:OutputUnit(main, {})*/
+/*class: C1:null*/
 class C1 {
   /*strong.element: C1.foo:OutputUnit(3, {lib2})*/
   /*strongConst.element: C1.foo:
diff --git a/tests/compiler/dart2js/end_to_end/command_line_test.dart b/tests/compiler/dart2js/end_to_end/command_line_test.dart
index 88fb3e8..076b918 100644
--- a/tests/compiler/dart2js/end_to_end/command_line_test.dart
+++ b/tests/compiler/dart2js/end_to_end/command_line_test.dart
@@ -10,6 +10,7 @@
 import 'package:expect/expect.dart';
 
 import 'package:compiler/compiler_new.dart' as api;
+import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/dart2js.dart' as entry;
 import 'package:compiler/src/options.dart' show CompilerOptions;
 
@@ -17,11 +18,191 @@
   entry.enableWriteString = false;
   asyncTest(() async {
     await test([], exitCode: 1);
-    await test(['foo.dart']);
+    await test(['foo.dart'], out: 'out.js');
+    await test(['foo.dart', '-ofoo.js'], out: 'foo.js');
+    await test(['foo.dart', '--out=foo.js'], out: 'foo.js');
+
+    await test([Flags.cfeOnly], exitCode: 1);
+    await test([Flags.cfeOnly, 'foo.dart'], out: 'out.dill');
+    await test([Flags.cfeOnly, 'foo.dart', '--out=out.dill'], out: 'out.dill');
+    await test([Flags.cfeOnly, 'foo.dart', Flags.readData], exitCode: 1);
+    await test(['foo.dart', Flags.readData, Flags.cfeOnly], exitCode: 1);
+    await test([Flags.cfeOnly, 'foo.dart', Flags.readCodegen], exitCode: 1);
+    await test(['foo.dart', Flags.readCodegen, Flags.cfeOnly], exitCode: 1);
+    await test([Flags.cfeOnly, 'foo.dart', Flags.writeData], exitCode: 1);
+    await test(['foo.dart', Flags.writeData, Flags.cfeOnly], exitCode: 1);
+    await test([Flags.cfeOnly, 'foo.dart', Flags.writeCodegen], exitCode: 1);
+    await test(['foo.dart', Flags.writeCodegen, Flags.cfeOnly], exitCode: 1);
+
+    await test([Flags.writeData, 'foo.dart'],
+        out: 'out.dill', writeData: 'out.dill.data');
+    await test(['${Flags.writeData}=foo.data', 'foo.dart', '--out=foo.dill'],
+        out: 'foo.dill', writeData: 'foo.data');
+    await test([Flags.readData, Flags.writeData, 'foo.dart'], exitCode: 1);
+    await test([Flags.writeData, Flags.readData, 'foo.dart'], exitCode: 1);
+    await test([Flags.readCodegen, Flags.writeData, 'foo.dart'], exitCode: 1);
+    await test([Flags.writeData, Flags.readCodegen, 'foo.dart'], exitCode: 1);
+
+    await test([Flags.readData, 'foo.dill'],
+        out: 'out.js', readData: 'foo.dill.data');
+    await test([Flags.readData, 'foo.dill', '--out=foo.js'],
+        out: 'foo.js', readData: 'foo.dill.data');
+    await test(['${Flags.readData}=out.data', 'foo.dill'],
+        out: 'out.js', readData: 'out.data');
+    await test(['${Flags.readData}=out.data', 'foo.dill', '--out=foo.js'],
+        out: 'foo.js', readData: 'out.data');
+
+    await test([
+      Flags.writeCodegen,
+      'foo.dill',
+      '${Flags.codegenShard}=0',
+      '${Flags.codegenShards}=2'
+    ], exitCode: 1);
+    await test([
+      Flags.readData,
+      Flags.writeCodegen,
+      'foo.dill',
+      '${Flags.codegenShard}=0',
+      '${Flags.codegenShards}=2'
+    ],
+        out: 'out',
+        readData: 'foo.dill.data',
+        writeCodegen: 'out.code',
+        codegenShard: 0,
+        codegenShards: 2);
+    await test([
+      Flags.writeCodegen,
+      Flags.readData,
+      'foo.dill',
+      '${Flags.codegenShard}=1',
+      '${Flags.codegenShards}=2'
+    ],
+        out: 'out',
+        readData: 'foo.dill.data',
+        writeCodegen: 'out.code',
+        codegenShard: 1,
+        codegenShards: 2);
+    await test([
+      '${Flags.readData}=foo.data',
+      '${Flags.writeCodegen}=foo.code',
+      'foo.dill',
+      '${Flags.codegenShard}=0',
+      '${Flags.codegenShards}=3'
+    ],
+        out: 'out',
+        readData: 'foo.data',
+        writeCodegen: 'foo.code',
+        codegenShard: 0,
+        codegenShards: 3);
+    await test([
+      '${Flags.readData}=foo.data',
+      '${Flags.writeCodegen}',
+      'foo.dill',
+      '--out=foo.js',
+      '${Flags.codegenShard}=0',
+      '${Flags.codegenShards}=2'
+    ],
+        out: 'foo.js',
+        readData: 'foo.data',
+        writeCodegen: 'foo.js.code',
+        codegenShard: 0,
+        codegenShards: 2);
+    await test([Flags.writeCodegen, 'foo.dill', Flags.readCodegen],
+        exitCode: 1);
+    await test([Flags.readCodegen, Flags.writeCodegen, 'foo.dill'],
+        exitCode: 1);
+    await test(
+        [Flags.readData, Flags.writeCodegen, 'foo.dill', Flags.readCodegen],
+        exitCode: 1);
+    await test(
+        [Flags.readCodegen, Flags.readData, Flags.writeCodegen, 'foo.dill'],
+        exitCode: 1);
+    await test([
+      Flags.readData,
+      Flags.writeCodegen,
+      'foo.dill',
+    ], exitCode: 1);
+    await test([
+      Flags.readData,
+      Flags.writeCodegen,
+      'foo.dill',
+      '${Flags.codegenShard}=0'
+    ], exitCode: 1);
+    await test([
+      Flags.readData,
+      Flags.writeCodegen,
+      'foo.dill',
+      '${Flags.codegenShards}=2'
+    ], exitCode: 1);
+    await test([
+      Flags.readData,
+      Flags.writeCodegen,
+      'foo.dill',
+      '${Flags.codegenShards}=0'
+    ], exitCode: 1);
+    await test([
+      Flags.readData,
+      Flags.writeCodegen,
+      'foo.dill',
+      '${Flags.codegenShard}=-1',
+      '${Flags.codegenShards}=2'
+    ], exitCode: 1);
+    await test([
+      Flags.readData,
+      Flags.writeCodegen,
+      'foo.dill',
+      '${Flags.codegenShard}=2',
+      '${Flags.codegenShards}=2'
+    ], exitCode: 1);
+
+    await test([Flags.readCodegen, 'foo.dill', '${Flags.codegenShards}=2'],
+        out: 'out.js',
+        readData: 'foo.dill.data',
+        readCodegen: 'foo.dill.code',
+        codegenShards: 2);
+    await test([
+      '${Flags.readCodegen}=foo.code',
+      'foo.dill',
+      '${Flags.codegenShards}=3'
+    ],
+        out: 'out.js',
+        readData: 'foo.dill.data',
+        readCodegen: 'foo.code',
+        codegenShards: 3);
+
+    await test([
+      Flags.readData,
+      Flags.readCodegen,
+      'foo.dill',
+      '${Flags.codegenShards}=2'
+    ],
+        out: 'out.js',
+        readData: 'foo.dill.data',
+        readCodegen: 'foo.dill.code',
+        codegenShards: 2);
+    await test([
+      '${Flags.readData}=foo.data',
+      '${Flags.readCodegen}=foo.code',
+      'foo.dill',
+      '${Flags.codegenShards}=3',
+      '-v'
+    ],
+        out: 'out.js',
+        readData: 'foo.data',
+        readCodegen: 'foo.code',
+        codegenShards: 3);
   });
 }
 
-Future test(List<String> arguments, {int exitCode}) async {
+Future test(List<String> arguments,
+    {int exitCode,
+    String out,
+    String readData,
+    String writeData,
+    String readCodegen,
+    String writeCodegen,
+    int codegenShard,
+    int codegenShards}) async {
   print('--------------------------------------------------------------------');
   print('dart2js ${arguments.join(' ')}');
   print('--------------------------------------------------------------------');
@@ -47,8 +228,23 @@
   Expect.equals(exitCode, actualExitCode, "Unexpected exit code");
   if (actualExitCode == null) {
     Expect.isNotNull(options, "Missing options object");
+    Expect.equals(toUri(out), options.outputUri, "Unexpected output uri.");
+    Expect.equals(
+        toUri(readData), options.readDataUri, "Unexpected readData uri");
+    Expect.equals(
+        toUri(writeData), options.writeDataUri, "Unexpected writeData uri");
+    Expect.equals(toUri(readCodegen), options.readCodegenUri,
+        "Unexpected readCodegen uri");
+    Expect.equals(toUri(writeCodegen), options.writeCodegenUri,
+        "Unexpected writeCodegen uri");
+    Expect.equals(
+        codegenShard, options.codegenShard, "Unexpected codegenShard uri");
+    Expect.equals(
+        codegenShards, options.codegenShards, "Unexpected codegenShards uri");
   }
 
   entry.compileFunc = oldCompileFunc;
   entry.exitFunc = oldExitFunc;
 }
+
+Uri toUri(String path) => path != null ? Uri.base.resolve(path) : null;
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 e424fad..3397753 100644
--- a/tests/compiler/dart2js/end_to_end/exit_code_test.dart
+++ b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
@@ -11,6 +11,7 @@
 
 import 'package:compiler/compiler_new.dart' as api;
 import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/common/codegen.dart';
 import 'package:compiler/src/common/work.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/dart2js.dart' as entry;
@@ -110,10 +111,15 @@
             useNewSourceInfo: compiler.options.useNewSourceInfo);
 
   @override
-  WorldImpact generateCode(WorkItem work, JClosedWorld closedWorld,
-      EntityLookup entityLookup, ComponentLookup componentLookup) {
+  WorldImpact generateCode(
+      WorkItem work,
+      JClosedWorld closedWorld,
+      CodegenResults codegenResults,
+      EntityLookup entityLookup,
+      ComponentLookup componentLookup) {
     compiler.test('Compiler.codegen');
-    return super.generateCode(work, closedWorld, entityLookup, componentLookup);
+    return super.generateCode(
+        work, closedWorld, codegenResults, entityLookup, componentLookup);
   }
 }
 
diff --git a/tests/compiler/dart2js/inlining/inlining_test.dart b/tests/compiler/dart2js/inlining/inlining_test.dart
index c6a8b92..8e73762 100644
--- a/tests/compiler/dart2js/inlining/inlining_test.dart
+++ b/tests/compiler/dart2js/inlining/inlining_test.dart
@@ -12,7 +12,7 @@
 import 'package:compiler/src/js_backend/backend.dart';
 import 'package:compiler/src/js_model/element_map.dart';
 import 'package:compiler/src/js_model/js_world.dart';
-import 'package:compiler/src/ssa/builder_kernel.dart' as kernel;
+import 'package:compiler/src/ssa/builder_kernel.dart';
 import 'package:compiler/src/universe/world_impact.dart';
 import 'package:compiler/src/universe/use.dart';
 import 'package:kernel/ast.dart' as ir;
@@ -53,6 +53,7 @@
   final JavaScriptBackend backend;
   final JsToElementMap _elementMap;
   final ClosureData _closureDataLookup;
+  final InlineDataCache _inlineDataCache;
 
   InliningIrComputer(
       DiagnosticReporter reporter,
@@ -61,7 +62,8 @@
       MemberEntity member,
       this.backend,
       this._closureDataLookup)
-      : super(reporter, actualMap);
+      : this._inlineDataCache = new InlineDataCache(enableUserAssertions: true),
+        super(reporter, actualMap);
 
   String getMemberValue(MemberEntity member) {
     if (member is FunctionEntity) {
@@ -125,14 +127,16 @@
 
   String getTooDifficultReasonForbidLoops(MemberEntity member) {
     if (member is! FunctionEntity) return null;
-    return kernel.InlineWeeder.cannotBeInlinedReason(_elementMap, member, null,
-        enableUserAssertions: true);
+    return _inlineDataCache
+        .getInlineData(_elementMap, member)
+        .cannotBeInlinedReason();
   }
 
   String getTooDifficultReasonAllowLoops(MemberEntity member) {
     if (member is! FunctionEntity) return null;
-    return kernel.InlineWeeder.cannotBeInlinedReason(_elementMap, member, null,
-        allowLoops: true, enableUserAssertions: true);
+    return _inlineDataCache
+        .getInlineData(_elementMap, member)
+        .cannotBeInlinedReason(allowLoops: true);
   }
 
   @override
diff --git a/tests/compiler/dart2js/model/class_set_test.dart b/tests/compiler/dart2js/model/class_set_test.dart
index 5ceb1e8..ea78222 100644
--- a/tests/compiler/dart2js/model/class_set_test.dart
+++ b/tests/compiler/dart2js/model/class_set_test.dart
@@ -344,6 +344,7 @@
     List<ClassEntity> visited = <ClassEntity>[];
     classSet.forEachSubclass((cls) {
       visited.add(cls);
+      return IterationStep.CONTINUE;
     }, ClassHierarchyNode.ALL);
 
     Expect.listEquals(
@@ -381,6 +382,7 @@
     List<ClassEntity> visited = <ClassEntity>[];
     classSet.forEachSubtype((cls) {
       visited.add(cls);
+      return IterationStep.CONTINUE;
     }, ClassHierarchyNode.ALL);
 
     Expect.listEquals(
diff --git a/tests/compiler/dart2js/model/receiver_type_test.dart b/tests/compiler/dart2js/model/receiver_type_test.dart
index 663c6e3..3ad5042 100644
--- a/tests/compiler/dart2js/model/receiver_type_test.dart
+++ b/tests/compiler/dart2js/model/receiver_type_test.dart
@@ -6,6 +6,7 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/inferrer/typemasks/masks.dart';
+import 'package:compiler/src/universe/class_set.dart';
 import 'package:compiler/src/universe/selector.dart';
 import 'package:compiler/src/world.dart';
 import 'package:expect/expect.dart';
@@ -49,7 +50,8 @@
   Selector callSelector = new Selector.callClosure(0);
   closedWorld.classHierarchy.forEachStrictSubclassOf(
       closedWorld.commonElements.objectClass, (ClassEntity cls) {
-    if (cls.library.canonicalUri.scheme != 'memory') return;
+    if (cls.library.canonicalUri.scheme != 'memory')
+      return IterationStep.CONTINUE;
 
     TypeMask mask = new TypeMask.nonNullSubclass(cls, closedWorld);
     TypeMask receiverType = closedWorld.computeReceiverType(callSelector, mask);
@@ -65,6 +67,7 @@
       Expect.equals(expected, '$receiverType',
           "Unexpected receiver type for $callSelector on $mask");
     }
+    return IterationStep.CONTINUE;
   });
 
   Expect.equals(2, closureCount);
diff --git a/tests/compiler/dart2js/model/world_test.dart b/tests/compiler/dart2js/model/world_test.dart
index c49ff3d..b2106a8 100644
--- a/tests/compiler/dart2js/model/world_test.dart
+++ b/tests/compiler/dart2js/model/world_test.dart
@@ -99,6 +99,7 @@
       List<ClassEntity> visited = <ClassEntity>[];
       forEach(cls, (ClassEntity c) {
         visited.add(c);
+        return IterationStep.CONTINUE;
       });
       checkClasses('forEach($property)', cls, visited, expectedClasses,
           exact: exact);
@@ -424,6 +425,7 @@
       if (allClasses.contains(other)) {
         strictSubclasses.add(other);
       }
+      return IterationStep.CONTINUE;
     });
     Expect.setEquals(subclasses, strictSubclasses,
         "Unexpected strict subclasses of $cls: ${strictSubclasses}.");
@@ -433,6 +435,7 @@
       if (allClasses.contains(other)) {
         strictSubtypes.add(other);
       }
+      return IterationStep.CONTINUE;
     });
     Expect.setEquals(subtypes, strictSubtypes,
         "Unexpected strict subtypes of $cls: $strictSubtypes.");
diff --git a/tests/compiler/dart2js/modular/data/int_js_number/modules.yaml b/tests/compiler/dart2js/modular/data/int_js_number/modules.yaml
index a02b69a..e8cdeea 100644
--- a/tests/compiler/dart2js/modular/data/int_js_number/modules.yaml
+++ b/tests/compiler/dart2js/modular/data/int_js_number/modules.yaml
@@ -6,3 +6,5 @@
 # after serialization across modules.
 dependencies:
   main: def
+flags:
+  - constant-update-2018
diff --git a/tests/compiler/dart2js/modular/modular_test.dart b/tests/compiler/dart2js/modular/modular_test.dart
index 80aa857..fd60292 100644
--- a/tests/compiler/dart2js/modular/modular_test.dart
+++ b/tests/compiler/dart2js/modular/modular_test.dart
@@ -7,53 +7,40 @@
 /// This is a shell that runs multiple tests, one per folder under `data/`.
 import 'dart:io';
 
-import 'package:args/args.dart';
-import 'package:async_helper/async_helper.dart';
-import 'package:expect/expect.dart';
+import 'package:compiler/src/commandline_options.dart';
 import 'package:front_end/src/compute_platform_binaries_location.dart'
     show computePlatformBinariesLocation;
 import 'package:modular_test/src/io_pipeline.dart';
-import 'package:modular_test/src/loader.dart';
 import 'package:modular_test/src/pipeline.dart';
 import 'package:modular_test/src/suite.dart';
+import 'package:modular_test/src/runner.dart';
 
-_Options _options;
-main(List<String> args) {
-  _options = _Options.parse(args);
-  asyncTest(() async {
-    var baseUri = Platform.script.resolve('data/');
-    var baseDir = Directory.fromUri(baseUri);
-    await for (var entry in baseDir.list(recursive: false)) {
-      if (entry is Directory) {
-        await _runTest(entry.uri, baseUri);
-      }
-    }
-  });
-}
-
-Future<void> _runTest(Uri uri, Uri baseDir) async {
-  var dirName = uri.path.substring(baseDir.path.length);
-  if (_options.filter != null && !dirName.contains(_options.filter)) {
-    if (_options.showSkipped) print("skipped: $dirName");
-    return;
-  }
-
-  print("testing: $dirName");
-  ModularTest test = await loadTest(uri);
-  if (_options.verbose) print(test.debugString());
-  var pipeline = new IOPipeline([
-    SourceToDillStep(),
-    GlobalAnalysisStep(),
-    Dart2jsBackendStep(),
-    RunD8(),
-  ]);
-
-  await pipeline.run(test);
+Uri sdkRoot = Platform.script.resolve("../../../../");
+Options _options;
+main(List<String> args) async {
+  _options = Options.parse(args);
+  var suiteFolder = Platform.script.resolve('data/');
+  var suiteName = relativize(suiteFolder, sdkRoot).path;
+  await runSuite(
+      suiteFolder,
+      suiteName.substring(0, suiteName.length - 1), // remove trailing /
+      _options,
+      new IOPipeline([
+        SourceToDillStep(),
+        GlobalAnalysisStep(),
+        Dart2jsCodegenStep(codeId0),
+        Dart2jsCodegenStep(codeId1),
+        Dart2jsEmissionStep(),
+        RunD8(),
+      ], cacheSharedModules: true));
 }
 
 const dillId = const DataId("dill");
 const updatedDillId = const DataId("udill");
 const globalDataId = const DataId("gdata");
+const codeId = const ShardsDataId("code", 2);
+const codeId0 = const ShardDataId(codeId, 0);
+const codeId1 = const ShardDataId(codeId, 1);
 const jsId = const DataId("js");
 const txtId = const DataId("txt");
 
@@ -75,9 +62,10 @@
   bool get onlyOnMain => false;
 
   @override
-  Future<void> execute(
-      Module module, Uri root, ModuleDataToRelativeUri toUri) async {
-    if (_options.verbose) print("step: source-to-dill on $module");
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: source-to-dill on $module");
+
     // We use non file-URI schemes for representeing source locations in a
     // root-agnostic way. This allows us to refer to file across modules and
     // across steps without exposing the underlying temporary folders that are
@@ -86,7 +74,7 @@
     //
     // Files in packages are defined in terms of `package:` URIs, while
     // non-package URIs are defined using the `dart-dev-app` scheme.
-    String rootScheme = 'dev-dart-app';
+    String rootScheme = module.isSdk ? 'dart-dev-sdk' : 'dev-dart-app';
     String sourceToImportUri(Uri relativeUri) {
       if (module.isPackage) {
         var basePath = module.packageBase.path;
@@ -126,10 +114,30 @@
         .writeAsString('$packagesContents');
 
     var sdkRoot = Platform.script.resolve("../../../../");
-    var platform =
-        computePlatformBinariesLocation().resolve("dart2js_platform.dill");
+    List<String> sources;
+    List<String> extraArgs;
+    if (module.isSdk) {
+      // When no flags are passed, we can skip compilation and reuse the
+      // platform.dill created by build.py.
+      if (flags.isEmpty) {
+        var platform =
+            computePlatformBinariesLocation().resolve("dart2js_platform.dill");
+        var destination = root.resolveUri(toUri(module, dillId));
+        if (_options.verbose) {
+          print('command:\ncp $platform $destination');
+        }
+        await File.fromUri(platform).copy(destination.toFilePath());
+        return;
+      }
+      sources = ['dart:core'];
+      extraArgs = ['--libraries-file', '$rootScheme:///sdk/lib/libraries.json'];
+      assert(transitiveDependencies.isEmpty);
+    } else {
+      sources = module.sources.map(sourceToImportUri).toList();
+      extraArgs = ['--packages-file', '$rootScheme:/.packages'];
+    }
 
-    List<String> workerArgs = [
+    List<String> args = [
       sdkRoot.resolve("utils/bazel/kernel_worker.dart").toFilePath(),
       '--no-summary-only',
       '--target',
@@ -138,21 +146,24 @@
       '$root',
       '--multi-root-scheme',
       rootScheme,
-      '--dart-sdk-summary',
-      '${platform}',
+      ...extraArgs,
       '--output',
       '${toUri(module, dillId)}',
-      '--packages-file',
-      '$rootScheme:/.packages',
       ...(transitiveDependencies
           .expand((m) => ['--input-linked', '${toUri(m, dillId)}'])),
-      ...(module.sources.expand((uri) => ['--source', sourceToImportUri(uri)])),
+      ...(sources.expand((String uri) => ['--source', uri])),
+      ...(flags.expand((String flag) => ['--enable-experiment', flag])),
     ];
 
-    var result = await _runProcess(
-        Platform.resolvedExecutable, workerArgs, root.toFilePath());
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
     _checkExitCode(result, this, module);
   }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: source-to-dill on $module");
+  }
 }
 
 // Step that invokes the dart2js global analysis on the main module by providing
@@ -174,9 +185,9 @@
   bool get onlyOnMain => true;
 
   @override
-  Future<void> execute(
-      Module module, Uri root, ModuleDataToRelativeUri toUri) async {
-    if (_options.verbose) print("step: dart2js global analysis on $module");
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: dart2js global analysis on $module");
     Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
     Iterable<String> dillDependencies =
         transitiveDependencies.map((m) => '${toUri(m, dillId)}');
@@ -185,8 +196,9 @@
       '--packages=${sdkRoot.toFilePath()}/.packages',
       'package:compiler/src/dart2js.dart',
       '${toUri(module, dillId)}',
-      '--dill-dependencies=${dillDependencies.join(',')}',
-      '--write-data=${toUri(module, globalDataId)}',
+      for (String flag in flags) '--enable-experiment=$flag',
+      '${Flags.dillDependencies}=${dillDependencies.join(',')}',
+      '${Flags.writeData}=${toUri(module, globalDataId)}',
       '--out=${toUri(module, updatedDillId)}',
     ];
     var result =
@@ -194,13 +206,24 @@
 
     _checkExitCode(result, this, module);
   }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose)
+      print("\ncached step: dart2js global analysis on $module");
+  }
 }
 
-// Step that invokes the dart2js backend on the main module given the results of
-// the global analysis step.
-class Dart2jsBackendStep implements IOModularStep {
+// Step that invokes the dart2js code generation on the main module given the
+// results of the global analysis step and produces one shard of the codegen
+// output.
+class Dart2jsCodegenStep implements IOModularStep {
+  final ShardDataId codeId;
+
+  Dart2jsCodegenStep(this.codeId);
+
   @override
-  List<DataId> get resultData => const [jsId];
+  List<DataId> get resultData => [codeId];
 
   @override
   bool get needsSources => false;
@@ -215,15 +238,64 @@
   bool get onlyOnMain => true;
 
   @override
-  Future<void> execute(
-      Module module, Uri root, ModuleDataToRelativeUri toUri) async {
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: dart2js backend on $module");
+    var sdkRoot = Platform.script.resolve("../../../../");
+    List<String> args = [
+      '--packages=${sdkRoot.toFilePath()}/.packages',
+      'package:compiler/src/dart2js.dart',
+      '${toUri(module, updatedDillId)}',
+      for (String flag in flags) '--enable-experiment=$flag',
+      '${Flags.readData}=${toUri(module, globalDataId)}',
+      '${Flags.writeCodegen}=${toUri(module, codeId.dataId)}',
+      '${Flags.codegenShard}=${codeId.shard}',
+      '${Flags.codegenShards}=${codeId.dataId.shards}',
+    ];
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("cached step: dart2js backend on $module");
+  }
+}
+
+// Step that invokes the dart2js codegen enqueuer and emitter on the main module
+// given the results of the global analysis step and codegen shards.
+class Dart2jsEmissionStep implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [jsId];
+
+  @override
+  bool get needsSources => false;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [];
+
+  @override
+  List<DataId> get moduleDataNeeded =>
+      const [updatedDillId, globalDataId, codeId0, codeId1];
+
+  @override
+  bool get onlyOnMain => true;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
     if (_options.verbose) print("step: dart2js backend on $module");
     var sdkRoot = Platform.script.resolve("../../../../");
     List<String> args = [
       '--packages=${sdkRoot.toFilePath()}/.packages',
       'package:compiler/src/dart2js.dart',
       '${toUri(module, updatedDillId)}',
-      '--read-data=${toUri(module, globalDataId)}',
+      for (String flag in flags) '${Flags.enableLanguageExperiments}=$flag',
+      '${Flags.readData}=${toUri(module, globalDataId)}',
+      '${Flags.readCodegen}=${toUri(module, codeId)}',
+      '${Flags.codegenShards}=${codeId.shards}',
       '--out=${toUri(module, jsId)}',
     ];
     var result =
@@ -231,6 +303,11 @@
 
     _checkExitCode(result, this, module);
   }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: dart2js backend on $module");
+  }
 }
 
 /// Step that runs the output of dart2js in d8 and saves the output.
@@ -251,9 +328,9 @@
   bool get onlyOnMain => true;
 
   @override
-  Future<void> execute(
-      Module module, Uri root, ModuleDataToRelativeUri toUri) async {
-    if (_options.verbose) print("step: d8 on $module");
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: d8 on $module");
     var sdkRoot = Platform.script.resolve("../../../../");
     List<String> d8Args = [
       sdkRoot
@@ -269,6 +346,11 @@
     await File.fromUri(root.resolveUri(toUri(module, txtId)))
         .writeAsString(result.stdout);
   }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: d8 on $module");
+  }
 }
 
 void _checkExitCode(ProcessResult result, IOModularStep step, Module module) {
@@ -277,8 +359,9 @@
     stderr.write(result.stderr);
   }
   if (result.exitCode != 0) {
-    exitCode = result.exitCode;
-    Expect.fail("${step.runtimeType} failed on $module");
+    throw "${step.runtimeType} failed on $module:\n\n"
+        "stdout:\n${result.stdout}\n\n"
+        "stderr:\n${result.stderr}";
   }
 }
 
@@ -301,26 +384,31 @@
   throw new UnsupportedError('Unsupported platform.');
 }
 
-class _Options {
-  bool showSkipped = false;
-  bool verbose = false;
-  String filter = null;
+class ShardsDataId implements DataId {
+  @override
+  final String name;
+  final int shards;
 
-  static _Options parse(List<String> args) {
-    var parser = new ArgParser()
-      ..addFlag('verbose',
-          abbr: 'v',
-          defaultsTo: false,
-          help: "print detailed information about the test and modular steps")
-      ..addFlag('show-skipped',
-          defaultsTo: false,
-          help: "print the name of the tests skipped by the filtering option")
-      ..addOption('filter',
-          help: "only run tests containing this filter as a substring");
-    ArgResults argResults = parser.parse(args);
-    return _Options()
-      ..showSkipped = argResults['show-skipped']
-      ..verbose = argResults['verbose']
-      ..filter = argResults['filter'];
+  const ShardsDataId(this.name, this.shards);
+
+  @override
+  String toString() => name;
+}
+
+class ShardDataId implements DataId {
+  final ShardsDataId dataId;
+  final int _shard;
+
+  const ShardDataId(this.dataId, this._shard);
+
+  int get shard {
+    assert(0 <= _shard && _shard < dataId.shards);
+    return _shard;
   }
+
+  @override
+  String get name => '${dataId.name}${shard}';
+
+  @override
+  String toString() => name;
 }
diff --git a/tests/compiler/dart2js/optimization/data/arithmetic.dart b/tests/compiler/dart2js/optimization/data/arithmetic.dart
index f8aad1b..3ec5b39 100644
--- a/tests/compiler/dart2js/optimization/data/arithmetic.dart
+++ b/tests/compiler/dart2js/optimization/data/arithmetic.dart
@@ -118,19 +118,19 @@
 // Negation
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: negate:Specializer=[Negate],TypeConversion=[]*/
+/*element: negate:Specializer=[Negate],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 negate(o) {
   return -o;
 }
 
-/*element: negateNum:Specializer=[Negate],TypeConversion=[]*/
+/*element: negateNum:Specializer=[Negate],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 negateNum(o) {
   return -o;
 }
 
-/*element: negateNull:Specializer=[Negate],TypeConversion=[kind=receiver&type=num]*/
+/*element: negateNull:Specializer=[Negate],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 negateNull(o) {
   return -o;
@@ -146,37 +146,37 @@
 // Addition
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: add:Specializer=[Add],TypeConversion=[]*/
+/*element: add:Specializer=[Add],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 add(a, b) {
   return a + b;
 }
 
-/*element: addNumInt:Specializer=[Add],TypeConversion=[]*/
+/*element: addNumInt:Specializer=[Add],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 addNumInt(a, b) {
   return a + b;
 }
 
-/*element: addIntNum:Specializer=[Add],TypeConversion=[]*/
+/*element: addIntNum:Specializer=[Add],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 addIntNum(a, b) {
   return a + b;
 }
 
-/*element: addNumNum:Specializer=[Add],TypeConversion=[]*/
+/*element: addNumNum:Specializer=[Add],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 addNumNum(a, b) {
   return a + b;
 }
 
-/*element: addNullInt:Specializer=[Add],TypeConversion=[kind=receiver&type=num]*/
+/*element: addNullInt:Specializer=[Add],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 addNullInt(a, b) {
   return a + b;
 }
 
-/*element: addIntNull:Specializer=[Add],TypeConversion=[kind=argument&type=num]*/
+/*element: addIntNull:Specializer=[Add],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 addIntNull(a, b) {
   return a + b;
@@ -188,7 +188,7 @@
   return a + b;
 }
 
-/*element: addIntString:Specializer=[Add],TypeConversion=[kind=argument&type=num]*/
+/*element: addIntString:Specializer=[Add],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 addIntString(a, b) {
   return a + b;
@@ -198,49 +198,49 @@
 // Subtraction
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: subtract:Specializer=[Subtract],TypeConversion=[]*/
+/*element: subtract:Specializer=[Subtract],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 subtract(a, b) {
   return a - b;
 }
 
-/*element: subtractNumInt:Specializer=[Subtract],TypeConversion=[]*/
+/*element: subtractNumInt:Specializer=[Subtract],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 subtractNumInt(a, b) {
   return a - b;
 }
 
-/*element: subtractIntNum:Specializer=[Subtract],TypeConversion=[]*/
+/*element: subtractIntNum:Specializer=[Subtract],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 subtractIntNum(a, b) {
   return a - b;
 }
 
-/*element: subtractNumNum:Specializer=[Subtract],TypeConversion=[]*/
+/*element: subtractNumNum:Specializer=[Subtract],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 subtractNumNum(a, b) {
   return a - b;
 }
 
-/*element: subtractNullInt:Specializer=[Subtract],TypeConversion=[kind=receiver&type=num]*/
+/*element: subtractNullInt:Specializer=[Subtract],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 subtractNullInt(a, b) {
   return a - b;
 }
 
-/*element: subtractIntNull:Specializer=[Subtract],TypeConversion=[kind=argument&type=num]*/
+/*element: subtractIntNull:Specializer=[Subtract],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 subtractIntNull(a, b) {
   return a - b;
 }
 
-/*element: subtractStringInt:Specializer=[Subtract],TypeConversion=[kind=receiver&type=num]*/
+/*element: subtractStringInt:Specializer=[Subtract],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 subtractStringInt(a, b) {
   return a - b;
 }
 
-/*element: subtractIntString:Specializer=[Subtract],TypeConversion=[kind=argument&type=num]*/
+/*element: subtractIntString:Specializer=[Subtract],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 subtractIntString(a, b) {
   return a - b;
@@ -250,37 +250,37 @@
 // Multiplication
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: multiply:Specializer=[Multiply],TypeConversion=[]*/
+/*element: multiply:Specializer=[Multiply],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 multiply(a, b) {
   return a * b;
 }
 
-/*element: multiplyNumInt:Specializer=[Multiply],TypeConversion=[]*/
+/*element: multiplyNumInt:Specializer=[Multiply],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 multiplyNumInt(a, b) {
   return a * b;
 }
 
-/*element: multiplyIntNum:Specializer=[Multiply],TypeConversion=[]*/
+/*element: multiplyIntNum:Specializer=[Multiply],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 multiplyIntNum(a, b) {
   return a * b;
 }
 
-/*element: multiplyNumNum:Specializer=[Multiply],TypeConversion=[]*/
+/*element: multiplyNumNum:Specializer=[Multiply],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 multiplyNumNum(a, b) {
   return a * b;
 }
 
-/*element: multiplyNullInt:Specializer=[Multiply],TypeConversion=[kind=receiver&type=num]*/
+/*element: multiplyNullInt:Specializer=[Multiply],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 multiplyNullInt(a, b) {
   return a * b;
 }
 
-/*element: multiplyIntNull:Specializer=[Multiply],TypeConversion=[kind=argument&type=num]*/
+/*element: multiplyIntNull:Specializer=[Multiply],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 multiplyIntNull(a, b) {
   return a * b;
@@ -292,7 +292,7 @@
   return a * b;
 }
 
-/*element: multiplyIntString:Specializer=[Multiply],TypeConversion=[kind=argument&type=num]*/
+/*element: multiplyIntString:Specializer=[Multiply],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 multiplyIntString(a, b) {
   return a * b;
@@ -302,55 +302,55 @@
 // Division
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: divide:Specializer=[Divide],TypeConversion=[]*/
+/*element: divide:Specializer=[Divide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 divide(a, b) {
   return a / b;
 }
 
-/*element: divideZero:Specializer=[Divide],TypeConversion=[]*/
+/*element: divideZero:Specializer=[Divide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 divideZero(a) {
   return a / 0;
 }
 
-/*element: divideNumInt:Specializer=[Divide],TypeConversion=[]*/
+/*element: divideNumInt:Specializer=[Divide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 divideNumInt(a, b) {
   return a / b;
 }
 
-/*element: divideIntNum:Specializer=[Divide],TypeConversion=[]*/
+/*element: divideIntNum:Specializer=[Divide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 divideIntNum(a, b) {
   return a / b;
 }
 
-/*element: divideNumNum:Specializer=[Divide],TypeConversion=[]*/
+/*element: divideNumNum:Specializer=[Divide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 divideNumNum(a, b) {
   return a / b;
 }
 
-/*element: divideNullInt:Specializer=[Divide],TypeConversion=[kind=receiver&type=num]*/
+/*element: divideNullInt:Specializer=[Divide],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 divideNullInt(a, b) {
   return a / b;
 }
 
-/*element: divideIntNull:Specializer=[Divide],TypeConversion=[kind=argument&type=num]*/
+/*element: divideIntNull:Specializer=[Divide],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 divideIntNull(a, b) {
   return a / b;
 }
 
-/*element: divideStringInt:Specializer=[Divide],TypeConversion=[kind=receiver&type=num]*/
+/*element: divideStringInt:Specializer=[Divide],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 divideStringInt(a, b) {
   return a / b;
 }
 
-/*element: divideIntString:Specializer=[Divide],TypeConversion=[kind=argument&type=num]*/
+/*element: divideIntString:Specializer=[Divide],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 divideIntString(a, b) {
   return a / b;
@@ -360,7 +360,7 @@
 // Truncating division
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: truncatingDivide:Specializer=[TruncatingDivide],TypeConversion=[]*/
+/*element: truncatingDivide:Specializer=[TruncatingDivide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 truncatingDivide(a, b) {
   return a ~/ 2;
@@ -372,13 +372,13 @@
   return a ~/ 0;
 }
 
-/*element: truncatingDivideIntNonZero1:Specializer=[TruncatingDivide],TypeConversion=[]*/
+/*element: truncatingDivideIntNonZero1:Specializer=[TruncatingDivide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 truncatingDivideIntNonZero1(a) {
   return a ~/ 1;
 }
 
-/*element: truncatingDivideIntNonZero2:Specializer=[TruncatingDivide],TypeConversion=[]*/
+/*element: truncatingDivideIntNonZero2:Specializer=[TruncatingDivide],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 truncatingDivideIntNonZero2(a) {
   return a ~/ 2;
@@ -390,7 +390,7 @@
   return a ~/ b;
 }
 
-/*element: truncatingDivideNumNonZero:Specializer=[TruncatingDivide._tdivFast],TypeConversion=[]*/
+/*element: truncatingDivideNumNonZero:Specializer=[TruncatingDivide._tdivFast],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 truncatingDivideNumNonZero(a) {
   return a ~/ 2;
@@ -408,25 +408,25 @@
   return a ~/ b;
 }
 
-/*element: truncatingDivideNullInt:Specializer=[!TruncatingDivide],TypeConversion=[kind=receiver&type=num]*/
+/*element: truncatingDivideNullInt:Specializer=[!TruncatingDivide],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 truncatingDivideNullInt(a, b) {
   return a ~/ b;
 }
 
-/*element: truncatingDivideIntNull:Specializer=[!TruncatingDivide],TypeConversion=[kind=argument&type=num]*/
+/*element: truncatingDivideIntNull:Specializer=[!TruncatingDivide],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 truncatingDivideIntNull(a, b) {
   return a ~/ b;
 }
 
-/*element: truncatingDivideStringInt:Specializer=[!TruncatingDivide],TypeConversion=[kind=receiver&type=num]*/
+/*element: truncatingDivideStringInt:Specializer=[!TruncatingDivide],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 truncatingDivideStringInt(a, b) {
   return a ~/ b;
 }
 
-/*element: truncatingDivideIntString:Specializer=[!TruncatingDivide],TypeConversion=[kind=argument&type=num]*/
+/*element: truncatingDivideIntString:Specializer=[!TruncatingDivide],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 truncatingDivideIntString(a, b) {
   return a ~/ b;
diff --git a/tests/compiler/dart2js/optimization/data/bit.dart b/tests/compiler/dart2js/optimization/data/bit.dart
index 51e3741..543a87d 100644
--- a/tests/compiler/dart2js/optimization/data/bit.dart
+++ b/tests/compiler/dart2js/optimization/data/bit.dart
@@ -92,49 +92,49 @@
 // Bitwise and
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: bitAnd:Specializer=[BitAnd],TypeConversion=[]*/
+/*element: bitAnd:Specializer=[BitAnd],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitAnd(a, b) {
   return a & b;
 }
 
-/*element: bitAndNumInt:Specializer=[BitAnd],TypeConversion=[]*/
+/*element: bitAndNumInt:Specializer=[BitAnd],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitAndNumInt(a, b) {
   return a & b;
 }
 
-/*element: bitAndIntNum:Specializer=[BitAnd],TypeConversion=[]*/
+/*element: bitAndIntNum:Specializer=[BitAnd],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitAndIntNum(a, b) {
   return a & b;
 }
 
-/*element: bitAndNumNum:Specializer=[BitAnd],TypeConversion=[]*/
+/*element: bitAndNumNum:Specializer=[BitAnd],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitAndNumNum(a, b) {
   return a & b;
 }
 
-/*element: bitAndNullInt:Specializer=[BitAnd],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitAndNullInt:Specializer=[BitAnd],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 bitAndNullInt(a, b) {
   return a & b;
 }
 
-/*element: bitAndIntNull:Specializer=[BitAnd],TypeConversion=[kind=argument&type=num]*/
+/*element: bitAndIntNull:Specializer=[BitAnd],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 bitAndIntNull(a, b) {
   return a & b;
 }
 
-/*element: bitAndStringInt:Specializer=[BitAnd],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitAndStringInt:Specializer=[BitAnd],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 bitAndStringInt(a, b) {
   return a & b;
 }
 
-/*element: bitAndIntString:Specializer=[BitAnd],TypeConversion=[kind=argument&type=num]*/
+/*element: bitAndIntString:Specializer=[BitAnd],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 bitAndIntString(a, b) {
   return a & b;
@@ -144,49 +144,49 @@
 // Bitwise or
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: bitOr:Specializer=[BitOr],TypeConversion=[]*/
+/*element: bitOr:Specializer=[BitOr],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitOr(a, b) {
   return a | b;
 }
 
-/*element: bitOrNumInt:Specializer=[BitOr],TypeConversion=[]*/
+/*element: bitOrNumInt:Specializer=[BitOr],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitOrNumInt(a, b) {
   return a | b;
 }
 
-/*element: bitOrIntNum:Specializer=[BitOr],TypeConversion=[]*/
+/*element: bitOrIntNum:Specializer=[BitOr],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitOrIntNum(a, b) {
   return a | b;
 }
 
-/*element: bitOrNumNum:Specializer=[BitOr],TypeConversion=[]*/
+/*element: bitOrNumNum:Specializer=[BitOr],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitOrNumNum(a, b) {
   return a | b;
 }
 
-/*element: bitOrNullInt:Specializer=[BitOr],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitOrNullInt:Specializer=[BitOr],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 bitOrNullInt(a, b) {
   return a | b;
 }
 
-/*element: bitOrIntNull:Specializer=[BitOr],TypeConversion=[kind=argument&type=num]*/
+/*element: bitOrIntNull:Specializer=[BitOr],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 bitOrIntNull(a, b) {
   return a | b;
 }
 
-/*element: bitOrStringInt:Specializer=[BitOr],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitOrStringInt:Specializer=[BitOr],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 bitOrStringInt(a, b) {
   return a | b;
 }
 
-/*element: bitOrIntString:Specializer=[BitOr],TypeConversion=[kind=argument&type=num]*/
+/*element: bitOrIntString:Specializer=[BitOr],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 bitOrIntString(a, b) {
   return a | b;
@@ -196,49 +196,49 @@
 // Bitwise xor
 ////////////////////////////////////////////////////////////////////////////////
 
-/*element: bitXor:Specializer=[BitXor],TypeConversion=[]*/
+/*element: bitXor:Specializer=[BitXor],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitXor(a, b) {
   return a ^ b;
 }
 
-/*element: bitXorNumInt:Specializer=[BitXor],TypeConversion=[]*/
+/*element: bitXorNumInt:Specializer=[BitXor],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitXorNumInt(a, b) {
   return a ^ b;
 }
 
-/*element: bitXorIntNum:Specializer=[BitXor],TypeConversion=[]*/
+/*element: bitXorIntNum:Specializer=[BitXor],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitXorIntNum(a, b) {
   return a ^ b;
 }
 
-/*element: bitXorNumNum:Specializer=[BitXor],TypeConversion=[]*/
+/*element: bitXorNumNum:Specializer=[BitXor],PrimitiveCheck=[]*/
 @pragma('dart2js:noInline')
 bitXorNumNum(a, b) {
   return a ^ b;
 }
 
-/*element: bitXorNullInt:Specializer=[BitXor],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitXorNullInt:Specializer=[BitXor],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 bitXorNullInt(a, b) {
   return a ^ b;
 }
 
-/*element: bitXorIntNull:Specializer=[BitXor],TypeConversion=[kind=argument&type=num]*/
+/*element: bitXorIntNull:Specializer=[BitXor],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 bitXorIntNull(a, b) {
   return a ^ b;
 }
 
-/*element: bitXorStringInt:Specializer=[BitXor],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitXorStringInt:Specializer=[BitXor],PrimitiveCheck=[kind=receiver&type=num]*/
 @pragma('dart2js:noInline')
 bitXorStringInt(a, b) {
   return a ^ b;
 }
 
-/*element: bitXorIntString:Specializer=[BitXor],TypeConversion=[kind=argument&type=num]*/
+/*element: bitXorIntString:Specializer=[BitXor],PrimitiveCheck=[kind=argument&type=num]*/
 @pragma('dart2js:noInline')
 bitXorIntString(a, b) {
   return a ^ b;
diff --git a/tests/compiler/dart2js/serialization/serialization_test_helper.dart b/tests/compiler/dart2js/serialization/serialization_test_helper.dart
index 43ee996..9f48d01 100644
--- a/tests/compiler/dart2js/serialization/serialization_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/serialization_test_helper.dart
@@ -60,7 +60,7 @@
 
   Map<OutputType, Map<String, String>> output = collector1.clear();
 
-  compiler.emitJavaScriptCode(newGlobalInferenceResults);
+  compiler.generateJavaScriptCode(newGlobalInferenceResults);
   Map<OutputType, Map<String, String>> newOutput = collector2.clear();
 
   Expect.setEquals(output.keys, newOutput.keys, "Output type mismatch.");
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
index f38c7a6..9e4273d 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
@@ -262,6 +262,7 @@
         }
         return null;
       }
+      return null;
     });
   }
 }
diff --git a/tests/compiler/dart2js_native/compute_this_script_test.dart b/tests/compiler/dart2js_native/compute_this_script_test.dart
index 8519bc4..ee5c855 100644
--- a/tests/compiler/dart2js_native/compute_this_script_test.dart
+++ b/tests/compiler/dart2js_native/compute_this_script_test.dart
@@ -10,7 +10,7 @@
   // This is somewhat brittle and relies on an implementation detail
   // of our test runner, but I can think of no other way to test this.
   // -- ahe
-  if (!thisScript.endsWith('/out.js')) {
+  if (!thisScript.endsWith('/compute_this_script_test.js')) {
     throw 'Unexpected script: "$thisScript"';
   }
 }
diff --git a/tests/compiler/dartdevc_native/const_test.dart b/tests/compiler/dartdevc_native/const_test.dart
new file mode 100644
index 0000000..b2dbf27
--- /dev/null
+++ b/tests/compiler/dartdevc_native/const_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2019, 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 'dart:_foreign_helper' show JS;
+import 'dart:_runtime' as dart;
+
+void main() {
+  var data = JS('', '[1, 2, 3, 4]');
+  Expect.isFalse(data is List<int>);
+
+  var list = dart.constList(data, dart.unwrapType(int));
+  Expect.isTrue(list is List<int>);
+  Expect.throws(() {
+    list[0] = 0;
+  });
+
+  var set = dart.constSet<int>(data);
+  Expect.isTrue(set is Set<int>);
+  Expect.isTrue(set.contains(3));
+  Expect.throws(() => set.clear());
+
+  var map = dart.constMap<int, int>(data);
+  Expect.isTrue(map is Map<int, int>);
+  Expect.equals(map[1], 2);
+  Expect.throws(() {
+    map[1] = 42;
+  });
+}
diff --git a/tests/compiler/dartdevc_native/libraries_part.dart b/tests/compiler/dartdevc_native/libraries_part.dart
new file mode 100644
index 0000000..d5ac766
--- /dev/null
+++ b/tests/compiler/dartdevc_native/libraries_part.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of 'libraries_test.dart';
diff --git a/tests/compiler/dartdevc_native/libraries_test.dart b/tests/compiler/dartdevc_native/libraries_test.dart
new file mode 100644
index 0000000..533eb5d
--- /dev/null
+++ b/tests/compiler/dartdevc_native/libraries_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, 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 'dart:_foreign_helper' show JS;
+import 'dart:_runtime' as dart;
+
+part 'libraries_part.dart';
+
+void main() {
+  // Test getLibraries()
+  var libraries = dart.getLibraries();
+  Expect.isTrue(libraries.contains('dart:core'));
+  Expect.isTrue(libraries.contains('package:expect/expect.dart'));
+
+  // Test getParts(...)
+  var expectParts = dart.getParts('package:expect/expect.dart');
+  Expect.isTrue(expectParts.isEmpty);
+
+  var testLibraries =
+      libraries.where((l) => l.endsWith('libraries_test.dart')).toList();
+  Expect.isTrue(testLibraries.length == 1);
+  var testParts = dart.getParts(testLibraries.first);
+  Expect.isTrue(testParts.length == 1);
+  Expect.isTrue(testParts.first.endsWith('libraries_part.dart'));
+
+  // Test getLibrary(...)
+  var core = dart.getLibrary('dart:core');
+  var stackTraceType = dart.wrapType(JS('', '#.StackTrace', core));
+  Expect.equals(StackTrace, stackTraceType);
+}
diff --git a/tests/corelib_2/bigint_test.dart b/tests/corelib_2/bigint_test.dart
index 01dea1f..0b5b8c5 100644
--- a/tests/corelib_2/bigint_test.dart
+++ b/tests/corelib_2/bigint_test.dart
@@ -222,6 +222,15 @@
   test(mediumNumber, new BigInt.from(137), new BigInt.from(77));
   test(new BigInt.from(137), mediumNumber, new BigInt.from(540686667207353));
   test(bigNumber, new BigInt.from(137), new BigInt.from(128));
+  var x = BigInt.parse(
+      "28ea16430c1f1072754aa5ebbfda0d790605a507c6c9758e88697b0b5dd9e74c",
+      radix: 16);
+  var m = BigInt.parse(
+      "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
+      radix: 16);
+  var r = BigInt.parse("95929095851002583825372225918533539673793386278"
+                       "360575987103577151530201707061", radix: 10);
+  test(x, m, r);
 }
 
 testGcd() {
diff --git a/tests/ffi/ffi.status b/tests/ffi/ffi.status
index 2b170cf..0e982e4 100644
--- a/tests/ffi/ffi.status
+++ b/tests/ffi/ffi.status
@@ -11,7 +11,6 @@
 # dartbug.com/35768: Structs not supported on 32-bit.
 [ $arch == ia32 || $arch == arm || $arch == simdbc ]
 function_structs_test: Skip
-function_callbacks_test: Skip
 structs_test: Skip
 
 # dartbug.com/35934
@@ -42,3 +41,6 @@
 
 [ $system != android && $arch == arm ]
 *: Skip # "hardfp" calling convention is not yet supported (iOS is also supported but not tested): dartbug.com/36309
+
+[ $arch == simdbc64 ]
+function_callbacks_test: Skip  # Issue 37140
diff --git a/tests/ffi/function_callbacks_test.dart b/tests/ffi/function_callbacks_test.dart
index 0ad50a9..fc2e46c 100644
--- a/tests/ffi/function_callbacks_test.dart
+++ b/tests/ffi/function_callbacks_test.dart
@@ -8,71 +8,192 @@
 
 library FfiTest;
 
-import 'dart:ffi' as ffi;
-
+import 'dart:io';
+import 'dart:ffi';
+import 'dart:isolate';
 import 'dylib_utils.dart';
 
 import "package:expect/expect.dart";
 
-import 'coordinate.dart';
+typedef NativeCallbackTest = Int32 Function(Pointer);
+typedef NativeCallbackTestFn = int Function(Pointer);
 
-typedef NativeCoordinateOp = Coordinate Function(Coordinate);
+final DynamicLibrary testLibrary = dlopenPlatformSpecific("ffi_test_functions");
 
-typedef CoordinateTrice = Coordinate Function(
-    ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>>, Coordinate);
+class Test {
+  final String name;
+  final Pointer callback;
+  final bool skip;
 
-void main() {
-  testFunctionWithFunctionPointer();
-  testNativeFunctionWithFunctionPointer();
+  Test(this.name, this.callback, {bool skipIf: false}) : skip = skipIf {}
+
+  void run() {
+    if (skip) return;
+
+    final NativeCallbackTestFn tester = testLibrary
+        .lookupFunction<NativeCallbackTest, NativeCallbackTestFn>("Test$name");
+    final int testCode = tester(callback);
+    if (testCode != 0) {
+      Expect.fail("Test $name failed.");
+    }
+  }
 }
 
-ffi.DynamicLibrary ffiTestFunctions =
-    dlopenPlatformSpecific("ffi_test_functions");
+typedef SimpleAdditionType = Int32 Function(Int32, Int32);
+int simpleAddition(int x, int y) => x + y;
 
-/// pass a pointer to a c function as an argument to a c function
-void testFunctionWithFunctionPointer() {
-  ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>>
-      transposeCoordinatePointer =
-      ffiTestFunctions.lookup("TransposeCoordinate");
+typedef IntComputationType = Int64 Function(Int8, Int16, Int32, Int64);
+int intComputation(int a, int b, int c, int d) => d - c + b - a;
 
-  ffi.Pointer<ffi.NativeFunction<CoordinateTrice>> p2 =
-      ffiTestFunctions.lookup("CoordinateUnOpTrice");
-  CoordinateTrice coordinateUnOpTrice = p2.asFunction();
+typedef UintComputationType = Uint64 Function(Uint8, Uint16, Uint32, Uint64);
+int uintComputation(int a, int b, int c, int d) => d - c + b - a;
 
-  Coordinate c1 = Coordinate(10.0, 20.0, null);
-  c1.next = c1;
+typedef SimpleMultiplyType = Double Function(Double);
+double simpleMultiply(double x) => x * 1.337;
 
-  Coordinate result = coordinateUnOpTrice(transposeCoordinatePointer, c1);
+typedef SimpleMultiplyFloatType = Float Function(Float);
+double simpleMultiplyFloat(double x) => x * 1.337;
 
-  print(result.runtimeType);
-  print(result.x);
-  print(result.y);
-
-  c1.free();
+typedef ManyIntsType = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr, IntPtr,
+    IntPtr, IntPtr, IntPtr, IntPtr, IntPtr);
+int manyInts(
+    int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
+  return a + b + c + d + e + f + g + h + i + j;
 }
 
-typedef BinaryOp = int Function(int, int);
-
-typedef NativeIntptrBinOp = ffi.IntPtr Function(ffi.IntPtr, ffi.IntPtr);
-
-typedef NativeIntptrBinOpLookup
-    = ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> Function();
-
-void testNativeFunctionWithFunctionPointer() {
-  ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOpLookup>> p1 =
-      ffiTestFunctions.lookup("IntptrAdditionClosure");
-  NativeIntptrBinOpLookup intptrAdditionClosure = p1.asFunction();
-
-  ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> intptrAdditionPointer =
-      intptrAdditionClosure();
-  BinaryOp intptrAddition = intptrAdditionPointer.asFunction();
-  Expect.equals(37, intptrAddition(10, 27));
+typedef ManyDoublesType = Double Function(Double, Double, Double, Double,
+    Double, Double, Double, Double, Double, Double);
+double manyDoubles(double a, double b, double c, double d, double e, double f,
+    double g, double h, double i, double j) {
+  return a + b + c + d + e + f + g + h + i + j;
 }
 
-int myPlus(int a, int b) => a + b;
+typedef ManyArgsType = Double Function(
+    IntPtr,
+    Float,
+    IntPtr,
+    Double,
+    IntPtr,
+    Float,
+    IntPtr,
+    Double,
+    IntPtr,
+    Float,
+    IntPtr,
+    Double,
+    IntPtr,
+    Float,
+    IntPtr,
+    Double,
+    IntPtr,
+    Float,
+    IntPtr,
+    Double);
+double manyArgs(
+    int _1,
+    double _2,
+    int _3,
+    double _4,
+    int _5,
+    double _6,
+    int _7,
+    double _8,
+    int _9,
+    double _10,
+    int _11,
+    double _12,
+    int _13,
+    double _14,
+    int _15,
+    double _16,
+    int _17,
+    double _18,
+    int _19,
+    double _20) {
+  return _1 +
+      _2 +
+      _3 +
+      _4 +
+      _5 +
+      _6 +
+      _7 +
+      _8 +
+      _9 +
+      _10 +
+      _11 +
+      _12 +
+      _13 +
+      _14 +
+      _15 +
+      _16 +
+      _17 +
+      _18 +
+      _19 +
+      _20;
+}
 
-typedef NativeApplyTo42And74Type = ffi.IntPtr Function(
-    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>>);
+typedef StoreType = Pointer<Int64> Function(Pointer<Int64>);
+Pointer<Int64> store(Pointer<Int64> ptr) => ptr.elementAt(1)..store(1337);
 
-typedef ApplyTo42And74Type = int Function(
-    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>>);
+typedef NullPointersType = Pointer<Int64> Function(Pointer<Int64>);
+Pointer<Int64> nullPointers(Pointer<Int64> ptr) => ptr?.elementAt(1);
+
+typedef ReturnNullType = Int32 Function();
+int returnNull() {
+  print('Expect "unhandled exception" error message to follow.');
+  return null;
+}
+
+typedef ReturnVoid = Void Function();
+void returnVoid() {}
+
+final List<Test> testcases = [
+  Test("SimpleAddition", fromFunction<SimpleAdditionType>(simpleAddition)),
+  Test("IntComputation", fromFunction<IntComputationType>(intComputation)),
+  Test("UintComputation", fromFunction<UintComputationType>(uintComputation)),
+  Test("SimpleMultiply", fromFunction<SimpleMultiplyType>(simpleMultiply)),
+  Test("SimpleMultiplyFloat",
+      fromFunction<SimpleMultiplyFloatType>(simpleMultiplyFloat)),
+  Test("ManyInts", fromFunction<ManyIntsType>(manyInts)),
+  Test("ManyDoubles", fromFunction<ManyDoublesType>(manyDoubles)),
+  Test("ManyArgs", fromFunction<ManyArgsType>(manyArgs)),
+  Test("Store", fromFunction<StoreType>(store)),
+  Test("NullPointers", fromFunction<NullPointersType>(nullPointers)),
+  Test("ReturnNull", fromFunction<ReturnNullType>(returnNull)),
+];
+
+testCallbackWrongThread() =>
+    Test("CallbackWrongThread", fromFunction<ReturnVoid>(returnVoid)).run();
+
+testCallbackOutsideIsolate() =>
+    Test("CallbackOutsideIsolate", fromFunction<ReturnVoid>(returnVoid)).run();
+
+isolateHelper(int callbackPointer) {
+  final Pointer<Void> ptr = fromAddress(callbackPointer);
+  final NativeCallbackTestFn tester =
+      testLibrary.lookupFunction<NativeCallbackTest, NativeCallbackTestFn>(
+          "TestCallbackWrongIsolate");
+  Expect.equals(0, tester(ptr));
+}
+
+testCallbackWrongIsolate() async {
+  final int callbackPointer = fromFunction<ReturnVoid>(returnVoid).address;
+  final ReceivePort exitPort = ReceivePort();
+  await Isolate.spawn(isolateHelper, callbackPointer,
+      errorsAreFatal: true, onExit: exitPort.sendPort);
+  await exitPort.first;
+}
+
+void main() async {
+  testcases.forEach((t) => t.run()); //# 00: ok
+
+  // These tests terminate the process after successful completion, so we have
+  // to run them separately.
+  //
+  // Since they use signal handlers they only run on Linux.
+  if (Platform.isLinux && !const bool.fromEnvironment("dart.vm.product")) {
+    testCallbackWrongThread(); //# 01: ok
+    testCallbackOutsideIsolate(); //# 02: ok
+    await testCallbackWrongIsolate(); //# 03: ok
+  }
+}
diff --git a/tests/ffi/regress_37100_test.dart b/tests/ffi/regress_37100_test.dart
new file mode 100644
index 0000000..7281042
--- /dev/null
+++ b/tests/ffi/regress_37100_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2019, 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.
+//
+// SharedObjects=ffi_test_functions
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+
+import 'dylib_utils.dart';
+
+class EVP_MD extends Pointer<Void> {}
+
+DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+
+final EVP_sha1 = ffiTestFunctions
+    .lookupFunction<EVP_MD Function(), EVP_MD Function()>('LargePointer');
+
+main() {
+  int result = EVP_sha1().address;
+  // On 32 bit only the lowest 32 bits are returned, so only test those.
+  result &= 0x00000000FFFFFFFF;
+  Expect.equals(0x0000000082000000, result);
+}
diff --git a/tests/language_2/async_identifier_test.dart b/tests/language_2/async_identifier_test.dart
new file mode 100644
index 0000000..5af2722
--- /dev/null
+++ b/tests/language_2/async_identifier_test.dart
@@ -0,0 +1,209 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async' as async;
+import 'async_lib.dart' as l; // Minimal library containing "int async;".
+
+// Adapted from Analyzer test testing where `async` was not previously allowed.
+
+// Helpers
+void ignore(argument) {}
+
+class GNamed {
+  void g({Object async = null}) {}
+}
+
+class AGet {
+  int get async => 1;
+  set async(int i) {}
+}
+
+class ACall {
+  int async() => 1;
+}
+
+main() {
+  // Each test declares a spearate async function, tests that `async`
+  // can occur in it, and makes sure the function is run.
+  {
+    const int async = 0;
+    f() async {
+      g(@async x) {}
+      g(0);
+    }
+
+    f();
+  }
+  {
+    f(c) async {
+      c.g(async: 0);
+    }
+
+    f(GNamed());
+  }
+  {
+    f() async {
+      var async = 1;
+      ignore(async);
+    }
+
+    f();
+  }
+  {
+    f() async* {
+      var async = 1;
+      ignore(async);
+    }
+
+    f().forEach(ignore);
+  }
+  {
+    f() async {
+      async:
+      while (true) {
+        break async;
+      }
+    }
+
+    f();
+  }
+  {
+    g() {}
+    f() async {
+      try {
+        g();
+      } catch (async) {}
+    }
+
+    f();
+  }
+  {
+    g() {}
+    f() async {
+      try {
+        g();
+      } catch (e, async) {}
+    }
+
+    f();
+  }
+  {
+    f() async {
+      async:
+      while (true) {
+        if (false) continue async;
+        break;
+      }
+    }
+
+    f();
+  }
+  {
+    var async;
+    f() async {
+      for (async in []) {}
+    }
+
+    f();
+  }
+  {
+    f() async {
+      g(int async) {}
+      g(0);
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return new AGet().async;
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return new ACall().async();
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return new ACall()..async();
+    }
+
+    f();
+  }
+  {
+    g() {}
+    f() async {
+      async:
+      g();
+    }
+
+    f();
+  }
+  {
+    f() async {
+      int async() => null;
+      async();
+    }
+  }
+  {
+    f() async {
+      return async.Future.value(0);
+    }
+
+    f();
+  }
+  {
+    f() async {
+      new AGet().async = 1;
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return new AGet()..async = 1;
+    }
+
+    f();
+  }
+  {
+    int async = 1;
+    f() async {
+      return "$async";
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return l.async;
+    }
+
+    f();
+  }
+  {
+    f() async {
+      switch (0) {
+        async:
+        case 0:
+          break;
+      }
+    }
+
+    f();
+  }
+  {
+    f() sync* {
+      var async = 1;
+      ignore(async);
+    }
+
+    f();
+  }
+}
diff --git a/tests/language_2/async_lib.dart b/tests/language_2/async_lib.dart
new file mode 100644
index 0000000..a6be037
--- /dev/null
+++ b/tests/language_2/async_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2019, 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.
+
+// Helper library for async_identifier_test.dart
+
+int async;
diff --git a/tests/language_2/covariant_subtyping_with_substitution_test.dart b/tests/language_2/covariant_subtyping_with_substitution_test.dart
deleted file mode 100644
index 7cf2b52..0000000
--- a/tests/language_2/covariant_subtyping_with_substitution_test.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-import 'package:expect/expect.dart';
-
-typedef F<T>(T x);
-
-class B<T> {
-  void f(F<T> x) {}
-}
-
-abstract class I<U> {
-  void f(U x);
-}
-
-class C<V> extends B<V> implements I<F<V>> {}
-
-void acceptsObject(Object o) {}
-
-void acceptsNum(num n) {}
-
-void g(I<F<num>> i) {
-  i.f(acceptsObject);
-  // i.f has static type (F<num>)->void, or ((num)->void)->void.  Which means we
-  // are statically allowed to pass acceptsNum to it.  However, if i's runtime
-  // type is C<Object>, then it extends B<Object>, so its f function requires
-  // its argument to be F<Object>.  This means that passing acceptsNum to f
-  // would violate soundness (since acceptsNum has type F<num>, and F<num> is a
-  // supertype of F<Object>).  So we expect a type error here.
-  Expect.throwsTypeError(() => i.f(acceptsNum));
-}
-
-void main() {
-  g(new C<Object>());
-}
diff --git a/tests/language_2/extension_methods/syntax/extension_methods.dart b/tests/language_2/extension_methods/syntax/extension_methods.dart
new file mode 100644
index 0000000..51013db
--- /dev/null
+++ b/tests/language_2/extension_methods/syntax/extension_methods.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=extension-methods
+
+import 'package:expect/expect.dart';
+
+class C {
+  int get one => 1;
+}
+
+extension E on C {
+  int get two => 2;
+}
+
+main() {
+  C c = C();
+  var result = c.one + c.two;
+  Expect.equals(result, 3);
+}
diff --git a/tests/language_2/known_identifier_usage_error_test.dart b/tests/language_2/known_identifier_usage_error_test.dart
index 9c96dc1..0d56f26 100644
--- a/tests/language_2/known_identifier_usage_error_test.dart
+++ b/tests/language_2/known_identifier_usage_error_test.dart
@@ -21,7 +21,7 @@
 import 'dart:async';
 
 Future<int> f1() async {
-  int async = 1; //# 01: syntax error
+  int async = 1;
   int await = 1; //# 02: syntax error
   int yield = 1; //# 03: syntax error
 
@@ -32,7 +32,7 @@
 }
 
 Stream<int> f2() async* {
-  int async = 1; //# 04: syntax error
+  int async = 1;
   int await = 1; //# 05: syntax error
   int yield = 1; //# 06: syntax error
 
@@ -43,7 +43,7 @@
 }
 
 Iterable<int> f3() sync* {
-  int async = 1; //# 07: syntax error
+  int async = 1;
   int await = 1; //# 08: syntax error
   int yield = 1; //# 09: syntax error
 
diff --git a/tests/language_2/local_var_in_annotation_test.dart b/tests/language_2/local_var_in_annotation_test.dart
new file mode 100644
index 0000000..f6474f8
--- /dev/null
+++ b/tests/language_2/local_var_in_annotation_test.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/37065
+
+const x = 0;
+main(@x args) {
+  const z = 0;
+  foo(@z args) {}
+  bar(@x args) {}
+}
diff --git a/tests/language_2/nnbd/resolution/null_assertion_null_type_test.dart b/tests/language_2/nnbd/resolution/null_assertion_null_type_test.dart
new file mode 100644
index 0000000..159731d
--- /dev/null
+++ b/tests/language_2/nnbd/resolution/null_assertion_null_type_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that the trailing "!" properly promotes the type `Null` to `Never`, by
+// verifying that it's statically ok to pass it to a function expecting a
+// non-null parameter.
+import 'package:expect/expect.dart';
+
+void f(int i) {}
+
+void g(Null n) {
+   // Statically ok because `Never <: int`.  Throws at runtime.
+  f(n!);
+}
+
+main() {
+  Expect.throws(() => g(null));
+}
diff --git a/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart b/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart
new file mode 100644
index 0000000..35e756e
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'dart:async';
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that Object.operator==(Object o) is the signature of ==, but that we can
+// still compare nullable values to Object.
+//
+// This is because a == b is essentially sugar for
+//
+// ```
+// identical(a, null) || identical (b, null)
+//   ? identical(a, b)
+//   : a.operator==(b);
+// ```
+//
+// It should not be required to handle `null` inside the implementation of
+// operator==, but it should not be an error to "assign null" to the parameter
+// of the comparison operator.
+main() {
+  Object o;
+  // Valid comparison.
+  o == null;
+
+  // Caveat: it is NOT that the argument is promoted to non-null. Otherwise,
+  // types which we can't cleanly promote, such as FutureOr<int?>, would not be
+  // assignable in comparisons.
+  FutureOr<int?> foInt;
+
+  // Valid comparison.
+  o == foInt;
+}
+
+class C {
+  // Valid override
+  @override
+  bool operator==(Object other) => identical(other, this);
+}
diff --git a/tests/language_2/nnbd/static_errors/implicit_downcasts.dart b/tests/language_2/nnbd/static_errors/implicit_downcasts.dart
new file mode 100644
index 0000000..6d8b7b4
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/implicit_downcasts.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that it is an error to do what was once allowed as an "implicit
+// downcast."
+main() {
+  num asNum = 1;
+  Object asObject = 1;
+  dynamic asDynamic = 1;
+  int asInt1 = asNum; //# 01: compile-time error
+  double asDouble1 = asNum; //# 02: compile-time error
+  int asInt2 = asObject; //# 03: compile-time error
+  double asDouble2 = asObject; //# 04: compile-time error
+  String asString1 = asObject; //# 05: compile-time error
+  int asInt3 = asDynamic; //# 06: ok
+}
diff --git a/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart b/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart
index a991f55..ce24941 100644
--- a/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart
+++ b/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart
@@ -9,7 +9,6 @@
   int? x;
   bool? cond;
   List? list;
-  dynamic dyn;
   Function? func;
   List<Function?> funcList;
   Stream? stream;
@@ -51,8 +50,8 @@
   cond != null; //# 33: ok
   x?.isEven; //# 34: ok
   x?.round(); //# 35: ok
-  for(i in list) {}; //# 36: compile-time error
-  await for(i in stream) {}; //# 37: compile-time error
+  for(var i in list) {}; //# 36: compile-time error
+  await for(var i in stream) {}; //# 37: compile-time error
   assert(cond); //# 38: compile-time error
 }
 
@@ -60,3 +59,148 @@
   Iterable? iter;
   yield* iter; //# 39: compile-time error
 }
+
+void typeParametersNullableBounds<IQ extends int?, BQ extends bool?, LQ extends List?, FQ extends Function?, SQ extends Stream?>(
+    IQ x,
+    BQ cond,
+    LQ list,
+    FQ func,
+    List<FQ> funcList,
+    SQ stream,
+    ) async {
+  x.isEven; //# 40: compile-time error
+  x.round(); //# 41: compile-time error
+  x.toString(); //# 42: ok
+  x.hashCode; //# 43: ok
+  x.runtimeType; //# 44: ok
+  x.noSuchMethod(null); //# 45: ok
+  x + 1; //# 46: compile-time error
+  -x; //# 47: compile-time error
+  x++; //# 48: compile-time error
+  ++x; //# 49: compile-time error
+  x..isEven; //# 50: compile-time error
+  list[0]; //# 51: compile-time error
+  list[0] = 0; //# 52: compile-time error
+  x += 1; //# 53: compile-time error
+  x ??= null; //# 54: ok
+  x.round; //# 55: compile-time error
+  x.toString; //# 56: ok
+  x.noSuchMethod; //# 57: ok
+  func(); //# 58: compile-time error
+  funcList[0](); //# 59: compile-time error
+  funcList.single(); //# 60: compile-time error
+  throw x; //# 61: compile-time error
+  cond || true; //# 62: compile-time error
+  true || cond; //# 63: compile-time error
+  cond && true; //# 64: compile-time error
+  true && cond; //# 65: compile-time error
+  !cond; //# 66: compile-time error
+  cond ? null : null; //# 67: compile-time error
+  if (cond) {} //# 68: compile-time error
+  while (cond) {} //# 69: compile-time error
+  for (;cond;){} //# 70: compile-time error
+  do {} while (cond); //# 71: compile-time error
+  cond!; //# 72: ok
+  cond ?? null; //# 73: ok
+  cond == null; //# 74: ok
+  cond != null; //# 75: ok
+  x?.isEven; //# 76: ok
+  x?.round(); //# 77: ok
+  for(var i in list) {}; //# 78: compile-time error
+  await for(var i in stream) {}; //# 79: compile-time error
+  assert(cond); //# 39: compile-time error
+}
+
+void typeParametersNullableUses<I extends int, B extends bool, L extends List, F extends Function, S extends Stream>(
+    I? x,
+    B? cond,
+    L? list,
+    F? func,
+    List<F?> funcList,
+    S? stream,
+    ) async {
+  x.isEven; //# 80: compile-time error
+  x.round(); //# 81: compile-time error
+  x.toString(); //# 82: ok
+  x.hashCode; //# 83: ok
+  x.runtimeType; //# 84: ok
+  x.noSuchMethod(null); //# 85: ok
+  x + 1; //# 86: compile-time error
+  -x; //# 87: compile-time error
+  x++; //# 88: compile-time error
+  ++x; //# 89: compile-time error
+  x..isEven; //# 90: compile-time error
+  list[0]; //# 91: compile-time error
+  list[0] = 0; //# 92: compile-time error
+  x += 1; //# 93: compile-time error
+  x ??= null; //# 94: ok
+  x.round; //# 95: compile-time error
+  x.toString; //# 96: ok
+  x.noSuchMethod; //# 97: ok
+  func(); //# 98: compile-time error
+  funcList[0](); //# 99: compile-time error
+  funcList.single(); //# 100: compile-time error
+  throw x; //# 101: compile-time error
+  cond || true; //# 102: compile-time error
+  true || cond; //# 103: compile-time error
+  cond && true; //# 104: compile-time error
+  true && cond; //# 105: compile-time error
+  !cond; //# 106: compile-time error
+  cond ? null : null; //# 107: compile-time error
+  if (cond) {} //# 108: compile-time error
+  while (cond) {} //# 109: compile-time error
+  for (;cond;) {} //# 110: compile-time error
+  do {} while (cond); //# 111: compile-time error
+  cond!; //# 112: ok
+  cond ?? null; //# 113: ok
+  cond == null; //# 114: ok
+  cond != null; //# 115: ok
+  x?.isEven; //# 116: ok
+  x?.round(); //# 117: ok
+  for(var i in list) {}; //# 118: compile-time error
+  await for(var i in stream) {}; //# 119: compile-time error
+}
+
+void dynamicUses() async {
+  dynamic dyn;
+  dyn.isEven; //# 120: ok
+  dyn.round(); //# 121: ok
+  dyn.toString(); //# 122: ok
+  dyn.hashCode; //# 123: ok
+  dyn.runtimeType; //# 124: ok
+  dyn.noSuchMethod(null); //# 125: ok
+  dyn + 1; //# 126: ok
+  -dyn; //# 127: ok
+  dyn++; //# 128: ok
+  ++dyn; //# 129: ok
+  dyn..isEven; //# 130: ok
+  dyn[0]; //# 131: ok
+  dyn[0] = 0; //# 132: ok
+  dyn += 1; //# 133: ok
+  dyn ??= null; //# 134: ok
+  dyn.round; //# 135: ok
+  dyn.toString; //# 136: ok
+  dyn.noSuchMethod; //# 137: ok
+  dyn(); //# 138: ok
+  dyn[0](); //# 139: ok
+  dyn.single(); //# 140: ok
+  throw dyn; //# 141: ok
+  dyn || true; //# 142: ok
+  true || dyn; //# 143: ok
+  dyn && true; //# 144: ok
+  true && dyn; //# 145: ok
+  !dyn; //# 146: ok
+  dyn ? null : null; //# 147: ok
+  if (dyn) {} //# 148: ok
+  while (dyn) {} //# 149: ok
+  for (;dyn;) {} //# 150: ok
+  do {} while (dyn); //# 151: ok
+  dyn!; //# 152: ok
+  dyn ?? null; //# 153: ok
+  dyn == null; //# 154: ok
+  dyn != null; //# 155: ok
+  dyn?.isEven; //# 156: ok
+  dyn?.round(); //# 157: ok
+  for(var i in dyn) {}; //# 158: ok
+  await for(var i in dyn) {}; //# 159: ok
+}
diff --git a/tests/language_2/sync_generator2_test.dart b/tests/language_2/sync_generator2_test.dart
index 9e33f0c..feaee63 100644
--- a/tests/language_2/sync_generator2_test.dart
+++ b/tests/language_2/sync_generator2_test.dart
@@ -15,13 +15,10 @@
 test01() sync* {
   var yield = 0; // //# 01: syntax error
   var await = 0; // //# 02: syntax error
-  var async = 0; // //# 03: syntax error
   bool yield() => false; //# 04: syntax error
   bool await() => false; //# 05: syntax error
-  bool async() => false; //# 06: syntax error
 
   var x1 = sync;
-  var x2 = async; // //# 07: syntax error
   var x3 = await; // //# 08: syntax error
   var x4 = await 55; // //# 09: compile-time error
   var x4 = yield; // //# 10: syntax error
diff --git a/tests/lib_2/html/async_spawnuri_test.dart b/tests/lib_2/html/async_spawnuri_test.dart
deleted file mode 100644
index 1175a3e..0000000
--- a/tests/lib_2/html/async_spawnuri_test.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-library async_spawnuri_test;
-
-import 'package:unittest/unittest.dart';
-import 'package:unittest/html_config.dart';
-
-import 'dart:async';
-import 'dart:isolate';
-import 'dart:html';
-
-// OtherScripts=async_oneshot.dart async_periodictimer.dart async_cancellingisolate.dart
-main() {
-  useHtmlConfiguration();
-
-  test('one shot timer in pure isolate', () {
-    var response = new ReceivePort();
-    var remote = Isolate.spawnUri(
-        Uri.parse('async_oneshot.dart'), ['START'], response.sendPort);
-    remote.catchError((x) => expect("Error in oneshot isolate", x));
-    expect(remote.then((_) => response.first), completion('DONE'));
-  });
-
-  test('periodic timer in pure isolate', () {
-    var response = new ReceivePort();
-    var remote = Isolate.spawnUri(
-        Uri.parse('async_periodictimer.dart'), ['START'], response.sendPort);
-    remote.catchError((x) => expect("Error in periodic timer isolate", x));
-    expect(remote.then((_) => response.first), completion('DONE'));
-  });
-
-  test('cancellation in pure isolate', () {
-    var response = new ReceivePort();
-    var remote = Isolate.spawnUri(Uri.parse('async_cancellingisolate.dart'),
-        ['START'], response.sendPort);
-    remote.catchError((x) => expect("Error in cancelling isolate", x));
-    expect(remote.then((_) => response.first), completion('DONE'));
-  });
-}
diff --git a/tests/lib_2/isolate/browser/issue_12474_test.dart b/tests/lib_2/isolate/browser/issue_12474_test.dart
index aca9741..b1cfe70 100644
--- a/tests/lib_2/isolate/browser/issue_12474_test.dart
+++ b/tests/lib_2/isolate/browser/issue_12474_test.dart
@@ -2,11 +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.
 
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=issue_12474_child.dart
-// OtherScripts=package/issue_12474_lib.dart
-
 import 'dart:isolate';
 
 final SPAWN_PACKAGE_ROOT = Uri.parse(".");
diff --git a/tests/lib_2/isolate/error_at_spawnuri_test.dart b/tests/lib_2/isolate/error_at_spawnuri_test.dart
index d33ac09..5c428b9 100644
--- a/tests/lib_2/isolate/error_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/error_at_spawnuri_test.dart
@@ -1,8 +1,6 @@
 // Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-//
-// OtherScripts=error_at_spawnuri_iso.dart
 
 library error_at_spawnuri;
 
diff --git a/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart b/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
index 9643770..6e9a5a8 100644
--- a/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
@@ -1,8 +1,6 @@
 // Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-//
-// OtherScripts=error_exit_at_spawning_shared.dart
 
 library error_exit_at_spawnuri;
 
diff --git a/tests/lib_2/isolate/exit_at_spawnuri_test.dart b/tests/lib_2/isolate/exit_at_spawnuri_test.dart
index fd2287b..f415c66 100644
--- a/tests/lib_2/isolate/exit_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/exit_at_spawnuri_test.dart
@@ -1,8 +1,6 @@
 // Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-//
-// OtherScripts=exit_at_spawnuri_iso.dart
 
 library exit_at_spawn;
 
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
index 9da9678..74b6cc6 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
@@ -2,13 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=issue_21398_child_isolate1.dart
-// OtherScripts=issue_21398_child_isolate11.dart
-
 import 'dart:isolate';
-import 'dart:async';
 import "package:expect/expect.dart";
 import 'package:async_helper/async_helper.dart';
 
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
index 27d49b9..0fe1043 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
@@ -2,12 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=deferred_loaded_lib.dart
-
 import 'dart:isolate';
-import 'dart:async';
 import "package:expect/expect.dart";
 import 'package:async_helper/async_helper.dart';
 
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
index 967d25f..ab413e9 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
@@ -2,12 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=issue_21398_child_isolate.dart
-
 import 'dart:isolate';
-import 'dart:async';
 import "package:expect/expect.dart";
 import 'package:async_helper/async_helper.dart';
 
diff --git a/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart b/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
index 6294767..2c1dc54 100644
--- a/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
+++ b/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
@@ -2,12 +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.
 
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=issue_24243_child1_isolate.dart
-// OtherScripts=issue_24243_child2_isolate.dart
-// OtherScripts=issue_24243_child3_isolate.dart
-
 import 'dart:collection';
 import 'dart:isolate';
 
diff --git a/tests/lib_2/isolate/spawn_uri_multi_test.dart b/tests/lib_2/isolate/spawn_uri_multi_test.dart
index 6076617..2984fca 100644
--- a/tests/lib_2/isolate/spawn_uri_multi_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_multi_test.dart
@@ -3,9 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Negative test to make sure that we are reaching all assertions.
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=spawn_uri_child_isolate.dart
 library spawn_tests;
 
 import 'dart:isolate';
diff --git a/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart b/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
index 6d37e26..f558df5 100644
--- a/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
@@ -3,9 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Example of nested spawning of isolates from a URI
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=spawn_uri_nested_child1_vm_isolate.dart spawn_uri_nested_child2_vm_isolate.dart
 library NestedSpawnUriLibrary;
 
 import 'dart:isolate';
diff --git a/tests/lib_2/isolate/spawn_uri_test.dart b/tests/lib_2/isolate/spawn_uri_test.dart
index 3f52215..e71fed7 100644
--- a/tests/lib_2/isolate/spawn_uri_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_test.dart
@@ -3,9 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Example of spawning an isolate from a URI
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=spawn_uri_child_isolate.dart
 library spawn_tests;
 
 import 'dart:isolate';
diff --git a/tests/lib_2/isolate/spawn_uri_vm_test.dart b/tests/lib_2/isolate/spawn_uri_vm_test.dart
index 6bc2e6e..a3b8f61 100644
--- a/tests/lib_2/isolate/spawn_uri_vm_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_vm_test.dart
@@ -3,9 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Example of spawning an isolate from a URI
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=spawn_uri_child_isolate.dart
 library spawn_tests;
 
 import 'dart:isolate';
diff --git a/tests/lib_2/lib_2_dart2js.status b/tests/lib_2/lib_2_dart2js.status
index 6cd2ce3..b96429f 100644
--- a/tests/lib_2/lib_2_dart2js.status
+++ b/tests/lib_2/lib_2_dart2js.status
@@ -10,7 +10,6 @@
 convert/chunked_conversion_utf88_test: Slow
 convert/utf85_test: Slow
 developer/timeline_test: Skip # Not supported
-html/async_spawnuri_test: SkipByDesign
 html/async_test: SkipByDesign
 html/custom/document_register_basic_test: Slow
 html/custom/document_register_type_extensions_test/construction: Slow
@@ -82,7 +81,6 @@
 
 [ $compiler == dart2js && $runtime == d8 ]
 async/dart2js_uncaught_error_test: RuntimeError
-html/async_spawnuri_test: RuntimeError
 html/async_test: RuntimeError
 html/audiobuffersourcenode_test: RuntimeError
 html/audiocontext_test: RuntimeError
@@ -494,7 +492,6 @@
 html/postmessage_structured_test: SkipByDesign
 
 [ $compiler == dart2js && !$csp && $minified ]
-html/async_spawnuri_test: RuntimeError
 html/async_test: RuntimeError
 html/audiobuffersourcenode_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
 html/audiocontext_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status
index 0532e64..4b47ff6 100644
--- a/tests/lib_2/lib_2_dartdevc.status
+++ b/tests/lib_2/lib_2_dartdevc.status
@@ -41,7 +41,6 @@
 convert/streamed_conversion_json_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
 html/callback_list_test: Skip # Test requires user interaction to accept permissions.
 html/custom/attribute_changed_callback_test: Skip # Issue 31577
diff --git a/tests/standalone_2/io/http_cookie_date_test.dart b/tests/standalone_2/io/http_cookie_date_test.dart
index 112d700..621d9e5 100644
--- a/tests/standalone_2/io/http_cookie_date_test.dart
+++ b/tests/standalone_2/io/http_cookie_date_test.dart
@@ -2,14 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library dart.http;
+library dart._http;
 
 import "dart:async";
 import "dart:collection";
 import "dart:convert";
-import "dart:developer";
 import "dart:io";
-import "dart:isolate";
 import "dart:math";
 import "dart:typed_data";
 import "package:expect/expect.dart";
diff --git a/tests/standalone_2/io/http_cookie_test.dart b/tests/standalone_2/io/http_cookie_test.dart
index 50cad66..bfe9302 100644
--- a/tests/standalone_2/io/http_cookie_test.dart
+++ b/tests/standalone_2/io/http_cookie_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.
 
-import "dart:async";
 import "dart:io";
+
 import "package:expect/expect.dart";
 
 void testCookies() {
@@ -59,12 +59,28 @@
 }
 
 void testValidateCookieWithDoubleQuotes() {
-  try {
-    Cookie cookie = Cookie('key', '"double-quoted-value"');
-  } catch (e) {
-    Expect.fail("Unexpected error $e.\n"
-        "Unable to parse cookie with value in double-quote characters.");
-  }
+  Expect.equals(Cookie('key', 'value').toString(), 'key=value; HttpOnly');
+  Expect.equals(Cookie('key', '').toString(), 'key=; HttpOnly');
+  Expect.equals(Cookie('key', '""').toString(), 'key=""; HttpOnly');
+  Expect.equals(Cookie('key', '"value"').toString(), 'key="value"; HttpOnly');
+  Expect.equals(Cookie.fromSetCookieValue('key=value; HttpOnly').toString(),
+      'key=value; HttpOnly');
+  Expect.equals(
+      Cookie.fromSetCookieValue('key=; HttpOnly').toString(), 'key=; HttpOnly');
+  Expect.equals(Cookie.fromSetCookieValue('key=""; HttpOnly').toString(),
+      'key=""; HttpOnly');
+  Expect.equals(Cookie.fromSetCookieValue('key="value"; HttpOnly').toString(),
+      'key="value"; HttpOnly');
+  Expect.throwsFormatException(() => Cookie('key', '"'));
+  Expect.throwsFormatException(() => Cookie('key', '"""'));
+  Expect.throwsFormatException(() => Cookie('key', '"x""'));
+  Expect.throwsFormatException(() => Cookie('key', '"x"y"'));
+  Expect.throwsFormatException(
+      () => Cookie.fromSetCookieValue('key="; HttpOnly'));
+  Expect.throwsFormatException(
+      () => Cookie.fromSetCookieValue('key="""; HttpOnly'));
+  Expect.throwsFormatException(
+      () => Cookie.fromSetCookieValue('key="x""; HttpOnly'));
 }
 
 void main() {
diff --git a/tests/standalone_2/io/raw_socket_test.dart b/tests/standalone_2/io/raw_socket_test.dart
index d46d1d6..cf8087d 100644
--- a/tests/standalone_2/io/raw_socket_test.dart
+++ b/tests/standalone_2/io/raw_socket_test.dart
@@ -79,13 +79,14 @@
   RawSocket.startConnect(InternetAddress.loopbackIPv4, 0)
       .then((ConnectionTask<RawSocket> task) {
     task.cancel();
-    task.socket.catchError((error) {
-      Expect.isTrue(error is SocketException);
-      asyncEnd();
-    });
     task.socket.then((s) {
       Expect.fail("Unreachable");
+    }, onError: (e) {
+      Expect.isTrue(e is SocketException);
+      asyncEnd();
     });
+  }, onError: (e) {
+    Expect.fail("Unreachable");
   });
 }
 
@@ -474,6 +475,21 @@
   });
 }
 
+void testClosedServer() {
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    int port = server.port;
+    server.close().then((_) {
+      RawSocket.connect(InternetAddress.loopbackIPv4, server.port).then((_) {
+        Expect.fail('Connecting to the closed server socket should fail');
+      }, onError: (e) {
+        Expect.isTrue(e is SocketException);
+        asyncEnd();
+      });
+    });
+  });
+}
+
 main() {
   asyncStart();
   testArguments();
@@ -491,5 +507,6 @@
   testSocketZone();
   testSocketZoneError();
   testClosedError();
+  testClosedServer();
   asyncEnd();
 }
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index 69cdf98..1441048 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -106,7 +106,6 @@
 io/http_client_connect_test: Skip # Flaky.
 io/http_close_test: Crash
 io/http_content_length_test: Skip # Flaky.
-io/http_cookie_test: Skip # Flaky
 io/http_proxy_advanced_test: Skip # Flaky
 io/http_proxy_test: Skip # Flaky.
 io/http_response_deadline_test: Skip # Flaky.
diff --git a/third_party/babel/update.sh b/third_party/babel/update.sh
new file mode 100755
index 0000000..6b9ca5a
--- /dev/null
+++ b/third_party/babel/update.sh
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+# Uploads a new version of d8 CIPD package
+set -e
+set -x
+
+if [ -z "$1" ]; then
+  echo "Usage: update.sh version"
+  exit 1
+fi
+
+version=$1
+
+tmpdir=$(mktemp -d)
+cleanup() {
+  rm -rf "$tmpdir"
+}
+trap cleanup EXIT HUP INT QUIT TERM PIPE
+cd "$tmpdir"
+
+for file in "babel.js" "babel.min.js" "LICENSE"
+do
+  curl -o $file "https://unpkg.com/@babel/standalone@$version/$file"
+done
+
+cipd create \
+  -name dart/third_party/babel \
+  -in . \
+  -install-mode copy \
+  -tag version:$version
diff --git a/tools/VERSION b/tools/VERSION
index fb1b7d6..c0e5702 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -34,6 +34,6 @@
 MINOR 3
 PATCH 2
 PRERELEASE 0
-PRERELEASE_PATCH 0
+PRERELEASE_PATCH 1
 ABI_VERSION 5
 OLDEST_SUPPORTED_ABI_VERSION 3
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index b9af47b..0f6de4e 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -43,6 +43,7 @@
       "tests/standalone/",
       "tests/standalone_2/",
       "tests/ffi/",
+      "third_party/babel/babel.min.js",
       "third_party/d8/",
       "third_party/observatory_pub_packages/packages/web_components/",
       "third_party/pkg/",
@@ -245,7 +246,12 @@
       "options": {
         "use-sdk": true
     }},
-    "dart2js-win-(ie11|edge)": {
+    "dart2js-win-ie11": {
+      "options": {
+        "use-sdk": true,
+        "babel": "{\"presets\":[\"es2015\"]}"
+    }},
+    "dart2js-win-edge": {
       "options": {
         "use-sdk": true
     }},
@@ -274,9 +280,9 @@
       "options": {
         "host-checked": true
     }},
-    "dartkp-android-(debug|product|release)-arm": {
+    "dartkp-android-(debug|product|release)-(arm|arm64)": {
       "options": {
-        "use-blobs": true
+        "use-elf": true
     }},
     "dartk-android-(debug|product|release)-(arm|arm64)": {},
     "dartkp-linux-(debug|product|release)-(simarm|simarm64)": {
@@ -868,7 +874,8 @@
             "-ndartdevc-checked-${system}-release-chrome",
             "language_2",
             "corelib_2",
-            "lib_2"
+            "lib_2",
+            "dartdevc_native"
           ]
         },
         {
@@ -877,7 +884,8 @@
             "-ndartdevk-checked-${system}-release-chrome",
             "language_2",
             "corelib_2",
-            "lib_2"
+            "lib_2",
+            "dartdevc_native"
           ]
         },
         {
@@ -919,6 +927,27 @@
             "pkg/dev_compiler/test/worker/worker_test.dart",
             "-rnone"
           ]
+        },
+        {
+          "name": "ddc self host test",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
+          "arguments": [
+            "--enable-asserts",
+            "pkg/dev_compiler/bin/dartdevc.dart",
+            "-o=out/ReleaseX64/dartdevc.js",
+            "pkg/dev_compiler/bin/dartdevc.dart"
+          ]
+        },
+        {
+          "name": "ddk self host test",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
+          "arguments": [
+            "--enable-asserts",
+            "pkg/dev_compiler/bin/dartdevc.dart",
+            "-k",
+            "-o=out/ReleaseX64/dartdevk.js",
+            "pkg/dev_compiler/bin/dartdevc.dart"
+          ]
         }
       ]
     },
@@ -941,7 +970,8 @@
             "-ndartdevc-checked-mac-release-chrome",
             "language_2",
             "corelib_2",
-            "lib_2"
+            "lib_2",
+            "dartdevc_native"
           ]
         },
         {
@@ -950,7 +980,8 @@
             "-ndartdevk-checked-mac-release-chrome",
             "language_2",
             "corelib_2",
-            "lib_2"
+            "lib_2",
+            "dartdevc_native"
           ]
         },
         {
@@ -992,6 +1023,27 @@
             "pkg/dev_compiler/test/worker/worker_test.dart",
             "-rnone"
           ]
+        },
+        {
+          "name": "ddc self host test",
+          "script": "xcodebuild/ReleaseX64/dart-sdk/bin/dart",
+          "arguments": [
+            "--enable-asserts",
+            "pkg/dev_compiler/bin/dartdevc.dart",
+            "-o=xcodebuild/ReleaseX64/dartdevc.js",
+            "pkg/dev_compiler/bin/dartdevc.dart"
+          ]
+        },
+        {
+          "name": "ddk self host test",
+          "script": "xcodebuild/ReleaseX64/dart-sdk/bin/dart",
+          "arguments": [
+            "--enable-asserts",
+            "pkg/dev_compiler/bin/dartdevc.dart",
+            "-k",
+            "-o=xcodebuild/ReleaseX64/dartdevk.js",
+            "pkg/dev_compiler/bin/dartdevc.dart"
+          ]
         }
       ]
     },
diff --git a/tools/linux_dist_support/debian/rules b/tools/linux_dist_support/debian/rules
index 8c0665b..2ec324f 100755
--- a/tools/linux_dist_support/debian/rules
+++ b/tools/linux_dist_support/debian/rules
@@ -1,6 +1,8 @@
 #!/usr/bin/make -f
 export DH_VERBOSE = 1
 
+AOT_SUPPORTED_ARCHS := amd64 arm
+
 # Use DEB_BUILD_OPTIONS's parallel=n option (see Policy 4.9.1)
 ifneq (,$(findstring parallel,$(DEB_BUILD_OPTIONS)))
 PARALLEL_JOBS := $(shell echo $(DEB_BUILD_OPTIONS) | \
@@ -11,17 +13,21 @@
 
 ifeq (amd64,$(DEB_HOST_ARCH_CPU))
 BUILD_TYPE += ReleaseX64
+BUILD_TYPE_PRODUCT += ProductX64
 ARCH += x64
 else
 ifeq (i386,$(DEB_HOST_ARCH_CPU))
 BUILD_TYPE += ReleaseIA32
+BUILD_TYPE_PRODUCT += ProductIA32
 ARCH += ia32
 else
 ifeq (arm,$(DEB_HOST_ARCH_CPU))
 ifeq ($(DEB_BUILD_ARCH_CPU),$(DEB_HOST_ARCH_CPU))
 BUILD_TYPE += ReleaseARM
+BUILD_TYPE_PRODUCT += ProductARM
 else
 BUILD_TYPE += ReleaseXARM
+BUILD_TYPE_PRODUCT += ProductXARM
 endif
 ARCH += arm
 else
@@ -30,6 +36,22 @@
 endif
 endif
 
+# Only run AOT builds for supported archs.
+ifneq (,$(findstring $(DEB_HOST_ARCH_CPU),$(AOT_SUPPORTED_ARCHS)))
+AOT_BUILD_CMD := \
+python tools/build.py -v -m release -a $(ARCH) $(TOOLCHAIN) \
+		copy_gen_kernel_snapshot copy_dart2aot; \
+python tools/build.py -v -m product -a $(ARCH) $(TOOLCHAIN) \
+		copy_gen_snapshot copy_dartaotruntime; \
+mkdir -p out/$(BUILD_TYPE)/dart-sdk/bin/utils; \
+cp out/$(BUILD_TYPE_PRODUCT)/dart-sdk/bin/utils/gen_snapshot \
+		out/$(BUILD_TYPE)/dart-sdk/bin/utils/gen_snapshot; \
+cp out/$(BUILD_TYPE_PRODUCT)/dart-sdk/bin/dartaotruntime \
+		out/$(BUILD_TYPE)/dart-sdk/bin/dartaotruntime
+else
+AOT_BUILD_CMD := # empty
+endif
+
 # Verbose?
 ifeq (1,$(DH_VERBOSE))
 BUILD_ARGS += V=1
@@ -52,6 +74,7 @@
 override_dh_auto_build:
 	cd dart; \
 	python tools/build.py -v -m release -a $(ARCH) $(TOOLCHAIN) create_sdk; \
+	$(AOT_BUILD_CMD); \
 	cd ..
 
 # Building the Dart SDK will already strip all binaries.
diff --git a/tools/make_version.py b/tools/make_version.py
index 4bb7f75..bf88617 100755
--- a/tools/make_version.py
+++ b/tools/make_version.py
@@ -69,7 +69,7 @@
 
 def MakeFile(quiet, output_file, input_file, no_git_hash, custom_for_pub, version_file=None):
   if version_file:
-    version_string = utils.GetVersion(version_file)
+    version_string = utils.GetVersion(no_git_hash, version_file)
   else:
     version_string = MakeVersionString(quiet, no_git_hash, custom_for_pub)
 
diff --git a/tools/patches/flutter-flutter/445a23a9bc14a57ea6275e5d4da179f7cb0bbdb6.patch b/tools/patches/flutter-flutter/445a23a9bc14a57ea6275e5d4da179f7cb0bbdb6.patch
new file mode 100644
index 0000000..ec58158
--- /dev/null
+++ b/tools/patches/flutter-flutter/445a23a9bc14a57ea6275e5d4da179f7cb0bbdb6.patch
@@ -0,0 +1,46 @@
+diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart
+index 7d450be42..e158e33af 100644
+--- a/packages/flutter_test/lib/src/binding.dart
++++ b/packages/flutter_test/lib/src/binding.dart
+@@ -1763,9 +1763,10 @@ class _MockHttpResponse extends Stream<List<int>> implements HttpClientResponse
+   @override
+   int get contentLength => -1;
+ 
+-  // @override
+-  // TODO(tvolkert): Uncomment @override annotation once SDK change lands.
+-  bool get autoUncompress => true;
++  @override
++  HttpClientResponseCompressionState get compressionState {
++    return HttpClientResponseCompressionState.decompressed;
++  }
+ 
+   @override
+   List<Cookie> get cookies => null;
+diff --git a/packages/flutter_tools/lib/src/base/io.dart b/packages/flutter_tools/lib/src/base/io.dart
+index 4c9d2250b..8b3535d54 100644
+--- a/packages/flutter_tools/lib/src/base/io.dart
++++ b/packages/flutter_tools/lib/src/base/io.dart
+@@ -47,6 +47,7 @@ export 'dart:io'
+         HttpClient,
+         HttpClientRequest,
+         HttpClientResponse,
++        HttpClientResponseCompressionState,
+         HttpHeaders,
+         HttpRequest,
+         HttpServer,
+diff --git a/packages/flutter_tools/test/commands/create_test.dart b/packages/flutter_tools/test/commands/create_test.dart
+index b5453cbb1..f7cdf6164 100644
+--- a/packages/flutter_tools/test/commands/create_test.dart
++++ b/packages/flutter_tools/test/commands/create_test.dart
+@@ -1172,6 +1172,11 @@ class MockHttpClientResponse extends Stream<List<int>> implements HttpClientResp
+   @override
+   String get reasonPhrase => '<reason phrase>';
+ 
++  @override
++  HttpClientResponseCompressionState get compressionState {
++    return HttpClientResponseCompressionState.decompressed;
++  }
++
+   @override
+   StreamSubscription<List<int>> listen(
+     void onData(List<int> event), {
diff --git a/tools/patches/flutter-flutter/apply.sh b/tools/patches/flutter-flutter/apply.sh
index 47043f0..2b3a280 100755
--- a/tools/patches/flutter-flutter/apply.sh
+++ b/tools/patches/flutter-flutter/apply.sh
@@ -23,3 +23,9 @@
 if [ -e "$patch" ]; then
   (cd flutter && git apply ../$patch)
 fi
+
+pinned_dart_sdk=$(get_pinned_dart_version)
+patch=src/third_party/dart/tools/patches/flutter-flutter/${pinned_dart_sdk}.patch
+if [ -e "$patch" ]; then
+  (cd flutter && git apply ../$patch)
+fi
diff --git a/tools/run_offsets_extractor.sh b/tools/run_offsets_extractor.sh
new file mode 100755
index 0000000..4e1a5ad
--- /dev/null
+++ b/tools/run_offsets_extractor.sh
@@ -0,0 +1,42 @@
+#!/usr/bin/env bash
+# Copyright (c) 2019, 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.
+
+set -e
+
+FILE="runtime/vm/compiler/runtime_offsets_extracted.h"
+
+# Make sure we're running in the SDK directory.
+if ! test -f "$FILE"; then
+  echo "Couldn't find $FILE"
+  echo "Make sure to run this script from the Dart SDK directory."
+  exit 1
+fi
+
+# We're regenerating the file, but we want to keep all the comments etc at the
+# top of the file. So just delete everything after the first "#if defined".
+LINE=$(grep "#if defined" "$FILE" -n | head -n 1 | sed "s/^\([0-9]*\):.*/\1/")
+TEMP="${FILE}.temp"
+head -n $(expr $LINE - 1) "$FILE" >"$TEMP"
+
+# Run offsets_extractor for every architecture and append the results.
+run() {
+  echo "" >>"$TEMP"
+  tools/gn.py --mode=release --arch=$1
+  tools/build.py --mode=release --arch=$1 offsets_extractor
+  out/$2/offsets_extractor >>"$TEMP"
+}
+run simarm ReleaseSIMARM
+run x64 ReleaseX64
+run ia32 ReleaseIA32
+run simarm64 ReleaseSIMARM64
+run simdbc64 ReleaseSIMDBC64
+run simdbc ReleaseSIMDBC
+
+# Cleanup.
+echo "" >>"$TEMP"
+echo "#endif  // RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_" >>"$TEMP"
+mv "$TEMP" "$FILE"
+git cl format "$FILE"
+echo -e "\n\nSuccessfully generated $FILE :)"
diff --git a/tools/test.dart b/tools/test.dart
index ae5213c..edb0f8c 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -3,7 +3,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Run tests like on the given builder.
+// Run tests like on the given builder and/or named configuration.
 
 import 'dart:async';
 import 'dart:collection';
@@ -55,7 +55,7 @@
       await Process.run(executable, arguments, runInShell: runInShell);
   if (processResult.exitCode != 0) {
     final command =
-        ([executable]..addAll(arguments)).map(simpleShellSingleQuote).join(" ");
+        [executable, ...arguments].map(simpleShellSingleQuote).join(" ");
     throw new Exception("Command exited ${processResult.exitCode}: $command\n"
         "${processResult.stdout}\n${processResult.stderr}");
   }
@@ -73,7 +73,7 @@
   final processResult = new ProcessResult(process.pid, exitCode, "", "");
   if (processResult.exitCode != 0) {
     final command =
-        ([executable]..addAll(arguments)).map(simpleShellSingleQuote).join(" ");
+        [executable, ...arguments].map(simpleShellSingleQuote).join(" ");
     throw new Exception("Command exited ${processResult.exitCode}: $command");
   }
   return processResult;
@@ -319,12 +319,18 @@
 void main(List<String> args) async {
   final parser = new ArgParser();
   parser.addOption("builder",
-      abbr: "b", help: "Run tests like on the given buider");
+      abbr: "b", help: "Run tests like on the given builder");
   parser.addOption("branch",
       abbr: "B",
       help: "Select the builders building this branch",
       defaultsTo: "master");
   parser.addOption("commit", abbr: "C", help: "Compare with this commit");
+  parser.addFlag("deflake",
+      help: "Re-run failing newly tests $deflakingCount times.");
+  parser.addFlag("report-flakes",
+      help: "Report test failures for tests known to be flaky.\n"
+          "This ignores all flakiness data from CI but flakes\n"
+          "detected by --deflake will remain hidden");
   parser.addFlag("list-configurations",
       help: "Output list of configurations.", negatable: false);
   parser.addOption("named-configuration",
@@ -354,8 +360,8 @@
 
 Run tests and compare with the results on the given builder. Either the -n or
 the -b option, or both, must be used. Any options following -- and non-option
-arguments will be forwarded to test.py invocations. The results for the specified
-named configuration will be downloaded from the specified builder. If only a
+arguments will be forwarded to test.py invocations. The specified named
+configuration's results will be downloaded from the specified builder. If only a
 named configuration is specified, the results are downloaded from the
 appropriate builders. If only a builder is specified, the default named
 configuration is used if the builder only has a single named configuration.
@@ -404,7 +410,7 @@
     exitCode = 1;
     return;
   }
-  if (2 <= namedConfigurations.length) {
+  if (namedConfigurations.length > 1) {
     final builder = builders.single;
     stderr.writeln(
         "error: The builder $builder is testing multiple named configurations");
@@ -418,7 +424,7 @@
   }
   final namedConfiguration = namedConfigurations.single;
   final localConfiguration =
-      options["local-configuration"] ?? namedConfiguration;
+      options["local-configuration"] as String ?? namedConfiguration;
   for (final builder in builders) {
     if (localConfiguration != namedConfiguration) {
       print("Testing the named configuration $localConfiguration "
@@ -452,28 +458,34 @@
             "as baseline instead of $commit for $builder");
         inexactBuilds[builder] = buildSearchResult.commit;
       }
-      final buildNumber = buildSearchResult.build;
+      final buildNumber = buildSearchResult.build.toString();
       print("Downloading results from builder $builder build $buildNumber...");
-      await cpGsutil(
-          buildFileCloudPath(builder, buildNumber.toString(), "results.json"),
+      await cpGsutil(buildFileCloudPath(builder, buildNumber, "results.json"),
           "${outDirectory.path}/previous.json");
-      await cpGsutil(
-          buildFileCloudPath(builder, buildNumber.toString(), "flaky.json"),
-          "${outDirectory.path}/flaky.json");
+      if (!options["report-flakes"]) {
+        await cpGsutil(buildFileCloudPath(builder, buildNumber, "flaky.json"),
+            "${outDirectory.path}/flaky.json");
+      }
       print("Downloaded baseline results from builder $builder");
       // Merge the results for the builders.
-      if (2 <= builders.length) {
+      if (builders.length > 1) {
         mergedResults
             .addAll(await loadResultsMap("${outDirectory.path}/previous.json"));
-        mergedFlaky
-            .addAll(await loadResultsMap("${outDirectory.path}/flaky.json"));
+        if (!options["report-flakes"]) {
+          mergedFlaky
+              .addAll(await loadResultsMap("${outDirectory.path}/flaky.json"));
+        }
       }
     }
 
     // Write out the merged results for the builders.
-    if (2 <= builders.length) {
+    if (builders.length > 1) {
       await new File("${outDirectory.path}/previous.json").writeAsString(
           mergedResults.values.map((data) => jsonEncode(data) + "\n").join(""));
+    }
+
+    // Ensure that there is a flaky.json even if it wasn't downloaded.
+    if (builders.length > 1 || options["report-flakes"]) {
       await new File("${outDirectory.path}/flaky.json").writeAsString(
           mergedFlaky.values.map((data) => jsonEncode(data) + "\n").join(""));
     }
@@ -502,62 +514,18 @@
       "--silent-failures",
       "--write-results",
       "--write-logs",
-    ]..addAll(options.rest);
+      ...options.rest,
+    ];
     print("".padLeft(80, "="));
     print("Running tests");
     print("".padLeft(80, "="));
-    await runProcessInheritStdio("python", ["tools/test.py"]..addAll(arguments),
+    await runProcessInheritStdio("python", ["tools/test.py", ...arguments],
         runInShell: Platform.isWindows);
 
-    // Find the list of tests to deflake.
-    final deflakeListOutput = await runProcess(Platform.resolvedExecutable, [
-      "tools/bots/compare_results.dart",
-      "--changed",
-      "--failing",
-      "--passing",
-      "--flakiness-data=${outDirectory.path}/flaky.json",
-      "${outDirectory.path}/previous.json",
-      "${outDirectory.path}/results.json",
-    ]);
-    final deflakeListPath = "${outDirectory.path}/deflake.list";
-    final deflakeListFile = new File(deflakeListPath);
-    await deflakeListFile.writeAsString(deflakeListOutput.stdout);
-
-    // Deflake the changed tests.
-    final deflakingResultsPaths = <String>[];
-    for (int i = 1;
-        deflakeListOutput.stdout != "" && i <= deflakingCount;
-        i++) {
-      print("".padLeft(80, "="));
-      print("Running deflaking iteration $i");
-      print("".padLeft(80, "="));
-      final deflakeDirectory = new Directory("${outDirectory.path}/$i");
-      await deflakeDirectory.create();
-      final deflakeArguments = <String>[
-        "--named-configuration=$localConfiguration",
-        "--output-directory=${deflakeDirectory.path}",
-        "--clean-exit",
-        "--silent-failures",
-        "--write-results",
-        "--test-list=$deflakeListPath",
-      ]..addAll(options.rest);
-      await runProcessInheritStdio(
-          "python", ["tools/test.py"]..addAll(deflakeArguments),
-          runInShell: Platform.isWindows);
-      deflakingResultsPaths.add("${deflakeDirectory.path}/results.json");
+    if (options["deflake"]) {
+      await deflake(outDirectory, localConfiguration, options.rest);
     }
 
-    // Update the flakiness information based on what we've learned.
-    print("Updating flakiness information...");
-    await runProcess(
-        Platform.resolvedExecutable,
-        [
-          "tools/bots/update_flakiness.dart",
-          "--input=${outDirectory.path}/flaky.json",
-          "--output=${outDirectory.path}/flaky.json",
-          "${outDirectory.path}/results.json",
-        ]..addAll(deflakingResultsPaths));
-
     // Write out the final comparison.
     print("".padLeft(80, "="));
     print("Test Results");
@@ -589,3 +557,53 @@
     await outDirectory.delete(recursive: true);
   }
 }
+
+void deflake(Directory outDirectory, String localConfiguration,
+    List<String> testPyArgs) async {
+  // Find the list of tests to deflake.
+  final deflakeListOutput = await runProcess(Platform.resolvedExecutable, [
+    "tools/bots/compare_results.dart",
+    "--changed",
+    "--failing",
+    "--passing",
+    "--flakiness-data=${outDirectory.path}/flaky.json",
+    "${outDirectory.path}/previous.json",
+    "${outDirectory.path}/results.json",
+  ]);
+  final deflakeListPath = "${outDirectory.path}/deflake.list";
+  final deflakeListFile = new File(deflakeListPath);
+  await deflakeListFile.writeAsString(deflakeListOutput.stdout);
+
+  // Deflake the changed tests.
+  final deflakingResultsPaths = <String>[];
+  for (int i = 1; deflakeListOutput.stdout != "" && i <= deflakingCount; i++) {
+    print("".padLeft(80, "="));
+    print("Running deflaking iteration $i");
+    print("".padLeft(80, "="));
+    final deflakeDirectory = new Directory("${outDirectory.path}/$i");
+    await deflakeDirectory.create();
+    final deflakeArguments = <String>[
+      "--named-configuration=$localConfiguration",
+      "--output-directory=${deflakeDirectory.path}",
+      "--clean-exit",
+      "--silent-failures",
+      "--write-results",
+      "--test-list=$deflakeListPath",
+      ...testPyArgs,
+    ];
+    await runProcessInheritStdio(
+        "python", ["tools/test.py", ...deflakeArguments],
+        runInShell: Platform.isWindows);
+    deflakingResultsPaths.add("${deflakeDirectory.path}/results.json");
+  }
+
+  // Update the flakiness information based on what we've learned.
+  print("Updating flakiness information...");
+  await runProcess(Platform.resolvedExecutable, [
+    "tools/bots/update_flakiness.dart",
+    "--input=${outDirectory.path}/flaky.json",
+    "--output=${outDirectory.path}/flaky.json",
+    "${outDirectory.path}/results.json",
+    ...deflakingResultsPaths,
+  ]);
+}
diff --git a/tools/testing/dart/babel_transform.js b/tools/testing/dart/babel_transform.js
new file mode 100644
index 0000000..5229e8a
--- /dev/null
+++ b/tools/testing/dart/babel_transform.js
@@ -0,0 +1,12 @@
+// Copyright (c) 2019, 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 babelStandalonePath = arguments[0];
+load(babelStandalonePath);
+const inputFilePath = arguments[2];
+const input = read(inputFilePath);
+const options = JSON.parse(arguments[1]);
+const output = Babel.transform(input, options).code;
+console.log(output);
diff --git a/tools/testing/dart/command.dart b/tools/testing/dart/command.dart
index d89b964..2eb7648 100644
--- a/tools/testing/dart/command.dart
+++ b/tools/testing/dart/command.dart
@@ -76,10 +76,15 @@
         checked: checked);
   }
 
-  static Command adbPrecompiled(String precompiledRunner, String processTest,
-      String testDirectory, List<String> arguments, bool useBlobs) {
-    return new AdbPrecompilationCommand._(
-        precompiledRunner, processTest, testDirectory, arguments, useBlobs);
+  static Command adbPrecompiled(
+      String precompiledRunner,
+      String processTest,
+      String testDirectory,
+      List<String> arguments,
+      bool useBlobs,
+      bool useElf) {
+    return new AdbPrecompilationCommand._(precompiledRunner, processTest,
+        testDirectory, arguments, useBlobs, useElf);
   }
 
   static Command adbDartk(String precompiledRunner, String processTest,
@@ -252,7 +257,8 @@
 }
 
 class CompilationCommand extends ProcessCommand {
-  final String _outputFile;
+  /// The primary output file that will be created by this command.
+  final String outputFile;
 
   /// If true, then the compilation is run even if the input files are older
   /// than the output file.
@@ -261,7 +267,7 @@
 
   CompilationCommand._(
       String displayName,
-      this._outputFile,
+      this.outputFile,
       this._alwaysCompile,
       this._bootstrapDependencies,
       String executable,
@@ -274,7 +280,7 @@
 
   CompilationCommand indexedCopy(int index) => CompilationCommand._(
       displayName,
-      _outputFile,
+      outputFile,
       _alwaysCompile,
       _bootstrapDependencies,
       executable,
@@ -286,7 +292,7 @@
   bool get outputIsUpToDate {
     if (_alwaysCompile) return false;
 
-    var file = new io.File(new Path("$_outputFile.deps").toNativePath());
+    var file = new io.File(new Path("$outputFile.deps").toNativePath());
     if (!file.existsSync()) return false;
 
     var lines = file.readAsLinesSync();
@@ -300,7 +306,7 @@
 
     dependencies.addAll(_bootstrapDependencies);
     var jsOutputLastModified = TestUtils.lastModifiedCache
-        .getLastModified(new Uri(scheme: 'file', path: _outputFile));
+        .getLastModified(new Uri(scheme: 'file', path: outputFile));
     if (jsOutputLastModified == null) return false;
 
     for (var dependency in dependencies) {
@@ -316,14 +322,14 @@
 
   void _buildHashCode(HashCodeBuilder builder) {
     super._buildHashCode(builder);
-    builder.addJson(_outputFile);
+    builder.addJson(outputFile);
     builder.addJson(_alwaysCompile);
     builder.addJson(_bootstrapDependencies);
   }
 
   bool _equal(CompilationCommand other) =>
       super._equal(other) &&
-      _outputFile == other._outputFile &&
+      outputFile == other.outputFile &&
       _alwaysCompile == other._alwaysCompile &&
       deepJsonCompare(_bootstrapDependencies, other._bootstrapDependencies);
 }
@@ -347,7 +353,7 @@
   @override
   FastaCompilationCommand indexedCopy(int index) => FastaCompilationCommand._(
       _compilerLocation,
-      _outputFile,
+      outputFile,
       _bootstrapDependencies,
       executable,
       arguments,
@@ -437,7 +443,7 @@
 
   VMKernelCompilationCommand indexedCopy(int index) =>
       VMKernelCompilationCommand._(
-          _outputFile,
+          outputFile,
           _alwaysCompile,
           _bootstrapDependencies,
           executable,
@@ -589,6 +595,7 @@
   final String precompiledTestDirectory;
   final List<String> arguments;
   final bool useBlobs;
+  final bool useElf;
 
   AdbPrecompilationCommand._(
       this.precompiledRunnerFilename,
@@ -596,6 +603,7 @@
       this.precompiledTestDirectory,
       this.arguments,
       this.useBlobs,
+      this.useElf,
       {int index = 0})
       : super._("adb_precompilation", index: index);
 
@@ -605,6 +613,7 @@
       precompiledTestDirectory,
       arguments,
       useBlobs,
+      useElf,
       index: index);
   _buildHashCode(HashCodeBuilder builder) {
     super._buildHashCode(builder);
@@ -612,12 +621,14 @@
     builder.add(precompiledTestDirectory);
     builder.add(arguments);
     builder.add(useBlobs);
+    builder.add(useElf);
   }
 
   bool _equal(AdbPrecompilationCommand other) =>
       super._equal(other) &&
       precompiledRunnerFilename == other.precompiledRunnerFilename &&
       useBlobs == other.useBlobs &&
+      useElf == other.useElf &&
       arguments == other.arguments &&
       precompiledTestDirectory == other.precompiledTestDirectory;
 
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 7c55c86..f3459d0 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -118,8 +118,6 @@
     }
   }
 
-  // TODO(ahe): It shouldn't be necessary to pass [buildDir] to any of these
-  // functions. It is fixed for a given configuration.
   String computeCompilerPath() {
     throw "Unknown compiler for: $runtimeType";
   }
@@ -130,15 +128,6 @@
 
   List<Uri> bootstrapDependencies() => const <Uri>[];
 
-  /// Creates a [Command] to compile [inputFile] to [outputFile].
-  Command createCommand(String inputFile, String outputFile,
-      List<String> sharedOptions, Map<String, String> environment) {
-    // TODO(rnystrom): See if this method can be unified with
-    // computeCompilationArtifact() and/or computeCompilerArguments() for the
-    // other compilers.
-    throw new UnsupportedError("$this does not support createCommand().");
-  }
-
   CommandArtifact computeCompilationArtifact(
 
       /// Each test has its own temporary directory to avoid name collisions.
@@ -188,6 +177,11 @@
       List<String> originalArguments,
       CommandArtifact artifact) {
     var args = <String>[];
+    if (_isDebug) {
+      // Temporarily disable background compilation to avoid flaky crashes
+      // (see http://dartbug.com/30016 for details).
+      args.add('--no-background-compilation');
+    }
     if (_useEnableAsserts) {
       args.add('--enable_asserts');
     }
@@ -481,10 +475,26 @@
       List<String> arguments, Map<String, String> environmentOverrides) {
     var compilerArguments = arguments.toList()
       ..addAll(_configuration.dart2jsOptions);
-    return new CommandArtifact([
-      computeCompilationCommand(
-          '$tempDir/out.js', compilerArguments, environmentOverrides)
-    ], '$tempDir/out.js', 'application/javascript');
+
+    var commands = <Command>[];
+    // TODO(athom): input filename extraction is copied from DDC. Maybe this
+    // should be passed to computeCompilationArtifact, instead?
+    var inputFile = arguments.last;
+    var inputFilename = (new Uri.file(inputFile)).pathSegments.last;
+    var out = "$tempDir/${inputFilename.replaceAll('.dart', '.js')}";
+    var babel = _configuration.babel;
+    var babelOut = out;
+    if (babel != null && babel.isNotEmpty) {
+      out = out.replaceAll('.js', '.raw.js');
+    }
+    commands.add(computeCompilationCommand(
+        out, compilerArguments, environmentOverrides));
+
+    if (babel != null && babel.isNotEmpty) {
+      commands.add(computeBabelCommand(out, babelOut, babel));
+    }
+
+    return new CommandArtifact(commands, babelOut, 'application/javascript');
   }
 
   List<String> computeRuntimeArguments(
@@ -502,6 +512,22 @@
     return runtimeConfiguration.dart2jsPreambles(preambleDir)
       ..add(artifact.filename);
   }
+
+  Command computeBabelCommand(String input, String output, String options) {
+    var uri = Repository.uri;
+    var babelTransform =
+        uri.resolve('tools/testing/dart/babel_transform.js').toFilePath();
+    var babelStandalone =
+        uri.resolve('third_party/babel/babel.min.js').toFilePath();
+    return Command.compilation(
+        'babel',
+        output,
+        [],
+        _configuration.runtimeConfiguration.d8FileName,
+        [babelTransform, "--", babelStandalone, options, input],
+        {},
+        alwaysCompile: true); // TODO(athom): ensure dependency tracking works.
+  }
 }
 
 /// Configuration for `dartdevc` and `dartdevk` (DDC with Kernel)
@@ -532,7 +558,7 @@
     return result;
   }
 
-  Command createCommand(String inputFile, String outputFile,
+  Command _createCommand(String inputFile, String outputFile,
       List<String> sharedOptions, Map<String, String> environment) {
     /// This can be disabled to test DDC's hybrid mode (automatically converting
     /// Analyzer summaries to Kernel files).
@@ -624,7 +650,7 @@
     var outputFile = "$tempDir/${inputFilename.replaceAll('.dart', '.js')}";
 
     return new CommandArtifact(
-        [createCommand(inputFile, outputFile, sharedOptions, environment)],
+        [_createCommand(inputFile, outputFile, sharedOptions, environment)],
         outputFile,
         "application/javascript");
   }
@@ -668,7 +694,7 @@
           tempDir, arguments, environmentOverrides));
     }
 
-    if (!_configuration.useBlobs) {
+    if (!_configuration.useBlobs && !_configuration.useElf) {
       commands.add(
           computeAssembleCommand(tempDir, arguments, environmentOverrides));
       if (!_configuration.keepGeneratedFiles) {
@@ -724,6 +750,9 @@
     if (_configuration.useBlobs) {
       args.add("--snapshot-kind=app-aot-blobs");
       args.add("--blobs_container_filename=$tempDir/out.aotsnapshot");
+    } else if (_configuration.useElf) {
+      args.add("--snapshot-kind=app-aot-elf");
+      args.add("--assembly=$tempDir/out.aotsnapshot");
     } else {
       args.add("--snapshot-kind=app-aot-assembly");
       args.add("--assembly=$tempDir/out.S");
@@ -1153,6 +1182,7 @@
       args.add('--gen-bytecode');
       args.add('--drop-ast');
       args.add('--emit-bytecode-source-positions');
+      args.add('--emit-bytecode-local-var-info');
     }
 
     return Command.vmKernelCompilation(dillFile, true, bootstrapDependencies(),
@@ -1199,12 +1229,6 @@
   List<Uri> bootstrapDependencies() => [_platformDill];
 
   @override
-  Command createCommand(String inputFile, String outputFile,
-      List<String> sharedOptions, Map<String, String> environment) {
-    throw new UnimplementedError();
-  }
-
-  @override
   CommandArtifact computeCompilationArtifact(String tempDir,
       List<String> arguments, Map<String, String> environmentOverrides) {
     var output =
diff --git a/tools/testing/dart/configuration.dart b/tools/testing/dart/configuration.dart
index fac39a9..da990fb9 100644
--- a/tools/testing/dart/configuration.dart
+++ b/tools/testing/dart/configuration.dart
@@ -115,6 +115,7 @@
   bool get useAnalyzerCfe => configuration.useAnalyzerCfe;
   bool get useAnalyzerFastaParser => configuration.useAnalyzerFastaParser;
   bool get useBlobs => configuration.useBlobs;
+  bool get useElf => configuration.useElf;
   bool get useSdk => configuration.useSdk;
   bool get useEnableAsserts => configuration.enableAsserts;
 
@@ -164,6 +165,7 @@
   final String outputDirectory;
   final String packageRoot;
   final String suiteDirectory;
+  String get babel => configuration.babel;
   String get builderTag => configuration.builderTag;
   final List<String> reproducingArguments;
 
@@ -210,24 +212,30 @@
   ///     build/none_vm_release_x64
   String get buildDirectory => system.outputDirectory + configurationDirectory;
 
+  int _timeout;
+
   // TODO(whesse): Put non-default timeouts explicitly in configs, not this.
   /// Calculates a default timeout based on the compiler and runtime used,
   /// and the mode, architecture, etc.
   int get timeout {
-    if (configuration.timeout == null) {
-      var isReload = hotReload || hotReloadRollback;
+    if (_timeout == null) {
+      if (configuration.timeout > 0) {
+        _timeout = configuration.timeout;
+      } else {
+        var isReload = hotReload || hotReloadRollback;
 
-      var compilerMulitiplier = compilerConfiguration.timeoutMultiplier;
-      var runtimeMultiplier = runtimeConfiguration.timeoutMultiplier(
-          mode: mode,
-          isChecked: isChecked,
-          isReload: isReload,
-          arch: architecture);
+        var compilerMulitiplier = compilerConfiguration.timeoutMultiplier;
+        var runtimeMultiplier = runtimeConfiguration.timeoutMultiplier(
+            mode: mode,
+            isChecked: isChecked,
+            isReload: isReload,
+            arch: architecture);
 
-      configuration.timeout = 60 * compilerMulitiplier * runtimeMultiplier;
+        _timeout = 60 * compilerMulitiplier * runtimeMultiplier;
+      }
     }
 
-    return configuration.timeout;
+    return _timeout;
   }
 
   List<String> get standardOptions {
diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart
index bf979ac..9519f1c 100644
--- a/tools/testing/dart/options.dart
+++ b/tools/testing/dart/options.dart
@@ -181,6 +181,9 @@
     new _Option.bool(
         'use_blobs', 'Use mmap instead of shared libraries for precompilation.',
         hide: true),
+    new _Option.bool(
+        'use_elf', 'Directly generate an ELF 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'),
@@ -222,7 +225,7 @@
     new _Option.bool(
         'silent_failures',
         "Don't complain about failing tests. This is useful when in "
-        "combination with --write-results.",
+            "combination with --write-results.",
         hide: true),
     new _Option.bool('report_in_json',
         'When listing with --list, output result summary in JSON.',
@@ -250,12 +253,12 @@
     new _Option.bool(
         'write_results',
         'Write results to a "${TestUtils.resultsFileName}" json file '
-        'located at the debug_output_directory.',
+            'located at the debug_output_directory.',
         hide: true),
     new _Option.bool(
         'write_logs',
         'Include the stdout and stderr of tests that don\'t match expectations '
-        'in the "${TestUtils.logsFileName}" file',
+            'in the "${TestUtils.logsFileName}" file',
         hide: true),
     new _Option.bool(
         'reset_browser_configuration',
@@ -300,6 +303,11 @@
         hide: true),
     new _Option('shared_options', 'Extra shared options.', hide: true),
     new _Option(
+        'babel',
+        '''Transforms dart2js output with Babel. The value must be
+Babel options JSON.''',
+        hide: true),
+    new _Option(
         'suite_dir', 'Additional directory to add to the testing matrix.',
         hide: true),
     new _Option('package_root', 'The package root to use for testing.',
@@ -688,6 +696,7 @@
                     useAnalyzerFastaParser:
                         data["analyzer_use_fasta_parser"] as bool,
                     useBlobs: data["use_blobs"] as bool,
+                    useElf: data["use_elf"] as bool,
                     useSdk: data["use_sdk"] as bool,
                     useHotReload: data["hot_reload"] as bool,
                     useHotReloadRollback: data["hot_reload_rollback"] as bool,
@@ -696,6 +705,7 @@
                     isMinified: data["minified"] as bool,
                     vmOptions: vmOptions,
                     dart2jsOptions: dart2jsOptions,
+                    babel: data['babel'] as String,
                     builderTag: data["builder_tag"] as String,
                     previewDart2: true);
             var configuration = new TestConfiguration(
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index c523839..38c10b1 100644
--- a/tools/testing/dart/runtime_configuration.dart
+++ b/tools/testing/dart/runtime_configuration.dart
@@ -8,9 +8,7 @@
 import 'compiler_configuration.dart';
 import 'configuration.dart';
 import 'repository.dart';
-// TODO(ahe): Remove this import, we can precompute all the values required
-// from TestSuite once the refactoring is complete.
-import 'test_suite.dart';
+import 'utils.dart';
 
 /// Describes the commands to run a given test case or its compiled output.
 ///
@@ -50,10 +48,14 @@
       case Runtime.dartPrecompiled:
         if (configuration.system == System.android) {
           return new DartPrecompiledAdbRuntimeConfiguration(
-              useBlobs: configuration.useBlobs);
+            useBlobs: configuration.useBlobs,
+            useElf: configuration.useElf,
+          );
         } else {
           return new DartPrecompiledRuntimeConfiguration(
-              useBlobs: configuration.useBlobs);
+            useBlobs: configuration.useBlobs,
+            useElf: configuration.useElf,
+          );
         }
         break;
 
@@ -78,7 +80,6 @@
   }
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -88,9 +89,74 @@
     throw "Unimplemented runtime '$runtimeType'";
   }
 
+  /**
+   * The output directory for this suite's configuration.
+   */
+  String get buildDir => _configuration.buildDirectory;
+
   List<String> dart2jsPreambles(Uri preambleDir) => [];
 
   bool get shouldSkipNegativeTests => false;
+
+  /// Returns the path to the Dart VM executable.
+  String get dartVmBinaryFileName {
+    // Controlled by user with the option "--dart".
+    var dartExecutable = _configuration.dartPath;
+
+    if (dartExecutable == null) {
+      dartExecutable = dartVmExecutableFileName;
+    }
+
+    TestUtils.ensureExists(dartExecutable, _configuration);
+    return dartExecutable;
+  }
+
+  String get dartVmExecutableFileName {
+    return _configuration.useSdk
+        ? '$buildDir/dart-sdk/bin/dart$executableBinarySuffix'
+        : '$buildDir/dart$executableBinarySuffix';
+  }
+
+  String get dartPrecompiledBinaryFileName {
+    // Controlled by user with the option "--dart_precompiled".
+    var dartExecutable = _configuration.dartPrecompiledPath;
+
+    if (dartExecutable == null || dartExecutable == '') {
+      var suffix = executableBinarySuffix;
+      dartExecutable = '$buildDir/dart_precompiled_runtime$suffix';
+    }
+
+    TestUtils.ensureExists(dartExecutable, _configuration);
+    return dartExecutable;
+  }
+
+  String get processTestBinaryFileName {
+    var suffix = executableBinarySuffix;
+    var processTestExecutable = '$buildDir/process_test$suffix';
+    TestUtils.ensureExists(processTestExecutable, _configuration);
+    return processTestExecutable;
+  }
+
+  String get d8FileName {
+    var suffix = executableBinarySuffix;
+    var d8Dir = Repository.dir.append('third_party/d8');
+    var d8Path = d8Dir.append('${Platform.operatingSystem}/d8$suffix');
+    var d8 = d8Path.toNativePath();
+    TestUtils.ensureExists(d8, _configuration);
+    return d8;
+  }
+
+  String get jsShellFileName {
+    var executableSuffix = executableBinarySuffix;
+    var executable = 'jsshell$executableSuffix';
+    var jsshellDir = Repository.uri.resolve("tools/testing/bin").path;
+    var jsshell = '$jsshellDir/$executable';
+    TestUtils.ensureExists(jsshell, _configuration);
+    return jsshell;
+  }
+
+  String get executableBinarySuffix => Platform.isWindows ? '.exe' : '';
+  String get executableScriptSuffix => Platform.isWindows ? '.bat' : '';
 }
 
 /// The 'none' runtime configuration.
@@ -98,7 +164,6 @@
   NoneRuntimeConfiguration() : super._subclass();
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -126,7 +191,6 @@
   D8RuntimeConfiguration() : super('d8');
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -136,7 +200,7 @@
     checkArtifact(artifact);
     return [
       Command.jsCommandLine(
-          moniker, suite.d8FileName, arguments, environmentOverrides)
+          moniker, d8FileName, arguments, environmentOverrides)
     ];
   }
 
@@ -150,7 +214,6 @@
   JsshellRuntimeConfiguration() : super('jsshell');
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -159,7 +222,7 @@
     checkArtifact(artifact);
     return [
       Command.jsCommandLine(
-          moniker, suite.jsShellFileName, arguments, environmentOverrides)
+          moniker, jsShellFileName, arguments, environmentOverrides)
     ];
   }
 
@@ -210,7 +273,6 @@
 //// The standalone Dart VM binary, "dart" or "dart.exe".
 class StandaloneDartRuntimeConfiguration extends DartVmRuntimeConfiguration {
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -228,9 +290,9 @@
     if (isCrashExpected) {
       arguments.insert(0, '--suppress-core-dump');
     }
-    String executable = suite.dartVmBinaryFileName;
+    String executable = dartVmBinaryFileName;
     if (type == 'application/kernel-ir-fully-linked') {
-      executable = suite.dartVmExecutableFileName;
+      executable = dartVmExecutableFileName;
     }
     return [Command.vm(executable, arguments, environmentOverrides)];
   }
@@ -238,10 +300,12 @@
 
 class DartPrecompiledRuntimeConfiguration extends DartVmRuntimeConfiguration {
   final bool useBlobs;
-  DartPrecompiledRuntimeConfiguration({bool useBlobs}) : useBlobs = useBlobs;
+  final bool useElf;
+  DartPrecompiledRuntimeConfiguration({bool useBlobs, bool useElf})
+      : useBlobs = useBlobs,
+        useElf = useElf;
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -254,8 +318,7 @@
     }
 
     return [
-      Command.vm(
-          suite.dartPrecompiledBinaryFileName, arguments, environmentOverrides)
+      Command.vm(dartPrecompiledBinaryFileName, arguments, environmentOverrides)
     ];
   }
 }
@@ -265,7 +328,6 @@
   static const String DeviceTestDir = '/data/local/tmp/testing/test';
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -277,8 +339,8 @@
       throw "dart cannot run files of type '$type'.";
     }
 
-    final String buildPath = suite.buildDir;
-    final String processTest = suite.processTestBinaryFileName;
+    final String buildPath = buildDir;
+    final String processTest = processTestBinaryFileName;
     return [
       Command.adbDartk(buildPath, processTest, script, arguments, extraLibs)
     ];
@@ -292,10 +354,12 @@
       '/data/local/tmp/precompilation-testing/test';
 
   final bool useBlobs;
-  DartPrecompiledAdbRuntimeConfiguration({bool useBlobs}) : useBlobs = useBlobs;
+  final bool useElf;
+  DartPrecompiledAdbRuntimeConfiguration({bool useBlobs, bool useElf})
+      : useBlobs = useBlobs,
+        useElf = useElf;
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
@@ -307,11 +371,11 @@
       throw "dart_precompiled cannot run files of type '$type'.";
     }
 
-    String precompiledRunner = suite.dartPrecompiledBinaryFileName;
-    String processTest = suite.processTestBinaryFileName;
+    String precompiledRunner = dartPrecompiledBinaryFileName;
+    String processTest = processTestBinaryFileName;
     return [
       Command.adbPrecompiled(
-          precompiledRunner, processTest, script, arguments, useBlobs)
+          precompiledRunner, processTest, script, arguments, useBlobs, useElf)
     ];
   }
 }
@@ -333,17 +397,16 @@
   }
 
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
       List<String> extraLibs,
       bool isCrashExpected) {
-    String executable = suite.dartVmBinaryFileName;
+    String executable = dartVmBinaryFileName;
     return selfCheckers
         .map((String tester) => Command.vmBatch(
             executable, tester, arguments, environmentOverrides,
-            checked: suite.configuration.isChecked))
+            checked: _configuration.isChecked))
         .toList();
   }
 
@@ -356,7 +419,6 @@
 // TODO(ahe): Remove this class.
 class DummyRuntimeConfiguration extends DartVmRuntimeConfiguration {
   List<Command> computeRuntimeCommands(
-      TestSuite suite,
       CommandArtifact artifact,
       List<String> arguments,
       Map<String, String> environmentOverrides,
diff --git a/tools/testing/dart/test_configurations.dart b/tools/testing/dart/test_configurations.dart
index 32b9559..68f97a4 100644
--- a/tools/testing/dart/test_configurations.dart
+++ b/tools/testing/dart/test_configurations.dart
@@ -35,6 +35,7 @@
   new Path('tests/compiler/dart2js'),
   new Path('tests/compiler/dart2js_extra'),
   new Path('tests/compiler/dart2js_native'),
+  new Path('tests/compiler/dartdevc_native'),
   new Path('tests/corelib_2'),
   new Path('tests/kernel'),
   new Path('tests/language_2'),
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index ed69296..1d13426 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -244,7 +244,7 @@
  * it is longer than MAX_HEAD characters, and just keeps the head and
  * the last TAIL_LENGTH characters of the output.
  */
-class OutputLog {
+class OutputLog implements StreamConsumer<List<int>> {
   static const int MAX_HEAD = 500 * 1024;
   static const int TAIL_LENGTH = 10 * 1024;
   List<int> head = <int>[];
@@ -252,6 +252,7 @@
   List<int> complete;
   bool dataDropped = false;
   bool hasNonUtf8 = false;
+  StreamSubscription _subscription;
 
   OutputLog();
 
@@ -325,6 +326,53 @@
     }
     return complete;
   }
+
+  @override
+  Future addStream(Stream<List<int>> stream) {
+    _subscription = stream.listen(this.add);
+    return _subscription.asFuture();
+  }
+
+  @override
+  Future close() {
+    toList();
+    return _subscription?.cancel();
+  }
+
+  Future cancel() {
+    return _subscription?.cancel();
+  }
+}
+
+// An [OutputLog] that tees the output to a file as well.
+class FileOutputLog extends OutputLog {
+  io.File _outputFile;
+  io.IOSink _sink;
+
+  FileOutputLog(this._outputFile);
+
+  @override
+  void add(List<int> data) {
+    super.add(data);
+    _sink ??= _outputFile.openWrite();
+    _sink.add(data);
+  }
+
+  @override
+  Future close() {
+    return Future.wait([
+      super.close(),
+      if (_sink != null) _sink.flush().whenComplete(_sink.close)
+    ]);
+  }
+
+  @override
+  Future cancel() {
+    return Future.wait([
+      super.cancel(),
+      if (_sink != null) _sink.flush().whenComplete(_sink.close)
+    ]);
+  }
 }
 
 // Helper to get a list of all child pids for a parent process.
@@ -381,16 +429,19 @@
   int timeout;
   bool timedOut = false;
   DateTime startTime;
-  Timer timeoutTimer;
   int pid;
-  OutputLog stdout = new OutputLog();
-  OutputLog stderr = new OutputLog();
+  OutputLog stdout;
+  OutputLog stderr = OutputLog();
+  StreamConsumer stdoutConsumer;
   List<String> diagnostics = <String>[];
   bool compilationSkipped = false;
   Completer<CommandOutput> completer;
   TestConfiguration configuration;
 
-  RunningProcess(this.command, this.timeout, {this.configuration});
+  RunningProcess(this.command, this.timeout,
+      {this.configuration, io.File outputFile}) {
+    stdout = outputFile != null ? FileOutputLog(outputFile) : OutputLog();
+  }
 
   Future<CommandOutput> run() {
     completer = new Completer<CommandOutput>();
@@ -410,44 +461,10 @@
           environment: processEnvironment,
           workingDirectory: command.workingDirectory);
       processFuture.then((io.Process process) {
-        StreamSubscription stdoutSubscription =
-            _drainStream(process.stdout, stdout);
-        StreamSubscription stderrSubscription =
-            _drainStream(process.stderr, stderr);
-
-        var stdoutCompleter = new Completer<Null>();
-        var stderrCompleter = new Completer<Null>();
-
-        bool stdoutDone = false;
-        bool stderrDone = false;
+        var stdoutFuture = process.stdout.pipe(stdout);
+        var stderrFuture = process.stderr.pipe(stderr);
         pid = process.pid;
 
-        // This timer is used to close stdio to the subprocess once we got
-        // the exitCode. Sometimes descendants of the subprocess keep stdio
-        // handles alive even though the direct subprocess is dead.
-        Timer watchdogTimer;
-
-        closeStdout([_]) {
-          if (!stdoutDone) {
-            stdoutCompleter.complete();
-            stdoutDone = true;
-            if (stderrDone && watchdogTimer != null) {
-              watchdogTimer.cancel();
-            }
-          }
-        }
-
-        closeStderr([_]) {
-          if (!stderrDone) {
-            stderrCompleter.complete();
-            stderrDone = true;
-
-            if (stdoutDone && watchdogTimer != null) {
-              watchdogTimer.cancel();
-            }
-          }
-        }
-
         // Close stdin so that tests that try to block on input will fail.
         process.stdin.close();
         timeoutHandler() async {
@@ -507,30 +524,31 @@
           }
         }
 
-        stdoutSubscription.asFuture().then(closeStdout);
-        stderrSubscription.asFuture().then(closeStderr);
-
-        process.exitCode.then((exitCode) {
-          if (!stdoutDone || !stderrDone) {
-            watchdogTimer = new Timer(MAX_STDIO_DELAY, () {
-              DebugLogger.warning(
-                  "$MAX_STDIO_DELAY_PASSED_MESSAGE (command: $command)");
-              watchdogTimer = null;
-              stdoutSubscription.cancel();
-              stderrSubscription.cancel();
-              closeStdout();
-              closeStderr();
-            });
-          }
-
-          Future.wait([stdoutCompleter.future, stderrCompleter.future])
-              .then((_) {
+        // Wait for the process to finish or timeout
+        process.exitCode
+            .timeout(Duration(seconds: timeout), onTimeout: timeoutHandler)
+            .then((exitCode) {
+          // This timeout is used to close stdio to the subprocess once we got
+          // the exitCode. Sometimes descendants of the subprocess keep stdio
+          // handles alive even though the direct subprocess is dead.
+          Future.wait([stdoutFuture, stderrFuture]).timeout(MAX_STDIO_DELAY,
+              onTimeout: () async {
+            DebugLogger.warning(
+                "$MAX_STDIO_DELAY_PASSED_MESSAGE (command: $command)");
+            await stdout.cancel();
+            await stderr.cancel();
+            _commandComplete(exitCode);
+            return null;
+          }).then((_) {
+            if (stdout is FileOutputLog) {
+              // Prevent logging data that has already been written to a file
+              // and is unlikely too add value in the logs because the command
+              // succeeded.
+              stdout.complete = <int>[];
+            }
             _commandComplete(exitCode);
           });
         });
-
-        timeoutTimer =
-            new Timer(new Duration(seconds: timeout), timeoutHandler);
       }).catchError((e) {
         // TODO(floitsch): should we try to report the stacktrace?
         print("Process error:");
@@ -543,9 +561,6 @@
   }
 
   void _commandComplete(int exitCode) {
-    if (timeoutTimer != null) {
-      timeoutTimer.cancel();
-    }
     var commandOutput = _createCommandOutput(command, exitCode);
     completer.complete(commandOutput);
   }
@@ -573,11 +588,6 @@
     return commandOutput;
   }
 
-  StreamSubscription _drainStream(
-      Stream<List<int>> source, OutputLog destination) {
-    return source.listen(destination.add);
-  }
-
   Map<String, String> _createProcessEnvironment() {
     var environment = new Map<String, String>.from(io.Platform.environment);
 
@@ -1209,7 +1219,8 @@
       return _getBatchRunner(name)
           .runCommand(name, command, timeout, command.arguments);
     } else if (command is CompilationCommand &&
-        globalConfiguration.batchDart2JS) {
+        globalConfiguration.batchDart2JS &&
+        command.displayName == 'dart2js') {
       return _getBatchRunner("dart2js")
           .runCommand("dart2js", command, timeout, command.arguments);
     } else if (command is AnalysisCommand && globalConfiguration.batch) {
@@ -1243,6 +1254,12 @@
       var name = command.displayName;
       return _getBatchRunner(command.displayName + command.dartFile)
           .runCommand(name, command, timeout, command.arguments);
+    } else if (command is CompilationCommand &&
+        command.displayName == 'babel') {
+      return new RunningProcess(command, timeout,
+              configuration: globalConfiguration,
+              outputFile: io.File(command.outputFile))
+          .run();
     } else if (command is ProcessCommand) {
       return new RunningProcess(command, timeout,
               configuration: globalConfiguration)
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 6202455..f00c75d 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -141,12 +141,6 @@
   Map<String, String> get environmentOverrides => _environmentOverrides;
 
   /**
-   * Whether or not binaries should be found in the root build directory or
-   * in the built SDK.
-   */
-  bool get useSdk => configuration.useSdk;
-
-  /**
    * The output directory for this suite's configuration.
    */
   String get buildDir => configuration.buildDirectory;
@@ -165,80 +159,6 @@
     return name;
   }
 
-  /// Returns the name of the Dart VM executable.
-  String get dartVmBinaryFileName {
-    // Controlled by user with the option "--dart".
-    var dartExecutable = configuration.dartPath;
-
-    if (dartExecutable == null) {
-      dartExecutable = dartVmExecutableFileName;
-    }
-
-    TestUtils.ensureExists(dartExecutable, configuration);
-    return dartExecutable;
-  }
-
-  String get dartVmExecutableFileName {
-    return useSdk
-        ? '$buildDir/dart-sdk/bin/dart$executableBinarySuffix'
-        : '$buildDir/dart$executableBinarySuffix';
-  }
-
-  String get dartPrecompiledBinaryFileName {
-    // Controlled by user with the option "--dart_precompiled".
-    var dartExecutable = configuration.dartPrecompiledPath;
-
-    if (dartExecutable == null || dartExecutable == '') {
-      var suffix = executableBinarySuffix;
-      dartExecutable = '$buildDir/dart_precompiled_runtime$suffix';
-    }
-
-    TestUtils.ensureExists(dartExecutable, configuration);
-    return dartExecutable;
-  }
-
-  String get processTestBinaryFileName {
-    var suffix = executableBinarySuffix;
-    var processTestExecutable = '$buildDir/process_test$suffix';
-    TestUtils.ensureExists(processTestExecutable, configuration);
-    return processTestExecutable;
-  }
-
-  String get d8FileName {
-    var suffix = getExecutableSuffix('d8');
-    var d8Dir = Repository.dir.append('third_party/d8');
-    var d8Path = d8Dir.append('${Platform.operatingSystem}/d8$suffix');
-    var d8 = d8Path.toNativePath();
-    TestUtils.ensureExists(d8, configuration);
-    return d8;
-  }
-
-  String get jsShellFileName {
-    var executableSuffix = getExecutableSuffix('jsshell');
-    var executable = 'jsshell$executableSuffix';
-    var jsshellDir = '${Repository.dir.toNativePath()}/tools/testing/bin';
-    return '$jsshellDir/$executable';
-  }
-
-  /**
-   * The file extension (if any) that should be added to the given executable
-   * name for the current platform.
-   */
-  // TODO(ahe): Get rid of this. Use executableBinarySuffix instead.
-  String getExecutableSuffix(String executable) {
-    if (Platform.operatingSystem == 'windows') {
-      if (executable == 'd8' || executable == 'vm' || executable == 'none') {
-        return '.exe';
-      } else {
-        return '.bat';
-      }
-    }
-    return '';
-  }
-
-  String get executableBinarySuffix => Platform.isWindows ? '.exe' : '';
-  String get executableScriptSuffix => Platform.isWindows ? '.bat' : '';
-
   /**
    * Call the callback function onTest with a [TestCase] argument for each
    * test in the suite.  When all tests have been processed, call [onDone].
@@ -585,7 +505,7 @@
         extraVmOptions = configuration.vmOptions,
         super(configuration, suiteName, statusFilePaths) {
     // Initialize _dart2JsBootstrapDependencies
-    if (!useSdk) {
+    if (!configuration.useSdk) {
       _dart2JsBootstrapDependencies = [];
     } else {
       _dart2JsBootstrapDependencies = [
@@ -933,7 +853,6 @@
 
     return commands
       ..addAll(configuration.runtimeConfiguration.computeRuntimeCommands(
-          this,
           compilationArtifact,
           runtimeArguments,
           environment,
@@ -1028,30 +947,28 @@
     var fileName = info.filePath.toNativePath();
     var optionsFromFile = info.optionsFromFile;
     var compilationTempDir = createCompilationOutputDirectory(info.filePath);
-    var jsWrapperFileName = '$compilationTempDir/test.js';
     var nameNoExt = info.filePath.filenameWithoutExtension;
+    var outputDir = compilationTempDir;
+    var commonArguments =
+        commonArgumentsFromFile(info.filePath, optionsFromFile);
 
     // Use existing HTML document if available.
     String content;
     var customHtml = new File(
         info.filePath.directoryPath.append('$nameNoExt.html').toNativePath());
     if (customHtml.existsSync()) {
-      jsWrapperFileName = '$tempDir/$nameNoExt.js';
+      outputDir = tempDir;
       content = customHtml.readAsStringSync().replaceAll(
           '%TEST_SCRIPTS%', '<script src="$nameNoExt.js"></script>');
     } else {
       // Synthesize an HTML file for the test.
       if (configuration.compiler == Compiler.dart2js) {
-        var scriptPath = _createUrlPathFromFile(new Path(jsWrapperFileName));
+        var scriptPath = _createUrlPathFromFile(
+            new Path('$compilationTempDir/$nameNoExt.js'));
         content = dart2jsHtml(fileName, scriptPath);
       } else {
         var jsDir =
             new Path(compilationTempDir).relativeTo(Repository.dir).toString();
-        jsWrapperFileName =
-            new Path('$compilationTempDir/$nameNoExt.js').toNativePath();
-        // Always run with synchronous starts of `async` functions.
-        // If we want to make this dependent on other parameters or flags,
-        // this flag could be become conditional.
         content = dartdevcHtml(nameNoExt, jsDir, configuration.compiler);
       }
     }
@@ -1062,36 +979,21 @@
     // Construct the command(s) that compile all the inputs needed by the
     // browser test.
     var commands = <Command>[];
+    const supportedCompilers = {
+      Compiler.dart2js,
+      Compiler.dartdevc,
+      Compiler.dartdevk
+    };
+    assert(supportedCompilers.contains(configuration.compiler));
+    var sharedOptions = optionsFromFile["sharedOptions"] as List<String>;
+    var dart2jsOptions = optionsFromFile["dart2jsOptions"] as List<String>;
+    var ddcOptions = optionsFromFile["ddcOptions"] as List<String>;
 
-    void addCompileCommand(String fileName, String toPath) {
-      switch (configuration.compiler) {
-        case Compiler.dart2js:
-          commands.add(_dart2jsCompileCommand(
-              fileName, toPath, tempDir, optionsFromFile));
-          break;
-
-        case Compiler.dartdevc:
-        case Compiler.dartdevk:
-          var ddcOptions = optionsFromFile["sharedOptions"] as List<String>;
-          ddcOptions.addAll(optionsFromFile["ddcOptions"] as List<String>);
-          commands.add(configuration.compilerConfiguration.createCommand(
-              fileName, toPath, ddcOptions, environmentOverrides));
-          break;
-
-        default:
-          assert(false);
-      }
-    }
-
-    addCompileCommand(fileName, jsWrapperFileName);
-
-    // Some tests require compiling multiple input scripts.
-    for (var name in optionsFromFile['otherScripts'] as List<String>) {
-      var namePath = new Path(name);
-      var fromPath = info.filePath.directoryPath.join(namePath).toNativePath();
-      var toPath = new Path('$tempDir/${namePath.filename}.js').toNativePath();
-      addCompileCommand(fromPath, toPath);
-    }
+    var args = configuration.compilerConfiguration.computeCompilerArguments(
+        null, sharedOptions, null, dart2jsOptions, ddcOptions, commonArguments);
+    var compilation = configuration.compilerConfiguration
+        .computeCompilationArtifact(outputDir, args, environmentOverrides);
+    commands.addAll(compilation.commands);
 
     if (info.optionsFromFile['isMultiHtmlTest'] as bool) {
       // Variables for browser multi-tests.
@@ -1128,43 +1030,6 @@
     enqueueNewTestCase(fullName, commands, expectations, info);
   }
 
-  /// Creates a [Command] to compile a single .dart file using dart2js.
-  Command _dart2jsCompileCommand(String inputFile, String outputFile,
-      String dir, Map<String, dynamic> optionsFromFile) {
-    var args = <String>[];
-
-    if (compilerPath.endsWith('.dart')) {
-      // Run the compiler script via the Dart VM.
-      args.add(compilerPath);
-    }
-
-    args.addAll(configuration.standardOptions);
-    args.addAll(configuration.dart2jsOptions);
-
-    var packages = packagesArgument(optionsFromFile['packageRoot'] as String,
-        optionsFromFile['packages'] as String);
-    if (packages != null) args.add(packages);
-
-    args.add('--out=$outputFile');
-    args.add(inputFile);
-
-    var options = optionsFromFile['sharedOptions'] as List<String>;
-    if (options != null) args.addAll(options);
-    options = optionsFromFile['dart2jsOptions'] as List<String>;
-    if (options != null) args.addAll(options);
-    if (configuration.compiler == Compiler.dart2js) {
-      if (configuration.noPreviewDart2) {
-        args.add("--no-preview-dart-2");
-      } else {
-        args.add("--preview-dart-2");
-      }
-    }
-
-    return Command.compilation(Compiler.dart2js.name, outputFile,
-        dart2JsBootstrapDependencies, compilerPath, args, environmentOverrides,
-        alwaysCompile: !useSdk);
-  }
-
   List<String> commonArgumentsFromFile(
       Path filePath, Map<String, dynamic> optionsFromFile) {
     var args = configuration.standardOptions.toList();
@@ -1185,14 +1050,6 @@
       }
     }
 
-    if (configuration.compiler == Compiler.dart2js) {
-      if (configuration.noPreviewDart2) {
-        args.add("--no-preview-dart-2");
-      } else {
-        args.add("--preview-dart-2");
-      }
-    }
-
     args.add(filePath.toNativePath());
 
     return args;
@@ -1241,12 +1098,6 @@
    *     // Environment=ENV_VAR1=foo bar
    *     // Environment=ENV_VAR2=bazz
    *
-   *   - For tests that depend on compiling other files with dart2js (e.g.
-   *   isolate tests that use multiple source scripts), you can specify
-   *   additional files to compile using a comment too, as follows:
-   *
-   *     // OtherScripts=file1.dart file2.dart
-   *
    *   - Most tests are not web tests, but can (and will be) wrapped within
    *   an HTML file and another script file to test them also on browser
    *   environments (e.g. language and corelib tests are run this way).
@@ -1272,7 +1123,6 @@
     }
     RegExp testOptionsRegExp = new RegExp(r"// VMOptions=(.*)");
     RegExp environmentRegExp = new RegExp(r"// Environment=(.*)");
-    RegExp otherScriptsRegExp = new RegExp(r"// OtherScripts=(.*)");
     RegExp otherResourcesRegExp = new RegExp(r"// OtherResources=(.*)");
     RegExp sharedObjectsRegExp = new RegExp(r"// SharedObjects=(.*)");
     RegExp packageRootRegExp = new RegExp(r"// PackageRoot=(.*)");
@@ -1365,12 +1215,6 @@
       }
     }
 
-    var otherScripts = <String>[];
-    matches = otherScriptsRegExp.allMatches(contents);
-    for (var match in matches) {
-      otherScripts.addAll(wordSplit(match[1]));
-    }
-
     var otherResources = <String>[];
     matches = otherResourcesRegExp.allMatches(contents);
     for (var match in matches) {
@@ -1438,7 +1282,6 @@
       "hasCompileError": hasCompileError,
       "hasRuntimeError": hasRuntimeError,
       "hasStaticWarning": hasStaticWarning,
-      "otherScripts": otherScripts,
       "otherResources": otherResources,
       "sharedObjects": sharedObjects,
       "isMultitest": isMultitest,
@@ -1461,7 +1304,6 @@
       "hasCompileError": false,
       "hasRuntimeError": false,
       "hasStaticWarning": false,
-      "otherScripts": const [],
       "isMultitest": false,
       "isMultiHtmlTest": false,
       "subtestNames": const [],
diff --git a/utils/bazel/kernel_worker.dart b/utils/bazel/kernel_worker.dart
index 8ebfaee..5cd62a0 100644
--- a/utils/bazel/kernel_worker.dart
+++ b/utils/bazel/kernel_worker.dart
@@ -128,7 +128,9 @@
   ..addOption('output')
   ..addFlag('reuse-compiler-result', defaultsTo: false)
   ..addFlag('use-incremental-compiler', defaultsTo: false)
-  ..addFlag('track-widget-creation', defaultsTo: false);
+  ..addFlag('track-widget-creation', defaultsTo: false)
+  ..addMultiOption('enable-experiment',
+      help: 'Enable a language experiment when invoking the CFE.');
 
 class ComputeKernelResult {
   final bool succeeded;
@@ -167,8 +169,7 @@
   if (multiRoots.isEmpty) multiRoots.add(Uri.base);
   var fileSystem = new MultiRootFileSystem(parsedArgs['multi-root-scheme'],
       multiRoots, fe.StandardFileSystem.instance);
-  var sources =
-      (parsedArgs['source'] as List<String>).map(Uri.base.resolve).toList();
+  var sources = (parsedArgs['source'] as List<String>).map(_toUri).toList();
   var excludeNonSources = parsedArgs['exclude-non-sources'] as bool;
 
   var summaryOnly = parsedArgs['summary-only'] as bool;
@@ -222,19 +223,11 @@
       out.writeln('error: unsupported target: $targetName');
   }
 
-  // TODO(sigmund,jakemac): make it mandatory. We allow null while we migrate
-  // existing clients of this tool.
-  var librariesSpec = parsedArgs['libraries-file'] == null
-      ? null
-      : Uri.base.resolve(parsedArgs['libraries-file']);
+  List<Uri> linkedInputs =
+      (parsedArgs['input-linked'] as List<String>).map(_toUri).toList();
 
-  List<Uri> linkedInputs = (parsedArgs['input-linked'] as List<String>)
-      .map(Uri.base.resolve)
-      .toList();
-
-  List<Uri> summaryInputs = (parsedArgs['input-summary'] as List<String>)
-      .map(Uri.base.resolve)
-      .toList();
+  List<Uri> summaryInputs =
+      (parsedArgs['input-summary'] as List<String>).map(_toUri).toList();
 
   fe.InitializedCompilerState state;
   bool usingIncrementalCompiler = false;
@@ -253,27 +246,30 @@
       inputDigests[uri] = input.digest;
     }
 
+    // TODO(sigmund): add support for experiments with the incremental compiler.
     state = await fe.initializeIncrementalCompiler(
         previousState,
-        Uri.base.resolve(parsedArgs['dart-sdk-summary']),
-        Uri.base.resolve(parsedArgs['packages-file']),
-        librariesSpec,
+        _toUri(parsedArgs['dart-sdk-summary']),
+        _toUri(parsedArgs['packages-file']),
+        _toUri(parsedArgs['libraries-file']),
         summaryInputs,
         inputDigests,
         target,
         fileSystem,
+        (parsedArgs['enable-experiment'] as List<String>),
         summaryOnly);
   } else {
     state = await fe.initializeCompiler(
         // TODO(sigmund): pass an old state once we can make use of it.
         null,
-        Uri.base.resolve(parsedArgs['dart-sdk-summary']),
-        librariesSpec,
-        Uri.base.resolve(parsedArgs['packages-file']),
+        _toUri(parsedArgs['dart-sdk-summary']),
+        _toUri(parsedArgs['libraries-file']),
+        _toUri(parsedArgs['packages-file']),
         summaryInputs,
         linkedInputs,
         target,
-        fileSystem);
+        fileSystem,
+        (parsedArgs['enable-experiment'] as List<String>));
   }
 
   void onDiagnostic(fe.DiagnosticMessage message) {
@@ -299,8 +295,6 @@
 
       return Future.value(fe.serializeComponent(incrementalComponent));
     });
-
-    state.options.onDiagnostic = null; // See http://dartbug.com/36983.
   } else if (summaryOnly) {
     kernel = await fe.compileSummary(state, sources, onDiagnostic,
         includeOffsets: false);
@@ -308,9 +302,12 @@
     Component component =
         await fe.compileComponent(state, sources, onDiagnostic);
     kernel = fe.serializeComponent(component,
-        filter: (library) => sources.contains(library.importUri),
+        filter: excludeNonSources
+            ? (library) => sources.contains(library.importUri)
+            : null,
         includeOffsets: true);
   }
+  state.options.onDiagnostic = null; // See http://dartbug.com/36983.
 
   if (kernel != null) {
     var outputFile = new File(parsedArgs['output']);
@@ -365,3 +362,8 @@
     }
   }
 }
+
+Uri _toUri(String uriString) {
+  if (uriString == null) return null;
+  return Uri.base.resolve(uriString);
+}
diff --git a/utils/dartdevc/BUILD.gn b/utils/dartdevc/BUILD.gn
index 767bdb9..0fe884f 100644
--- a/utils/dartdevc/BUILD.gn
+++ b/utils/dartdevc/BUILD.gn
@@ -18,7 +18,7 @@
     "--dart-sdk",
     rebase_path("../../sdk"),
     "--dart-sdk-summary",
-    rebase_path(sdk_summary),
+    rebase_path(sdk_dill),
     "-k",
     "-o",
     "dartdevc.js",