Version 2.2.0-dev.0.0

Merge commit 'f9ce4729c5db9cfd64b084d77241864541dcbcc8' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6ef0c56..80630a8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,59 +1,342 @@
-# 2.1.0-dev.9.4
+## 2.2.0-dev.0.0
 
-Cherry-pick e23acaaf90996b84548ea23af14730ff1a21d826 to dev
+### Dart for the Web
 
-Cherry-pick e6d3a45b6a98ea36581ac375ec5cdd63dd829004 to dev
+#### dart2js
 
-Cherry-pick a40fd6a976d3d3bc341cd2e0f7fb290b7819a52a to dev
+* The `--categories=*` flag is being replaced. `--categories=all` was only used
+  for testing and it is no longer supported. `--categories=Server` continues to
+  work at this time but it is deprecated, please use `--server-mode` instead.
 
-Cherry-pick 9eb1d748819530bb3eb2f78699e0968de8b638fe to dev
+## 2.1.0 - 2018-11-15
 
-# 2.1.0-dev.9.3
+This is a minor version release. The team's focus was mostly on improving
+performance and stability after the large changes in Dart 2.0.0. Notable
+changes:
 
-Cherry-pick 65951ef5080bcfa7d8862685e96f75c2c5d17841 to dev
+*   We've introduced a dedicated syntax for declaring a mixin. Instead of the
+    `class` keyword, it uses `mixin`:
 
-Cherry-pick 6004c8a1876731e65104cf88f46af01bfe8c24c4 to dev
+    ```dart
+    mixin SetMixin<E> implements Set<E> {
+      ...
+    }
+    ```
 
-## 2.1.0-dev.9.2
+    The new syntax also enables `super` calls inside mixins.
 
-Cherry-pick 2cf0ca381ce33d1e6597c778eb1a915eecdac109 to dev
+*   Integer literals now work in double contexts. When passing a literal number
+    to a function that expects a `double`, you no longer need an explicit `.0`
+    at the end of the number. In releases before 2.1, you need code like this
+    when setting a double like `fontSize`:
 
-Cherry-pick c7e6cdf81ca2f6113cc132d85d5f73a9441d3643 to dev
+    ```dart
+    TextStyle(fontSize: 18.0)
+    ```
 
-Cherry-pick a6518386520af63764ad40dde3b53e5e160b9bff to dev
+    Now you can remove the `.0`:
 
-Cherry-pick 2085277771bb91d488edb6e6e55552ba7116dd72 to dev
+    ```dart
+    TextStyle(fontSize: 18)
+    ```
 
-Cherry-pick 0fd4a51e2c805aec79d4d0e42f446f5395c6113a to dev
+    In releases before 2.1, `fontSize : 18` causes a static error. This was a
+    common mistake and source of friction.
 
-Cherry-pick be815e1a867d302ad2fbc8db8d7467cfe85319d2 to dev
+*   **Breaking change:** A number of static errors that should have been
+    detected and reported were not supported in 2.0.0. These are reported now,
+    which means existing incorrect code may show new errors.
 
-Cherry-pick 61df5fdec81be4f8f04c18a774147856931ebbb9 to dev
+*   `dart:core` now exports `Future` and `Stream`. You no longer need to import
+    `dart:async` to use those very common types.
 
-Cherry-pick d8d68358498c83127e26ad1796359146772decad to dev
+### Language
 
-Cherry-pick 9c95624a6307f09f1cdc49054bdd08125acb6f53 to dev
+*   Introduced a new syntax for mixin declarations.
 
-Cherry-pick cde479301a81f9fbaec3fb007457a4ec8e5a65a7 to dev
+    ```dart
+    mixin SetMixin<E> implements Set<E> {
+      ...
+    }
+    ```
 
-## 2.1.0-dev.9.1
+    Most classes that are intended to be used as mixins are intended to *only*
+    be used as mixins. The library author doesn't want users to be able to
+    construct or subclass the class. The new syntax makes that intent clear and
+    enforces it in the type system. It is an error to extend or construct a type
+    declared using `mixin`. (You can implement it since mixins expose an
+    implicit interface.)
 
-Cherry-pick commit 0fe448a99643e149acb2e7e32d7a30eba7dd646d to update the analysis server edit.dartfix protocol.
+    Over time, we expect most mixin declarations to use the new syntax. However,
+    if you have a "mixin" class where users *are* extending or constructing it,
+    note that moving it to the new syntax is a breaking API change since it
+    prevents users from doing that. If you have a type like this that is a
+    mixin as well as being a concrete class and/or superclass, then the existing
+    syntax is what you want.
 
-Cherry-pick commit 45d070d437bb1b596516edd3717e6ee614c5f9ac to update linter to version 0.1.71.
+    If you need to use a `super` inside a mixin, the new syntax is required.
+    This was previously only allowed with the experimental `--supermixins` flag
+    because it has some complex interactions with the type system. The new
+    syntax addresses those issues and lets you use `super` calls by declaring
+    the superclass constraint your mixin requires:
 
-Cherry-pick commit 00f27a32cf52834b3e9e1f52889b6f1c83ad338c to fix usage of mixins in dart dev compiler.
+    ```dart
+    class Superclass {
+      superclassMethod() {
+        print("in superclass");
+      }
+    }
 
-Cherry-pick commit 523353d28017fced825581ea327509c620eed67e to fix the ARM 32-bit build.
+    mixin SomeMixin on Superclass {
+      mixinMethod() {
+        // This is OK:
+        super.superclassMethod();
+      }
+    }
 
-Cherry-pick commit db4271378f56a66528a87f2f920c678162d59a35 to fix an
-issue with coverage
+    class GoodSub extends Superclass with SomeMixin {}
 
-## 2.1.0-dev.9.0
+    class BadSub extends Object with SomeMixin {}
+    // Error: Since the super() call in mixinMethod() can't find a
+    // superclassMethod() to call, this is prohibited.
+    ```
 
-## 2.1.0-dev.8.0
+    Even if you don't need to use `super` calls, the new mixin syntax is good
+    because it clearly expresses that you intend the type to be mixed in.
+
+*   Allow integer literals to be used in double contexts. An integer literal
+    used in a place where a double is required is now interpreted as a double
+    value. The numerical value of the literal needs to be precisely
+    representable as a double value.
+
+*   Integer literals compiled to JavaScript are now allowed to have any value
+    that can be exactly represented as a JavaScript `Number`. They were
+    previously limited to such numbers that were also representable as signed
+    64-bit integers.
+
+**(Breaking)** A number of static errors that should have been detected and
+reported were not supported in 2.0.0. These are reported now, which means
+existing incorrect code may show new errors:
+
+*   **Setters with the same name as the enclosing class aren't allowed.** (Issue
+    [34225][].) It is not allowed to have a class member with the same name as
+    the enclosing class:
+
+    ```dart
+    class A {
+      set A(int x) {}
+    }
+    ```
+
+    Dart 2.0.0 incorrectly allows this for setters (only). Dart 2.1.0 rejects
+    it.
+
+    *To fix:* This is unlikely to break anything, since it violates all style
+    guides anyway.
+
+*   **Constant constructors cannot redirect to non-constant constructors.**
+    (Issue [34161][].) It is not allowed to have a constant constructor that
+    redirects to a non-constant constructor:
+
+    ```dart
+    class A {
+      const A.foo() : this(); // Redirecting to A()
+      A() {}
+    }
+    ```
+
+    Dart 2.0.0 incorrectly allows this. Dart 2.1.0 rejects it.
+
+    *To fix:* Make the target of the redirection a properly const constructor.
+
+*   **Abstract methods may not unsoundly override a concrete method.** (Issue
+    [32014][].) Concrete methods must be valid implementations of their
+    interfaces:
+
+    ```dart
+    class A {
+      num get thing => 2.0;
+    }
+
+    abstract class B implements A {
+      int get thing;
+    }
+
+    class C extends A with B {}
+    // 'thing' from 'A' is not a valid override of 'thing' from 'B'.
+
+    main() {
+      print(new C().thing.isEven); // Expects an int but gets a double.
+    }
+    ```
+
+    Dart 2.0.0 allows unsound overrides like the above in some cases. Dart 2.1.0
+    rejects them.
+
+    *To fix:* Relax the type of the invalid override, or tighten the type of the
+    overridden method.
+
+*   **Classes can't implement FutureOr.** (Issue [33744][].) Dart doesn't allow
+    classes to implement the FutureOr type:
+
+    ```dart
+    class A implements FutureOr<Object> {}
+    ```
+
+    Dart 2.0.0 allows classes to implement FutureOr. Dart 2.1.0 does not.
+
+    *To fix:* Don't do this.
+
+*   **Type arguments to generic typedefs must satisfy their bounds.** (Issue
+    [33308][].) If a parameterized typedef specifies a bound, actual arguments
+    must be checked against it:
+
+    ```dart
+    class A<X extends int> {}
+
+    typedef F<Y extends int> = A<Y> Function();
+
+    F<num> f = null;
+    ```
+
+    Dart 2.0.0 allows bounds violations like `F<num>` above. Dart 2.1.0 rejects
+    them.
+
+    *To fix:* Either remove the bound on the typedef parameter, or pass a valid
+    argument to the typedef.
+
+*   **Constructor invocations must use valid syntax, even with optional `new`.**
+    (Issue [34403][].) Type arguments to generic named constructors go after the
+    class name, not the constructor name, even when used without an explicit
+    `new`:
+
+    ```dart
+    class A<T> {
+      A.foo() {}
+    }
+
+    main() {
+      A.foo<String>(); // Incorrect syntax, was accepted in 2.0.0.
+      A<String>.foo(); // Correct syntax.
+    }
+    ```
+
+    Dart 2.0.0 accepts the incorrect syntax when the `new` keyword is left out.
+    Dart 2.1.0 correctly rejects this code.
+
+    *To fix:* Move the type argument to the correct position after the class
+    name.
+
+*   **Instance members should shadow prefixes.** (Issue [34498][].) If the same
+    name is used as an import prefix and as a class member name, then the class
+    member name takes precedence in the class scope.
+
+    ```dart
+    import 'dart:core';
+    import 'dart:core' as core;
+
+    class A {
+      core.List get core => null; // "core" refers to field, not prefix.
+    }
+    ```
+
+    Dart 2.0.0 incorrectly resolves the use of `core` in `core.List` to the
+    prefix name. Dart 2.1.0 correctly resolves this to the field name.
+
+    *To fix:* Change the prefix name to something which does not clash with the
+    instance member.
+
+*   **Implicit type arguments in extends clauses must satisfy the class
+    bounds.** (Issue [34532][].) Implicit type arguments for generic classes are
+    computed if not passed explicitly, but when used in an `extends` clause they
+    must be checked for validity:
+
+    ```dart
+    class Foo<T> {}
+
+    class Bar<T extends Foo<T>> {}
+
+    class Baz extends Bar {} // Should error because Bar completes to Bar<Foo>
+    ```
+
+    Dart 2.0.0 accepts the broken code above. Dart 2.1.0 rejects it.
+
+    *To fix:* Provide explicit type arguments to the superclass that satisfy the
+    bound for the superclass.
+
+*   **Mixins must correctly override their superclasses.** (Issue [34235][].) In
+    some rare cases, combinations of uses of mixins could result in invalid
+    overrides not being caught:
+
+    ```dart
+    class A {
+      num get thing => 2.0;
+    }
+
+    class M1 {
+      int get thing => 2;
+    }
+
+    class B = A with M1;
+
+    class M2 {
+      num get thing => 2.0;
+    }
+
+    class C extends B with M2 {} // 'thing' from 'M2' not a valid override.
+
+    main() {
+      M1 a = new C();
+      print(a.thing.isEven); // Expects an int but gets a double.
+    }
+    ```
+
+    Dart 2.0.0 accepts the above example. Dart 2.1.0 rejects it.
+
+    *To fix:* Ensure that overriding methods are correct overrides of their
+    superclasses, either by relaxing the superclass type, or tightening the
+    subclass/mixin type.
+
+[32014]: https://github.com/dart-lang/sdk/issues/32014
+[33308]: https://github.com/dart-lang/sdk/issues/33308
+[33744]: https://github.com/dart-lang/sdk/issues/33744
+[34161]: https://github.com/dart-lang/sdk/issues/34161
+[34225]: https://github.com/dart-lang/sdk/issues/34225
+[34235]: https://github.com/dart-lang/sdk/issues/34235
+[34403]: https://github.com/dart-lang/sdk/issues/34403
+[34498]: https://github.com/dart-lang/sdk/issues/34498
+[34532]: https://github.com/dart-lang/sdk/issues/34532
+
+### Core libraries
+
+#### `dart:async`
+
+*   Fixed a bug where calling `stream.take(0).drain(value)` would not correctly
+    forward the `value` through the returned `Future`.
+*   Added a `StreamTransformer.fromBind` constructor.
+*   Updated `Stream.fromIterable` to send a done event after the error when the
+    iterator's `moveNext` throws, and handle if the `current` getter throws
+    (issue [33431][]).
+
+[33431]: http://dartbug.com/33431
+
+#### `dart:core`
+
+*   Added `HashMap.fromEntries` and `LinkedHashmap.fromEntries` constructors.
+*   Added `ArgumentError.checkNotNull` utility method.
+*   Made `Uri` parsing more permissive about `[` and `]` occurring in the path,
+    query or fragment, and `#` occurring in fragment.
+*   Exported `Future` and `Stream` from `dart:core`.
+*   Added operators `&`, `|` and `^` to `bool`.
+*   Added missing methods to `UnmodifiableMapMixin`. Some maps intended to
+    be unmodifiable incorrectly allowed new methods added in Dart 2 to
+    succeed.
+*   Deprecated the `provisional` annotation and the `Provisional`
+    annotation class. These should have been removed before releasing Dart 2.0,
+    and they have no effect.
 
 #### `dart:html`
+
 Fixed Service Workers and any Promise/Future API with a Dictionary parameter.
 
 APIs in dart:html (that take a Dictionary) will receive a Dart Map parameter.
@@ -65,321 +348,135 @@
 This caused a number of breaks especially in Service Workers (register, etc.).
 Here is a complete list of the fixed APIs:
 
-* BackgroundFetchManager
-  * `Future<BackgroundFetchRegistration> fetch(String id, Object requests, [Map options])`
+*   BackgroundFetchManager
+    *   `Future<BackgroundFetchRegistration> fetch(String id, Object requests,
+        [Map options])`
+*   CacheStorage
+    *   `Future match(/*RequestInfo*/ request, [Map options])`
+*   CanMakePayment
+    *   `Future<List<Client>> matchAll([Map options])`
+*   CookieStore
+    *   `Future getAll([Map options])`
+    *   `Future set(String name, String value, [Map options])`
+*   CredentialsContainer
+    *   `Future get([Map options])`
+    *   `Future create([Map options])`
+*   ImageCapture
+    *   `Future setOptions(Map photoSettings)`
+*   MediaCapabilities
+    *   `Future<MediaCapabilitiesInfo> decodingInfo(Map configuration)`
+    *   `Future<MediaCapabilitiesInfo> encodingInfo(Map configuration)`
+*   MediaStreamTrack
+    *   `Future applyConstraints([Map constraints])`
+*   Navigator
+    *   `Future requestKeyboardLock([List<String> keyCodes])`
+    *   `Future requestMidiAccess([Map options])`
+    *   `Future share([Map data])`
+*   OffscreenCanvas
+    *   `Future<Blob> convertToBlob([Map options])`
+*   PaymentInstruments
+    *   `Future set(String instrumentKey, Map details)`
+*   Permissions
+    *   `Future<PermissionStatus> query(Map permission)`
+    *   `Future<PermissionStatus> request(Map permissions)`
+    *   `Future<PermissionStatus> revoke(Map permission)`
+*   PushManager
+    *   `Future permissionState([Map options])`
+    *   `Future<PushSubscription> subscribe([Map options])`
+*   RtcPeerConnection
+    *   Changed:
 
-* CacheStorage
-  * `Future match(/*RequestInfo*/ request, [Map options])`
+        ```dart
+        Future createAnswer([options_OR_successCallback,
+            RtcPeerConnectionErrorCallback failureCallback,
+            Map mediaConstraints])
+        ```
 
-* CanMakePayment
-  * `Future<List<Client>> matchAll([Map options])`
+        to:
 
-* CookieStore
-  * `Future getAll([Map options])`
-  * `Future set(String name, String value, [Map options])`
+        ```dart
+        Future<RtcSessionDescription> createAnswer([Map options])
+        ```
 
-* CredentialsContainer
-  * `Future get([Map options])`
-  * `Future create([Map options])`
+    *   Changed:
 
-* ImageCapture
-  * `Future setOptions(Map photoSettings)`
+        ```dart
+        Future createOffer([options_OR_successCallback,
+            RtcPeerConnectionErrorCallback failureCallback,
+            Map rtcOfferOptions])
+        ```
 
-* MediaCapabilities
-  * `Future<MediaCapabilitiesInfo> decodingInfo(Map configuration)`
-  * `Future<MediaCapabilitiesInfo> encodingInfo(Map configuration)`
+        to:
 
-* MediaStreamTrack
-  * `Future applyConstraints([Map constraints])`
+        ```dart
+        Future<RtcSessionDescription> createOffer([Map options])
+        ```
 
-* Navigator
-  * `Future requestKeyboardLock([List<String> keyCodes])`
-  * `Future requestMidiAccess([Map options])`
-  * `Future share([Map data])`
+    *   Changed:
 
-* OffscreenCanvas
-  * `Future<Blob> convertToBlob([Map options])`
+        ```dart
+        Future setLocalDescription(Map description,
+            VoidCallback successCallback,
+            [RtcPeerConnectionErrorCallback failureCallback])
+        ```
 
-* PaymentInstruments
-  * `Future set(String instrumentKey, Map details)`
+        to:
 
-* Permissions
-  * `Future<PermissionStatus> query(Map permission)`
-  * `Future<PermissionStatus> request(Map permissions)`
-  * `Future<PermissionStatus> revoke(Map permission)`
+        ```dart
+        Future setLocalDescription(Map description)
+        ```
 
-* PushManager
-  * `Future permissionState([Map options])`
-  * `Future<PushSubscription> subscribe([Map options])`
+    *   Changed:
 
-* RtcPeerConnection
-  * **CHANGED**
+        ```dart
+        Future setLocalDescription(Map description,
+            VoidCallback successCallback,
+            [RtcPeerConnectionErrorCallback failureCallback])
+        ```
 
-    ```dart
-    Future createAnswer([options_OR_successCallback,
-                         RtcPeerConnectionErrorCallback failureCallback,
-                         Map mediaConstraints])
-    ```
+        to:
 
-    to
+        ```dart
+        Future setRemoteDescription(Map description)
+        ```
 
-    `Future<RtcSessionDescription> createAnswer([Map options])`
-
-  * **CHANGED**
-
-    ```dart
-    Future createOffer([options_OR_successCallback,
-                        RtcPeerConnectionErrorCallback failureCallback,
-                        Map rtcOfferOptions])
-    ```
-
-    to
-
-    `Future<RtcSessionDescription> createOffer([Map options])`
-
-  * **CHANGED**
-
-    ```dart
-    Future setLocalDescription(Map description, VoidCallback successCallback,
-                               [RtcPeerConnectionErrorCallback failureCallback])
-    ```
-
-    to
-
-    `Future setLocalDescription(Map description)`
-  * **CHANGED**
-
-    ```dart
-    Future setLocalDescription(Map description, VoidCallback successCallback,
-                               [RtcPeerConnectionErrorCallback failureCallback])
-    ```
-
-    to
-
-    `Future setRemoteDescription(Map description)`
-
-* ServiceWorkerContainer
-  * `Future<ServiceWorkerRegistration> register(String url, [Map options])`
-
-* ServiceWorkerRegistration
-  * `Future<List<Notification>> getNotifications([Map filter])`
-  * `Future showNotification(String title, [Map options])`
-
-* VRDevice
-  * `Future requestSession([Map options])`
-  * `Future supportsSession([Map options])`
-
-* VRSession
-  * `Future requestFrameOfReference(String type, [Map options])`
-
-* Window
-  * `Future fetch(/*RequestInfo*/ input, [Map init])`
-
-* WorkerGlobalScope
-  * `Future fetch(/*RequestInfo*/ input, [Map init])`
+*   ServiceWorkerContainer
+    *   `Future<ServiceWorkerRegistration> register(String url, [Map options])`
+*   ServiceWorkerRegistration
+    *   `Future<List<Notification>> getNotifications([Map filter])`
+    *   `Future showNotification(String title, [Map options])`
+*   VRDevice
+    *   `Future requestSession([Map options])`
+    *   `Future supportsSession([Map options])`
+*   VRSession
+    *   `Future requestFrameOfReference(String type, [Map options])`
+*   Window
+    *   `Future fetch(/*RequestInfo*/ input, [Map init])`
+*   WorkerGlobalScope
+    *   `Future fetch(/*RequestInfo*/ input, [Map init])`
 
 In addition, exposed Service Worker "self" as a static getter named "instance".
 The instance is exposed on four different Service Worker classes and can throw
 a InstanceTypeError if the instance isn't of the class expected
 (WorkerGlobalScope.instance will always work and not throw):
 
-*   SharedWorkerGlobalScope.instance
-*   DedicatedWorkerGlobalScope.instance
-*   ServiceWorkerGlobalScope.instance
-*   WorkerGlobalScope.instance
+*   `SharedWorkerGlobalScope.instance`
+*   `DedicatedWorkerGlobalScope.instance`
+*   `ServiceWorkerGlobalScope.instance`
+*   `WorkerGlobalScope.instance`
 
-### Language
+#### `dart:io`
 
-*   Allow integer literals to be used in double contexts.
-    An integer literal used in a place where a double is required is now
-    interpreted as a double value. The numerical value of the literal needs
-    to be precisely representable as a double value.
+*   Added new HTTP status codes.
 
-*   Integer literals compiled to JavaScript are now allowed to have any
-    value that can be exactly represented as a JavaScript `Number`.
-    They were previously limited to such numbers that were also representable
-    as signed 64-bit integers.
-
-### Core library changes
-
-*   Add `HashMap.fromEntries` and `LinkedHashmap.fromEntries` constructors.
-*   Add `ArgumentError.checkNotNull` utility method.
-
-### Tool Changes
-
-#### Linter
-
-Bumped the linter to `0.1.70` which includes the following new lints:
-
-* `avoid_returning_null_for_void`
-* `sort_pub_dependencies`
-* `prefer_mixin`
-* `avoid_implementing_value_types`
-* `flutter_style_todos`
-* `avoid_void_async`
-* `prefer_void_to_null`
-
-and improvements:
-
-* fix NPE in `prefer_iterable_whereType`
-* improved message display for `await_only_futures`
-* performance improvements for `null_closures`
-* mixin support
-* update to `sort_constructors_first` to apply to all members
-* update `unnecessary_this` to work on field initializers
-* updated `unawaited_futures` to ignore assignments within cascades
-* improved handling of constant expressions with generic type params
-* NPE fix for `invariant_booleans`
-* improved docs for `unawaited_futures`
-* `unawaited_futures` updated to check cascades
-* relaxed `void_checks` (allowing `T Function()` to be assigned to `void Function()`)
-* fixed false positives in `lines_longer_than_80_chars`
+### Dart for the Web
 
 #### dart2js
 
-*   Breaking change: duplicate keys in a const map are not allowed and produce a
-    compile-time error.  Dart2js used to report this as a warning before. Note
-    this is already an error in dartanalyzer and DDC and will be an error in
-    other tools in the future as well.
-
-## 2.1.0-dev.7.1
-
-* Cherry-pick 6b67cd784bbd13d5b6127cba44281a879fa7275c to dev
-
-## 2.1.0-dev.7.0
-
-### Language
-
-*   Fixed a bug (issue [32014](http://dartbug.com/32014)) that caused invalid
-    implementations of the interface of a class to not be reported in some cases.
-    For instance, the following code would not produce a compile-time error:
-
-    ```dart
-    class A {
-      num get thing => 2.0;
-    }
-
-    abstract class B implements A {
-      int get thing;
-    }
-
-    class C extends A with B {} // 'thing' from 'A' is not a valid override of 'thing' from 'B'.
-
-    main() {
-      print(new C().thing.isEven); // Expects an int but gets a double.
-    }
-    ```
-
-*   Fixed a bug (issue [34235](http://dartbug.com/34235)) that caused invalid
-    overrides between a mixin member and an overridden member in the superclass
-    of the mixin application to not be reported. For instance, the following
-    code would not produce a compile-time error:
-
-    ```dart
-    class A {
-      int get thing => 2;
-    }
-
-    class B {
-      num get thing => 2.0;
-    }
-
-    class C extends A with B {} // 'thing' from 'B' is not a valid override of 'thing' from 'A'.
-
-    main() {
-      A a = new C();
-      print(a.thing.isEven); // Expects an int but gets a double.
-    }
-    ```
-
-### Core library changes
-
-#### `dart:core`
-
-*   Made `Uri` parsing more permissive about `[` and `]` occurring
-    in the path, query or fragment, and `#` occurring in fragment.
-
-## 2.1.0-dev.6.0
-
-## 2.1.0-dev.5.0
-
-### Core library changes
-
-#### `dart:core`
-
-*   Exported `Future` and `Stream` from `dart:core`.
-*   Added operators `&`, `|` and `^` to `bool`.
-
-#### `dart:async`
-
-*   Fix a bug where calling `stream.take(0).drain(value)` would not correctly
-    forward the `value` through the returned `Future`.
-*   Add a `StreamTransformer.fromBind` constructor.
-
-## 2.1.0-dev.4.0
-
-### Core library changes
-
-#### `dart:core`
-
-*   Added missing methods to `UnmodifiableMapMixin`. Some maps intended to
-    be unmodifiable incorrectly allowed new methods added in Dart 2 to
-    succeed.
-
-## 2.1.0-dev.3.1
-
-### Tool Changes
-
-#### dartanalyzer
-
-* Fix a bug in analyzer by cherry-picking commit
-  bd9645abad40d14c8cd9197dfb5c9cc45b20e9d6
-
-## 2.1.0-dev.3.0
-
-### Core library changes
-
-#### `dart:async`
-
-*   Update `Stream.fromIterable` to send a done event after the error when the
-    iterator's `moveNext` throws, and handle if the `current` getter throws.
-    Issue [33431](http://dartbug.com/33431).
-
-## 2.1.0-dev.2.0
-
-### Tool Changes
-
-#### dartfmt
-
-*   Upgrade to an intermediate version of dartfmt.
-*   Address several dartfmt issues when used with the new CFE parser.
-
-### Core library changes
-
-#### `dart:core`:
-
-*   Deprecated the `provisional` annotation and the `Provisional`
-    annotation class. These should have been removed before releasing Dart 2.0,
-    and they have no effect.
-
-## 2.1.0-dev.1.0
-
-### Tool Changes
-
-#### Pub
-
-* Rename the `--checked` flag to `pub run` to `--enable-asserts`.
-
-## 2.1.0-dev.0.0
-
-### Tool Changes
-
-#### Pub
-
-*   Pub will no longer delete directories named "packages".
-*   The `--packages-dir` flag is now ignored.
-
-#### dart2js
+*   **(Breaking)** Duplicate keys in a const map are not allowed and produce a
+    compile-time error. Dart2js used to report this as a warning before. This
+    was already an error in dartanalyzer and DDC and will be an error in other
+    tools in the future as well.
 
 *   Added `-O` flag to tune optimization levels.  For more details run `dart2js
     -h -v`.
@@ -392,6 +489,47 @@
     At this time we recommend to test and debug with `-O1` and to deploy with
     `-O3`.
 
+### Tool Changes
+
+#### dartfmt
+
+*   Addressed several dartfmt issues when used with the new CFE parser.
+
+#### Linter
+
+Bumped the linter to `0.1.70` which includes the following new lints:
+
+*   `avoid_returning_null_for_void`
+*   `sort_pub_dependencies`
+*   `prefer_mixin`
+*   `avoid_implementing_value_types`
+*   `flutter_style_todos`
+*   `avoid_void_async`
+*   `prefer_void_to_null`
+
+and improvements:
+
+*   Fixed NPE in `prefer_iterable_whereType`.
+*   Improved message display for `await_only_futures`
+*   Performance improvements for `null_closures`
+*   Mixin support
+*   Updated `sort_constructors_first` to apply to all members.
+*   Updated `unnecessary_this` to work on field initializers.
+*   Updated `unawaited_futures` to ignore assignments within cascades.
+*   Improved handling of constant expressions with generic type params.
+*   NPE fix for `invariant_booleans`.
+*   Improved docs for `unawaited_futures`.
+*   Updated `unawaited_futures` to check cascades.
+*   Relaxed `void_checks` (allowing `T Function()` to be assigned to
+    `void Function()`).
+*   Fixed false positives in `lines_longer_than_80_chars`.
+
+#### Pub
+
+*   Renamed the `--checked` flag to `pub run` to `--enable-asserts`.
+*   Pub will no longer delete directories named "packages".
+*   The `--packages-dir` flag is now ignored.
+
 ## 2.0.0 - 2018-08-07
 
 This is the first major version release of Dart since 1.0.0, so it contains many
diff --git a/DEPS b/DEPS
index 5323847..4e7c835 100644
--- a/DEPS
+++ b/DEPS
@@ -36,7 +36,7 @@
   "chromium_git": "https://chromium.googlesource.com",
   "fuchsia_git": "https://fuchsia.googlesource.com",
 
-  "co19_2_rev": "77825446f59893bb2b20f2e9517a4567e0371193",
+  "co19_2_rev": "740cb9e9b3fc8e1da2f55e10554ffeac90461b73",
 
   # As Flutter does, we pull buildtools, including the clang toolchain, from
   # Fuchsia. This revision should be kept up to date with the revision pulled
@@ -81,7 +81,7 @@
 
   "dartdoc_tag" : "v0.24.1",
   "file_rev": "515ed1dd48740ab14b625de1be464cb2bca4fefd",  # 5.0.6
-  "fixnum_tag": "0.10.8",
+  "fixnum_tag": "0.10.9",
   "func_rev": "25eec48146a58967d75330075ab376b3838b18a8",
   "glob_tag": "1.1.7",
   "html_tag" : "0.13.3+2",
@@ -139,7 +139,7 @@
   "unittest_rev": "2b8375bc98bb9dc81c539c91aaea6adce12e1072",
   "usage_tag": "3.4.0",
   "utf_tag": "0.9.0+5",
-  "watcher_rev": "0.9.7+10",
+  "watcher_rev": "0.9.7+12",
   "web_components_rev": "8f57dac273412a7172c8ade6f361b407e2e4ed02",
   "web_socket_channel_tag": "1.0.9",
   "WebCore_rev": "fb11e887f77919450e497344da570d780e078bc8",
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py
index cfc2f50..32eb669 100644
--- a/build/vs_toolchain.py
+++ b/build/vs_toolchain.py
@@ -21,6 +21,7 @@
 import stat
 import subprocess
 import sys
+
 from gn_helpers import ToGNString
 
 
@@ -63,9 +64,14 @@
       win_sdk = toolchain_data['win8sdk']
     wdk = toolchain_data['wdk']
     # TODO(scottmg): The order unfortunately matters in these. They should be
-    # split into separate keys for x86 and x64. (See CopyDlls call below).
+    # split into separate keys for x64/x86/arm64. (See CopyDlls call below).
     # http://crbug.com/345992
     vs_runtime_dll_dirs = toolchain_data['runtime_dirs']
+    # The number of runtime_dirs in the toolchain_data was two (x64/x86) but
+    # changed to three (x64/x86/arm64) and this code needs to handle both
+    # possibilities, which can change independently from this code.
+    if len(vs_runtime_dll_dirs) == 2:
+      vs_runtime_dll_dirs.append('Arm64Unused')
 
     os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain
     os.environ['GYP_MSVS_VERSION'] = version
@@ -87,9 +93,12 @@
     # directory ensures that they are available when needed.
     bitness = platform.architecture()[0]
     # When running 64-bit python the x64 DLLs will be in System32
+    # ARM64 binaries will not be available in the system directories because we
+    # don't build on ARM64 machines.
     x64_path = 'System32' if bitness == '64bit' else 'Sysnative'
     x64_path = os.path.join(os.path.expandvars('%windir%'), x64_path)
-    vs_runtime_dll_dirs = [x64_path, os.path.expandvars('%windir%/SysWOW64')]
+    vs_runtime_dll_dirs = [x64_path, os.path.expandvars('%windir%/SysWOW64'),
+                           'Arm64Unused']
 
   return vs_runtime_dll_dirs
 
@@ -141,7 +150,6 @@
     raise Exception(('Visual Studio version %s (from GYP_MSVS_VERSION)'
                      ' not supported. Supported versions are: %s') % (
                        version_as_year, ', '.join(year_to_version.keys())))
-  version = year_to_version[version_as_year]
   if version_as_year == '2017':
     # The VC++ 2017 install location needs to be located using COM instead of
     # the registry. For details see:
@@ -201,16 +209,21 @@
       os.environ.get('WINDOWSSDKDIR',
                      os.path.expandvars('%ProgramFiles(x86)%'
                                         '\\Windows Kits\\10')))
-  ucrt_dll_dirs = os.path.join(win_sdk_dir, 'Redist', 'ucrt', 'DLLs',
-                               target_cpu)
-  ucrt_files = glob.glob(os.path.join(ucrt_dll_dirs, 'api-ms-win-*.dll'))
-  assert len(ucrt_files) > 0
-  for ucrt_src_file in ucrt_files:
-    file_part = os.path.basename(ucrt_src_file)
-    ucrt_dst_file = os.path.join(target_dir, file_part)
-    _CopyRuntimeImpl(ucrt_dst_file, ucrt_src_file, False)
-  _CopyRuntimeImpl(os.path.join(target_dir, 'ucrtbase' + suffix),
-                    os.path.join(source_dir, 'ucrtbase' + suffix))
+  # ARM64 doesn't have a redist for the ucrt DLLs because they are always
+  # present in the OS.
+  if target_cpu != 'arm64':
+    ucrt_dll_dirs = os.path.join(win_sdk_dir, 'Redist', 'ucrt', 'DLLs',
+                                 target_cpu)
+    ucrt_files = glob.glob(os.path.join(ucrt_dll_dirs, 'api-ms-win-*.dll'))
+    assert len(ucrt_files) > 0
+    for ucrt_src_file in ucrt_files:
+      file_part = os.path.basename(ucrt_src_file)
+      ucrt_dst_file = os.path.join(target_dir, file_part)
+      _CopyRuntimeImpl(ucrt_dst_file, ucrt_src_file, False)
+  # We must copy ucrtbase.dll for x64/x86, and ucrtbased.dll for all CPU types.
+  if target_cpu != 'arm64' or not suffix.startswith('.'):
+    _CopyRuntimeImpl(os.path.join(target_dir, 'ucrtbase' + suffix),
+                     os.path.join(source_dir, 'ucrtbase' + suffix))
 
 
 def FindVCToolsRoot():
@@ -249,6 +262,7 @@
     # from HostX86/x86.
     pgo_x86_runtime_dir = os.path.join(pgo_runtime_root, 'HostX86', 'x86')
     pgo_x64_runtime_dir = os.path.join(pgo_runtime_root, 'HostX64', 'x64')
+    pgo_arm64_runtime_dir = os.path.join(pgo_runtime_root, 'arm64')
   else:
     raise Exception('Unexpected toolchain version: %s.' % env_version)
 
@@ -261,8 +275,10 @@
       source = os.path.join(pgo_x86_runtime_dir, runtime)
     elif target_cpu == 'x64':
       source = os.path.join(pgo_x64_runtime_dir, runtime)
+    elif target_cpu == 'arm64':
+      source = os.path.join(pgo_arm64_runtime_dir, runtime)
     else:
-      raise NotImplementedError("Unexpected target_cpu value: " + target_cpu)
+      raise NotImplementedError('Unexpected target_cpu value: ' + target_cpu)
     if not os.path.exists(source):
       raise Exception('Unable to find %s.' % source)
     _CopyRuntimeImpl(os.path.join(target_dir, runtime), source)
@@ -271,7 +287,7 @@
 def _CopyRuntime(target_dir, source_dir, target_cpu, debug):
   """Copy the VS runtime DLLs, only if the target doesn't exist, but the target
   directory does exist. Handles VS 2015 and VS 2017."""
-  suffix = "d.dll" if debug else ".dll"
+  suffix = 'd.dll' if debug else '.dll'
   # VS 2017 uses the same CRT DLLs as VS 2015.
   _CopyUCRTRuntime(target_dir, source_dir, target_cpu, '%s140' + suffix,
                     suffix)
@@ -290,8 +306,15 @@
   if not vs_runtime_dll_dirs:
     return
 
-  x64_runtime, x86_runtime = vs_runtime_dll_dirs
-  runtime_dir = x64_runtime if target_cpu == 'x64' else x86_runtime
+  x64_runtime, x86_runtime, arm64_runtime = vs_runtime_dll_dirs
+  if target_cpu == 'x64':
+    runtime_dir = x64_runtime
+  elif target_cpu == 'x86':
+    runtime_dir = x86_runtime
+  elif target_cpu == 'arm64':
+    runtime_dir = arm64_runtime
+  else:
+    raise Exception('Unknown target_cpu: ' + target_cpu)
   _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=False)
   if configuration == 'Debug':
     _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=True)
@@ -424,7 +447,7 @@
 
 
 def NormalizePath(path):
-  while path.endswith("\\"):
+  while path.endswith('\\'):
     path = path[:-1]
   return path
 
@@ -476,4 +499,4 @@
 
 
 if __name__ == '__main__':
-  sys.exit(main())
\ No newline at end of file
+  sys.exit(main())
diff --git a/docs/language/.gitignore b/docs/language/.gitignore
index 13c7614..8c6cc1f 100644
--- a/docs/language/.gitignore
+++ b/docs/language/.gitignore
@@ -1,4 +1,7 @@
 dartLangSpec*.aux
+dartLangSpec*.idx
+dartLangSpec*.ilg
+dartLangSpec*.ind
 dartLangSpec*.log
 dartLangSpec*.out
 dartLangSpec*.pdf
diff --git a/docs/language/Makefile b/docs/language/Makefile
index 4819c23..aecfd61 100644
--- a/docs/language/Makefile
+++ b/docs/language/Makefile
@@ -6,21 +6,25 @@
 
 pdf:
 	pdflatex $(SPEC)
+	makeindex $(NAME).idx
 	pdflatex $(SPEC)
 	pdflatex $(SPEC)
 
 pdfhash: hash_and_list
 	pdflatex $(HASH)
+	makeindex $(NAME)-hash.idx
 	pdflatex $(HASH)
 	pdflatex $(HASH)
 
 dvi:
 	latex $(SPEC)
+	makeindex $(NAME).idx
 	latex $(SPEC)
 	latex $(SPEC)
 
 dvihash: hash_and_list
 	latex $(HASH)
+	makeindex $(NAME)-hash.idx
 	latex $(HASH)
 	latex $(HASH)
 
@@ -35,8 +39,7 @@
 	@echo "  clean: remove all generated files"
 
 cleanish:
-	rm -f *.aux *.log *.toc *.out
+	rm -f *.aux *.log *.toc *.out *.idx *.ilg
 
 clean: cleanish
-	rm -f *.dvi *.pdf $(HASH) $(LIST)
- 
+	rm -f *.dvi *.pdf *.ind $(HASH) $(LIST)
diff --git a/docs/language/dart.sty b/docs/language/dart.sty
index d6c265d..0aede6b 100644
--- a/docs/language/dart.sty
+++ b/docs/language/dart.sty
@@ -78,7 +78,7 @@
 
 % Used as line break in the right hand side of a grammar
 % alternative, that is, when starting a "continuation line".
-\newcommand{\gnewline}{\\\mbox{}\qquad{}}
+\newcommand{\gnewline}{\leavevmode\\}
 
 % Metavariables for argument lists.
 \newcommand{\argumentList}[1]{\metavar{{#1}s}}
@@ -110,6 +110,17 @@
 % A commonly used name for an identifier
 \newcommand{\id}{\metavar{id}}
 
+% Used for defining occurrence of phrase, with customized index entry.
+\newcommand{\IndexCustom}[2]{%
+  \leavevmode\marginpar{\ensuremath{\diamond}}\emph{#1}\index{#2}}
+
+% Used for a defining occurrence of a phrase, adding it to the index.
+\newcommand{\Index}[1]{\IndexCustom{#1}{#1}}
+
+% Same appearance, but not adding an entry to the index.
+\newcommand{\NoIndex}[1]{
+  \leavevmode\marginpar{\ensuremath{\diamond}}\emph{#1}}
+
 % ----------------------------------------------------------------------
 % Support for hash valued Location Markers
 
@@ -128,14 +139,14 @@
 \definecolor{LMdim}{gray}{1.0}
 
 % insert location marker showing hash value of following paragraph
-\newcommand{\LMHash}[1]{%
-  \hspace{0pt}\marginpar{\raisebox{0.5ex}{\miniscule{\color{LMdim}#1}}}}
+\newcommand{\LMHash}[1]{\leavevmode\marginpar{\quad%
+    \raisebox{0.5ex}{\miniscule{\color{LMdim}#1}}\vspace{-2\baselineskip}}}
 
 % support convenient renewcommand
 \let\OriginalLMHash\LMHash
 
 % define a label, and show the associated logical location marker
 \newcommand{\LMLabel}[1]{%
-  \vspace{-\baselineskip}\hspace{0pt}\OriginalLMHash{\raisebox{10ex}{#1}}%
+  \vspace{-\baselineskip}\leavevmode\OriginalLMHash{\raisebox{10ex}{#1}}%
   \label{#1}}
 % ----------------------------------------------------------------------
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index c04765f..ecc249e 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -1,4 +1,4 @@
-\documentclass{article}
+\documentclass[makeidx]{article}
 \usepackage{xspace}
 \usepackage{epsfig}
 \usepackage{color}
@@ -7,9 +7,11 @@
 \usepackage{hyperref}
 \usepackage{lmodern}
 \usepackage[T1]{fontenc}
+\usepackage{makeidx}
+\makeindex
 \title{Dart Programming Language Specification\\
 {5th edition draft}\\
-{\large Version 2.1.0-dev}}
+{\large Version 2.2.0-dev}}
 \author{}
 
 % For information about Location Markers (and in particular the
@@ -19,6 +21,9 @@
 % CHANGES
 % =======
 % Significant changes to the specification.
+% 2.2
+%  - Specify whether the values of literal expressions override Object.==.
+%  - Allow Type objects as case expressions and const map keys.
 %
 % 2.1
 % - Remove 64-bit constraint on integer literals compiled to JavaScript numbers.
@@ -67,6 +72,7 @@
 %   must imply bound satisfaction everywhere in the body.
 % - Specify that super-bounded generic type alias applications must trigger
 %   a well-boundedness check on all types occurring in the denoted type.
+% - Corrected corner case of rules for generation of noSuchMethod forwarders.
 %
 % 2.0
 % - Don't allow functions as assert test values.
@@ -189,7 +195,7 @@
 \section{Scope}
 \LMLabel{ecmaScope}
 
-\LMHash{}
+\LMHash{}%
 This Ecma standard specifies the syntax and semantics of the Dart programming language.
 It does not specify the APIs of the Dart libraries except where those library elements are essential to the correct functioning of the language itself (e.g., the existence of class \code{Object} with methods such as \code{noSuchMethod}, \code{runtimeType}).
 
@@ -197,17 +203,17 @@
 \section{Conformance}
 \LMLabel{ecmaConformance}
 
-\LMHash{}
+\LMHash{}%
 A conforming implementation of the Dart programming language must provide and support all the APIs (libraries, types, functions, getters, setters, whether top-level, static, instance or local) mandated in this specification.
 
-\LMHash{}
+\LMHash{}%
 A conforming implementation is permitted to provide additional APIs, but not additional syntax, except for experimental features in support of null-aware cascades that are likely to be introduced in the next revision of this specification.
 
 
 \section{Normative References}
 \LMLabel{ecmaNormativeReferences}
 
-\LMHash{}
+\LMHash{}%
 The following referenced documents are indispensable for the application of this document.
 For dated references, only the edition cited applies.
 For undated references, the latest edition of the referenced document (including any amendments) applies.
@@ -223,16 +229,17 @@
 \section{Terms and Definitions}
 \LMLabel{ecmaTermsAndDefinitions}
 
-\LMHash{}
+\LMHash{}%
 Terms and definitions used in this specification are given in the body of the specification proper.
-Such terms are highlighted in italics when they are introduced, e.g., `we use the term {\em verbosity} to refer to the property of excess verbiage'.
+Such terms are highlighted in italics when they are introduced, e.g., `we use the term \NoIndex{verbosity} to refer to the property of excess verbiage',
+and add a marker in the margin.
 % End Ecma Boilerplate
 
 
 \section{Notation}
 \LMLabel{notation}
 
-\LMHash{}
+\LMHash{}%
 We distinguish between normative and non-normative text.
 Normative text defines the rules of Dart.
 It is given in this font.
@@ -256,14 +263,14 @@
 \Q{Should the text at the end of the previous bullet be rationale or commentary?}
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Reserved words and built-in identifiers (\ref{identifierReference}) appear in {\bf bold}.
 
 \commentary{
 Examples would be \SWITCH{} or \CLASS{}.
 }
 
-\LMHash{}
+\LMHash{}%
 Grammar productions are given in a common variant of EBNF.
 The left hand side of a production ends with a colon.
 On the right hand side, alternation is represented by vertical bars, and sequencing by spacing.
@@ -293,32 +300,32 @@
   \alt <A\_LEXICAL\_THING>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Both syntactic and lexical productions are represented this way.
 Lexical productions are distinguished by their names.
 The names of lexical productions consist exclusively of upper case characters and underscores.
 As always, within grammatical productions, whitespace and comments between elements of the production are implicitly ignored unless stated otherwise.
 Punctuation tokens appear in quotes.
 
-\LMHash{}
+\LMHash{}%
 Productions are embedded, as much as possible, in the discussion of the constructs they represent.
 
-\LMHash{}
-A {\em term} is a syntactic construct.
+\LMHash{}%
+A \Index{term} is a syntactic construct.
 It may be considered to be a piece of text which is derivable in the grammar,
 and it may be considered to be a tree created by such a derivation.
-An {\em immediate subterm} of a given term $t$ is a syntactic construct
+An \Index{immediate subterm} of a given term $t$ is a syntactic construct
 which corresponds to an immediate subtree of $t$ considered as a derivation tree.
-A {\em subterm} of a given term $t$ is $t$,
+A \Index{subterm} of a given term $t$ is $t$,
 or an immediate subterm of $t$,
 or a subterm of an immediate subterm of $t$.
 
-\LMHash{}
+\LMHash{}%
 A list $x_1, \ldots, x_n$ denotes any list of $n$ elements of the form $x_i, 1 \le i \le n$.
 Note that $n$ may be zero, in which case the list is empty.
 We use such lists extensively throughout this specification.
 
-\LMHash{}
+\LMHash{}%
 For $j \in 1 .. n$,
 let $y_j$ be an atomic syntactic entity (like an identifier),
 $x_j$ a composite syntactic entity (like an expression or a type),
@@ -326,7 +333,7 @@
 The notation $[x_1/y_1, \ldots, x_n/y_n]E$ then denotes a copy of $E$
 in which each occurrence of $y_i, 1 \le i \le n$ has been replaced by $x_i$.
 
-\LMHash{}
+\LMHash{}%
 This operation is also known as substitution, and it is the variant that avoids capture.
 That is, when $E$ contains a construct that introduces $y_i$ into a nested scope for some $i \in 1 .. n$,
 the substitution will not replace $y_i$ in that scope.
@@ -337,11 +344,11 @@
 In short, capture freedom ensures that the ``meaning'' of each identifier is preserved during substitution.
 }
 
-\LMHash{}
+\LMHash{}%
 We sometimes abuse list or map literal syntax, writing $[o_1, \ldots, o_n]$ (respectively $\{k_1: o_1, \ldots, k_n: o_n\}$) where the $o_i$ and $k_i$ may be objects rather than expressions.
 The intent is to denote a list (respectively map) object whose elements are the $o_i$ (respectively, whose keys are the $k_i$ and values are the $o_i$).
 
-\LMHash{}
+\LMHash{}%
 The specifications of operators often involve statements such as $x$ $op$ $y$ is equivalent to the method invocation $x.op(y)$.
 Such specifications should be understood as a shorthand for:
 \begin{itemize}
@@ -354,22 +361,28 @@
 However, it is painfully verbose, and we prefer to state this rule once here, and use a concise and clear notation across the specification.
 }
 
-\LMHash{}
+\LMHash{}%
 When the specification refers to the order given in the program, it means the order of the program source code text, scanning left-to-right and top-to-bottom.
 
-\LMHash{}
-When the specification refers to a {\em fresh variable}, it means a variable with a name that doesn't occur anywhere in the current program.
+\LMHash{}%
+When the specification refers to a
+\IndexCustom{fresh variable}{variable!fresh},
+it means a variable with a name that doesn't occur anywhere
+in the current program.
 When the specification introduces a fresh variable bound to a value, the fresh variable is implicitly bound in a surrounding scope.
 
-\LMHash{}
+\LMHash{}%
 References to otherwise unspecified names of program entities (such as classes or functions) are interpreted as the names of members of the Dart core library.
 
 \commentary{
 Examples would be the classes \code{Object} and \code{Type} representing the root of the class hierarchy and the reification of run-time types respectively.
 }
 
-\LMHash{}
-When the specification says that one piece of syntax {\em is equivalent to} another piece of syntax, it means that it is equivalent in all ways, and the former syntax should generate the same compile-time errors and have the same run-time behavior as the latter, if any.
+\LMHash{}%
+When the specification says that one piece of syntax \Index{is equivalent to}
+another piece of syntax, it means that it is equivalent in all ways,
+and the former syntax should generate the same compile-time errors
+and have the same run-time behavior as the latter, if any.
 \commentary{
 Error messages, if any, should always refer to the original syntax.
 }
@@ -379,12 +392,12 @@
 \section{Overview}
 \LMLabel{overview}
 
-\LMHash{}
+\LMHash{}%
 Dart is a class-based, single-inheritance, pure object-oriented programming language.
 Dart is optionally typed (\ref{types}) and supports reified generics.
 The run-time type of every object is represented as an instance of class \code{Type} which can be obtained by calling the getter \code{runtimeType} declared in class \code{Object}, the root of the Dart class hierarchy.
 
-\LMHash{}
+\LMHash{}%
 Dart programs may be statically checked.
 Programs with compile-time errors do not have a specified dynamic semantics.
 This specification makes no attempt to answer additional questions
@@ -404,7 +417,7 @@
 this specification makes no attempt to specify exactly what that means.
 }
 
-\LMHash{}
+\LMHash{}%
 As specified in this document,
 dynamic checks are guaranteed to be performed in certain situations,
 and certain violations of the type system throw exceptions at run time.
@@ -448,8 +461,9 @@
 A future version of this specification will also specify type inference.
 }
 
-\LMHash{}
-Dart programs are organized in a modular fashion into units called {\em libraries} (\ref{librariesAndScripts}).
+\LMHash{}%
+Dart programs are organized in a modular fashion into
+units called \NoIndex{libraries} (\ref{librariesAndScripts}).
 Libraries are units of encapsulation and may be mutually recursive.
 
 \commentary{
@@ -457,7 +471,7 @@
 To get multiple copies of a library running simultaneously, one needs to spawn an isolate.
 }
 
-\LMHash{}
+\LMHash{}%
 A dart program execution may occur with assertions enabled or disabled.
 The method used to enable or disable assertions is implementation specific.
 
@@ -465,13 +479,13 @@
 \subsection{Scoping}
 \LMLabel{scoping}
 
-\LMHash{}
-A {\em namespace} is a mapping of names denoting declarations to actual declarations.
+\LMHash{}%
+A \Index{namespace} is a mapping of names denoting declarations to actual declarations.
 Let $NS$ be a namespace.
-We say that a name $n$ {\em is in }$NS$ if $n$ is a key of $NS$.
-We say a declaration $d$ {\em is in }$NS$ if a key of $NS$ maps to $d$.
+We say that a name $n$ \Index{is in} $NS$ if $n$ is a key of $NS$.
+We say a declaration $d$ \NoIndex{is in} $NS$ if a key of $NS$ maps to $d$.
 
-\LMHash{}
+\LMHash{}%
 A scope $S_0$ induces a namespace $NS_0$ that maps the simple name of each variable, type or function declaration $d$ declared in $S_0$ to $d$.
 Labels are not included in the induced namespace of a scope; instead they have their own dedicated namespace.
 
@@ -480,7 +494,7 @@
 Similarly one cannot declare a top-level function with the same name as a library variable or a class.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if there is more than one entity with the same name declared in the same scope.
 
 \commentary{
@@ -488,14 +502,14 @@
 Setters have names that are distinct from the corresponding getters because they always have an = automatically added at the end, and unary minus has the special name unary-.
 }
 
-\LMHash{}
+\LMHash{}%
 Dart is lexically scoped.
 Scopes may nest.
-A name or declaration $d$ is {\em available in scope} $S$ if $d$ is in the namespace induced by $S$ or if $d$ is available in the lexically enclosing scope of $S$.
-We say that a name or declaration $d$ is {\em in scope} if $d$ is available in the current scope.
+A name or declaration $d$ is \Index{available in scope} $S$ if $d$ is in the namespace induced by $S$ or if $d$ is available in the lexically enclosing scope of $S$.
+We say that a name or declaration $d$ is \Index{in scope} if $d$ is available in the current scope.
 
-\LMHash{}
-If a declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ {\em hides} any declaration named $n$ that is available in the lexically enclosing scope of $S$.
+\LMHash{}%
+If a declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ \Index{hides} any declaration named $n$ that is available in the lexically enclosing scope of $S$.
 
 \commentary{
 A consequence of these rules is that it is possible to hide a type with a method or variable.
@@ -509,7 +523,7 @@
 \}
 \end{dartCode}
 
-\LMHash{}
+\LMHash{}%
 Names may be introduced into a scope by declarations within the scope or by other mechanisms such as imports or inheritance.
 
 \rationale{
@@ -562,20 +576,27 @@
 \subsection{Privacy}
 \LMLabel{privacy}
 
-\LMHash{}
-Dart supports two levels of privacy: {\em public} and {\em private}.
-A declaration is {\em private} if{}f its name is private, otherwise it is {\em public}.
-A name $q$ is private if{}f any one of the identifiers that comprise $q$ is private, otherwise it is {\em public}.
-An identifier is private if{}f it begins with an underscore (the \_ character) otherwise it is {\em public}.
+\LMHash{}%
+Dart supports two levels of \Index{privacy}: public and private.
+A declaration is \IndexCustom{private}{private!declaration}
+if{}f its name is private,
+otherwise it is \IndexCustom{public}{public!declaration}.
+A name $q$ is \IndexCustom{private}{private!name}
+if{}f any one of the identifiers that comprise $q$ is private,
+otherwise it is \IndexCustom{public}{public!name}.
+An identifier is \IndexCustom{private}{private!identifier}
+if{}f it begins with an underscore (the \_ character)
+otherwise it is \IndexCustom{public}{public!identifier}.
 
-\LMHash{}
-A declaration $m$ is {\em accessible to library $L$} if $m$ is declared in $L$ or if $m$ is public.
+\LMHash{}%
+A declaration $m$ is \Index{accessible to a library} $L$
+if $m$ is declared in $L$ or if $m$ is public.
 
 \commentary{
 This means private declarations may only be accessed within the library in which they are declared.
 }
 
-\LMHash{}
+\LMHash{}%
 Privacy applies only to declarations within a library, not to library declarations themselves.
 
 \rationale{
@@ -597,12 +618,12 @@
 \subsection{Concurrency}
 \LMLabel{concurrency}
 
-\LMHash{}
+\LMHash{}%
 Dart code is always single threaded.
 There is no shared-state concurrency in Dart.
-Concurrency is supported via actor-like entities called {\em isolates}.
+Concurrency is supported via actor-like entities called \Index{isolates}.
 
-\LMHash{}
+\LMHash{}%
 An isolate is a unit of concurrency.
 It has its own memory and its own thread of control.
 Isolates communicate by message passing (\ref{sendingMessages}).
@@ -613,11 +634,12 @@
 \section{Errors and Warnings}
 \LMLabel{errorsAndWarnings}
 
-\LMHash{}
+\LMHash{}%
 This specification distinguishes between several kinds of errors.
 
-\LMHash{}
-{\em Compile-time errors} are errors that preclude execution.
+\LMHash{}%
+\IndexCustom{Compile-time errors}{compile-time error}
+are errors that preclude execution.
 A compile-time error must be reported by a Dart compiler before the erroneous code is executed.
 
 \rationale{
@@ -637,14 +659,14 @@
 It is outside the scope of this document to specify how such transformations work, and where they may be applied.
 }
 
-\LMHash{}
+\LMHash{}%
 If an uncaught compile-time error occurs within the code of a running isolate $A$, $A$ is immediately suspended.
 The only circumstance where a compile-time error could be caught would be via code run reflectively, where the mirror system can catch it.
 
 \rationale{
 Typically, once a compile-time error is thrown and $A$ is suspended, $A$ will then be terminated.
 However, this depends on the overall environment.
-A Dart engine runs in the context of an {\em embedder},
+A Dart engine runs in the context of an \Index{embedder},
 a program that interfaces between the engine and the surrounding computing environment.
 The embedder will often be a web browser, but need not be; it may be a C++ program on the server for example.
 When an isolate fails with a compile-time error as described above, control returns to the embedder, along with an exception describing the problem.
@@ -652,32 +674,37 @@
 It is then the embedder's decision whether to terminate the isolate or not.
 }
 
-\LMHash{}
-{\em Compile-time warnings} are situations that do not preclude execution,
+\LMHash{}%
+\IndexCustom{Static warnings}{static warning}
+are situations that do not preclude execution,
 but which are unlikely to be intended,
 and likely to cause bugs or inconveniences.
-A compile-time warning must be reported by a Dart compiler before the associated code is executed.
+A static warning must be reported by a Dart compiler before the associated code is executed.
 
-\LMHash{}
-When this specification says that a {\em run-time error} occurs,
+\LMHash{}%
+When this specification says that a \Index{run-time error} occurs,
 it means that a corresponding error object is thrown.
-When it says that a {\em dynamic type error} occurs,
+When it says that a \Index{dynamic type error} occurs,
 it represents a failed run-time type check,
 and the object which is thrown implements \code{TypeError}.
 
-\LMHash{}
-Whenever we say that an exception $ex$ is {\em thrown},
-it acts like an expression had {\em thrown} (\ref{completion}) with $ex$ as exception object and with a stack trace corresponding to the current system state.
-When we say that {\em a} $C$ {\em is thrown}, where $C$ is a class, we mean that an instance of class $C$ is thrown.
+\LMHash{}%
+Whenever we say that an exception $ex$ is
+\IndexCustom{thrown}{throwing an exception},
+it acts like an expression had thrown (\ref{completion})
+with $ex$ as exception object and with a stack trace
+corresponding to the current system state.
+When we say that a $C$ \IndexCustom{is thrown}{throwing a class},
+where $C$ is a class, we mean that an instance of class $C$ is thrown.
 
-\LMHash{}
+\LMHash{}%
 If an uncaught exception is thrown by a running isolate $A$, $A$ is immediately suspended.
 
 
 \section{Variables}
 \LMLabel{variables}
 
-\LMHash{}
+\LMHash{}%
 Variables are storage locations in memory.
 
 \begin{grammar}
@@ -692,7 +719,7 @@
 <varOrType> ::= \VAR{}
   \alt <type>
 
-<initializedVariableDeclaration> ::=
+<initializedVariableDeclaration> ::= \gnewline{}
   <declaredIdentifier> (`=' <expression>)? (`,' <initializedIdentifier>)*
 
 <initializedIdentifier> ::= <identifier> (`=' <expression>)?
@@ -700,7 +727,7 @@
 <initializedIdentifierList> ::= <initializedIdentifier> (`,' <initializedIdentifier>)*
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 A variable declaration that contains one or more terms of the form
 \syntax{<identifier>}
 (\commentary{i.e., a declaration that declares two or more variables})
@@ -708,7 +735,7 @@
 the same set of variable names in the same order,
 with the same type and modifiers.
 
-\LMHash{}
+\LMHash{}%
 An \syntax{<initializedVariableDeclaration>} that contains one or more terms of the form
 \syntax{<initializedIdentifier>}
 (\commentary{that is, a declaration that declares two or more initialized variables})
@@ -727,17 +754,17 @@
 \code{\STATIC{} \FINAL{} String s1; \STATIC{} \FINAL{} String s2 = "foo";}.
 }
 
-\LMHash{}
+\LMHash{}%
 In a variable declaration of one of the forms
 \code{$N$ $v$;}
 \code{$N$ $v$ = $e$;}
 where $N$ is derived from
 \syntax{<metadata> <finalConstVarOrType>},
-we say that $v$ is the {\em declaring occurrence} of the identifier.
+we say that $v$ is the \Index{declaring occurrence} of the identifier.
 For every identifier which is not a declaring occurrence,
-we say that it is an {\em referencing occurrence}.
+we say that it is an \Index{referencing occurrence}.
 We also abbreviate that to say that an identifier is
-a {\em declaring identifier} respectively an {\em referencing identifier}.
+a \Index{declaring identifier} respectively an \Index{referencing identifier}.
 
 \commentary{
 In an expression of the form \code{$e$.\id} it is possible that
@@ -746,42 +773,49 @@
 but in this situation \id{} is still a referencing identifier.
 }
 
-\LMHash{}
-An {\em initializing variable declaration}
+\LMHash{}%
+An \Index{initializing variable declaration}
 is a variable declaration whose declaring identifier is
-immediately followed by `\code{=}' and an {\em initializing expression}.
+immediately followed by `\code{=}' and an \Index{initializing expression}.
 
-\LMHash{}
-A variable declared at the top-level of a library is referred to as either a {\em library variable} or a top-level variable.
+\LMHash{}%
+A variable declared at the top-level of a library is referred to as either a
+\IndexCustom{library variable}{variable!library} or a
+\IndexCustom{top-level variable}{variable!top-level}.
 
-\LMHash{}
-A {\em static variable} is a variable that is not associated with a particular instance, but rather with an entire library or class.
+\LMHash{}%
+A \IndexCustom{static variable}{variable!static}
+is a variable that is not associated with a particular instance,
+but rather with an entire library or class.
 Static variables include library variables and class variables.
 Class variables are variables whose declaration is immediately nested inside a class declaration and includes the modifier \STATIC{}.
 A library variable is implicitly static.
 It is a compile-time error to preface a top-level variable declaration with the built-in identifier (\ref{identifierReference}) \STATIC{}.
 
-\LMHash{}
-A {\em constant variable} is a variable whose declaration includes the modifier \CONST{}.
+\LMHash{}%
+A \IndexCustom{constant variable}{variable!constant}
+is a variable whose declaration includes the modifier \CONST{}.
 A constant variable must be initialized to a constant expression (\ref{constants}) or a compile-time error occurs.
 
-\LMHash{}
-A {\em final variable} is a variable whose binding is fixed upon initialization;
+\LMHash{}%
+A \IndexCustom{final variable}{variable!final}
+is a variable whose binding is fixed upon initialization;
 a final variable $v$ will always refer to the same object after $v$ has been initialized.
 A variable is final if{}f its declaration includes the modifier \FINAL{} or the modifier \CONST{}.
 
-\LMHash{}
-A {\em mutable variable} is a variable which is not final.
+\LMHash{}%
+A \IndexCustom{mutable variable}{variable!mutable}
+is a variable which is not final.
 
 %% Note that the following relies on the assumption that inference has
 %% already taken place, including member signature inference. For instance,
 %% if `var x;` is an instance variable declaration that overrides `T get x;`
 %% then we treat `var x;` as if it had been `T x;`.
 
-\LMHash{}
+\LMHash{}%
 The following rules apply to all static and instance variables.
 
-\LMHash{}
+\LMHash{}%
 A variable declaration of one of the forms
 \code{$T$ $v$;}
 \code{$T$ $v$ = $e$;}
@@ -794,7 +828,7 @@
 (\ref{evaluationOfImplicitVariableGetters}).
 In these cases the static type of $v$ is $T$.
 
-\LMHash{}
+\LMHash{}%
 A variable declaration of one of the forms
 \code{\VAR{} $v$;}
 \code{\VAR{} $v$ = $e$;}
@@ -813,7 +847,7 @@
 In these cases, the static type of $v$ is \DYNAMIC{}
 (\ref{typeDynamic}).
 
-\LMHash{}
+\LMHash{}%
 A mutable variable declaration of the form
 \code{{} $T$ $v$;}
 or \code{$T$ $v$ = $e$;}
@@ -821,7 +855,7 @@
 \code{\VOID{} \SET{} $v$=($T$ $x$)}
 whose execution sets the value of $v$ to the incoming argument $x$.
 
-\LMHash{}
+\LMHash{}%
 A mutable variable declaration of the form
 \code{\VAR{} $v$;}
 or \code{\VAR{} $v$ = $e$;}
@@ -829,20 +863,20 @@
 \code{\VOID{} \SET{} $v$=(\DYNAMIC{} $x$)}
 whose execution sets the value of $v$ to the incoming argument $x$.
 
-\LMHash{}
+\LMHash{}%
 The scope into which the implicit getters and setters are introduced depends on the kind of variable declaration involved.
 
-\LMHash{}
+\LMHash{}%
 A library variable introduces a getter into the top level scope of the enclosing library.
 A static class variable introduces a static getter into the immediately enclosing class.
 An instance variable introduces an instance getter into the immediately enclosing class.
 
-\LMHash{}
+\LMHash{}%
 A mutable library variable introduces a setter into the top level scope of the enclosing library.
 A mutable static class variable introduces a static setter into the immediately enclosing class.
 A mutable instance variable introduces an instance setter into the immediately enclosing class.
 
-\LMHash{}
+\LMHash{}%
 Let $v$ be variable declared in an initializing variable declaration,
 and let $e$ be the associated initializing expression.
 It is a compile-time error if the static type of $e$ is not assignable to the declared type of $v$.
@@ -869,11 +903,11 @@
 but if there is no setter it will cause a dynamic error.
 }
 
-\LMHash{}
+\LMHash{}%
 A variable that has no initializing expression has the null object (\ref{null}) as its initial value.
 Otherwise, variable initialization proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 Static variable declarations with an initializing expression are initialized lazily
 (\ref{evaluationOfImplicitVariableGetters}).
 
@@ -888,7 +922,7 @@
 (\ref{initializerLists}).
 }
 
-\LMHash{}
+\LMHash{}%
 Initialization of an instance variable $v$
 with an initializing expression $e$
 proceeds as follows:
@@ -911,7 +945,7 @@
 will throw.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a dynamic type error if $o$ is not the null object (\ref{null})
 and the dynamic type of $o$ is not
 a subtype of the actual type of the variable $v$
@@ -921,7 +955,7 @@
 \subsection{Evaluation of Implicit Variable Getters}
 \LMLabel{evaluationOfImplicitVariableGetters}
 
-\LMHash{}
+\LMHash{}%
 Let $d$ be the declaration of a static or instance variable $v$.
 If $d$ is an instance variable,
 then the invocation of the implicit getter of $v$ evaluates to
@@ -973,11 +1007,12 @@
 \section{Functions}
 \LMLabel{functions}
 
-\LMHash{}
+\LMHash{}%
 Functions abstract over executable actions.
 
 \begin{grammar}
-<functionSignature> ::= <metadata> <returnType>? <identifier> <formalParameterPart>
+<functionSignature> ::= \gnewline{}
+  <metadata> <returnType>? <identifier> <formalParameterPart>
 
 <formalParameterPart> ::= <typeParameters>? <formalParameterList>
 
@@ -990,7 +1025,7 @@
 <block> ::= `{' <statements> `}'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Functions can be introduced by function declarations (\ref{functionDeclarations}),
 method declarations (\ref{instanceMethods}, \ref{staticMethods}),
 getter declarations (\ref{getters}),
@@ -998,7 +1033,7 @@
 and constructor declarations (\ref{constructors});
 and they can be introduced by function literals (\ref{functionExpressions}).
 
-\LMHash{}
+\LMHash{}%
 Each declaration that introduces a function has a signature that specifies its return type, name, and formal parameter part,
 except that the return type may be omitted, and getters never have a formal parameter part.
 Function literals have a formal parameter part, but no return type and no name.
@@ -1033,20 +1068,22 @@
   \end{itemize}
 \end{itemize}
 
-\LMHash{}
-A function is {\em asynchronous} if its body is marked with the \ASYNC{} or \code{\ASYNC*} modifier.
-Otherwise the function is {\em synchronous}.
-A function is a {\em generator} if its body is marked with the \code{\SYNC*} or \code{\ASYNC*} modifier.
+\LMHash{}%
+A function is \IndexCustom{asynchronous}{function!asynchronous}
+if its body is marked with the \ASYNC{} or \code{\ASYNC*} modifier.
+Otherwise the function is \IndexCustom{synchronous}{function!synchronous}.
+A function is a \IndexCustom{generator}{function!generator}
+if its body is marked with the \code{\SYNC*} or \code{\ASYNC*} modifier.
 
 \commentary{
 Whether a function is synchronous or asynchronous is orthogonal to whether it is a generator or not.
 Generator functions are a sugar for functions that produce collections in a systematic way,
-by lazily applying a function that {\em generates} individual elements of a collection.
+by lazily applying a function that \emph{generates} individual elements of a collection.
 Dart provides such a sugar in both the synchronous case, where one returns an iterable, and in the asynchronous case, where one returns a stream.
 Dart also allows both synchronous and asynchronous functions that produce a single value.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if an \ASYNC, \code{\ASYNC*} or \code{\SYNC*} modifier is attached to the body of a setter or constructor.
 
 \rationale{
@@ -1065,7 +1102,7 @@
 This situation is very unusual so it is not worth making an exception to the general rule for constructors in order to allow it.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the declared return type of a function marked \ASYNC{} is not a supertype of \code{Future<$T$>} for some type $T$.
 It is a compile-time error if the declared return type of a function marked \code{\SYNC*} is not a supertype of \code{Iterable<$T$>} for some type $T$.
 It is a compile-time error if the declared return type of a function marked \code{\ASYNC*} is not a supertype of \code{Stream<$T$>} for some type $T$.
@@ -1074,60 +1111,69 @@
 \subsection{Function Declarations}
 \LMLabel{functionDeclarations}
 
-\LMHash{}
-A {\em function declaration} is a function that is neither a member of a class nor a function literal.
-Function declarations include {\em library functions}, which are function declarations
+\LMHash{}%
+A \Index{function declaration} is a function that is neither a member of a class nor a function literal.
+Function declarations include exactly the following:
+\IndexCustom{library functions}{function!library},
+which are function declarations
 %(including getters and setters)
-at the top level of a library, and {\em local functions}, which are function declarations declared inside other functions.
+at the top level of a library, and
+\IndexCustom{local functions}{function!local},
+which are function declarations declared inside other functions.
 Library functions are often referred to simply as top-level functions.
 
-\LMHash{}
+\LMHash{}%
 A function declaration consists of an identifier indicating the function's name, possibly prefaced by a return type.
 The function name is followed by a signature and body.
 For getters, the signature is empty.
 The body is empty for functions that are external.
 
-\LMHash{}
+\LMHash{}%
 The scope of a library function is the scope of the enclosing library.
 The scope of a local function is described in section \ref{localFunctionDeclaration}.
 In both cases, the name of the function is in scope in its formal parameter scope (\ref{formalParameters}).
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error to preface a function declaration with the built-in identifier \STATIC{}.
 
-\LMHash{}
-When we say that a function $f_1$ {\em forwards} to another function $f_2$, we mean that invoking $f_1$ causes $f_2$ to be executed with the same arguments and/or receiver as $f_1$, and returns the result of executing $f_2$ to the caller of $f_1$, unless $f_2$ throws an exception, in which case $f_1$ throws the same exception.
+\LMHash{}%
+When we say that a function $f_1$ \Index{forwards} to another function $f_2$, we mean that invoking $f_1$ causes $f_2$ to be executed with the same arguments and/or receiver as $f_1$, and returns the result of executing $f_2$ to the caller of $f_1$, unless $f_2$ throws an exception, in which case $f_1$ throws the same exception.
 Furthermore, we only use the term for synthetic functions introduced by the specification.
 
 
 \subsection{Formal Parameters}
 \LMLabel{formalParameters}
 
-\LMHash{}
-Every non-getter function declaration includes a {\em formal parameter list},
+\LMHash{}%
+Every non-getter function declaration includes a \Index{formal parameter list},
 which consists of a list of required positional parameters (\ref{requiredFormals}),
 followed by any optional parameters (\ref{optionalFormals}).
 The optional parameters may be specified either as a set of named parameters or as a list of positional parameters, but not both.
 
-\LMHash{}
-Some function declarations include a {\em formal type parameter list} (\ref{functions}),
-in which case we say that it is a {\em generic function}.
-A {\em non-generic function} is a function which is not generic.
+\LMHash{}%
+Some function declarations include a
+\Index{formal type parameter list} (\ref{functions}),
+in which case we say that it is a
+\IndexCustom{generic function}{function!generic}.
+A \IndexCustom{non-generic function}{function!non-generic}
+is a function which is not generic.
 
-\LMHash{}
-The {\em formal parameter part} of a function declaration consists of the formal type parameter list, if any, and the formal parameter list.
+\LMHash{}%
+The \Index{formal parameter part} of a function declaration consists of the formal type parameter list, if any, and the formal parameter list.
 
 \commentary{
 The following kinds of functions cannot be generic:
 Getters, setters, operators, and constructors.
 }
 
-\LMHash{}
-The formal type parameter list of a function declaration introduces a new scope known as the function's {\em type parameter scope}.
+\LMHash{}%
+The formal type parameter list of a function declaration introduces
+a new scope known as the function's
+\IndexCustom{type parameter scope}{scope!type parameter}.
 The type parameter scope of a generic function $f$ is enclosed in the scope where $f$ is declared.
 Every formal type parameter introduces a type into the type parameter scope.
 
-\LMHash{}
+\LMHash{}%
 If it exists, the type parameter scope of a function $f$ is the current scope for the signature of $f$, and for the formal type parameter list itself;
 otherwise the scope where $f$ is declared is the current scope for the signature of $f$.
 
@@ -1142,8 +1188,9 @@
 \code{class D<X \EXTENDS{} Y, Y> \{ \ldots{} \}}.
 }
 
-\LMHash{}
-The formal parameter list of a function declaration introduces a new scope known as the function's {\em formal parameter scope}.
+\LMHash{}%
+The formal parameter list of a function declaration introduces a new scope known as the function's
+\IndexCustom{formal parameter scope}{scope!formal parameter}.
 The formal parameter scope of a non-generic function $f$ is enclosed in the scope where $f$ is declared.
 The formal parameter scope of a generic function $f$ is enclosed in the type parameter scope of $f$.
 Every formal parameter introduces a local variable into the formal parameter scope.
@@ -1155,8 +1202,9 @@
 but the formal parameters are not in scope in the signature.
 }
 
-\LMHash{}
-The body of a function declaration introduces a new scope known as the function's {\em body scope}.
+\LMHash{}%
+The body of a function declaration introduces a new scope known as the function's
+\IndexCustom{body scope}{scope!function body}.
 The body scope of a function $f$ is enclosed in the scope introduced by the formal parameter scope of $f$.
 
 %The formal parameter scope of a function maps the name of each formal parameter $p$ to the value $p$ is bound to.
@@ -1164,7 +1212,7 @@
 % The formal parameters of a function are processed in the enclosing scope of the function.
 % \commentary{this means that the parameters themselves may not be referenced within the formal parameter list.}
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a formal parameter is declared as a constant variable (\ref{variables}).
 
 \begin{grammar}
@@ -1173,14 +1221,17 @@
   \alt `(' <normalFormalParameters> `,' <optionalFormalParameters> `)'
   \alt `(' <optionalFormalParameters> `)'
 
-<normalFormalParameters> ::= <normalFormalParameter> (`,' <normalFormalParameter>)*
+<normalFormalParameters> ::= \gnewline{}
+  <normalFormalParameter> (`,' <normalFormalParameter>)*
 
 <optionalFormalParameters> ::= <optionalPositionalFormalParameters>
   \alt <namedFormalParameters>
 
-<optionalPositionalFormalParameters> ::= `[' <defaultFormalParameter> (`,' <defaultFormalParameter>)* `,'? `]'
+<optionalPositionalFormalParameters> ::= \gnewline{}
+  `[' <defaultFormalParameter> (`,' <defaultFormalParameter>)* `,'? `]'
 
-<namedFormalParameters> ::= `{' <defaultNamedParameter> (`,' <defaultNamedParameter>)* `,'? `}'
+<namedFormalParameters> ::= \gnewline{}
+  `{' <defaultNamedParameter> (`,' <defaultNamedParameter>)* `,'? `}'
 \end{grammar}
 
 Formal parameter lists allow an optional trailing comma after the last parameter (\syntax{`,'?}).
@@ -1191,8 +1242,8 @@
 \subsubsection{Required Formals}
 \LMLabel{requiredFormals}
 
-\LMHash{}
-A {\em required formal parameter} may be specified in one of three ways:
+\LMHash{}%
+A \Index{required formal parameter} may be specified in one of three ways:
 \begin{itemize}
 \item By means of a function signature that names the parameter and describes its type as a function type (\ref{functionTypes}).
 It is a compile-time error if any default values are specified in the signature of such a function type.% explain what the type is in this case? Where is this described in general?
@@ -1205,16 +1256,18 @@
   \alt <fieldFormalParameter>
   \alt <simpleFormalParameter>
 
-<functionFormalParameter> ::= <metadata> \COVARIANT{}? <returnType>? <identifier>
-  \gnewline{} <formalParameterPart>
+<functionFormalParameter> ::= \gnewline{}
+  <metadata> \COVARIANT{}? <returnType>? <identifier> <formalParameterPart>
 
-<simpleFormalParameter> ::= <metadata> \COVARIANT{}? <finalConstVarOrType>? <identifier>
+<simpleFormalParameter> ::= \gnewline{}
+  <metadata> \COVARIANT{}? <finalConstVarOrType>? <identifier>
 
-<fieldFormalParameter> ::= <metadata> <finalConstVarOrType>? \THIS{} `.' <identifier>
-  \gnewline{} <formalParameterPart>?
+<fieldFormalParameter> ::= \gnewline{}
+  <metadata> <finalConstVarOrType>? \THIS{} `.' <identifier> \gnewline{}
+  <formalParameterPart>?
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 It is possible to include the modifier \COVARIANT{} in some forms of parameter declarations.
 This modifier has no effect.
 
@@ -1223,14 +1276,14 @@
 The modifier is allowed here even though it has no effect, such that source code can be used in both contexts.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the modifier \COVARIANT{} occurs on a parameter of a function which is not an instance method, instance setter, or instance operator.
 
 
 \subsubsection{Optional Formals}
 \LMLabel{optionalFormals}
 
-\LMHash{}
+\LMHash{}%
 Optional parameters may be specified and provided with default values.
 
 \begin{grammar}
@@ -1240,18 +1293,17 @@
   \alt <normalFormalParameter> ( `:' <expression>)?
 \end{grammar}
 
-A \syntax{<defaultNamedParameter>} of the form
-\syntax{<normalFormalParameter> `:' <expression>}
-is equivalent to one of the form:
+The form \syntax{<normalFormalParameter> `:' <expression>}
+is equivalent to the form
 \syntax{<normalFormalParameter> `=' <expression>}.
 The colon-syntax is included only for backwards compatibility.
 It is deprecated and will be removed in a later version of the language specification.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the default value of an optional parameter is not a constant expression (\ref{constants}).
 If no default is explicitly specified for an optional parameter an implicit default of \NULL{} is provided.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the name of a named optional parameter begins with an `_' character.
 
 \rationale{
@@ -1265,12 +1317,12 @@
 \subsection{Type of a Function}
 \LMLabel{typeOfAFunction}
 
-\LMHash{}
+\LMHash{}%
 If a function declaration does not declare a return type explicitly, its return type is \DYNAMIC{} (\ref{typeDynamic}),
 unless it is a constructor function, in which case its return type is the immediately enclosing class,
 or it is a setter or operator \code{[]=}, in which case its return type is \VOID{}.
 
-\LMHash{}
+\LMHash{}%
 A function declaration may declare formal type parameters.
 The type of the function includes the names of the type parameters and their upper bounds.
 When consistent renaming of type parameters can make two function types identical,
@@ -1282,11 +1334,11 @@
 This treatment of names is also known as alpha-equivalence.
 }
 
-\LMHash{}
+\LMHash{}%
 In the following three paragraphs,
 if the number $m$ of formal type parameters is zero then the type parameter list in the function type should be omitted.
 
-\LMHash{}
+\LMHash{}%
 Let $F$ be a function with
 formal type parameters $X_1\ B_1, \ldots,\ X_m\ B_m$,
 required formal parameters $T_1\ p_1, \ldots,\ T_n\ p_n$,
@@ -1295,7 +1347,7 @@
 Then the type of $F$ is
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n$) $ \rightarrow T_0$}.
 
-\LMHash{}
+\LMHash{}%
 Let $F$ be a function with
 formal type parameters $X_1\ B_1, \ldots,\ X_m\ B_m$,
 required formal parameters $T_1\ p_1, \ldots,\ T_n\ p_n$,
@@ -1305,7 +1357,7 @@
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ [$T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}$]) $ \rightarrow T_0$}.
 
-\LMHash{}
+\LMHash{}%
 Let $F$ be a function with
 formal type parameters $X_1\ B_1, \ldots,\ X_m\ B_m$,
 required formal parameters $T_1\ p_1, \ldots,\ T_n\ p_n$,
@@ -1315,7 +1367,7 @@
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ \{$T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}$\}) $ \rightarrow T_0$}.
 
-\LMHash{}
+\LMHash{}%
 The run-time type of a function object always implements the class \FUNCTION{}.
 
 \commentary{
@@ -1334,8 +1386,9 @@
 \subsection{External Functions}
 \LMLabel{externalFunctions}
 
-\LMHash{}
-An {\em external function} is a function whose body is provided separately from its declaration.
+\LMHash{}%
+An \IndexCustom{external function}{function!external}
+is a function whose body is provided separately from its declaration.
 An external function may be a top-level function (\ref{librariesAndScripts}), a method (\ref{instanceMethods}, \ref{staticMethods}), a getter (\ref{getters}), a setter (\ref{setters}) or a non-redirecting constructor (\ref{generativeConstructors}, \ref{factories}).
 External functions are introduced via the built-in identifier \EXTERNAL{} (\ref{identifierReference}) followed by the function signature.
 
@@ -1345,22 +1398,24 @@
 
 \commentary{
 Examples of external functions might be foreign functions (defined in C, or Javascript etc.), primitives of the implementation (as defined by the Dart run-time system), or code that was dynamically generated but whose interface is statically known.
-However, an abstract method is different from an external function, as it has {\em no} body.
+However, an abstract method is different from an external function,
+as it has \emph{no} body.
 }
 
-\LMHash{}
+\LMHash{}%
 An external function is connected to its body by an implementation specific mechanism.
 Attempting to invoke an external function that has not been connected to its body will throw a \code{NoSuchMethodError} or some subclass thereof.
 
-\LMHash{}
+\LMHash{}%
 The actual syntax is given in sections \ref{classes} and \ref{librariesAndScripts} below.
 
 
 \section{Classes}
 \LMLabel{classes}
 
-\LMHash{}
-A {\em class} defines the form and behavior of a set of objects which are its {\em instances}.
+\LMHash{}%
+A \Index{class} defines the form and behavior of a set of objects which are its
+\IndexCustom{instances}{instance}.
 Classes may be defined by class declarations as described below, or via mixin applications (\ref{mixinApplication}).
 
 \begin{grammar}
@@ -1396,12 +1451,13 @@
   \alt \FINAL{} <type>? <initializedIdentifierList>
   \alt (\STATIC{} | \COVARIANT{})? (\VAR{} | <type>) <initializedIdentifierList>
 
-<staticFinalDeclarationList> ::= <staticFinalDeclaration> (`,' <staticFinalDeclaration>)*
+<staticFinalDeclarationList> ::= \gnewline{}
+  <staticFinalDeclaration> (`,' <staticFinalDeclaration>)*
 
 <staticFinalDeclaration> ::= <identifier> `=' <expression>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 It is possible to include the modifier \COVARIANT{} in some forms of declarations.
 This modifier has no effect.
 
@@ -1410,36 +1466,47 @@
 The modifier is allowed here even though it has no effect, such that source code can be used in both contexts.
 }
 
-\LMHash{}
+\LMHash{}%
 A class has constructors, instance members and static members.
-The instance members of a class are its instance methods, getters, setters and instance variables.
-The static members of a class are its static methods, getters, setters and class variables.
-The members of a class are its static and instance members.
+The \IndexCustom{instance members}{members!instance} of a class
+are its instance methods, getters, setters and instance variables.
+The \IndexCustom{static members}{members!static} of a class
+are its static methods, getters, setters and class variables.
+The \IndexCustom{members}{members} of a class
+are its static and instance members.
 
-\LMHash{}
+\LMHash{}%
 A class has several scopes:
 \begin{itemize}
-\item A {\em type-parameter scope}, which is empty if the class is not generic (\ref{generics}).
+\item A \IndexCustom{type-parameter scope}{scope!type parameter},
+  which is empty if the class is not generic (\ref{generics}).
 The enclosing scope of the type-parameter scope of a class is the enclosing scope of the class declaration.
-\item A {\em static scope}.
+\item A \IndexCustom{static scope}{scope!static}.
 The enclosing scope of the static scope of a class is the type parameter scope (\ref{generics}) of the class.
-\item An {\em instance scope}.
+\item An \IndexCustom{instance scope}{scope!instance}.
 The enclosing scope of a class' instance scope is the class' static scope.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 The enclosing scope of an instance member declaration is the instance scope of the class in which it is declared.
 
-\LMHash{}
+\LMHash{}%
 The enclosing scope of a static member declaration is the static scope of the class in which it is declared.
 
-\LMHash{}
+\LMHash{}%
 Every class has a single superclass except class \code{Object} which has no superclass.
 A class may implement a number of interfaces by declaring them in its implements clause (\ref{superinterfaces}).
 
-\LMHash{}
-An {\em abstract class} is a class that is explicitly declared with the \ABSTRACT{} modifier, either by means of a class declaration or via a type alias (\ref{typedef}) for a mixin application (\ref{mixinApplication}).
-A {\em concrete class} is a class that is not abstract.
+\LMHash{}%
+An \IndexCustom{abstract class declaration}{class declaration!abstract}
+is a class declaration that is explicitly declared
+with the \ABSTRACT{} modifier.
+A \IndexCustom{concrete class declaration}{class declaration!concrete}
+is a class declaration that is not abstract.
+An \IndexCustom{abstract class}{class!abstract} is a class
+whose declaration is abstract, and
+a \IndexCustom{concrete class}{class!concrete} is a class
+whose declaration is concrete.
 
 \rationale{
 We want different behavior for concrete classes and abstract classes.
@@ -1447,8 +1514,8 @@
 In contrast, if $A$ is intended to be concrete, the checker should warn about all unimplemented methods, but allow clients to instantiate it freely.
 }
 
-\LMHash{}
-The {\em interface of class $C$} is an implicit interface that declares instance members that correspond to the instance members declared by $C$, and whose direct superinterfaces are the direct superinterfaces of $C$ (\ref{superinterfaces}).
+\LMHash{}%
+The \Index{interface of a class} $C$ is an implicit interface that declares instance members that correspond to the instance members declared by $C$, and whose direct superinterfaces are the direct superinterfaces of $C$ (\ref{superinterfaces}).
 When a class name appears as a type, that name denotes the interface of the class.
 
 % making an exception for the setters generated for final fields is tempting but problematic.
@@ -1465,7 +1532,9 @@
 
 \commentary{
 Here are simple examples, that illustrate the difference between ``has a member'' and ``declares a member''.
-For example, \code{B} {\em declares} one member named \code{f}, but {\em has} two such members.
+For example, \code{B} \IndexCustom{declares}{declares member}
+ one member named \code{f},
+but \IndexCustom{has}{has member} two such members.
 The rules of inheritance determine what members a class has.
 }
 
@@ -1486,7 +1555,7 @@
 \}
 \end{dartCode}
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a class named $C$ declares
 a member with basename (\ref{classMemberConflicts}) $C$.
 If a generic class named $G$ declares a type variable named $X$,
@@ -1499,19 +1568,23 @@
 \subsection{Instance Methods}
 \LMLabel{instanceMethods}
 
-\LMHash{}
+\LMHash{}%
 Instance methods are functions (\ref{functions}) whose declarations are immediately contained within a class declaration and that are not declared \STATIC{}.
 The instance methods of a class $C$ are those instance methods declared by $C$ and the instance methods inherited by $C$ from its superclass.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if an instance method $m_1$ overrides (\ref{inheritanceAndOverriding}) an instance member $m_2$ and $m_1$ has a greater number of required parameters than $m_2$.
 It is a compile-time error if an instance method $m_1$ overrides an instance member $m_2$ and $m_1$ has fewer positional parameters than $m_2$.
 It is a compile-time error if an instance method $m_1$ overrides an instance member $m_2$ and $m_1$ does not declare all the named parameters declared by $m_2$.
 
-\LMHash{}
+\LMHash{}%
 %% TODO(eernst): We need to use the concept of 'correctly overrides' rather than 'is a subtype of', e.g., to treat `void` correctly.
 It is a compile-time error if an instance method $m_1$ overrides an instance member $m_2$ and the type of $m_1$ is not a subtype of the type of $m_2$.
-It is a compile-time warning if an instance method $m_1$ overrides an instance member $m_2$, the signature of $m_2$ explicitly specifies a default value for a formal parameter $p$, and the signature of $m_1$ implies a different default value for $p$.
+It is a static warning if
+an instance method $m_1$ overrides an instance member $m_2$,
+the signature of $m_2$ explicitly specifies a default value
+for a formal parameter $p$, and
+the signature of $m_1$ implies a different default value for $p$.
 
 \commentary{
 A method declaration may conflict with other declarations
@@ -1522,11 +1595,12 @@
 \subsubsection{Operators}
 \LMLabel{operators}
 
-\LMHash{}
-{\em Operators} are instance methods with special names.
+\LMHash{}%
+\IndexCustom{Operators}{operators} are instance methods with special names.
 
 \begin{grammar}
-<operatorSignature> ::= <returnType>? \OPERATOR{} <operator> <formalParameterList>
+<operatorSignature> ::= \gnewline{}
+  <returnType>? \OPERATOR{} <operator> <formalParameterList>
 
 <operator> ::= `~'
   \alt <binaryOperator>
@@ -1541,10 +1615,10 @@
   \alt <bitwiseOperator>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 An operator declaration is identified using the built-in identifier (\ref{identifierReference}) \OPERATOR{}.
 
-\LMHash{}
+\LMHash{}%
 The following names are allowed for user-defined operators:
 \syntax{`<'},
 \syntax{`>'},
@@ -1567,7 +1641,7 @@
 \syntax{`[]'},
 \syntax{`~'}.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the arity of the user-declared operator
 \syntax{`[]='} is not 2.
 It is a compile-time error if the arity of a user-declared operator with one of the names:
@@ -1601,23 +1675,23 @@
 If it has an argument, it denotes binary subtraction.
 }
 
-\LMHash{}
+\LMHash{}%
 The name of the unary operator \syntax{`-'} is \code{unary-}.
 
 \rationale{
 This device allows the two methods to be distinguished for purposes of method lookup, override and reflection.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the arity of the user-declared operator
 \syntax{`~'}
 is not 0.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error to declare an optional parameter in an operator.
 
-\LMHash{}
-It is a compile-time warning if the return type of a user-declared operator
+\LMHash{}%
+It is a static warning if the return type of a user-declared operator
 \syntax{`[]='}
 is explicitly declared and not \VOID{}.
 
@@ -1646,7 +1720,7 @@
 \subsubsection{The Method \code{noSuchMethod}}
 \LMLabel{theMethodNoSuchMethod}
 
-\LMHash{}
+\LMHash{}%
 The method \code{noSuchMethod} is invoked implicitly during execution
 in situations where one or more member lookups fail
 (\ref{ordinaryInvocation},
@@ -1677,8 +1751,8 @@
 as explained below.
 }
 
-\LMHash{}
-We say that a class $C$ {\em has a non-trivial \code{noSuchMethod}}
+\LMHash{}%
+We say that a class $C$ \Index{has a non-trivial \code{noSuchMethod}}
 if $C$ has a concrete member named \code{noSuchMethod}
 which is distinct from the one declared in the built-in class \code{Object}.
 
@@ -1717,10 +1791,10 @@
 \}
 \end{dartCode}
 
-\LMHash{}
+\LMHash{}%
 Let $C$ be a concrete class and
 let $L$ be the library that contains the declaration of $C$.
-The member $m$ is {\em noSuchMethod forwarded in} $C$ if{}f
+The member $m$ is \Index{noSuchMethod forwarded} in $C$ if{}f
 one of the following is true:
 
 \begin{itemize}
@@ -1740,10 +1814,11 @@
   a concrete declaration of $m$ accessible to $L_2$.
 \end{itemize}
 
-\LMHash{}
-For a concrete class $C$, a {\em \code{noSuchMethod} forwarder}
+\LMHash{}%
+For a concrete class $C$, a
+\IndexCustom{\code{noSuchMethod} forwarder}{noSuchMethod forwarder}
 is implicitly induced for each member $m$
-which is \code{noSuchMethod} forwarded.
+which is noSuchMethod forwarded.
 This is a concrete member of $C$
 with the signature taken from the interface of $C$ respectively $D$ above,
 and with the same default value for each optional parameter.
@@ -1792,11 +1867,11 @@
 because compilers control the treatment of private names.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a concrete class $C$ has
 a \code{noSuchMethod} forwarded method signature $S$
 for a method named $m$,
-and a superclass of $C$ has a concrete declaration of $m$
+and a superclass of $C$ has an accessible concrete declaration of $m$
 which is not a \code{noSuchMethod} forwarder.
 
 \commentary{
@@ -1846,7 +1921,7 @@
 and hence there is no error in that situation.
 }
 
-\LMHash{}
+\LMHash{}%
 For the dynamic semantics,
 assume that a class $C$ has an implicitly induced
 \code{noSuchMethod} forwarder named $m$,
@@ -1866,7 +1941,7 @@
 because the former is covered by $m = 0$.
 }
 
-\LMHash{}
+\LMHash{}%
 The execution of the body of $m$ creates
 an instance $im$ of the predefined class \code{Invocation}
 such that:
@@ -1888,7 +1963,7 @@
   \code{<Type>[$X_1, \ldots,\ X_r$]}.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Next, \code{noSuchMethod} is invoked with $i$ as the actual argument,
 and the result obtained from there is returned by the execution of $m$.
 
@@ -1938,23 +2013,23 @@
 \subsection{Getters}
 \LMLabel{getters}
 
-\LMHash{}
+\LMHash{}%
 Getters are functions (\ref{functions}) that are used to retrieve the values of object properties.
 
 \begin{grammar}
 <getterSignature> ::= <returnType>? \GET{} <identifier>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 If no return type is specified, the return type of the getter is \DYNAMIC{}.
 
-\LMHash{}
+\LMHash{}%
 A getter definition that is prefixed with the \STATIC{} modifier defines a static getter.
 Otherwise, it defines an instance getter.
 The name of the getter is given by the identifier in the definition.
 The effect of a static getter declaration in class $C$ is to add an instance getter with the same name and signature to the \code{Type} object for class $C$ that forwards (\ref{functionDeclarations}) to the static getter.
 
-\LMHash{}
+\LMHash{}%
 The instance getters of a class $C$ are those instance getters declared by $C$, either implicitly or explicitly, and the instance getters inherited by $C$ from its superclass.
 The static getters of a class $C$ are those static getters declared by $C$.
 
@@ -1965,7 +2040,7 @@
 and a method can never override a getter or an instance variable.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a getter $m_1$ overrides (\ref{inheritanceAndOverriding}) a getter $m_2$
 and the return type of $m_1$ is not a subtype of the return type of $m_2$.
 
@@ -1973,7 +2048,7 @@
 \subsection{Setters}
 \LMLabel{setters}
 
-\LMHash{}
+\LMHash{}%
 Setters are functions (\ref{functions}) that are used to set the values of object properties.
 
 \begin{grammar}
@@ -1984,7 +2059,7 @@
 If no return type is specified, the return type of the setter is \VOID{} (\ref{typeOfAFunction}).
 }
 
-\LMHash{}
+\LMHash{}%
 A setter definition that is prefixed with the \STATIC{} modifier defines a static setter.
 Otherwise, it defines an instance setter.
 The name of a setter is obtained by appending the string `=' to the identifier given in its signature.
@@ -1994,21 +2069,21 @@
 Hence, a setter name can never conflict with, override or be overridden by a getter or method.
 }
 
-\LMHash{}
+\LMHash{}%
 The instance setters of a class $C$ are those instance setters declared by $C$ either implicitly or explicitly, and the instance setters inherited by $C$ from its superclass.
 The static setters of a class $C$ are those static setters declared by $C$.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a setter's formal parameter list does not consist of exactly one required formal parameter $p$.
 \rationale{
 We could enforce this via the grammar, but we'd have to specify the evaluation rules in that case.
 }
 
-\LMHash{}
-It is a compile-time warning if a setter declares a return type other than \VOID{}.
+\LMHash{}%
+It is a static warning if a setter declares a return type other than \VOID{}.
 It is a compile-time error if a setter $m_1$ overrides (\ref{inheritanceAndOverriding}) a setter $m_2$
 and the parameter type of $m_1$ is not a supertype of the parameter type of $m_2$.
-It is a compile-time warning if a class has
+It is a static warning if a class has
 a setter named $v=$ with argument type $T$ and
 a getter named $v$ with return type $S$,
 and $S$ may not be assigned to $T$.
@@ -2022,9 +2097,17 @@
 \subsection{Abstract Instance Members}
 \LMLabel{abstractInstanceMembers}
 
-\LMHash{}
-An {\em abstract method} (respectively, {\em abstract getter} or {\em abstract setter)} is an instance method, getter or setter that is not declared \EXTERNAL{} and does not provide an implementation.
-A {\em concrete method} (respectively, {\em concrete getter} or {\em concrete setter)} is an instance method, getter or setter that is not abstract.
+\LMHash{}%
+An \IndexCustom{abstract method}{method!abstract}
+(respectively,
+\IndexCustom{abstract getter}{getter!abstract} or
+\IndexCustom{abstract setter}{setter!abstract})
+is an instance method, getter or setter that is not declared \EXTERNAL{} and does not provide an implementation.
+A \IndexCustom{concrete method}{method!concrete}
+(respectively,
+\IndexCustom{concrete getter}{getter!concrete} or
+\IndexCustom{concrete setter}{setter!concrete})
+is an instance method, getter or setter that is not abstract.
 
 \rationale{
 Earlier versions of Dart required that abstract members be identified by prefixing them with the modifier \ABSTRACT{}.
@@ -2054,7 +2137,7 @@
 In classes used as mixins, it is often useful to introduce such declarations for methods that the mixin expects will be provided by the superclass the mixin is applied to.
 }
 
-\LMHash{}
+\LMHash{}%
 %% TODO(eernst): This is semi-redundant: We should define what it means for
 %% a class to be 'fully implemented' and require once and for all that it is
 %% a compile-time error if a concrete class is not fully implemented. That
@@ -2093,11 +2176,11 @@
 \subsection{Instance Variables}
 \LMLabel{instanceVariables}
 
-\LMHash{}
+\LMHash{}%
 Instance variables are variables whose declarations are immediately contained within a class declaration and that are not declared \STATIC{}.
 The instance variables of a class $C$ are those instance variables declared by $C$ and the instance variables inherited by $C$ from its superclass.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if an instance variable is declared to be constant.
 
 \rationale{
@@ -2116,16 +2199,16 @@
 \subsection{Constructors}
 \LMLabel{constructors}
 
-\LMHash{}
-A {\em constructor} is a special function that is used in instance creation expressions (\ref{instanceCreation}) to obtain objects, typically by creating or initializing them.
+\LMHash{}%
+A \Index{constructor} is a special function that is used in instance creation expressions (\ref{instanceCreation}) to obtain objects, typically by creating or initializing them.
 Constructors may be generative (\ref{generativeConstructors}) or they may be factories (\ref{factories}).
 
-\LMHash{}
-A {\em constructor name} always begins with the name of its immediately enclosing class, and may optionally be followed by a dot and an identifier \id.
+\LMHash{}%
+A \Index{constructor name} always begins with the name of its immediately enclosing class, and may optionally be followed by a dot and an identifier \id.
 It is a compile-time error if the name of a constructor is not a constructor name.
 
-\LMHash{}
-The {\em function type of a constructor} $k$ is the function type whose
+\LMHash{}%
+The \Index{function type of a constructor} $k$ is the function type whose
 return type is the class that contains the declaration of $k$,
 and whose formal parameter types, optionality, and names of named parameters
 correspond to the declaration of $k$.
@@ -2150,35 +2233,44 @@
 
 % The enclosing scope of a generative constructor is the instance scope of the class in which it is declared (but what about redirecting?)
 
-\LMHash{}
+\LMHash{}%
 If{}f no constructor is specified for a class $C$, it implicitly has a default constructor \code{C() : \SUPER{}() \{\}}, unless $C$ is class \code{Object}.
 
 
 \subsubsection{Generative Constructors}
 \LMLabel{generativeConstructors}
 
-\LMHash{}
-A {\em generative constructor} consists of a constructor name, a constructor parameter list, and either a redirect clause or an initializer list and an optional body.
+\LMHash{}%
+A \IndexCustom{generative constructor}{constructor!generative}
+declaration consists of a constructor name, a constructor parameter list,
+and either a redirect clause or an initializer list and an optional body.
 
 \begin{grammar}
-<constructorSignature> ::= <identifier> (`.' <identifier>)? <formalParameterList>
+<constructorSignature> ::= \gnewline{}
+  <identifier> (`.' <identifier>)? <formalParameterList>
 \end{grammar}
 
-\LMHash{}
-A {\em constructor parameter list} is a parenthesized, comma-separated list of formal constructor parameters.
-A {\em formal constructor parameter} is either a formal parameter (\ref{formalParameters}) or an initializing formal.
-An {\em initializing formal} has the form \code{\THIS{}.\id}, where \id{} is the name of an instance variable of the immediately enclosing class.
+\LMHash{}%
+A \Index{constructor parameter list} is a parenthesized, comma-separated list of formal constructor parameters.
+A \Index{formal constructor parameter} is either a formal parameter (\ref{formalParameters}) or an initializing formal.
+An \Index{initializing formal} has the form \code{\THIS{}.\id}, where \id{} is the name of an instance variable of the immediately enclosing class.
 It is a compile-time error if \id{} is not an instance variable of the immediately enclosing class.
 It is a compile-time error if an initializing formal is used by a function other than a non-redirecting generative constructor.
 
-\LMHash{}
+\LMHash{}%
 If an explicit type is attached to the initializing formal, that is its static type.
 Otherwise, the type of an initializing formal named \id{} is $T_{id}$, where $T_{id}$ is the type of the instance variable named \id{} in the immediately enclosing class.
 It is a compile-time error if the static type of \id{} is not a subtype of $T_{id}$.
 
-\LMHash{}
-Initializing formals constitute an exception to the rule that every formal parameter introduces a local variable into the formal parameter scope (\ref{formalParameters}).
-When the formal parameter list of a non-redirecting generative constructor contains any initializing formals, a new scope is introduced, the {\em formal parameter initializer scope}, which is the current scope of the initializer list of the constructor, and which is enclosed in the scope where the constructor is declared.
+\LMHash{}%
+Initializing formals constitute an exception to the rule that
+every formal parameter introduces a local variable into
+the formal parameter scope (\ref{formalParameters}).
+When the formal parameter list of a non-redirecting generative constructor
+contains any initializing formals, a new scope is introduced, the
+\IndexCustom{formal parameter initializer scope}{scope!formal parameter initializer},
+which is the current scope of the initializer list of the constructor,
+and which is enclosed in the scope where the constructor is declared.
 Each initializing formal in the formal parameter list introduces a final local variable into the formal parameter initializer scope, but not into the formal parameter scope; every other formal parameter introduces a local variable into both the formal parameter scope and the formal parameter initializer scope.
 
 \commentary{
@@ -2187,7 +2279,7 @@
 The type of the constructor is defined in terms of its formal parameters, including the initializing formals.
 }
 
-\LMHash{}
+\LMHash{}%
 Initializing formals are executed during the execution of generative constructors detailed below.
 Executing an initializing formal \code{\THIS{}.\id} causes the instance variable \id{} of the immediately surrounding class to be assigned the value of the corresponding actual parameter,
 unless \id{} is a final variable that has already been initialized, in which case a run-time error occurs.
@@ -2214,8 +2306,8 @@
 \}
 \end{dartCode}
 
-\LMHash{}
-A {\em fresh instance} is an instance whose identity is distinct from any previously allocated instance of its class.
+\LMHash{}%
+A \Index{fresh instance} is an instance whose identity is distinct from any previously allocated instance of its class.
 A generative constructor always operates on a fresh instance of its immediately enclosing class.
 
 \commentary{
@@ -2224,15 +2316,17 @@
 See the section on instance creation (\ref{instanceCreation}).
 }
 
-\LMHash{}
+\LMHash{}%
 If a generative constructor $c$ is not a redirecting constructor and no body is provided, then $c$ implicitly has an empty body \code{\{\}}.
 
 
 \paragraph{Redirecting Generative Constructors}
 \LMLabel{redirectingGenerativeConstructors}
 
-\LMHash{}
-A generative constructor may be {\em redirecting}, in which case its only action is to invoke another generative constructor.
+\LMHash{}%
+A generative constructor may be
+\IndexCustom{redirecting}{constructor!redirecting},
+in which case its only action is to invoke another generative constructor.
 A redirecting constructor has no body;
 instead, it has a redirect clause that specifies which constructor the invocation is redirected to, and with which arguments.
 
@@ -2242,7 +2336,7 @@
 
 \def\ConstMetavar{\mbox{\CONST{}?}}
 
-\LMHash{}
+\LMHash{}%
 Assume that
 \code{$C$<$X_1\ \EXTENDS\ B_1 \ldots,\ X_m\ \EXTENDS\ B_m$>}
 is the name and formal type parameters of the enclosing class,
@@ -2262,8 +2356,10 @@
 
 \code{$\THIS{}.\id$($e_1 \ldots,\ e_p,\ x_1$: $e_{p+1}, \ldots,\ x_q$: $e_{p+q}$)}
 
-\LMHash{}
-The {\em redirectee constructor} for this declaration is then the constructor denoted by
+\LMHash{}%
+The
+\IndexCustom{redirectee constructor}{constructor!redirectee}
+for this declaration is then the constructor denoted by
 \code{$C$<$X_1 \ldots,\ X_m$>} respectively \code{$C$<$X_1 \ldots,\ X_m$>.\id}.
 It is a compile-time error if the static argument list type (\ref{actualArgumentLists}) of
 \code{($e_1 \ldots,\ e_p,\ x_1$: $e_{p+1}, \ldots,\ x_q$: $e_{p+q}$)}
@@ -2286,14 +2382,14 @@
 actual arguments to function invocations in general.
 }
 
-\LMHash{}
+\LMHash{}%
 When $\ConstMetavar$ is \CONST{},
 it is a compile-time error if the redirectee is not a constant constructor.
 Moreover, when $\ConstMetavar$ is \CONST{}, each
 $e_i,\ i \in 1 .. p+q$,
 must be a potentially constant expression (\ref{constantConstructors}).
 
-\LMHash{}
+\LMHash{}%
 It is a dynamic type error if an actual argument passed in an invocation of a redirecting generative constructor $k$
 is not a subtype of the actual type (\ref{actualTypeOfADeclaration})
 of the corresponding formal parameter in the declaration of $k$.
@@ -2306,15 +2402,19 @@
 \paragraph{Initializer Lists}
 \LMLabel{initializerLists}
 
-\LMHash{}
-An initializer list begins with a colon, and consists of a comma-separated list of individual {\em initializers}.
+\LMHash{}%
+An initializer list begins with a colon, and consists of a comma-separated list of individual \Index{initializers}.
 
 \commentary{
 There are three kinds of initializers.
 \begin{itemize}
-\item[$\bullet$] A {\em superinitializer} identifies a {\em superconstructor}\,---\,that is, a specific constructor of the superclass.
-Execution of the superinitializer causes the initializer list of the superconstructor to be executed.
-\item[$\bullet$] An {\em instance variable initializer} assigns a value to an individual instance variable.
+\item[$\bullet$] A \emph{superinitializer} identifies a
+  \emph{superconstructor}\,---\,that is,
+  a specific constructor of the superclass.
+  Execution of the superinitializer causes
+  the initializer list of the superconstructor to be executed.
+\item[$\bullet$] An \emph{instance variable initializer}
+  assigns a value to an individual instance variable.
 \item[$\bullet$] An assertion.
 \end{itemize}
 }
@@ -2327,19 +2427,20 @@
   \alt <fieldInitializer>
   \alt <assertion>
 
-<fieldInitializer> ::= (\THIS{} `.')? <identifier> `=' <conditionalExpression> <cascadeSection>*
+<fieldInitializer> ::= \gnewline{}
+  (\THIS{} `.')? <identifier> `=' <conditionalExpression> <cascadeSection>*
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 An initializer of the form \code{$v$ = $e$} is equivalent to
 an initializer of the form \code{\THIS{}.$v$ = $e$},
-both forms are called {\em instance variable initializers}.
+both forms are called \Index{instance variable initializers}.
 It is a compile-time error if the enclosing class does not declare an instance variable named $v$.
 Otherwise, let $T$ be the static type of $v$.
 It is a compile-time error unless the static type of $e$ is assignable to $T$.
 
-\LMHash{}
-Consider a {\em superinitializer} $s$ of the form
+\LMHash{}%
+Consider a \Index{superinitializer} $s$ of the form
 
 \code{\SUPER{}($a_1, \ldots,\ a_n,\ x_{n+1}: a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
 respectively
@@ -2360,7 +2461,7 @@
 for the corresponding actual type arguments passed to the superclass
 in the header of the current class.
 
-\LMHash{}
+\LMHash{}%
 Let $k$ be a generative constructor.
 Then $k$ may include at most one superinitializer in its initializer list or a compile-time error occurs.
 If no superinitializer is provided, an implicit superinitializer of the form \SUPER{}() is added at the end of $k$'s initializer list,
@@ -2371,7 +2472,7 @@
 It is a compile-time error if $k$'s initializer list contains an initializer for a final variable $f$ whose declaration includes an initialization expression.
 It is a compile-time error if $k$ includes an initializing formal for a final variable $f$ whose declaration includes an initialization expression.
 
-\LMHash{}
+\LMHash{}%
 Let $f$ be a final instance variable declared in
 the immediately enclosing class.
 A compile-time error occurs unless $f$ is initialized
@@ -2382,21 +2483,21 @@
 \item $f$ has an initializer in $k$'s initializer list.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $k$'s initializer list contains an initializer for a variable that is not an instance variable declared in the immediately surrounding class.
 
 \commentary{
 The initializer list may of course contain an initializer for any instance variable declared by the immediately surrounding class, even if it is not final.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a generative constructor of class \code{Object} includes a superinitializer.
 
 
 \paragraph{Execution of Generative Constructors}
 \LMLabel{executionOfGenerativeConstructors}
 
-\LMHash{}
+\LMHash{}%
 Execution of a generative constructor $k$ of type $T$ to initialize a fresh instance $i$
 is always done with respect to a set of bindings for its formal parameters
 and the type parameters of the immediately enclosing class bound to
@@ -2407,7 +2508,7 @@
 However, they may also be determined by a reflective call.
 }
 
-\LMHash{}
+\LMHash{}%
 If $k$ is redirecting then its redirect clause has the form
 
 \code{\THIS{}.$g$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
@@ -2420,24 +2521,24 @@
 in an environment where the type parameters of the enclosing class are bound to
 $t_1, \ldots, t_m$.
 
-\LMHash{}
+\LMHash{}%
 Next, the body of $g$ is executed to initialize $i$ with respect to the bindings that map
 the formal parameters of $g$ to the corresponding objects in the actual argument list $a$,
 with \THIS{} bound to $i$,
 and the type parameters of the immediately enclosing class bound to $t_1, \ldots, t_m$.
 
-\LMHash{}
+\LMHash{}%
 Otherwise, $k$ is not redirecting.
 Execution then proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 The instance variable declarations of the immediately enclosing class are visited in the order they appear in the program text.
 For each such declaration $d$, if $d$ has the form
 \code{\syntax{finalConstVarOrType} $v$ = $e$; }
 then $e$ is evaluated to an object $o$
 and the instance variable $v$ of $i$ is bound to $o$.
 
-\LMHash{}
+\LMHash{}%
 Any initializing formals declared in $k$'s parameter list are executed in the order they appear in the program text.
 % In fact, this order is unobservable; this could be done any time prior to running the body, since
 % these only effect \THIS{}.
@@ -2450,17 +2551,17 @@
 So we need to specify the order.
 }
 
-\LMHash{}
+\LMHash{}%
 Then if any instance variable of $i$ declared by the immediately enclosing class
 is not yet bound to a value,
 all such variables are initialized with the null object (\ref{null}).
 
-\LMHash{}
+\LMHash{}%
 Then, unless the enclosing class is \code{Object}, the explicitly specified or
 implicitly added superinitializer (\ref{initializerLists}) is executed to
 further initialize $i$.
 
-\LMHash{}
+\LMHash{}%
 After the superinitializer has completed, the body of $k$ is executed in a scope where \THIS{} is bound to $i$.
 
 \rationale{
@@ -2474,12 +2575,12 @@
 \paragraph{Execution of Initializer Lists}
 \LMLabel{executionOfInitializerLists}
 
-\LMHash{}
+\LMHash{}%
 During the execution of a generative constructor to initialize an instance $i$,
 execution of an initializer of the form \code{\THIS{}.$v$ = $e$}
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 First, the expression $e$ is evaluated to an object $o$.
 Then, the instance variable $v$ of $i$ is bound to $o$.
 It is a dynamic type error if $o$ is not the null object
@@ -2488,10 +2589,10 @@
 (\ref{actualTypeOfADeclaration})
 of the instance variable $v$.
 
-\LMHash{}
+\LMHash{}%
 Execution of an initializer that is an assertion proceeds by executing the assertion (\ref{assert}).
 
-\LMHash{}
+\LMHash{}%
 Consider a superinitializer $s$ of the form
 
 \code{\SUPER{}($a_1, \ldots,\ a_n,\ x_{n+1}: a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
@@ -2499,7 +2600,7 @@
 
 \code{\SUPER{}.\id($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
 
-\LMHash{}
+\LMHash{}%
 Let $C$ be the class in which $s$ appears and let $S$ be the superclass of $C$.
 If $S$ is generic (\ref{generics}),
 let $u_1, \ldots, u_p$ be the actual type arguments passed to $S$,
@@ -2511,7 +2612,7 @@
 Let $k$ be the constructor declared in $S$ and named
 $S$ respectively \code{$S$.\id}.
 
-\LMHash{}
+\LMHash{}%
 Execution of $s$ proceeds as follows:
 The argument list
 \code{($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
@@ -2526,23 +2627,27 @@
 \subsubsection{Factories}
 \LMLabel{factories}
 
-\LMHash{}
-A {\em factory} is a constructor prefaced by the built-in identifier (\ref{identifierReference}) \FACTORY{}.
+\LMHash{}%
+A \IndexCustom{factory}{constructor!factory}
+is a constructor prefaced by the built-in identifier
+(\ref{identifierReference})
+\FACTORY{}.
 
 \begin{grammar}
-<factoryConstructorSignature> ::= \FACTORY{} <identifier> (`.' <identifier>)? <formalParameterList>
+<factoryConstructorSignature> ::= \gnewline{}
+  \FACTORY{} <identifier> (`.' <identifier>)? <formalParameterList>
 \end{grammar}
 
 %The enclosing scope of a factory constructor is the static scope \ref{} of the class in which it is declared.
 
-\LMHash{}
-The {\em return type} of a factory whose signature is of the form \FACTORY{} $M$ or the form \FACTORY{} \code{$M$.\id} is $M$ if $M$ is not a generic type;
+\LMHash{}%
+The return type of a factory whose signature is of the form \FACTORY{} $M$ or the form \FACTORY{} \code{$M$.\id} is $M$ if $M$ is not a generic type;
 otherwise the return type is \code{$M$<$T_1, \ldots,\ T_n$>} where $T_1, \ldots, T_n$ are the type parameters of the enclosing class.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $M$ is not the name of the immediately enclosing class.
 
-\LMHash{}
+\LMHash{}%
 It is a dynamic type error if a factory returns a non-null object
 whose type is not a subtype of its actual
 (\ref{actualTypeOfADeclaration})
@@ -2563,12 +2668,15 @@
 \paragraph{Redirecting Factory Constructors}
 \LMLabel{redirectingFactoryConstructors}
 
-\LMHash{}
-A {\em redirecting factory constructor} specifies a call to a constructor of another class that is to be used whenever the redirecting constructor is called.
+\LMHash{}%
+A \IndexCustom{redirecting factory constructor}{constructor!redirecting factory}
+specifies a call to a constructor of another class that is to be used
+whenever the redirecting constructor is called.
 
 \begin{grammar}
-<redirectingFactoryConstructorSignature> ::= \CONST{}? \FACTORY{} <identifier> (`.' <identifier>)? <formalParameterList>
-  \gnewline{} `=' <type> (`.' <identifier>)?
+<redirectingFactoryConstructorSignature> ::= \gnewline{}
+  \CONST{}? \FACTORY{} <identifier> (`.' <identifier>)? <formalParameterList> `='
+  \gnewline{} <type> (`.' <identifier>)?
 \end{grammar}
 
 Assume that
@@ -2592,7 +2700,7 @@
 \code{$T$<$S_1 \ldots,\ S_p$>} or
 \code{$T$<$S_1 \ldots,\ S_p$>.\id}.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $T$ does not denote
 a class accessible in the current scope.
 If $T$ does denote such a class $D$,
@@ -2602,11 +2710,12 @@
 % redirections:
 Otherwise, it is a compile-time error
 if $R$ denotes a generative constructor and $D$ is abstract.
-Otherwise, the {\em redirectee constructor} for this declaration is
-the constructor denoted by $R$.
+Otherwise, the
+\IndexCustom{redirectee constructor}{constructor!redirectee}
+for this declaration is the constructor denoted by $R$.
 
-\LMHash{}
-A redirecting factory constructor $q'$ is {\em redirection-reachable}
+\LMHash{}%
+A redirecting factory constructor $q'$ is \Index{redirection-reachable}
 from a redirecting factory constructor $q$ if{}f
 $q'$ is the redirectee constructor of $q$,
 or $q''$ is the redirectee constructor of $q$
@@ -2614,7 +2723,7 @@
 It is a compile-time error if a redirecting factory constructor
 is redirection-reachable from itself.
 
-\LMHash{}
+\LMHash{}%
 Let $\argumentList{T}$ be the static argument list type (\ref{actualArgumentLists})
 \code{($T_1 \ldots,\ T_{n+k}$)}
 when $k$ takes no named arguments, and
@@ -2640,15 +2749,16 @@
 and/or the actual type argument list of the redirectee constructor is omitted (\ref{generics}).
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $k$ explicitly specifies a default value for an optional parameter.
 
 \commentary{
-Default values specified in $k$ would be ignored, since it is the {\em actual} parameters that are passed to $k'$.
+Default values specified in $k$ would be ignored,
+since it is the \emph{actual} parameters that are passed to $k'$.
 Hence, default values are disallowed.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a formal parameter of $k'$ has a default value
 whose type is not a subtype of the type annotation
 on the corresponding formal parameter in $k$.
@@ -2666,10 +2776,10 @@
 \end{itemize}
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $k$ is prefixed with the \CONST{} modifier but $k'$ is not a constant constructor (\ref{constantConstructors}).
 
-\LMHash{}
+\LMHash{}%
 Let $T_1, \ldots, T_m$ be the actual type arguments passed to $k'$
 in the declaration of $k$.
 Let $X_1, \ldots, X_m$ be the formal type arguments declared by
@@ -2685,22 +2795,22 @@
 the interface of the immediately enclosing class of $k$.
 }
 
-\LMHash{}
+\LMHash{}%
 For the dynamic semantics,
 assume that $k$ is a redirecting factory constructor
 and $k'$ is the redirectee of $k$.
 
-\LMHash{}
+\LMHash{}%
 It is a dynamic type error if an actual argument passed in an invocation of $k$
 is not a subtype of the actual type (\ref{actualTypeOfADeclaration})
 of the corresponding formal parameter in the declaration of $k$.
 
-\LMHash{}
+\LMHash{}%
 When the redirectee $k'$ is a factory constructor,
 execution of $k$ amounts to execution of $k'$ with the actual arguments passed to $k$.
 The result of the execution of $k'$ is the result of $k$.
 
-\LMHash{}
+\LMHash{}%
 When the redirectee $k'$ is a generative constructor,
 let $o$ be a fresh instance (\ref{generativeConstructors})
 of the class that contains $k'$.
@@ -2713,8 +2823,9 @@
 \subsubsection{Constant Constructors}
 \LMLabel{constantConstructors}
 
-\LMHash{}
-A {\em constant constructor} may be used to create compile-time constant (\ref{constants}) objects.
+\LMHash{}%
+A \IndexCustom{constant constructor}{constructor!constant}
+may be used to create compile-time constant (\ref{constants}) objects.
 A constant constructor is prefixed by the reserved word \CONST{}.
 
 \begin{grammar}
@@ -2727,28 +2838,28 @@
 All the work of a constant constructor must be handled via its initializers.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a constant constructor is declared by a class that has a mutable instance variable.
 
 \commentary{
 The above refers to both locally declared and inherited instance variables.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a constant constructor is declared by a class $C$ if any instance variable declared in $C$ is initialized with an expression that is not a constant expression.
 
 \commentary{
 A superclass of $C$ cannot declare such an initializer either, because it must necessarily declare constant constructor as well (unless it is \code{Object}, which declares no instance variables).
 }
 
-\LMHash{}
+\LMHash{}%
 The superinitializer that appears, explicitly or implicitly, in the initializer list of a constant constructor must specify a constant constructor of the superclass of the immediately enclosing class or a compile-time error occurs.
 
-\LMHash{}
+\LMHash{}%
 Any expression that appears within the initializer list of a constant constructor must be a potentially constant expression, or a compile-time error occurs.
 
-\LMHash{}
-A {\em potentially constant expression} is an expression $e$ that could be a valid constant expression if all formal parameters of $e$'s immediately enclosing constant constructor were treated as compile-time constants of appropriate types, and where $e$ is also a valid expression if all the formal parameters are treated as non-constant variables.
+\LMHash{}%
+A \Index{potentially constant expression} is an expression $e$ that could be a valid constant expression if all formal parameters of $e$'s immediately enclosing constant constructor were treated as compile-time constants of appropriate types, and where $e$ is also a valid expression if all the formal parameters are treated as non-constant variables.
 
 \commentary{
 The difference between a potentially constant expression and a constant expression (\ref{const}) deserves some explanation.
@@ -2805,7 +2916,7 @@
 This is precluded by the following rule, combined with the rules for evaluating constant objects (\ref{const}).
 }
 
-\LMHash{}
+\LMHash{}%
 When a constant constructor $k$ is invoked from a constant object expression,
 it is a compile-time error if
 the invocation of $k$ at run time would throw an exception,
@@ -2830,11 +2941,12 @@
 \subsection{Static Methods}
 \LMLabel{staticMethods}
 
-\LMHash{}
-{\em Static methods} are functions, other than getters or setters, whose declarations are immediately contained within a class declaration and that are declared \STATIC{}.
+\LMHash{}%
+\IndexCustom{Static methods}{method!static}
+are functions, other than getters or setters, whose declarations are immediately contained within a class declaration and that are declared \STATIC{}.
 The static methods of a class $C$ are those static methods declared by $C$.
 
-\LMHash{}
+\LMHash{}%
 The effect of a static method declaration in class $C$ is to add an instance method with the same name and signature to the \code{Type} object for class $C$ that forwards (\ref{functionDeclarations}) to the static method.
 
 \rationale{
@@ -2865,7 +2977,7 @@
 %% class (unless we start defining nested classes, such that the
 %% superclass can be declared in that scope).
 
-\LMHash{}
+\LMHash{}%
 The superclass $S'$ of a class $C$ whose declaration has a with clause
 \code{\WITH{} $M_1, \ldots,\ M_k$}
 and an extends clause
@@ -2882,7 +2994,7 @@
 \code{\EXTENDS{} Object}, and the rules above apply.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error to specify an \EXTENDS{} clause
 for class \code{Object}.
 
@@ -2895,10 +3007,10 @@
 %This means that in a generic class, the type parameters of the generic are available in the superclass clause.
 %}
 
-\LMHash{}
+\LMHash{}%
 The scope of the \EXTENDS{} and \WITH{} clauses of a class $C$ is the type-parameter scope of $C$.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the type in the \EXTENDS{} clause of a class $C$ is
 a type variable (\ref{generics}), a type alias (\ref{typedef}),
 an enumerated type (\ref{enums}), a malformed type (\ref{staticTypes}),
@@ -2917,27 +3029,27 @@
 class G<T> extends T \{\}
 \end{dartCode}
 
-\LMHash{}
+\LMHash{}%
 %% TODO(eernst): Consider replacing all occurrences of `a superclass`
 %% by `a direct or indirect superclass`, because it's too confusing.
-A class $S$ is {\em a superclass} of a class $C$ if{}f either:
+A class $S$ is a \Index{superclass} of a class $C$ if{}f either:
 \begin{itemize}
 \item $S$ is the superclass of $C$, or
 \item $S$ is a superclass of a class $S'$,
 and $S'$ is the superclass of $C$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a class $C$ is a superclass of itself.
 
 
 \subsubsection{Inheritance and Overriding}
 \LMLabel{inheritanceAndOverriding}
 
-\LMHash{}
+\LMHash{}%
 Let $C$ be a class, let $A$ be a superclass of $C$, and
 let $S_1, \ldots, S_k$ be superclasses of $C$ that are also subclasses of $A$.
-$C$ {\em inherits} all concrete, accessible instance members of $A$
+$C$ \Index{inherits} all concrete, accessible instance members of $A$
 that have not been overridden by a concrete declaration in $C$ or in at least one of $S_1, \ldots, S_k$.
 
 \rationale{
@@ -2948,10 +3060,10 @@
 but the superclass chain of $S$ includes a class declared in $L_1$.
 }
 
-\LMHash{}
+\LMHash{}%
 A class may override instance members that would otherwise have been inherited from its superclass.
 
-\LMHash{}
+\LMHash{}%
 Let $C = S_0$ be a class declared in library $L$, and
 let $\{S_1, \ldots, S_k\}$ be the set of all superclasses of $C$,
 where $S_i$ is the superclass of $S_{i-1}$ for $i \in 1 .. k$.
@@ -2972,7 +3084,7 @@
 Again, a local definition of overriding would be preferable, but fails to account for library privacy.
 }
 
-\LMHash{}
+\LMHash{}%
 Whether an override is legal or not is described elsewhere in this specification (see \ref{instanceMethods}, \ref{getters} and \ref{setters}).
 
 \commentary{
@@ -2990,7 +3102,7 @@
 Finally, static members never override anything.
 }
 
-\LMHash{}
+\LMHash{}%
 Let $C$ be a concrete class
 whose interface has an accessible member $m$ named \id{}.
 It is a compile-time error if $C$ does not have
@@ -3118,7 +3230,7 @@
 \LMLabel{superinterfaces}
 % what about rules about classes that fail to implement their interfaces?
 
-\LMHash{}
+\LMHash{}%
 A class has a set of direct superinterfaces.
 This set includes the interface of its superclass and the interfaces specified in the \IMPLEMENTS{} clause of the class.
 
@@ -3126,10 +3238,10 @@
 <interfaces> ::= \IMPLEMENTS{} <typeList>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 The scope of the \IMPLEMENTS{} clause of a class $C$ is the type-parameter scope of $C$.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if an element in the type list of the \IMPLEMENTS{} clause of a class $C$ is
 a type variable (\ref{generics}), a type alias (\ref{typedef}),
 an enumerated type (\ref{enums}), a malformed type (\ref{staticTypes}),
@@ -3148,10 +3260,10 @@
 As such, it is an indication that the programmer may very well have meant to say something else - and that is a mistake that should be called to her or his attention.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the interface of a class $C$ is a superinterface of itself.
 
-\LMHash{}
+\LMHash{}%
 Let $C$ be a concrete class that does not have a concrete \code{noSuchMethod()} method distinct from the one declared in class \code{Object}.
 %% TODO(eernst): Adjust to use 'correctly overrides' terminology.
 It is a compile-time error if the implicit interface of $C$ has an accessible instance member $m$ of type $F$,
@@ -3175,7 +3287,7 @@
 This allows proxy classes for specific types to be implemented without provoking errors.
 }
 
-\LMHash{}
+\LMHash{}%
 %% TODO(eernst): Switch to use 'correctly overrides' terminology.
 It is a compile-time error if the implicit interface of a class $C$ has an instance member $m$ of type $F$ and $C$ declares or inherits a corresponding instance member $m$ of type $F'$ if $F'$ is not a subtype of $F$.
 
@@ -3187,16 +3299,16 @@
 \subsection{Class Member Conflicts}
 \LMLabel{classMemberConflicts}
 
-\LMHash{}
+\LMHash{}%
 Some pairs of class member declarations cannot coexist,
 even though they do not both introduce the same name into the same scope.
 This section specifies these errors.
 
-\LMHash{}
-The {\em basename} of a getter or method named $n$ is $n$;
+\LMHash{}%
+The \Index{basename} of a getter or method named $n$ is $n$;
 the basename of a setter named \code{$n$=} is $n$.
 
-\LMHash{}
+\LMHash{}%
 Let $C$ be a class.
 It is a compile-time error if $C$ declares a
 \begin{itemize}
@@ -3212,25 +3324,25 @@
 \section{Interfaces}
 \LMLabel{interfaces}
 
-\LMHash{}
-An {\em interface} defines how one may interact with an object.
+\LMHash{}%
+An \Index{interface} defines how one may interact with an object.
 An interface has methods, getters and setters and a set of superinterfaces.
 
 
 \subsection{Superinterfaces}
 \LMLabel{interfaceSuperinterfaces}
 
-\LMHash{}
+\LMHash{}%
 An interface has a set of direct superinterfaces.
 
-\LMHash{}
+\LMHash{}%
 An interface $J$ is a superinterface of an interface $I$ if{}f either $J$ is a direct superinterface of $I$ or $J$ is a superinterface of a direct superinterface of $I$.
 
 
 \subsubsection{Inheritance and Overriding}
 \LMLabel{interfaceInheritanceAndOverriding}
 
-\LMHash{}
+\LMHash{}%
 Let $J$ be an interface and $K$ be a library.
 We define $inherited(J, K)$ to be the set of members $m$ such that all of the following hold:
 \begin{itemize}
@@ -3243,7 +3355,7 @@
 \item $m$ is not overridden by $J$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Furthermore, we define $overrides(J, K)$ to be the set of members $m'$ such that all of the following hold:
 \begin{itemize}
 \item $J$ is the implicit interface of a class $C$.
@@ -3257,14 +3369,14 @@
   \end{itemize}
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Let $I$ be the implicit interface of a class $C$ declared in library $L$.
-$I$ {\em inherits} all members of $inherited(I, L)$ and $I$ {\em overrides} $m'$ if $m' \in overrides(I, L)$.
+$I$ \Index{inherits} all members of $inherited(I, L)$ and $I$ \Index{overrides} $m'$ if $m' \in overrides(I, L)$.
 
-\LMHash{}
+\LMHash{}%
 All the compile-time errors pertaining to the overriding of instance members given in section \ref{classes} above hold for overriding between interfaces as well.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $m$ is a method and $m'$ is a getter, or if $m$ is a getter and $m'$ is a method.
 
 %Let $I = S_0$ be the implicit interface of a class $C$ declared in library $L$, and let $\{S_1, \ldots, S_k\}$ be the set of all superinterfaces of $I$.
@@ -3273,13 +3385,13 @@
 
 % tighten definition? do we need chain as for classes?  Definition for interface override?
 
-\LMHash{}
+\LMHash{}%
 However, if the above rules would cause multiple members $m_1, \ldots, m_k$ with the same name $n$ to be inherited (because identically named members existed in several superinterfaces) then at most one member is inherited.
 
-\LMHash{}
+\LMHash{}%
 If some but not all of the $m_i, 1 \le i \le k$ are getters, a compile-time error occurs.
 
-\LMHash{}
+\LMHash{}%
 %% TODO(eernst): Adjust to use 'correctly overrides' terminology.
 Otherwise, if the static types $T_1, \ldots, T_k$ of the members $m_1, \ldots, m_k$ are not identical then there must be an $x \in 1 .. k$ such that $T_x <: T_i$ for all $i \in 1 .. k$,
 or a compile-time error occurs.
@@ -3289,11 +3401,11 @@
 \section{Mixins}
 \LMLabel{mixins}
 
-\LMHash{}
+\LMHash{}%
 A mixin describes the difference between a class and its superclass.
 A mixin is always derived from an existing class declaration.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error to derive a mixin from a class which explicitly declares a generative constructor.
 It is a compile-time error to derive a mixin from a class which has a superclass other than \code{Object}.
 
@@ -3308,7 +3420,7 @@
 \subsection{Mixin Application}
 \LMLabel{mixinApplication}
 
-\LMHash{}
+\LMHash{}%
 A mixin may be applied to a superclass, yielding a new class.
 Mixin application occurs when one or more mixins are mixed into a class declaration via its \WITH{} clause.
 The mixin application may be used to extend a class per section \ref{classes};
@@ -3320,26 +3432,27 @@
 or type \code{FutureOr<$T$>} for any $T$ (\ref{typeFutureOr}).
 
 \begin{grammar}
-<mixinApplicationClass> ::= <identifier> <typeParameters>? `=' <mixinApplication> `;'
+<mixinApplicationClass> ::= \gnewline{}
+  <identifier> <typeParameters>? `=' <mixinApplication> `;'
 
 <mixinApplication> ::= <type> <mixins> <interfaces>?
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 A mixin application of the form \code{$S$ \WITH{} $M$;} for the name $N$ defines a class $C$ with superclass $S$ and name $N$.
 
-\LMHash{}
+\LMHash{}%
 A mixin application of the form \code{$S$ \WITH{} $M_1,\ \ldots,\ M_k$;} for the name $N$ defines a class $C$ whose superclass is the application of the mixin composition (\ref{mixinComposition}) $M_{k-1} * \ldots * M_1$ to $S$ of a name that is a fresh identifer, and whose name is $N$.
 \rationale{The name of the resulting class is necessary because it is part of the names of the introduced constructors.}
 
-\LMHash{}
+\LMHash{}%
 In both cases above, $C$ declares the same instance members as $M$ (respectively, $M_k$),
 and it does not declare any static members.
 If any of the instance variables of $M$ (respectively, $M_k$) have initializers,
 they are executed in the instance scope of $M$ (respectively, $M_k$)
 to initialize the corresponding instance variables of $C$.
 
-\LMHash{}
+\LMHash{}%
 Let $L_C$ be the library containing the mixin application.
 \commentary{That is, the library containing the clause \code{$S$ \WITH{} $M$}
 or the clause \code{$S_0$ \WITH{} $M_1$, \ldots,\ $M_k$, $M$}.}
@@ -3360,7 +3473,7 @@
 If $S_q$ is a generative const constructor, and $M$ does not declare any
 fields, $C_q$ is also a const constructor.
 
-\LMHash{}
+\LMHash{}%
 For each generative constructor of the form \code{$S_q$($T_{1}$ $a_{1}$, \ldots , $T_{k}$ $a_{k}$, [$T_{k+1}$ $a_{k+1}$ = $d_1$, \ldots , $T_{k+p}$ $a_{k+p}$ = $d_p$])} of $S$ that is accessible to $L_C$, $C$ has an implicitly declared constructor of the form
 
 \begin{dartCode}
@@ -3378,7 +3491,7 @@
 If $S_q$ is a generative const constructor, and $M$ does not declare any
 fields, $C_q$ is also a const constructor.
 
-\LMHash{}
+\LMHash{}%
 For each generative constructor of the form \code{$S_q$($T_{1}$ $a_{1}$, \ldots , $T_{k}$ $a_{k}$, \{$T_{k+1}$ $a_{k+1}$ = $d_1$, \ldots , $T_{k+n}$ $a_{k+n}$ = $d_n$\})} of $S$ that is accessible to $L_C$, $C$ has an implicitly declared constructor of the form
 
 \begin{dartCode}
@@ -3395,15 +3508,15 @@
 If $S_q$ is a generative const constructor, and $M$ does not declare any
 fields, $C_q$ is also a const constructor.
 
-\LMHash{}
+\LMHash{}%
 If the mixin application class declares interfaces, the resulting class also implements those interfaces.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $S$ is an enumerated type (\ref{enums}) or a malformed type.
 It is a compile-time error if $M$ (respectively, any of $M_1, \ldots, M_k$) is an enumerated type (\ref{enums}) or a malformed type.
 It is a compile-time error if a well formed mixin cannot be derived from $M$ (respectively, from each of $M_1, \ldots, M_k$).
 
-\LMHash{}
+\LMHash{}%
 Let $K$ be a class declaration with the same constructors, superclass and interfaces as $C$, and the instance members declared by $M$ (respectively $M_1, \ldots, M_k$).
 It is a compile-time error if the declaration of $K$ would cause a compile-time error.
 
@@ -3413,19 +3526,19 @@
 this will result in a compile-time error just as if we had defined $K$ by means of an ordinary class declaration extending $S$, with a body that included $im$.
 }
 
-\LMHash{}
+\LMHash{}%
 The effect of a class definition of the form \code{\CLASS{} $C$ = $M$; } or the form \code{\CLASS{} $C<T_1, \ldots,\ T_n>$ = $M$; } in library $L$ is to introduce the name $C$ into the scope of $L$, bound to the class (\ref{classes}) defined by the mixin application $M$ for the name $C$.
 The name of the class is also set to $C$.
 If{}f the class is prefixed by the built-in identifier \ABSTRACT{}, the class being defined is an abstract class.
 
-\LMHash{}
+\LMHash{}%
 Let $M_A$ be a mixin derived from a class $M$ with direct superclass $S_{static}$, e.g., as defined by the class declaration \code{class M extends S$_{static}$ \{ \ldots \}}.
 
-\LMHash{}
+\LMHash{}%
 Let $A$ be an application of $M_A$.
 It is a compile-time error if the superclass of $A$ is not a subtype of $S_{static}$.
 
-\LMHash{}
+\LMHash{}%
 Let $C$ be a class declaration that includes $M_A$ in a with clause.
 It is a compile-time error if $C$ does not implement, directly or indirectly, all the direct superinterfaces of $M$.
 
@@ -3437,12 +3550,18 @@
 Dart does not directly support mixin composition, but the concept is useful when defining how the superclass of a class with a mixin clause is created.
 }
 
-\LMHash{}
-The {\em composition of two mixins}, $M_1<T_1, \ldots, T_{k_{M_1}}>$ and $M_2<U_1, \ldots, U_{k_{M_2}}>$, written $M_1<T_1, \ldots, T_{k_{M_1}}> * M_2<U_1, \ldots, U_{k_{M_2}}>$ defines an anonymous mixin such that for any class $S<V_1, \ldots, V_{k_S}>$, the application of
+\LMHash{}%
+The \Index{composition of two mixins},
+\code{$M_1$<$T_1, \ldots, T_{k_{M_1}}$>} and
+\code{$M_2$<$U_1, \ldots, U_{k_{M_2}}$>}, written
+\code{$M_1$<$T_1, \ldots, T_{k_{M_1}}$>$ * M_2$<$U_1, \ldots, U_{k_{M_2}}$>}
+defines an anonymous mixin such that for any class
+\code{$S$<$V_1, \ldots, V_{k_S}$>},
+the application of
 
-$M_1<T_1, \ldots, T_{k_{M_1}}> * M_2<U_1, \ldots, U_{k_{M_2}}>$
+\code{$M_1$<$T_1, \ldots, T_{k_{M_1}}$> $*$ $M_2$<$U_1, \ldots, U_{k_{M_2}}$>}
 
-to $S<V_1, \ldots, V_{k_S}>$ for the name $C$ is equivalent to
+to \code{$S$<$V_1, \ldots, V_{k_S}$>} for the name $C$ is equivalent to
 
 \begin{dartCode}
 \ABSTRACT{} \CLASS{} $C<T_1, \ldots, T_{k_{M_1}}, U_1, \ldots, U_{k_{M_2}}, V_1, \ldots, V_{k_S}> = $
@@ -3464,7 +3583,7 @@
 Consequently, no errors are raised if a mixin composition includes abstract members, or incompletely implements an interface.
 }
 
-\LMHash{}
+\LMHash{}%
 Mixin composition is associative.
 
 \commentary{
@@ -3476,8 +3595,8 @@
 \section{Enums}
 \LMLabel{enums}
 
-\LMHash{}
-An {\em enumerated type}, or {\em enum}, is used to represent a fixed number of constant values.
+\LMHash{}%
+An \Index{enumerated type}, or \Index{enum}, is used to represent a fixed number of constant values.
 
 \begin{grammar}
 <enumType> ::= <metadata> \ENUM{} <identifier>
@@ -3486,7 +3605,7 @@
 <enumEntry> ::= <metadata> <identifier>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 The declaration of an enum of the form
 \code{$m$ \ENUM{} $E$ \{$m_0\,\,\id_0, \ldots,\ m_{n-1}\,\,\id_{n-1}$\}}
 has the same effect as a class declaration
@@ -3512,10 +3631,10 @@
 \section{Generics}
 \LMLabel{generics}
 
-\LMHash{}
-A class declaration (\ref{classes}), type alias (\ref{typedef}), or function (\ref{functions}) $G$ may be {\em generic}, that is, $G$ may have formal type parameters declared.
+\LMHash{}%
+A class declaration (\ref{classes}), type alias (\ref{typedef}), or function (\ref{functions}) $G$ may be \Index{generic}, that is, $G$ may have formal type parameters declared.
 
-\LMHash{}
+\LMHash{}%
 When an entity in this specification is described as generic,
 and the special case is considered where the number of type arguments is zero,
 the type argument list should be omitted.
@@ -3530,19 +3649,21 @@
 operations where formal type parameters are replaced by actual type arguments.
 }
 
-\LMHash{}
-A {\em generic class declaration} introduces a generic class into the enclosing library scope.
-A {\em generic class} is a mapping that accepts a list of actual type arguments and maps them to a class.
+\LMHash{}%
+A \IndexCustom{generic class declaration}{class declaration!generic}
+introduces a generic class into the enclosing library scope.
+A \IndexCustom{generic class}{class!generic}
+is a mapping that accepts a list of actual type arguments and maps them to a class.
 Consider a generic class declaration $G$ named \code{C} with formal type parameter declarations
 $X_1\ \EXTENDS\ B_1, \ldots,\ X_m\ \EXTENDS\ B_m$,
 and a parameterized type $T$ of the form \code{C<$T_1, \ldots,\ T_l$>}.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $m \not= l$.
 It is a compile-time error if $T$ is not well-bounded
 (\ref{superBoundedTypes}).
 
-\LMHash{}
+\LMHash{}%
 Otherwise, said parameterized type \code{C<$T_1, \ldots,\ T_m$>} denotes an application of the generic class declared by $G$ to the type arguments $T_1, \ldots, T_m$.
 This yields a class $C'$ whose members are equivalent to those of a class declaration which is obtained from the declaration of $G$ by replacing each occurrence of $X_j$ by $T_j$.
 \commentary{
@@ -3551,8 +3672,8 @@
 Other properties of $C'$ such as the subtype relationships are specified elsewhere (\ref{interfaceTypes}).
 }
 
-\LMHash{}
-A {\em generic type alias}
+\LMHash{}%
+A \IndexCustom{generic type alias}{type alias!generic}
 introduces a mapping from actual type argument lists to types.
 Consider a generic type alias declaration $G$ named \code{F}
 with formal type parameter declarations
@@ -3561,7 +3682,7 @@
 %% Explain what "the right hand side" means for an old-style declaration.
 and right hand side $T$.
 
-\LMHash{}
+\LMHash{}%
 Under the assumption that $X_1,\ \ldots,\ X_m$ are types such that
 $X_j <: B_j$, for all $j \in 1 .. m$,
 it is a compile-time error if any type in $T$ is not regular-bounded.
@@ -3573,7 +3694,7 @@
 the bounds that pertain to any type in the body must also be satisfied.
 }
 
-\LMHash{}
+\LMHash{}%
 Let $G$, \code{F}, and $X_1,\ \ldots,\ X_m$ be as defined above,
 let $T_1,\ \ldots,\ T_l$ be types,
 and let $S$ be the parameterized type \code{F<$T_1, \ldots,\ T_l$>}.
@@ -3581,7 +3702,7 @@
 It is a compile-time error if $S$ is not well-bounded
 (\ref{superBoundedTypes}).
 
-\LMHash{}
+\LMHash{}%
 Otherwise, said parameterized type
 \code{F<$T_1, \ldots,\ T_m$>}
 denotes an application of the mapping denoted by $G$ to the type arguments
@@ -3623,19 +3744,20 @@
 they just cannot be abbreviated using a generic type alias.
 }
 
-\LMHash{}
-A {\em generic type} is a type which is introduced by
+\LMHash{}%
+A \IndexCustom{generic type}{type!generic} is a type which is introduced by
 a generic class declaration or a generic type alias,
 or it is the type \code{FutureOr}.
 
-\LMHash{}
-A {\em generic function declaration} introduces a generic function (\ref{formalParameters}) into the enclosing scope.
+\LMHash{}%
+A \IndexCustom{generic function declaration}{function declaration!generic}
+introduces a generic function (\ref{formalParameters}) into the enclosing scope.
 Consider a function invocation expression of the form
 \code{f<$T_1, \ldots,\ T_l$>(\ldots)},
 where the static type of \code{f} is a generic function type with formal type parameters
 $X_1\ \EXTENDS\ B_1, \ldots,\ X_m\ \EXTENDS\ B_m$.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $m \not= l$.
 It is a compile-time error if there exists a $j$
 such that $T_j$ is not a subtype of $[T_1/X_1, \ldots, T_m/X_m]B_j$.
@@ -3652,8 +3774,8 @@
 <typeParameters> ::= `<' <typeParameter> (`,' <typeParameter>)* `>'
 \end{grammar}
 
-\LMHash{}
-A type parameter $T$ may be suffixed with an \EXTENDS{} clause that specifies the {\em upper bound} for $T$.
+\LMHash{}%
+A type parameter $T$ may be suffixed with an \EXTENDS{} clause that specifies the \Index{upper bound} for $T$.
 If no \EXTENDS{} clause is present, the upper bound is \code{Object}.
 It is a compile-time error if a type parameter is a supertype of its upper bound
 when that upper bound is itself a type variable.
@@ -3665,7 +3787,7 @@
 \code{X \EXTENDS{} Y, Y \EXTENDS{} X}.
 }
 
-\LMHash{}
+\LMHash{}%
 Type parameters are declared in the type parameter scope of a class or function.
 The type parameters of a generic $G$ are in scope in the bounds of all of the type parameters of $G$.
 The type parameters of a generic class declaration $G$ are also in scope in the \EXTENDS{} and \IMPLEMENTS{} clauses of $G$ (if these exist) and in the body of $G$.
@@ -3754,25 +3876,25 @@
 \subsection{Variance}
 \LMLabel{variance}
 
-\LMHash{}
-We say that a type $S$ {\em occurs covariantly} in a type $T$ if{}f
+\LMHash{}%
+We say that a type $S$ \Index{occurs covariantly} in a type $T$ if{}f
 $S$ occurs in a covariant position in $T$,
 but not in a contravariant position,
 and not in an invariant position.
 
-\LMHash{}
-We say that a type $S$ {\em occurs contravariantly} in a type $T$ if{}f
+\LMHash{}%
+We say that a type $S$ \Index{occurs contravariantly} in a type $T$ if{}f
 $S$ occurs in a contravariant position in $T$,
 but not in a covariant position,
 and not in an invariant position.
 
-\LMHash{}
-We say that a type $S$ {\em occurs invariantly} in a type $T$ if{}f
+\LMHash{}%
+We say that a type $S$ \Index{occurs invariantly} in a type $T$ if{}f
 $S$ occurs in an invariant position in $T$,
 or $S$ occurs in a covariant position as well as a contravariant position.
 
-\LMHash{}
-We say that a type $S$ occurs {\em in a covariant position} in a type $T$
+\LMHash{}%
+We say that a type $S$ occurs in a \Index{covariant position} in a type $T$
 if{}f one of the following conditions is true:
 
 \begin{itemize}
@@ -3820,8 +3942,8 @@
   and $S$ occurs in a contravariant position in $S_j$.
 \end{itemize}
 
-\LMHash{}
-We say that a type $S$ occurs {\em in a contravariant position} in a type $T$
+\LMHash{}%
+We say that a type $S$ occurs in a \Index{contravariant position} in a type $T$
 if{}f one of the following conditions is true:
 
 \begin{itemize}
@@ -3868,8 +3990,8 @@
   and $S$ occurs in a covariant position in $S_j$.
 \end{itemize}
 
-\LMHash{}
-We say that a type $S$ occurs {\em in an invariant position} in a type $T$
+\LMHash{}%
+We say that a type $S$ occurs in an \Index{invariant position} in a type $T$
 if{}f one of the following conditions is true:
 
 \begin{itemize}
@@ -3906,17 +4028,21 @@
   and $S$ occurs in $S_j$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Consider a generic type alias declaration $G$
 with formal type parameter declarations
 $X_1\ \EXTENDS\ B_1, \ldots,\ X_m\ \EXTENDS\ B_m$,
 and right hand side $T$.
 Let $j \in 1 .. m$.
 %
-We say that {\em the formal type parameter} $X_j$ {\em is invariant}
-if{}f $X_j$ occurs invariantly in $T$,
-$X_j$ {\em is covariant} if{}f $X_j$ occurs covariantly in $T$,
-and $X_j$ {\em is contravariant} if{}f $X_j$ occurs contravariantly in $T$.
+We say that
+\IndexCustom{the formal type parameter $X_j$ is invariant}{%
+  type parameter!invariant}
+if{}f $X_j$ occurs invariantly in $T$, $X_j$
+\IndexCustom{is covariant}{type parameter!covariant}
+if{}f $X_j$ occurs covariantly in $T$, and $X_j$
+\IndexCustom{is contravariant}{type parameter!contravariant}
+if{}f $X_j$ occurs contravariantly in $T$.
 
 \rationale{
 Variance gives a characterization of the way a type varies
@@ -3938,13 +4064,13 @@
 \subsection{Super-Bounded Types}
 \LMLabel{superBoundedTypes}
 
-\LMHash{}
+\LMHash{}%
 This section describes how
 the declared upper bounds of formal type parameters are enforced,
 including some cases where a limited form of violation is allowed.
 
-\LMHash{}
-A {\em top type} is a type $T$ such that \code{Object} is a subtype of $T$.
+\LMHash{}%
+A \Index{top type} is a type $T$ such that \code{Object} is a subtype of $T$.
 \commentary{
 For instance, \code{Object}, \DYNAMIC, and \VOID{} are top types,
 and so are \code{FutureOr<\VOID>} and \code{FutureOr<FutureOr<\DYNAMIC>{}>}.
@@ -3957,22 +4083,22 @@
 % require that types must be regular-bounded when used in certain
 % situations.
 
-\LMHash{}
-Every type which is not a parameterized type is {\em regular-bounded}.
+\LMHash{}%
+Every type which is not a parameterized type is \Index{regular-bounded}.
 
 \commentary{
 In particular, every non-generic class and every function type
 is a regular-bounded type.
 }
 
-\LMHash{}
+\LMHash{}%
 Let $T$ be a parameterized type of the form
 \code{$G$<$S_1, \ldots,\ S_n$>}
 where $G$ denotes a generic class or a generic type alias.
 Let
 \code{$X_1\ \EXTENDS\ B_1, \ldots,\ X_n\ \EXTENDS\ B_n$}
 be the formal type parameter declarations of $G$.
-$T$ is {\em regular-bounded} if{}f
+$T$ is \Index{regular-bounded} if{}f
 $S_j$ is a subtype of
 $[S_1/X_1, \ldots,\ S_n/X_n]B_j$,
 for all $j \in 1 .. n$.
@@ -3982,11 +4108,11 @@
 that do not violate their type parameter bounds.
 }
 
-\LMHash{}
+\LMHash{}%
 Let $T$ be a parameterized type of the form
 \code{$G$<$S_1, \ldots,\ S_n$>}
 where $G$ denotes a generic class or a generic type alias.
-$T$ is {\em super-bounded} if{}f the following conditions are both true:
+$T$ is \Index{super-bounded} if{}f the following conditions are both true:
 
 \begin{itemize}
 \item
@@ -4013,14 +4139,14 @@
 opposite extreme type, depending on their variance.
 }
 
-\LMHash{}
-A type $T$ is {\em well-bounded} if{}f
+\LMHash{}%
+A type $T$ is \Index{well-bounded} if{}f
 it is either regular-bounded or super-bounded.
 
-\LMHash{}
+\LMHash{}%
 Any use of a type $T$ which is not well-bounded is a compile-time error.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a parameterized type $T$ is super-bounded
 when it is used in any of the following ways:
 \begin{itemize}
@@ -4130,14 +4256,14 @@
 \section{Metadata}
 \LMLabel{metadata}
 
-\LMHash{}
+\LMHash{}%
 Dart supports metadata which is used to attach user defined annotations to program structures.
 
 \begin{grammar}
 <metadata> ::= (`@' <qualified> (`.' <identifier>)? (<arguments>)?)*
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Metadata consists of a series of annotations, each of which begin with the character @, followed by a constant expression that starts with an identifier.
 It is a compile-time error if the expression is not one of the following:
 \begin{itemize}
@@ -4145,7 +4271,7 @@
 \item A call to a constant constructor.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Metadata is associated with the abstract syntax tree of the program construct $p$ that immediately follows the metadata, assuming $p$ is not itself metadata or a comment.
 Metadata can be retrieved at run time via a reflective call, provided the annotated program construct $p$ is accessible via reflection.
 
@@ -4165,24 +4291,29 @@
 As noted above, the data can be retrieved statically if source code is available.
 }
 
-\LMHash{}
+\LMHash{}%
 Metadata can appear before a library, part header, class, typedef, type parameter, constructor, factory, function, parameter, or variable declaration and before an import, export or part directive.
 
-\LMHash{}
+\LMHash{}%
 The constant expression given in an annotation is type checked and evaluated in the scope surrounding the declaration being annotated.
 
 
 \section{Expressions}
 \LMLabel{expressions}
 
-\LMHash{}
+\LMHash{}%
 \label{evaluation}
-An {\em expression} is a fragment of Dart code that can be evaluated at run time.
-Evaluating an expression either {\em produces a value} (an object),
-or it {\em throws} an exception object and an associated stack trace.
-In the former case, we also say that the expression {\em evaluates to a value}.
+An \Index{expression} is a fragment of Dart code that can be evaluated at run time.
+Evaluating an expression either
+\IndexCustom{produces a value}{expression!produces a value}
+(an object),
+or it
+\IndexCustom{throws}{expression!throws}
+an exception object and an associated stack trace.
+In the former case, we also say that the expression
+\NoIndex{evaluates to a value}.
 
-\LMHash{}
+\LMHash{}%
 Every expression has an associated static type (\ref{staticTypes}) and
 may have an associated static context type.
 \commentary{The static context type represents
@@ -4193,7 +4324,7 @@
 of the expression.
 Every value has an associated dynamic type (\ref{dynamicTypeSystem}).
 
-\LMHash{}
+\LMHash{}%
 If evaluation of one expression, $e$, is defined in terms of evaluation of another expression, typically a subexpression of $e$,
 and the evaluation of the other expression throws an exception and a stack trace,
 the evaluation of $e$ stops at that point and throws the same exception object and stack trace.
@@ -4220,7 +4351,7 @@
   \alt `(' <expression> `)'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 An expression $e$ may always be enclosed in parentheses, but this never has any semantic effect on $e$.
 
 \commentary{
@@ -4232,7 +4363,7 @@
 \subsection{Object Identity}
 \LMLabel{objectIdentity}
 
-\LMHash{}
+\LMHash{}%
 The predefined Dart function \code{identical()} is defined such that \code{identical($c_1$, $c_2$)} if{}f:
 \begin{itemize}
 \item $c_1$ evaluates to either the null object (\ref{null}) or an instance of \code{bool} and \code{$c_1$ == $c_2$}, OR
@@ -4274,7 +4405,7 @@
 All usages of the word 'constant' in Dart are associated with compile time.
 A potentially constant expression is an expression that will generally yield
 a constant value when the value of certain parameters is given.
-The constant expressions is a subset of the potentially constant expressions that {\em can} be evaluated entirely at compile time.
+The constant expressions is a subset of the potentially constant expressions that \emph{can} be evaluated entirely at compile time.
 }
 
 \rationale{
@@ -4284,8 +4415,11 @@
 only members of the system classes \code{int}, \code{double}, \code{bool}, \code{String} or \code{Null}.
 }
 
-\LMHash{}
-The {\em potentially constant expressions} and {\em constant expressions} are the following:
+\LMHash{}%
+The \IndexCustom{potentially constant expressions}{%
+  potentially constant expression}
+and \IndexCustom{constant expressions}{constant expression}
+are the following:
 
 \begin{itemize}
 \item A literal boolean, \TRUE{} or \FALSE{} (\ref{booleans}), is a potentially constant and constant expression.
@@ -4326,7 +4460,7 @@
 \item A constant object expression (\ref{const}),
 \code{\CONST{} $C$<$T_1,\ \ldots,\ T_k$>(\metavar{arguments})} or
 \code{\CONST{} $C$<$T_1,\ \ldots,\ T_k$>.\id(\metavar{arguments})},
-or either expression without the leading \CONST{} that occurs in a constant context, is a potentially constant expression if $T_1$, \ldots{}, $T_k$ are constant type expressions, and the actual argument expressions in \metavar{arguments} are constant expressions.
+or either expression without the leading \CONST{} that occurs in a constant context, is a potentially constant expression.
 It is further a constant expression if the invocation evaluates to a value.
 % \ref{const} requires each actual argument to be a constant expression,
 % but here we also catch errors during evaluation, e.g., `C(1, 0)` where
@@ -4341,15 +4475,10 @@
 It is further a constant expression if the list literal evaluates to a value.
 
 \item A constant map literal (\ref{maps}),
-\code{\CONST{} <$K$, $V$>\{$k_1$: $v_1$, \ldots{}, $k_n$: $v_n$\}}
-is a potentially constant expression if
-\begin{itemize}
-  \item $K$ and $V$ are constant type expressions,
-  \item $k_1$, \ldots{}, $k_n$ are constant expressions evaluating to values that are either \code{int} or \code{String} instances, created using a symbol literal or a const invocation of the \code{Symbol} constructor, or instances of classes that that do not override the \code{==} operator inherited from \code{Object}, and
-  \item $v_1$, \ldots{}, $v_n$ are constant expressions.
-\end{itemize}
+\code{\CONST{} <$K$, $V$>\{$k_1$: $v_1$, \ldots{}, $k_n$: $v_n$\}}, or
+\code{<$K$, $V$>\{$k_1$: $v_1$, \ldots{}, $k_n$: $v_n$\}} that occurs in a constant context,
+is a potentially constant expression.
 It is further a constant expression if the map literal evaluates to a value.
-%Should we also require the key instances to not override hashCode? Because Symbols do.
 
 \item A parenthesized expression \code{($e$)} is a potentially constant expression if $e$ is a potentially constant expression. It is further a constant expression if $e$ is a constant expression.
 
@@ -4419,7 +4548,7 @@
 
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 % New in 2.1.
 A constant type expression is one of:
 \begin{itemize}
@@ -4448,7 +4577,7 @@
 % A validly typed potentially constant expression can still fail when evaluated.
 % If that happens in a const invociation, it's a compile-time error.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if an expression is required to be a constant expression but its evaluation would throw an exception.
 It is a compile-time error if an assertion is evaluated as part of a constant object expression evaluation, and the assertion would throw an exception.
 
@@ -4515,7 +4644,7 @@
 \code{\CONST{} C(foo): \THIS.foo = foo ?? someDefaultValue;}
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the value of a constant expression depends on itself.
 
 \commentary{
@@ -4544,14 +4673,14 @@
 \subsection{Null}
 \LMLabel{null}
 
-\LMHash{}
-The reserved word \NULL{} evaluates to the {\em null object}.
+\LMHash{}%
+The reserved word \NULL{} evaluates to the \Index{null object}.
 
 \begin{grammar}
 <nullLiteral> ::= \NULL{}
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 The null object is the sole instance of the built-in class \code{Null}.
 Attempting to instantiate \code{Null} causes a run-time error.
 It is a compile-time error for a class to extend, mix in or implement \code{Null}.
@@ -4559,15 +4688,16 @@
 \commentary{As such, it does not override the \code{==} operator inherited
 from the \code{Object} class.}
 
-\LMHash{}
+\LMHash{}%
 The static type of \NULL{} is the \code{Null} type.
 
 
 \subsection{Numbers}
 \LMLabel{numbers}
 
-\LMHash{}
-A {\em numeric literal} is either a decimal or hexadecimal numeral representing an integer value, or a decimal double representation.
+\LMHash{}%
+A \IndexCustom{numeric literal}{literal!numeric}
+is either a decimal or hexadecimal numeral representing an integer value, or a decimal double representation.
 
 \begin{grammar}
 <numericLiteral> ::= <NUMBER>
@@ -4586,20 +4716,22 @@
   \alt <DIGIT>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 A numeric literal starting with `0x' or `0X'
-is a {\em hexadecimal integer literal}.
+is a \IndexCustom{hexadecimal integer literal}{literal!hexadecimal integer}.
 It has the numeric integer value of the hexadecimal numeral
 following `0x' (respectively `0X').
 
-\LMHash{}
-A numeric literal that contains only decimal digits is a {\em decimal integer literal}.
+\LMHash{}%
+A numeric literal that contains only decimal digits is a
+\IndexCustom{decimal integer literal}{literal!decimal integer}.
 It has the numeric integer value of the decimal numeral.
 
-\LMHash{}
-An {\em integer literal} is either a hexadecimal integer literal or a decimal integer literal.
+\LMHash{}%
+An \IndexCustom{integer literal}{literal!integer}
+is either a hexadecimal integer literal or a decimal integer literal.
 
-\LMHash{}
+\LMHash{}%
 Let $l$ be an integer literal that is not the operand
 of by a unary minus operator,
 and let $T$ be the static context type of $l$.
@@ -4611,12 +4743,13 @@
   when it would satisfy the type requirement, and an \code{int} would not. Otherwise it is an \code{int}, even in situations where that is an error.
 }
 
-\LMHash{}
-A numeric literal that is not an integer literal is a {\em double literal}.
+\LMHash{}%
+A numeric literal that is not an integer literal is a
+\IndexCustom{double literal}{literal!double}.
 \commentary{A double literal always contains either a decimal point or an exponent part.}
 The static type of a double literal is \code{double}.
 
-\LMHash{}
+\LMHash{}%
 If $l$ is an integer literal with numeric value $i$ and static type \code{int},
 and $l$ is not the operand of a unary minus operator,
 then evaluation of $l$ proceeds as follows:
@@ -4642,16 +4775,16 @@
 exactly.
 }
 
-\LMHash{}
+\LMHash{}%
 A double literal evaluates to a an instance of the \code{double} class
 representing a 64 bit double precision floating point number
 as specified by the IEEE 754 standard.
 
-\LMHash{}
+\LMHash{}%
 An integer literal with static type \code{double} and numeric value $i$
 evaluates to an instance of the \code{double} class representing
 the value $i$. It is a compile-time error if the value $i$ cannot be
-represented {\em precisely} by the an instance of \code{double}.
+represented \emph{precisely} by the an instance of \code{double}.
 \commentary{
 A 64 bit double precision floating point number
 is usually taken to represent a range of real numbers
@@ -4662,36 +4795,40 @@
 is the precise value of the \code{double} instance.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error for a class to extend, mix in or implement \code{int}.
 It is a compile-time error for a class to extend, mix in or implement \code{double}.
 It is a compile-time error for any class other than \code{int} and \code{double} to extend, mix in or implement \code{num}.
 
-\LMHash{}
+\LMHash{}%
 The instances of \code{int} and \code{double} all override the \code{==} operator inherited from the \code{Object} class.
 
 \subsection{Booleans}
 \LMLabel{booleans}
 
-\LMHash{}
-The reserved words \TRUE{} and \FALSE{} evaluate to objects {\em true} and {\em false} that represent the boolean values true and false respectively.
-They are the {\em boolean literals}.
+\LMHash{}%
+The reserved words \TRUE{} and \FALSE{} evaluate to objects
+\IndexCustom{true}{true, the object} and
+\IndexCustom{false}{false, the object}
+that represent the boolean values true and false respectively.
+They are the \IndexCustom{boolean literals}{literal!boolean}.
 
 \begin{grammar}
 <booleanLiteral> ::= \TRUE{}
   \alt \FALSE{}
 \end{grammar}
 
-\LMHash{}
-Both {\em true} and {\em false} are instances of the built-in class \code{bool},
+\LMHash{}%
+Both \NoIndex{true} and \NoIndex{false} are instances of
+the built-in class \code{bool},
 and there are no other objects that implement \code{bool}.
 It is a compile-time error for a class to extend, mix in or implement \code{bool}.
 
-\LMHash{}
+\LMHash{}%
 The \code{bool} class does not override the \code{==} operator inherited from
 the \code{Object} class.
 
-\LMHash{}
+\LMHash{}%
 Invoking the getter \code{runtimeType} on a boolean value returns the \code{Type} object that is the value of the expression \code{bool}.
 The static type of a boolean literal is \code{bool}.
 
@@ -4699,8 +4836,8 @@
 \subsection{Strings}
 \LMLabel{strings}
 
-\LMHash{}
-A {\em string} is a sequence of UTF-16 code units.
+\LMHash{}%
+A \Index{string} is a sequence of UTF-16 code units.
 
 \rationale{
 This decision was made for compatibility with web browsers and Javascript.
@@ -4712,7 +4849,7 @@
 <stringLiteral> ::= (<multilineString> | <singleLineString>)+
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 A string can be a sequence of single line strings and multiline strings.
 
 \begin{grammar}
@@ -4722,7 +4859,7 @@
   \alt `r"' (\~{}( `"' | <NEWLINE>))* `"'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 A single line string is delimited by either matching single quotes or matching double quotes.
 
 \commentary{
@@ -4734,7 +4871,7 @@
 The grammar ensures that a single line string cannot span more than one line of source code, unless it includes an interpolated expression that spans multiple lines.
 }
 
-\LMHash{}
+\LMHash{}%
 Adjacent strings are implicitly concatenated to form a single string literal.
 
 \commentary{
@@ -4798,13 +4935,14 @@
   \alt `\\u' <HEX\_DIGIT> <HEX\_DIGIT> <HEX\_DIGIT> <HEX\_DIGIT>
   \alt `\\u{' <HEX\_DIGIT\_SEQUENCE> `}'
 
-<HEX\_DIGIT\_SEQUENCE> ::= <HEX\_DIGIT> <HEX\_DIGIT>? <HEX\_DIGIT>?
+<HEX\_DIGIT\_SEQUENCE> ::= \gnewline{}
+  <HEX\_DIGIT> <HEX\_DIGIT>? <HEX\_DIGIT>?
   \gnewline{} <HEX\_DIGIT>? <HEX\_DIGIT>? <HEX\_DIGIT>?
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Multiline strings are delimited by either matching triples of single quotes or matching triples of double quotes.
-If the first line of a multiline string consists solely of the whitespace characters defined by the production {\em WHITESPACE} (\ref{lexicalRules}), possibly prefixed by \syntax{`\\'}, then that line is ignored, including the line break at its end.
+If the first line of a multiline string consists solely of the whitespace characters defined by the production \synt{WHITESPACE} (\ref{lexicalRules}), possibly prefixed by \syntax{`\\'}, then that line is ignored, including the line break at its end.
 
 \rationale{
 The idea is to ignore a whitespace-only first line of a multiline string, where whitespace is defined as tabs, spaces and the final line break.
@@ -4815,7 +4953,7 @@
  %    """ ignored not. It depends if we mean whitespace before escapes are interpreted,
  % or after, or both.  See https://code.google.com/p/dart/issues/detail?id=23020
 
-\LMHash{}
+\LMHash{}%
 Strings support escape sequences for special characters.
 The escapes are:
 \begin{itemize}
@@ -4830,6 +4968,8 @@
 \syntax{`\\u{' <HEX\_DIGIT>$_1$ <HEX\_DIGIT>$_2$ `}'}.
 \item \syntax{`\\u' <HEX\_DIGIT>$_1$ <HEX\_DIGIT>$_2$ <HEX\_DIGIT>$_3$ <HEX\_DIGIT>$_4$},
 equivalent to
+
+\noindent
 \syntax{`\\u{' <HEX\_DIGIT>$_1$ <HEX\_DIGIT>$_2$ <HEX\_DIGIT>$_3$ <HEX\_DIGIT>$_4$ `}'}.
 \item \syntax{`\\u{' <HEX\_DIGIT\_SEQUENCE> `}'} is the Unicode code point represented by the
 \syntax{<HEX\_DIGIT\_SEQUENCE>}.
@@ -4841,16 +4981,16 @@
 \syntax{$\{$`n', `r', `f', `b', `t', `v', `x', `u'$\}$}.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Any string may be prefixed with the character \syntax{`r'},
-indicating that it is a {\em raw string},
+indicating that it is a \Index{raw string},
 in which case no escapes or interpolations are recognized.
 
-\LMHash{}
+\LMHash{}%
 Line breaks in a multiline string are represented by the \syntax{<NEWLINE>} production.
 A line break introduces a single newline character into the string value.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a non-raw string literal contains a character sequence of the form \syntax{`\\x'} that is not followed by a sequence of two hexadecimal digits.
 It is a compile-time error if a non-raw string literal contains a character sequence of the form \syntax{`\\u'} that is not followed by either a sequence of four hexadecimal digits, or by curly brace delimited sequence of hexadecimal digits.
 
@@ -4876,7 +5016,7 @@
   \alt `\\r\\n'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 All string literals evaluate to instances of the built-in class \code{String}.
 It is a compile-time error for a class to extend, mix in or implement \code{String}.
 The \code{String} class overrides the \code{==} operator inherited from
@@ -4887,9 +5027,9 @@
 \subsubsection{String Interpolation}
 \LMLabel{stringInterpolation}
 
-\LMHash{}
+\LMHash{}%
 It is possible to embed expressions within non-raw string literals, such that these expressions are evaluated, and the resulting values are converted into strings and concatenated with the enclosing string.
-This process is known as {\em string interpolation}.
+This process is known as \Index{string interpolation}.
 
 \begin{grammar}
 <stringInterpolation> ::= `$' <IDENTIFIER\_NO\_DOLLAR>
@@ -4900,7 +5040,7 @@
 The reader will note that the expression inside the interpolation could itself include strings, which could again be interpolated recursively.
 }
 
-\LMHash{}
+\LMHash{}%
 An unescaped \syntax{`$'} character in a string signifies the beginning of an interpolated expression.
 The \syntax{`$'} sign may be followed by either:
 \begin{itemize}
@@ -4908,7 +5048,7 @@
 \item An expression $e$ delimited by curly braces.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 The form \code{\$\id} is equivalent to the form \code{\$\{\id\}}.
 An interpolated string, $s$, with content
 `\code{$s_0$\$\{$e_1$\}$s_1\ldots{}s_{n-1}$\$\{$e_n$\}$s_{n}$}' (where any of $s_0, \ldots, s_n$ can be empty)
@@ -4925,15 +5065,16 @@
 \subsection{Symbols}
 \LMLabel{symbols}
 
-\LMHash{}
-A {\em symbol literal} denotes a name that would be either
+\LMHash{}%
+A \IndexCustom{symbol literal}{literal!symbol}
+denotes a name that would be either
 a valid declaration name or a valid library name in a Dart program.
 
 \begin{grammar}
 <symbolLiteral> ::= `#' (<operator> | (<identifier> (`.' <identifier>)*))
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 A symbol literal \code{\#\id} where \id{} is an identifier
 that does not begin with an underscore ('\code{\_}'),
 evaluates to an instance of \code{Symbol} representing the identifier \id.
@@ -4943,7 +5084,7 @@
 or to a \code{Symbol} instance that is equal
 (according to the \code{==} operator \ref{equality}) to that instance.
 
-\LMHash{}
+\LMHash{}%
 A symbol literal \code{\#$\id.\id_2\ldots\id_n$}
 where $\id{} \ldots \id_n$ are identifiers,
 evaluates to an instance of \code{Symbol} representing that particular sequence of identifiers.
@@ -4954,21 +5095,21 @@
 \commentary{This kind of symbol literal denotes the name of a library declaration. Library names are not subject to library privacy, even
 if some of its identifiers begin with an underscore.}
 
-\LMHash{}
+\LMHash{}%
 A symbol literal \code{\#\metavar{operator}} evaluates to an instance of \code{Symbol}
 representing that particular operator name.
 All occurrences of \code{\#\metavar{operator}} evaluate to the same instance,
 and no other symbol literals evaluate to that \code{Symbol} instance
 or to a \code{Symbol} instance that is \code{==} to that instance.
 
-\LMHash{}
+\LMHash{}%
 A symbol literal \code{\#\_\id}, evaluates to an instance of \code{Symbol}
 representing the private identifier \code{\_\id} of the containing library.
-All occurrences of \code{\#\_\id} {\em in the same library} evaluate to the same instance,
+All occurrences of \code{\#\_\id} \emph{in the same library} evaluate to the same instance,
 and no other symbol literals evaluate to that \code{Symbol} instance
 or to a \code{Symbol} instance that is \code{==} to that instance.
 
-\LMHash{}
+\LMHash{}%
 The objects created by symbol literals all override
 the \code{==} operator inherited from the \code{Object} class.
 
@@ -4987,20 +5128,21 @@
 The fact that symbols are easy to type and can often act as convenient substitutes for enums are secondary benefits.
 }
 
-\LMHash{}
+\LMHash{}%
 The static type of a symbol literal is \code{Symbol}.
 
 \subsection{Lists}
 \LMLabel{lists}
 
-\LMHash{}
-A {\em list literal} denotes a list, which is an integer indexed collection of objects.
+\LMHash{}%
+A \IndexCustom{list literal}{literal!list}
+denotes a list, which is an integer indexed collection of objects.
 
 \begin{grammar}
 <listLiteral> ::= \CONST{}? <typeArguments>? `[' (<expressionList> `,'?)? `]'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 A list may contain zero or more objects.
 The number of elements in a list is its size.
 A list has an associated set of indices.
@@ -5008,22 +5150,27 @@
 A non-empty list has the index set $\{0, \ldots, n - 1\}$ where $n$ is the size of the list.
 It is a run-time error to attempt to access a list using an index that is not a member of its set of indices.
 
-\LMHash{}
-If a list literal begins with the reserved word \CONST{}, it is a {\em constant list literal} which is a constant expression (\ref{constants}) and therefore evaluated at compile time.
-Otherwise, it is a {\em run-time list literal} and it is evaluated at run time.
+\LMHash{}%
+If a list literal begins with the reserved word \CONST{}, it is a
+\IndexCustom{constant list literal}{literal!list!constant}
+which is a constant expression (\ref{constants}) and therefore evaluated at compile time.
+Otherwise, it is a
+\IndexCustom{run-time list literal}{literal!list!run-time}
+and it is evaluated at run time.
 Only run-time list literals can be mutated
 after they are created.
 Attempting to mutate a constant list literal will result in a dynamic error.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if an element of a constant list literal is not a constant expression.
 % Need 'free': `const <Function(Function<X>(X))>[]` is OK, but `X` is not free.
-It is a compile-time error if the type argument of a constant list literal is or contains a free type variable.
+It is a compile-time error if the type argument of a constant list literal is
+not a constant type expression.
 \rationale{
 The binding of a type parameter is not known at compile time, so we cannot use type parameters inside constant expressions.
 }
 
-\LMHash{}
+\LMHash{}%
 The value of a constant list literal
 \code{\CONST{} <$E$>[$e_1, \ldots, e_n$]}
 is an object $a$ whose class implements the built-in class
@@ -5034,7 +5181,7 @@
 is defined as the value of the constant list literal
 \code{\CONST{} <\DYNAMIC{}>[$e_1, \ldots, e_n$]}.
 
-\LMHash{}
+\LMHash{}%
 Let
 $list_1 =$ \code{\CONST{} <$V$>[$e_{11}, \ldots, e_{1n}$]}
 and
@@ -5046,7 +5193,7 @@
 In other words, constant list literals are canonicalized.
 }
 
-\LMHash{}
+\LMHash{}%
 A run-time list literal
 \code{<$E$>[$e_1, \ldots, e_n$]}
 is evaluated as follows:
@@ -5064,7 +5211,7 @@
 The result of the evaluation is $a$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 The objects created by list literals do not override
 the \code{==} operator inherited from the \code{Object} class.
 
@@ -5076,7 +5223,7 @@
 a dynamic type error will occur when $a[i]$ is assigned $o_{i-1}$.
 }
 
-\LMHash{}
+\LMHash{}%
 A run-time list literal
 \code{[$e_1, \ldots, e_n$]}
 is evaluated as
@@ -5090,13 +5237,13 @@
 containing two lists with type parameter \code{int}.
 }
 
-\LMHash{}
+\LMHash{}%
 The static type of a list literal of the form
 \code{\CONST{} <$E$>[$e_1, \ldots, e_n$]}
 or the form
 \code{<$E$>[$e_1, \ldots, e_n$]}
 is \code{List<$E$>}.
-The static type a list literal of the form
+The static type of a list literal of the form
 \code{\CONST{} [$e_1, \ldots, e_n$]}
 or the form
 \code{[$e_1, \ldots, e_n$]}
@@ -5106,8 +5253,8 @@
 \subsection{Maps}
 \LMLabel{maps}
 
-\LMHash{}
-A {\em map literal} denotes a map object.
+\LMHash{}%
+A \IndexCustom{map literal}{literal!map} denotes a map object.
 
 \begin{grammar}
 <mapLiteral> ::= \CONST{}? <typeArguments>?
@@ -5116,32 +5263,39 @@
 <mapLiteralEntry> ::= <expression> `:' <expression>
 \end{grammar}
 
-\LMHash{}
-A {\em map literal} consists of zero or more entries.
-Each entry has a {\em key} and a {\em value}.
+\LMHash{}%
+A map literal consists of zero or more entries.
+Each entry has a \Index{key} and a \Index{value}.
 Each key and each value is denoted by an expression.
 
-\LMHash{}
-If a map literal begins with the reserved word \CONST{}, it is a {\em constant map literal} which is a constant expression (\ref{constants}) and therefore evaluated at compile time.
-Otherwise, it is a {\em run-time map literal} and it is evaluated at run time.
+\LMHash{}%
+If a map literal begins with the reserved word \CONST{}, it is a
+\IndexCustom{constant map literal}{literal!map!constant}
+which is a constant expression (\ref{constants}) and therefore evaluated at compile time.
+Otherwise, it is a
+\IndexCustom{run-time map literal}{literal!map!run-time}
+and it is evaluated at run time.
 Only run-time map literals can be mutated after they are created.
 Attempting to mutate a constant map literal will result in a dynamic error.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if either a key or a value of an entry in a constant map literal is not a constant expression.
 It is a compile-time error if the key of an entry in a constant map literal is an instance of
 a class that has a concrete operator \syntax{`=='} declaration different from the one in \code{Object},
 unless the key is a string or an integer,
-or the key expression evaluates to an instance of the built-in
+the key expression evaluates to an instance of the built-in
 class \code{Symbol} which was originally obtained by evaluation of a
 literal symbol or
-a constant invocation of a constructor of the \code{Symbol} class.
+a constant invocation of a constructor of the \code{Symbol} class,
+or to an object implementing the built-in class \code{Type}
+which was originally obtained by evaluating a constant type literal
+(\ref{dynamicTypeSystem}).
 % Needs 'free': `const <int, Function(Function<X>(X))>{}` is OK, but
 % `X` is not free.
 It is a compile-time error if a type argument of a constant map literal
-is or contains a free type variable.
+is not a constant type expression \ref{constants}.
 
-\LMHash{}
+\LMHash{}%
 The value of a constant map literal
 \code{\CONST{} <$K, V$>\{$k_1:e_1, \ldots, k_n:e_n$\}}
 is an object $m$ whose class implements the built-in class
@@ -5152,7 +5306,7 @@
 is defined as the value of a constant map literal
 \code{\CONST{} <\DYNAMIC{}, \DYNAMIC{}>\{$k_1:e_1, \ldots, k_n:e_n$\}}.
 
-\LMHash{}
+\LMHash{}%
 Let
 $map_1 =$ \code{\CONST{} <$K, V$>\{$k_{11}:e_{11}, \ldots, k_{1n}:e_{1n}$\}}
 and
@@ -5165,7 +5319,7 @@
 In other words, constant map literals are canonicalized.
 }
 
-\LMHash{}
+\LMHash{}%
 A run-time map literal
 \code{<$K, V$>\{$k_1:e_1, \ldots, k_n:e_n$\}}
 is evaluated as follows:
@@ -5183,21 +5337,21 @@
 The result of the evaluation is $m$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 The objects created by map literals do not override
 the \code{==} operator inherited from the \code{Object} class.
 
-\LMHash{}
+\LMHash{}%
 A run-time map literal
 \code{\{$k_1:e_1, \ldots, k_n:e_n$\}}
 is evaluated as
 
 \code{<\DYNAMIC{}, \DYNAMIC{}>\{$k_1:e_1, \ldots, k_n:e_n$\}}.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if two keys of a constant map literal are equal.
 
-\LMHash{}
+\LMHash{}%
 A map literal is ordered: iterating over the keys and/or values of the maps always happens in the
  order the keys appeared in the source code.
 
@@ -5205,7 +5359,7 @@
 Of course, if a key repeats, the order is defined by first occurrence, but the value is defined by the last.
 }
 
-\LMHash{}
+\LMHash{}%
 The static type of a map literal of the form
 \code{\CONST{} <$K, V$>\{$k_1:e_1, \ldots, k_n:e_n$\}}
 or the form
@@ -5222,8 +5376,8 @@
 \subsection{Throw}
 \LMLabel{throw}
 
-\LMHash{}
-The {\em throw expression} is used to throw an exception.
+\LMHash{}%
+The \Index{throw expression} is used to throw an exception.
 
 \begin{grammar}
 <throwExpression> ::= \THROW{} <expression>
@@ -5231,43 +5385,44 @@
 <throwExpressionWithoutCascade> ::= \THROW{} <expressionWithoutCascade>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a throw expression of the form \code{\THROW{} $e$;} proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 The expression $e$ is evaluated to a value $v$ (\ref{evaluation}).
 
 \commentary{
 There is no requirement that the expression $e$ must evaluate to any special kind of object.
 }
 
-\LMHash{}
+\LMHash{}%
 If $v$ is the null object (\ref{null}), then a \code{NullThrownError} is thrown.
 Otherwise let $t$ be a stack trace corresponding to the current execution state,
 and the \THROW{} statement throws with $v$ as exception object
 and $t$ as stack trace (\ref{evaluation}).
 
-\LMHash{}
+\LMHash{}%
 If $v$ is an instance of class \code{Error} or a subclass thereof,
 and it is the first time that \code{Error} object is thrown,
 the stack trace $t$ is stored on $v$ so that it will be returned
 by the $v$'s \code{stackTrace} getter
 
 \commentary{
-If the same \code{Error} object is thrown more than once, its \code{stackTrace} getter will return the stack trace from the {\em first} time it was thrown.
+If the same \code{Error} object is thrown more than once, its \code{stackTrace} getter will return the stack trace from the \emph{first} time it was thrown.
 }
 
-\LMHash{}
+\LMHash{}%
 The static type of a throw expression is $\bot$.
 
 
 \subsection{Function Expressions}
 \LMLabel{functionExpressions}
 
-\LMHash{}
+\LMHash{}%
 %% TODO(eernst): A function literal is a syntactic construct, and we may use
 %% function closurization to obtain a corresponding function object.
-A {\em function literal} is an object that encapsulates an executable unit of code.
+A \IndexCustom{function literal}{literal!function}
+is an object that encapsulates an executable unit of code.
 
 \begin{grammar}
 <functionExpression> ::= <formalParameterPart> <functionBody>
@@ -5284,10 +5439,10 @@
 %% actually used to select the function literal signature must be described
 %% specifically for each relevant type of situation.
 
-\LMHash{}
+\LMHash{}%
 The class of a function literal implements the built-in class \FUNCTION{}.
 
-\LMHash{}
+\LMHash{}%
 The static type of a function literal of the form
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
@@ -5303,7 +5458,7 @@
 %% TODO[inference]: The static type of the function literal may come from context.
 where $T_0$ is the static type of $e$.
 
-\LMHash{}
+\LMHash{}%
 The static type of a function literal of the form
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
@@ -5320,7 +5475,7 @@
 \noindent
 where $T_0$ is the static type of $e$.
 
-\LMHash{}
+\LMHash{}%
 In the previous two paragraphs, the type argument lists are omitted in the case where $m = 0$, and \flatten{T} is defined as follows:
 
 \begin{itemize}
@@ -5349,7 +5504,7 @@
 \item In any other circumstance, $\flatten{T} = T$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 The static type of a function literal of the form
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
@@ -5364,7 +5519,7 @@
 \noindent
 where $T_0$ is the static type of $e$.
 
-\LMHash{}
+\LMHash{}%
 The static type of a function literal of the form
 
 \code{<$X_1 B_1, \ldots,\ X_m B_m$>}
@@ -5381,7 +5536,7 @@
 \noindent
 where $T_0$ is the static type of $e$.
 
-\LMHash{}
+\LMHash{}%
 The static type of a function literal of the form
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
@@ -5393,7 +5548,7 @@
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ [$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$]) $ \rightarrow$ \DYNAMIC{}}.
 
-\LMHash{}
+\LMHash{}%
 The static type of a function literal of the form
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
@@ -5405,7 +5560,7 @@
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ [$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$]) $ \rightarrow$ Future}.
 
-\LMHash{}
+\LMHash{}%
 The static type of a function literal of the form
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
@@ -5417,7 +5572,7 @@
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ [$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$]) $ \rightarrow$ Stream}.
 
-\LMHash{}
+\LMHash{}%
 The static type of a function literal of the form
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
@@ -5429,7 +5584,7 @@
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ [$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$]) $ \rightarrow$ Iterable}.
 
-\LMHash{}
+\LMHash{}%
 The static type of a function literal of the form
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
@@ -5441,7 +5596,7 @@
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ [$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$]) $ \rightarrow$ \DYNAMIC{}}.
 
-\LMHash{}
+\LMHash{}%
 The static type of a function literal of the form
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
@@ -5453,7 +5608,7 @@
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ \{$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$\}) $ \rightarrow$ Future}.
 
-\LMHash{}
+\LMHash{}%
 The static type of a function literal of the form
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
@@ -5465,7 +5620,7 @@
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ \{$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$\}) $ \rightarrow$ Stream}.
 
-\LMHash{}
+\LMHash{}%
 The static type of a function literal of the form
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>}
@@ -5477,7 +5632,7 @@
 
 \code{<$X_1\ B_1, \ldots,\ X_m\ B_m$>($T_1, \ldots,\ T_n, $ \{$T_{n+1}\ x_{n+1}, \ldots,\ T_{n+k}\ x_{n+k}$\}) $ \rightarrow$ Iterable}.
 
-\LMHash{}
+\LMHash{}%
 In all of the above cases,
 the type argument lists are omitted when $m=0$,
 and whenever $T_i, 1 \le i \le n+k$, is not specified,
@@ -5487,28 +5642,28 @@
 \subsection{This}
 \LMLabel{this}
 
-\LMHash{}
+\LMHash{}%
 The reserved word \THIS{} denotes the target of the current instance member invocation.
 
 \begin{grammar}
 <thisExpression> ::= \THIS{}
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 The static type of \THIS{} is the interface of the immediately enclosing class.
 
 \commentary{
 We do not support self-types at this point.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if \THIS{} appears, implicitly or explicitly, in a top-level function or variable initializer, in a factory constructor, or in a static method or variable initializer, or in the initializer of an instance variable.
 
 
 \subsection{Instance Creation}
 \LMLabel{instanceCreation}
 
-\LMHash{}
+\LMHash{}%
 Instance creation expressions generally produce instances
 and invoke constructors to initialize them.
 
@@ -5525,7 +5680,7 @@
 
 %It is a compile-time error if a constructor of a non-generic type invoked by a new expression or a constant object expression is passed any type arguments. It is a compile-time error if a constructor of a generic type with $n$ type parameters invoked by a new expression or a constant object expression is passed $m$ type arguments where $m \ne n$, or if any of its type arguments is misconstructed (\ref{parameterizedTypes}).
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if
 the type $T$ in an instance creation expression of one of the forms
 
@@ -5546,14 +5701,14 @@
 \subsubsection{New}
 \LMLabel{new}
 
-\LMHash{}
-The {\em new expression} invokes a constructor (\ref{constructors}).
+\LMHash{}%
+The \Index{new expression} invokes a constructor (\ref{constructors}).
 
 \begin{grammar}
 <newExpression> ::= \NEW{} <type> (`.' <identifier>)? <arguments>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Let $e$ be a new expression of the form
 
 \code{\NEW{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
@@ -5561,7 +5716,7 @@
 
 \code{\NEW{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $T$ is not
 a class or a parameterized type accessible in the current scope,
 or if $T$ is a parameterized type which is not a class.
@@ -5569,7 +5724,7 @@
 For instance, \code{\NEW{} F<int>()} is an error if \code{F} is a type alias.
 }
 
-\LMHash{}
+\LMHash{}%
 If $T$ is a parameterized type (\ref{parameterizedTypes})
 \code{$S$<$U_1, \ldots,\ U_m$>},
 let $R$ be the generic class $S$,
@@ -5591,10 +5746,10 @@
   a constructor declared by $R$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Let $q$ be the above-mentioned constructor named \code{$R$.\id} or $R$.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $R$ is abstract
 and $q$ is not a factory constructor.
 It is a compile-time error if $R$ is a non-generic class
@@ -5611,7 +5766,7 @@
 and $T$ is not regular-bounded
 (\ref{superBoundedTypes}).
 
-\LMHash{}
+\LMHash{}%
 If $q$ is a redirecting factory constructor,
 it is a compile-time error if $q$ in some number of
 redirecting factory redirections redirects to itself.
@@ -5624,7 +5779,7 @@
 are detected at compile time.
 }
 
-\LMHash{}
+\LMHash{}%
 Let $S_i$ be the static type of
 the formal parameter of the constructor \code{$R$.\id} (respectively $R$)
 corresponding to the actual argument $a_i$, $i \in 1 .. n+k$.
@@ -5635,13 +5790,13 @@
 The non-generic case is covered with $m = 0$.
 }
 
-\LMHash{}
+\LMHash{}%
 The static type of $e$ is $T$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of $e$ proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 First, the argument part
 
 \code{<$U_1, \ldots,\ U_m$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
@@ -5659,11 +5814,11 @@
 $[u_1/X_1, \ldots, u_m/X_m]S_j$,
 a dynamic type error occurs.
 
-\LMHash{}
+\LMHash{}%
 \Case{Non-loaded deferred constructors}
 If $T$ is a deferred type with prefix $p$, then if $p$ has not been successfully loaded, a dynamic error occurs.
 
-\LMHash{}
+\LMHash{}%
 \Case{Generative constructors}
 When $q$ is a generative constructor
 (\ref{generativeConstructors})
@@ -5679,13 +5834,13 @@
 if $R$ is a generic class,
 with its type parameters bound to $u_1, \ldots, u_m$.
 
-\LMHash{}
+\LMHash{}%
 If execution of $q$ completes normally (\ref{completion}), $e$ evaluates to $i$.
 Otherwise execution of $q$ throws an exception object $x$ and stack trace $t$,
 and then evaluation of $e$ also throws exception object $x$ and stack trace $t$
 (\ref{evaluation}).
 
-\LMHash{}
+\LMHash{}%
 \Case{Redirecting factory constructors}
 When $q$ is a redirecting factory constructor
 (\ref{factories})
@@ -5702,7 +5857,7 @@
 We need access to the type variables because $c$ may contain them.
 }
 
-\LMHash{}
+\LMHash{}%
 \Case{Non-redirecting factory constructors}
 When $q$ is a non-redirecting factory constructor,
 the body of $q$ is executed with respect to
@@ -5725,15 +5880,15 @@
 \subsubsection{Const}
 \LMLabel{const}
 
-\LMHash{}
-A {\em constant object expression} invokes a constant constructor
+\LMHash{}%
+A \Index{constant object expression} invokes a constant constructor
 (\ref{constantConstructors}).
 
 \begin{grammar}
 <constObjectExpression> ::= \CONST{} <type> (`.' <identifier>)? <arguments>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Let $e$ be a constant object expression of the form
 
 \code{\CONST{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
@@ -5741,7 +5896,7 @@
 
 \code{\CONST{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $T$ is not
 a class or a parameterized type accessible in the current scope,
 or if $T$ is a parameterized type which is not a class.
@@ -5751,11 +5906,11 @@
 In particular, $T$ must not be a type variable.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $a_i$ is not a constant expression
 for some $i \in 1 .. n + k$.
 
-\LMHash{}
+\LMHash{}%
 If $T$ is a parameterized type (\ref{parameterizedTypes})
 \code{$S$<$U_1, \ldots,\ U_m$>},
 let $R$ be the generic class $S$,
@@ -5764,9 +5919,9 @@
 be the formal type parameters of $S$.
 If $T$ is not a parameterized type, let $R$ be $T$.
 
-\LMHash{}
+\LMHash{}%
 If $T$ is a parameterized type,
-it is a compile-time error if $U_j$ contains a type variable for any
+it is a compile-time error if $U_j$ is not a constant type expression for any
 $j \in 1 .. m$.
 
 \begin{itemize}
@@ -5782,14 +5937,14 @@
   a constant constructor declared by $R$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Let $q$ be the above-mentioned constant constructor named \code{$R$.\id} or $R$.
 
 %% TODO(eernst): These errors are the same as with `new`. Can we avoid
 %% stating them twice? We'd need to refer to an awkwardly shaped portion
 %% of text in the previous subsection, or just loosely say "exactly the
 %% same errors"..
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $R$ is abstract
 and $q$ is not a factory constructor.
 It is a compile-time error if $R$ is a non-generic class
@@ -5806,7 +5961,7 @@
 and $T$ is not regular-bounded
 (\ref{superBoundedTypes}).
 
-\LMHash{}
+\LMHash{}%
 Let $S_i$ be the static type of
 the formal parameter of the constructor \code{$R$.\id} (respectively $R$)
 corresponding to the actual argument $a_i$, $i \in 1 .. n+k$.
@@ -5817,13 +5972,13 @@
 The non-generic case is covered with $m = 0$.
 }
 
-\LMHash{}
+\LMHash{}%
 The static type of $e$ is $T$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of $e$ proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 If $e$ is of the form
 \code{\CONST{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
 let $i$ be the value of the expression $e'$:
@@ -5839,7 +5994,7 @@
 This means that the value is well-defined.
 }
 
-\LMHash{}
+\LMHash{}%
 If $e$ is of the form
 \code{\CONST{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
 let $i$ be the value of
@@ -5848,7 +6003,7 @@
 Which is well-defined for the same reason.
 }
 
-\LMHash{}
+\LMHash{}%
 \begin{itemize}
 \item If during execution of the program,
   a constant object expression has already evaluated to
@@ -5876,7 +6031,7 @@
 The constructor need only be executed once per call site, at compile time.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if evaluation of a constant object
 results in an uncaught exception being thrown.
 
@@ -5918,11 +6073,11 @@
 \subsection{Spawning an Isolate}
 \LMLabel{spawningAnIsolate}
 
-\LMHash{}
+\LMHash{}%
 Spawning an isolate is accomplished via what is syntactically an ordinary library call, invoking one of the functions \code{spawnUri()} or \code{spawn()} defined in the \code{dart:isolate} library.
 However, such calls have the semantic effect of creating a new isolate with its own memory and thread of control.
 
-\LMHash{}
+\LMHash{}%
 An isolate's memory is finite, as is the space available to its thread's call stack.
 It is possible for a running isolate to exhaust its memory or stack, resulting in a run-time error that cannot be effectively caught, which will force the isolate to be suspended.
 
@@ -5934,7 +6089,7 @@
 \subsection{Function Invocation}
 \LMLabel{functionInvocation}
 
-\LMHash{}
+\LMHash{}%
 Function invocation occurs in the following cases:
 when a function expression (\ref{functionExpressions}) is invoked (\ref{functionExpressionInvocation}),
 when a method (\ref{methodInvocation}), getter (\ref{topLevelGetterInvocation}, \ref{propertyExtraction}) or setter (\ref{assignment}) is invoked,
@@ -5946,11 +6101,11 @@
 and the formal parameters of $f$ are bound to corresponding actual arguments.
 When the body of $f$ is executed it will be executed with the aforementioned bindings.
 
-\LMHash{}
+\LMHash{}%
 Executing a body of the form \code{=> $e$} is equivalent to executing a body of the form \code{\{ return $e$; \}}.
 Execution a body of the form \code{\ASYNC{} => $e$} is equivalent to executing a body of the form \code{\ASYNC{} \{ return $e$; \}}.
 
-\LMHash{}
+\LMHash{}%
 If $f$ is synchronous and is not a generator (\ref{functions}) then execution of the body of $f$ begins immediately.
 If the execution of the body of $f$ returns a value, $v$, (\ref{completion}), the invocation evaluates to $v$.
 If the execution completes normally or it returns without a value, the invocation evaluates to the null object (\ref{null}).
@@ -5963,7 +6118,7 @@
 Completing normally or returning without a value is treated the same as returning the null object (\ref{null}), so the result of executing a function body can always be used as the result of evaluating an expression, either by evaluating to a value or by the evaluation throwing.
 }
 
-\LMHash{}
+\LMHash{}%
 If $f$ is marked \code{\SYNC*} (\ref{functions}),
 then a fresh instance (\ref{generativeConstructors}) $i$
 implementing \code{Iterable<$U$>} is immediately returned,
@@ -5978,7 +6133,7 @@
 The only method that needs to be added by the Dart implementation in that case is \code{iterator}.
 }
 
-\LMHash{}
+\LMHash{}%
 The iterable implementation must comply with the contract of \code{Iterable} and should not take any steps identified as exceptionally efficient in that contract.
 
 \commentary{
@@ -5989,7 +6144,7 @@
 It would not be acceptable to pre-compute the results of the generator and cache them, for example.
 }
 
-\LMHash{}
+\LMHash{}%
 When iteration over the iterable is started, by getting an iterator $j$ from the iterable and calling \code{moveNext()}, execution of the body of $f$ will begin.
 When execution of the body of $f$ completes (\ref{completion}),
 \begin{itemize}
@@ -6012,14 +6167,14 @@
 If the iterator depends on external state that might change, it should check that the state is still valid after every yield (and maybe throw a \code{ConcurrentModificationError} if it isn't).
 }
 
-\LMHash{}
+\LMHash{}%
 Each iterator runs with its own shallow copies of all local variables; in particular, each iterator has the same initial arguments, even if their bindings are modified by the function.
 \commentary{
 Two executions of an iterator interact only via state outside the function.
 }
 % The alternative would be to cache the results of an iterator in the iterable, and check the cache at each \YIELD{}.  This would have strange issues as well. The yielded value might differ from the expression in the yield. And it is a potential memory leak as the cache is kept alive by any iterator.
 
-\LMHash{}
+\LMHash{}%
 If $f$ is marked \ASYNC{} (\ref{functions}),
 then a fresh instance (\ref{generativeConstructors}) $o$ is associated with the invocation,
 where the dynamic type of $o$ implements \code{Future<$flatten(T)$>},
@@ -6038,10 +6193,10 @@
 completion of $o$ happens at some future time after the invocation has returned.
 \rationale{
 The caller needs time to set up error handling for the returned future,
-so the future is not completed with an error {\em before} it has been returned.
+so the future is not completed with an error \emph{before} it has been returned.
 }
 
-\LMHash{}
+\LMHash{}%
 If $f$ is marked \code{\ASYNC*} (\ref{functions}),
 then a fresh instance (\ref{generativeConstructors}) $s$
 implementing \code{Stream<$U$>} is immediately returned,
@@ -6070,14 +6225,14 @@
 We choose to direct any exceptions that occur at this time to the cancellation future rather than have them be lost.
 }
 
-%\LMHash{}
+%\LMHash{}%
 %When a stream is canceled, the implementation must wait for the cancelation future returned by \code{cancell()} to complete before proceeding.
 
 
 \subsubsection{Actual Argument Lists}
 \LMLabel{actualArgumentLists}
 
-\LMHash{}
+\LMHash{}%
 Actual argument lists have the following syntax:
 
 \begin{grammar}
@@ -6089,20 +6244,20 @@
 <namedArgument> ::= <label> <expression>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Argument lists allow an optional trailing comma after the last argument (\syntax{`,'?}).
 An argument list with such a trailing comma is equivalent in all ways to the same parameter list without the trailing comma.
 All argument lists in this specification are shown without a trailing comma,
 but the rules and semantics apply equally to the corresponding argument list with a trailing comma.
 
-\LMHash{}
+\LMHash{}%
 Let $L$ be an argument list of the form
 \code{($e_1 \ldots,\ e_m,\ y_{m+1}$: $e_{m+1} \ldots,\ y_{m+p}$: $e_{m+p}$)}
 and assume that the static type of $e_i$ is $S_i$, $i \in 1 .. m+p$.
-The {\em static argument list type} of $L$ is then
+The \Index{static argument list type} of $L$ is then
 \code{($S_1 \ldots,\ S_m,\ S_{m+1}\ y_{m+1} \ldots,\ S_{m+p}\ y_{m+p}$)}.
 
-\LMHash{}
+\LMHash{}%
 Let $\argumentList{S}$ be the static argument list type
 
 \code{($S_1 \ldots,\ S_m,\ S_{m+1}\ y_{m+1} \ldots,\ S_{m+p}\ y_{m+p}$)}
@@ -6115,13 +6270,15 @@
 \noindent
 where each parameter may be marked \COVARIANT{} (\commentary{not shown, but allowed}).
 
-\LMHash{}
-We say that $\argumentList{S}$ {\em is a subtype match} for $\parameterList{P}$
+\LMHash{}%
+We say that $\argumentList{S}$ is
+a \Index{subtype match} for $\parameterList{P}$
 if{}f $p = 0$, $n \leq m \leq n+k$, and $S_i$ is a subtype of $T_i$ for all $i \in 1 .. m$.
-We say that $\argumentList{S}$ {\em is an assignable match} for $\parameterList{P}$
+We say that $\argumentList{S}$ is
+an \Index{assignable match} for $\parameterList{P}$
 if{}f $p = 0$, $n \leq m \leq n+k$, and $S_i$ is assignable to $T_i$ for all $i \in 1 .. m$.
 
-\LMHash{}
+\LMHash{}%
 Let $\argumentList{S}$ be the static argument list type
 
 \code{($S_1 \ldots,\ S_m,\ S_{m+1}\ y_{m+1} \ldots,\ S_{m+p}\ y_{m+p}$)}
@@ -6134,15 +6291,17 @@
 \noindent
 where each parameter may be marked \COVARIANT{} (\commentary{not shown, but allowed}).
 
-\LMHash{}
-We say that $\argumentList{S}$ {\em is a subtype match} for $\parameterList{P}$
+\LMHash{}%
+We say that $\argumentList{S}$ is
+a \Index{subtype match} for $\parameterList{P}$
 if{}f $m = n$,
 $\{y_{m+1}\ldots,\ y_{m+p}\} \subseteq \{x_{n+1}\ldots,\ x_{n+k}\}$,
 $S_i$ is a subtype of $T_i$ for all $i \in 1 .. m$,
 and $S_i$ is a subtype of $T_j$ whenever $y_i = x_j$ and
 $j \in n + 1 .. n + k$, for all
 $i \in m + 1 .. m + p$.
-We say that $\argumentList{S}$ {\em is an assignable match} for $\parameterList{P}$
+We say that $\argumentList{S}$
+is an \Index{assignable match} for $\parameterList{P}$
 if{}f $m = n$,
 $\{y_{m+1}\ldots,\ y_{m+p}\} \subseteq \{x_{n+1}\ldots,\ x_{n+k}\}$,
 $S_i$ is assignable to $T_i$ for all $i \in 1 .. m$,
@@ -6159,11 +6318,11 @@
 \subsubsection{Actual Argument List Evaluation}
 \LMLabel{actualArguments}
 
-\LMHash{}
+\LMHash{}%
 Function invocation involves evaluation of the list of actual arguments to the function,
 and binding of the results to the function's formal parameters.
 
-\LMHash{}
+\LMHash{}%
 When parsing an argument list, an ambiguity may arise because the same source code could be one generic function invocation,
 and it could be two or more relational expressions and/or shift expressions.
 In this situation, the expression is always parsed as a generic function invocation.
@@ -6184,14 +6343,14 @@
 Also, we expect that it will be more common to have generic function invocations as actual arguments than having relational or shift expressions that happen to match up and have parentheses at the end, such that the ambiguity arises.
 }
 
-\LMHash{}
+\LMHash{}%
 Evaluation of an actual argument part of the form
 
 \code{<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_m,\ q_1$: $a_{m+1}, \ldots,\ q_l$: $a_{m+l}$)}
 
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 The type arguments $A_1, \ldots, A_r$ are evaluated in the order they appear in the program, producing types $t_1, \ldots, t_r$.
 The arguments $a_1, \ldots, a_{m+l}$ are evaluated in the order they appear in the program, producing objects $o_1, \ldots, o_{m+l}$.
 
@@ -6211,7 +6370,7 @@
 and similarly for empty type parameter lists (\ref{generics}).
 }
 
-\LMHash{}
+\LMHash{}%
 Consider an invocation $i$ of a function $f$ with an actual argument part of the form
 \code{<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_m,\ q_1$: $a_{m+1}, \ldots,\ q_l$: $a_{m+l}$)}.
 
@@ -6247,16 +6406,16 @@
 even though there may not be corresponding entity in the heap at run time.
 }
 
-\LMHash{}
+\LMHash{}%
 % We cannot pass the same named parameter twice.
 It is a compile-time error if $q_j = q_k$ for any $j \ne k$.
 
-\LMHash{}
+\LMHash{}%
 If the static type of $f$ is \DYNAMIC{} or the built-in class \FUNCTION{},
 no further static checks are performed and the static type of $i$ is \DYNAMIC{};
 otherwise, it is a compile-time error if the static type of $f$ is not a function type.
 
-\LMHash{}
+\LMHash{}%
 Otherwise, the static type of $f$ is a function type $F$.
 Let $S_0$ be the return type of $F$,
 let $X_1\ \EXTENDS\ B_1, \ldots, X_s\ \EXTENDS\ B_s$
@@ -6334,7 +6493,7 @@
   \label{fig:argumentsAndParameters}
 \end{figure}
 
-\LMHash{}
+\LMHash{}%
 % Type inference is assumed complete, so we must have the correct number of type arguments.
 It is a compile-time error if $r \not= s$.
 It is a compile-time error if $r = s$ and for some $j \in 1 .. s$,
@@ -6352,20 +6511,20 @@
 For each named argument there must be a named parameter with the same name.
 }
 
-\LMHash{}
+\LMHash{}%
 The static type of $i$ is $[A_1/X_1, \ldots, A_r/X_s]S_0$.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $T_j$ may not be assigned to $S_j, j \in 1 .. m$.
 It is a compile-time error if $T_{m+j}$ may not be assigned to $S_{q_j}, j \in 1 .. l$.
 
-\LMHash{}
+\LMHash{}%
 For the dynamic semantics,
 let $f$ be a function with $s$ type parameters and $h$ required parameters;
 let $p_1, \ldots, p_n$ be the positional parameters of $f$;
 and let $p_{h+1}, \ldots, p_{h+k}$ be the optional parameters declared by $f$.
 
-\LMHash{}
+\LMHash{}%
 An evaluated actual argument part
 
 \code{<$t_1, \ldots,\ t_r$>($o_1, \ldots,\ o_m,\ q_1$: $o_{m+1},\ \ldots,\ q_l$: $o_{m+l}$)}
@@ -6378,7 +6537,7 @@
 \noindent
 is bound to the formal type parameters and formal parameters of $f$ as follows:
 
-\LMHash{}
+\LMHash{}%
 % Passing a wrong number of actual type arguments.
 If $r = 0$ and $s > 0$ then replace the actual type argument list:
 %% TODO[instantiate-to-bound]: The actual type arguments passed here
@@ -6406,7 +6565,7 @@
 All of these remaining parameters are necessarily optional and thus have default values.
 }
 
-\LMHash{}
+\LMHash{}%
 % Check the type arguments.
 It is a dynamic type error if $t_i$ is not a subtype of the actual bound
 (\ref{actualTypeOfADeclaration})
@@ -6426,7 +6585,7 @@
 \subsubsection{Unqualified Invocation}
 \LMLabel{unqualifiedInvocation}
 
-\LMHash{}
+\LMHash{}%
 An unqualified function invocation $i$ has the form
 
 \code{\id<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
@@ -6438,13 +6597,13 @@
 Note that the type argument list is omitted when $r = 0$ (\ref{generics}).
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $i$ occurs inside a top-level or static function
 (be it function, method, getter, or setter)
 or a top-level or static variable initializer,
 and there is no lexically visible declaration named \id{} in scope.
 
-\LMHash{}
+\LMHash{}%
 If there exists a lexically visible declaration named \id,
 let $f_{id}$ be the innermost such declaration.
 Then:
@@ -6483,7 +6642,7 @@
 \subsubsection{Function Expression Invocation}
 \LMLabel{functionExpressionInvocation}
 
-\LMHash{}
+\LMHash{}%
 A function expression invocation $i$ has the form
 
 \code{$e_f$<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
@@ -6495,7 +6654,7 @@
 Note that the type argument list is omitted when $r = 0$ (\ref{generics}).
 }
 
-\LMHash{}
+\LMHash{}%
 If $e_f$ is an identifier \id, then \id{} must necessarily denote
 a local function, a library function, a library or static getter or a variable as described above,
 or $i$ is not considered a function expression invocation.
@@ -6509,7 +6668,7 @@
 but $e_f$ may also have other forms, e.g., \code{p.C}.
 }
 
-\LMHash{}
+\LMHash{}%
 If $e_f$ is a property extraction expression (\ref{propertyExtraction}),
 then $i$ isn't a function expression invocation and is instead recognized as an ordinary method invocation (\ref{ordinaryInvocation}).
 
@@ -6520,12 +6679,12 @@
 The \code{Invocation} passed to \code{noSuchMethod()} would describe a call to a method \code{$b$} with argument \code{$x$} in the former case, and a call to a getter \code{$b$} (with no arguments) in the latter.
 }
 
-\LMHash{}
+\LMHash{}%
 Let $F$ be the static type of $e_f$.
 The static analysis of $i$ is performed as specified in Section~\ref{bindingActualsToFormals},
 and the static type of $i$ is as specified there.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a function expression invocation
 
 \code{$e_f$<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
@@ -6541,7 +6700,7 @@
 and executing the body of $f$ with those bindings;
 the returned result is then the result of evaluating $i$.
 
-\LMHash{}
+\LMHash{}%
 Otherwise $o$ is not a function object.
 If $o$ has a method named \CALL{}
 the following ordinary method invocation is evaluated,
@@ -6549,7 +6708,7 @@
 
 \code{$f$.call<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
 
-\LMHash{}
+\LMHash{}%
 Otherwise $o$ has no method named \CALL{}.
 A new instance $im$ of the predefined class \code{Invocation} is created, such that:
 \begin{itemize}
@@ -6567,7 +6726,7 @@
 \code{<Type>[$A_1, \ldots,\ A_r$]}.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Then the method invocation \code{f.noSuchMethod($im$)} is evaluated,
 and its result is then the result of evaluating $i$.
 
@@ -6583,25 +6742,26 @@
 \subsection{Function Closurization}
 \LMLabel{functionClosurization}
 
-\LMHash{}
+\LMHash{}%
 Let $f$ be an expression denoting
 a declaration of a local function, a static method, or a top-level function
 (\ref{identifierReference})
 or let $f$ be a function literal
 (\ref{functionExpressions}).
 Evaluation of $f$ yields a function object
-which is the outcome of a {\em function closurization}
+which is the outcome of a \Index{function closurization}
 applied to the declaration denoted by $f$
 respectively to the function literal $f$ considered as a function declaration.
 % Note that we do not promise that this will be a fresh function object,
 % such that constant expressions are covered as well, and others may be
 % identical even if not required, e.g., local functions with no free variables.
-{\em Closurization} denotes instance method closurization
+\IndexCustom{Closurization}{closurization}
+denotes instance method closurization
 (\ref{ordinaryMemberClosurization})
 as well as function closurization,
 and it is also used as a shorthand for either of them when there is no ambiguity.
 
-\LMHash{}
+\LMHash{}%
 Function closurization applied to a function declaration $f$
 amounts to the creation of a function object $o$
 which is an instance of a class whose interface is a subtype of the actual type
@@ -6625,8 +6785,8 @@
 \subsection{Lookup}
 \LMLabel{lookup}
 
-\LMHash{}
-A {\em lookup} is a procedure which selects
+\LMHash{}%
+A \Index{lookup} is a procedure which selects
 a concrete instance member declaration based on a traversal of
 a sequence of classes, starting with a given class $C$
 and proceeding with the superclass of the current class at each step.
@@ -6644,7 +6804,7 @@
 { % Scope for 'lookup' definition.
 
 \def\LookupDefinitionWithStart#1{
-\LMHash{}
+\LMHash{}%
 The result of a
 {\em {#1} lookup for $m$ in $o$ with respect to $L$ starting in class $C$}
 is the result of a {#1} lookup for $m$ in $C$ with respect to $L$.
@@ -6660,7 +6820,7 @@
 
 }
 
-\LMHash{}
+\LMHash{}%
 Let $m$ be an identifier, $o$ an object, $L$ a library,
 and $C$ a class which is the class of $o$ or a superclass thereof.
 
@@ -6676,7 +6836,7 @@
 starting with the class of $o$.
 }
 
-\LMHash{}
+\LMHash{}%
 Let $m$ be an identifier, $o$ an object, and $L$ a library.
 \LookupDefinition{method}
 \LookupDefinition{getter}
@@ -6704,10 +6864,10 @@
 \subsection{Top level Getter Invocation}
 \LMLabel{topLevelGetterInvocation}
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a top-level getter invocation $i$ of the form $m$, where $m$ is an identifier, proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 The getter function $m$ is invoked.
 The value of $i$ is the result returned by the call to the getter function.
 \commentary{
@@ -6715,26 +6875,29 @@
 Per the rules for identifier references, an identifier will not be treated as a top-level getter invocation unless the getter $i$ is defined.
 }
 
-\LMHash{}
+\LMHash{}%
 The static type of $i$ is the declared return type of $m$.
 
 
 \subsection{Method Invocation}
 \LMLabel{methodInvocation}
 
-\LMHash{}
+\LMHash{}%
 Method invocation can take several forms as specified below.
 
 
 \subsubsection{Ordinary Invocation}
 \LMLabel{ordinaryInvocation}
 
-\LMHash{}
-An ordinary method invocation can be {\em conditional} or {\em unconditional}.
+\LMHash{}%
+An ordinary method invocation can be conditional or unconditional.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$e$?.$m$<$\cdots$>($\cdots$)}}
-Consider a {\em conditional ordinary method invocation} $i$ of the form
+Consider a
+\IndexCustom{conditional ordinary method invocation}{%
+  method invocation!conditional ordinary}
+$i$ of the form
 \code{$e$?.$m$<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
 
 \commentary{
@@ -6743,7 +6906,7 @@
 and similarly for formal type parameter lists (\ref{generics}).
 }
 
-\LMHash{}
+\LMHash{}%
 The static type of $i$ is the same as the static type of
 
 \code{$e$.$m$<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
@@ -6756,15 +6919,15 @@
 \noindent
 are also generated in the case of $i$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of $i$ proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 If $e$ is a type literal, $i$ is equivalent to
 
 \code{$e$.$m$<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
 
-\LMHash{}
+\LMHash{}%
 Otherwise, evaluate $e$ to an object $o$.
 If $o$ is the null object, $i$ evaluates to the null object (\ref{null}).
 Otherwise let $v$ be a fresh variable bound to $o$ and evaluate
@@ -6772,9 +6935,11 @@
 to a value $r$.
 Then $e$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$e$.$m$<$\cdots$>($\cdots$)}}
-An {\em unconditional ordinary method invocation} $i$ has the form
+An \IndexCustom{unconditional ordinary method invocation}{%
+  method invocation!unconditional ordinary}
+$i$ has the form
 \code{$e$.$m$<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
 
 \commentary{
@@ -6782,7 +6947,7 @@
 where the number of type arguments is zero (\ref{generics}).
 }
 
-\LMHash{}
+\LMHash{}%
 Let $T$ be the static type of $e$.
 It is a compile-time error if $T$ does not have an accessible (\ref{privacy}) instance member named $m$, unless either:
 \begin{itemize}
@@ -6805,12 +6970,12 @@
 }
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 If $T$ did not have an accessible member named $m$ the static type of $i$ is \DYNAMIC{},
 and no further static checks are performed on $i$
 (\commentary{except that subexpressions of $i$ are subject to their own static analysis}).
 
-\LMHash{}
+\LMHash{}%
 Otherwise \code{$T$.$m$} denotes an instance member.
 Let $L$ be the library that contains $i$.
 Let $d$ be the result of method lookup for $m$ in $T$ with respect to $L$,
@@ -6819,11 +6984,11 @@
 and let $F$ be the return type of $d$.
 (\commentary{Since \code{$T$.$m$} exists we cannot have a failure in both lookups.})
 
-\LMHash{}
+\LMHash{}%
 The static analysis of $i$ is performed as specified in Section~\ref{bindingActualsToFormals},
 and the static type of $i$ is as specified there.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error to invoke any of the methods of class \code{Object} on a prefix object (\ref{imports})
 or on a constant type literal that is immediately followed by the token `.'\,.
 
@@ -6834,30 +6999,30 @@
 If needed, \code{(int).toString()} may be used instead.
 }
 
-\LMHash{}
+\LMHash{}%
 Evaluation of an unconditional ordinary method invocation $i$ of the form
 \code{$e$.$m$<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 First, the expression $e$ is evaluated to a value $o$.
 Let $f$ be the result of looking up (\ref{lookup}) method $m$ in $o$ with respect to the current library $L$.
 
-\LMHash{}
+\LMHash{}%
 %% TODO(eernst): This is metaclass stuff, should be deleted.
 If method lookup succeeded,
 but $o$ is an instance of \code{Type} and $e$ is not a constant type literal,
 then if $m$ is a method that forwards (\ref{functionDeclarations}) to a static method,
 method lookup is considered to have failed.
 
-\LMHash{}
+\LMHash{}%
 If the method lookup succeeded,
 the binding of actual arguments to formal parameters is performed as specified in Section~\ref{bindingActualsToFormals}.
 The body of $f$ is then executed with respect to the bindings that resulted from the evaluation of the argument list,
 and with \THIS{} bound to $o$.
 The value of $i$ is the value returned by the execution of $f$'s body.
 
-\LMHash{}
+\LMHash{}%
 If the method lookup failed,
 then let $g$ be the result of looking up getter (\ref{lookup}) $m$ in $o$ with respect to $L$.
 %% TODO(eernst): This is metaclass stuff, should be deleted.
@@ -6866,14 +7031,14 @@
 then if $g$ is a getter that forwards to a static getter,
 getter lookup is considered to have failed.
 
-\LMHash{}
+\LMHash{}%
 If the getter lookup succeeded then invoke the getter $o.m$
 and let $v_g$ be the returned value.
 Then the value of $i$ is the value of
 
 \code{$v_g$<$A_1, \ldots,\ A_r$>($a_1,\ \ldots,\ a_n,\ x_{n+1}$: $a_{n+1},\ \ldots,\ x_{n+k}$: $a_{n+k}$)}.
 
-\LMHash{}
+\LMHash{}%
 If getter lookup has also failed,
 then a new instance $im$ of the predefined class \code{Invocation} is created, such that:
 \begin{itemize}
@@ -6891,7 +7056,7 @@
   \code{<Type>[$A_1, \ldots,\ A_r$]}.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Then the method \code{noSuchMethod()} is looked up in $o$ and invoked with argument $im$,
 and the result of this invocation is the result of evaluating $i$.
 
@@ -6905,8 +7070,9 @@
 \subsubsection{Cascaded Invocations}
 \LMLabel{cascadedInvocations}
 
-\LMHash{}
-A {\em cascaded method invocation} has the form \code{$e$..\metavar{suffix}}
+\LMHash{}%
+A \IndexCustom{cascaded method invocation}{method invocation!cascaded}
+has the form \code{$e$..\metavar{suffix}}
 where $e$ is an expression and \metavar{suffix} is a sequence of operator, method, getter or setter invocations.
 
 \begin{grammar}
@@ -6921,7 +7087,7 @@
   <typeArguments>? <arguments>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a cascaded method invocation expression $c$ of the form \code{$e$..\metavar{suffix}} proceeds as follows:
 
 Evaluate $e$ to an object $o$.
@@ -6929,7 +7095,7 @@
 Evaluate \code{$t$.\metavar{suffix}} to an object.
 Then $c$ evaluates to $o$.
 
-\LMHash{}
+\LMHash{}%
 The static type of $c$ is the static type of $e$.
 
 \rationale{
@@ -6946,7 +7112,7 @@
 
 % Conditional super invocation is meaningless: \THIS{} is not null.
 
-\LMHash{}
+\LMHash{}%
 A super method invocation $i$ has the form
 
 \code{\SUPER{}.$m$<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
@@ -6957,7 +7123,7 @@
 and similarly for formal type parameter lists (\ref{generics}).
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a super method invocation occurs in a top-level function or variable initializer,
 in an instance variable initializer or initializer list,
 in class \code{Object},
@@ -6968,7 +7134,7 @@
 
 \def\SuperClass{\ensuremath{S_{\mbox{\scriptsize{}super}}}}
 
-\LMHash{}
+\LMHash{}%
 Let \SuperClass{} be the superclass (\ref{superclasses})
 of the immediately enclosing class for $i$,
 and let $L$ be the library that contains $i$.
@@ -6983,7 +7149,7 @@
 and let $F$ be the return type of $d$.
 If both lookups failed, a compile-time error occurs.
 
-\LMHash{}
+\LMHash{}%
 Otherwise (\commentary{when one of the lookups succeeded}),
 the static analysis of $i$ is performed as specified in Section~\ref{bindingActualsToFormals},
 considering the function to have static type $F$,
@@ -6995,7 +7161,7 @@
 as well as when it does not exist at all.
 }
 
-\LMHash{}
+\LMHash{}%
 Evaluation of $i$ proceeds as follows:
 Let $o$ be the current binding of \THIS{},
 let $C$ be the enclosing class for $i$,
@@ -7019,7 +7185,7 @@
 at compile-time, and the program then has a compile-time error.
 }
 
-\LMHash{}
+\LMHash{}%
 Otherwise perform the binding of actual arguments to formal parameters for
 \code{$f$<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
 as specified in Section~\ref{bindingActualsToFormals},
@@ -7033,7 +7199,7 @@
 \subsubsection{Sending Messages}
 \LMLabel{sendingMessages}
 
-\LMHash{}
+\LMHash{}%
 Messages are the sole means of communication among isolates.
 Messages are sent by invoking specific methods in the Dart libraries; there is no specific syntax for sending a message.
 
@@ -7045,8 +7211,9 @@
 \subsection{Property Extraction}
 \LMLabel{propertyExtraction}
 
-\LMHash{}
-{\em Property extraction} allows for a member to be accessed as a property rather than a function.
+\LMHash{}%
+\IndexCustom{Property extraction}{property extraction}
+allows for a member to be accessed as a property rather than a function.
 A property extraction can be either:
 \begin{enumerate}
 \item An instance method closurization,
@@ -7061,16 +7228,17 @@
 Function objects derived from members via closurization are colloquially known as tear-offs.
 }
 
-Property extraction can be either {\em conditional} or {\em unconditional}.
+Property extraction can be either conditional or unconditional.
 
-\LMHash{}
-Evaluation of a {\em conditional property extraction expression} $e$
-of the form \code{$e_1$?.\id} proceeds as follows:
+\LMHash{}%
+Evaluation of a \IndexCustom{conditional property extraction expression}{%
+  property extraction!conditional}
+$e$ of the form \code{$e_1$?.\id} proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 If $e_1$ is a type literal, $e$ is equivalent to \code{$e_1$.$m$}.
 
-\LMHash{}
+\LMHash{}%
 Otherwise evaluate $e_1$ to an object $o$.
 If $o$ is the null object, $e$ evaluates to the null object (\ref{null}).
 Otherwise let $x$ be a fresh variable bound to $o$
@@ -7081,17 +7249,22 @@
 Let $T$ be the static type of $e_1$ and let $y$ be a fresh variable of type $T$.
 Exactly the same compile-time errors that would be caused by \code{$y$.\id} are also generated in the case of \code{$e_1$?.\id}.
 
-\LMHash{}
-Unconditional property extraction has one of two syntactic forms: $e.m$ (\ref{getterAccessAndMethodExtraction}) or $\SUPER.m$ (\ref{superGetterAccessAndMethodClosurization}), where $e$ is an expression and $m$ is an identifier.
+\LMHash{}%
+\IndexCustom{Unconditional property extraction}{%
+  property extraction!unconditional}
+has one of two syntactic forms:
+$e.m$ (\ref{getterAccessAndMethodExtraction}) or
+$\SUPER.m$ (\ref{superGetterAccessAndMethodClosurization}),
+where $e$ is an expression and $m$ is an identifier.
 
 
 \subsubsection{Getter Access and Method Extraction}
 \LMLabel{getterAccessAndMethodExtraction}
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a property extraction $i$ of the form $e.m$ proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 First, the expression $e$ is evaluated to an object $o$.
 Let $f$ be the result of looking up (\ref{lookup}) method (\ref{instanceMethods}) $m$ in $o$ with respect to the current library $L$.
 %% TODO(eernst): This is metaclass stuff, should be deleted.
@@ -7105,7 +7278,7 @@
 The regrettable implication is that the error will refer to a missing getter rather than an attempt to closurize an abstract method.
 }
 
-\LMHash{}
+\LMHash{}%
 Otherwise, $i$ is a getter invocation.
 Let $f$ be the result of looking up (\ref{lookup}) getter (\ref{getters}) $m$ in $o$ with respect to $L$.
 %% TODO(eernst): This is metaclass stuff, should be deleted.
@@ -7113,7 +7286,7 @@
 Otherwise, the body of $f$ is executed with \THIS{} bound to $o$.
 The value of $i$ is the result returned by the call to the getter function.
 
-\LMHash{}
+\LMHash{}%
 If the getter lookup has failed, then a new instance $im$ of the predefined class \code{Invocation} is created, such that:
 \begin{itemize}
 \item \code{$im$.isGetter} evaluates to \code{\TRUE{}}.
@@ -7128,7 +7301,7 @@
 \code{List<Type>}.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Then the method \code{noSuchMethod()} is looked up in $o$ and invoked with argument $im$,
 and the result of this invocation is the result of evaluating $i$.
 
@@ -7137,14 +7310,14 @@
 when the static type of $e$ is \DYNAMIC{}.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $m$ is a member of class \code{Object} and $e$ is either a prefix object (\ref{imports}) or a constant type literal.
 
 \commentary{
 This precludes \code{int.toString} but not \code{(int).toString} because in the latter case, $e$ is a parenthesized expression.
 }
 
-\LMHash{}
+\LMHash{}%
 Let $T$ be the static type of $e$.
 It is a compile-time error if $T$ does not have a method or getter named $m$,
 %% TODO(eernst): This is metaclass stuff, should be deleted.
@@ -7152,7 +7325,7 @@
 $e$ is a constant type literal,
 and the class corresponding to $e$ has a static method or getter named $m$.
 
-\LMHash{}
+\LMHash{}%
 The static type of $i$ is:
 \begin{itemize}
 \item The declared return type of \code{$T$.$m$}, if $T$ has an accessible instance getter named $m$.
@@ -7174,16 +7347,16 @@
 \subsubsection{Super Getter Access and Method Closurization}
 \LMLabel{superGetterAccessAndMethodClosurization}
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a property extraction $i$ of the form $\SUPER.m$ proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 Let $g$ be the method currently executing, and let $C$ be the class in which $g$ was looked up.
 Let $S_{dynamic}$ be the superclass of $C$.
 Let $f$ be the result of looking up method $m$ in $S_{dynamic}$ with respect to the current library $L$.
 If method lookup succeeds then $i$ evaluates to the closurization of method $f$ with respect to superclass $S_{dynamic}$ (\ref{superClosurization}).
 
-\LMHash{}
+\LMHash{}%
 Otherwise, $i$ is a getter invocation.
 Let $f$ be the result of looking up getter $m$ in $S_{dynamic}$ with respect to $L$.
 The body of $f$ is executed with \THIS{} bound to the current value of \THIS{}.
@@ -7195,7 +7368,7 @@
 does not have a concrete member named $m$.
 }
 
-\LMHash{}
+\LMHash{}%
 Let $S_{static}$ be the superclass of the immediately enclosing class.
 It is a compile-time error if $S_{static}$ does not have an accessible instance method or getter named $m$.
 
@@ -7215,14 +7388,15 @@
 in which case the type parameter declarations are omitted (\ref{generics}).
 }
 
-\LMHash{}
-An {\em instance method closurization}
+\LMHash{}%
+An \Index{instance method closurization}
 is a closurization of some method on some object, defined below,
 or a super closurization (\ref{superClosurization}).
 
-\LMHash{}
+\LMHash{}%
 Let $o$ be an object, and let $u$ be a fresh final variable bound to $o$.
-The {\em closurization of method $f$ on object $o$} is defined to be equivalent
+The \Index{closurization of method} $f$ on object $o$
+is defined to be equivalent
 (\commentary{except for equality, as noted below}) to:
 \begin{itemize}
 %\item $(a) \{\RETURN{}$ $u$ $op$ $a;$\} if $f$ is named $op$ and $op$ is one of \code{<, >, <=, >=, ==, -, +, /, \~{}/, *, \%, $|$, \^{}, \&, $<<$, $>>$} (this precludes closurization of unary -).
@@ -7252,7 +7426,7 @@
 $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 $B'_j, j \in 1 .. s$, are determined as follows:
 If $o$ is an instance of a non-generic class, $B'_j = B_j, j \in 1 .. s$.
 Otherwise, let $X'_1, \ldots, X'_{s'}$ be the formal type parameters of the class of $o$,
@@ -7274,7 +7448,7 @@
 %% as a whole will be taken from the statically known type of the receiver
 %% of the tear-off invocation.
 
-\LMHash{}
+\LMHash{}%
 The parameter types $T_j, j \in 1 .. n+k$, are determined as follows:
 Let the method declaration $D$ be the implementation of $m$ which is invoked by the expression in the body.
 Let $T$ be the class that contains $D$.
@@ -7283,12 +7457,12 @@
 Note that $T$ is the dynamic type of $o$, or a superclass thereof.
 }
 
-\LMHash{}
+\LMHash{}%
 If $T$ is a non-generic class then for $j \in 1 .. n+k$,
 $T_j$ is a type annotation that denotes the same type as that which is denoted by the type annotation on the corresponding parameter declaration in $D$.
 If that parameter declaration has no type annotation then $T_j$ is \DYNAMIC{}.
 
-\LMHash{}
+\LMHash{}%
 Otherwise $T$ is a generic instantiation of a generic class $G$.
 Let $X''_1, \ldots, X''_{s''}$ be the formal type parameters of $G$,
 and $t''_1, \ldots, t''_{s''}$ be the actual type arguments of $o$ at $T$.
@@ -7296,7 +7470,7 @@
 where $S_j$ is the type annotation of the corresponding parameter in $D$.
 If that parameter declaration has no type annotation then $T_j$ is \DYNAMIC{}.
 
-\LMHash{}
+\LMHash{}%
 There is one way in which
 the function object yielded by the instance method closurization differs from
 the function object obtained by function closurization on the above mentioned function literal:
@@ -7336,7 +7510,7 @@
 in which case the type parameter declarations are omitted (\ref{generics}).
 }
 
-\LMHash{}
+\LMHash{}%
 Consider expressions in the body of a class $T$ which is a subclass of a given class $S$,
 where a method declaration that implements $f$ exists in $S$,
 and there is no class $U$ which is a subclass of $S$ and a superclass of $T$ which implements $f$.
@@ -7345,14 +7519,14 @@
 In short, consider a situation where a super invocation of $f$ will execute $f$ as declared in $S$.
 }
 
-\LMHash{}
-A {\em super closurization}
+\LMHash{}%
+A \Index{super closurization}
 is a closurization of a method with respect to a class, as defined next.
-The {\em closurization of the method $f$ with respect to the class $S$}
+The \Index{closurization of a method} $f$ with respect to the class $S$
 is defined to be equivalent
 (\commentary{except for equality, as noted below}) to:
 
-\LMHash{}
+\LMHash{}%
 \begin{itemize}
 %\item $(a) \{\RETURN{}$ \SUPER{} $op$ $a;$\} if $f$ is named $op$ and $op$ is one of \code{<, >, <=, >=, ==, -, +, /, \~{}/, *, \%, $|$, \^{}, \&, $<<$, $>>$}.
 %\item $() \{\RETURN{}$ \~{}\SUPER;\} if $f$ is named \~{}.
@@ -7381,11 +7555,11 @@
 \end{itemize}
 
 \commentary{
-Note that a super closurization is an {\em instance method closurization},
+Note that a super closurization is an instance method closurization,
 as defined in (\ref{ordinaryMemberClosurization}).
 }
 
-\LMHash{}
+\LMHash{}%
 $B'_j, j \in 1 .. s$, are determined as follows:
 If $S$ is a non-generic class then $B'_j = B_j, j \in 1 .. s$.
 Otherwise, let $X'_1, \ldots, X'_{s'}$ be the formal type parameters of $S$,
@@ -7408,16 +7582,16 @@
 %% as a whole will be taken from the statically known type of the receiver
 %% of the tear-off invocation.
 
-\LMHash{}
+\LMHash{}%
 The parameter types $T_j, j \in 1 .. n+k$, are determined as follows:
 Let the method declaration $D$ be the implementation of $m$ in $S$.
 
-\LMHash{}
+\LMHash{}%
 If $S$ is a non-generic class then for $j \in 1 .. n+k$,
 $T_j$ is a type annotation that denotes the same type as that which is denoted by the type annotation on the corresponding parameter declaration in $D$.
 If that parameter declaration has no type annotation then $T_j$ is \DYNAMIC{}.
 
-\LMHash{}
+\LMHash{}%
 Otherwise $S$ is a generic instantiation of a generic class $G$.
 Let $X''_1, \ldots, X''_{s''}$ be the formal type parameters of $G$,
 and $t''_1, \ldots, t''_{s''}$ be the actual type arguments of $o$ at $S$.
@@ -7425,7 +7599,7 @@
 where $S_j$ is the type annotation of the corresponding parameter in $D$.
 If that parameter declaration has no type annotation then $T_j$ is \DYNAMIC{}.
 
-\LMHash{}
+\LMHash{}%
 There is one way in which
 the function object yielded by the super closurization differs from
 the function object obtained by function closurization on the above mentioned function literal:
@@ -7438,7 +7612,7 @@
 \subsection{Assignment}
 \LMLabel{assignment}
 
-\LMHash{}
+\LMHash{}%
 An assignment changes the value associated with a mutable variable or property.
 
 \begin{grammar}
@@ -7446,7 +7620,7 @@
   \alt <compoundAssignmentOperator>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$v$ = $e$}}
 %% TODO(eernst): This _only_ works if we assume that `v = e` has already
 %% been expanded to `this.v = e` "when that's the right thing to do".
@@ -7462,13 +7636,13 @@
 It is a compile-time error if the static type of $e$ may not be assigned to $T$.
 The static type of $a$ is the static type of $e$.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if an assignment of the form \code{$v$ = $e$} occurs
 inside a top level or static function (be it function, method, getter, or setter) or variable initializer,
 and there is neither a mutable local variable declaration with name $v$
 nor a setter declaration with name \code{$v$=} in the lexical scope enclosing the assignment.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of an assignment $a$ of the form \code{$v$ = $e$}
 proceeds as follows:
 %% TODO(eernst): $d$ is defined ambiguously: both getter & setter may exist.
@@ -7476,7 +7650,7 @@
 It is a compile-time error if $d$ denotes
 a prefix object, type declaration, or function declaration.
 
-\LMHash{}
+\LMHash{}%
 If $d$ is the declaration of a local variable, the expression $e$ is evaluated to an object $o$.
 Then, the variable $v$ is bound to $o$.
 If no error occurs, the value of the assignment expression is $o$.
@@ -7488,14 +7662,14 @@
 
 % add local functions per bug 23218
 
-\LMHash{}
+\LMHash{}%
 % TODO(eernst): $d$ defined ambiguously, re-check next sentence when fixing.
 If $d$ is the declaration of a library variable, top level getter or top level setter, the expression $e$ is evaluated to an object $o$.
 % TODO(eernst): $d$ defined ambiguously, re-check when fixing: Case $d$ is the getter and there is no setter.
 Then the setter \code{$v$=} is invoked with its formal parameter bound to $o$.
 The value of the assignment expression is $o$.
 
-\LMHash{}
+\LMHash{}%
 Otherwise, if $d$ is the declaration of a class variable, static getter or static setter in class $C$,
 then the assignment is equivalent to the assignment \code{$C$.$v$ = $e$}.
 
@@ -7505,26 +7679,26 @@
 a compile-time error has occurred.
 }
 
-\LMHash{}
+\LMHash{}%
 %% TODO(eernst): We don't want to transform code and than complain, see if this
 %% can be reworded to rely on static checks such that it only happens when it
 %% works, or maybe that's already true.
 Otherwise, the assignment is equivalent to the assignment \code{\THIS{}.$v$ = $e$}.
 
-\LMHash{}
+\LMHash{}%
 It is a dynamic type error if $o$ is not the null object (\ref{null})
 and the dynamic type of $o$ is not a subtype of the actual type
 (\ref{actualTypeOfADeclaration})
 of $v$.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$e_1$?.$v$ = $e_2$}}
 Consider an assignment $a$ of the form \code{$e_1$?.$v$ = $e_2$}.
 Exactly the same compile-time errors that would be caused by
 \code{$e_1$.$v$ = $e_2$} are also generated in the case of $a$.
 The static type of $a$ is the static type of $e_2$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of an assignment $a$ of the form \code{$e_1$?.$v$ = $e_2$}
 proceeds as follows:
 If $e_1$ is a type literal, $a$ is equivalent to \code{$e_1$.$v$ = $e_2$}.
@@ -7534,7 +7708,7 @@
 and evaluate \code{$x$.$v$ = $e_2$} to an object $r$.
 Then $a$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$e_1$.$v$ = $e_2$}}
 Consider an assignment $a$ of the form \code{$e_1$.$v$ = $e_2$}.
 Let $T$ be the static type of $e_1$.
@@ -7546,7 +7720,7 @@
 Whether or not $T$ is \DYNAMIC{},
 the static type of $a$ is the static type of $e_2$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of an assignment of the form \code{$e_1$.$v$ = $e_2$}
 proceeds as follows:
 The expression $e_1$ is evaluated to an object $o_1$.
@@ -7557,7 +7731,7 @@
 (\ref{actualTypeOfADeclaration}).
 Otherwise, the body of the setter is executed with its formal parameter bound to $o_2$ and \THIS{} bound to $o_1$.
 
-\LMHash{}
+\LMHash{}%
 If the setter lookup has failed, then a new instance $im$ of the predefined class \code{Invocation} is created, such that:
 \begin{itemize}
 \item \code{$im$.isSetter} evaluates to \code{\TRUE{}}.
@@ -7572,7 +7746,7 @@
 \code{List<Type>}.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Then the method \code{noSuchMethod()} is looked up in $o_1$ and invoked with argument $im$.
 
 \commentary{
@@ -7580,10 +7754,10 @@
 when the static type of $e_1$ is \DYNAMIC{}.
 }
 
-\LMHash{}
+\LMHash{}%
 The value of the assignment expression is $o_2$ irrespective of whether setter lookup has failed or succeeded.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{\SUPER.$v$ = $e$}}
 Consider an assignment $a$ of the form \code{\SUPER.$v$ = $e$}.
 Let $S_{static}$ be the superclass of the immediately enclosing class.
@@ -7592,7 +7766,7 @@
 may not be assigned to the static type of the formal parameter of said setter.
 The static type of $a$ is the static type of $e$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of an assignment of the form \code{\SUPER.$v$ = $e$}
 proceeds as follows:
 Let $g$ be the currently executing method, and let $C$ be the class in which $g$ was looked up.
@@ -7607,16 +7781,16 @@
 when no concrete setter named \code{$v$=} exists in $S_{static}$.
 }
 
-\LMHash{}
+\LMHash{}%
 The value of the assignment expression is $o$.
 
-\LMHash{}
+\LMHash{}%
 It is a dynamic type error if $o$ is not the null object (\ref{null})
 and the dynamic type of $o$ is
 not a subtype of the actual type of the formal parameter of \code{$v$=}
 (\ref{actualTypeOfADeclaration}) in $S_{static}$.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$e_1$[$e_2$] = $e_3$}}
 Consider an assignment $a$ of the form \code{$e_1$[$e_2$] = $e_3$}.
 Let $T$ be the static type of $e_1$.
@@ -7631,7 +7805,7 @@
 Whether or not $T$ is \DYNAMIC{},
 the static type of $a$ is the static type of $e_3$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of an assignment $a$ of the form \code{$e_1$[$e_2$] = $e_3$}
 proceeds as follows:
 Evaluate $e_1$ to an object $a$, then evaluate $e_2$ to an object $i$, and finally evaluate $e_3$ to an object $v$.
@@ -7639,7 +7813,7 @@
 Then $a$ evaluates to $v$.
 % Should we add: It is a dynamic error if $e_1$ evaluates to a constant list or map?
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{\SUPER[$e_1$] = $e_2$}}
 Consider an assignment $a$ of the form \code{\SUPER[$e_1$] = $e_2$}.
 Let $S_{static}$ be the superclass of the immediately enclosing class.
@@ -7651,7 +7825,7 @@
 may not be assigned to $S_1$ respectively $S_2$.
 The static type of $a$ is the static type of $e_2$.
 
-\LMHash{}
+\LMHash{}%
 For evaluation, an assignment of the form \code{\SUPER[$e_1$] = $e_2$}
 is equivalent to the expression \code{\SUPER.[$e_1$] = $e_2$}.
 
@@ -7659,7 +7833,7 @@
 \subsubsection{Compound Assignment}
 \LMLabel{compoundAssignment}
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$v$ ??= $e$}}
 Consider a compound assignment $a$ of the form \code{$v$ ??= $e$}
 where $v$ is an identifier or an identifier qualified by an import prefix,
@@ -7668,7 +7842,7 @@
 %% TODO(eernst): We should mention other cases, e.g., `v=` denotes a setter, but there is no getter.
 The static type of $a$ is the least upper bound of the static type of $v$ and the static type of $e$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a compound assignment $a$ of the form \code{$v$ ??= $e$}
 proceeds as follows:
 Evaluate $v$ to an object $o$.
@@ -7676,7 +7850,7 @@
 Otherwise evaluate \code{$v$ = $e$} to a value $r$,
 and then $a$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$C$.$v$ ??= $e$}}
 Consider a compound assignment $a$ of the form \code{$C$.$v$ ??= $e$}
 where $C$ is a type literal
@@ -7686,7 +7860,7 @@
 %% TODO(eernst): We should mention other cases, e.g., `C.v=` denotes a setter, but there is no getter.
 The static type of $a$ is the least upper bound of the static type of \code{$C$.$v$} and the static type of $e$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a compound assignment $a$ of the form \code{$C$.$v$ ??= $e$}
 where $C$ is a type literal proceeds as follow:
 Evaluate \code{$C$.$v$} to an object $o$.
@@ -7694,7 +7868,7 @@
 Otherwise evaluate \code{$C$.$v$ = $e$} to a value $r$,
 and then $a$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$e_1$.$v$ ??= $e_2$}}
 Consider a compound assignment $a$ of the form \code{$e_1$.$v$ ??= $e_2$}.
 Let $T$ be the static type of $e_1$ and let $x$ be a fresh variable of type $T$.
@@ -7703,7 +7877,7 @@
 %% TODO(eernst): Also, we should mention other cases, e.g., there is no getter `z.v`.
 The static type of $a$ is the least upper bound of the static type of \code{$e_1$.$v$} and the static type of $e_2$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a compound assignment $a$ of the form \code{$e_1$.$v$ ??= $e_2$}
 proceeds as follows:
 Evaluate $e_1$ to an object $u$.
@@ -7713,14 +7887,14 @@
 Otherwise evaluate \code{$x$.$v$ = $e_2$} to an object $r$,
 and then $a$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$e_1$[$e_2$] ??= $e_3$}}
 Consider a compound assignment $a$ of the form \code{$e_1$[$e_2$] ??= $e_3$}.
 Exactly the same compile-time errors that would be caused by \code{$e_1$[$e_2$] = $e_3$} are also generated in the case of $a$.
 %% TODO(eernst): We should mention other cases, e.g., there is no `operator []`.
 The static type of $a$ is the least upper bound of the static type of \code{$e_1$[$e_2$]} and the static type of $e_3$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a compound assignment $a$ of the form \code{$e_1$[$e_2$] ??= $e_3$}
 proceeds as follows:
 Evaluate $e_1$ to an object $u$ and then evaluate $e_2$ to an object $i$.
@@ -7730,14 +7904,14 @@
 and then call the \code{[]=} method on $u$ with $i$ as first argument and $v$ as second argument.
 Then $a$ evaluates to $v$.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{\SUPER.$v$ ??= $e$}}
 Consider a compound assignment $a$ of the form \code{\SUPER.$v$ ??= $e$}.
 Exactly the same compile-time errors that would be caused by \code{\SUPER.$v$ = $e$} are also generated in the case of $a$.
 %% TODO(eernst): We should mention other cases, e.g., there is no getter `\SUPER.v`.
 The static type of $a$ is the least upper bound of the static type of \code{\SUPER.$v$} and the static type of $e$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a compound assignment $a$ of the form \code{\SUPER.$v$ ??= $e$}
 proceeds as follows:
 Evaluate \code{\SUPER.$v$} to an object $o$.
@@ -7745,7 +7919,7 @@
 Otherwise evaluate \code{\SUPER.$v$ = $e$} to an object $r$,
 and then $a$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$e_1$?.$v$ ??= $e_2$}}
 Consider a compound assignment $a$ of the form \code{$e_1$?.$v$ ??= $e_2$}.
 Exactly the same compile-time errors that would be caused by \code{$e_1$.$v$ ??= $e_2$} are also generated in the case of $a$.
@@ -7754,7 +7928,7 @@
 % if NNBD is introduced, and because it reduces the amount of synthetic syntax.
 The static type of $a$ is the least upper bound of the static type of \code{$e_1$?.$v$} and the static type of $e_2$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a compound assignment $a$ of the form \code{$e_1$?.$v$ ??= $e_2$}
 proceeds as follows:
 Evaluate $e_1$ to an object $u$.
@@ -7765,27 +7939,27 @@
 Otherwise evaluate \code{$x$.$v$ = $e_2$} to an object $r$,
 and then $a$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$C$?.$v$ ??= $e_2$}}
 A compound assignment of the form \code{$C$?.$v$ ??= $e_2$}
 where $C$ is a type literal
 that may or may not be be qualified by an import prefix
 is equivalent to the expression \code{$C$.$v$ ??= $e$}.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$v$ $op$= $e$}}
 For any other valid operator $op$, a compound assignment of the form \code{$v$ $op$= $e$}
 is equivalent to \code{$v$ = $v$ $op$ $e$},
 where $v$ is an identifier or an identifier qualified by an import prefix.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$C$.$v$ $op$= $e$}}
 A compound assignment of the form \code{$C$.$v$ $op$= $e$}
 where $C$ is a type literal
 that may or may not be qualified by an import prefix
 is equivalent to \code{$C$.$v$ = $C$.$v$ $op$ $e$}.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$e_1$.$v$ $op$= $e_2$}}
 Consider a compound assignment $a$ of the form \code{$e_1$.$v$ $op$= $e_2$}.
 Let $x$ be a fresh variable whose static type is the static type of $e_1$.
@@ -7793,14 +7967,14 @@
 exactly the same compile-time errors that would be caused by \code{$x$.$v$ = $x$.$v$ $op$ $e_2$} are also generated in the case of $a$.
 The static type of $a$ is the static type of \code{$e_1$.$v$ $op$ $e_2$}.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a compound assignment $a$ of the form \code{$e_1$.$v$ $op$= $e_2$}
 proceeds as follows:
 Evaluate $e_1$ to an object $u$ and let $x$ be a fresh variable bound to $u$.
 Evaluate \code{$x$.$v$ = $x$.$v$ $op$ $e_2$} to an object $r$
 and then $a$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$e_1$[$e_2$] $op$= $e_3$}}
 Consider a compound assignment $a$ of the form \code{$e_1$[$e_2$] $op$= $e_3$}.
 Let $x$ and $i$ be fresh variables
@@ -7810,7 +7984,7 @@
 exactly the same compile-time errors that would be caused by \code{$x$[$i$] = $x$[$i$] $op$ $e_3$} are also generated in the case of $a$.
 The static type of $a$ is the static type of \code{$x$[$i$] $op$ $e_3$}.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of s compound assignment $a$ of the form \code{$e_1$[$e_2$] $op$= $e_3$}
 proceeds as follows:
 Evaluate $e_1$ to an object $u$ and evaluate $e_2$ to an object $v$.
@@ -7818,13 +7992,13 @@
 Evaluate \code{$x$[$i$] = $x$[$i$] $op$ $e_3$} to an object $r$,
 and then $a$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$e_1$?.$v$ $op$= $e_2$}}
 Consider a compound assignment $a$ of the form \code{$e_1$?.$v$ $op$= $e_2$}.
 Exactly the same compile-time errors that would be caused by \code{$e_1$.$v$ $op$= $e_2$} are also generated in the case of $a$.
 The static type of $a$ is the static type of \code{$e_1$.$v$ $op$= $e_2$}.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a compound assignment $a$ of the form \code{$e_1$?.$v$ $op$= $e_2$}
 proceeds as follows:
 Evaluate $e_1$ to an object $u$.
@@ -7833,7 +8007,7 @@
 Evaluate \code{$x$.$v$ $op$= $e_2$} to an object $r$.
 Then $a$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 \Case{\code{$C$?.$v$ $op$ = $e_2$}}
 A compound assignment of the form \code{$C$?.$v$ $op$ = $e_2$}
 where $C$ is a type literal
@@ -7859,24 +8033,24 @@
 \subsection{Conditional}
 \LMLabel{conditional}
 
-\LMHash{}
-A {\em conditional expression} evaluates one of two expressions based on a boolean condition.
+\LMHash{}%
+A \Index{conditional expression} evaluates one of two expressions based on a boolean condition.
 
 \begin{grammar}
 <conditionalExpression> ::= <ifNullExpression>
   \gnewline{} (`?' <expressionWithoutCascade> `:' <expressionWithoutCascade>)?
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a conditional expression $c$ of the form $e_1 ? e_2 : e_3$ proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 First, $e_1$ is evaluated to an object $o_1$.
 It is a run-time error if the run-time type of $o_1$ is not \code{bool}.
 If $r$ is \TRUE, then the value of $c$ is the result of evaluating the expression $e_2$.
 Otherwise the value of $c$ is the result of evaluating the expression $e_3$.
 
-\LMHash{}
+\LMHash{}%
 If $e_1$ shows that a local variable $v$ has type $T$,
 then the type of $v$ is known to be $T$ in $e_2$,
 unless any of the following are true:
@@ -7888,7 +8062,7 @@
 $v$ is potentially mutated anywhere in the scope of $v$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the static type of $e_1$ may not be assigned to \code{bool}.
 The static type of $c$ is the least upper bound (\ref{leastUpperBounds}) of the static type of $e_2$ and the static type of $e_3$.
 
@@ -7896,57 +8070,58 @@
 \subsection{If-null Expressions}
 \LMLabel{ifNull}
 
-\LMHash{}
-An {\em if-null expression} evaluates an expression and if the result is the null object (\ref{null}), evaluates another.
+\LMHash{}%
+An \Index{if-null expression} evaluates an expression and if the result is the null object (\ref{null}), evaluates another.
 
 \begin{grammar}
 <ifNullExpression> ::= <logicalOrExpression> (`??' <logicalOrExpression>)*
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Evaluation of an if-null expression $e$ of the form \code{$e_1$ ?? $e_2$}
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 Evaluate $e_1$ to an object $o$.
 If $o$ is not the null object (\ref{null}), then $e$ evaluates to $o$.
 Otherwise evaluate $e_2$ to an object $r$,
 and then $e$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 The static type of $e$ is the least upper bound (\ref{leastUpperBounds}) of the static type of $e_1$ and the static type of $e_2$.
 
 
 \subsection{Logical Boolean Expressions}
 \LMLabel{logicalBooleanExpressions}
 
-\LMHash{}
+\LMHash{}%
 The logical boolean expressions combine boolean objects using the boolean conjunction and disjunction operators.
 
 \begin{grammar}
-<logicalOrExpression> ::= <logicalAndExpression> (`||' <logicalAndExpression>)*
+<logicalOrExpression> ::= \gnewline{}
+  <logicalAndExpression> (`||' <logicalAndExpression>)*
 
 <logicalAndExpression> ::= <equalityExpression> (`\&\&' <equalityExpression>)*
 \end{grammar}
 
-\LMHash{}
-A {\em logical boolean expression} is either an equality expression (\ref{equality}), or an invocation of a logical boolean operator on an expression $e_1$ with argument $e_2$.
+\LMHash{}%
+A \Index{logical boolean expression} is either an equality expression (\ref{equality}), or an invocation of a logical boolean operator on an expression $e_1$ with argument $e_2$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a logical boolean expression $b$ of the form $e_1 || e_2$ causes the evaluation of $e_1$ to a value $o_1$.
 It is a run-time error if the run-time type of $o_1$ is not \code{bool}.
 If $o_1$ is \TRUE, the result of evaluating $b$ is \TRUE, otherwise $e_2$ is evaluated to an object $o_2$.
 It is a run-time error if the run-time type of $o_2$ is not \code{bool}.
 Otherwise the result of evaluating $b$ is $o_2$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a logical boolean expression $b$ of the form $e_1 \&\& e_2$ causes the evaluation of $e_1$ producing an object $o_1$.
 It is a run-time error if the run-time type of $o_1$ is not \code{bool}.
 If $o_1$ is \FALSE, the result of evaluating $b$ is \FALSE, otherwise $e_2$ is evaluated to an object $o_2$.
 It is a run-time error if the run-time type of $o_2$ is not \code{bool}.
 Otherwise the result of evaluating $b$ is $o_2$.
 
-\LMHash{}
+\LMHash{}%
 A logical boolean expression $b$ of the form $e_1 \&\& e_2$
 shows that a local variable $v$ has type $T$
 if both of the following conditions hold:
@@ -7955,7 +8130,7 @@
 \item $v$ is not mutated in $e_2$ or within a function other than the one where $v$ is declared.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 If $e_1$ shows that a local variable $v$ has type $T$,
 then the type of $v$ is known to be $T$ in $e_2$,
 unless any of the following are true:
@@ -7977,7 +8152,7 @@
 $v$ is potentially mutated anywhere in the scope of $v$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the static type of $e_1$ may not be assigned to \code{bool} or if the static type of $e_2$ may not be assigned to \code{bool}.
 The static type of a logical boolean expression is \code{bool}.
 
@@ -7985,21 +8160,22 @@
 \subsection{Equality}
 \LMLabel{equality}
 
-\LMHash{}
+\LMHash{}%
 Equality expressions test objects for equality.
 
 \begin{grammar}
-<equalityExpression> ::= <relationalExpression> (<equalityOperator> <relationalExpression>)?
+<equalityExpression> ::= \gnewline{}
+  <relationalExpression> (<equalityOperator> <relationalExpression>)?
   \alt \SUPER{} <equalityOperator> <relationalExpression>
 
 <equalityOperator> ::= `=='
   \alt `!='
 \end{grammar}
 
-\LMHash{}
-An {\em equality expression} is either a relational expression (\ref{relationalExpressions}), or an invocation of an equality operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
+\LMHash{}%
+An \Index{equality expression} is either a relational expression (\ref{relationalExpressions}), or an invocation of an equality operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of an equality expression $ee$ of the form \code{$e_1$ == $e_2$} proceeds as follows:
 \begin{itemize}
 \item The expression $e_1$ is evaluated to an object $o_1$.
@@ -8009,7 +8185,7 @@
 \item evaluation of $ee$ is equivalent to the method invocation \code{$o_1$.==($o_2$)}.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Evaluation of an equality expression $ee$ of the form \code{\SUPER{} == $e$} proceeds as follows:
 \begin{itemize}
 \item The expression $e$ is evaluated to an object $o$.
@@ -8026,25 +8202,25 @@
 Another implication is that there is never a need to use \code{identical()} to test against \NULL{}, nor should anyone ever worry about whether to write \NULL{} == $e$ or $e$ == \NULL{}.
 }
 
-\LMHash{}
+\LMHash{}%
 An equality expression of the form \code{$e_1$ != $e_2$} is equivalent to the expression \code{!($e_1$ == $e_2$)}.
 An equality expression of the form \code{\SUPER{} != $e$} is equivalent to the expression \code{!(\SUPER{} == $e$)}.
 
 %The expression $e_1$ is evaluated to an object $o_1$; then the expression $e_2$ is evaluated to an object $o_2$.  Next, if $o_1$ and $o_2$ are the same object, then $ee$ evaluates to \TRUE{}, otherwise $ee$ evaluates to \FALSE{}.
 
-\LMHash{}
+\LMHash{}%
 The static type of an equality expression is \code{bool}.
 
 
 \subsection{Relational Expressions}
 \LMLabel{relationalExpressions}
 
-\LMHash{}
+\LMHash{}%
 Relational expressions invoke the relational operators on objects.
 
 \begin{grammar}
-<relationalExpression> ::= <bitwiseOrExpression> (<typeTest> | <typeCast> |
-  \gnewline{} <relationalOperator> <bitwiseOrExpression>)?
+<relationalExpression> ::= <bitwiseOrExpression> \gnewline{}
+  (<typeTest> | <typeCast> | <relationalOperator> <bitwiseOrExpression>)?
   \alt \SUPER{} <relationalOperator> <bitwiseOrExpression>
 
 <relationalOperator> ::= `>='
@@ -8053,10 +8229,10 @@
   \alt `<'
 \end{grammar}
 
-\LMHash{}
-A {\em relational expression} is either a bitwise expression (\ref{bitwiseExpressions}), or an invocation of a relational operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
+\LMHash{}%
+A \Index{relational expression} is either a bitwise expression (\ref{bitwiseExpressions}), or an invocation of a relational operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
 
-\LMHash{}
+\LMHash{}%
 A relational expression of the form $e_1$ $op$ $e_2$ is equivalent to the method invocation \code{$e_1$.$op$($e_2$)}.
 A relational expression of the form \SUPER{} $op$ $e_2$ is equivalent to the method invocation \code{\SUPER{}.$op$($e_2$)}.
 
@@ -8064,14 +8240,16 @@
 \subsection{Bitwise Expressions}
 \LMLabel{bitwiseExpressions}
 
-\LMHash{}
+\LMHash{}%
 Bitwise expressions invoke the bitwise operators on objects.
 
 \begin{grammar}
-<bitwiseOrExpression> ::= <bitwiseXorExpression> (`|' <bitwiseXorExpression>)*
+<bitwiseOrExpression> ::= \gnewline{}
+  <bitwiseXorExpression> (`|' <bitwiseXorExpression>)*
   \alt \SUPER{} (`|' <bitwiseXorExpression>)+
 
-<bitwiseXorExpression> ::= <bitwiseAndExpression> (`^' <bitwiseAndExpression>)*
+<bitwiseXorExpression> ::= \gnewline{}
+  <bitwiseAndExpression> (`^' <bitwiseAndExpression>)*
   \alt \SUPER{} (`^' <bitwiseAndExpression>)+
 
 <bitwiseAndExpression> ::= <shiftExpression> (`\&' <shiftExpression>)*
@@ -8082,10 +8260,10 @@
   \alt `|'
 \end{grammar}
 
-\LMHash{}
-A {\em bitwise expression} is either a shift expression (\ref{shift}), or an invocation of a bitwise operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
+\LMHash{}%
+A \Index{bitwise expression} is either a shift expression (\ref{shift}), or an invocation of a bitwise operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
 
-\LMHash{}
+\LMHash{}%
 A bitwise expression of the form \code{$e_1$ $op$ $e_2$} is equivalent to the method invocation $e_1.op(e_2)$.
 A bitwise expression of the form \code{\SUPER{} $op$ $e_2$} is equivalent to the method invocation \code{\SUPER{}.$op$($e_2$)}.
 
@@ -8098,11 +8276,12 @@
 \subsection{Shift}
 \LMLabel{shift}
 
-\LMHash{}
+\LMHash{}%
 Shift expressions invoke the shift operators on objects.
 
 \begin{grammar}
-<shiftExpression> ::= <additiveExpression> (<shiftOperator> <additiveExpression>)*
+<shiftExpression> ::= \gnewline{}
+  <additiveExpression> (<shiftOperator> <additiveExpression>)*
   \alt \SUPER{} (<shiftOperator> <additiveExpression>)+
 
 <shiftOperator> ::= `\ltlt'
@@ -8110,10 +8289,10 @@
   \alt `\gtgtgt'
 \end{grammar}
 
-\LMHash{}
-A {\em shift expression} is either an additive expression (\ref{additiveExpressions}), or an invocation of a shift operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
+\LMHash{}%
+A \Index{shift expression} is either an additive expression (\ref{additiveExpressions}), or an invocation of a shift operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
 
-\LMHash{}
+\LMHash{}%
 A shift expression of the form $e_1$ $op$ $e_2$ is equivalent to the method invocation \code{$e_1$.$op$($e_2$)}.
 A shift expression of the form \SUPER{} $op$ $e_2$ is equivalent to the method invocation \code{\SUPER{}.$op$($e_2$)}.
 
@@ -8130,7 +8309,7 @@
 \subsection{Additive Expressions}
 \LMLabel{additiveExpressions}
 
-\LMHash{}
+\LMHash{}%
 Additive expressions invoke the addition operators on objects.
 
 \begin{grammar}
@@ -8142,14 +8321,14 @@
   \alt `-'
 \end{grammar}
 
-\LMHash{}
-An {\em additive expression} is either a multiplicative expression (\ref{multiplicativeExpressions}), or an invocation of an additive operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
+\LMHash{}%
+An \Index{additive expression} is either a multiplicative expression (\ref{multiplicativeExpressions}), or an invocation of an additive operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
 
-\LMHash{}
+\LMHash{}%
 An additive expression of the form $e_1$ $op$ $e_2$ is equivalent to the method invocation \code{$e_1$.$op$($e_2$)}.
 An additive expression of the form \SUPER{} $op$ $e_2$ is equivalent to the method invocation \code{\SUPER{}.$op$($e_2$)}.
 
-\LMHash{}
+\LMHash{}%
 The static type of an additive expression is usually determined by the signature given in the declaration of the operator used.
 However, invocations of the operators \code{+} and \code{-} of class \code{int} are treated specially by the typechecker.
 The static type of an expression $e_1 + e_2$ where $e_1$ has static type \code{int} is \code{int} if the static type of $e_2$ is \code{int}, and \code{double} if the static type of $e_2$ is \code{double}.
@@ -8159,11 +8338,12 @@
 \subsection{Multiplicative Expressions}
 \LMLabel{multiplicativeExpressions}
 
-\LMHash{}
+\LMHash{}%
 Multiplicative expressions invoke the multiplication operators on objects.
 
 \begin{grammar}
-<multiplicativeExpression> ::= <unaryExpression> (<multiplicativeOperator> <unaryExpression>)*
+<multiplicativeExpression> ::= \gnewline{}
+  <unaryExpression> (<multiplicativeOperator> <unaryExpression>)*
   \alt \SUPER{} (<multiplicativeOperator> <unaryExpression>)+
 
 <multiplicativeOperator> ::= `*'
@@ -8172,14 +8352,14 @@
   \alt `~/'
 \end{grammar}
 
-\LMHash{}
- A {\em multiplicative expression} is either a unary expression (\ref{unaryExpressions}), or an invocation of a multiplicative operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
+\LMHash{}%
+ A \Index{multiplicative expression} is either a unary expression (\ref{unaryExpressions}), or an invocation of a multiplicative operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
 
-\LMHash{}
+\LMHash{}%
 A multiplicative expression of the form $e_1$ $op$ $e_2$ is equivalent to the method invocation \code{$e_1$.$op$($e_2$)}.
 A multiplicative expression of the form \SUPER{} $op$ $e_2$ is equivalent to the method invocation \code{\SUPER{}.$op$($e_2$)}.
 
-\LMHash{}
+\LMHash{}%
 The static type of an multiplicative expression is usually determined by the signature given in the declaration of the operator used.
 However, invocations of the operators \code{*} and \code{\%} of class \code{int} are treated specially by the typechecker.
 The static type of an expression $e_1 * e_2$ where $e_1$ has static type \code{int} is \code{int} if the static type of $e_2$ is \code{int}, and \code{double} if the static type of $e_2$ is \code{double}.
@@ -8188,7 +8368,7 @@
 \subsection{Unary Expressions}
 \LMLabel{unaryExpressions}
 
-\LMHash{}
+\LMHash{}%
 Unary expressions invoke unary operators on objects.
 
 \begin{grammar}
@@ -8209,17 +8389,17 @@
 <tildeOperator> ::= `~'
 \end{grammar}
 
-\LMHash{}
-A {\em unary expression} is either a postfix expression (\ref{postfixExpressions}), an await expression (\ref{awaitExpressions}) or an invocation of a prefix operator on an expression or an invocation of a unary operator on either \SUPER{} or an expression $e$.
+\LMHash{}%
+A \Index{unary expression} is either a postfix expression (\ref{postfixExpressions}), an await expression (\ref{awaitExpressions}) or an invocation of a prefix operator on an expression or an invocation of a unary operator on either \SUPER{} or an expression $e$.
 
-\LMHash{}
+\LMHash{}%
 The expression $!e$ is equivalent to the expression \code{$e$\,?\,\FALSE\,:\,\TRUE}.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of an expression of the form \code{++$e$} is equivalent to \code{$e$\,+=\,1}.
 Evaluation of an expression of the form \code{-{}-$e$} is equivalent to \code{$e$\,-=\,1}.
 
-\LMHash{}
+\LMHash{}%
 Let $e$ be an expression of the form \code{-$l$}
 where $l$ is an integer literal (\ref{numbers}) with numeric integer value $i$,
 and with static context type $T$.
@@ -8227,7 +8407,7 @@
 then the static type of $e$ is \code{double};
 otherwise the static type of $e$ is \code{int}.
 
-\LMHash{}
+\LMHash{}%
 If the static type of $e$ is \code{int} then $e$ evaluates to
 to an instance of the \code{int} class representing the numeric value $-i$.
 If $i$ is zero and the \code{int} class can represent a negative zero value,
@@ -8235,7 +8415,7 @@
 It is a compile-time error if the integer $-i$ cannot be represented
 exactly by an instance of \code{int}.
 
-\LMHash{}
+\LMHash{}%
 If the static type of $e$ is \code{double} then $e$ evaluates to
 to an instance of the \code{double} class representing the numeric value $-i$.
 If $i$ is zero, the resulting instance instead represents the
@@ -8249,7 +8429,7 @@
 or concern ourselves with its static type.
 }
 
-\LMHash{}
+\LMHash{}%
 Any other expression of the form \code{$op$ $e$} is equivalent to the method invocation \code{$e.op()$}.
 An expression of the form \code{$op$ \SUPER{}} is equivalent to the method invocation (\ref{superInvocation}) \code{\SUPER{}.$op()$}.
 
@@ -8257,24 +8437,24 @@
 \subsection{Await Expressions}
 \LMLabel{awaitExpressions}
 
-\LMHash{}
-An {\em await expression} allows code to yield control until an asynchronous operation (\ref{functions}) completes.
+\LMHash{}%
+An \Index{await expression} allows code to yield control until an asynchronous operation (\ref{functions}) completes.
 
 \begin{grammar}
 <awaitExpression> ::= \AWAIT{} <unaryExpression>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Evaluation of an await expression $a$ of the form \AWAIT{} $e$ proceeds as follows:
 First, the expression $e$ is evaluated to an object $o$.
 
-\LMHash{}
+\LMHash{}%
 % NOTICE: Removed the requirement that an error thrown by $e$ is caught in a
 % future. There is no reason $var x = e; await x;$ and $await e$ should behave
 % differently, and no implementation actually implemented it.
 Then, if $o$ is not an instance of \code{Future}, then let $f$ be the result of creating a new object using the constructor \code{Future.value()} with $o$ as its argument; otherwise let $f$ be $o$.
 
-\LMHash{}
+\LMHash{}%
 Next, the stream associated with the innermost enclosing asynchronous for loop (\ref{asynchronousFor-in}), if any, is paused.
 The current invocation of the function body immediately enclosing $a$ is suspended until after $f$ completes.
 At some time after $f$ is completed, control returns to the current invocation.
@@ -8301,14 +8481,14 @@
 Tools may choose to give a hint in such cases.
 }
 
-\LMHash{}
+\LMHash{}%
 The static type of $a$ is \flatten{T} (\flatten{} is defined in section \ref{functionExpressions}) where $T$ is the static type of $e$.
 
 
 \subsection{Postfix Expressions}
 \LMLabel{postfixExpressions}
 
-\LMHash{}
+\LMHash{}%
 Postfix expressions invoke the postfix operators on objects.
 
 \begin{grammar}
@@ -8324,18 +8504,18 @@
   \alt `-\mbox-'
 \end{grammar}
 
-\LMHash{}
-A {\em postfix expression} is either a primary expression, a function, method or getter invocation, or an invocation of a postfix operator on an expression $e$.
+\LMHash{}%
+A \Index{postfix expression} is either a primary expression, a function, method or getter invocation, or an invocation of a postfix operator on an expression $e$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a postfix expression $e$ of the form \code{$v$++}, where $v$ is an identifier, proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 Evaluate $v$ to an object $r$ and let $y$ be a fresh variable bound to $r$.
 Evaluate \code{$v$ = $y$ + 1}.
 Then $e$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 The static type of such an expression is the static type of $v$.
 
 \rationale{
@@ -8343,38 +8523,38 @@
 Likewise in the cases below.
 }
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a postfix expression $e$ of the form \code{$C$.$v$++}
 where $C$ is a type literal proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 Evaluate \code{$C$.$v$} to a value $r$
 and let $y$ be a fresh variable bound to $r$.
 Evaluate \code{$C$.$v$ = $y$ + 1}.
 Then $e$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 The static type of such an expression is the static type of \code{$C$.$v$}.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a postfix expression $e$ of the form \code{$e_1$.$v$++}
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 Evaluate $e_1$ to an object $u$ and let $x$ be a fresh variable bound to $u$.
 Evaluate \code{$x$.$v$} to a value $r$
 and let $y$ be a fresh variable bound to $r$.
 Evaluate \code{$x$.$v$ = $y$ + 1}.
 Then $e$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 The static type of such an expression is the static type of \code{$e_1$.$v$}.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a postfix expression $e$ of the form \code{$e_1$[$e_2$]++}
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 Evaluate $e_1$ to an object $u$ and $e_2$ to an object $v$.
 Let $a$ and $i$ be fresh variables bound to $u$ and $v$ respectively.
 Evaluate \code{$a$[$i$]} to an object $r$
@@ -8382,53 +8562,53 @@
 Evaluate \code{$a$[$i$] = $y$ + 1}.
 Then $e$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 The static type of such an expression is the static type of \code{$e_1$[$e_2$]}.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a postfix expression $e$ of the form \code{$v$-{}-}, where $v$ is an identifier, proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 Evaluate the expression $v$ to an object $r$
 and let $y$ be a fresh variable bound to $r$.
 Evaluate \code{$v$ = $y$ - 1}.
 Then $e$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 The static type of such an expression is the static type of $v$.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a postfix expression $e$ of the form \code{$C$.$v$-{}-}
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 Evaluate \code{$C$.$v$} to a value $r$
 and let $y$ be a fresh variable bound to $r$.
 Evaluate \code{$C$.$v$ = $y$ - 1}.
 Then $e$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 The static type of such an expression is the static type of \code{$C$.$v$}.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a postfix expression of the form \code{$e_1$.$v$-{}-}
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 Evaluate $e_1$ to an object $u$ and let $x$ be a fresh variable bound to $u$.
 Evaluate \code{$x$.$v$} to a value $r$
 and let $y$ be a fresh variable bound to $r$.
 Evaluate \code{$x$.$v$ = $y$ - 1}.
 Then $e$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 The static type of such an expression is the static type of \code{$e_1$.$v$}.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a postfix expression $e$ of the form \code{$e_1$[$e_2$]-{}-}
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 Evaluate $e_1$ to an object $u$ and $e_2$ to an object $v$.
 Let $a$ and $i$ be fresh variables bound to $u$ and $v$ respectively.
 Evaluate \code{$a$[$i$]} to an object $r$
@@ -8436,28 +8616,28 @@
 Evaluate \code{$a$[$i$] = $y$ - 1}.
 Then $e$ evaluates to $r$.
 
-\LMHash{}
+\LMHash{}%
 The static type of such an expression is the static type of \code{$e_1$[$e_2$]}.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a postfix expression $e$ of the form \code{$e_1$?.$v$++}
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 If $e_1$ is a type literal, evaluation of $e$ is equivalent to
 evaluation of \code{$e_1$.$v$++}.
 
-\LMHash{}
+\LMHash{}%
 Otherwise evaluate $e_1$ to an object $u$.
 if $u$ is the null object, $e$ evaluates to the null object (\ref{null}).
 Otherwise let $x$ be a fresh variable bound to $u$.
 Evaluate \code{$x$.$v$++} to an object $o$.
 Then $e$ evaluates to $o$.
 
-\LMHash{}
+\LMHash{}%
 The static type of such an expression is the static type of \code{$e_1$.$v$}.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of a postfix expression $e$ of the form \code{$e_1$?.$v$-{}-}
 proceeds as follows:
 
@@ -8470,19 +8650,19 @@
 Evaluate \code{$x$.$v$-{}-} to an object $o$.
 Then $e$ evaluates to $o$.
 
-\LMHash{}
+\LMHash{}%
 The static type of such an expression is the static type of \code{$e_1$.$v$}.
 
 
 \subsection{Assignable Expressions}
 \LMLabel{assignableExpressions}
 
-\LMHash{}
+\LMHash{}%
 Assignable expressions are expressions that can appear on the left hand side of an assignment.
 This section describes how to evaluate these expressions when they do not constitute the complete left hand side of an assignment.
 
 \rationale{
-Of course, if assignable expressions always appeared {\em as} the left hand side, one would have no need for their value, and the rules for evaluating them would be unnecessary.
+Of course, if assignable expressions always appeared \emph{as} the left hand side, one would have no need for their value, and the rules for evaluating them would be unnecessary.
 However, assignable expressions can be subexpressions of other expressions and therefore must be evaluated.
 }
 
@@ -8498,37 +8678,37 @@
   \alt `?.' <identifier>
 \end{grammar}
 
-\LMHash{}
-An {\em assignable expression} is either:
+\LMHash{}%
+An \Index{assignable expression} is either:
 \begin{itemize}
 \item An identifier.
 \item An invocation (possibly conditional) of a getter (\ref{getters}) or list access operator on an expression $e$.
 \item An invocation of a getter or list access operator on \SUPER{}.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 An assignable expression of the form \id{} is evaluated as an identifier expression (\ref{identifierReference}).
 
 %An assignable expression of the form \code{$e$.\id($a_1, \ldots,\ a_n$)} is evaluated as a method invocation (\ref{methodInvocation}).
 
-\LMHash{}
+\LMHash{}%
 An assignable expression of the form \code{$e$.\id} or \code{$e$?.\id} is evaluated as a property extraction (\ref{propertyExtraction}).
 
-\LMHash{}
+\LMHash{}%
 An assignable expression of the form \code{$e_1$[$e_2$]} is evaluated as a method invocation of the operator method \code{[]} on $e_1$ with argument $e_2$.
 
-\LMHash{}
+\LMHash{}%
 An assignable expression of the form \code{\SUPER{}.\id} is evaluated as a property extraction.
 
-\LMHash{}
+\LMHash{}%
 Evaluation of an assignable expression of the form \code{\SUPER{}[$e_2$]} is equivalent to evaluation of the method invocation \code{\SUPER{}.[]($e_2$)}.
 
 
 \subsection{Identifier Reference}
 \LMLabel{identifierReference}
 
-\LMHash{}
-An {\em identifier expression} consists of a single identifier; it provides access to an object via an unqualified name.
+\LMHash{}%
+An \Index{identifier expression} consists of a single identifier; it provides access to an object via an unqualified name.
 
 \begin{grammar}
 <identifier> ::= <IDENTIFIER>
@@ -8566,7 +8746,8 @@
 <IDENTIFIER\_START\_NO\_DOLLAR> ::= <LETTER>
   \alt `_'
 
-<IDENTIFIER\_PART\_NO\_DOLLAR> ::= <IDENTIFIER\_START\_NO\_DOLLAR>
+<IDENTIFIER\_PART\_NO\_DOLLAR> ::= \gnewline{}
+  <IDENTIFIER\_START\_NO\_DOLLAR>
   \alt <DIGIT>
 
 <IDENTIFIER\_PART> ::= <IDENTIFIER\_START>
@@ -8575,8 +8756,9 @@
 <qualified> ::= <identifier> (`.' <identifier>)?
 \end{grammar}
 
-\LMHash{}
-A built-in identifier is one of the identifiers produced by the production {\em BUILT\_IN\_IDENTIFIER}.
+\LMHash{}%
+A built-in identifier is one of the identifiers produced by the production
+\synt{BUILT\_IN\_IDENTIFIER}.
 It is a compile-time error if a built-in identifier is used as the declared name of a prefix, class, type parameter or type alias.
 It is a compile-time error to use a built-in identifier other than \DYNAMIC{} in a type annotation or type parameter.
 
@@ -8590,7 +8772,7 @@
 Furthermore, types should begin with an uppercase letter (see the appendix) and so no clash should occur in any Dart user program anyway.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if either of the identifiers \AWAIT{} or \YIELD{} is used as an identifier in a function body marked with either \ASYNC{}, \code{\ASYNC*} or \code{\SYNC*}.
 
 \rationale{
@@ -8599,16 +8781,16 @@
 Hence the restriction, which treats these names as reserved words in a limited context.
 }
 
-\LMHash{}
+\LMHash{}%
 Evaluation of an identifier expression $e$ of the form \id{} proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 Let $d$ be the innermost declaration in the enclosing lexical scope whose name is \id{} or \code{\id=}.
 If no such declaration exists in the lexical scope, let $d$ be the declaration of the inherited member named \id{} if it exists.
 
 \begin{itemize}
 \item if $d$ is a prefix $p$, a compile-time error occurs unless the token immediately following $d$ is \code{'.'}.
-\item If $d$ is a class or type alias $T$, the value of $e$ is an instance of class \code{Type} (or a subclass thereof) reifying $T$.
+\item If $d$ is a class or type alias $T$, the value of $e$ is an object implementing the class \code{Type} which reifies $T$.
 \item If $d$ is a type parameter $T$, then the value of $e$ is the value of the actual type argument corresponding to $T$ that was passed to the generative constructor that created the current binding of \THIS{}.
 If, however, $e$ occurs inside a static member, a compile-time error occurs.
 
@@ -8628,7 +8810,7 @@
 \item Otherwise, evaluation of $e$ is equivalent to evaluation of the property extraction (\ref{propertyExtraction}) \code{\THIS.\id}.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 The static type of $e$ is determined as follows:
 
 \begin{itemize}
@@ -8657,7 +8839,7 @@
 The intent is to prevent errors when a getter in a surrounding scope is used accidentally.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if an identifier expression \id{} occurs inside a top level or static function
 (be it function, method, getter, or setter)
 or in an instance variable initializer,
@@ -8668,8 +8850,8 @@
 \subsection{Type Test}
 \LMLabel{typeTest}
 
-\LMHash{}
-The {\em is-expression} tests if an object is a member of a type.
+\LMHash{}%
+The \Index{is-expression} tests if an object is a member of a type.
 
 \begin{grammar}
 <typeTest> ::= <isOperator> <type>
@@ -8677,10 +8859,10 @@
 <isOperator> ::= \IS{} `!'?
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Evaluation of the is-expression \code{$e$ \IS{} $T$} proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 The expression $e$ is evaluated to a value $v$.
 % TODO(eernst): https://github.com/dart-lang/sdk/issues/34521.
 Then, if $T$ is a malformed or deferred type (\ref{staticTypes}), a dynamic error occurs.
@@ -8696,12 +8878,12 @@
 Users should test for the null object (\ref{null}) directly rather than via type tests.
 }
 
-\LMHash{}
+\LMHash{}%
 The is-expression \code{$e$ \IS{}! $T$} is equivalent to \code{!($e$ \IS{} $T$)}.
 
 % Add flow dependent types
 
-\LMHash{}
+\LMHash{}%
 Let $v$ be a local variable (\commentary{which can be a formal parameter}).
 An is-expression of the form \code{$v$ \IS{} $T$} shows that $v$ has type $T$ if{}f $T$ is more specific than the type $S$ of the expression $v$ and both $T \ne \DYNAMIC{}$ and $S \ne \DYNAMIC{}$.
 
@@ -8720,15 +8902,15 @@
 The opposite requirement, that $T \ne \DYNAMIC{}$ is a safeguard lest $S$ ever be $\bot$.
 }
 
-\LMHash{}
+\LMHash{}%
 The static type of an is-expression is \code{bool}.
 
 
 \subsection{Type Cast}
 \LMLabel{typeCast}
 
-\LMHash{}
-The {\em cast expression} ensures that an object is a member of a type.
+\LMHash{}%
+The \Index{cast expression} ensures that an object is a member of a type.
 
 \begin{grammar}
 <typeCast> ::= <asOperator> <type>
@@ -8736,10 +8918,10 @@
 <asOperator> ::= \AS{}
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
  Evaluation of the cast expression \code{$e$ \AS{} $T$} proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 The expression $e$ is evaluated to a value $v$.
 %% TODO(eernst): https://github.com/dart-lang/sdk/issues/34521
 Then, if $T$ is a malformed or deferred type (\ref{staticTypes}), a dynamic error occurs.
@@ -8747,19 +8929,28 @@
 and the dynamic type of $o$ is not a subtype of $T$.
 Otherwise $e$ evaluates to $v$.
 
-\LMHash{}
+\LMHash{}%
 The static type of a cast expression \code{$e$ \AS{} $T$} is $T$.
 
 
 \section{Statements}
 \LMLabel{statements}
 
-\LMHash{}
-A {\em statement} is a fragment of Dart code that can be executed at run time.
+\LMHash{}%
+A \Index{statement} is a fragment of Dart code that can be executed at run time.
 Statements, unlike expressions, do not evaluate to a value, but are instead executed for their effect on the program state and control flow.
 
 \label{completion}
-Execution of a statement {\em completes} in one of five ways: either it {\em completes normally}, it {\em breaks} or it {\em continues} (either to a label or without a label), it {\em returns} (with or without a value), or it {\em throws} an exception object and an associated stack trace.
+Execution of a statement \IndexCustom{completes}{completion}
+in one of five ways:
+either it
+\IndexCustom{completes normally}{completion!normally},
+it \IndexCustom{breaks}{completion!breaks}
+or it \IndexCustom{continues}{completion!continues}
+(either to a label or without a label),
+it \IndexCustom{returns}{completion!returns} (with or without a value),
+or it \IndexCustom{throws}{completion!throws}
+an exception object and an associated stack trace.
 
 In the description of statement execution, the default is that the execution
 completes normally unless otherwise stated.
@@ -8783,7 +8974,7 @@
 Likewise, if evaluation of the expression of a \RETURN{} statement throws, so does execution of the \RETURN{} statement.
 }
 
-\LMHash{}
+\LMHash{}%
 
 \begin{grammar}
 <statements> ::= <statement>*
@@ -8813,31 +9004,31 @@
 \subsection{Blocks}
 \LMLabel{blocks}
 
-\LMHash{}
-A {\em block statement} supports sequencing of code.
+\LMHash{}%
+A \Index{block statement} supports sequencing of code.
 
-\LMHash{}
+\LMHash{}%
 Execution of a block statement $\{s_1, \ldots, s_n\}$ proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 For $i \in 1 .. n, s_i$ is executed.
 
-\LMHash{}
+\LMHash{}%
 A block statement introduces a new scope, which is nested in the lexically enclosing scope in which the block statement appears.
 
 
 \subsection{Expression Statements}
 \LMLabel{expressionStatements}
 
-\LMHash{}
-An {\em expression statement} consists of an expression that does not
+\LMHash{}%
+An \Index{expression statement} consists of an expression that does not
 begin with a \syntax{`{'} character.
 
 \begin{grammar}
 <expressionStatement> ::= <expression>? `;'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 The expression of an expression statement is not allowed to begin with a \syntax{`\{'}.
 \commentary{
 This means that if some source text could otherwise be parsed as an expression
@@ -8852,7 +9043,7 @@
 before deciding that it is parsing a block statement.
 }
 
-\LMHash{}
+\LMHash{}%
 Execution of an expression statement \code{$e$;} proceeds by evaluating $e$.
 If the expression evaluates to a value, then the value is ignored
 and the execution completes normally.
@@ -8861,18 +9052,19 @@
 \subsection{Local Variable Declaration}
 \LMLabel{localVariableDeclaration}
 
-\LMHash{}
-A {\em variable declaration statement},
-also known as a {\em local variable declaration},
+\LMHash{}%
+A \Index{variable declaration statement},
+also known as a \Index{local variable declaration},
 has the following form:
 
 \begin{grammar}
 <localVariableDeclaration> ::= <initializedVariableDeclaration> `;'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Each local variable declaration introduces
-a {\em local variable} into the innermost enclosing scope.
+a \IndexCustom{local variable}{variable!local}
+into the innermost enclosing scope.
 
 \commentary{
 Local variables do not induce getters and setters.
@@ -8881,17 +9073,21 @@
 (\ref{formalParameters}).
 }
 
-\LMHash{}
+\LMHash{}%
 The properties of being
-{\em initialized}, {\em constant}, {\em final}, and {\em mutable}
+\IndexCustom{initialized}{variable!initialized},
+\IndexCustom{constant}{variable!constant},
+\IndexCustom{final}{variable!final}, and
+\IndexCustom{mutable}{variable!mutable}
 apply to local variables with the same definitions as for other variables
 (\ref{variables}).
 
-\LMHash{}
-We say that a local variable $v$ is {\em potentially mutated} in some scope $s$
+\LMHash{}%
+We say that a local variable $v$ is \Index{potentially mutated}
+in some scope $s$
 if $v$ is mutable, and an assignment to $v$ occurs in $s$.
 
-\LMHash{}
+\LMHash{}%
 A local variable declaration of the form \code{\VAR{} $v$;} is equivalent to \code{\VAR{} $v$ = \NULL{};}.
 A local variable declaration of the form \code{$T$ $v$;} is equivalent to \code{$T$ $v$ = \NULL{};}.
 
@@ -8900,7 +9096,7 @@
 E.g., \code{int i;} is equivalent to \code{int i = null;}.
 }
 
-\LMHash{}
+\LMHash{}%
 The type of a local variable with a declaration of one of the forms
 \code{$T$ $v$ = $e$;}
 \code{\CONST{} $T$ $v$ = $e$;}
@@ -8912,7 +9108,7 @@
 \code{\FINAL{} $v$ = $e$;}
 is \DYNAMIC{}.
 
-\LMHash{}
+\LMHash{}%
 Let $v$ be a local variable declared by an initializing variable declaration,
 and let $e$ be the associated initializing expression.
 It is a compile-time error if the static type of $e$ is not assignable to the type of $v$.
@@ -8924,7 +9120,7 @@
 (\ref{assignment}).
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if
 a local variable is referenced at a source code location that is before
 the end of its initializing expression, if any,
@@ -9001,7 +9197,7 @@
 Similarly, for the declaration of `\code{aC}'.
 }
 
-\LMHash{}
+\LMHash{}%
 Execution of a variable declaration statement of one of the forms
 \code{\VAR{} $v$ = $e$;}
 \code{$T$ $v$ = $e$;}
@@ -9011,7 +9207,7 @@
 \code{\FINAL{} $T$ $v$ = $e$;}
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 The expression $e$ is evaluated to an object $o$.
 Then, the variable $v$ is set to $o$.
 A dynamic type error occurs
@@ -9026,14 +9222,14 @@
 \subsection{Local Function Declaration}
 \LMLabel{localFunctionDeclaration}
 
-\LMHash{}
+\LMHash{}%
 A function declaration statement declares a new local function (\ref{functionDeclarations}).
 
 \begin{grammar}
 <localFunctionDeclaration> ::= <functionSignature> <functionBody>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 A function declaration statement of one of the forms
 \code{\id{} \metavar{signature} \{ \metavar{statements} \}}
 or
@@ -9090,14 +9286,14 @@
 \subsection{If}
 \LMLabel{if}
 
-\LMHash{}
-The {\em if statement} allows for conditional execution of statements.
+\LMHash{}%
+The \Index{if statement} allows for conditional execution of statements.
 
 \begin{grammar}
 <ifStatement> ::= \IF{} `(' <expression> `)' <statement> (\ELSE{} <statement>)?
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 An if statement of the form \code{\IF{} ($e$) $s_1$ \ELSE{} $s_2$} where $s_1$ is not a block statement is equivalent to the statement \code{\IF{} ($e$) \{$s_1$\} \ELSE{} $s_2$}.
 An if statement of the form \code{\IF{} ($e$) $s_1$ \ELSE{} $s_2$} where $s_2$ is not a block statement is equivalent to the statement \code{\IF{} ($e$) $s_1$ \ELSE{} \{$s_2$\}}.
 
@@ -9124,18 +9320,18 @@
 We expect tools to highlight cases of shadowing to help avoid such situations.
 }
 
-\LMHash{}
+\LMHash{}%
 Execution of an if statement of the form \code{\IF{} ($b$) $s_1$ \ELSE{} $s_2$} where $s_1$ and $s_2$ are block statements, proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 First, the expression $b$ is evaluated to an object $o$.
 It is a run-time error if the run-time type of $o$ is not \code{bool}.
 If $o$ is \TRUE{}, then the block statement $s_1$ is executed, otherwise the block statement $s_2$ is executed.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the type of the expression $b$ may not be assigned to \code{bool}.
 
-\LMHash{}
+\LMHash{}%
 If $b$ shows that a local variable $v$ has type $T$,
 then the type of $v$ is known to be $T$ in $s_2$,
 unless any of the following are true
@@ -9147,15 +9343,15 @@
 $v$ is potentially mutated anywhere in the scope of $v$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 An if statement of the form \code{\IF{} ($e$) $s$} is equivalent to the if statement \code{\IF{} ($e$) $s$ \ELSE{} \{\}}.
 
 
 \subsection{For}
 \LMLabel{for}
 
-\LMHash{}
-The {\em for statement} supports iteration.
+\LMHash{}%
+The \Index{for statement} supports iteration.
 
 \begin{grammar}
 <forStatement> ::= \AWAIT? \FOR{} `(' <forLoopParts> `)' <statement>
@@ -9168,20 +9364,20 @@
   \alt <expression>? `;'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
  The for statement has three forms - the traditional for loop and two forms of the for-in statement - synchronous and asynchronous.
 
 
 \subsubsection{For Loop}
 \LMLabel{forLoop}
 
-\LMHash{}
+\LMHash{}%
 Execution of a for statement of the form \code{\FOR{} (\VAR{} $v$ = $e_0$; $c$; $e$) $s$} proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 If $c$ is empty then let $c'$ be \TRUE{} otherwise let $c'$ be $c$.
 
-\LMHash{}
+\LMHash{}%
 First the variable declaration statement \VAR{} $v = e_0$ is executed.
 Then:
 \begin{enumerate}
@@ -9222,7 +9418,7 @@
 and then modifies $v''$ as required for the next iteration.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the static type of $c$ may not be assigned to \code{bool}.
 
 %A for statement of the form \code{\FOR{} ($d$ ; $c$; $e$) $s$} is equivalent to the following code:
@@ -9241,7 +9437,7 @@
 \subsubsection{For-in}
 \LMLabel{for-in}
 
-\LMHash{}
+\LMHash{}%
 Let $D$ be derived from \syntax{<finalConstVarOrType>?}
 and let $n0$ be an identifier that does not occur anywhere in the program.
 A for statement of the form \code{\FOR{} ($D$ \id{} \IN{} $e$) $s$} is equivalent to the following code:
@@ -9266,23 +9462,23 @@
 \subsubsection{Asynchronous For-in}
 \LMLabel{asynchronousFor-in}
 
-\LMHash{}
+\LMHash{}%
 A for-in statement may be asynchronous.
 The asynchronous form is designed to iterate over streams.
 An asynchronous for loop is distinguished by the keyword \AWAIT{} immediately preceding the keyword \FOR.
 
-\LMHash{}
+\LMHash{}%
 Let $D$ be derived from \syntax{<finalConstVarOrType>?}.
 Execution of a for-in statement, $f$, of the form
 \code{\AWAIT{} \FOR{} ($D$ \id{} \IN{} $e$) $s$}
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 The expression $e$ is evaluated to an object $o$.
 It is a dynamic type error if $o$ is not an instance of a class that implements \code{Stream}.
 It is a compile-time error if $D$ is empty and \id{} is a final variable.
 
-\LMHash{}
+\LMHash{}%
 The stream associated with the innermost enclosing asynchronous for loop, if any, is paused.
 The stream $o$ is listened to, producing a stream subscription $u$,
 and execution of the asynchronous for-in loop is suspended
@@ -9299,8 +9495,8 @@
 The \code{pause} call can throw, although that should never happen for a correctly implemented stream.
 }
 
-\LMHash{}
-For each {\em data event} from $u$,
+\LMHash{}%
+For each \Index{data event} from $u$,
 the statement $s$ is executed with \id{} bound to the value of the current data event.
 
 \commentary{
@@ -9311,7 +9507,7 @@
 If $o$ doesn't act as a valid stream, for example by not respecting pause requests, the behavior of the asynchronous loop may become unpredictable.
 }
 
-\LMHash{}
+\LMHash{}%
 If execution of $s$ continues without a label, or to a label (\ref{labels}) that prefixes the asynchronous for statement (\ref{completion}), then the execution of $s$ is treated as if it had completed normally.
 
 If execution of $s$ otherwise does not complete normally, the subscription $u$ is canceled by evaluating \code{\AWAIT{} $v$.cancel()} where $v$ is a fresh variable referencing the stream subscription $u$.
@@ -9328,8 +9524,8 @@
 That should never happen for a correctly implemented stream.
 }
 
-\LMHash{}
-On an {\em error event} from $u$,
+\LMHash{}%
+On an \Index{error event} from $u$,
 with error object $e$ and stack trace $st$,
 the subscription $u$ is canceled by evaluating \code{\AWAIT{} v.cancel()}
 where $v$ is a fresh variable referencing the stream subscription $u$.
@@ -9337,10 +9533,10 @@
 execution of $f$ throws the same exception object and stack trace.
 Otherwise execution of $f$ throws with $e$ as exception object and $st$ as stack trace.
 
-\LMHash{}
+\LMHash{}%
 When $u$ is done, execution of $f$ completes normally.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if an asynchronous for-in statement appears inside a synchronous function (\ref{functions}).
 It is a compile-time error if a traditional for loop (\ref{forLoop}) is prefixed by the \AWAIT{} keyword.
 
@@ -9352,24 +9548,24 @@
 \subsection{While}
 \LMLabel{while}
 
-\LMHash{}
+\LMHash{}%
 The while statement supports conditional iteration, where the condition is evaluated prior to the loop.
 
 \begin{grammar}
 <whileStatement> ::= \WHILE{} `(' <expression> `)' <statement>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Execution of a while statement of the form \code{\WHILE{} ($e$) $s$;} proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 The expression $e$ is evaluated to an object $o$.
 It is a run-time error if the run-time type of $o$ is not \code{bool}.
 
-\LMHash{}
+\LMHash{}%
 If $o$ is \FALSE{}, then execution of the while statement completes normally (\ref{completion}).
 
-\LMHash{}
+\LMHash{}%
 Otherwise $o$ is \TRUE{} and then the statement $\{s\}$ is executed.
 If that execution completes normally or it continues with no label or to a label (\ref{labels}) that prefixes the \WHILE{} statement (\ref{completion}), then the while statement is re-executed.
 If the execution breaks without a label, execution of the while statement completes normally.
@@ -9378,52 +9574,53 @@
 it does end execution of the loop, but the break itself is handled by the surrounding labeled statement (\ref{labels}).
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the static type of $e$ may not be assigned to \code{bool}.
 
 
 \subsection{Do}
 \LMLabel{do}
 
-\LMHash{}
+\LMHash{}%
 The do statement supports conditional iteration, where the condition is evaluated after the loop.
 
 \begin{grammar}
 <doStatement> ::= \DO{} <statement> \WHILE{} `(' <expression> `)' `;'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Execution of a do statement of the form \code{\DO{} $s$ \WHILE{} ($e$);} proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 The statement $\{s\}$ is executed.
 If that execution continues with no label, or to a label (\ref{labels}) that prefixes the do statement (\ref{completion}), then the execution of $s$ is treated as if it had completed normally.
 
-\LMHash{}
+\LMHash{}%
 Then, the expression $e$ is evaluated to an object $o$.
 It is a run-time error if the run-time type of $o$ is not \code{bool}.
 If $o$ is \FALSE{}, execution of the do statement completes normally (\ref{completion}).
 If $o$ is \TRUE{}, then the do statement is re-executed.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the static type of $e$ may not be assigned to \code{bool}.
 
 
 \subsection{Switch}
 \LMLabel{switch}
 
-\LMHash{}
-The {\em switch statement} supports dispatching control among a large number of cases.
+\LMHash{}%
+The \Index{switch statement} supports dispatching control among a large number of cases.
 
 \begin{grammar}
-<switchStatement> ::= \SWITCH{} `(' <expression> `)' `{' <switchCase>* <defaultCase>? `}'
+<switchStatement> ::= \gnewline{}
+  \SWITCH{} `(' <expression> `)' `{' <switchCase>* <defaultCase>? `}'
 
 <switchCase> ::= <label>* \CASE{} <expression> `:' <statements>
 
 <defaultCase> ::= <label>* \DEFAULT{} `:' <statements>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
  Given a switch statement of the form
 
 \begin{dartCode}
@@ -9462,14 +9659,17 @@
 Note that the values of the expressions are known at compile time, and are independent of any type annotations.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the class $C$ has an implementation of
 the operator \code{==} other than the one inherited from \code{Object},
 unless the expression evaluates to a string or an integer,
-or the expression evaluates to an instance of the built-in
+the expression evaluates to an instance of the built-in
 class \code{Symbol} which was initially obtained by evaluation of a
 literal symbol or
-a constant invocation of a constructor of the \code{Symbol} class.
+a constant invocation of a constructor of the \code{Symbol} class,
+or to an object implementing the built-in class \code{Type}
+which was originally created by evaluating a constant type literal
+(\ref{dynamicTypeSystem}).
 
 \rationale{
 The prohibition on user defined equality allows us to implement the switch efficiently for user defined types.
@@ -9481,7 +9681,7 @@
 The \SWITCH{} statement should only be used in very limited situations (e.g., interpreters or scanners).
 }
 
-\LMHash{}
+\LMHash{}%
 Execution of a switch statement of the form
 
 \begin{dartCode}
@@ -9505,7 +9705,7 @@
 
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 The statement \code{\VAR{} \id{} = $e$;} is evaluated, where \id{} is a fresh variable.
 It is a run-time error if the value of $e$ is
 not an instance of the same class as the constants $e_1, \ldots, e_n$.
@@ -9514,11 +9714,11 @@
 Note that if there are no case clauses ($n = 0$), the type of $e$ does not matter.
 }
 
-\LMHash{}
+\LMHash{}%
 Next, the case clause \CASE{} $e_{1}$: $s_{1}$ is matched against \id, if $n > 0$.
 Otherwise if there is a \DEFAULT{} clause, the case statements $s_{n+1}$ are executed (\ref{case-execute}).
 
-\LMHash{}
+\LMHash{}%
 Matching of a \CASE{} clause \CASE{} $e_{k}: s_{k}$ of a switch statement
 
 \begin{dartCode}
@@ -9532,7 +9732,7 @@
 
 against the value of a variable \id{} proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 The expression \code{$e_k$ == \id} is evaluated to an object $o$.
 It is a run-time error if the run-time type of $o$ is not \code{bool}.
 If $o$ is \FALSE{} the following case, \CASE{} $e_{k+1}: s_{k+1}$ is matched against \id{} if $k < n$, and if $k = n$, then the \DEFAULT{} clause's statements are executed (\ref{case-execute}).
@@ -9540,7 +9740,7 @@
 If no such $h$ exists, let $h = n + 1$.
 The case statements $s_h$ are then executed (\ref{case-execute}).
 
-\LMHash{}
+\LMHash{}%
 Matching of a \CASE{} clause \CASE{} $e_{k}: s_{k}$ of a switch statement
 
 \begin{dartCode}
@@ -9553,7 +9753,7 @@
 
 against the value of a variable \id{} proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 The expression \code{$e_k$ == \id} is evaluated to an object $o$.
 It is a run-time error if the run-time type of $o$ is not \code{bool}.
 If $o$ is \FALSE{} the following case, \CASE{} $e_{k+1}: s_{k+1}$ is matched against \id{} if $k < n$.
@@ -9561,7 +9761,7 @@
 If such a $h$ exists, the case statements $s_h$ are executed (\ref{case-execute}).
 Otherwise the switch statement completes normally (\ref{completion}).
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the type of $e$ may not be assigned to the type of $e_k$.
 Let $s$ be the last statement of the statement sequence $s_k$.
 If $s$ is a non-empty block statement, let $s$ instead be the last statement of the block statement.
@@ -9594,8 +9794,8 @@
   Very elaborate code in a case clause is probably bad style in any case, and such code can always be refactored.
 }
 
-\LMHash{}
-It is a compile-time warning if all of the following conditions hold:
+\LMHash{}%
+It is a static warning if all of the following conditions hold:
 \begin{itemize}
 \item The switch statement does not have a default clause.
 \item The static type of $e$ is an enumerated type with elements $\id_1, \ldots, \id_n$.
@@ -9610,7 +9810,7 @@
 \subsubsection{Switch case statements}
 \LMLabel{case-execute}
 
-\LMHash{}
+\LMHash{}%
 Execution of the case statements $s_h$ of a switch statement
 
 \begin{dartCode}
@@ -9634,7 +9834,7 @@
 
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 Execute $\{s_h\}$.
 If this execution completes normally,
 and if $s_h$ is not the statements of the last case of the switch
@@ -9662,17 +9862,17 @@
 \subsection{Rethrow}
 \LMLabel{rethrow}
 
-\LMHash{}
-The {\em rethrow statement} is used to re-throw an exception and its associated stack trace.
+\LMHash{}%
+The \Index{rethrow statement} is used to re-throw an exception and its associated stack trace.
 
 \begin{grammar}
 <rethrowStatement> ::= \RETHROW{} `;'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Execution of a \code{\RETHROW{}} statement proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 Let $f$ be the immediately enclosing function, and let \code{\ON{} $T$ \CATCH{} ($p_1$, $p_2$)} be the immediately enclosing catch clause (\ref{try}).
 
 \rationale{
@@ -9680,17 +9880,17 @@
 So we can assume that the \RETHROW{} is enclosed in a \CATCH{} clause of that form.
 }
 
-\LMHash{}
-The \RETHROW{} statement {\em throws} (\ref{completion}) with $p_1$ as the exception object and $p_2$ as the stack trace.
+\LMHash{}%
+The \RETHROW{} statement throws (\ref{completion}) with $p_1$ as the exception object and $p_2$ as the stack trace.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a \code{\RETHROW{}} statement is not enclosed within an \ON-\CATCH{} clause.
 
 
 \subsection{Try}
 \LMLabel{try}
 
-\LMHash{}
+\LMHash{}%
 The try statement supports the definition of exception handling code in a structured way.
 
 \begin{grammar}
@@ -9704,7 +9904,7 @@
 <finallyPart> ::= \FINALLY{} <block>
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 A try statement consists of a block statement, followed by at least one of:
 \begin{enumerate}
 \item
@@ -9718,26 +9918,26 @@
 The \ON{} clause can be omitted, leaving what looks like a Javascript catch clause.
 }
 
-\LMHash{}
+\LMHash{}%
 A try statement of the form \code{\TRY{} $s_1$ $on-catch_1 \ldots on-catch_n$;} is equivalent to the statement \code{\TRY{} $s_1$ $on-catch_1 \ldots on-catch_n$ \FINALLY{} $\{\}$}.
 
-\LMHash{}
+\LMHash{}%
 An \ON{}-\CATCH{} clause of the form \code{\ON{} $T$ \CATCH{} ($p_1$) $s$} is equivalent to an \ON{}-\CATCH{} clause \code{\ON{} $T$ \CATCH{} ($p_1$, $p_2$) $s$} where $p_2$ is a fresh identifier.
 
-\LMHash{}
+\LMHash{}%
 An \ON{}-\CATCH{} clause of the form \code{\ON{} $T$ $s$} is equivalent to an \ON{}-\CATCH{} clause \code{\ON{} $T$ \CATCH{} ($p_1$, $p_2$) $s$} where $p_1$ and $p_2$ are fresh identifiers.
 
-\LMHash{}
+\LMHash{}%
 An \ON{}-\CATCH{} clause of the form \code{\CATCH{} ($p$) $s$} is equivalent to an \ON{}-\CATCH{} clause \code{\ON{} \DYNAMIC{} \CATCH{} ($p$, $p_2$) $s$} where $p_2$ is a fresh identifier.
 
 An \ON{}-\CATCH{} clause of the form \code{\CATCH{} ($p_1$, $p_2$) $s$} is equivalent to an \ON{}-\CATCH{} clause \code{\ON{} \DYNAMIC{} \CATCH{} ($p_1$, $p_2$) $s$}.
 
-\LMHash{}
+\LMHash{}%
 An \ON{}-\CATCH{} clause of the form \code{\ON{} $T$ \CATCH{} ($p_1$, $p_2$) $s$} introduces a new scope $CS$ in which final local variables specified by $p_1$ and $p_2$ are defined.
 The statement $s$ is enclosed within $CS$.
 The static type of $p_1$ is $T$ and the static type of $p_2$ is \code{StackTrace}.
 
-\LMHash{}
+\LMHash{}%
 Execution of a \TRY{} statement $s$ of the form:
 
 \begin{dartCode}
@@ -9749,7 +9949,7 @@
 \end{dartCode}
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 First $b$ is executed.
 If execution of $b$ throws (\ref{completion}) with exception object $e$ and stack trace $t$, then $e$ and $t$ are matched against the \ON{}-\CATCH{} clauses to yield a new completion (\ref{on-catch}).
 
@@ -9760,7 +9960,7 @@
 Otherwise if execution of $b$ threw (\ref{completion}), the \TRY{} statement completes in the same way as the matching against the \ON{}-\CATCH{} clauses.
 Otherwise the \TRY{} statement completes in the same way as the execution of $b$.
 
-\LMHash{}
+\LMHash{}%
 If $T_1$ is a malformed or deferred type (\ref{staticTypes}), then performing a match causes a run-time error.
 It is a compile-time error if $T_i$, $1 \le i \le n$ is a deferred or malformed type.
 
@@ -9768,7 +9968,7 @@
 \subsubsection{\ON{}-\CATCH{} clauses}
 \LMLabel{on-catch}
 
-\LMHash{}
+\LMHash{}%
 Matching an exception object $e$ and stack trace $t$ against a (potentially empty) sequence of \ON{}-\CATCH{} clauses of the form
 
 \begin{dartCode}
@@ -9778,17 +9978,17 @@
 \end{dartCode}
 proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 If there are no \ON{}-\CATCH{} clauses ($n = 0$), matching throws the exception object $e$ and stack trace $t$ (\ref{completion}).
 
-\LMHash{}
+\LMHash{}%
 Otherwise the exception is matched against the first clause.
 
-\LMHash{}
+\LMHash{}%
 Otherwise, if the type of $e$ is a subtype of $T_1$, then the first clause matches, and then $e_1$ is bound to the exception object $e$ and $t_1$ is bound to the stack trace $t$, and $s_1$ is executed in this scope.
 The matching completes in the same way as this execution.
 
-\LMHash{}
+\LMHash{}%
 Otherwise, if the first clause did not match $e$, $e$ and $t$ are recursively matched against the remaining \ON{}-\CATCH{} clauses:
 
 \begin{dartCode}
@@ -9801,8 +10001,8 @@
 \subsection{Return}
 \LMLabel{return}
 
-\LMHash{}
-The {\em return statement} returns a result to the caller of a synchronous function,
+\LMHash{}%
+The \Index{return statement} returns a result to the caller of a synchronous function,
 completes the future associated with an asynchronous function,
 or terminates the stream or iterable associated with a generator (\ref{functions}).
 
@@ -9810,17 +10010,17 @@
 <returnStatement> ::= \RETURN{} <expression>? `;'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Consider a return statement of the form \code{\RETURN{} $e$;}.
 Let $T$ be the static type of $e$, let $f$ be the immediately enclosing function,
 and let $S$ be the declared return type of $f$.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the body of $f$ is marked \ASYNC{}
 and the type \code{Future<\flatten{T}>} (\ref{functionExpressions}) may not be assigned to $S$.
 Otherwise, it is a compile-time error if $T$ may not be assigned to $S$.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a return statement of the form \code{\RETURN{} $e$;} appears in a generative constructor (\ref{generativeConstructors}).
 
 \rationale{
@@ -9830,16 +10030,16 @@
 There is no real downside to it, as returning a value from a generative constructor is meaningless.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a return statement of the form \code{\RETURN{} $e$;} appears in a generator function.
 
 \rationale{
 In the case of a generator function, the value returned by the function is the iterable or stream associated with it, and individual elements are added to that iterable using yield statements, and so returning a value makes no sense.
 }
 
-\LMHash{}
+\LMHash{}%
 Let $f$ be the function immediately enclosing a return statement of the form \code{\RETURN{};}.
-It is a compile-time warning if $f$ is neither a generator nor a generative constructor and either:
+It is a static warning if $f$ is neither a generator nor a generative constructor and either:
 \begin{itemize}
 %% TODO(eernst): Integrating generalized-void.md, "may not be assigned
 %% to void" is useless. Update, also considering invalid_returns.md.
@@ -9849,7 +10049,7 @@
 \end{itemize}
 
 \commentary{
-Hence, a compile-time warning will not be raised if $f$ has no declared return type,
+Hence, a static warning will not be raised if $f$ has no declared return type,
 %% TODO(eernst): Update when integrating generalized-void.md!
 since the return type would be \DYNAMIC{} and \DYNAMIC{} may be assigned to \VOID{} and to \code{Future<Null>}.
 However, any synchronous non-generator function that declares a return type must return an expression explicitly.
@@ -9867,10 +10067,10 @@
 Leaving the return type of a function marked \ASYNC{} blank will be interpreted as \DYNAMIC{} as always, and cause no type error.
 }
 
-\LMHash{}
+\LMHash{}%
 Executing a return statement \code{\RETURN{} $e$;} proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 First the expression $e$ is evaluated, producing an object $o$.
 Let $T$ be the run-time type of $o$ and
 let $S$ be the actual return type of $f$
@@ -9910,7 +10110,7 @@
 %% that we can have this dynamic variation at a location in the code
 %% where there is no static justification for expecting a future.
 
-\LMHash{}
+\LMHash{}%
 Let $U$ be the run-time type of $r$.
 \begin{itemize}
 \item If the body of $f$ is marked \ASYNC{} (\ref{functions})
@@ -9925,17 +10125,17 @@
 and $U$ is not a subtype of $S$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Executing a return statement with no expression, \code{\RETURN;} returns with no value (\ref{completion}).
 
 
 \subsection{Labels}
 \LMLabel{labels}
 
-\LMHash{}
-A {\em label} is an identifier followed by a colon.
-A {\em labeled statement} is a statement prefixed by a label $L$.
-A {\em labeled case clause} is a case clause within a switch statement (\ref{switch}) prefixed by a label $L$.
+\LMHash{}%
+A \Index{label} is an identifier followed by a colon.
+A \Index{labeled statement} is a statement prefixed by a label $L$.
+A \Index{labeled case clause} is a case clause within a switch statement (\ref{switch}) prefixed by a label $L$.
 
 \rationale{
 The sole role of labels is to provide targets for the break (\ref{break}) and continue (\ref{continue}) statements.
@@ -9945,16 +10145,16 @@
 <label> ::= <identifier> `:'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Execution a labeled statement $s$, $label: s_l$, consists of executing $s_l$.
 If execution of $s_l$ breaks to the label $label$ (\ref{completion}),
 then execution of $s$ completes normally,
 otherwise execution of $s$ completes in the same ways as the execution of $s_l$.
 
-\LMHash{}
+\LMHash{}%
 The namespace of labels is distinct from the one used for types, functions and variables.
 
-\LMHash{}
+\LMHash{}%
 The scope of a label that labels a statement $s$ is $s$.
 The scope of a label that labels a case clause of a switch statement $s$ is $s$.
 
@@ -9967,14 +10167,14 @@
 \subsection{Break}
 \LMLabel{break}
 
-\LMHash{}
-The {\em break statement} consists of the reserved word \BREAK{} and an optional label (\ref{labels}).
+\LMHash{}%
+The \Index{break statement} consists of the reserved word \BREAK{} and an optional label (\ref{labels}).
 
 \begin{grammar}
 <breakStatement> ::= \BREAK{} <identifier>? `;'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Let $s_b$ be a \BREAK{} statement.
 If $s_b$ is of the form \code{\BREAK{} $L$;},
 then it is a compile-time error if $s_b$ is not enclosed in a labeled statement
@@ -9985,7 +10185,7 @@
 \DO{} (\ref{do}), \FOR{} (\ref{for}), \SWITCH{} (\ref{switch})
 or \WHILE{} (\ref{while}) statement within the innermost function in which $s_b$ occurs.
 
-\LMHash{}
+\LMHash{}%
 Execution of a \BREAK{} statement \code{\BREAK{} $L$;} breaks to the label $L$ (\ref{completion}).
 Execution of a \BREAK{} statement \code{\BREAK{};} breaks without a label (\ref{completion}).
 
@@ -9993,14 +10193,14 @@
 \subsection{Continue}
 \LMLabel{continue}
 
-\LMHash{}
-The {\em continue statement} consists of the reserved word \CONTINUE{} and an optional label (\ref{labels}).
+\LMHash{}%
+The \Index{continue statement} consists of the reserved word \CONTINUE{} and an optional label (\ref{labels}).
 
 \begin{grammar}
 <continueStatement> ::= \CONTINUE{} <identifier>? `;'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Let $s_c$ be a \CONTINUE{} statement.
 If $s_c$ is of the form \code{\CONTINUE{} $L$;},
 then it is a compile-time error if $s_c$ is not enclosed in either an
@@ -10014,7 +10214,7 @@
 \DO{} (\ref{do}), \FOR{} (\ref{for}), or \WHILE{} (\ref{while}) statement
 within the innermost function in which $s_c$ occurs.
 
-\LMHash{}
+\LMHash{}%
 Execution of a \CONTINUE{} statement \code{\CONTINUE{} $L$;} continues to the label $L$ (\ref{completion}).
 Execution of a \CONTINUE{} statement \code{\CONTINUE{};} continues without a label (\ref{completion}).
 
@@ -10026,24 +10226,24 @@
 \subsubsection{Yield}
 \LMLabel{yield}
 
-\LMHash{}
-The {\em yield statement} adds an element to the result of a generator function (\ref{functions}).
+\LMHash{}%
+The \Index{yield statement} adds an element to the result of a generator function (\ref{functions}).
 
 \begin{grammar}
 <yieldStatement> ::= \YIELD{} <expression> `;'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Execution of a statement $s$ of the form \code{\YIELD{} $e$;} proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 First, the expression $e$ is evaluated to an object $o$.
 If the enclosing function $m$ is marked \code{\ASYNC*} (\ref{functions}) and the stream $u$ associated with $m$ has been paused, then the nearest enclosing asynchronous for loop (\ref{asynchronousFor-in}), if any, is paused and execution of $m$ is suspended until $u$ is resumed or canceled.
 
-\LMHash{}
+\LMHash{}%
 Next, $o$ is added to the iterable or stream associated with the immediately enclosing function.
 
-\LMHash{}
+\LMHash{}%
 If the enclosing function $m$ is marked \code{\ASYNC*} and the stream $u$ associated with $m$ has been canceled, then the \YIELD{} statement returns without a value (\ref{completion}), otherwise it completes normally.
 
 \rationale{
@@ -10052,7 +10252,7 @@
 At this point, the only plausible action for the generator is to clean up after itself via its \FINALLY{} clauses.
 }
 
-\LMHash{}
+\LMHash{}%
 Otherwise, if the enclosing function $m$ is marked \code{\ASYNC*} (\ref{functions}) then the enclosing function may suspend, in which case the nearest enclosing asynchronous for loop (\ref{asynchronousFor-in}), if any, is paused first.
 
 \rationale{
@@ -10065,7 +10265,7 @@
 The only requirement is that consumers are not blocked indefinitely.
 }
 
-\LMHash{}
+\LMHash{}%
 If the enclosing function $m$ is marked \code{\SYNC*} (\ref{functions}) then:
 \begin{itemize}
 \item
@@ -10074,10 +10274,10 @@
 The current call to \code{moveNext()} returns \TRUE.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a yield statement appears in a function that is not a generator function.
 
-\LMHash{}
+\LMHash{}%
 Let $T$ be the static type of $e$ and let $f$ be the immediately enclosing function.
 It is a compile-time error if either:
 \begin{itemize}
@@ -10091,20 +10291,20 @@
 \subsubsection{Yield-Each}
 \LMLabel{yieldEach}
 
-\LMHash{}
-The {\em yield-each statement} adds a series of values to the result of a generator function (\ref{functions}).
+\LMHash{}%
+The \Index{yield-each statement} adds a series of values to the result of a generator function (\ref{functions}).
 
 \begin{grammar}
 <yieldEachStatement> ::= \YIELD{} `*' <expression> `;'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Execution of a statement $s$ of the form \code{\YIELD* $e$;} proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 First, the expression $e$ is evaluated to an object $o$.
 
-\LMHash{}
+\LMHash{}%
 If the immediately enclosing function $m$ is marked \code{\SYNC*} (\ref{functions}), then:
 \begin{enumerate}
 \item It is a dynamic type error if the class of $o$ does not implement \code{Iterable}.
@@ -10121,7 +10321,7 @@
 The current call to \code{moveNext()} returns \TRUE.
 \end{enumerate}
 
-\LMHash{}
+\LMHash{}%
 If $m$ is marked \code{\ASYNC*} (\ref{functions}), then:
 \begin{itemize}
 \item It is a dynamic type error if the class of $o$ does not implement \code{Stream}.
@@ -10142,10 +10342,10 @@
 \item If the stream $o$ is done, execution of $s$ completes normally.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a yield-each statement appears in a function that is not a generator function.
 
-\LMHash{}
+\LMHash{}%
 Let $T$ be the static type of $e$ and let $f$ be the immediately enclosing function.
 It is a compile-time error if $T$ may not be assigned to the declared return type of $f$.
 If $f$ is synchronous it is a compile-time error if $T$ may not be assigned to \code{Iterable}.
@@ -10155,8 +10355,8 @@
 \subsection{Assert}
 \LMLabel{assert}
 
-\LMHash{}
-An {\em assert statement} is used to disrupt normal execution if a given boolean condition does not hold.
+\LMHash{}%
+An \Index{assert statement} is used to disrupt normal execution if a given boolean condition does not hold.
 
 \begin{grammar}
 <assertStatement> ::= <assertion> `;'
@@ -10164,20 +10364,20 @@
 <assertion> ::= \ASSERT{} `(' <expression> (`,' <expression> )? `,'? `)'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 The grammar allows a trailing comma before the closing parenthesis,
 similarly to an argument list.
 That comma, if present, has no effect.
 An assertion with a trailing comma is equivalent to one with that comma removed.
 
-\LMHash{}
+\LMHash{}%
 An assertion of the form \code{\ASSERT($e$)} is equivalent to an assertion of the form \code{\ASSERT($e$, \NULL{})}.
 
-\LMHash{}
+\LMHash{}%
 Execution of an assert statement executes the assertion as described below
 and completes in the same way as the assertion.
 
-\LMHash{}
+\LMHash{}%
 When assertions are not enabled,
 execution of an assertion immediately completes normally
 (\ref{completion}).
@@ -10185,7 +10385,7 @@
 When assertions are enabled,
 execution of an assertion \code{\ASSERT{}($c$, $e$)} proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 The expression $c$ is evaluated to an object $r$.
 It is a dynamic type error if $r$ is not of type \code{bool}.
 \commentary{
@@ -10195,7 +10395,7 @@
 Otherwise, $e$ is evaluated to an object $m$
 and then the execution of the assert statement throws (\ref{completion}) an \code{AssertionError} containing $m$ and with a stack trace corresponding to the current execution state at the assertion.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the type of $c$ may not be assigned to \code{bool}.
 
 \rationale{
@@ -10231,11 +10431,11 @@
 \section{Libraries and Scripts}
 \LMLabel{librariesAndScripts}
 
-\LMHash{}
-A Dart program consists of one or more libraries, and may be built out of one or more {\em compilation units}.
+\LMHash{}%
+A Dart program consists of one or more libraries, and may be built out of one or more \Index{compilation units}.
 A compilation unit may be a library or a part (\ref{parts}).
 
-\LMHash{}
+\LMHash{}%
 A library consists of (a possibly empty) set of imports, a set of exports, and a set of top-level declarations.
 A top-level declaration is either a class (\ref{classes}), a type alias declaration (\ref{typedef}), a function (\ref{functions}) or a variable declaration (\ref{variables}).
 The members of a library $L$ are those top level declarations given within $L$.
@@ -10256,7 +10456,8 @@
 <getOrSet> ::= \GET{}
   \alt \SET{}
 
-<libraryDefinition> ::= <scriptTag>? <libraryName>? <importOrExport>* <partDirective>*
+<libraryDefinition> ::= \gnewline{}
+  <scriptTag>? <libraryName>? <importOrExport>* <partDirective>*
   \gnewline{} <topLevelDefinition>*
 
 <scriptTag> ::= `#!' (\~{}<NEWLINE>)* <NEWLINE>
@@ -10269,16 +10470,16 @@
 <dottedIdentifierList> ::= <identifier> (`.' <identifier>)*
 \end{grammar}
 
-\LMHash{}
-Libraries may be {\em explicitly named} or {\em implicitly named}.
-An explicitly named library begins with the word \LIBRARY{} (possibly prefaced with any applicable metadata annotations), followed by a qualified identifier that gives the name of the library.
+\LMHash{}%
+Libraries may be explicitly named or implicitly named.
+An \Index{explicitly named library} begins with the word \LIBRARY{} (possibly prefaced with any applicable metadata annotations), followed by a qualified identifier that gives the name of the library.
 
 \commentary{
 Technically, each dot and identifier is a separate token and so spaces between them are acceptable.
 However, the actual library name is the concatenation of the simple identifiers and dots and contains no spaces.
 }
 
-\LMHash{}
+\LMHash{}%
 An implicitly named library has the empty string as its name.
 
 \rationale{
@@ -10292,15 +10493,15 @@
 Each pub package is guaranteed a unique name, effectively enforcing a global namespace.
 }
 
-\LMHash{}
-A library may optionally begin with a {\em script tag}.
+\LMHash{}%
+A library may optionally begin with a \Index{script tag}.
 Script tags are intended for use with scripts (\ref{scripts}).
 A script tag can be used to identify the interpreter of the script to whatever computing environment the script is embedded in.
 The script tag must appear before any whitespace or comments.
 A script tag begins with \syntax{`#!'} and ends at the end of the line.
 Any characters that follow \syntax{`#!'} in the script tag are ignored by the Dart implementation.
 
-\LMHash{}
+\LMHash{}%
 Libraries are units of privacy.
 A private declaration declared within a library $L$ can only be accessed by code within $L$.
 Any attempt to access a private member declaration from outside $L$ will cause a method, getter or setter lookup failure.
@@ -10309,20 +10510,21 @@
 Since top level privates are not imported, using the top level privates of another library is never possible.
 }
 
-\LMHash{}
-The {\em public namespace} of library $L$ is the mapping that maps the simple name of each public top-level member $m$ of $L$ to $m$.
+\LMHash{}%
+The \Index{public namespace} of library $L$ is the mapping that maps the simple name of each public top-level member $m$ of $L$ to $m$.
 The scope of a library $L$ consists of the names introduced by all top-level declarations declared in $L$, and the names added by $L$'s imports (\ref{imports}).
 
 
 \subsection{Imports}
 \LMLabel{imports}
 
-\LMHash{}
-An {\em import} specifies a library to be used in the scope of another library.
+\LMHash{}%
+An \Index{import} specifies a library to be used in the scope of another library.
 \begin{grammar}
 <libraryImport> ::= <metadata> <importSpecification>
 
-<importSpecification> ::= \IMPORT{} <configurableUri> (\AS{} <identifier>)? <combinator>* `;'
+<importSpecification> ::= \gnewline{}
+  \IMPORT{} <configurableUri> (\AS{} <identifier>)? <combinator>* `;'
   \alt \IMPORT{} <uri> \DEFERRED{} \AS{} <identifier> <combinator>* `;'
 
 <combinator> ::= \SHOW{} <identifierList>
@@ -10331,19 +10533,21 @@
 <identifierList> ::= <identifier> (, <identifier>)*
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 An import specifies a URI $x$ where the declaration of an imported library is to be found.
 
-\LMHash{}
-Imports may be {\em deferred} or {\em immediate}.
+\LMHash{}%
+Imports may be
+\IndexCustom{deferred}{import!deferred} or
+\IndexCustom{immediate}{import!immediate}.
 A deferred import is distinguished by the appearance of the built-in identifier \DEFERRED{} after the URI.
 Any import that is not deferred is immediate.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the specified URI of an immediate import does not refer to a library declaration.
 The interpretation of URIs is described in section \ref{uris} below.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the specified URI of a deferred import does not refer to a library declaration.
 
 \rationale{
@@ -10351,26 +10555,28 @@
 However the development environment should detect the problem.
 }
 
-\LMHash{}
-The {\em current library} is the library currently being compiled.
+\LMHash{}%
+The \Index{current library} is the library currently being compiled.
 The import modifies the namespace of the current library in a manner that is determined by the imported library and by the optional elements of the import.
 
-\LMHash{}
+\LMHash{}%
 An immediate import directive $I$ may optionally include a prefix clause of the form \code{\AS{} \id} used to prefix names imported by $I$.
 A deferred import must include a prefix clause or a compile-time error occurs.
 It is a compile-time error if a prefix used in a deferred import is used in another import clause.
 
-\LMHash{}
+\LMHash{}%
 An import directive $I$ may optionally include a namespace combinator clauses used to restrict the set of names imported by $I$.
 Currently, two namespace combinators are supported: \HIDE{} and \SHOW{}.
 
-\LMHash{}
+\LMHash{}%
 Let $I$ be an import directive that refers to a URI via the string $s_1$.
 Evaluation of $I$ proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 If $I$ is a deferred import, no evaluation takes place.
-Instead, a mapping of the name of the prefix, $p$ to a {\em deferred prefix object} is added to the scope of the current library $L$.
+Instead, a mapping of the name of the prefix, $p$ to a
+\Index{deferred prefix object} is added to
+the scope of the current library $L$.
 The deferred prefix object has the following methods:
 
 \begin{itemize}
@@ -10397,13 +10603,13 @@
 
 The static type of the prefix object $p$ is a unique interface type that has those members whose names and signatures are listed above.
 
-\LMHash{}
+\LMHash{}%
 After a call succeeds, the name $p$ is mapped to a non-deferred prefix object as described below.
 In addition, the prefix object also supports the \code{loadLibrary} method, and so it is possible to call \code{loadLibrary} again.
 If a call fails, nothing happens, and one again has the option to call \code{loadLibrary} again.
 Whether a repeated call to \code{loadLibrary} succeeds will vary as described below.
 
-\LMHash{}
+\LMHash{}%
 The effect of a repeated call to \code{$p$.loadLibrary} is as follows:
 \begin{itemize}
 \item
@@ -10425,7 +10631,7 @@
 We do not specify what value the future returned resolves to.
 }
 
-\LMHash{}
+\LMHash{}%
 If $I$ is an immediate import then, first
 
 \begin{itemize}
@@ -10437,7 +10643,7 @@
 \item Otherwise, the contents of the URI denoted by $s_1$ have been compiled into a library $B$ within the current isolate.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Let $NS_0$ be the exported namespace (\ref{exports}) of $B$.
 Then, for each combinator clause $C_i, i \in 1 .. n$ in $I$:
 \begin{itemize}
@@ -10460,8 +10666,8 @@
 where $hide(l, n)$ takes a list of identifiers $l$ and a namespace $n$, and produces a namespace that is identical to $n$ except that for each name $k$ in $l$, $k$ and \code{$k$=} are undefined.
 \end{itemize}
 
-\LMHash{}
-Next, if $I$ includes a prefix clause of the form \AS{} $p$, let $NS = NS_n \cup \{p: prefixObject(NS_n)\}$ where $prefixObject(NS_n)$ is a {\em prefix object} for the namespace $NS_n$, which is an object that has the following members:
+\LMHash{}%
+Next, if $I$ includes a prefix clause of the form \AS{} $p$, let $NS = NS_n \cup \{p: prefixObject(NS_n)\}$ where $prefixObject(NS_n)$ is a \Index{prefix object} for the namespace $NS_n$, which is an object that has the following members:
 
 \begin{itemize}
 \item For every top level function $f$ named \id{} in $NS_n$, a corresponding method with the same name and signature as $f$ that forwards (\ref{functionDeclarations}) to $f$.
@@ -10470,7 +10676,7 @@
 \item For every type $T$ named \id{} in $NS_n$, a corresponding getter named \id{} with return type \code{Type}, that, when invoked, returns the type object for $T$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Otherwise, let $NS = NS_n$.
 It is a compile-time error if the current library declares a top-level member named $p$.
 
@@ -10480,7 +10686,7 @@
 % This is problematic, because it implies that p.T would be available even in a scope that declared p. We really need to think of p as a single object with properties p.T etc., except it isn't really that
 % either. After all, p isn't actually available as a stand alone name.
 
-\LMHash{}
+\LMHash{}%
 Then, for each entry mapping key $k$ to declaration $d$ in $NS$, $d$ is made available in the top level scope of $L$ under the name $k$ unless either:
 \begin{itemize}
 \item
@@ -10492,9 +10698,9 @@
 The greatly increases the chance that a member can be added to a library without breaking its importers.
 }
 
-\LMHash{}
-A {\em system library} is a library that is part of the Dart implementation.
-Any other library is a {\em non-system library}.
+\LMHash{}%
+A \Index{system library} is a library that is part of the Dart implementation.
+Any other library is a \Index{non-system library}.
 
 If a name $N$ is referenced by a library $L$
 and $N$ would be introduced into the top level scope of $L$
@@ -10513,13 +10719,14 @@
 It is recommended that tools that deploy Dart code produce output in which all imports use show clauses to ensure that additions to the namespace of a library never impact deployed code.
 }
 
-\LMHash{}
+\LMHash{}%
 If a name $N$ is referenced by a library $L$ and $N$ is introduced into the top level scope of $L$ by more than one import
 and not all the imports denote the same declaration,
 a compile-time error occurs.
 
-\LMHash{}
-We say that the namespace $NS$ {\em has been imported into} $L$.
+\LMHash{}%
+We say that the namespace $NS$
+\IndexCustom{has been imported into}{namespace!imported} $L$.
 
 \commentary{
 It is not an error if $N$ is introduced by two or more imports but never referred to.
@@ -10538,8 +10745,8 @@
 %On a related note, the provenance of the conflicting elements is not considered. An element that is imported via distinct paths may conflict with itself. This avoids variants of the well known "diamond" problem.
 }
 
-\LMHash{}
-It is a compile-time warning to import two different libraries with the same name unless their name is the empty string.
+\LMHash{}%
+It is a static warning to import two different libraries with the same name unless their name is the empty string.
 
 \commentary{
 A widely disseminated library should be given a name that will not conflict with other such libraries.
@@ -10553,7 +10760,7 @@
 This prevents situations where removing a name from a library would cause breakage of a client library.
 }
 
-\LMHash{}
+\LMHash{}%
 The dart core library \code{dart:core} is implicitly imported into every dart library other than itself via an import clause of the form
 
 \code{\IMPORT{} `dart:core';}
@@ -10576,31 +10783,38 @@
 \subsection{Exports}
 \LMLabel{exports}
 
-\LMHash{}
+\LMHash{}%
 A library $L$ exports a namespace (\ref{scoping}), meaning that the declarations in the namespace are made available to other libraries if they choose to import $L$ (\ref{imports}).
-The namespace that $L$ exports is known as its {\em exported namespace}.
+The namespace that $L$ exports is known as its
+\IndexCustom{exported namespace}{namespace!exported}.
 
 \begin{grammar}
 <libraryExport> ::= <metadata> \EXPORT{} <configurableUri> <combinator>* `;'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 An export specifies a URI $x$ where the declaration of an exported library is to be found.
 It is a compile-time error if the specified URI does not refer to a library declaration.
 
-\LMHash{}
-We say that a name {\em is exported by a library} (or equivalently, that a library {\em exports a name}) if the name is in the library's exported namespace.
-We say that a declaration {\em is exported by a library} (or equivalently, that a library {\em exports a declaration}) if the declaration is in the library's exported namespace.
+\LMHash{}%
+We say that a name is \Index{exported by a library}
+(or equivalently, that a library
+\IndexCustom{exports a name}{exports!name})
+if the name is in the library's exported namespace.
+We say that a declaration \Index{is exported by a library}
+(or equivalently, that a library
+\IndexCustom{exports a declaration}{exports!declaration})
+if the declaration is in the library's exported namespace.
 
-\LMHash{}
+\LMHash{}%
 A library always exports all names and all declarations in its public namespace.
-In addition, a library may choose to re-export additional libraries via {\em export directives}, often referred to simply as {\em exports}.
+In addition, a library may choose to re-export additional libraries via \Index{export directives}, often referred to simply as \Index{exports}.
 
-\LMHash{}
+\LMHash{}%
 Let $E$ be an export directive that refers to a URI via the string $s_1$.
 Evaluation of $E$ proceeds as follows:
 
-\LMHash{}
+\LMHash{}%
 First,
 
 \begin{itemize}
@@ -10609,7 +10823,7 @@
 \item Otherwise, the contents of the URI denoted by $s_1$ have been compiled into a library $B$ within the current isolate.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Let $NS_0$ be the exported namespace of $B$.
 Then, for each combinator clause $C_i, i \in 1 .. n$ in $E$:
 \begin{itemize}
@@ -10621,11 +10835,11 @@
 then let $NS_i = \HIDE{}([\id_1, \ldots,\ \id_k], NS_{i-1}$).
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 For each
 entry mapping key $k$ to declaration $d$ in $NS_n$ an entry mapping $k$ to $d$ is added to the exported namespace of $L$ unless a top-level declaration with the name $k$ exists in $L$.
 
-\LMHash{}
+\LMHash{}%
 If a name $N$ is not declared by a library $L$
 and $N$ would be introduced into the exported namespace of $L$
 by exports of two libraries, $L_1$ and $L_2$,
@@ -10638,11 +10852,14 @@
 See the discussion in section \ref{imports} for the reasoning behind this rule.
 }
 
-\LMHash{}
-We say that $L$ {\em re-exports library } $B$, and also that $L$ {\em re-exports namespace } $NS_n$.
-When no confusion can arise, we may simply state that $L$ {\em re-exports }$B$, or that $L$ {\em re-exports }$NS_n$.
+\LMHash{}%
+We say that $L$ \Index{re-exports library} $B$, and also
+that $L$ \Index{re-exports namespace} $NS_n$.
+When no confusion can arise, we may simply state
+that $L$ \NoIndex{re-exports} $B$, or
+that $L$ \NoIndex{re-exports} $NS_n$.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a name $N$ is re-exported by a library $L$ and $N$ is introduced into the export namespace of $L$ by more than one export, unless all exports refer to same declaration for the name $N$.
 It is a compile-time error to export two different libraries with the same name unless their name is the empty string.
 
@@ -10650,12 +10867,12 @@
 \subsection{Parts}
 \LMLabel{parts}
 
-\LMHash{}
-A library may be divided into {\em parts}, each of which can be stored in a separate location.
+\LMHash{}%
+A library may be divided into \Index{parts}, each of which can be stored in a separate location.
 A library identifies its parts by listing them via \PART{} directives.
 
-\LMHash{}
-A {\em part directive} specifies a URI where a Dart compilation unit that should be incorporated into the current library may be found.
+\LMHash{}%
+A \Index{part directive} specifies a URI where a Dart compilation unit that should be incorporated into the current library may be found.
 
 \begin{grammar}
 <partDirective> ::= <metadata> \PART{} <uri> `;'
@@ -10665,29 +10882,29 @@
 <partDeclaration> ::= <partHeader> <topLevelDefinition>* <EOF>
 \end{grammar}
 
-\LMHash{}
-A {\em part header} begins with \PART{} \OF{} followed by the name of the library the part belongs to.
+\LMHash{}%
+A \Index{part header} begins with \PART{} \OF{} followed by the name of the library the part belongs to.
 A part declaration consists of a part header followed by a sequence of top-level declarations.
 
-\LMHash{}
+\LMHash{}%
 Compiling a part directive of the form \code{\PART{} $s$;} causes the Dart system to attempt to compile the contents of the URI that is the value of $s$.
 The top-level declarations at that URI are then compiled by the Dart compiler in the scope of the current library.
 It is a compile-time error if the contents of the URI are not a valid part declaration.
 It is a compile-time error if the referenced part declaration $p$ names a library other than the current library as the library to which $p$ belongs.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a library contains
 two part directives with the same URI.
 
-\LMHash{}
-We say that a library $L_1$ is {\em reachable from} a library $L$ if
+\LMHash{}%
+We say that a library $L_1$ is \Index{reachable from} a library $L$ if
 any of the following is true (\ref{imports}, \ref{exports}):
 \begin{itemize}
 \item $L$ and $L_1$ is the same library.
 \item $L$ imports or exports a library $L_2$, and $L_1$ is reachable from $L_2$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Let $L$ be a library, let $u$ be a URI,
 and let $L_1$ and $L_2$ be distinct libraries which are reachable from $L$.
 It is a compile-time error if $L_1$ and $L_2$ both contain
@@ -10706,14 +10923,14 @@
 \subsection{Scripts}
 \LMLabel{scripts}
 
-\LMHash{}
-A {\em script} is a library whose exported namespace (\ref{exports}) includes
+\LMHash{}%
+A \Index{script} is a library whose exported namespace (\ref{exports}) includes
 a top-level function declaration named \code{main}
 that has either zero, one or two required arguments.
 
 A script $S$ is executed as follows:
 
-\LMHash{}
+\LMHash{}%
 First, $S$ is compiled as a library as specified above.
 Then, the top-level function defined by \code{main}
 in the exported namespace of $S$ is invoked (\ref{functionInvocation})
@@ -10742,7 +10959,7 @@
 A Dart program will typically be executed by executing a script.
 }
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if a library's export scope contains a declaration
 named \code{main}, and the library is not a script.
 \commentary{This restriction ensures that all top-level \code{main} declarations
@@ -10757,7 +10974,7 @@
 \subsection{URIs}
 \LMLabel{uris}
 
-\LMHash{}
+\LMHash{}%
 URIs are specified by means of string literals:
 
 \begin{grammar}
@@ -10770,13 +10987,16 @@
 <uriTest> ::= <dottedIdentifierList> (`==' <stringLiteral>)?
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if the string literal $x$ that describes a URI contains a string interpolation.
 
-\LMHash{}
-It is a compile-time error if the string literal $x$ that is used in a {\em uriTest} is not a constant expression, or if $x$ involves string interpolation.
+\LMHash{}%
+It is a compile-time error if the string literal $x$ that is used in a \synt{uriTest} is not a constant expression, or if $x$ involves string interpolation.
 
-\LMHash{} A {\em configurable URI} $c$ of the form \code{\metavar{uri} $\metavar{configurationUri}_1$ \ldots $\metavar{configurationUri}_n$} {\em specifies a URI} as follows:
+\LMHash{}%
+A \Index{configurable URI} $c$ of the form
+\code{\metavar{uri} $\metavar{configurationUri}_1$ \ldots $\metavar{configurationUri}_n$}
+\IndexCustom{specifies a URI}{specify a URI} as follows:
 \begin{itemize}
 \item{} Let $u$ be \metavar{uri}.
 \item{} For each of the following configuration URIs of the form \code{\IF{} ($\metavar{test}_i$) $\metavar{uri}_i$}, in source order, do the following.
@@ -10787,7 +11007,8 @@
   then create a string, \metavar{key}, from \metavar{ids}
   by concatenating the identfiers and dots,
   omitting any spaces between them that may occur in the source.
-  \item{} Look up \metavar{key} in the available compilation {\em environment}.
+  \item{} Look up \metavar{key} in the available
+  \Index{compilation environment}.
   \commentary{
   The compilation environment is provided by the platform.
   It maps some string keys to string values,
@@ -10805,7 +11026,7 @@
 \item{} The URI specified by $c$ is $u$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 This specification does not discuss the interpretation of URIs, with the following exceptions.
 
 \rationale{
@@ -10814,17 +11035,17 @@
 While it might seem attractive to specify, say, that URIs are interpreted with respect to a standard such as IETF RFC 3986, in practice this will usually depend on the browser and cannot be relied upon.
 }
 
-\LMHash{}
+\LMHash{}%
 A URI of the form \code{dart:$s$} is interpreted as a reference to a system library (\ref{imports}) $s$.
 
-\LMHash{}
+\LMHash{}%
 A URI of the form \code{package:$s$} is interpreted in an implementation specific manner.
 
 \rationale{
 The intent is that, during development, Dart programmers can rely on a package manager to find elements of their program.
 }
 
-\LMHash{}
+\LMHash{}%
 Otherwise, any relative URI is interpreted as relative to the location of the current library.
 All further interpretation of URIs is implementation dependent.
 
@@ -10836,7 +11057,7 @@
 \section{Types}
 \LMLabel{types}
 
-\LMHash{}
+\LMHash{}%
 Dart supports optional typing based on interface types.
 
 \rationale{
@@ -10850,7 +11071,7 @@
 \subsection{Static Types}
 \LMLabel{staticTypes}
 
-\LMHash{}
+\LMHash{}%
 Type annotations are used in variable declarations (\ref{variables}) (including formal parameters (\ref{formalParameters})), in the return types of functions (\ref{functions}) and in the bounds of type variables.
 Type annotations are used during static checking and when running programs.
 
@@ -10864,7 +11085,7 @@
 <typeList> ::= <type> (`,' <type>)*
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 A Dart implementation must provide a static checker that detects and reports exactly those situations this specification identifies as compile-time errors,
 and only those situations.
 However:
@@ -10878,8 +11099,8 @@
 However, using these tools must not preclude successful compilation and execution of Dart code.
 }
 
-\LMHash{}
-A type $T$ is {\em malformed} if{}f:
+\LMHash{}%
+A type $T$ is \Index{malformed} if{}f:
 \begin{itemize}
 \item
   $T$ has the form \id{} or the form \code{\metavar{prefix}.\id},
@@ -10918,7 +11139,7 @@
   $T$ denotes declarations that were imported from multiple imports clauses.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 Any use of a malformed type gives rise to a compile-time error.
 A malformed type is then interpreted as \DYNAMIC{} by the static type checker unless explicitly specified otherwise.
 
@@ -10926,8 +11147,9 @@
 This ensures that the developer is spared a series of cascading errors as the malformed type interacts with other types.
 }
 
-\LMHash{}
-A type $T$ is {\em deferred} if{}f it is of the form $p.T$ where $p$ is a deferred prefix.
+\LMHash{}%
+A type $T$ is \IndexCustom{deferred}{type!deferred}
+if{}f it is of the form $p.T$ where $p$ is a deferred prefix.
 It is a compile-time error to use a deferred type in a type annotation, type test, type cast or as a type parameter.
 However, all other compile-time errors must be issued under the assumption that all deferred libraries have successfully been loaded.
 
@@ -10937,16 +11159,16 @@
 \subsubsection{Type Promotion}
 \LMLabel{typePromotion}
 
-\LMHash{}
+\LMHash{}%
 The static type system ascribes a static type to every expression.
 In some cases, the type of a local variable (\commentary{which can be a formal parameter})
 may be promoted from the declared type, based on control flow.
 
-\LMHash{}
+\LMHash{}%
 We say that a variable $v$ is known to have type $T$ whenever we allow the type of $v$ to be promoted.
 The exact circumstances when type promotion is allowed are given in the relevant sections of the specification (\ref{logicalBooleanExpressions}, \ref{conditional} and \ref{if}).
 
-\LMHash{}
+\LMHash{}%
 Type promotion for a variable $v$ is allowed only when we can deduce that such promotion is valid based on an analysis of certain boolean expressions.
 In such cases, we say that the boolean expression $b$ shows that $v$ has type $T$.
 As a rule, for all variables $v$ and types $T$, a boolean expression does not show that $v$ has type $T$.
@@ -10961,9 +11183,9 @@
 % that the dynamic type of an instance is a non-generic class or
 % a generic instantiation of a generic class.
 
-\LMHash{}
+\LMHash{}%
 Let $o$ be an instance.
-The {\em dynamic type} of $o$ is the class which is specified
+The \Index{dynamic type} of $o$ is the class which is specified
 for the situation where $o$ was obtained as a fresh instance
 (\ref{redirectingFactoryConstructors},
 \ref{lists}, \ref{maps}, \ref{new}, \ref{functionInvocation}).
@@ -10976,7 +11198,7 @@
 except of course that said subtype requirement must be satisfied.
 }
 
-\LMHash{}
+\LMHash{}%
 The dynamic types of a running Dart program are equivalent to
 the static types with regard to subtyping.
 
@@ -11004,7 +11226,7 @@
 (\ref{actualTypeOfADeclaration}).
 }
 
-\LMHash{}
+\LMHash{}%
 When types are reified as instances of the built-in class \code{Type},
 those objects override the \code{==} operator
 inherited from the \code{Object} class, so that
@@ -11031,6 +11253,24 @@
 \}
 \end{dartCode}
 
+\LMHash{}
+\commentary{
+Instances of \code{Type} can be obtained in various ways,
+for example by using reflection,
+by reading the \code{runtimeType} of an object,
+or by evaluating a \emph{type literal} expression.
+}
+
+\LMHash{}
+An expression is a \emph{type literal} if it is an identifier,
+or a qualified identifier,
+which denotes a class, mixin or type alias declaration, or it is
+an identifier denoting a type parameter of a generic class or function.
+It is a \emph{constant type literal} if it does not denote a type parameter,
+and it is not qualified by a deferred prefix.
+\commentary{
+A constant type literal is a constant expression (\ref{constants}).
+}
 
 \subsection{Type Declarations}
 \LMLabel{typeDeclarations}
@@ -11039,15 +11279,16 @@
 \subsubsection{Typedef}
 \LMLabel{typedef}
 
-\LMHash{}
-A {\em type alias} declares a name for a type expression.
+\LMHash{}%
+A \Index{type alias} declares a name for a type expression.
 
 \begin{grammar}
 <typeAlias> ::= <metadata> \TYPEDEF{} <typeAliasBody>
 
 <typeAliasBody> ::= <functionTypeAlias>
 
-<functionTypeAlias> ::= <functionPrefix> <typeParameters>? <formalParameterList> `;'
+<functionTypeAlias> ::= \gnewline{}
+  <functionPrefix> <typeParameters>? <formalParameterList> `;'
 
 <functionPrefix> ::= <returnType>? <identifier>
 \end{grammar}
@@ -11055,7 +11296,7 @@
 % TODO(eernst): Introduce new type aliases and new function type syntax, then
 % include support for generic functions here.
 
-\LMHash{}
+\LMHash{}%
 The effect of a type alias of the form
 
 \code{\TYPEDEF{} $T$ \id($T_1\ p_1, \ldots,\ T_n\ p_n,\ [T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}]$)}
@@ -11073,7 +11314,7 @@
 In either case, if{}f no return type is specified, it is taken to be \DYNAMIC{}.
 Likewise, if a type annotation is omitted on a formal parameter, it is taken to be \DYNAMIC{}.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if any default values are specified in the signature of a function type alias.
 %A typedef may only refer to itself via the bounds of its generic parameters.
 Any self reference in a typedef, either directly, or recursively via another typedef, is a compile-time error.
@@ -11083,7 +11324,7 @@
 \subsection{Interface Types}
 \LMLabel{interfaceTypes}
 
-\LMHash{}
+\LMHash{}%
 The implicit interface of class $I$ is a direct supertype of the implicit interface of class $J$ if{}f:
 \begin{itemize}
 \item $I$ is \code{Object}, and $J$ has no \EXTENDS{} clause.
@@ -11093,7 +11334,7 @@
 \item $J$ is a mixin application (\ref{mixinApplication}) of the mixin of $I$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 A type $T$ is more specific than a type $S$, written $T << S$, if one of the following conditions is met:
 \begin{itemize}
 \item $T$ is $S$.
@@ -11110,7 +11351,7 @@
 \item $T << U$ and $U << S$.
 \end{itemize}
 
-\LMHash{}
+\LMHash{}%
 $<<$ is a partial order on types.
 $T$ is a subtype of $S$, written $T <: S$, if{}f $[\bot/\DYNAMIC{}]T << S$.
 
@@ -11129,18 +11370,18 @@
 \commentary{
 The \code{Null} type is more specific than all non-$\bot$ types, even though
 it doesn't actually extend or implement those types.
-The other types are effectively treated as if they are {\em nullable},
+The other types are effectively treated as if they are nullable,
 which makes the null object (\ref{null}) assignable to them.
 }
 
-\LMHash{}
+\LMHash{}%
 $S$ is a supertype of $T$, written $S :> T$, if{}f $T$ is a subtype of $S$.
 
 \commentary{
 The supertypes of an interface are its direct supertypes and their supertypes.
 }
 
-\LMHash{}
+\LMHash{}%
 An interface type $T$ may be assigned to a type $S$, written $T \Longleftrightarrow S$, if{}f either $T <: S$, $S <: T$.
 
 \rationale{
@@ -11155,7 +11396,7 @@
 \subsection{Function Types}
 \LMLabel{functionTypes}
 
-\LMHash{}
+\LMHash{}%
 Function types come in two variants:
 \begin{enumerate}
 \item
@@ -11179,7 +11420,7 @@
 in which case the type parameter declarations are omitted (\ref{generics}).
 }
 
-\LMHash{}
+\LMHash{}%
 Two function types are considered equal if consistent renaming of type
 parameters can make them identical.
 
@@ -11191,7 +11432,7 @@
 no subtype relationship exists.
 }
 
-\LMHash{}
+\LMHash{}%
 %A function type $(T_1, \ldots, T_n, [T_{n+1} , \ldots, T_{n+k}]) \rightarrow T$ is a subtype of the
 % the line below revises the rule to be more liberal
 The function type
@@ -11219,7 +11460,7 @@
 \item $\forall i \in 1 .. n, T_i \Longleftrightarrow S_i$.
 \end{enumerate}
 
-\LMHash{}
+\LMHash{}%
 A function type
 
 \code{<$X_1\ \EXTENDS\ B_1, \ldots,\ X_s\ \EXTENDS\ B_s$>}
@@ -11257,7 +11498,7 @@
 %The rules above need to be sanity checked, but the intent is that we view functions with rest parameters as having type $(T_1, ..., T_n, [\_{Tn+1}[] \_]) \rightarrow T$, where \_ is some magical identifier. Then the rules above may cover everything.
 % This is wrong - from the outside, the type takes an unbounded sequence of types, not a list. This can be modeled as $(T_1, \ldots, T_n, [T_{n+1}, \_, \ldots, T_{n+k} \_]) \rightarrow T$ for some finite $k$.
 
-\LMHash{}
+\LMHash{}%
 In addition, the following subtype rules apply:
 
 % NOTE(eernst): In Dart 1 we do not have transitivity of subtyping so we
@@ -11297,16 +11538,16 @@
 However, they induce useful relationships between function types that declare no optional parameters and those that do.
 }
 
-\LMHash{}
+\LMHash{}%
 A function type $T$ may be assigned to a function type $S$, written $T \Longleftrightarrow S$, if{}f $T <: S$.
 
-\LMHash{}
+\LMHash{}%
 A function is always an instance of some class that implements the class \FUNCTION{}.
 All function types are subtypes of \FUNCTION{}.
 
 %\commentary{Need to specify how a function values dynamic type is derived from its static signature.}
 
-\LMHash{}
+\LMHash{}%
 A function type
 
 \code{<$X_1\ \EXTENDS\ B_1, \ldots,\ X_s\ \EXTENDS\ B_s$>}
@@ -11331,7 +11572,7 @@
 \item $\forall i \in 1 .. n, T_i << S_i$.
 \end{enumerate}
 
-\LMHash{}
+\LMHash{}%
 A function type
 
 \code{<$X_1\ \EXTENDS\ B_1, \ldots,\ X_s\ \EXTENDS\ B_s$>}
@@ -11359,14 +11600,14 @@
 \item For all $y_i \in \{y_1, \ldots, y_m\}, y_i = x_j \Rightarrow T_j << S_i$
 \end{enumerate}
 
-\LMHash{}
+\LMHash{}%
 Furthermore, if $F$ is a function type, $F << \FUNCTION{}$.
 
 
 \subsection{Type \DYNAMIC{}}
 \LMLabel{typeDynamic}
 
-\LMHash{}
+\LMHash{}%
 The type \DYNAMIC{} is a static type which is a supertype of all other types,
 just like \code{Object},
 but it it differs from other types in that the static analysis
@@ -11383,10 +11624,10 @@
 of any type,
 without error.
 Note that the invocation will still cause a compile-time error
-if one or more arguments or other subterms has an error.
+if there is an error in one or more arguments or other subterms.
 }
 
-\LMHash{}
+\LMHash{}%
 % Inference is assumed to have taken place, so the type was not inferred.
 If no static type annotation has been provided,
 the type system considers declarations to have type \DYNAMIC{}.
@@ -11403,7 +11644,7 @@
 \code{$G$<$\DYNAMIC{}, \ldots,\ \DYNAMIC{}$>}.
 }
 
-\LMHash{}
+\LMHash{}%
 The built-in type declaration \code{dynamic},
 which is declared in the library \code{dart:core},
 denotes the \DYNAMIC{} type.
@@ -11413,22 +11654,141 @@
 
 \commentary{
 This \code{Type} object must compare equal to the corresponding \code{Type}
-objects for \code{Object} and \VOID{}
+objects for \code{Object} and \VOID{} according to operator `\code{==}'
 (\ref{dynamicTypeSystem}).
 }
 
+\LMHash{}%
+To improve the precision of static types,
+member accesses on a receiver of type \DYNAMIC{} that refer to
+declarations of the built-in class \code{Object}
+are given the static type corresponding to those declarations
+whenever doing so is sound.
+
+\begin{itemize}
+\item
+  Let $e$ be an expression of the form \code{$d$.\id}, which is not followed by an
+  argument part, where the static type of $d$ is \DYNAMIC, and \id{} is the name of a
+  getter declared in \code{Object}; if the return type of \code{Object.\id} is $T$
+  then the static type of $e$ is $T$.
+  \commentary{
+  For instance, \code{d.hashCode} has type \code{int}
+  and \code{d.runtimeType} has type \code{Type}.
+  }
+
+\item
+  Let $e$ be an expression of the form \code{$d$.\id}, which is not followed by an
+  argument part, where the static type of $d$ is \DYNAMIC, and \id{} is the name of a
+  method declared in \code{Object} whose method signature has type $F$
+  (\commentary{which is a function type}). The static type of $e$ is then $F$.
+  \commentary{
+  For instance, \code{$d$.toString} has type \code{String \FUNCTION()}.
+  }
+
+\item
+  Let $e$ be an expression of the form \code{$d$.\id(\metavar{arguments})} or
+  \code{$d$.\id<\metavar{typeArguments}>(\metavar{arguments})}
+  where the static type of $d$ is \DYNAMIC,
+  \id{} is the name of a getter declared in \code{Object} with return type $F$,
+  \metavar{arguments} are derived from \synt{arguments}, and
+  \metavar{typeArguments} are derived from \synt{typeArguments}, if present.
+  Static analysis will then process $e$ as a function expression invocation
+  where an object of static type $F$ is applied to the given argument part.
+  \commentary{
+  So this is always a compile-time error.
+  For instance, \code{$d$.runtimeType(42)} is a compile-time error,
+  because it is checked as a
+  function expression invocation where an entity of static type \code{Type} is
+  invoked. Note that it could actually succeed: An overriding implementation
+  of \code{runtimeType} could return an instance whose dynamic type is a subtype
+  of \code{Type} that has a \code{call} method.
+  We decided to make it an error because it is likely to be a mistake,
+  especially in cases like \code{$d$.hashCode()}
+  where a developer might have forgotten that \code{hashCode} is a getter.
+  }
+
+\item
+  Let $e$ be an expression of the form \code{$d$.\id(\metavar{arguments})}
+  where the static type of $d$ is \DYNAMIC, \metavar{arguments} is
+  an actual argument list derived from \synt{arguments},
+  and \id{} is the name of a method declared in \code{Object}
+  whose method signature has type $F$.
+  If the number of positional actual arguments in \metavar{arguments} is less than the
+  number of required positional arguments of $F$ or greater than the number
+  of positional arguments in $F$, or if \metavar{arguments} includes any named
+  arguments with a name that is not declared in $F$, the type of $e$ is
+  \DYNAMIC. Otherwise, the type of $e$ is the return type in $F$.
+  \commentary{
+    So \code{$d$.toString(bazzle:\,42)} has type \DYNAMIC{} whereas
+    \code{$d$.toString()} has type \code{String}.
+    Note that invocations which "do not fit" the statically
+    known declaration are not errors, they just get return type \DYNAMIC.
+  }
+
+\item
+  Let $e$ be an expression of the form
+  \code{$d$.\id<\metavar{typeArguments}>(\metavar{arguments})} where
+  the static type of $d$ is \DYNAMIC, \metavar{typeArguments} is a list of actual
+  type arguments derived from \synt{typeArguments}, and
+  \metavar{arguments} is an actual argument list derived from \synt{arguments}.
+  It is a compile-time error if \id{} is the name of
+  a non-generic method declared in \code{Object}.
+  \commentary{
+  No generic methods are declared in \code{Object}.
+  Hence, we do not specify that there must be
+  the statically required number of actual type arguments, and
+  they must satisfy the bounds.
+  That would otherwise be the consistent approach,
+  because the invocation is guaranteed to fail when any of those
+  requirements are violated,
+  but generalizations of this mechanism would need to include such rules.
+  }
+
+\item
+  For an instance method invocation $e$ (including invocations of getters,
+  setters, and operators) where the receiver has static type \DYNAMIC{} and
+  $e$ does not match any of the above cases, the static type of $e$ is
+  \DYNAMIC.
+  When an expression derived from \synt{cascadeSection} performs
+  a getter or method invocation that corresponds to one of the cases above,
+  the corresponding static analysis and compile-time errors apply.
+  \commentary{
+  For instance, \code{$d$..foobar(16)..hashCode()} is an error.
+  }
+\end{itemize}
+
+\commentary{
+Note that only very few forms of instance method invocation with a
+receiver of type \DYNAMIC{} can be a compile-time error.
+Of course, some expressions like \code{x[1, 2]} are syntax errors
+even though they could also be considered "invocations",
+and subexpressions are checked separately so
+any given actual argument could be a compile-time error.
+But almost any given argument list shape could be handled via \code{noSuchMethod},
+and an argument of any type could be accepted because any
+formal parameter in an overriding declaration could have its type
+annotation contravariantly changed to \code{Object}.
+So it is a natural consequence of the principle of
+that
+a \DYNAMIC{} receiver admits almost all instance method invocations.
+The few cases where an instance method invocation with
+a receiver of type \DYNAMIC{} is an error
+are either guaranteed to fail at run time,
+or they are very, very likely to be developer mistakes.
+}
+
 
 \subsection{Type FutureOr}
 \LMLabel{typeFutureOr}
 
 %% TODO(eernst): We should make this a separate section, or change the title of this section.
 
-\LMHash{}
+\LMHash{}%
 The built-in type declaration \code{FutureOr},
 which is declared in the library \code{dart:async},
 defines a generic type with one type parameter (\ref{generics}).
 
-\LMHash{}
+\LMHash{}%
 The \code{FutureOr<$T$>} type is a non-class type with the following
 type relations:
 \begin{itemize}
@@ -11441,11 +11801,11 @@
 
 \commentary{
 The last point guarantees that generic type \code{FutureOr} is
-{\em covariant} in its type parameter, just like class types.
+\emph{covariant} in its type parameter, just like class types.
 That is, if $S$ <: $T$ then \code{FutureOr<$S$>} <: \code{FutureOr<$T$>}.
 }
 
-\LMHash{}
+\LMHash{}%
 If the type arguments passed to \code{FutureOr} would incur compile-time errors
 if applied to a normal generic class with one type parameter,
 the same compile-time errors are issued for \code{FutureOr}.
@@ -11461,7 +11821,7 @@
 to provide a more precise type analysis.
 }
 
-\LMHash{}
+\LMHash{}%
 The type \code{FutureOr<$T$>} has an interface that is identical to that
 of \code{Object}.
 
@@ -11485,7 +11845,7 @@
 
 %% TODO(eernst): Adjust everything in this section when specifying generalized-void.
 
-\LMHash{}
+\LMHash{}%
 The special type \VOID{} may only be used as the return type of a function: it is a compile-time error to use \VOID{} in any other context.
 
 \commentary{
@@ -11537,7 +11897,7 @@
 % (\code{var f = foo<int>;}), or if we allow it to arise implicitly based
 % on inference. That new concept should probably be added to this section.
 
-\LMHash{}
+\LMHash{}%
 A \emph{parameterized type} is a syntactic construct where the name of a generic type declaration is applied to a list of actual type arguments.
 A \emph{generic instantiation} is the operation where a generic type is applied to actual type arguments.
 
@@ -11546,10 +11906,10 @@
 When using the former, we will often leave the latter implicit.
 }
 
-\LMHash{}
+\LMHash{}%
 Let $T$ be a parameterized type \code{$G$<$S_1, \ldots,\ S_n$>}.
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $G$ is not a generic type,
 or $G$ is a generic type, but the number of formal type parameters in the declaration of $G$ is not $n$.
 Otherwise, let
@@ -11558,20 +11918,20 @@
 $B_1, \ldots, B_n$
 be the corresponding upper bounds, using \DYNAMIC{} when no bound is declared.
 
-\LMHash{}
-$T$ is {\em malbounded} if{}f either
+\LMHash{}%
+$T$ is \Index{malbounded} if{}f either
 $S_i$ is malbounded for one or more $i \in 1 .. n$,
 or $T$ is not well-bounded (\ref{superBoundedTypes}).
 
-\LMHash{}
+\LMHash{}%
 It is a compile-time error if $T$ is malbounded.
 
-\LMHash{}
+\LMHash{}%
 $T$ is evaluated as follows.
 Let $t_i$ be the result of evaluating $S_i$, for $i \in 1 .. n$.
 $T$ then evaluates to the generic instantiation where $G$ is applied to $t_1, \ldots, t_n$.
 
-\LMHash{}
+\LMHash{}%
 Let $T$ be a parameterized type of the form
 \code{$G$<$A_1, \ldots,\ A_n$>}
 and assume that $T$ is not malformed and not malbounded.
@@ -11606,7 +11966,7 @@
 % even if it is a recursive invocation on the form \code{foo<C<X>>()} in the
 % body.
 
-\LMHash{}
+\LMHash{}%
 Let $T$ be the declared type of a declaration $d$,
 as it appears in the program source.
 Let $X_1, \ldots, X_n$ be the formal type parameters in scope at $d$.
@@ -11614,7 +11974,7 @@
 $X_1, \ldots, X_n$
 are
 $t_1, \ldots, t_n$,
-the {\em actual type} of $d$ is
+the \Index{actual type} of $d$ is
 $[t_1/X_1, \ldots, t_n/X_n]T$.
 
 \commentary{
@@ -11625,7 +11985,7 @@
 one or more enclosing generic functions and an enclosing generic class.
 }
 
-\LMHash{}
+\LMHash{}%
 Let \code{$X$ \EXTENDS{} $B$} be a formal type parameter declaration.
 Let
 $X_1, \ldots, X_n$
@@ -11634,7 +11994,7 @@
 $X_1, \ldots, X_n$
 are
 $t_1, \ldots, t_n$,
-the {\em actual bound} for $X$ is
+the \Index{actual bound} for $X$ is
 $[t_1/X_1, \ldots, t_n/X_n]B$.
 
 \commentary{
@@ -11650,7 +12010,7 @@
 % into account, but no other changes have been performed. Hence, we still
 % need to update this section to use Dart 2 rules for LUB.
 
-\LMHash{}
+\LMHash{}%
 % does this diverge in some cases?
 Given two interfaces $I$ and $J$,
 let $S_I$ be the set of superinterfaces of $I$,
@@ -11665,20 +12025,20 @@
 which must exist because $S_0$ is $\{\code{Object}\}$.
 The least upper bound of $I$ and $J$ is the sole element of $S_q$.
 
-\LMHash{}
+\LMHash{}%
 The least upper bound of \DYNAMIC{} and any type $T$ is \DYNAMIC{}.
 The least upper bound of \VOID{} and any type $T \ne \DYNAMIC{}$ is \VOID{}.
 The least upper bound of $\bot$ and any type $T$ is $T$.
 Let $U$ be a type variable with upper bound $B$.
 The least upper bound of $U$ and a type $T \ne \bot$ is the least upper bound of $B$ and $T$.
 
-\LMHash{}
+\LMHash{}%
 The least upper bound operation is commutative and idempotent,
 but it is not associative.
 
 % Function types
 
-\LMHash{}
+\LMHash{}%
 The least upper bound of a function type and an interface type $T$ is the least upper bound of \FUNCTION{} and $T$.
 Let $F$ and $G$ be function types.
 If $F$ and $G$ differ in their number of required parameters,
@@ -11741,7 +12101,7 @@
 \subsection{Lexical Rules}
 \LMLabel{lexicalRules}
 
-\LMHash{}
+\LMHash{}%
 Dart source text is represented as a sequence of Unicode code points.
 This sequence is first converted into a sequence of tokens according to the lexical rules given in this specification.
 At any point in the tokenization process, the longest possible token is recognized.
@@ -11750,8 +12110,8 @@
 \subsubsection{Reserved Words}
 \LMLabel{reservedWords}
 
-\LMHash{}
-A {\em reserved word} may not be used as an identifier; it is a compile-time error if a reserved word is used where an identifier is expected.
+\LMHash{}%
+A \Index{reserved word} may not be used as an identifier; it is a compile-time error if a reserved word is used where an identifier is expected.
 
 \ASSERT{}, \BREAK{}, \CASE{}, \CATCH{}, \CLASS{}, \CONST{}, \CONTINUE{}, \DEFAULT{}, \DO{}, \ELSE{}, \ENUM{}, \EXTENDS{}, \FALSE{}, \FINAL{}, \FINALLY{}, \FOR{}, \IF{}, \IN{}, \IS{}, \NEW{}, \NULL{}, \RETHROW, \RETURN{}, \SUPER{}, \SWITCH{}, \THIS{}, \THROW{}, \TRUE{}, \TRY{}, \VAR{}, \VOID{}, \WHILE{}, \WITH{}.
 
@@ -11768,40 +12128,43 @@
 \subsubsection{Comments}
 \LMLabel{comments}
 
-\LMHash{}
-{\em Comments} are sections of program text that are used for documentation.
+\LMHash{}%
+\IndexCustom{Comments}{comment}
+are sections of program text that are used for documentation.
 
 \begin{grammar}
 <SINGLE\_LINE\_COMMENT> ::= `//' \~{}(<NEWLINE>)* (<NEWLINE>)?
 
-<MULTI\_LINE\_COMMENT> ::= `/*' (<MULTI\_LINE\_COMMENT> | \~{} `*/')* `*/'
+<MULTI\_LINE\_COMMENT> ::= \gnewline{}
+  `/*' (<MULTI\_LINE\_COMMENT> | \~{} `*/')* `*/'
 \end{grammar}
 
-\LMHash{}
+\LMHash{}%
 Dart supports both single-line and multi-line comments.
-A {\em single line comment} begins with the token \code{//}.
+A \Index{single line comment} begins with the token \code{//}.
 Everything between \code{//} and the end of line must be ignored by the Dart compiler unless the comment is a documentation comment.
 
-\LMHash{}
-A {\em multi-line comment} begins with the token \code{/*} and ends with the token \code{*/}.
+\LMHash{}%
+A \Index{multi-line comment} begins with the token \code{/*} and ends with the token \code{*/}.
 Everything between \code{/}* and \code{*}/ must be ignored by the Dart compiler unless the comment is a documentation comment.
 Comments may nest.
 
-\LMHash{}
-{\em Documentation comments} are comments that begin with the tokens \code{///} or \code{/**}.
+\LMHash{}%
+\IndexCustom{Documentation comments}{documentation comments}
+are comments that begin with the tokens \code{///} or \code{/**}.
 Documentation comments are intended to be processed by a tool that produces human readable documentation.
 
-\LMHash{}
+\LMHash{}%
 The scope of a documentation comment immediately preceding the declaration of a class $C$ is the instance scope of $C$.
 
-\LMHash{}
+\LMHash{}%
 The scope of a documentation comment immediately preceding the declaration of a function $f$ is the scope in force at the very beginning of the body of $f$.
 
 
 \subsection{Operator Precedence}
 \LMLabel{operatorPrecedence}
 
-\LMHash{}
+\LMHash{}%
 Operator precedence is given implicitly by the grammar.
 
 \commentary{
@@ -11864,7 +12227,7 @@
 \item[$\bullet$]
 Valid values of JavaScript \code{int} are any
 IEEE-754 64-bit floating point number with no fractional part.
-This includes positive and negative {\em infinity},
+This includes positive and negative \Index{infinity},
 which can be reached by overflowing
 (integer division by zero is still not allowed).
 Otherwise valid integer literals (including any leading minus sign)
@@ -11876,7 +12239,8 @@
 JavaScript \code{int} instances also implement \code{double},
 and integer-valued \code{double} instances also implement \code{int}.
 The \code{int} and \code{double} class are still separate subclasses of the
-class \code{num}, but {\em instances} of either class that represent an integer,
+class \code{num},
+but \emph{instances} of either class that represent an integer
 act as if they are actually instances of a common subclass implementing both
 \code{int} and \code{double}. Fractional numbers only implement \code{double}.
 \item[$\bullet$]
@@ -11884,12 +12248,14 @@
 all truncate the operands to 32-bit values.
 \item[$\bullet$]
 The \code{identical} method cannot distinguish the values $0.0$ and $-0.0$,
-and it cannot recognize any {\em NaN} value as identical to itself.
+and it cannot recognize any \Index{NaN} value as identical to itself.
 For efficiency, the \code{identical} operation uses the JavaScript \code{===}
 operator.
 \end{itemize}
 }
 
+\printindex
+
 \end{document}
 
 [Text after \end{document} is ignored, hence we do not need "%"]
diff --git a/docs/language/informal/dynamic-members.md b/docs/language/informal/dynamic-members.md
index 07a8371..78c070d 100644
--- a/docs/language/informal/dynamic-members.md
+++ b/docs/language/informal/dynamic-members.md
@@ -4,7 +4,7 @@
 
 **Version**: 0.2 (2018-09-04)
 
-**Status**: Under implementation.
+**Status**: Background material. Normative text is now in dartLangSpec.tex.
 
 **This document** is a Dart 2 feature specification of the static typing
 of instance members of a receiver whose static type is `dynamic`.
diff --git a/docs/language/informal/mixin-declaration.md b/docs/language/informal/mixin-declaration.md
index 0521fc9..a4e5081 100644
--- a/docs/language/informal/mixin-declaration.md
+++ b/docs/language/informal/mixin-declaration.md
@@ -2,4 +2,4 @@
 
 **Status**: This is now background material.
 
-## The canonical version of this document now resides [here](https://github.com/dart-lang/language/blob/master/working/0006.%20Super-invocations%20in%20mixins/0007.%20Mixin%20declarations/lrhn-strawman.md).
+## The canonical version of this document now resides [here](https://github.com/dart-lang/language/blob/master/accepted/2.1/super-mixins/feature-specification.md).
diff --git a/docs/process/experimental-flags.md b/docs/process/experimental-flags.md
new file mode 100644
index 0000000..e0af8b2
--- /dev/null
+++ b/docs/process/experimental-flags.md
@@ -0,0 +1,97 @@
+# Dart SDK process for changes behind experimental flags
+
+## Problem statement
+
+The Dart SDK ships via a number of channels:
+
+- Via the [Dart SDK](https://www.dartlang.org/tools/sdk#install)
+- Via the [Flutter SDK](http://flutter.io)
+- Internally at Google via an internal channel
+
+Each of these channels use varying release calendars, and keeping these entirely
+aligned is not practical. Further, a number of developers interested in staying
+current with Dart changes, consume the Dart SDK via our [dev
+channel](https://github.com/dart-lang/sdk/wiki/Branches-and-releases). As a
+result, we should anticipate that any dev channel build has the potential to end
+up as a shipped SDK though some channel. And as a consequence of that, it is
+critical that we keep the quality of our dev channel high AND that we keep it
+consistent wrt. which features are complete and supported. At the same time, we
+need the ability to land incomplete features to facilitate a number of tasks:
+
+- Compose a feature that spans multiple components/areas
+- Automated testing prior to the full completion of the feature
+- Allow partner teams to get a preview of a future feature
+- Allow customers to get a preview of a future feature
+- Etc.
+
+## Solution
+
+To ensure completed & supported features can be differentiated from incomplete
+features in-progress, we will put all in-progress features behind a single set
+of flags. Changes to features behind these flags are not considered breaking
+(even if the feature behind the flag was in a stable SDK), and they are subject
+to removal at any time. For details about breaking changes, see the breaking
+change process.
+
+All new features that meet one of the following criteria must be developed
+behind a flag (when possible):
+
+- All breaking changes
+- All language changes
+
+Further, it is recommended to consider developing behind a flag when:
+
+- Landing larger, user-visible changes which will be in an intermediate state
+  over several weeks and perhaps even releases
+- Making changes with the potential to have significant negative performance
+  impact for several weeks and perhaps even across releases
+
+## Details
+
+### Flag format for CLI-based tools
+
+Flags consist of one or more words, combined using dashes, using all lower-case.
+The single source of truth of these flags shall be a single shared .dart file.
+The tools are expected to offer a framework for querying these flags so that the
+implementation of the tools can easily access new flags.
+
+The flags are passed to CLI-based tools using the `--enable-experiment` flag
+Multiple flags can be passed by using multiple flags, or by passing several
+comma-separated flags. Examples:
+
+```
+dart --enable-experiment super-mixins
+dart --enable-experiment super-mixins,no-slow-checks,preview-dart3
+dart --enable-experiment super-mixins --enable-experiment no-slow-checks --enable-experiment preview-dart3
+```
+
+If the user passes a flag that is not recognized (for example, when the flag is
+no longer supported), the tool is required to inform about this by printing to
+stderr, and not fail.
+
+```
+dart --enable-experiment better-mixins
+Unknown experiment flag 'better-mixins'.
+```
+
+### Flag format for UI-based tools (IDEs/editors/etc.)
+
+IDEs and editors which offer the ability to invoke Dart tools, must support
+passing these flags. The support should be generic and flexible so that no UI
+change is required when we add or remove a flag. This is expected to take one of
+two forms:
+
+- Experiments affecting analysis can be enabled in `analysis_options.yaml` under
+  a single `enable-experiment:` key, e.g. to enable the flags `super-mixins` &
+  `no-slow-checks`:
+
+  ```
+  analyzer:
+    enable-experiment:
+      - super-mixins
+      - no-slow-checks
+  ```
+
+- Experiments affecting launch/run behavior, can be enabled in the IDE specific
+  run Configuration, by passing the same `--enable-experiment` flag as listed in
+  the CLI section.
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 1280460..38d52a9 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -6,6 +6,8 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
+const String PROTOCOL_VERSION = '1.21.1';
+
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
 const String ANALYSIS_NOTIFICATION_CLOSING_LABELS = 'analysis.closingLabels';
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 0ef82e1..ae93b77 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -9,6 +9,8 @@
 import 'dart:math' show max;
 
 import 'package:analysis_server/protocol/protocol.dart';
+import 'package:analysis_server/protocol/protocol_constants.dart'
+    show PROTOCOL_VERSION;
 import 'package:analysis_server/protocol/protocol_generated.dart'
     hide AnalysisOptions;
 import 'package:analysis_server/src/analysis_logger.dart';
@@ -84,12 +86,6 @@
  */
 class AnalysisServer {
   /**
-   * The version of the analysis server. The value should be replaced
-   * automatically during the build.
-   */
-  static final String VERSION = '1.21.1';
-
-  /**
    * The options of this server instance.
    */
   AnalysisServerOptions options;
@@ -362,7 +358,8 @@
       });
     });
     searchEngine = new SearchEngineImpl(driverMap.values);
-    Notification notification = new ServerConnectedParams(VERSION, io.pid,
+    Notification notification = new ServerConnectedParams(
+            PROTOCOL_VERSION, io.pid,
             sessionId: instrumentationService.sessionId)
         .toNotification();
     channel.sendNotification(notification);
diff --git a/pkg/analysis_server/lib/src/domain_server.dart b/pkg/analysis_server/lib/src/domain_server.dart
index 39497ac..728a4dd 100644
--- a/pkg/analysis_server/lib/src/domain_server.dart
+++ b/pkg/analysis_server/lib/src/domain_server.dart
@@ -28,8 +28,7 @@
    * Return the version number of the analysis server.
    */
   Response getVersion(Request request) {
-    return new ServerGetVersionResult(AnalysisServer.VERSION)
-        .toResponse(request.id);
+    return new ServerGetVersionResult(PROTOCOL_VERSION).toResponse(request.id);
   }
 
   @override
diff --git a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
index 6673fb4..2dc141b 100644
--- a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
@@ -12,6 +12,7 @@
 import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
 import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -97,25 +98,7 @@
       preferMixinFix,
       preferIntLiteralsFix,
     ];
-    final visitors = <AstVisitor>[];
-    final registry = new NodeLintRegistry(false);
-    for (Linter linter in linters) {
-      if (linter != null) {
-        final visitor = linter.getVisitor();
-        if (visitor != null) {
-          visitors.add(visitor);
-        }
-        if (linter is NodeLintRule) {
-          (linter as NodeLintRule).registerNodeProcessors(registry);
-        }
-      }
-    }
-    final AstVisitor astVisitor = visitors.isNotEmpty
-        ? new ExceptionHandlingDelegatingAstVisitor(
-            visitors, ExceptionHandlingDelegatingAstVisitor.logException)
-        : null;
-    final AstVisitor linterVisitor = new LinterVisitor(
-        registry, ExceptionHandlingDelegatingAstVisitor.logException);
+    final lintVisitorsBySession = <AnalysisSession, _LintVisitors>{};
 
     // TODO(danrubel): Determine if a lint is configured to run as part of
     // standard analysis and use those results if available instead of
@@ -159,10 +142,12 @@
             linter.reporter.source = source;
           }
         }
-        if (astVisitor != null) {
-          unit.accept(astVisitor);
+        var lintVisitors = lintVisitorsBySession[result.session] ??=
+            await _setupLintVisitors(result, linters);
+        if (lintVisitors.astVisitor != null) {
+          unit.accept(lintVisitors.astVisitor);
         }
-        unit.accept(linterVisitor);
+        unit.accept(lintVisitors.linterVisitor);
         for (LinterFix fix in fixes) {
           await fix.applyLocalFixes(result);
         }
@@ -247,6 +232,48 @@
         result.path, offset, length, locInfo.lineNumber, locInfo.columnNumber);
     return location;
   }
+
+  Future<_LintVisitors> _setupLintVisitors(
+      AnalysisResult result, List<Linter> linters) async {
+    final visitors = <AstVisitor>[];
+    final registry = new NodeLintRegistry(false);
+    // TODO(paulberry): use an API that provides this information more readily
+    var unitElement = result.unit.declaredElement;
+    var session = result.session;
+    var currentUnit = LinterContextUnit(result.content, result.unit);
+    var allUnits = <LinterContextUnit>[];
+    for (var cu in unitElement.library.units) {
+      if (identical(cu, unitElement)) {
+        allUnits.add(currentUnit);
+      } else {
+        var result = await session.getResolvedAst(cu.source.fullName);
+        allUnits.add(LinterContextUnit(result.content, result.unit));
+      }
+    }
+    var context = LinterContextImpl(allUnits, currentUnit,
+        session.declaredVariables, result.typeProvider, result.typeSystem);
+    for (Linter linter in linters) {
+      if (linter != null) {
+        final visitor = linter.getVisitor();
+        if (visitor != null) {
+          visitors.add(visitor);
+        }
+        if (linter is NodeLintRuleWithContext) {
+          (linter as NodeLintRuleWithContext)
+              .registerNodeProcessors(registry, context);
+        } else if (linter is NodeLintRule) {
+          (linter as NodeLintRule).registerNodeProcessors(registry);
+        }
+      }
+    }
+    final AstVisitor astVisitor = visitors.isNotEmpty
+        ? new ExceptionHandlingDelegatingAstVisitor(
+            visitors, ExceptionHandlingDelegatingAstVisitor.logException)
+        : null;
+    final AstVisitor linterVisitor = new LinterVisitor(
+        registry, ExceptionHandlingDelegatingAstVisitor.logException);
+    return _LintVisitors(astVisitor, linterVisitor);
+  }
 }
 
 class EditDartFixAssistContext implements DartAssistContext {
@@ -333,3 +360,11 @@
     // ignored
   }
 }
+
+class _LintVisitors {
+  final AstVisitor astVisitor;
+
+  final AstVisitor linterVisitor;
+
+  _LintVisitors(this.astVisitor, this.linterVisitor);
+}
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index b676b41..de0500c 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -6,6 +6,8 @@
 import 'dart:io';
 import 'dart:math';
 
+import 'package:analysis_server/protocol/protocol_constants.dart'
+    show PROTOCOL_VERSION;
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/server/detachable_filesystem_manager.dart';
 import 'package:analysis_server/src/server/dev_server.dart';
@@ -436,7 +438,7 @@
             : _readUuid(instrumentationService),
         analysisServerOptions.clientId,
         analysisServerOptions.clientVersion,
-        AnalysisServer.VERSION,
+        PROTOCOL_VERSION,
         defaultSdk.sdkVersion);
     AnalysisEngine.instance.instrumentationService = instrumentationService;
 
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 dffd207..b9a6be5 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -406,7 +406,7 @@
     await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
       builder.addReplacement(new SourceRange(literal.offset, literal.length),
           (DartEditBuilder builder) {
-        builder.write('${intValue}');
+        builder.write('$intValue');
       });
     });
     _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_TO_INT_LITERAL);
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index 56423be..dc21222 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -7,6 +7,8 @@
 import 'dart:developer' as developer;
 import 'dart:io';
 
+import 'package:analysis_server/protocol/protocol_constants.dart'
+    show PROTOCOL_VERSION;
 import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/domain_completion.dart';
@@ -1319,7 +1321,7 @@
 
     buf.writeln('<div class="column one-half">');
     h3('Versions');
-    buf.writeln(writeOption('Analysis server version', AnalysisServer.VERSION));
+    buf.writeln(writeOption('Analysis server version', PROTOCOL_VERSION));
     buf.writeln(writeOption('Dart SDK', Platform.version));
     buf.writeln('</div>');
 
diff --git a/pkg/analysis_server/test/domain_edit_dartfix_test.dart b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
new file mode 100644
index 0000000..b7f6182
--- /dev/null
+++ b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
@@ -0,0 +1,107 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/protocol/protocol.dart';
+import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analysis_server/src/edit/edit_dartfix.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:linter/src/rules.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'analysis_abstract.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(EditDartfixDomainHandlerTest);
+  });
+}
+
+@reflectiveTest
+class EditDartfixDomainHandlerTest extends AbstractAnalysisTest {
+  String libPath;
+
+  void expectEdits(List<SourceFileEdit> fileEdits, String expectedSource) {
+    expect(fileEdits, hasLength(1));
+    expect(fileEdits[0].file, testFile);
+    List<SourceEdit> edits = fileEdits[0].edits;
+    String source = testCode;
+    for (SourceEdit edit in edits) {
+      source = edit.apply(source);
+    }
+    expect(source, expectedSource);
+  }
+
+  void expectSuggestion(DartFixSuggestion suggestion, String partialText,
+      int offset, int length) {
+    expect(suggestion.description, contains(partialText));
+    expect(suggestion.location.offset, offset);
+    expect(suggestion.location.length, length);
+  }
+
+  Future<EditDartfixResult> performFix() async {
+    final request = new Request(
+        '33', 'edit.dartfix', new EditDartfixParams([libPath]).toJson());
+
+    final response = await new EditDartFix(server, request).compute();
+    expect(response.id, '33');
+
+    return EditDartfixResult.fromResponse(response);
+  }
+
+  @override
+  void setUp() {
+    super.setUp();
+    registerLintRules();
+    createProject();
+    libPath = resourceProvider.convertPath('/project/lib');
+    testFile = resourceProvider.convertPath('/project/lib/fileToBeFixed.dart');
+  }
+
+  test_dartfix_convertClassToMixin() async {
+    addTestFile('''
+class A {}
+class B extends A {}
+class C with B {}
+    ''');
+    EditDartfixResult result = await performFix();
+    expect(result.suggestions, hasLength(1));
+    expectSuggestion(result.suggestions[0], 'mixin', 17, 1);
+    expectEdits(result.edits, '''
+class A {}
+mixin B implements A {}
+class C with B {}
+    ''');
+  }
+
+  test_dartfix_convertToIntLiteral() async {
+    addTestFile('''
+const double myDouble = 42.0;
+    ''');
+    EditDartfixResult result = await performFix();
+    expect(result.suggestions, hasLength(1));
+    expectSuggestion(result.suggestions[0], 'int literal', 24, 4);
+    expectEdits(result.edits, '''
+const double myDouble = 42;
+    ''');
+  }
+
+  test_dartfix_moveTypeArgumentToClass() async {
+    addTestFile('''
+class A<T> { A.from(Object obj) { } }
+main() {
+  print(new A.from<String>([]));
+}
+    ''');
+    EditDartfixResult result = await performFix();
+    expect(result.suggestions, hasLength(1));
+    expectSuggestion(result.suggestions[0], 'type arguments', 65, 8);
+    expectEdits(result.edits, '''
+class A<T> { A.from(Object obj) { } }
+main() {
+  print(new A<String>.from([]));
+}
+    ''');
+  }
+}
diff --git a/pkg/analysis_server/test/domain_server_test.dart b/pkg/analysis_server/test/domain_server_test.dart
index 149a7d3..f7f1fda 100644
--- a/pkg/analysis_server/test/domain_server_test.dart
+++ b/pkg/analysis_server/test/domain_server_test.dart
@@ -40,7 +40,7 @@
           response.toJson(),
           equals({
             Response.ID: '0',
-            Response.RESULT: {VERSION: AnalysisServer.VERSION}
+            Response.RESULT: {VERSION: PROTOCOL_VERSION}
           }));
     });
 
diff --git a/pkg/analysis_server/test/test_all.dart b/pkg/analysis_server/test/test_all.dart
index a736732..5afc1e7 100644
--- a/pkg/analysis_server/test/test_all.dart
+++ b/pkg/analysis_server/test/test_all.dart
@@ -13,6 +13,7 @@
 import 'domain_analysis_test.dart' as domain_analysis_test;
 import 'domain_completion_test.dart' as domain_completion_test;
 import 'domain_diagnostic_test.dart' as domain_experimental_test;
+import 'domain_edit_dartfix_test.dart' as domain_edit_dartfix_test;
 import 'domain_execution_test.dart' as domain_execution_test;
 import 'domain_server_test.dart' as domain_server_test;
 import 'edit/test_all.dart' as edit_all;
@@ -36,6 +37,7 @@
     context_manager_test.main();
     domain_analysis_test.main();
     domain_completion_test.main();
+    domain_edit_dartfix_test.main();
     domain_execution_test.main();
     domain_experimental_test.main();
     domain_server_test.main();
diff --git a/pkg/analysis_server/tool/spec/codegen_dart_notification_handler.dart b/pkg/analysis_server/tool/spec/codegen_dart_notification_handler.dart
new file mode 100644
index 0000000..45c8f2e
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/codegen_dart_notification_handler.dart
@@ -0,0 +1,143 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/codegen/tools.dart';
+import 'package:html/dom.dart';
+
+import 'api.dart';
+import 'codegen_dart.dart';
+import 'codegen_protocol_constants.dart' show generateConstName;
+import 'from_html.dart';
+
+GeneratedFile clientTarget() {
+  return new GeneratedFile(
+      '../analysis_server_client/lib/handler/notification_handler.dart',
+      (String pkgPath) async {
+    CodegenNotificationHandlerVisitor visitor =
+        new CodegenNotificationHandlerVisitor(readApi(pkgPath));
+    return visitor.collectCode(visitor.visitApi);
+  });
+}
+
+/**
+ * Visitor which produces Dart code representing the API.
+ */
+class CodegenNotificationHandlerVisitor extends DartCodegenVisitor
+    with CodeGenerator {
+  CodegenNotificationHandlerVisitor(Api api) : super(api) {
+    codeGeneratorSettings.commentLineLength = 79;
+    codeGeneratorSettings.languageName = 'dart';
+  }
+
+  void emitImports() {
+    writeln("import 'package:analysis_server_client/protocol.dart';");
+  }
+
+  void emitNotificationHandler() {
+    _NotificationVisitor visitor = new _NotificationVisitor(api)..visitApi();
+    final notifications = visitor.notificationConstants;
+    notifications.sort((n1, n2) => n1.constName.compareTo(n2.constName));
+
+    writeln('''
+/// [NotificationHandler] processes analysis server notifications
+/// and dispatches those notifications to different methods based upon
+/// the type of notification. Clients may override
+/// any of the "on<EventName>" methods that are of interest.
+///
+/// Clients may mix-in this class, but may not implement it.
+mixin NotificationHandler {
+  void handleEvent(Notification notification) {
+    Map<String, Object> params = notification.params;
+    ResponseDecoder decoder = new ResponseDecoder(null);
+    switch (notification.event) {
+''');
+    for (_Notification notification in notifications) {
+      writeln('      case ${notification.constName}:');
+      writeln('        ${notification.methodName}(');
+      writeln('          new ${notification.paramsTypeName}');
+      writeln("            .fromJson(decoder, 'params', params));");
+      writeln('        break;');
+    }
+    writeln('      default:');
+    writeln('        onUnknownNotification(notification.event, params);');
+    writeln('        break;');
+    writeln('    }');
+    writeln('  }');
+    for (_Notification notification in notifications) {
+      writeln();
+      emitDartdoc(notification.dartdoc);
+      writeln('  void ${notification.methodName}(');
+      writeln('    ${notification.paramsTypeName} params) {');
+      writeln('  }');
+    }
+    writeln();
+    writeln('  /// Reports a notification that is not processed');
+    writeln('  /// by any other notification handlers.');
+    writeln('  void onUnknownNotification(String event, params) {}');
+    writeln('}');
+  }
+
+  void emitDartdoc(List<String> dartdoc) {
+    bool first = true;
+    for (String paragraph in dartdoc) {
+      if (first) {
+        first = false;
+      } else {
+        writeln('  ///');
+      }
+      for (String line in paragraph.split(new RegExp('\r?\n'))) {
+        writeln('  /// ${line.trim()}');
+      }
+    }
+  }
+
+  @override
+  visitApi() {
+    outputHeader(year: '2018');
+    writeln();
+    emitImports();
+    emitNotificationHandler();
+  }
+}
+
+class _Notification {
+  final String constName;
+  final String methodName;
+  final String paramsTypeName;
+  final List<String> dartdoc;
+
+  _Notification(
+      this.constName, this.methodName, this.paramsTypeName, this.dartdoc);
+}
+
+class _NotificationVisitor extends HierarchicalApiVisitor {
+  final notificationConstants = <_Notification>[];
+
+  _NotificationVisitor(Api api) : super(api);
+
+  @override
+  void visitNotification(Notification notification) {
+    notificationConstants.add(new _Notification(
+        generateConstName(
+            notification.domainName, 'notification', notification.event),
+        _generateNotificationMethodName(
+            notification.domainName, notification.event),
+        _generateParamTypeName(notification.domainName, notification.event),
+        _generateDartDoc(notification.html)));
+  }
+}
+
+List<String> _generateDartDoc(Element html) => html.children
+    .where((Element elem) => elem.localName == 'p')
+    .map<String>((Element elem) => elem.text.trim())
+    .toList();
+
+String _generateNotificationMethodName(String domainName, String event) =>
+    'on${_capitalize(domainName)}${_capitalize(event)}';
+
+String _generateParamTypeName(String domainName, String event) =>
+    '${_capitalize(domainName)}${_capitalize(event)}Params';
+
+_capitalize(String name) =>
+    '${name.substring(0, 1).toUpperCase()}${name.substring(1)}';
diff --git a/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart b/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart
index 8ddfb5e..658f2c7 100644
--- a/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart
+++ b/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart
@@ -22,6 +22,17 @@
 });
 
 /**
+   * Generate a name from the [domainName], [kind] and [name] components.
+   */
+String generateConstName(String domainName, String kind, String name) {
+  List<String> components = <String>[];
+  components.addAll(_split(domainName));
+  components.add(kind);
+  components.addAll(_split(name));
+  return _fromComponents(components);
+}
+
+/**
  * A visitor that produces Dart code defining constants associated with the API.
  */
 class CodegenVisitor extends DartCodegenVisitor with CodeGenerator {
@@ -34,6 +45,8 @@
    * Generate all of the constants associates with the [api].
    */
   void generateConstants() {
+    writeln("const String PROTOCOL_VERSION = '${api.version}';");
+    writeln();
     _ConstantVisitor visitor = new _ConstantVisitor(api);
     visitor.visitApi();
     List<_Constant> constants = visitor.constants;
@@ -101,7 +114,7 @@
     String domainName = notification.domainName;
     String event = notification.event;
 
-    String constantName = _generateName(domainName, 'notification', event);
+    String constantName = generateConstName(domainName, 'notification', event);
     constants.add(new _Constant(constantName, "'$domainName.$event'"));
     _addFieldConstants(constantName, notification.params);
   }
@@ -111,11 +124,13 @@
     String domainName = request.domainName;
     String method = request.method;
 
-    String requestConstantName = _generateName(domainName, 'request', method);
+    String requestConstantName =
+        generateConstName(domainName, 'request', method);
     constants.add(new _Constant(requestConstantName, "'$domainName.$method'"));
     _addFieldConstants(requestConstantName, request.params);
 
-    String responseConstantName = _generateName(domainName, 'response', method);
+    String responseConstantName =
+        generateConstName(domainName, 'response', method);
     _addFieldConstants(responseConstantName, request.result);
   }
 
@@ -137,40 +152,29 @@
       constants.add(new _Constant(fieldConstantName, "'$name'"));
     });
   }
+}
 
-  /**
+/**
    * Return a name generated by converting each of the given [components] to an
    * uppercase equivalent, then joining them with underscores.
    */
-  String _fromComponents(List<String> components) =>
-      components.map((String component) => component.toUpperCase()).join('_');
+String _fromComponents(List<String> components) =>
+    components.map((String component) => component.toUpperCase()).join('_');
 
-  /**
-   * Generate a name from the [domainName], [kind] and [name] components.
-   */
-  String _generateName(String domainName, String kind, String name) {
-    List<String> components = <String>[];
-    components.addAll(_split(domainName));
-    components.add(kind);
-    components.addAll(_split(name));
-    return _fromComponents(components);
-  }
-
-  /**
+/**
    * Return the components of the given [string] that are indicated by an upper
    * case letter.
    */
-  Iterable<String> _split(String first) {
-    RegExp regExp = new RegExp('[A-Z]');
-    List<String> components = <String>[];
-    int start = 1;
-    int index = first.indexOf(regExp, start);
-    while (index >= 0) {
-      components.add(first.substring(start - 1, index));
-      start = index + 1;
-      index = first.indexOf(regExp, start);
-    }
-    components.add(first.substring(start - 1));
-    return components;
+Iterable<String> _split(String first) {
+  RegExp regExp = new RegExp('[A-Z]');
+  List<String> components = <String>[];
+  int start = 1;
+  int index = first.indexOf(regExp, start);
+  while (index >= 0) {
+    components.add(first.substring(start - 1, index));
+    start = index + 1;
+    index = first.indexOf(regExp, start);
   }
+  components.add(first.substring(start - 1));
+  return components;
 }
diff --git a/pkg/analysis_server/tool/spec/generate_all.dart b/pkg/analysis_server/tool/spec/generate_all.dart
index 39cd887..a29593d 100644
--- a/pkg/analysis_server/tool/spec/generate_all.dart
+++ b/pkg/analysis_server/tool/spec/generate_all.dart
@@ -8,6 +8,8 @@
 import 'package:path/path.dart';
 
 import 'codegen_analysis_server.dart' as codegen_analysis_server;
+import 'codegen_dart_notification_handler.dart'
+    as codegen_dart_notification_handler;
 import 'codegen_dart_protocol.dart' as codegen_dart_protocol;
 import 'codegen_inttest_methods.dart' as codegen_inttest_methods;
 import 'codegen_java_types.dart' as codegen_java_types;
@@ -30,6 +32,7 @@
 List<GeneratedContent> get allTargets {
   List<GeneratedContent> targets = <GeneratedContent>[];
   targets.add(codegen_analysis_server.target);
+  targets.add(codegen_dart_notification_handler.clientTarget());
   targets.add(codegen_dart_protocol.clientTarget(false));
   targets.add(codegen_dart_protocol.serverTarget(false));
   targets.add(codegen_java_types.targetDir);
diff --git a/pkg/analysis_server_client/CHANGELOG.md b/pkg/analysis_server_client/CHANGELOG.md
index 14d2f07..ef20851 100644
--- a/pkg/analysis_server_client/CHANGELOG.md
+++ b/pkg/analysis_server_client/CHANGELOG.md
@@ -1,5 +1,11 @@
-#1.0.1
-* Update path on homepage
+# 1.1.0
+ * Add analysis server protocol consts and classes
+ * Overhaul the Server class
+ * Add an example showing analysis of *.dart files in a directory
+ * Update the required SDK
 
-#1.0.0
-* Initial version
\ No newline at end of file
+# 1.0.1
+ * Update path on homepage
+
+# 1.0.0
+ * Initial version
diff --git a/pkg/analysis_server_client/README.md b/pkg/analysis_server_client/README.md
index 3351705..c4cc469 100644
--- a/pkg/analysis_server_client/README.md
+++ b/pkg/analysis_server_client/README.md
@@ -1,13 +1,22 @@
-# Analysis Server Client
+# analysis_server_client
 
-A client wrapper over Analysis Server. Instances of this client manages
-connection to Analysis Server and process and faciliates JSON protocol
-communication to and from the server. 
+analysis_server_client is a client wrapper over Analysis Server.
 
-Current implementation has no knowledge of the Analysis Server library yet.
-Future updates will allow for full class-access of Analysis Server protocol
-objects. 
+## Overview
 
-Analysis Server process must be instantiated separately and loaded into
-Analysis Server Client. To learn how to generate an Analysis Server Process,
-refer to the [Analysis Server page.](https://github.com/dart-lang/sdk/tree/master/pkg/analysis_server)
+ * Instances of [__Server__](lib/server.dart) manage a connection to an analysis server process,
+   and facilitate communication to and from the server.
+
+ * The [__Protocol__](lib/protocol.dart) library provides constants and classes
+   to build requests for the server and decode responses and notifications from the server.
+
+## Example
+
+The [example](example/example.dart) uses the [__Server__](lib/server.dart) to
+launch the analysis server, analyze all *.dart files in the specified directory,
+display the results, and shutdown the analysis server.
+
+## References
+
+For more about the analysis server, see the
+[Analysis Server page](https://github.com/dart-lang/sdk/tree/master/pkg/analysis_server).
diff --git a/pkg/analysis_server_client/example/example.dart b/pkg/analysis_server_client/example/example.dart
new file mode 100644
index 0000000..21573b4
--- /dev/null
+++ b/pkg/analysis_server_client/example/example.dart
@@ -0,0 +1,128 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io' show Directory, Platform, ProcessSignal, exit;
+
+import 'package:analysis_server_client/handler/notification_handler.dart';
+import 'package:analysis_server_client/handler/connection_handler.dart';
+import 'package:analysis_server_client/protocol.dart';
+import 'package:analysis_server_client/server.dart';
+import 'package:path/path.dart' as path;
+import 'package:pub_semver/pub_semver.dart';
+
+/// A simple application that uses the analysis server to analyze a package.
+main(List<String> args) async {
+  String target = await parseArgs(args);
+  print('Analyzing $target');
+
+  // Launch the server
+  Server server = new Server();
+  await server.start();
+
+  // Connect to the server
+  _Handler handler = new _Handler(server);
+  server.listenToOutput(notificationProcessor: handler.handleEvent);
+  if (!await handler.serverConnected(timeLimit: const Duration(seconds: 15))) {
+    exit(1);
+  }
+
+  // Request analysis
+  await server.send(SERVER_REQUEST_SET_SUBSCRIPTIONS,
+      new ServerSetSubscriptionsParams([ServerService.STATUS]).toJson());
+  await server.send(ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS,
+      new AnalysisSetAnalysisRootsParams([target], const []).toJson());
+
+  // Continue to watch for analysis until the user presses Ctrl-C
+  StreamSubscription<ProcessSignal> subscription;
+  subscription = ProcessSignal.sigint.watch().listen((_) async {
+    print('Exiting...');
+    subscription.cancel();
+    await server.stop();
+  });
+}
+
+class _Handler with NotificationHandler, ConnectionHandler {
+  final Server server;
+  int errorCount = 0;
+
+  _Handler(this.server);
+
+  @override
+  void onAnalysisErrors(AnalysisErrorsParams params) {
+    List<AnalysisError> errors = params.errors;
+    bool first = true;
+    for (AnalysisError error in errors) {
+      if (error.type.name == 'TODO') {
+        // Ignore these types of "errors"
+        continue;
+      }
+      if (first) {
+        first = false;
+        print('${params.file}:');
+      }
+      Location loc = error.location;
+      print('  ${error.message} • ${loc.startLine}:${loc.startColumn}');
+      ++errorCount;
+    }
+  }
+
+  @override
+  void onFailedToConnect() {
+    print('Failed to connect to server');
+  }
+
+  @override
+  void onProtocolNotSupported(Version version) {
+    print('Expected protocol version $PROTOCOL_VERSION, but found $version');
+  }
+
+  @override
+  void onServerError(ServerErrorParams params) {
+    if (params.isFatal) {
+      print('Fatal Server Error: ${params.message}');
+    } else {
+      print('Server Error: ${params.message}');
+    }
+    if (params.stackTrace != null) {
+      print(params.stackTrace);
+    }
+    super.onServerError(params);
+  }
+
+  @override
+  void onServerStatus(ServerStatusParams params) {
+    if (!params.analysis.isAnalyzing) {
+      // Whenever the server stops analyzing,
+      // print a brief summary of what issues have been found.
+      if (errorCount == 0) {
+        print('No issues found.');
+      } else {
+        print('Found ${errorCount} errors/warnings/hints');
+      }
+      errorCount = 0;
+      print('--------- ctrl-c to exit ---------');
+    }
+  }
+}
+
+Future<String> parseArgs(List<String> args) async {
+  if (args.length != 1) {
+    printUsageAndExit('Expected exactly one directory');
+  }
+  final dir = new Directory(path.normalize(path.absolute(args[0])));
+  if (!(await dir.exists())) {
+    printUsageAndExit('Could not find directory ${dir.path}');
+  }
+  return dir.path;
+}
+
+void printUsageAndExit(String errorMessage) {
+  print(errorMessage);
+  print('');
+  var appName = path.basename(Platform.script.toFilePath());
+  print('Usage: $appName <directory path>');
+  print('  Analyze the *.dart source files in <directory path>');
+  exit(1);
+}
diff --git a/pkg/analysis_server_client/lib/analysis_server_client.dart b/pkg/analysis_server_client/lib/analysis_server_client.dart
deleted file mode 100644
index 484397b..0000000
--- a/pkg/analysis_server_client/lib/analysis_server_client.dart
+++ /dev/null
@@ -1,101 +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 'dart:async';
-import 'dart:convert';
-import 'dart:io';
-
-/// Type of callbacks used to process notification.
-typedef void NotificationProcessor(String event, Map<String, Object> params);
-
-/// Instances of the class [AnalysisServerClient] manage a connection to an
-/// [AnalysisServer] process, and facilitate communication to and from the
-/// client/user.
-class AnalysisServerClient {
-  /// AnalysisServer process object, or null if the server has been shut down.
-  final Process _process;
-
-  /// Commands that have been sent to the server but not yet acknowledged,
-  /// and the [Completer] objects which should be completed when
-  /// acknowledgement is received.
-  final Map<String, Completer> _pendingCommands = <String, Completer>{};
-
-  /// Number which should be used to compute the 'id' to send to the next
-  /// command sent to the server.
-  int _nextId = 0;
-
-  AnalysisServerClient(this._process);
-
-  /// Return a future that will complete when all commands that have been
-  /// sent to the server so far have been flushed to the OS buffer.
-  Future<Null> flushCommands() {
-    return _process.stdin.flush();
-  }
-
-  /// Force kill the server. Returns exit code future.
-  Future<int> kill() {
-    _process.kill();
-    return _process.exitCode;
-  }
-
-  void listenToOutput({NotificationProcessor notificationProcessor}) {
-    _process.stdout
-        .transform((new Utf8Codec()).decoder)
-        .transform(new LineSplitter())
-        .listen((String line) {
-      String trimmedLine = line.trim();
-      if (trimmedLine.startsWith('Observatory listening on ')) {
-        return;
-      }
-      final result = json.decoder.convert(trimmedLine) as Map;
-      if (result.containsKey('id')) {
-        final id = result['id'] as String;
-        final completer = _pendingCommands.remove(id);
-
-        if (result.containsKey('error')) {
-          completer.completeError(new ServerErrorMessage(result['error']));
-        } else {
-          completer.complete(result['result']);
-        }
-      } else if (notificationProcessor != null && result.containsKey('event')) {
-        // Message is a notification. It should have an event and possibly
-        // params.
-        notificationProcessor(result['event'], result['params']);
-      }
-    });
-  }
-
-  /// Sends a command to the server. An 'id' will be automatically assigned.
-  /// The returned [Future] will be completed when the server acknowledges
-  /// the command with a response. If the server acknowledges the command
-  /// with a normal (non-error) response, the future will be completed
-  /// with the 'result' field from the response. If the server acknowledges
-  /// the command with an error response, the future will be completed with an
-  /// error.
-  Future send(String method, Map<String, dynamic> params) {
-    String id = '${_nextId++}';
-    Map<String, dynamic> command = <String, dynamic>{
-      'id': id,
-      'method': method
-    };
-    if (params != null) {
-      command['params'] = params;
-    }
-    Completer completer = new Completer();
-    _pendingCommands[id] = completer;
-    String commandAsJson = json.encode(command);
-    _process.stdin.add(utf8.encoder.convert('$commandAsJson\n'));
-    return completer.future;
-  }
-}
-
-class ServerErrorMessage {
-  final Map errorJson;
-
-  ServerErrorMessage(this.errorJson);
-
-  String get code => errorJson['code'].toString();
-  String get message => errorJson['message'];
-  String get stackTrace => errorJson['stackTrace'];
-}
diff --git a/pkg/analysis_server_client/lib/handler/connection_handler.dart b/pkg/analysis_server_client/lib/handler/connection_handler.dart
new file mode 100644
index 0000000..29be0a1
--- /dev/null
+++ b/pkg/analysis_server_client/lib/handler/connection_handler.dart
@@ -0,0 +1,67 @@
+// 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.
+//
+// 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".
+
+import 'dart:async';
+
+import 'package:analysis_server_client/protocol.dart';
+import 'package:analysis_server_client/handler/notification_handler.dart';
+import 'package:analysis_server_client/server.dart';
+import 'package:pub_semver/pub_semver.dart';
+
+/// [ConnectionHandler] listens to analysis server notifications
+/// and detects when a connection has been established with the server.
+///
+/// Clients may override [onFailedToConnect], [onProtocolNotSupported],
+/// and [onServerError] to display connection failure information.
+///
+/// Clients may mix-in this class, but may not extend or implement it.
+mixin ConnectionHandler implements NotificationHandler {
+  Completer<bool> _connected = new Completer();
+
+  /// Clients should implement this method to return the server being managed.
+  /// This mixin will stop the server process if a connection cannot be
+  /// established or if a server error occurs after connecting.
+  Server get server;
+
+  void onFailedToConnect() {}
+
+  void onProtocolNotSupported(Version version) {}
+
+  @override
+  void onServerConnected(ServerConnectedParams params) {
+    final minVersion = new Version.parse(PROTOCOL_VERSION);
+    final maxVersion = minVersion.nextBreaking;
+    final version = new Version.parse(params.version);
+    if (minVersion <= version && version < maxVersion) {
+      _connected.complete(true);
+    } else {
+      onProtocolNotSupported(version);
+      _connected.complete(false);
+      server.stop();
+    }
+  }
+
+  @override
+  void onServerError(ServerErrorParams params) {
+    server.stop();
+  }
+
+  /// Return a future that completes with a `bool` indicating whether
+  /// a connection was successfully established with the server.
+  Future<bool> serverConnected({Duration timeLimit}) {
+    Future<bool> future = _connected.future;
+    if (timeLimit != null) {
+      future = future.timeout(timeLimit, onTimeout: () {
+        onFailedToConnect();
+        server.stop();
+        return false;
+      });
+    }
+    return future;
+  }
+}
diff --git a/pkg/analysis_server_client/lib/handler/notification_handler.dart b/pkg/analysis_server_client/lib/handler/notification_handler.dart
new file mode 100644
index 0000000..8bdbf14
--- /dev/null
+++ b/pkg/analysis_server_client/lib/handler/notification_handler.dart
@@ -0,0 +1,270 @@
+// 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.
+//
+// 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".
+
+import 'package:analysis_server_client/protocol.dart';
+
+/// [NotificationHandler] processes analysis server notifications
+/// and dispatches those notifications to different methods based upon
+/// the type of notification. Clients may override
+/// any of the "on<EventName>" methods that are of interest.
+///
+/// Clients may mix-in this class, but may not implement it.
+mixin NotificationHandler {
+  void handleEvent(Notification notification) {
+    Map<String, Object> params = notification.params;
+    ResponseDecoder decoder = new ResponseDecoder(null);
+    switch (notification.event) {
+      case ANALYSIS_NOTIFICATION_ANALYZED_FILES:
+        onAnalysisAnalyzedFiles(new AnalysisAnalyzedFilesParams.fromJson(
+            decoder, 'params', params));
+        break;
+      case ANALYSIS_NOTIFICATION_CLOSING_LABELS:
+        onAnalysisClosingLabels(new AnalysisClosingLabelsParams.fromJson(
+            decoder, 'params', params));
+        break;
+      case ANALYSIS_NOTIFICATION_ERRORS:
+        onAnalysisErrors(
+            new AnalysisErrorsParams.fromJson(decoder, 'params', params));
+        break;
+      case ANALYSIS_NOTIFICATION_FLUSH_RESULTS:
+        onAnalysisFlushResults(
+            new AnalysisFlushResultsParams.fromJson(decoder, 'params', params));
+        break;
+      case ANALYSIS_NOTIFICATION_FOLDING:
+        onAnalysisFolding(
+            new AnalysisFoldingParams.fromJson(decoder, 'params', params));
+        break;
+      case ANALYSIS_NOTIFICATION_HIGHLIGHTS:
+        onAnalysisHighlights(
+            new AnalysisHighlightsParams.fromJson(decoder, 'params', params));
+        break;
+      case ANALYSIS_NOTIFICATION_IMPLEMENTED:
+        onAnalysisImplemented(
+            new AnalysisImplementedParams.fromJson(decoder, 'params', params));
+        break;
+      case ANALYSIS_NOTIFICATION_INVALIDATE:
+        onAnalysisInvalidate(
+            new AnalysisInvalidateParams.fromJson(decoder, 'params', params));
+        break;
+      case ANALYSIS_NOTIFICATION_NAVIGATION:
+        onAnalysisNavigation(
+            new AnalysisNavigationParams.fromJson(decoder, 'params', params));
+        break;
+      case ANALYSIS_NOTIFICATION_OCCURRENCES:
+        onAnalysisOccurrences(
+            new AnalysisOccurrencesParams.fromJson(decoder, 'params', params));
+        break;
+      case ANALYSIS_NOTIFICATION_OUTLINE:
+        onAnalysisOutline(
+            new AnalysisOutlineParams.fromJson(decoder, 'params', params));
+        break;
+      case ANALYSIS_NOTIFICATION_OVERRIDES:
+        onAnalysisOverrides(
+            new AnalysisOverridesParams.fromJson(decoder, 'params', params));
+        break;
+      case COMPLETION_NOTIFICATION_RESULTS:
+        onCompletionResults(
+            new CompletionResultsParams.fromJson(decoder, 'params', params));
+        break;
+      case EXECUTION_NOTIFICATION_LAUNCH_DATA:
+        onExecutionLaunchData(
+            new ExecutionLaunchDataParams.fromJson(decoder, 'params', params));
+        break;
+      case FLUTTER_NOTIFICATION_OUTLINE:
+        onFlutterOutline(
+            new FlutterOutlineParams.fromJson(decoder, 'params', params));
+        break;
+      case SEARCH_NOTIFICATION_RESULTS:
+        onSearchResults(
+            new SearchResultsParams.fromJson(decoder, 'params', params));
+        break;
+      case SERVER_NOTIFICATION_CONNECTED:
+        onServerConnected(
+            new ServerConnectedParams.fromJson(decoder, 'params', params));
+        break;
+      case SERVER_NOTIFICATION_ERROR:
+        onServerError(
+            new ServerErrorParams.fromJson(decoder, 'params', params));
+        break;
+      case SERVER_NOTIFICATION_STATUS:
+        onServerStatus(
+            new ServerStatusParams.fromJson(decoder, 'params', params));
+        break;
+      default:
+        onUnknownNotification(notification.event, params);
+        break;
+    }
+  }
+
+  /// Reports the paths of the files that are being analyzed.
+  ///
+  /// This notification is not subscribed to by default. Clients can
+  /// subscribe by including the value "ANALYZED_FILES" in the list
+  /// of services passed in an analysis.setGeneralSubscriptions request.
+  void onAnalysisAnalyzedFiles(AnalysisAnalyzedFilesParams params) {}
+
+  /// Reports closing labels relevant to a given file.
+  ///
+  /// This notification is not subscribed to by default. Clients
+  /// can subscribe by including the value "CLOSING_LABELS"
+  /// in the list of services passed in an
+  /// analysis.setSubscriptions request.
+  void onAnalysisClosingLabels(AnalysisClosingLabelsParams params) {}
+
+  /// Reports the errors associated with a given file. The set of
+  /// errors included in the notification is always a complete
+  /// list that supersedes any previously reported errors.
+  void onAnalysisErrors(AnalysisErrorsParams params) {}
+
+  /// Reports that any analysis results that were previously
+  /// associated with the given files should be considered to be
+  /// invalid because those files are no longer being analyzed,
+  /// either because the analysis root that contained it is no
+  /// longer being analyzed or because the file no longer exists.
+  ///
+  /// If a file is included in this notification and at some later
+  /// time a notification with results for the file is received,
+  /// clients should assume that the file is once again being
+  /// analyzed and the information should be processed.
+  ///
+  /// It is not possible to subscribe to or unsubscribe from this
+  /// notification.
+  void onAnalysisFlushResults(AnalysisFlushResultsParams params) {}
+
+  /// Reports the folding regions associated with a given
+  /// file. Folding regions can be nested, but will not be
+  /// overlapping. Nesting occurs when a foldable element, such as
+  /// a method, is nested inside another foldable element such as
+  /// a class.
+  ///
+  /// This notification is not subscribed to by default. Clients
+  /// can subscribe by including the value "FOLDING" in
+  /// the list of services passed in an analysis.setSubscriptions
+  /// request.
+  void onAnalysisFolding(AnalysisFoldingParams params) {}
+
+  /// Reports the highlight regions associated with a given file.
+  ///
+  /// This notification is not subscribed to by default. Clients
+  /// can subscribe by including the value "HIGHLIGHTS"
+  /// in the list of services passed in an
+  /// analysis.setSubscriptions request.
+  void onAnalysisHighlights(AnalysisHighlightsParams params) {}
+
+  /// Reports the classes that are implemented or extended and
+  /// class members that are implemented or overridden in a file.
+  ///
+  /// This notification is not subscribed to by default. Clients
+  /// can subscribe by including the value "IMPLEMENTED" in
+  /// the list of services passed in an analysis.setSubscriptions
+  /// request.
+  void onAnalysisImplemented(AnalysisImplementedParams params) {}
+
+  /// Reports that the navigation information associated with a region of a
+  /// single file has become invalid and should be re-requested.
+  ///
+  /// This notification is not subscribed to by default. Clients can
+  /// subscribe by including the value "INVALIDATE" in the list of
+  /// services passed in an analysis.setSubscriptions request.
+  void onAnalysisInvalidate(AnalysisInvalidateParams params) {}
+
+  /// Reports the navigation targets associated with a given file.
+  ///
+  /// This notification is not subscribed to by default. Clients
+  /// can subscribe by including the value "NAVIGATION"
+  /// in the list of services passed in an
+  /// analysis.setSubscriptions request.
+  void onAnalysisNavigation(AnalysisNavigationParams params) {}
+
+  /// Reports the occurrences of references to elements within a
+  /// single file.
+  ///
+  /// This notification is not subscribed to by default. Clients
+  /// can subscribe by including the value "OCCURRENCES"
+  /// in the list of services passed in an
+  /// analysis.setSubscriptions request.
+  void onAnalysisOccurrences(AnalysisOccurrencesParams params) {}
+
+  /// Reports the outline associated with a single file.
+  ///
+  /// This notification is not subscribed to by default. Clients
+  /// can subscribe by including the value "OUTLINE" in
+  /// the list of services passed in an analysis.setSubscriptions
+  /// request.
+  void onAnalysisOutline(AnalysisOutlineParams params) {}
+
+  /// Reports the overriding members in a file.
+  ///
+  /// This notification is not subscribed to by default. Clients
+  /// can subscribe by including the value "OVERRIDES" in
+  /// the list of services passed in an analysis.setSubscriptions
+  /// request.
+  void onAnalysisOverrides(AnalysisOverridesParams 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
+  /// previously reported suggestions.
+  void onCompletionResults(CompletionResultsParams params) {}
+
+  /// Reports information needed to allow a single file to be launched.
+  ///
+  /// This notification is not subscribed to by default. Clients can
+  /// subscribe by including the value "LAUNCH_DATA" in the list of services
+  /// passed in an execution.setSubscriptions request.
+  void onExecutionLaunchData(ExecutionLaunchDataParams params) {}
+
+  /// Reports the Flutter outline associated with a single file.
+  ///
+  /// This notification is not subscribed to by default. Clients
+  /// can subscribe by including the value "OUTLINE" in
+  /// the list of services passed in an flutter.setSubscriptions
+  /// request.
+  void onFlutterOutline(FlutterOutlineParams params) {}
+
+  /// Reports some or all of the results of performing a requested
+  /// search. Unlike other notifications, this notification
+  /// contains search results that should be added to any
+  /// previously received search results associated with the same
+  /// search id.
+  void onSearchResults(SearchResultsParams params) {}
+
+  /// Reports that the server is running. This notification is
+  /// issued once after the server has started running but before
+  /// any requests are processed to let the client know that it
+  /// started correctly.
+  ///
+  /// It is not possible to subscribe to or unsubscribe from this
+  /// notification.
+  void onServerConnected(ServerConnectedParams params) {}
+
+  /// Reports that an unexpected error has occurred while
+  /// executing the server. This notification is not used for
+  /// problems with specific requests (which are returned as part
+  /// of the response) but is used for exceptions that occur while
+  /// performing other tasks, such as analysis or preparing
+  /// notifications.
+  ///
+  /// It is not possible to subscribe to or unsubscribe from this
+  /// notification.
+  void onServerError(ServerErrorParams params) {}
+
+  /// Reports the current status of the server. Parameters are
+  /// omitted if there has been no change in the status
+  /// represented by that parameter.
+  ///
+  /// This notification is not subscribed to by default. Clients
+  /// can subscribe by including the value "STATUS" in
+  /// the list of services passed in a server.setSubscriptions
+  /// request.
+  void onServerStatus(ServerStatusParams params) {}
+
+  /// Reports a notification that is not processed
+  /// by any other notification handlers.
+  void onUnknownNotification(String event, params) {}
+}
diff --git a/pkg/analysis_server_client/lib/listener/server_listener.dart b/pkg/analysis_server_client/lib/listener/server_listener.dart
new file mode 100644
index 0000000..3f1b074
--- /dev/null
+++ b/pkg/analysis_server_client/lib/listener/server_listener.dart
@@ -0,0 +1,61 @@
+// 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.
+
+/// Instances of the class [ServerListener] receive information from [Server]
+/// about interactions with the server.
+///
+/// Clients may mix-in this class, but may not implement it.
+mixin ServerListener {
+  /// Called when the [Server] could not decode a message.
+  void badMessage(String trimmedLine, exception) {
+    log('JSON decode failure', '$exception');
+  }
+
+  /// Called when the [Server] receives a line on stderr.
+  void errorMessage(String line) {
+    log('ERR:', line);
+  }
+
+  /// Called when the [Server] is terminating the server process
+  /// rather than requesting that the server stop itself.
+  void killingServerProcess(String reason) {
+    log('FORCIBLY TERMINATING SERVER: ', reason);
+  }
+
+  /// Log a message about interaction with the server.
+  void log(String prefix, String details);
+
+  /// Called when the [Server] received a response or notification.
+  void messageReceived(String json) {
+    log('<== ', json);
+  }
+
+  /// Called when the [Server] sends a request.
+  void requestSent(String json) {
+    log('==> ', json);
+  }
+
+  /// Called when the [Server] starts the server process.
+  void startingServer(String dartBinary, List<String> arguments) {
+    log('Starting analysis server:', '$dartBinary ${arguments.join(' ')}');
+  }
+
+  /// Called when the [Server] receives an unexpected message
+  /// which is not a notification or response.
+  void unexpectedMessage(Map<String, dynamic> message) {
+    log('Unexpected message from server:', '$message');
+  }
+
+  /// Called when the [Server] recieved an unexpected response
+  /// where the [id] does not match the [id] of an outstanding request.
+  void unexpectedResponse(Map<String, dynamic> message, id) {
+    log('Unexpected response from server', 'id=$id');
+  }
+
+  /// Called when the server process unexpectedly exits
+  /// with a non-zero exit code.
+  void unexpectedStop(int exitCode) {
+    log('Server terminated with exit code', '$exitCode');
+  }
+}
diff --git a/pkg/analysis_server_client/lib/server.dart b/pkg/analysis_server_client/lib/server.dart
new file mode 100644
index 0000000..32b0c04
--- /dev/null
+++ b/pkg/analysis_server_client/lib/server.dart
@@ -0,0 +1,278 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:analysis_server_client/listener/server_listener.dart';
+import 'package:analysis_server_client/protocol.dart';
+import 'package:path/path.dart';
+
+/// Type of callbacks used to process notifications.
+typedef void NotificationProcessor(Notification notification);
+
+/// Instances of the class [Server] manage a server process,
+/// and facilitate communication to and from the server.
+///
+/// Clients may not extend, implement or mix-in this class.
+class Server {
+  /// If not `null`, [_listener] will be sent information
+  /// about interactions with the server.
+  ServerListener _listener;
+
+  /// Server process object, or `null` if server hasn't been started yet
+  /// or if the server has already been stopped.
+  Process _process;
+
+  /// Commands that have been sent to the server but not yet acknowledged,
+  /// and the [Completer] objects which should be completed
+  /// when acknowledgement is received.
+  final _pendingCommands = <String, Completer<Map<String, dynamic>>>{};
+
+  /// Number which should be used to compute the 'id'
+  /// to send in the next command sent to the server.
+  int _nextId = 0;
+
+  /// The stderr subscription or `null` if either
+  /// [listenToOutput] has not been called or [stop] has been called.
+  StreamSubscription<String> _stderrSubscription;
+
+  /// The stdout subscription or `null` if either
+  /// [listenToOutput] has not been called or [stop] has been called.
+  StreamSubscription<String> _stdoutSubscription;
+
+  Server({ServerListener listener, Process process})
+      : this._listener = listener,
+        this._process = process;
+
+  /// Force kill the server. Returns exit code future.
+  Future<int> kill({String reason = 'none'}) {
+    _listener?.killingServerProcess(reason);
+    final process = _process;
+    _process = null;
+    process.kill();
+    return process.exitCode;
+  }
+
+  /// Start listening to output from the server,
+  /// and deliver notifications to [notificationProcessor].
+  void listenToOutput({NotificationProcessor notificationProcessor}) {
+    _stdoutSubscription = _process.stdout
+        .transform(utf8.decoder)
+        .transform(new LineSplitter())
+        .listen((String line) {
+      String trimmedLine = line.trim();
+
+      // Guard against lines like:
+      //   {"event":"server.connected","params":{...}}Observatory listening on ...
+      const observatoryMessage = 'Observatory listening on ';
+      if (trimmedLine.contains(observatoryMessage)) {
+        trimmedLine = trimmedLine
+            .substring(0, trimmedLine.indexOf(observatoryMessage))
+            .trim();
+      }
+      if (trimmedLine.isEmpty) {
+        return;
+      }
+
+      _listener?.messageReceived(trimmedLine);
+      Map<String, dynamic> message;
+      try {
+        message = json.decoder.convert(trimmedLine);
+      } catch (exception) {
+        _listener?.badMessage(trimmedLine, exception);
+        return;
+      }
+
+      final id = message[Response.ID];
+      if (id != null) {
+        // Handle response
+        final completer = _pendingCommands.remove(id);
+        if (completer == null) {
+          _listener?.unexpectedResponse(message, id);
+        }
+        if (message.containsKey(Response.ERROR)) {
+          completer.completeError(new RequestError.fromJson(
+              new ResponseDecoder(null), '.error', message[Response.ERROR]));
+        } else {
+          completer.complete(message[Response.RESULT]);
+        }
+      } else {
+        // Handle notification
+        final String event = message[Notification.EVENT];
+        if (event != null) {
+          if (notificationProcessor != null) {
+            notificationProcessor(
+                new Notification(event, message[Notification.PARAMS]));
+          }
+        } else {
+          _listener?.unexpectedMessage(message);
+        }
+      }
+    });
+    _stderrSubscription = _process.stderr
+        .transform(utf8.decoder)
+        .transform(new LineSplitter())
+        .listen((String line) {
+      String trimmedLine = line.trim();
+      _listener?.errorMessage(trimmedLine);
+    });
+  }
+
+  /// Send a command to the server. An 'id' will be automatically assigned.
+  /// The returned [Future] will be completed when the server acknowledges
+  /// the command with a response.
+  /// If the server acknowledges the command with a normal (non-error) response,
+  /// the future will be completed with the 'result' field from the response.
+  /// If the server acknowledges the command with an error response,
+  /// the future will be completed with an error.
+  Future<Map<String, dynamic>> send(
+      String method, Map<String, dynamic> params) {
+    String id = '${_nextId++}';
+    Map<String, dynamic> command = <String, dynamic>{
+      Request.ID: id,
+      Request.METHOD: method
+    };
+    if (params != null) {
+      command[Request.PARAMS] = params;
+    }
+    final completer = new Completer<Map<String, dynamic>>();
+    _pendingCommands[id] = completer;
+    String line = json.encode(command);
+    _listener?.requestSent(line);
+    _process.stdin.add(utf8.encoder.convert("$line\n"));
+    return completer.future;
+  }
+
+  /// Start the server.
+  ///
+  /// If [profileServer] is `true`, the server will be started
+  /// with "--observe" and "--pause-isolates-on-exit", allowing the observatory
+  /// to be used.
+  ///
+  /// If [serverPath] is specified, then that analysis server will be launched,
+  /// otherwise the analysis server snapshot in the SDK will be launched.
+  Future start({
+    String clientId,
+    String clientVersion,
+    int diagnosticPort,
+    String instrumentationLogFile,
+    bool profileServer: false,
+    String sdkPath,
+    String serverPath,
+    int servicesPort,
+    bool suppressAnalytics: true,
+    bool useAnalysisHighlight2: false,
+  }) async {
+    if (_process != null) {
+      throw new Exception('Process already started');
+    }
+    String dartBinary = Platform.executable;
+
+    // The integration tests run 3x faster when run from snapshots
+    // (you need to run test.py with --use-sdk).
+    if (serverPath == null) {
+      // Look for snapshots/analysis_server.dart.snapshot.
+      serverPath = normalize(join(dirname(Platform.resolvedExecutable),
+          'snapshots', 'analysis_server.dart.snapshot'));
+
+      if (!FileSystemEntity.isFileSync(serverPath)) {
+        // Look for dart-sdk/bin/snapshots/analysis_server.dart.snapshot.
+        serverPath = normalize(join(dirname(Platform.resolvedExecutable),
+            'dart-sdk', 'bin', 'snapshots', 'analysis_server.dart.snapshot'));
+      }
+    }
+
+    List<String> arguments = [];
+    //
+    // Add VM arguments.
+    //
+    if (profileServer) {
+      if (servicesPort == null) {
+        arguments.add('--observe');
+      } else {
+        arguments.add('--observe=$servicesPort');
+      }
+      arguments.add('--pause-isolates-on-exit');
+    } else if (servicesPort != null) {
+      arguments.add('--enable-vm-service=$servicesPort');
+    }
+    if (Platform.packageConfig != null) {
+      arguments.add('--packages=${Platform.packageConfig}');
+    }
+    //
+    // Add the server executable.
+    //
+    arguments.add(serverPath);
+    //
+    // Add server arguments.
+    //
+    // TODO(danrubel): Consider moving all cmdline argument consts
+    // out of analysis_server and into analysis_server_client
+    if (clientId != null) {
+      arguments.add('--client-id');
+      arguments.add(clientId);
+    }
+    if (clientVersion != null) {
+      arguments.add('--client-version');
+      arguments.add(clientVersion);
+    }
+    if (suppressAnalytics) {
+      arguments.add('--suppress-analytics');
+    }
+    if (diagnosticPort != null) {
+      arguments.add('--port');
+      arguments.add(diagnosticPort.toString());
+    }
+    if (instrumentationLogFile != null) {
+      arguments.add('--instrumentation-log-file=$instrumentationLogFile');
+    }
+    if (sdkPath != null) {
+      arguments.add('--sdk=$sdkPath');
+    }
+    if (useAnalysisHighlight2) {
+      arguments.add('--useAnalysisHighlight2');
+    }
+    _listener?.startingServer(dartBinary, arguments);
+    _process = await Process.start(dartBinary, arguments);
+    _process.exitCode.then((int code) {
+      if (code != 0 && _process != null) {
+        // Report an error if server abruptly terminated
+        _listener?.unexpectedStop(code);
+      }
+    });
+  }
+
+  /// Attempt to gracefully shutdown the server.
+  /// If that fails, then kill the process.
+  Future<int> stop({Duration timeLimit}) async {
+    timeLimit ??= const Duration(seconds: 5);
+    if (_process == null) {
+      // Process already exited
+      return -1;
+    }
+    final future = send(SERVER_REQUEST_SHUTDOWN, null);
+    final process = _process;
+    _process = null;
+    await future
+        // fall through to wait for exit
+        .timeout(timeLimit, onTimeout: () {
+      return null;
+    }).whenComplete(() async {
+      await _stderrSubscription?.cancel();
+      _stderrSubscription = null;
+      await _stdoutSubscription?.cancel();
+      _stdoutSubscription = null;
+    });
+    return process.exitCode.timeout(
+      timeLimit,
+      onTimeout: () {
+        _listener?.killingServerProcess('server failed to exit');
+        process.kill();
+        return process.exitCode;
+      },
+    );
+  }
+}
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_base.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_base.dart
index 040972f..320bc4d 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_base.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_base.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
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 1280460..38d52a9 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -6,6 +6,8 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
+const String PROTOCOL_VERSION = '1.21.1';
+
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
 const String ANALYSIS_NOTIFICATION_CLOSING_LABELS = 'analysis.closingLabels';
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_internal.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_internal.dart
index 95d5663..c95e384 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_internal.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_internal.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_util.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_util.dart
index dab28db..bdce37f 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_util.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_util.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
diff --git a/pkg/analysis_server_client/pubspec.yaml b/pkg/analysis_server_client/pubspec.yaml
index 51661db..6b11339 100644
--- a/pkg/analysis_server_client/pubspec.yaml
+++ b/pkg/analysis_server_client/pubspec.yaml
@@ -1,12 +1,15 @@
 name: analysis_server_client
-version: 1.0.1
+version: 1.1.0
 author: Dart Team <misc@dartlang.org>
 description:
-  A client wrapper over analysis_server. Instances of this client
-  manage a connection to the analysis_server process and
-  facilitates communication to and from the server.
-homepage: http://github.com/dart-lang/sdk/pkg/analysis_server_client
+  A client wrapper over analysis_server.
+  Instances of the class [Server] manage a connection to a server process,
+  and facilitate communication to and from the server.
+homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analysis_server_client
+environment:
+  sdk: '>=2.1.0-dev.9.0 <3.0.0'
+dependencies:
+  path: ^1.6.2
+  pub_semver: ^1.4.2
 dev_dependencies:
   test: ^1.3.4
-environment:
-  sdk: ">=1.0.0 < 2.0.0-dev.infinity"
diff --git a/pkg/analysis_server_client/test/all.dart b/pkg/analysis_server_client/test/all.dart
new file mode 100644
index 0000000..ceede33
--- /dev/null
+++ b/pkg/analysis_server_client/test/all.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'live_test.dart' as live_test;
+import 'server_test.dart' as server_test;
+
+main() {
+  server_test.main();
+  live_test.main();
+}
diff --git a/pkg/analysis_server_client/test/analysis_server_client_test.dart b/pkg/analysis_server_client/test/analysis_server_client_test.dart
deleted file mode 100644
index c07ea61..0000000
--- a/pkg/analysis_server_client/test/analysis_server_client_test.dart
+++ /dev/null
@@ -1,144 +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 'dart:async';
-import 'dart:convert';
-import 'dart:io';
-
-import 'package:analysis_server_client/analysis_server_client.dart';
-import 'package:test/test.dart';
-
-void main() {
-  MockProcess process;
-  AnalysisServerClient serverWrapper;
-
-  setUp(() async {
-    process = new MockProcess();
-    serverWrapper = new AnalysisServerClient(process);
-  });
-
-  test('test_listenToOutput_good', () async {
-    process.stdout = _goodMessage();
-
-    final future = serverWrapper.send('blahMethod', null);
-    serverWrapper.listenToOutput();
-
-    final response = await future;
-    expect(response, const TypeMatcher<Map>());
-    final responseAsMap = response as Map;
-    expect(responseAsMap['foo'], 'bar');
-  });
-
-  test('test_listenToOutput_error', () async {
-    process.stdout = _badMessage();
-    final future = serverWrapper.send('blahMethod', null);
-    future.catchError((e) {
-      expect(e, const TypeMatcher<ServerErrorMessage>());
-      final e2 = e as ServerErrorMessage;
-      expect(e2.code, 'someErrorCode');
-      expect(e2.message, 'something went wrong');
-      expect(e2.stackTrace, 'some long stack trace');
-    });
-    serverWrapper.listenToOutput();
-  });
-
-  test('test_listenToOutput_event', () async {
-    process.stdout = _eventMessage();
-
-    void eventHandler(String event, Map<String, Object> params) {
-      expect(event, 'fooEvent');
-      expect(params.length, 2);
-      expect(params['foo'] as String, 'bar');
-      expect(params['baz'] as String, 'bang');
-    }
-
-    serverWrapper.send('blahMethod', null);
-    serverWrapper.listenToOutput(notificationProcessor: eventHandler);
-  });
-}
-
-final _badErrorMessage = {
-  'code': 'someErrorCode',
-  'message': 'something went wrong',
-  'stackTrace': 'some long stack trace'
-};
-
-Stream<List<int>> _badMessage() async* {
-  yield utf8.encoder.convert('Observatory listening on foo bar\n');
-  final sampleJson = {'id': '0', 'error': _badErrorMessage};
-  yield utf8.encoder.convert(json.encode(sampleJson));
-}
-
-Stream<List<int>> _eventMessage() async* {
-  yield utf8.encoder.convert('Observatory listening on foo bar\n');
-  final sampleJson = {
-    'event': 'fooEvent',
-    'params': {'foo': 'bar', 'baz': 'bang'}
-  };
-  yield utf8.encoder.convert(json.encode(sampleJson));
-}
-
-Stream<List<int>> _goodMessage() async* {
-  yield utf8.encoder.convert('Observatory listening on foo bar\n');
-  final sampleJson = {
-    'id': '0',
-    'result': {'foo': 'bar'}
-  };
-  yield utf8.encoder.convert(json.encode(sampleJson));
-}
-
-class MockProcess implements Process {
-  @override
-  Stream<List<int>> stderr;
-
-  @override
-  IOSink stdin = new MockStdin();
-
-  @override
-  Stream<List<int>> stdout;
-
-  @override
-  Future<int> get exitCode => null;
-
-  @override
-  int get pid => null;
-
-  @override
-  bool kill([ProcessSignal signal = ProcessSignal.sigterm]) => null;
-}
-
-class MockStdin implements IOSink {
-  @override
-  Encoding encoding;
-
-  @override
-  Future get done => null;
-
-  @override
-  void add(List<int> data) {}
-
-  @override
-  void addError(Object error, [StackTrace stackTrace]) {}
-
-  @override
-  Future addStream(Stream<List<int>> stream) => null;
-
-  @override
-  Future close() => null;
-
-  @override
-  Future flush() => null;
-
-  @override
-  void write(Object obj) {}
-
-  @override
-  void writeAll(Iterable objects, [String separator = ""]) {}
-
-  @override
-  void writeCharCode(int charCode) {}
-
-  @override
-  void writeln([Object obj = ""]) {}
-}
diff --git a/pkg/analysis_server_client/test/live_test.dart b/pkg/analysis_server_client/test/live_test.dart
new file mode 100644
index 0000000..5d73c8d
--- /dev/null
+++ b/pkg/analysis_server_client/test/live_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server_client/listener/server_listener.dart';
+import 'package:analysis_server_client/handler/notification_handler.dart';
+import 'package:analysis_server_client/handler/connection_handler.dart';
+import 'package:analysis_server_client/protocol.dart';
+import 'package:analysis_server_client/server.dart';
+import 'package:test/test.dart';
+
+const _debug = false;
+
+void main() {
+  test('live', () async {
+    final server = new Server(listener: _debug ? new TestListener() : null);
+    await server.start(clientId: 'test', suppressAnalytics: true);
+
+    TestHandler handler = new TestHandler(server);
+    server.listenToOutput(notificationProcessor: handler.handleEvent);
+    if (!await handler.serverConnected(
+        timeLimit: const Duration(seconds: 15))) {
+      fail('failed to connect to server');
+    }
+
+    Map<String, dynamic> json = await server.send(
+        SERVER_REQUEST_GET_VERSION, new ServerGetVersionParams().toJson());
+    final result = ServerGetVersionResult.fromJson(
+        new ResponseDecoder(null), 'result', json);
+    await server.stop();
+
+    expect(result.version, isNotEmpty);
+  });
+}
+
+class TestHandler with NotificationHandler, ConnectionHandler {
+  final Server server;
+
+  TestHandler(this.server);
+}
+
+class TestListener with ServerListener {
+  @override
+  void log(String prefix, String details) {
+    print('$prefix $details');
+  }
+}
diff --git a/pkg/analysis_server_client/test/server_test.dart b/pkg/analysis_server_client/test/server_test.dart
new file mode 100644
index 0000000..9f3d643
--- /dev/null
+++ b/pkg/analysis_server_client/test/server_test.dart
@@ -0,0 +1,208 @@
+// 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 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:analysis_server_client/server.dart';
+import 'package:analysis_server_client/protocol.dart';
+import 'package:test/test.dart';
+
+void main() {
+  MockProcess process;
+  Server server;
+
+  setUp(() async {
+    process = new MockProcess();
+    server = new Server(process: process);
+  });
+
+  group('listenToOutput', () {
+    test('good', () async {
+      process.stdout = _goodMessage();
+      process.stderr = _noMessage();
+
+      final future = server.send('blahMethod', null);
+      server.listenToOutput();
+
+      final response = await future;
+      expect(response['foo'], 'bar');
+    });
+
+    test('error', () async {
+      process.stdout = _badMessage();
+      process.stderr = _noMessage();
+
+      final future = server.send('blahMethod', null);
+      future.catchError((e) {
+        expect(e, const TypeMatcher<RequestError>());
+        final error = e as RequestError;
+        expect(error.code, RequestErrorCode.UNKNOWN_REQUEST);
+        expect(error.message, 'something went wrong');
+        expect(error.stackTrace, 'some long stack trace');
+      });
+      server.listenToOutput();
+    });
+
+    test('event', () async {
+      process.stdout = _eventMessage();
+      process.stderr = _noMessage();
+
+      final completer = new Completer();
+      void eventHandler(Notification notification) {
+        expect(notification.event, 'fooEvent');
+        expect(notification.params.length, 2);
+        expect(notification.params['foo'] as String, 'bar');
+        expect(notification.params['baz'] as String, 'bang');
+        completer.complete();
+      }
+
+      server.send('blahMethod', null);
+      server.listenToOutput(notificationProcessor: eventHandler);
+      await completer.future;
+    });
+  });
+
+  group('stop', () {
+    test('ok', () async {
+      final mockout = new StreamController<List<int>>();
+      process.stdout = mockout.stream;
+      process.stderr = _noMessage();
+      process.mockin.controller.stream.first.then((_) {
+        String encoded = json.encode({'id': '0'});
+        mockout.add(utf8.encoder.convert('$encoded\n'));
+      });
+      process.exitCode = new Future.value(0);
+
+      server.listenToOutput();
+      await server.stop(timeLimit: const Duration(milliseconds: 1));
+      expect(process.killed, isFalse);
+    });
+    test('stopped', () async {
+      final mockout = new StreamController<List<int>>();
+      process.stdout = mockout.stream;
+      process.stderr = _noMessage();
+      process.exitCode = new Future.value(0);
+
+      server.listenToOutput();
+      await server.stop(timeLimit: const Duration(milliseconds: 1));
+      expect(process.killed, isFalse);
+    });
+    test('kill', () async {
+      final mockout = new StreamController<List<int>>();
+      process.stdout = mockout.stream;
+      process.stderr = _noMessage();
+      process.exitCode = new Future.delayed(const Duration(seconds: 1));
+
+      server.listenToOutput();
+      await server.stop(timeLimit: const Duration(milliseconds: 10));
+      expect(process.killed, isTrue);
+    });
+  });
+}
+
+final _badErrorMessage = {
+  'code': 'UNKNOWN_REQUEST',
+  'message': 'something went wrong',
+  'stackTrace': 'some long stack trace'
+};
+
+Stream<List<int>> _badMessage() async* {
+  yield utf8.encoder.convert('Observatory listening on foo bar\n');
+  final sampleJson = {
+    'id': '0',
+    'error': _badErrorMessage,
+  };
+  yield utf8.encoder.convert(json.encode(sampleJson));
+}
+
+Stream<List<int>> _eventMessage() async* {
+  yield utf8.encoder.convert('Observatory listening on foo bar\n');
+  final sampleJson = {
+    'event': 'fooEvent',
+    'params': {'foo': 'bar', 'baz': 'bang'}
+  };
+  yield utf8.encoder.convert(json.encode(sampleJson));
+}
+
+Stream<List<int>> _goodMessage() async* {
+  yield utf8.encoder.convert('Observatory listening on foo bar\n');
+  final sampleJson = {
+    'id': '0',
+    'result': {'foo': 'bar'}
+  };
+  yield utf8.encoder.convert(json.encode(sampleJson));
+}
+
+Stream<List<int>> _noMessage() async* {
+  yield utf8.encoder.convert('');
+}
+
+class MockProcess implements Process {
+  MockStdin mockin = new MockStdin();
+
+  bool killed = false;
+
+  @override
+  Stream<List<int>> stderr;
+
+  @override
+  IOSink get stdin => mockin;
+
+  @override
+  Stream<List<int>> stdout;
+
+  @override
+  Future<int> exitCode;
+
+  @override
+  int get pid => null;
+
+  @override
+  bool kill([ProcessSignal signal = ProcessSignal.sigterm]) {
+    bool wasKilled = killed;
+    killed = true;
+    return !wasKilled;
+  }
+}
+
+class MockStdin implements IOSink {
+  final controller = new StreamController<String>();
+
+  @override
+  Encoding encoding;
+
+  @override
+  Future get done => null;
+
+  @override
+  void add(List<int> data) {
+    controller.add(utf8.decode(data));
+  }
+
+  @override
+  void addError(Object error, [StackTrace stackTrace]) {}
+
+  @override
+  Future addStream(Stream<List<int>> stream) => null;
+
+  @override
+  Future close() => null;
+
+  @override
+  Future flush() => null;
+
+  @override
+  void write(Object obj) {}
+
+  @override
+  void writeAll(Iterable objects, [String separator = ""]) {}
+
+  @override
+  void writeCharCode(int charCode) {}
+
+  @override
+  void writeln([Object obj = ""]) {}
+}
diff --git a/pkg/analyzer/lib/dart/analysis/results.dart b/pkg/analyzer/lib/dart/analysis/results.dart
index 635fe97..2c33745 100644
--- a/pkg/analyzer/lib/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/dart/analysis/results.dart
@@ -49,6 +49,25 @@
   List<AnalysisError> get errors;
 }
 
+/// The declaration of an [Element].
+abstract class ElementDeclarationResult {
+  /// The [Element] that this object describes.
+  Element get element;
+
+  /// The node that declares the [element]. Depending on whether it is returned
+  /// from [ResolvedLibraryResult] or [ParsedLibraryResult] it might be resolved
+  /// or just parsed.
+  AstNode get node;
+
+  /// If this declaration is returned from [ParsedLibraryResult], the parsed
+  /// unit that contains the [node]. Otherwise `null`.
+  ParsedUnitResult get parsedUnit;
+
+  /// If this declaration is returned from [ResolvedLibraryResult], the
+  /// resolved unit that contains the [node]. Otherwise `null`.
+  ResolvedUnitResult get resolvedUnit;
+}
+
 /**
  * The result of computing all of the errors contained in a single file, both
  * syntactic and semantic.
@@ -75,6 +94,25 @@
   LineInfo get lineInfo;
 }
 
+/// The result of building parsed AST(s) for the whole library.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ParsedLibraryResult implements AnalysisResult {
+  /// The parsed units of the library.
+  List<ParsedUnitResult> get units;
+
+  /// Return the declaration of the [element], or `null` if the [element]
+  /// is synthetic. Throw [ArgumentError] if the [element] is not defined in
+  /// this library.
+  ElementDeclarationResult getElementDeclaration(Element element);
+}
+
+/// The result of parsing of a single file. The errors returned include only
+/// those discovered during scanning and parsing.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ParsedUnitResult implements ParseResult {}
+
 /**
  * The result of parsing of a single file. The errors returned include only
  * those discovered during scanning and parsing.
@@ -93,6 +131,31 @@
   CompilationUnit get unit;
 }
 
+/// The result of building resolved AST(s) for the whole library.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ResolvedLibraryResult implements AnalysisResult {
+  /// The element representing this library.
+  LibraryElement get element;
+
+  /// The type provider used when resolving the library.
+  TypeProvider get typeProvider;
+
+  /// The resolved units of the library.
+  List<ResolvedUnitResult> get units;
+
+  /// Return the declaration of the [element], or `null` if the [element]
+  /// is synthetic. Throw [ArgumentError] if the [element] is not defined in
+  /// this library.
+  ElementDeclarationResult getElementDeclaration(Element element);
+}
+
+/// The result of building a resolved AST for a single file. The errors returned
+/// include both syntactic and semantic errors.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ResolvedUnitResult implements ResolveResult {}
+
 /**
  * The result of building a resolved AST for a single file. The errors returned
  * include both syntactic and semantic errors.
@@ -116,6 +179,11 @@
   TypeProvider get typeProvider;
 
   /**
+   * The type system used when resolving the compilation [unit].
+   */
+  TypeSystem get typeSystem;
+
+  /**
    * The fully resolved compilation unit for the [content].
    */
   CompilationUnit get unit;
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index 3c4d9cf..1760f2a 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/uri_converter.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -24,6 +25,11 @@
  */
 abstract class AnalysisSession {
   /**
+   * The declared environment variables.
+   */
+  DeclaredVariables get declaredVariables;
+
+  /**
    * Return the [ResourceProvider] that is used to access the file system.
    */
   ResourceProvider get resourceProvider;
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index dd10465..b647c6a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -93,7 +93,7 @@
   /**
    * The version of data format, should be incremented on every format change.
    */
-  static const int DATA_VERSION = 73;
+  static const int DATA_VERSION = 76;
 
   /**
    * The number of exception contexts allowed to write. Once this field is
@@ -859,6 +859,27 @@
   }
 
   /**
+   * Return `true` is the file with the given absolute [uri] is a library,
+   * or `false` if it is a part. More specifically, return `true` if the file
+   * is not known to be a part.
+   *
+   * Correspondingly, return `true` if the [uri] does not correspond to a file,
+   * for any reason, e.g. the file does not exist, or the [uri] cannot be
+   * resolved to a file path, or the [uri] is invalid, e.g. a `package:` URI
+   * without a package name. In these cases we cannot prove that the file is
+   * not a part, so it must be a library.
+   */
+  bool isLibraryByUri(Uri uri) {
+    if (_externalSummaries != null) {
+      var uriStr = uri.toString();
+      if (_externalSummaries.unlinkedMap[uriStr] != null) {
+        return _externalSummaries.linkedMap.containsKey(uriStr);
+      }
+    }
+    return !_fsState.getFileForUri(uri).isPart;
+  }
+
+  /**
    * Return a [Future] that completes with a [ParseResult] for the file
    * with the given [path].
    *
@@ -2017,6 +2038,9 @@
 
   @override
   TypeProvider get typeProvider => unit.declaredElement.context.typeProvider;
+
+  @override
+  TypeSystem get typeSystem => unit.declaredElement.context.typeSystem;
 }
 
 abstract class BaseAnalysisResult implements results.AnalysisResult {
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index c1aad81..c308e2e 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -220,6 +220,12 @@
   bool get isPart => _unlinked.libraryNameOffset == 0 && _unlinked.isPartOf;
 
   /**
+   * Return `true` if the file is the "unresolved" file, which does not have
+   * neither a valid URI, nor a path.
+   */
+  bool get isUnresolved => uri == null;
+
+  /**
    * If the file [isPart], return a currently know library the file is a part
    * of. Return `null` if a library is not known, for example because we have
    * not processed a library file yet.
@@ -834,9 +840,10 @@
   }
 
   /**
-   * Return the [FileState] for the given absolute [uri]. May return `null` if
-   * the [uri] is invalid, e.g. a `package:` URI without a package name. The
-   * returned file has the last known state since if was last refreshed.
+   * Return the [FileState] for the given absolute [uri]. May return the
+   * "unresolved" file if the [uri] is invalid, e.g. a `package:` URI without
+   * a package name. The returned file has the last known state since if was
+   * last refreshed.
    */
   FileState getFileForUri(Uri uri) {
     FileState file = _uriToFile[uri];
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 2a05e11..8264e19 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -15,8 +15,8 @@
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/constant/constant_verifier.dart';
-import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/constant/utilities.dart';
+import 'package:analyzer/src/dart/constant/compute.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/handle.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
@@ -31,7 +31,6 @@
 import 'package:analyzer/src/lint/linter.dart';
 import 'package:analyzer/src/lint/linter_visitor.dart';
 import 'package:analyzer/src/services/lint.dart';
-import 'package:analyzer/src/summary/link.dart';
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/task/strong/checker.dart';
 
@@ -49,6 +48,7 @@
   final AnalysisContextImpl _context;
   final ElementResynthesizer _resynthesizer;
   final TypeProvider _typeProvider;
+  final TypeSystem _typeSystem;
 
   LibraryElement _libraryElement;
   LibraryScope _libraryScope;
@@ -72,7 +72,8 @@
       this._resynthesizer,
       this._library)
       : _inheritance = new InheritanceManager2(_context.typeSystem),
-        _typeProvider = _context.typeProvider;
+        _typeProvider = _context.typeProvider,
+        _typeSystem = _context.typeSystem;
 
   /**
    * Compute analysis results for all units of the library.
@@ -145,9 +146,12 @@
 
       if (_analysisOptions.lint) {
         PerformanceStatistics.lints.makeCurrentWhile(() {
-          units.forEach((file, unit) {
-            _computeLints(file, unit);
-          });
+          var allUnits = _library.libraryFiles
+              .map((file) => LinterContextUnit(file.content, units[file]))
+              .toList();
+          for (int i = 0; i < allUnits.length; i++) {
+            _computeLints(_library.libraryFiles[i], allUnits[i], allUnits);
+          }
         });
       }
     } finally {
@@ -176,23 +180,12 @@
    * Compute [_constants] in all units.
    */
   void _computeConstants() {
-    ConstantEvaluationEngine evaluationEngine = new ConstantEvaluationEngine(
-        _typeProvider, _declaredVariables,
-        forAnalysisDriver: true, typeSystem: _context.typeSystem);
-
-    List<_ConstantNode> nodes = [];
-    Map<ConstantEvaluationTarget, _ConstantNode> nodeMap = {};
-    for (ConstantEvaluationTarget constant in _constants) {
-      var node = new _ConstantNode(evaluationEngine, nodeMap, constant);
-      nodes.add(node);
-      nodeMap[constant] = node;
-    }
-
-    for (_ConstantNode node in nodes) {
-      if (!node.isEvaluated) {
-        new _ConstantWalker(evaluationEngine).walk(node);
-      }
-    }
+    computeConstants(
+      _typeProvider,
+      _context.typeSystem,
+      _declaredVariables,
+      _constants.toList(),
+    );
   }
 
   void _computeHints(FileState file, CompilationUnit unit) {
@@ -251,7 +244,9 @@
     }
   }
 
-  void _computeLints(FileState file, CompilationUnit unit) {
+  void _computeLints(FileState file, LinterContextUnit currentUnit,
+      List<LinterContextUnit> allUnits) {
+    var unit = currentUnit.unit;
     if (file.source == null) {
       return;
     }
@@ -260,9 +255,14 @@
 
     var nodeRegistry = new NodeLintRegistry(_analysisOptions.enableTiming);
     var visitors = <AstVisitor>[];
+    var context = LinterContextImpl(
+        allUnits, currentUnit, _declaredVariables, _typeProvider, _typeSystem);
     for (Linter linter in _analysisOptions.lintRules) {
       linter.reporter = errorReporter;
-      if (linter is NodeLintRule) {
+      if (linter is NodeLintRuleWithContext) {
+        (linter as NodeLintRuleWithContext)
+            .registerNodeProcessors(nodeRegistry, context);
+      } else if (linter is NodeLintRule) {
         (linter as NodeLintRule).registerNodeProcessors(nodeRegistry);
       } else {
         AstVisitor visitor = linter.getVisitor();
@@ -724,58 +724,6 @@
 }
 
 /**
- * [Node] that is used to compute constants in dependency order.
- */
-class _ConstantNode extends Node<_ConstantNode> {
-  final ConstantEvaluationEngine evaluationEngine;
-  final Map<ConstantEvaluationTarget, _ConstantNode> nodeMap;
-  final ConstantEvaluationTarget constant;
-
-  bool isEvaluated = false;
-
-  _ConstantNode(this.evaluationEngine, this.nodeMap, this.constant);
-
-  @override
-  List<_ConstantNode> computeDependencies() {
-    List<ConstantEvaluationTarget> targets = [];
-    evaluationEngine.computeDependencies(constant, targets.add);
-    return targets.map(_getNode).toList();
-  }
-
-  _ConstantNode _getNode(ConstantEvaluationTarget constant) {
-    return nodeMap.putIfAbsent(
-        constant, () => new _ConstantNode(evaluationEngine, nodeMap, constant));
-  }
-}
-
-/**
- * [DependencyWalker] for computing constants and detecting cycles.
- */
-class _ConstantWalker extends DependencyWalker<_ConstantNode> {
-  final ConstantEvaluationEngine evaluationEngine;
-
-  _ConstantWalker(this.evaluationEngine);
-
-  @override
-  void evaluate(_ConstantNode node) {
-    evaluationEngine.computeConstantValue(node.constant);
-    node.isEvaluated = true;
-  }
-
-  @override
-  void evaluateScc(List<_ConstantNode> scc) {
-    var constantsInCycle = scc.map((node) => node.constant);
-    for (_ConstantNode node in scc) {
-      if (node.constant is ConstructorElementImpl) {
-        (node.constant as ConstructorElementImpl).isCycleFree = false;
-      }
-      evaluationEngine.generateCycleError(constantsInCycle, node.constant);
-      node.isEvaluated = true;
-    }
-  }
-}
-
-/**
  * Either the name or the source associated with a part-of directive.
  */
 class _NameOrSource {
diff --git a/pkg/analyzer/lib/src/dart/analysis/results.dart b/pkg/analyzer/lib/src/dart/analysis/results.dart
new file mode 100644
index 0000000..2f1eb6c
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/analysis/results.dart
@@ -0,0 +1,256 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+abstract class AnalysisResultImpl implements AnalysisResult {
+  @override
+  final AnalysisSession session;
+
+  @override
+  final String path;
+
+  @override
+  final Uri uri;
+
+  AnalysisResultImpl(this.session, this.path, this.uri);
+}
+
+class ElementDeclarationResultImpl implements ElementDeclarationResult {
+  @override
+  final Element element;
+
+  @override
+  final AstNode node;
+
+  @override
+  final ParsedUnitResult parsedUnit;
+
+  @override
+  final ResolvedUnitResult resolvedUnit;
+
+  ElementDeclarationResultImpl(
+      this.element, this.node, this.parsedUnit, this.resolvedUnit);
+}
+
+class ErrorsResultImpl extends FileResultImpl implements ErrorsResult {
+  @override
+  final List<AnalysisError> errors;
+
+  ErrorsResultImpl(AnalysisSession session, String path, Uri uri,
+      LineInfo lineInfo, bool isPart, this.errors)
+      : super(session, path, uri, lineInfo, isPart);
+}
+
+class FileResultImpl extends AnalysisResultImpl implements FileResult {
+  @override
+  final LineInfo lineInfo;
+
+  @override
+  final bool isPart;
+
+  FileResultImpl(
+      AnalysisSession session, String path, Uri uri, this.lineInfo, this.isPart)
+      : super(session, path, uri);
+
+  @override
+  ResultState get state => ResultState.VALID;
+}
+
+class ParsedLibraryResultImpl extends AnalysisResultImpl
+    implements ParsedLibraryResult {
+  @override
+  final ResultState state = ResultState.VALID;
+
+  @override
+  final List<ParsedUnitResult> units;
+
+  ParsedLibraryResultImpl(
+      AnalysisSession session, String path, Uri uri, this.units)
+      : super(session, path, uri);
+
+  @Deprecated('This factory exists temporary until AnalysisSession migration.')
+  factory ParsedLibraryResultImpl.tmp(LibraryElement library) {
+    var libraryPath = library.source.fullName;
+    var analysisContext = library.context;
+    var units = <ParsedUnitResult>[];
+    for (var unitElement in library.units) {
+      var unitSource = unitElement.source;
+
+      if (!analysisContext.exists(unitSource)) {
+        continue;
+      }
+
+      var content = analysisContext.getContents(unitSource).data;
+      var lineInfo = analysisContext.getLineInfo(unitSource);
+      var unit = analysisContext.parseCompilationUnit(unitSource);
+      units.add(ParsedUnitResultImpl(null, unitSource.fullName, unitSource.uri,
+          content, lineInfo, unitSource != library.source, unit, const []));
+    }
+    return ParsedLibraryResultImpl(
+        null, libraryPath, library.source.uri, units);
+  }
+
+  @override
+  ElementDeclarationResult getElementDeclaration(Element element) {
+    var elementPath = element.source.fullName;
+    var unitResult = units.firstWhere(
+      (r) => r.path == elementPath,
+      orElse: () {
+        throw ArgumentError('Element (${element.runtimeType}) $element is not '
+            'defined in this library.');
+      },
+    );
+
+    if (element.isSynthetic || element.nameOffset == -1) {
+      return null;
+    }
+
+    var locator = NodeLocator2(element.nameOffset);
+    var node = locator.searchWithin(unitResult.unit)?.parent;
+    return ElementDeclarationResultImpl(element, node, unitResult, null);
+  }
+}
+
+class ParsedUnitResultImpl extends FileResultImpl implements ParsedUnitResult {
+  @override
+  final String content;
+
+  @override
+  final CompilationUnit unit;
+
+  @override
+  final List<AnalysisError> errors;
+
+  ParsedUnitResultImpl(AnalysisSession session, String path, Uri uri,
+      this.content, LineInfo lineInfo, bool isPart, this.unit, this.errors)
+      : super(session, path, uri, lineInfo, isPart);
+
+  @override
+  ResultState get state => ResultState.VALID;
+}
+
+class ResolvedLibraryResultImpl extends AnalysisResultImpl
+    implements ResolvedLibraryResult {
+  @override
+  final LibraryElement element;
+
+  @override
+  final ResultState state = ResultState.VALID;
+
+  @override
+  final TypeProvider typeProvider;
+
+  @override
+  final List<ResolvedUnitResult> units;
+
+  ResolvedLibraryResultImpl(AnalysisSession session, String path, Uri uri,
+      this.element, this.typeProvider, this.units)
+      : super(session, path, uri);
+
+  @override
+  ElementDeclarationResult getElementDeclaration(Element element) {
+    var elementPath = element.source.fullName;
+    var unitResult = units.firstWhere(
+      (r) => r.path == elementPath,
+      orElse: () {
+        throw ArgumentError('Element (${element.runtimeType}) $element is not '
+            'defined in this library.');
+      },
+    );
+
+    if (element.isSynthetic || element.nameOffset == -1) {
+      return null;
+    }
+
+    var locator = NodeLocator2(element.nameOffset);
+    var node = locator.searchWithin(unitResult.unit)?.parent;
+    return ElementDeclarationResultImpl(element, node, null, unitResult);
+  }
+
+  @Deprecated('This method exists temporary until AnalysisSession migration.')
+  static Future<ResolvedLibraryResult> tmp(LibraryElement library) async {
+    var libraryPath = library.source.fullName;
+    var units = <ResolvedUnitResult>[];
+    var analysisContext = library.context;
+    for (var unitElement in library.units) {
+      var unitSource = unitElement.source;
+
+      if (!analysisContext.exists(unitSource)) {
+        continue;
+      }
+
+      var path = unitSource.fullName;
+      var content = analysisContext.getContents(unitSource).data;
+      var lineInfo = analysisContext.getLineInfo(unitSource);
+      var unit = analysisContext.resolveCompilationUnit(unitSource, library);
+      units.add(ResolvedUnitResultImpl(null, path, unitSource.uri, true,
+          content, lineInfo, unitSource != library.source, unit, const []));
+    }
+    return ResolvedLibraryResultImpl(null, libraryPath, library.source.uri,
+        library, library.context.typeProvider, units);
+  }
+}
+
+class ResolvedUnitResultImpl extends FileResultImpl
+    implements ResolvedUnitResult {
+  /// Return `true` if the file exists.
+  final bool exists;
+
+  @override
+  final String content;
+
+  @override
+  final CompilationUnit unit;
+
+  @override
+  final List<AnalysisError> errors;
+
+  ResolvedUnitResultImpl(
+      AnalysisSession session,
+      String path,
+      Uri uri,
+      this.exists,
+      this.content,
+      LineInfo lineInfo,
+      bool isPart,
+      this.unit,
+      this.errors)
+      : super(session, path, uri, lineInfo, isPart);
+
+  @override
+  LibraryElement get libraryElement => unit.declaredElement.library;
+
+  @override
+  ResultState get state => exists ? ResultState.VALID : ResultState.NOT_A_FILE;
+
+  @override
+  TypeProvider get typeProvider => unit.declaredElement.context.typeProvider;
+
+  @override
+  TypeSystem get typeSystem => unit.declaredElement.context.typeSystem;
+}
+
+class UnitElementResultImpl extends AnalysisResultImpl
+    implements UnitElementResult {
+  @override
+  final String signature;
+
+  @override
+  final CompilationUnitElement element;
+
+  UnitElementResultImpl(AnalysisSession session, String path, Uri uri,
+      this.signature, this.element)
+      : super(session, path, uri);
+
+  @override
+  ResultState get state => ResultState.VALID;
+}
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index ebbbf1d..982f3bb 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/analysis/uri_converter.dart';
@@ -50,6 +51,9 @@
   AnalysisSessionImpl(this._driver);
 
   @override
+  DeclaredVariables get declaredVariables => _driver.declaredVariables;
+
+  @override
   ResourceProvider get resourceProvider => _driver.resourceProvider;
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/constant/compute.dart b/pkg/analyzer/lib/src/dart/constant/compute.dart
new file mode 100644
index 0000000..707d34a
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/constant/compute.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/resolver.dart'
+    show TypeProvider, TypeSystem;
+import 'package:analyzer/src/summary/link.dart' as graph
+    show DependencyWalker, Node;
+import 'package:analyzer/src/task/dart.dart';
+
+/// Compute values of the given [constants] with correct ordering.
+void computeConstants(
+    TypeProvider typeProvider,
+    TypeSystem typeSystem,
+    DeclaredVariables declaredVariables,
+    List<ConstantEvaluationTarget> constants) {
+  var evaluationEngine = ConstantEvaluationEngine(
+      typeProvider, declaredVariables,
+      forAnalysisDriver: true, typeSystem: typeSystem);
+
+  var nodes = <_ConstantNode>[];
+  var nodeMap = <ConstantEvaluationTarget, _ConstantNode>{};
+  for (var constant in constants) {
+    var node = _ConstantNode(evaluationEngine, nodeMap, constant);
+    nodes.add(node);
+    nodeMap[constant] = node;
+  }
+
+  for (var node in nodes) {
+    if (!node.isEvaluated) {
+      _ConstantWalker(evaluationEngine).walk(node);
+    }
+  }
+}
+
+/**
+ * [graph.Node] that is used to compute constants in dependency order.
+ */
+class _ConstantNode extends graph.Node<_ConstantNode> {
+  final ConstantEvaluationEngine evaluationEngine;
+  final Map<ConstantEvaluationTarget, _ConstantNode> nodeMap;
+  final ConstantEvaluationTarget constant;
+
+  _ConstantNode(this.evaluationEngine, this.nodeMap, this.constant);
+
+  @override
+  bool get isEvaluated => constant.isConstantEvaluated;
+
+  @override
+  List<_ConstantNode> computeDependencies() {
+    var targets = <ConstantEvaluationTarget>[];
+    evaluationEngine.computeDependencies(constant, targets.add);
+    return targets.map(_getNode).toList();
+  }
+
+  _ConstantNode _getNode(ConstantEvaluationTarget constant) {
+    return nodeMap.putIfAbsent(
+      constant,
+      () => _ConstantNode(evaluationEngine, nodeMap, constant),
+    );
+  }
+}
+
+/**
+ * [graph.DependencyWalker] for computing constants and detecting cycles.
+ */
+class _ConstantWalker extends graph.DependencyWalker<_ConstantNode> {
+  final ConstantEvaluationEngine evaluationEngine;
+
+  _ConstantWalker(this.evaluationEngine);
+
+  @override
+  void evaluate(_ConstantNode node) {
+    evaluationEngine.computeConstantValue(node.constant);
+  }
+
+  @override
+  void evaluateScc(List<_ConstantNode> scc) {
+    var constantsInCycle = scc.map((node) => node.constant);
+    for (var node in scc) {
+      var constant = node.constant;
+      if (constant is ConstructorElementImpl) {
+        constant.isCycleFree = false;
+      }
+      evaluationEngine.generateCycleError(constantsInCycle, constant);
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index c016009..3cab468 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -183,15 +183,20 @@
   void computeConstantValue(ConstantEvaluationTarget constant) {
     validator.beforeComputeValue(constant);
     if (constant is ParameterElementImpl) {
-      Expression defaultValue = constant.constantInitializer;
-      if (defaultValue != null) {
-        RecordingErrorListener errorListener = new RecordingErrorListener();
-        ErrorReporter errorReporter =
-            new ErrorReporter(errorListener, constant.source);
-        DartObjectImpl dartObject =
-            defaultValue.accept(new ConstantVisitor(this, errorReporter));
-        constant.evaluationResult =
-            new EvaluationResultImpl(dartObject, errorListener.errors);
+      if (constant.isOptional) {
+        Expression defaultValue = constant.constantInitializer;
+        if (defaultValue != null) {
+          RecordingErrorListener errorListener = new RecordingErrorListener();
+          ErrorReporter errorReporter =
+              new ErrorReporter(errorListener, constant.source);
+          DartObjectImpl dartObject =
+              defaultValue.accept(new ConstantVisitor(this, errorReporter));
+          constant.evaluationResult =
+              new EvaluationResultImpl(dartObject, errorListener.errors);
+        } else {
+          constant.evaluationResult =
+              EvaluationResultImpl(typeProvider.nullObject);
+        }
       }
     } else if (constant is VariableElementImpl) {
       Expression constantInitializer = constant.constantInitializer;
@@ -216,12 +221,13 @@
         constant.evaluationResult =
             new EvaluationResultImpl(dartObject, errorListener.errors);
       }
-    } else if (constant is ConstructorElement) {
+    } else if (constant is ConstructorElementImpl) {
       if (constant.isConst) {
         // No evaluation needs to be done; constructor declarations are only in
         // the dependency graph to ensure that any constants referred to in
         // initializer lists and parameter defaults are evaluated before
         // invocations of the constructor.
+        constant.isConstantEvaluated = true;
       }
     } else if (constant is ElementAnnotationImpl) {
       Annotation constNode = constant.annotationAst;
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 62f46eb..513799f 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/constant/compute.dart';
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/handle.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -1783,6 +1784,9 @@
   }
 
   @override
+  bool get isConstantEvaluated => true;
+
+  @override
   void set isFinal(bool isFinal) {
     assert(false);
   }
@@ -1835,6 +1839,9 @@
   /// is a part of a cycle.
   bool _isCycleFree = true;
 
+  @override
+  bool isConstantEvaluated = false;
+
   /// Initialize a newly created constructor element to have the given [name
   /// ] and[offset].
   ConstructorElementImpl(String name, int offset) : super(name, offset);
@@ -2168,6 +2175,9 @@
     _evaluationResult = evaluationResult;
   }
 
+  @override
+  bool get isConstantEvaluated => _evaluationResult != null;
+
   /// If this element is resynthesized from the summary, return the unlinked
   /// initializer, otherwise return `null`.
   UnlinkedExpr get _unlinkedConst;
@@ -2178,7 +2188,12 @@
   /// of this variable could not be computed because of errors.
   DartObject computeConstantValue() {
     if (evaluationResult == null) {
-      context?.computeResult(this, CONSTANT_VALUE);
+      computeConstants(
+        context.typeProvider,
+        context.typeSystem,
+        context.declaredVariables,
+        [this],
+      );
     }
     return evaluationResult?.value;
   }
@@ -2359,6 +2374,9 @@
       element.name == _ALWAYS_THROWS_VARIABLE_NAME &&
       element.library?.name == _META_LIB_NAME;
 
+  @override
+  bool get isConstantEvaluated => evaluationResult != null;
+
   /// Return `true` if this annotation marks the associated parameter as being
   /// covariant, meaning it is allowed to have a narrower type in an override.
   bool get isCovariant =>
@@ -2468,7 +2486,12 @@
   @override
   DartObject computeConstantValue() {
     if (evaluationResult == null) {
-      context?.computeResult(this, CONSTANT_VALUE);
+      computeConstants(
+        context.typeProvider,
+        context.typeSystem,
+        context.declaredVariables,
+        [this],
+      );
     }
     return constantValue;
   }
@@ -7391,6 +7414,9 @@
       UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement)
       : super.forSerialized(unlinkedVariable, enclosingElement);
 
+  @override
+  bool get isConstantEvaluated => true;
+
   @deprecated
   @override
   DartType get propagatedType => null;
@@ -7995,6 +8021,9 @@
   }
 
   @override
+  bool get isConstantEvaluated => true;
+
+  @override
   bool get isFinal {
     return hasModifier(Modifier.FINAL);
   }
diff --git a/pkg/analyzer/lib/src/dart/element/handle.dart b/pkg/analyzer/lib/src/dart/element/handle.dart
index 95ac102..728ff86 100644
--- a/pkg/analyzer/lib/src/dart/element/handle.dart
+++ b/pkg/analyzer/lib/src/dart/element/handle.dart
@@ -281,6 +281,9 @@
   bool get isConst => actualElement.isConst;
 
   @override
+  bool get isConstantEvaluated => actualElement.isConstantEvaluated;
+
+  @override
   bool get isDefaultConstructor => actualElement.isDefaultConstructor;
 
   @override
@@ -1138,6 +1141,9 @@
   DartType get propagatedType => null;
 
   @override
+  bool get isConstantEvaluated => actualElement.isConstantEvaluated;
+
+  @override
   PropertyAccessorElement get setter => actualElement.setter;
 }
 
@@ -1217,6 +1223,9 @@
   FunctionElement get initializer => actualElement.initializer;
 
   @override
+  bool get isConstantEvaluated => actualElement.isConstantEvaluated;
+
+  @override
   bool get isConst => actualElement.isConst;
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart
index 860bcb9..8d18330 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart
@@ -35,6 +35,10 @@
   /// Cached instance interfaces for [InterfaceType].
   final Map<InterfaceType, Interface> _interfaces = {};
 
+  /// The set of classes that are currently being processed, used to detect
+  /// self-referencing cycles.
+  final Set<ClassElement> _processingClasses = new Set<ClassElement>();
+
   /// Cached implemented members for [InterfaceType].
   final Map<InterfaceType, Map<Name, FunctionType>> _implemented = {};
 
@@ -53,63 +57,64 @@
   /// members, not necessary accessible in all libraries.
   Interface getInterface(InterfaceType type) {
     if (type == null) {
-      return const Interface._(const {}, const {}, const [{}], const []);
+      return Interface._empty;
     }
 
     var result = _interfaces[type];
     if (result != null) {
       return result;
     }
+    _interfaces[type] = Interface._empty;
 
-    _interfaces[type] = const Interface._(
-      const {},
-      const {},
-      const [{}],
-      const [],
-    );
-    Map<Name, FunctionType> map = {};
-    List<Map<Name, FunctionType>> superImplemented = [];
-    List<Conflict> conflicts = null;
-
-    // If a class declaration has a member declaration, the signature of that
-    // member declaration becomes the signature in the interface.
-    _addTypeMembers(map, type);
-
-    Map<Name, List<FunctionType>> namedCandidates = {};
-
-    for (var interface in type.interfaces) {
-      _addCandidates(namedCandidates, interface);
+    var classElement = type.element;
+    if (!_processingClasses.add(classElement)) {
+      return Interface._empty;
     }
 
-    if (type.element.isMixin) {
-      for (var constraint in type.superclassConstraints) {
-        _addCandidates(namedCandidates, constraint);
+    Map<Name, FunctionType> map = {};
+    Map<Name, List<FunctionType>> namedCandidates = {};
+    List<Map<Name, FunctionType>> superImplemented = [];
+    try {
+      // If a class declaration has a member declaration, the signature of that
+      // member declaration becomes the signature in the interface.
+      _addTypeMembers(map, type);
+
+      for (var interface in type.interfaces) {
+        _addCandidates(namedCandidates, interface);
       }
 
-      // `mixin M on S1, S2 {}` can call using `super` any instance member
-      // from its superclass constraints, whether it is abstract or concrete.
-      Map<Name, FunctionType> mixinSuperClass = {};
-      _findMostSpecificFromNamedCandidates(mixinSuperClass, namedCandidates);
-      superImplemented.add(mixinSuperClass);
-    } else {
-      Map<Name, FunctionType> implemented;
+      if (type.element.isMixin) {
+        for (var constraint in type.superclassConstraints) {
+          _addCandidates(namedCandidates, constraint);
+        }
 
-      if (type.superclass != null) {
-        _addCandidates(namedCandidates, type.superclass);
+        // `mixin M on S1, S2 {}` can call using `super` any instance member
+        // from its superclass constraints, whether it is abstract or concrete.
+        Map<Name, FunctionType> mixinSuperClass = {};
+        _findMostSpecificFromNamedCandidates(mixinSuperClass, namedCandidates);
+        superImplemented.add(mixinSuperClass);
+      } else {
+        Map<Name, FunctionType> implemented;
 
-        implemented = _getImplemented(type.superclass);
-        superImplemented.add(implemented);
+        if (type.superclass != null) {
+          _addCandidates(namedCandidates, type.superclass);
+
+          implemented = _getImplemented(type.superclass);
+          superImplemented.add(implemented);
+        }
+
+        for (var mixin in type.mixins) {
+          _addCandidates(namedCandidates, mixin);
+
+          var implementedInMixin = _getImplemented(mixin);
+          implemented = <Name, FunctionType>{}
+            ..addAll(implemented)
+            ..addAll(implementedInMixin);
+          superImplemented.add(implemented);
+        }
       }
-
-      for (var mixin in type.mixins) {
-        _addCandidates(namedCandidates, mixin);
-
-        var implementedInMixin = _getImplemented(mixin);
-        implemented = <Name, FunctionType>{}
-          ..addAll(implemented)
-          ..addAll(implementedInMixin);
-        superImplemented.add(implemented);
-      }
+    } finally {
+      _processingClasses.remove(classElement);
     }
 
     // If a class declaration does not have a member declaration with a
@@ -118,7 +123,10 @@
     // super-interfaces that is a valid override of all the other
     // super-interface signatures with the same name. That "most specific"
     // signature becomes the signature of the class's interface.
-    conflicts = _findMostSpecificFromNamedCandidates(map, namedCandidates);
+    List<Conflict> conflicts = _findMostSpecificFromNamedCandidates(
+      map,
+      namedCandidates,
+    );
 
     var interface = new Interface._(
       map,
@@ -385,6 +393,13 @@
 
 /// The instance interface of an [InterfaceType].
 class Interface {
+  static const _empty = const Interface._(
+    const {},
+    const {},
+    const [{}],
+    const [],
+  );
+
   /// The map of names to their signature in the interface.
   final Map<Name, FunctionType> map;
 
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index b1df8d9..c5f7657 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -41,6 +41,9 @@
   bool get isConst => baseElement.isConst;
 
   @override
+  bool get isConstantEvaluated => baseElement.isConstantEvaluated;
+
+  @override
   bool get isDefaultConstructor => baseElement.isDefaultConstructor;
 
   @override
@@ -1012,6 +1015,9 @@
   bool get isConst => baseElement.isConst;
 
   @override
+  bool get isConstantEvaluated => baseElement.isConstantEvaluated;
+
+  @override
   bool get isFinal => baseElement.isFinal;
 
   @override
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 382bfd6..2c718d9 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -767,6 +767,23 @@
     pop(); // block
   }
 
+  @override
+  void handleForInitializerEmptyStatement(Token token) {
+    debugEvent("ForInitializerEmptyStatement");
+    push(NullValue.Expression);
+  }
+
+  @override
+  void handleForInitializerExpressionStatement(Token token) {
+    debugEvent("ForInitializerExpressionStatement");
+  }
+
+  @override
+  void handleForInitializerLocalVariableDeclaration(Token token) {
+    debugEvent("ForInitializerLocalVariableDeclaration");
+  }
+
+  @override
   void endForStatement(Token forKeyword, Token leftParen, Token leftSeparator,
       int updateExpressionCount, Token endToken) {
     assert(optional('for', forKeyword));
@@ -1440,12 +1457,6 @@
     push(ast.label(name, colon));
   }
 
-  void handleNoExpression(Token token) {
-    debugEvent("NoExpression");
-
-    push(NullValue.Expression);
-  }
-
   void handleIndexedExpression(Token leftBracket, Token rightBracket) {
     assert(optional('[', leftBracket));
     assert(optional(']', rightBracket));
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 9f5eef9..207515d 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -4082,7 +4082,7 @@
     InterfaceType mixinSupertype = mixinElement.supertype;
     if (mixinSupertype != null) {
       if (!mixinSupertype.isObject ||
-          !mixinElement.isMixinApplication && mixinElement.mixins.length != 0) {
+          !mixinElement.isMixinApplication && mixinElement.mixins.isNotEmpty) {
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT,
             mixinName,
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 61fc2a4..7fd6ce9 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -388,6 +388,20 @@
   }
 
   @override
+  Object visitFieldDeclaration(FieldDeclaration node) {
+    bool wasInDeprecatedMember = _inDeprecatedMember;
+    if (_hasDeprecatedAnnotation(node.metadata)) {
+      _inDeprecatedMember = true;
+    }
+
+    try {
+      return super.visitFieldDeclaration(node);
+    } finally {
+      _inDeprecatedMember = wasInDeprecatedMember;
+    }
+  }
+
+  @override
   Object visitFormalParameterList(FormalParameterList node) {
     _checkRequiredParameter(node);
     return super.visitFormalParameterList(node);
@@ -471,11 +485,18 @@
   Object visitMixinDeclaration(MixinDeclaration node) {
     _enclosingClass = node.declaredElement;
     _invalidAccessVerifier._enclosingClass = _enclosingClass;
+
+    bool wasInDeprecatedMember = _inDeprecatedMember;
+    if (_hasDeprecatedAnnotation(node.metadata)) {
+      _inDeprecatedMember = true;
+    }
+
     try {
       return super.visitMixinDeclaration(node);
     } finally {
       _enclosingClass = null;
       _invalidAccessVerifier._enclosingClass = null;
+      _inDeprecatedMember = wasInDeprecatedMember;
     }
   }
 
@@ -518,6 +539,20 @@
   }
 
   @override
+  Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    bool wasInDeprecatedMember = _inDeprecatedMember;
+    if (_hasDeprecatedAnnotation(node.metadata)) {
+      _inDeprecatedMember = true;
+    }
+
+    try {
+      return super.visitTopLevelVariableDeclaration(node);
+    } finally {
+      _inDeprecatedMember = wasInDeprecatedMember;
+    }
+  }
+
+  @override
   Object visitVariableDeclaration(VariableDeclaration node) {
     _checkForInvalidAssignment(node.name, node.initializer);
     return super.visitVariableDeclaration(node);
@@ -1189,6 +1224,15 @@
     return false;
   }
 
+  static bool _hasDeprecatedAnnotation(List<Annotation> annotations) {
+    for (var i = 0; i < annotations.length; i++) {
+      if (annotations[i].elementAnnotation.isDeprecated) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   /// Given a parenthesized expression, this returns the parent (or recursively
   /// grand-parent) of the expression that is a parenthesized expression, but
   /// whose parent is not a parenthesized expression.
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index a94e348..78a7d03 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -6,11 +6,13 @@
 import 'dart:io';
 
 import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/file_system/file_system.dart' as file_system;
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisErrorInfo, AnalysisErrorInfoImpl, Logger;
 import 'package:analyzer/src/generated/java_engine.dart' show CaughtException;
+import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart' show LineInfo;
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/lint/analysis.dart';
@@ -186,6 +188,49 @@
   String _emph(msg) => bold ? '<strong>$msg</strong>' : msg;
 }
 
+/// Provides access to information needed by lint rules that is not available
+/// from AST nodes or the element model.
+abstract class LinterContext {
+  List<LinterContextUnit> get allUnits;
+
+  LinterContextUnit get currentUnit;
+
+  DeclaredVariables get declaredVariables;
+
+  TypeProvider get typeProvider;
+
+  TypeSystem get typeSystem;
+}
+
+/// Implementation of [LinterContext]
+class LinterContextImpl implements LinterContext {
+  @override
+  final List<LinterContextUnit> allUnits;
+
+  @override
+  final LinterContextUnit currentUnit;
+
+  @override
+  final DeclaredVariables declaredVariables;
+
+  @override
+  final TypeProvider typeProvider;
+
+  @override
+  final TypeSystem typeSystem;
+
+  LinterContextImpl(this.allUnits, this.currentUnit, this.declaredVariables,
+      this.typeProvider, this.typeSystem);
+}
+
+class LinterContextUnit {
+  final String content;
+
+  final CompilationUnit unit;
+
+  LinterContextUnit(this.content, this.unit);
+}
+
 /// Thrown when an error occurs in linting.
 class LinterException implements Exception {
   /// A message describing the error.
@@ -330,9 +375,29 @@
 abstract class NodeLintRule {
   /// This method is invoked to let the [LintRule] register node processors
   /// in the given [registry].
+  ///
+  /// In a future release of the analyzer, a `context` argument will be added.
+  /// To opt into the new API, use [NodeLintRuleWithContext] instead.
   void registerNodeProcessors(NodeLintRegistry registry);
 }
 
+/// [LintRule]s that implement this interface want to process only some types
+/// of AST nodes, and will register their processors in the registry.
+///
+/// TODO(paulberry): once NodeLintRule is removed, rename this interface to
+/// NodeLintRule.
+abstract class NodeLintRuleWithContext extends NodeLintRule {
+  /// This method is invoked to let the [LintRule] register node processors
+  /// in the given [registry].
+  ///
+  /// The node processors may use the provided [context] to access information
+  /// that is not available from the AST nodes or their associated elements.
+  /// In a future release of the analyzer, [context] will become a required
+  /// parameter.
+  void registerNodeProcessors(NodeLintRegistry registry,
+      [LinterContext context]);
+}
+
 class PrintingReporter implements Reporter, Logger {
   final Printer _print;
 
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 875a093..7e5c4bc 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -2383,6 +2383,11 @@
    * constant.
    */
   AnalysisContext get context;
+
+  /**
+   * Return whether this constant is evaluated.
+   */
+  bool get isConstantEvaluated;
 }
 
 /**
diff --git a/pkg/analyzer/test/generated/non_hint_code_test.dart b/pkg/analyzer/test/generated/non_hint_code_test.dart
index 2900675e..b6053b6 100644
--- a/pkg/analyzer/test/generated/non_hint_code_test.dart
+++ b/pkg/analyzer/test/generated/non_hint_code_test.dart
@@ -340,6 +340,21 @@
     verify([source]);
   }
 
+  test_deprecatedMemberUse_inDeprecatedField() async {
+    Source source = addSource(r'''
+@deprecated
+class C {}
+
+class X {
+  @deprecated
+  C f;
+}
+''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   test_deprecatedMemberUse_inDeprecatedFunction() async {
     Source source = addSource(r'''
 @deprecated
@@ -409,6 +424,36 @@
     verify([source]);
   }
 
+  test_deprecatedMemberUse_inDeprecatedMixin() async {
+    Source source = addSource(r'''
+@deprecated
+f() {}
+
+@deprecated
+mixin M {
+  m() {
+    f();
+  }
+}
+''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  test_deprecatedMemberUse_inDeprecatedTopLevelVariable() async {
+    Source source = addSource(r'''
+@deprecated
+class C {}
+
+@deprecated
+C v;
+''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   test_divisionOptimization() async {
     Source source = addSource(r'''
 f(int x, int y) {
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index dce0e04..1bcac17 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -928,6 +928,25 @@
 @reflectiveTest
 class StatementParserTest_Fasta extends FastaParserTestCase
     with StatementParserTestMixin {
+  void test_35177() {
+    ExpressionStatement statement = parseStatement('(f)()<int>();');
+
+    FunctionExpressionInvocation funct1 = statement.expression;
+    NodeList<TypeAnnotation> typeArgs = funct1.typeArguments.arguments;
+    expect(typeArgs, hasLength(1));
+    TypeName typeName = typeArgs[0];
+    expect(typeName.name.name, 'int');
+    expect(funct1.argumentList.arguments, hasLength(0));
+
+    FunctionExpressionInvocation funct2 = funct1.function;
+    expect(funct2.typeArguments, isNull);
+    expect(funct2.argumentList.arguments, hasLength(0));
+
+    ParenthesizedExpression expression = funct2.function;
+    SimpleIdentifier identifier = expression.expression;
+    expect(identifier.name, 'f');
+  }
+
   void test_invalid_typeArg_34850() {
     var unit = parseCompilationUnit('foo Future<List<int>> bar() {}', errors: [
       expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 4),
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index b46d1b7..feb577a 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -11135,6 +11135,84 @@
     }
   }
 
+  void test_issue_34610_get() {
+    final unit = parseCompilationUnit('class C { get C.named => null; }',
+        errors: usingFastaParser
+            ? [
+                expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 15, 1),
+                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
+                expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 16, 5),
+              ]
+            : [
+                expectedError(
+                    ParserErrorCode.STATIC_GETTER_WITHOUT_BODY, 15, 1),
+                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
+                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 15, 1),
+                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 22, 2),
+                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 22, 2),
+                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 22, 2),
+                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 25, 4),
+                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 25, 4),
+                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 29, 1),
+              ]);
+    ClassDeclaration declaration = unit.declarations[0];
+    MethodDeclaration method = declaration.members[0];
+    expect(method.name.name, 'C');
+    expect(method.isGetter, isTrue);
+  }
+
+  void test_issue_34610_initializers() {
+    final unit = parseCompilationUnit('class C { C.named : super(); }',
+        errors: usingFastaParser
+            ? [expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1)]
+            : [
+                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 19),
+                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 19),
+                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 18, 19),
+                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 20, 25),
+                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 20, 25),
+                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 25, 26),
+                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 25, 26),
+                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 26, 27),
+                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 26, 27),
+                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 27, 28),
+              ]);
+    ClassDeclaration declaration = unit.declarations[0];
+    if (usingFastaParser) {
+      ConstructorDeclaration constructor = declaration.members[0];
+      expect(constructor.name.name, 'named');
+      expect(constructor.parameters, isNotNull);
+      expect(constructor.parameters.parameters, hasLength(0));
+    } else {
+      FieldDeclaration field = declaration.members[0];
+      expect(field.fields.type.toSource(), 'C.named');
+    }
+  }
+
+  void test_issue_34610_missing_param() {
+    final unit = parseCompilationUnit('class C { C.named => null; }',
+        errors: usingFastaParser
+            ? [expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1)]
+            : [
+                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 2),
+                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 2),
+                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 18, 2),
+                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 21, 4),
+                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 21, 4),
+                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 25, 1),
+              ]);
+    ClassDeclaration declaration = unit.declarations[0];
+    if (usingFastaParser) {
+      ConstructorDeclaration constructor = declaration.members[0];
+      expect(constructor.name.name, 'named');
+      expect(constructor.parameters, isNotNull);
+      expect(constructor.parameters.parameters, hasLength(0));
+    } else {
+      FieldDeclaration field = declaration.members[0];
+      expect(field.fields.type.toSource(), 'C.named');
+    }
+  }
+
   void test_keywordInPlaceOfIdentifier() {
     // TODO(brianwilkerson) We could do better with this.
     parseCompilationUnit("do() {}",
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index b0adc84..1afe213 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -10,8 +10,10 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/src/dart/analysis/byte_store.dart';
 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/status.dart';
 import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/dart/constant/evaluation.dart';
@@ -24,8 +26,6 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
-import 'package:analyzer/src/dart/analysis/byte_store.dart';
-import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -2322,6 +2322,50 @@
     await waitForIdleWithoutExceptions();
   }
 
+  test_isLibraryByUri() async {
+    var a1 = _p('/aaa/lib/a1.dart');
+    var a2 = _p('/aaa/lib/a2.dart');
+    var b1 = _p('/bbb/lib/b1.dart');
+    var b2 = _p('/bbb/lib/b2.dart');
+
+    String a1UriStr = 'package:aaa/a1.dart';
+    String a2UriStr = 'package:aaa/a2.dart';
+    String b1UriStr = 'package:bbb/b1.dart';
+    String b2UriStr = 'package:bbb/b2.dart';
+
+    provider.newFile(a1, "part 'a2.dart';");
+    provider.newFile(a2, "part of 'a1.dart';");
+    provider.newFile(b1, "part 'b2.dart';");
+    provider.newFile(b2, "part of 'b1.dart';");
+
+    // Build the store with the library.
+    var store = await createAnalysisDriver().test.getSummaryStore(a1);
+    expect(store.unlinkedMap.keys, contains(a1UriStr));
+    expect(store.unlinkedMap.keys, contains(a2UriStr));
+    expect(store.linkedMap.keys, contains(a1UriStr));
+
+    // Remove the stored files from the file system.
+    provider.deleteFile(a1);
+    provider.deleteFile(a2);
+
+    // We can ask isLibraryByUri() for both external and local units.
+    AnalysisDriver driver = createAnalysisDriver(externalSummaries: store);
+    expect(driver.isLibraryByUri(Uri.parse(a1UriStr)), isTrue);
+    expect(driver.isLibraryByUri(Uri.parse(a2UriStr)), isFalse);
+    expect(driver.isLibraryByUri(Uri.parse(b1UriStr)), isTrue);
+    expect(driver.isLibraryByUri(Uri.parse(b2UriStr)), isFalse);
+  }
+
+  test_isLibraryByUri_doesNotExist() async {
+    var uri = Uri.parse('file:///test.dart');
+    expect(driver.isLibraryByUri(uri), isTrue);
+  }
+
+  test_isLibraryByUri_invalidUri() async {
+    var uri = Uri.parse('package:aaa');
+    expect(driver.isLibraryByUri(uri), isTrue);
+  }
+
   test_issue34619() async {
     var a = _p('/test/lib/a.dart');
     provider.newFile(a, r'''
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 091ec5c..aeb0e75 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -7,7 +7,9 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/src/dart/analysis/byte_store.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/top_level_declaration.dart';
 import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart'
@@ -16,8 +18,6 @@
 import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:convert/convert.dart';
 import 'package:crypto/crypto.dart';
-import 'package:analyzer/src/dart/analysis/byte_store.dart';
-import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -567,6 +567,15 @@
     expect(file2, same(file1));
   }
 
+  test_getFileForUri_invalidUri() {
+    var uri = Uri.parse('package:x');
+    var file = fileSystemState.getFileForUri(uri);
+    expect(file.isUnresolved, isTrue);
+    expect(file.uri, isNull);
+    expect(file.path, isNull);
+    expect(file.isPart, isFalse);
+  }
+
   test_getFileForUri_packageVsFileUri() {
     String path = _p('/aaa/lib/a.dart');
     var packageUri = Uri.parse('package:aaa/a.dart');
diff --git a/pkg/analyzer/test/src/dart/resolution/constant_test.dart b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
new file mode 100644
index 0000000..53a5c74
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'driver_resolution.dart';
+import 'resolution.dart';
+import 'task_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConstantDriverTest);
+    defineReflectiveTests(ConstantTaskTest);
+  });
+}
+
+@reflectiveTest
+class ConstantDriverTest extends DriverResolutionTest with ConstantMixin {}
+
+abstract class ConstantMixin implements ResolutionTest {
+  test_constantValue_defaultParameter_noDefaultValue() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {
+  const A({int p});
+}
+''');
+    addTestFile(r'''
+import 'a.dart';
+const a = const A();
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    var aLib = findElement.import('package:test/a.dart').importedLibrary;
+    var aConstructor = aLib.getType('A').constructors.single;
+    DefaultParameterElementImpl p = aConstructor.parameters.single;
+
+    // To evaluate `const A()` we have to evaluate `{int p}`.
+    // Even if its value is `null`.
+    expect(p.isConstantEvaluated, isTrue);
+    expect(p.constantValue.isNull, isTrue);
+  }
+
+  test_constFactoryRedirection_super() async {
+    addTestFile(r'''
+class I {
+  const factory I(int f) = B;
+}
+
+class A implements I {
+  final int f;
+
+  const A(this.f);
+}
+
+class B extends A {
+  const B(int f) : super(f);
+}
+
+@I(42)
+main() {}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    var node = findNode.annotation('@I');
+    var value = node.elementAnnotation.constantValue;
+    expect(value.getField('(super)').getField('f').toIntValue(), 42);
+  }
+}
+
+@reflectiveTest
+class ConstantTaskTest extends TaskResolutionTest with ConstantMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/enum_test.dart b/pkg/analyzer/test/src/dart/resolution/enum_test.dart
index d30bf67..930ab7c 100644
--- a/pkg/analyzer/test/src/dart/resolution/enum_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/enum_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/error/codes.dart';
+import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
@@ -44,6 +45,20 @@
     var v = findElement.topVar('v');
     assertElementTypeString(v.type, 'List<Object>');
   }
+
+  test_isConstantEvaluated() async {
+    addTestFile(r'''
+enum E {
+  aaa, bbb
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    expect(findElement.field('aaa').isConstantEvaluated, isTrue);
+    expect(findElement.field('bbb').isConstantEvaluated, isTrue);
+    expect(findElement.field('values').isConstantEvaluated, isTrue);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/dart/resolution/find_element.dart b/pkg/analyzer/test/src/dart/resolution/find_element.dart
index dff0500..4eadf43 100644
--- a/pkg/analyzer/test/src/dart/resolution/find_element.dart
+++ b/pkg/analyzer/test/src/dart/resolution/find_element.dart
@@ -73,21 +73,28 @@
   }
 
   FieldElement field(String name) {
-    for (var type in unitElement.mixins) {
-      for (var field in type.fields) {
+    for (var enum_ in unitElement.enums) {
+      for (var field in enum_.fields) {
         if (field.name == name) {
           return field;
         }
       }
     }
-    for (var type in unitElement.types) {
-      for (var field in type.fields) {
+    for (var mixin in unitElement.mixins) {
+      for (var field in mixin.fields) {
         if (field.name == name) {
           return field;
         }
       }
     }
-    fail('Not found class field: $name');
+    for (var class_ in unitElement.types) {
+      for (var field in class_.fields) {
+        if (field.name == name) {
+          return field;
+        }
+      }
+    }
+    fail('Not found field: $name');
   }
 
   FunctionElement function(String name) {
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
index e086247..40ae57a 100644
--- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
diff --git a/pkg/analyzer_cli/README.md b/pkg/analyzer_cli/README.md
index db0a161..19054e3 100644
--- a/pkg/analyzer_cli/README.md
+++ b/pkg/analyzer_cli/README.md
@@ -3,8 +3,8 @@
 Use _dartanalyzer_ to statically analyze your code at the command line,
 checking for errors and warnings that are specified in the
 [Dart Language Specification](https://www.dartlang.org/docs/spec/).
-DartPad, code editors, and IDEs such as WebStorm use the same
-analysis engine that dartanalyzer uses.
+DartPad, code editors, and IDEs such as Android Studio and VS Code
+use the same analysis engine that dartanalyzer uses.
 
 ## Basic usage
 
diff --git a/pkg/build_integration/pubspec.yaml b/pkg/build_integration/pubspec.yaml
index a8c5bef..b746b5c 100644
--- a/pkg/build_integration/pubspec.yaml
+++ b/pkg/build_integration/pubspec.yaml
@@ -5,5 +5,8 @@
 # This package is not intended to be published - yet
 publish_to: none
 
+environment:
+  sdk: '>=2.0.0 <3.0.0'
+
 dependencies:
   front_end: ^0.1.0
diff --git a/pkg/compiler/analysis_options.yaml b/pkg/compiler/analysis_options.yaml
index 050bbb3..3400954 100644
--- a/pkg/compiler/analysis_options.yaml
+++ b/pkg/compiler/analysis_options.yaml
@@ -3,8 +3,6 @@
 # BSD-style license that can be found in the LICENSE file.
 
 analyzer:
-  language:
-    enableSuperMixins: false
   errors:
     todo: ignore
     deprecated_member_use: ignore
diff --git a/pkg/compiler/lib/compiler.dart b/pkg/compiler/lib/compiler.dart
index 671f426..0c79da0 100644
--- a/pkg/compiler/lib/compiler.dart
+++ b/pkg/compiler/lib/compiler.dart
@@ -6,8 +6,6 @@
 
 import 'dart:async';
 
-import 'package:package_config/packages.dart';
-
 import 'compiler_new.dart' as new_api;
 import 'src/old_to_new_api.dart';
 import 'src/options.dart' show CompilerOptions;
@@ -69,12 +67,6 @@
 typedef void DiagnosticHandler(
     Uri uri, int begin, int end, String message, Diagnostic kind);
 
-/**
- * Provides a package lookup mechanism in the case that no package root or
- * package resolution configuration file are explicitly specified.
- */
-typedef Future<Packages> PackagesDiscoveryProvider(Uri uri);
-
 /// Information resulting from the compilation.
 class CompilationResult {
   /// `true` if the compilation succeeded, that is, compilation didn't fail due
@@ -105,20 +97,22 @@
  * as the compiler may create multiple files to support lazy loading
  * of libraries.
  */
-Future<CompilationResult> compile(Uri script, Uri libraryRoot, Uri packageRoot,
-    CompilerInputProvider inputProvider, DiagnosticHandler handler,
+Future<CompilationResult> compile(
+    Uri script,
+    Uri librariesSpecificationUri,
+    Uri packageRoot,
+    CompilerInputProvider inputProvider,
+    DiagnosticHandler handler,
     [List<String> options = const [],
     CompilerOutputProvider outputProvider,
     Map<String, String> environment = const {},
-    Uri packageConfig,
-    PackagesDiscoveryProvider packagesDiscoveryProvider]) {
-  CompilerOptions compilerOptions =
-      CompilerOptions.parse(options, libraryRoot: libraryRoot)
-        ..entryPoint = script
-        ..packageRoot = packageRoot
-        ..packageConfig = packageConfig
-        ..packagesDiscoveryProvider = packagesDiscoveryProvider
-        ..environment = environment;
+    Uri packageConfig]) {
+  CompilerOptions compilerOptions = CompilerOptions.parse(options,
+      librariesSpecificationUri: librariesSpecificationUri)
+    ..entryPoint = script
+    ..packageRoot = packageRoot
+    ..packageConfig = packageConfig
+    ..environment = environment;
 
   new_api.CompilerInput compilerInput = new LegacyCompilerInput(inputProvider);
   new_api.CompilerDiagnostics compilerDiagnostics =
diff --git a/pkg/compiler/lib/compiler_new.dart b/pkg/compiler/lib/compiler_new.dart
index a85fe85..d7de722 100644
--- a/pkg/compiler/lib/compiler_new.dart
+++ b/pkg/compiler/lib/compiler_new.dart
@@ -15,7 +15,7 @@
 import 'src/apiimpl.dart';
 import 'src/options.dart' show CompilerOptions;
 
-export 'compiler.dart' show Diagnostic, PackagesDiscoveryProvider;
+export 'compiler.dart' show Diagnostic;
 
 // Unless explicitly allowed, passing `null` for any argument to the
 // methods of library will result in an Error being thrown.
@@ -89,6 +89,15 @@
   void close();
 }
 
+/// Sink interface used for generating binary data from the compiler.
+abstract class BinaryOutputSink {
+  /// Writes indices [start] to [end] of [buffer] to the sink.
+  void write(List<int> buffer, [int start = 0, int end]);
+
+  /// Closes the sink.
+  void close();
+}
+
 /// Interface for producing output from the compiler. That is, JavaScript target
 /// files, source map files, dump info files, etc.
 abstract class CompilerOutput {
@@ -101,6 +110,10 @@
   // TODO(johnniwinther): Replace [name] and [extension] with something like
   // [id] and [uri].
   OutputSink createOutputSink(String name, String extension, OutputType type);
+
+  /// Returns an [BinaryOutputSink] that will serve as compiler output for the
+  /// given URI.
+  BinaryOutputSink createBinarySink(Uri uri);
 }
 
 /// Interface for receiving diagnostic message from the compiler. That is,
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index a855925..4f13e9b 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -5,12 +5,10 @@
 library leg_apiimpl;
 
 import 'dart:async';
+import 'dart:convert' show utf8;
 
-import 'package:package_config/packages.dart';
-import 'package:package_config/packages_file.dart' as pkgs;
-import 'package:package_config/src/packages_impl.dart'
-    show MapPackages, NonFilePackagesDirectoryPackages;
-import 'package:package_config/src/util.dart' show checkValidPackageUri;
+import 'package:front_end/src/api_unstable/dart2js.dart'
+    show LibrariesSpecification, TargetLibrariesSpecification, LibraryInfo;
 
 import '../compiler_new.dart' as api;
 import 'common/tasks.dart' show GenericTask, Measurer;
@@ -18,9 +16,8 @@
 import 'compiler.dart';
 import 'diagnostics/messages.dart' show Message;
 import 'environment.dart';
+import 'io/source_file.dart';
 import 'options.dart' show CompilerOptions;
-import 'platform_configuration.dart' as platform_configuration;
-import 'resolved_uri_translator.dart';
 
 /// Implements the [Compiler] using a [api.CompilerInput] for supplying the
 /// sources.
@@ -28,15 +25,9 @@
   final Measurer measurer;
   api.CompilerInput provider;
   api.CompilerDiagnostics handler;
-  Packages packages;
-
-  ForwardingResolvedUriTranslator resolvedUriTranslator;
 
   GenericTask userHandlerTask;
   GenericTask userProviderTask;
-  GenericTask userPackagesDiscoveryTask;
-
-  Uri get libraryRoot => options.platformConfigUri.resolve(".");
 
   CompilerImpl(this.provider, api.CompilerOutput outputProvider, this.handler,
       CompilerOptions options,
@@ -44,19 +35,14 @@
       // NOTE: allocating measurer is done upfront to ensure the wallclock is
       // started before other computations.
       : measurer = new Measurer(enableTaskMeasurements: options.verbose),
-        resolvedUriTranslator = new ForwardingResolvedUriTranslator(),
         super(
             options: options,
             outputProvider: outputProvider,
             environment: new _Environment(options.environment),
             makeReporter: makeReporter) {
-    _Environment env = environment;
-    env.compiler = this;
     tasks.addAll([
       userHandlerTask = new GenericTask('Diagnostic handler', measurer),
       userProviderTask = new GenericTask('Input provider', measurer),
-      userPackagesDiscoveryTask =
-          new GenericTask('Package discovery', measurer),
     ]);
   }
 
@@ -65,68 +51,28 @@
         null, null, null, null, message, api.Diagnostic.VERBOSE_INFO);
   }
 
-  /**
-   * Translates a readable URI into a resource URI.
-   *
-   * See [LibraryLoader] for terminology on URIs.
-   */
-  Uri translateUri(Spannable node, Uri uri) =>
-      uri.scheme == 'package' ? translatePackageUri(node, uri) : uri;
-
-  Uri translatePackageUri(Spannable node, Uri uri) {
-    try {
-      checkValidPackageUri(uri);
-    } on ArgumentError catch (e) {
-      reporter.reportErrorMessage(node, MessageKind.INVALID_PACKAGE_URI,
-          {'uri': uri, 'exception': e.message});
-      return null;
-    }
-    return packages.resolve(uri, notFound: (Uri notFound) {
-      reporter.reportErrorMessage(
-          node, MessageKind.LIBRARY_NOT_FOUND, {'resolvedUri': uri});
-      return null;
-    });
-  }
-
-  Future setupPackages(Uri uri) {
-    if (options.packageRoot != null) {
-      // Use "non-file" packages because the file version requires a [Directory]
-      // and we can't depend on 'dart:io' classes.
-      packages = new NonFilePackagesDirectoryPackages(options.packageRoot);
-    } else if (options.packageConfig != null) {
-      Future<api.Input<List<int>>> future =
-          callUserProvider(options.packageConfig, api.InputKind.binary);
-      return future.then((api.Input<List<int>> binary) {
-        packages =
-            new MapPackages(pkgs.parse(binary.data, options.packageConfig));
-      }).catchError((error) {
-        reporter.reportErrorMessage(
-            NO_LOCATION_SPANNABLE,
-            MessageKind.INVALID_PACKAGE_CONFIG,
-            {'uri': options.packageConfig, 'exception': error});
-        packages = Packages.noPackages;
-      });
-    } else {
-      if (options.packagesDiscoveryProvider == null) {
-        packages = Packages.noPackages;
-      } else {
-        return callUserPackagesDiscovery(uri).then((p) {
-          packages = p;
-        });
-      }
-    }
-    return new Future.value();
-  }
-
   Future setupSdk() {
     var future = new Future.value(null);
-    if (resolvedUriTranslator.isNotSet) {
+    _Environment env = environment;
+    if (env.librariesSpecification == null) {
       future = future.then((_) {
-        return platform_configuration
-            .load(options.platformConfigUri, provider)
-            .then((Map<String, Uri> mapping) {
-          resolvedUriTranslator.resolvedUriTranslator =
-              new ResolvedUriTranslator(mapping);
+        Uri specificationUri = options.librariesSpecificationUri;
+        return provider.readFromUri(specificationUri).then((api.Input spec) {
+          String json = null;
+          // TODO(sigmund): simplify this, we have some API inconsistencies when
+          // our internal input adds a terminating zero.
+          if (spec is SourceFile) {
+            json = spec.slowText();
+          } else if (spec is Binary) {
+            json = utf8.decode(spec.data);
+          }
+
+          // TODO(sigmund): would be nice to front-load some of the CFE option
+          // processing and parse this .json file only once.
+          env.librariesSpecification =
+              LibrariesSpecification.parse(specificationUri, json)
+                  .specificationFor(
+                      options.compileForServer ? "dart2js_server" : "dart2js");
         });
       });
     }
@@ -139,12 +85,7 @@
   Future<bool> run(Uri uri) {
     Duration setupDuration = measurer.wallClock.elapsed;
     return selfTask.measureSubtask("CompilerImpl.run", () {
-      log('Using platform configuration at ${options.platformConfigUri}');
-
-      return setupSdk().then((_) => setupPackages(uri)).then((_) {
-        assert(resolvedUriTranslator.isSet);
-        assert(packages != null);
-
+      return setupSdk().then((_) {
         return super.run(uri);
       }).then((bool success) {
         if (options.verbose) {
@@ -236,32 +177,16 @@
       rethrow;
     }
   }
-
-  Future<Packages> callUserPackagesDiscovery(Uri uri) {
-    try {
-      return userPackagesDiscoveryTask
-          .measureIo(() => options.packagesDiscoveryProvider(uri));
-    } catch (ex, s) {
-      reportCrashInUserCode('Uncaught exception in package discovery', ex, s);
-      rethrow;
-    }
-  }
 }
 
 class _Environment implements Environment {
   final Map<String, String> definitions;
 
-  // TODO(sigmund): break the circularity here: Compiler needs an environment to
-  // initialize the library loader, but the environment here needs to know about
-  // how the sdk is set up and about whether the backend supports mirrors.
-  CompilerImpl compiler;
+  TargetLibrariesSpecification librariesSpecification;
 
   _Environment(this.definitions);
 
   String valueOf(String name) {
-    assert(compiler.resolvedUriTranslator != null,
-        failedAt(NO_LOCATION_SPANNABLE, "setupSdk() has not been run"));
-
     var result = definitions[name];
     if (result != null || definitions.containsKey(name)) return result;
     if (!name.startsWith(_dartLibraryEnvironmentPrefix)) return null;
@@ -270,28 +195,10 @@
 
     // Private libraries are not exposed to the users.
     if (libraryName.startsWith("_")) return null;
-
-    Uri libraryUri = compiler.resolvedUriTranslator.sdkLibraries[libraryName];
-    // TODO(sigmund): use libraries.json instead of .platform files, then simply
-    // use the `supported` bit.
-    if (libraryUri != null && libraryUri.scheme != "unsupported") {
-      if (libraryName == 'mirrors') return null;
-      if (libraryName == 'isolate') return null;
+    LibraryInfo info = librariesSpecification.libraryInfoFor(libraryName);
+    if (info != null && info.isSupported) {
       return "true";
     }
-
-    // Note: we return null on `dart:io` here, even if we allow users to
-    // unconditionally import it.
-    //
-    // In the past it was invalid to import `dart:io` for client apps. We just
-    // made it valid to import it as a stopgap measure to support packages like
-    // `http`. This is temporary until we support config-imports in the
-    // language.
-    //
-    // Because it is meant to be temporary and because the returned `dart:io`
-    // implementation will throw on most APIs, we still preserve that
-    // when compiling client apps the `dart:io` library is technically not
-    // supported, and so `const bool.fromEnvironment(dart.library.io)` is false.
     return null;
   }
 }
diff --git a/pkg/compiler/lib/src/backend_strategy.dart b/pkg/compiler/lib/src/backend_strategy.dart
index c3aefb1..5711ff3 100644
--- a/pkg/compiler/lib/src/backend_strategy.dart
+++ b/pkg/compiler/lib/src/backend_strategy.dart
@@ -15,6 +15,7 @@
 import 'js_backend/native_data.dart';
 import 'ssa/ssa.dart';
 import 'types/types.dart';
+import 'universe/codegen_world_builder.dart';
 import 'universe/world_builder.dart';
 import 'world.dart';
 
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 22b3fc7..41e51e6 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -113,7 +113,7 @@
   void forEachBoxedVariable(f(Local local, FieldEntity field)) {}
 
   /// True if [variable] has been mutated and is also used in another scope.
-  bool isBoxed(Local variable) => false;
+  bool isBoxedVariable(Local variable) => false;
 }
 
 /// Class representing the usage of a scope that has been captured in the
@@ -299,10 +299,6 @@
   /// scopes.
   void forEachFreeVariable(f(Local variable, FieldEntity field)) {}
 
-  /// Return true if [variable] has been captured and mutated (all other
-  /// variables do not require boxing).
-  bool isVariableBoxed(Local variable) => false;
-
   // TODO(efortuna): Remove this method. The old system was using
   // ClosureClassMaps for situations other than closure class maps, and that's
   // just confusing.
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index c68391d..d9e8b8a 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -62,8 +62,14 @@
   static const String useMultiSourceInfo = '--use-multi-source-info';
   static const String useNewSourceInfo = '--use-new-source-info';
   static const String verbose = '--verbose';
+  static const String progress = '--show-internal-progress';
   static const String version = '--version';
 
+  static const String readData = '--read-data';
+  static const String writeData = '--write-data';
+
+  static const String serverMode = '--server-mode';
+
   /// Flag for a combination of flags for 'production' mode.
   static const String benchmarkingProduction = '--benchmarking-production';
 
diff --git a/pkg/compiler/lib/src/common/tasks.dart b/pkg/compiler/lib/src/common/tasks.dart
index 9f3ce1e5..f617999 100644
--- a/pkg/compiler/lib/src/common/tasks.dart
+++ b/pkg/compiler/lib/src/common/tasks.dart
@@ -180,11 +180,27 @@
     // Use a nested CompilerTask for the measurement to ensure nested [measure]
     // calls work correctly. The subtasks will never themselves have nested
     // subtasks because they are not accessible outside.
-    GenericTask subtask =
-        _subtasks.putIfAbsent(name, () => new GenericTask(name, measurer));
+    GenericTask subtask = _subtasks[name] ??= new GenericTask(name, measurer);
     return subtask.measure(action);
   }
 
+  /// Asynchronous version of [measureSubtask]. Use this when action returns a
+  /// future that's truly asynchronous, such I/O. Only one task can use this
+  /// concurrently.
+  ///
+  /// Note: we assume that this method is used only by the compiler input
+  /// provider, but it could be used by other tasks as long as the input
+  /// provider will not be called by those tasks.
+  Future<T> measureIoSubtask<T>(String name, Future<T> action()) {
+    if (_isDisabled) return action();
+
+    // Use a nested CompilerTask for the measurement to ensure nested [measure]
+    // calls work correctly. The subtasks will never themselves have nested
+    // subtasks because they are not accessible outside.
+    GenericTask subtask = _subtasks[name] ??= new GenericTask(name, measurer);
+    return subtask.measureIo(action);
+  }
+
   Iterable<String> get subtasks => _subtasks.keys;
 
   int getSubtaskTime(String subtask) => _subtasks[subtask].timing;
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 9140c04..a98f635 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -33,15 +33,17 @@
 import 'js_model/js_strategy.dart';
 import 'kernel/kernel_strategy.dart';
 import 'library_loader.dart' show LibraryLoaderTask, LoadedLibraries;
-import 'null_compiler_output.dart' show NullCompilerOutput, NullSink;
+import 'null_compiler_output.dart' show NullCompilerOutput;
 import 'options.dart' show CompilerOptions, DiagnosticOptions;
+import 'serialization/task.dart';
+import 'serialization/strategies.dart';
 import 'ssa/nodes.dart' show HInstruction;
 import 'types/abstract_value_domain.dart' show AbstractValueStrategy;
 import 'types/types.dart'
     show GlobalTypeInferenceResults, GlobalTypeInferenceTask;
 import 'universe/selector.dart' show Selector;
-import 'universe/world_builder.dart'
-    show ResolutionWorldBuilder, CodegenWorldBuilder;
+import 'universe/codegen_world_builder.dart';
+import 'universe/resolution_world_builder.dart';
 import 'universe/world_impact.dart'
     show ImpactStrategy, WorldImpact, WorldImpactBuilderImpl;
 import 'world.dart' show JClosedWorld, KClosedWorld;
@@ -115,6 +117,7 @@
   EnqueueTask enqueuer;
   DeferredLoadTask deferredLoadTask;
   DumpInfoTask dumpInfoTask;
+  SerializationTask serializationTask;
 
   bool get hasCrashed => _reporter.hasCrashed;
 
@@ -157,8 +160,8 @@
     _impactCache = <Entity, WorldImpact>{};
     _impactCacheDeleter = new _MapImpactCacheDeleter(_impactCache);
 
-    if (options.verbose) {
-      progress = new ProgressImpl(_reporter);
+    if (options.showInternalProgress) {
+      progress = new InteractiveProgress();
     }
 
     backend = createBackend();
@@ -176,6 +179,7 @@
       enqueuer,
       dumpInfoTask = new DumpInfoTask(this),
       selfTask,
+      serializationTask = new SerializationTask(this, measurer),
     ];
 
     tasks.addAll(backend.tasks);
@@ -264,16 +268,23 @@
     assert(uri != null);
     // As far as I can tell, this branch is only used by test code.
     reporter.log('Compiling $uri (${options.buildId})');
-    LoadedLibraries loadedLibraries = await libraryLoader.loadLibraries(uri);
-    // Note: libraries may be null because of errors trying to find files or
-    // parse-time errors (when using `package:front_end` as a loader).
-    if (loadedLibraries == null) return;
-    if (compilationFailed && !options.generateCodeWithCompileTimeErrors) {
-      return;
+
+    if (options.readDataUri != null) {
+      GlobalTypeInferenceResults results =
+          await serializationTask.deserialize();
+      generateJavaScriptCode(results);
+    } else {
+      LoadedLibraries loadedLibraries = await libraryLoader.loadLibraries(uri);
+      // Note: libraries may be null because of errors trying to find files or
+      // parse-time errors (when using `package:front_end` as a loader).
+      if (loadedLibraries == null) return;
+      if (compilationFailed && !options.generateCodeWithCompileTimeErrors) {
+        return;
+      }
+      _mainLibraryUri = loadedLibraries.rootLibraryUri;
+      processLoadedLibraries(loadedLibraries);
+      await compileLoadedLibraries(loadedLibraries);
     }
-    _mainLibraryUri = loadedLibraries.rootLibraryUri;
-    processLoadedLibraries(loadedLibraries);
-    compileLoadedLibraries(loadedLibraries);
   }
 
   /// Starts the resolution phase, creating the [ResolutionEnqueuer] if not
@@ -317,7 +328,7 @@
 
     phase = PHASE_RESOLVING;
     resolutionEnqueuer.applyImpact(mainImpact);
-    reporter.log('Resolving...');
+    if (options.showInternalProgress) reporter.log('Resolving...');
 
     processQueue(
         frontendStrategy.elementEnvironment, resolutionEnqueuer, mainFunction,
@@ -350,7 +361,7 @@
   GlobalTypeInferenceResults performGlobalTypeInference(
       JClosedWorld closedWorld) {
     FunctionEntity mainFunction = closedWorld.elementEnvironment.mainFunction;
-    reporter.log('Inferring types...');
+    if (options.showInternalProgress) reporter.log('Inferring types...');
     InferredDataBuilder inferredDataBuilder =
         new InferredDataBuilderImpl(closedWorld.annotationsData);
     return globalInference.runGlobalTypeInference(
@@ -362,7 +373,7 @@
     JClosedWorld closedWorld = globalInferenceResults.closedWorld;
     backendStrategy.registerJClosedWorld(closedWorld);
     FunctionEntity mainFunction = closedWorld.elementEnvironment.mainFunction;
-    reporter.log('Compiling...');
+    if (options.showInternalProgress) reporter.log('Compiling...');
     phase = PHASE_COMPILING;
 
     Enqueuer codegenEnqueuer =
@@ -391,6 +402,24 @@
       if (closedWorld != null) {
         GlobalTypeInferenceResults globalInferenceResults =
             performGlobalTypeInference(closedWorld);
+        if (options.writeDataUri != null) {
+          serializationTask.serialize(globalInferenceResults);
+          return;
+        }
+        if (options.testMode) {
+          SerializationStrategy strategy =
+              const BytesInMemorySerializationStrategy();
+          List<int> irData =
+              strategy.serializeComponent(globalInferenceResults);
+          List worldData = strategy.serializeData(globalInferenceResults);
+          globalInferenceResults = strategy.deserializeData(
+              options,
+              reporter,
+              environment,
+              abstractValueStrategy,
+              strategy.deserializeComponent(irData),
+              worldData);
+        }
         if (stopAfterTypeInference) return;
         generateJavaScriptCode(globalInferenceResults);
       }
@@ -625,11 +654,17 @@
         // Disable output in test mode: The build bot currently uses the time
         // stamp of the generated file to determine whether the output is
         // up-to-date.
-        return NullSink.outputProvider(name, extension, type);
+        return const NullCompilerOutput()
+            .createOutputSink(name, extension, type);
       }
     }
     return _userOutput.createOutputSink(name, extension, type);
   }
+
+  @override
+  api.BinaryOutputSink createBinarySink(Uri uri) {
+    return _userOutput.createBinarySink(uri);
+  }
 }
 
 /// Information about suppressed warnings and hints for a given library.
@@ -970,3 +1005,33 @@
     _stopwatch.reset();
   }
 }
+
+/// Progress implementations that prints progress to the [DiagnosticReporter]
+/// with 500ms intervals using escape sequences to keep the progress data on a
+/// single line.
+class InteractiveProgress implements Progress {
+  final Stopwatch _stopwatchPhase = new Stopwatch()..start();
+  final Stopwatch _stopwatchInterval = new Stopwatch()..start();
+  void startPhase() {
+    print('');
+    _stopwatchPhase.reset();
+    _stopwatchInterval.reset();
+  }
+
+  void showProgress(String prefix, int count, String suffix) {
+    if (_stopwatchInterval.elapsedMilliseconds > 500) {
+      var time = _stopwatchPhase.elapsedMilliseconds / 1000;
+      var rate = count / _stopwatchPhase.elapsedMilliseconds;
+      var s = new StringBuffer('\x1b[1A\x1b[K') // go up and clear the line.
+        ..write('\x1b[48;5;40m\x1b[30m==>\x1b[0m $prefix')
+        ..write(count)
+        ..write('$suffix Elapsed time: ')
+        ..write(time.toStringAsFixed(2))
+        ..write(' s. Rate: ')
+        ..write(rate.toStringAsFixed(2))
+        ..write(' units/ms');
+      print('$s');
+      _stopwatchInterval.reset();
+    }
+  }
+}
diff --git a/pkg/compiler/lib/src/constants/evaluation.dart b/pkg/compiler/lib/src/constants/evaluation.dart
index 9ed3440..ff9355f 100644
--- a/pkg/compiler/lib/src/constants/evaluation.dart
+++ b/pkg/compiler/lib/src/constants/evaluation.dart
@@ -59,6 +59,12 @@
 
   /// `true` if assertions are enabled.
   bool get enableAssertions;
+
+  /// If `true`, implicit casts should be checked.
+  ///
+  /// This is used to avoid circular dependencies between js-interop classes
+  /// and their metadata. For non-metadata constants we always check the casts.
+  bool get checkCasts;
 }
 
 abstract class EvaluationEnvironmentBase implements EvaluationEnvironment {
@@ -71,6 +77,8 @@
     _spannableStack = _spannableStack.prepend(spannable);
   }
 
+  bool get checkCasts => true;
+
   DiagnosticReporter get reporter;
 
   /// Returns the [Spannable] used for reporting errors and warnings.
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index 79419e8..60a18ca 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -24,7 +24,6 @@
   CONCATENATE,
   CONDITIONAL,
   CONSTRUCTED,
-  DEFERRED,
   DOUBLE,
   ERRONEOUS,
   FUNCTION,
@@ -39,7 +38,6 @@
   STRING_FROM_ENVIRONMENT,
   STRING_LENGTH,
   SYMBOL,
-  SYNTHETIC,
   TYPE,
   UNARY,
   LOCAL_VARIABLE,
@@ -162,41 +160,6 @@
   bool _equals(ErroneousConstantExpression other) => true;
 }
 
-// TODO(johnniwinther): Avoid the need for this class.
-class SyntheticConstantExpression extends ConstantExpression {
-  final SyntheticConstantValue value;
-
-  SyntheticConstantExpression(this.value);
-
-  @override
-  ConstantValue evaluate(
-      EvaluationEnvironment environment, ConstantSystem constantSystem) {
-    return value;
-  }
-
-  @override
-  void _createStructuredText(StringBuffer sb) {
-    sb.write('Synthetic(value=${value.toStructuredText()})');
-  }
-
-  @override
-  int _computeHashCode() => 13 * value.hashCode;
-
-  accept(ConstantExpressionVisitor visitor, [context]) {
-    throw "unsupported";
-  }
-
-  @override
-  bool _equals(SyntheticConstantExpression other) {
-    return value == other.value;
-  }
-
-  ConstantExpressionKind get kind => ConstantExpressionKind.SYNTHETIC;
-
-  @override
-  bool get isImplicit => false;
-}
-
 /// Boolean literal constant.
 class BoolConstantExpression extends ConstantExpression {
   final bool boolValue;
@@ -866,6 +829,8 @@
     ConstantValue expressionValue =
         expression.evaluate(environment, constantSystem);
 
+    if (!environment.checkCasts) return expressionValue;
+
     // The expression type is `int`.
     DartType expressionType =
         expressionValue.getType(environment.commonElements);
@@ -2112,55 +2077,6 @@
   }
 }
 
-/// A constant expression referenced with a deferred prefix.
-/// For example `lib.C`.
-class DeferredConstantExpression extends ConstantExpression {
-  final ConstantExpression expression;
-  final ImportEntity import;
-
-  DeferredConstantExpression(this.expression, this.import);
-
-  ConstantExpressionKind get kind => ConstantExpressionKind.DEFERRED;
-
-  @override
-  void _createStructuredText(StringBuffer sb) {
-    sb.write('Deferred(import=$import,expression=');
-    expression._createStructuredText(sb);
-    sb.write(')');
-  }
-
-  @override
-  ConstantValue evaluate(
-      EvaluationEnvironment environment, ConstantSystem constantSystem) {
-    return new DeferredConstantValue(
-        expression.evaluate(environment, constantSystem), import);
-  }
-
-  @override
-  int _computeHashCode() {
-    return 13 * expression.hashCode;
-  }
-
-  ConstantExpression apply(NormalizedArguments arguments) {
-    return new DeferredConstantExpression(expression.apply(arguments), import);
-  }
-
-  @override
-  bool _equals(DeferredConstantExpression other) {
-    return expression == other.expression;
-  }
-
-  @override
-  accept(ConstantExpressionVisitor visitor, [context]) {
-    return visitor.visitDeferred(this, context);
-  }
-
-  @override
-  bool get isPotential {
-    return expression.isPotential;
-  }
-}
-
 class InstantiationConstantExpression extends ConstantExpression {
   final List<DartType> typeArguments;
   final ConstantExpression expression;
@@ -2245,7 +2161,6 @@
       IntFromEnvironmentConstantExpression exp, A context);
   R visitStringFromEnvironment(
       StringFromEnvironmentConstantExpression exp, A context);
-  R visitDeferred(DeferredConstantExpression exp, A context);
   R visitAssert(AssertConstantExpression exp, A context);
   R visitInstantiation(InstantiationConstantExpression exp, A context);
 
@@ -2487,13 +2402,6 @@
   }
 
   @override
-  void visitDeferred(DeferredConstantExpression exp, context) {
-    sb.write(exp.import.name);
-    sb.write('.');
-    write(exp, exp.expression);
-  }
-
-  @override
   void visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp,
       [_]) {
     sb.write('const bool.fromEnvironment(');
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index 48f4397..aae0175 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -24,7 +24,7 @@
   TYPE,
   INTERCEPTOR,
   SYNTHETIC,
-  DEFERRED,
+  INSTANTIATION,
   DEFERRED_GLOBAL,
   NON_CONSTANT,
 }
@@ -46,7 +46,6 @@
   R visitInterceptor(
       covariant InterceptorConstantValue constant, covariant A arg);
   R visitSynthetic(covariant SyntheticConstantValue constant, covariant A arg);
-  R visitDeferred(covariant DeferredConstantValue constant, covariant A arg);
   R visitDeferredGlobal(
       covariant DeferredGlobalConstantValue constant, covariant A arg);
   R visitNonConstant(covariant NonConstantValue constant, covariant A arg);
@@ -676,6 +675,7 @@
         hashCode = Hashing.unorderedMapHash(fields, Hashing.objectHash(type)),
         super(type) {
     assert(type != null);
+    assert(!fields.containsKey(null));
     assert(!fields.containsValue(null));
   }
 
@@ -743,40 +743,6 @@
   }
 }
 
-/// A reference to a constant in another output unit.
-///
-/// Used for referring to deferred constants when evaluating constant values.
-class DeferredConstantValue extends ConstantValue {
-  DeferredConstantValue(this.referenced, this.import);
-
-  final ConstantValue referenced;
-  final ImportEntity import;
-
-  bool get isReference => true;
-
-  bool operator ==(other) {
-    return other is DeferredConstantValue &&
-        referenced == other.referenced &&
-        import == other.import;
-  }
-
-  int get hashCode => (referenced.hashCode * 17 + import.hashCode) & 0x3fffffff;
-
-  List<ConstantValue> getDependencies() => <ConstantValue>[referenced];
-
-  accept(ConstantValueVisitor visitor, arg) => visitor.visitDeferred(this, arg);
-
-  DartType getType(CommonElements types) => referenced.getType(types);
-
-  ConstantValueKind get kind => ConstantValueKind.DEFERRED;
-
-  String toDartText() => 'deferred(${referenced.toDartText()})';
-
-  String toStructuredText() {
-    return 'DeferredConstant(${referenced.toStructuredText()})';
-  }
-}
-
 class InstantiationConstantValue extends ConstantValue {
   final List<DartType> typeArguments;
   final FunctionConstantValue function;
@@ -805,7 +771,7 @@
     return type.instantiate(typeArguments);
   }
 
-  ConstantValueKind get kind => ConstantValueKind.DEFERRED;
+  ConstantValueKind get kind => ConstantValueKind.INSTANTIATION;
 
   String toDartText() =>
       '<${typeArguments.join(', ')}>(${function.toDartText()})';
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index c1db5c4..75633a7 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -10,7 +10,6 @@
 import 'dart:isolate' show Isolate;
 
 import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
-import 'package:package_config/discovery.dart' show findPackages;
 
 import '../compiler_new.dart' as api;
 import 'commandline_options.dart';
@@ -21,7 +20,7 @@
 import 'util/uri_extras.dart';
 import 'util/util.dart' show stackTraceFilePrefix;
 
-const String LIBRARY_ROOT = '../../../../sdk';
+const String _defaultSpecificationUri = '../../../../sdk/lib/libraries.json';
 const String OUTPUT_LANGUAGE_DART = 'Dart';
 
 /**
@@ -110,10 +109,13 @@
     {fe.InitializedCompilerState kernelInitializedCompilerState}) {
   Stopwatch wallclock = new Stopwatch()..start();
   stackTraceFilePrefix = '$currentDirectory';
-  Uri libraryRoot = currentDirectory;
+  Uri librariesSpecificationUri =
+      currentDirectory.resolve('lib/libraries.json');
   bool outputSpecified = false;
-  Uri out = currentDirectory.resolve('out.js');
-  Uri sourceMapOut = currentDirectory.resolve('out.js.map');
+  Uri out;
+  Uri sourceMapOut;
+  Uri readDataUri;
+  Uri writeDataUri;
   List<String> bazelPaths;
   Uri packageConfig = null;
   Uri packageRoot = null;
@@ -133,6 +135,7 @@
   int optimizationLevel = null;
   Uri platformBinaries = fe.computePlatformBinariesLocation();
   Map<String, String> environment = new Map<String, String>();
+  CompilationStrategy compilationStrategy = CompilationStrategy.direct;
 
   void passThrough(String argument) => options.add(argument);
   void ignoreOption(String argument) {}
@@ -141,8 +144,9 @@
     passThrough("--build-id=$BUILD_ID");
   }
 
-  void setLibraryRoot(String argument) {
-    libraryRoot = currentDirectory.resolve(extractPath(argument));
+  void setLibrarySpecificationUri(String argument) {
+    librariesSpecificationUri =
+        currentDirectory.resolve(extractPath(argument, isDirectory: false));
   }
 
   void setPackageRoot(String argument) {
@@ -166,7 +170,6 @@
       path = extractParameter(arguments.current);
     }
     out = currentDirectory.resolve(nativeToUriPath(path));
-    sourceMapOut = Uri.parse('$out.map');
   }
 
   void setOptimizationLevel(String argument) {
@@ -232,17 +235,16 @@
 
   void setCategories(String argument) {
     List<String> categories = extractParameter(argument).split(',');
-    if (categories.contains('all')) {
-      categories = ["Client", "Server"];
+    bool isServerMode = categories.length == 1 && categories.single == "Server";
+    if (isServerMode) {
+      hints.add("The --categories flag is deprecated and will be deleted in a "
+          "future release, please use '${Flags.serverMode}' instead of "
+          "'--categories=Server'.");
+      passThrough(Flags.serverMode);
     } else {
-      for (String category in categories) {
-        if (!["Client", "Server"].contains(category)) {
-          fail('Unsupported library category "$category", '
-              'supported categories are: Client, Server, all');
-        }
-      }
+      hints.add(
+          "The --categories flag is deprecated, see the usage for details.");
     }
-    passThrough('--categories=${categories.join(",")}');
   }
 
   void setPlatformBinaries(String argument) {
@@ -250,6 +252,28 @@
         currentDirectory.resolve(extractPath(argument, isDirectory: true));
   }
 
+  void setReadData(String argument) {
+    if (compilationStrategy == CompilationStrategy.toData) {
+      fail("Cannot read and write serialized simultaneously.");
+    }
+    if (argument != Flags.readData) {
+      readDataUri = currentDirectory
+          .resolve(nativeToUriPath(extractPath(argument, isDirectory: false)));
+    }
+    compilationStrategy = CompilationStrategy.fromData;
+  }
+
+  void setWriteData(String argument) {
+    if (compilationStrategy == CompilationStrategy.fromData) {
+      fail("Cannot read and write serialized simultaneously.");
+    }
+    if (argument != Flags.writeData) {
+      writeDataUri = currentDirectory
+          .resolve(nativeToUriPath(extractPath(argument, isDirectory: false)));
+    }
+    compilationStrategy = CompilationStrategy.toData;
+  }
+
   void handleThrowOnError(String argument) {
     throwOnError = true;
     String parameter = extractParameter(argument, isOptionalArgument: true);
@@ -303,8 +327,12 @@
     new OptionHandler(Flags.platformBinaries, setPlatformBinaries),
     new OptionHandler(Flags.noFrequencyBasedMinification, passThrough),
     new OptionHandler(Flags.verbose, setVerbose),
+    new OptionHandler(Flags.progress, passThrough),
     new OptionHandler(Flags.version, (_) => wantVersion = true),
-    new OptionHandler('--library-root=.+', setLibraryRoot),
+    new OptionHandler('--library-root=.+', ignoreOption),
+    new OptionHandler('--libraries-spec=.+', setLibrarySpecificationUri),
+    new OptionHandler('${Flags.readData}|${Flags.readData}=.+', setReadData),
+    new OptionHandler('${Flags.writeData}|${Flags.writeData}=.+', setWriteData),
     new OptionHandler('--out=.+|-o.*', setOutput, multipleArguments: true),
     new OptionHandler('-O.*', setOptimizationLevel),
     new OptionHandler(Flags.allowMockCompilation, ignoreOption),
@@ -337,6 +365,7 @@
     new OptionHandler(Flags.resolveOnly, ignoreOption),
     new OptionHandler(Flags.disableNativeLiveTypeAnalysis, passThrough),
     new OptionHandler('--categories=.*', setCategories),
+    new OptionHandler(Flags.serverMode, passThrough),
     new OptionHandler(Flags.disableInlining, passThrough),
     new OptionHandler(Flags.disableProgramSplit, passThrough),
     new OptionHandler(Flags.disableTypeInference, passThrough),
@@ -455,8 +484,26 @@
     helpAndFail("Cannot specify both '--package-root' and '--packages.");
   }
 
+  String scriptName = arguments[0];
+
+  switch (compilationStrategy) {
+    case CompilationStrategy.direct:
+      out ??= currentDirectory.resolve('out.js');
+      break;
+    case CompilationStrategy.toData:
+      out ??= currentDirectory.resolve('out.dill');
+      writeDataUri ??= currentDirectory.resolve('$out.data');
+      options.add('${Flags.writeData}=${writeDataUri}');
+      break;
+    case CompilationStrategy.fromData:
+      out ??= currentDirectory.resolve('out.js');
+      readDataUri ??= currentDirectory.resolve('$scriptName.data');
+      options.add('${Flags.readData}=${readDataUri}');
+      break;
+  }
   options.add('--out=$out');
-  options.add('--source-map=$sourceMapOut');
+  sourceMapOut = Uri.parse('$out.map');
+  options.add('--source-map=${sourceMapOut}');
 
   RandomAccessFileOutputProvider outputProvider =
       new RandomAccessFileOutputProvider(out, sourceMapOut,
@@ -468,45 +515,89 @@
     }
     writeString(
         Uri.parse('$out.deps'), getDepsOutput(inputProvider.getSourceUris()));
-    int dartCharactersRead = inputProvider.dartCharactersRead;
-    int jsCharactersWritten = outputProvider.totalCharactersWrittenJavaScript;
-    int jsCharactersPrimary = outputProvider.totalCharactersWrittenPrimary;
+    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');
 
-    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.');
+          }
+        }
+        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);
+        String dataOutput =
+            relativize(currentDirectory, writeDataUri, Platform.isWindows);
+        print('Dart file ($input) serialized to '
+            '${dillOutput} 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');
 
-    diagnosticHandler.info(
-        '${_formatCharacterCount(jsCharactersPrimary)} characters JavaScript'
-        ' in '
-        '${relativize(currentDirectory, out, Platform.isWindows)}');
-    if (diagnosticHandler.verbose) {
-      String input = uriPathToNative(arguments[0]);
-      print('Dart file ($input) compiled to JavaScript.');
-      print('Wrote the following files:');
-      for (String filename in outputProvider.allOutputFiles) {
-        print("  $filename");
-      }
-    } else if (outputSpecified) {
-      String input = uriPathToNative(arguments[0]);
-      String output = relativize(currentDirectory, out, Platform.isWindows);
-      print('Dart file ($input) compiled to JavaScript: $output');
+        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.');
+          }
+        }
+        break;
     }
+
     return result;
   }
 
-  Uri script = currentDirectory.resolve(arguments[0]);
+  Uri script = currentDirectory.resolve(scriptName);
+
   diagnosticHandler.autoReadFileUri = true;
   CompilerOptions compilerOptions = CompilerOptions.parse(options,
-      libraryRoot: libraryRoot, platformBinaries: platformBinaries)
+      librariesSpecificationUri: librariesSpecificationUri,
+      platformBinaries: platformBinaries)
     ..entryPoint = script
     ..packageRoot = packageRoot
     ..packageConfig = packageConfig
     ..environment = environment
-    ..packagesDiscoveryProvider = findPackages
     ..kernelInitializedCompilerState = kernelInitializedCompilerState
     ..optimizationLevel = optimizationLevel;
   return compileFunc(
@@ -563,13 +654,15 @@
 
 Future<api.CompilationResult> compilerMain(List<String> arguments,
     {fe.InitializedCompilerState kernelInitializedCompilerState}) async {
-  Uri script = Platform.script;
-  if (script.isScheme("package")) {
-    script = await Isolate.resolvePackageUri(script);
+  if (!arguments.any((a) => a.startsWith('--libraries-spec='))) {
+    Uri script = Platform.script;
+    if (script.isScheme("package")) {
+      script = await Isolate.resolvePackageUri(script);
+    }
+    Uri librariesJson = script.resolve(_defaultSpecificationUri);
+    arguments = <String>['--libraries-spec=${librariesJson.toFilePath()}']
+      ..addAll(arguments);
   }
-  Uri libraryRoot = script.resolve(LIBRARY_ROOT);
-  arguments = <String>['--library-root=${libraryRoot.toFilePath()}']
-    ..addAll(arguments);
   return compile(arguments,
       kernelInitializedCompilerState: kernelInitializedCompilerState);
 }
@@ -741,8 +834,8 @@
   --throw-on-error
     Throw an exception if a compile-time error is detected.
 
-  --library-root=<directory>
-    Where to find the Dart platform libraries.
+  --libraries-spec=<file>
+    A .json file containing the libraries specification for dart2js.
 
   --allow-mock-compilation
     Do not generate a call to main if either of the following
@@ -752,11 +845,14 @@
     Disable the optimization that removes unused native types from dart:html
     and related libraries.
 
+  --server-mode
+    Compile with server support. The compiler will use a library specification
+    that disables dart:html but supports dart:js in conditional imports.
+
   --categories=<categories>
-    A comma separated list of allowed library categories.  The default
-    is "Client".  Possible categories can be seen by providing an
-    unsupported category, for example, --categories=help.  To enable
-    all categories, use --categories=all.
+    (deprecated)
+    Use '--server-mode' instead of '--categories=Server'. All other category
+    values have no effect on the compiler behavior.
 
   --deferred-map=<file>
     Generates a json file with a mapping from each deferred import to a list of
@@ -908,3 +1004,5 @@
     });
   });
 }
+
+enum CompilationStrategy { direct, toData, fromData }
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 7243452..a7e2e97 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -8,13 +8,12 @@
 
 import 'common/tasks.dart' show CompilerTask;
 import 'common.dart';
-import 'common_elements.dart' show KElementEnvironment;
+import 'common_elements.dart' show ElementEnvironment, KElementEnvironment;
 import 'compiler.dart' show Compiler;
 import 'constants/values.dart'
     show
         ConstantValue,
         ConstructedConstantValue,
-        DeferredConstantValue,
         TypeConstantValue,
         DeferredGlobalConstantValue,
         InstantiationConstantValue;
@@ -23,6 +22,7 @@
 import 'kernel/kelements.dart' show KLocalFunction;
 import 'library_loader.dart';
 import 'serialization/serialization.dart';
+import 'options.dart';
 import 'universe/use.dart';
 import 'universe/world_impact.dart'
     show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl;
@@ -99,16 +99,6 @@
 
   static const ImpactUseCase IMPACT_USE = const ImpactUseCase('Deferred load');
 
-  /// A mapping from the name of a defer import to all the output units it
-  /// depends on in a list of lists to be loaded in the order they appear.
-  ///
-  /// For example {"lib1": [[lib1_lib2_lib3], [lib1_lib2, lib1_lib3],
-  /// [lib1]]} would mean that in order to load "lib1" first the hunk
-  /// lib1_lib2_lib2 should be loaded, then the hunks lib1_lib2 and lib1_lib3
-  /// can be loaded in parallel. And finally lib1 can be loaded.
-  final Map<String, List<OutputUnit>> hunksToLoad =
-      new Map<String, List<OutputUnit>>();
-
   /// A cache of the result of calling `computeImportDeferName` on the keys of
   /// this map.
   final Map<ImportEntity, String> _importDeferName = <ImportEntity, String>{};
@@ -127,7 +117,7 @@
   Map<ConstantValue, ImportSet> _constantToSet =
       new Map<ConstantValue, ImportSet>();
 
-  Iterable<ImportEntity> get allDeferredImports =>
+  Iterable<ImportEntity> get _allDeferredImports =>
       _deferredImportDescriptions.keys;
 
   /// Because the token-stream is forgotten later in the program, we cache a
@@ -152,29 +142,6 @@
       compiler.frontendStrategy.elementEnvironment;
   DiagnosticReporter get reporter => compiler.reporter;
 
-  /// Returns the unique name for the given deferred [import].
-  String getImportDeferName(Spannable node, ImportEntity import) {
-    String name = _importDeferName[import];
-    if (name == null) {
-      reporter.internalError(node, "No deferred name for $import.");
-    }
-    return name;
-  }
-
-  /// Returns the names associated with each deferred import in [unit].
-  Iterable<String> getImportNames(OutputUnit unit) {
-    return unit._imports.map((i) => _importDeferName[i]);
-  }
-
-  void registerConstantDeferredUse(
-      DeferredConstantValue constant, ImportEntity import) {
-    if (!isProgramSplit || disableProgramSplit) return;
-    var newSet = importSets.singleton(import);
-    assert(
-        _constantToSet[constant] == null || _constantToSet[constant] == newSet);
-    _constantToSet[constant] = newSet;
-  }
-
   /// Given [imports] that refer to an element from a library, determine whether
   /// the element is explicitly deferred.
   static bool _isExplicitlyDeferred(Iterable<ImportEntity> imports) {
@@ -554,16 +521,6 @@
     }
 
     for (ConstantValue dependency in dependencies.constants) {
-      // TODO(sigmund): either delete DeferredConstantValue or use it to
-      // represent deferred TypeConstantValues below.
-      if (dependency is DeferredConstantValue) {
-        if (_shouldAddDeferredDependency(newSet)) {
-          queue.addConstant(
-              dependency, importSets.singleton(dependency.import));
-        }
-        continue;
-      }
-
       if (dependency is TypeConstantValue) {
         var type = dependency.representedType;
         var imports = const <ImportEntity>[];
@@ -618,10 +575,11 @@
     _allOutputUnits.sort();
   }
 
-  void _setupHunksToLoad() {
+  Map<String, List<OutputUnit>> _setupHunksToLoad() {
+    Map<String, List<OutputUnit>> hunksToLoad = {};
     Set<String> usedImportNames = new Set<String>();
 
-    for (ImportEntity import in allDeferredImports) {
+    for (ImportEntity import in _allDeferredImports) {
       String result = computeImportDeferName(import, compiler);
       assert(result != null);
       // Note: tools that process the json file to build multi-part initial load
@@ -645,7 +603,7 @@
     List<OutputUnit> sortedOutputUnits = _allOutputUnits.reversed.toList();
 
     // For each deferred import we find out which outputUnits to load.
-    for (ImportEntity import in allDeferredImports) {
+    for (ImportEntity import in _allDeferredImports) {
       // We expect to find an entry for any call to `loadLibrary`, even if
       // there is no code to load. In that case, the entry will be an empty
       // list.
@@ -657,6 +615,7 @@
         }
       }
     }
+    return hunksToLoad;
   }
 
   /// Returns a name for a deferred import.
@@ -794,7 +753,7 @@
 
   OutputUnitData _buildResult() {
     _createOutputUnits();
-    _setupHunksToLoad();
+    Map<String, List<OutputUnit>> hunksToLoad = _setupHunksToLoad();
     Map<ClassEntity, OutputUnit> classMap = <ClassEntity, OutputUnit>{};
     Map<MemberEntity, OutputUnit> memberMap = <MemberEntity, OutputUnit>{};
     Map<Local, OutputUnit> localFunctionMap = <Local, OutputUnit>{};
@@ -817,7 +776,10 @@
         memberMap,
         localFunctionMap,
         constantMap,
-        _allOutputUnits);
+        _allOutputUnits,
+        _importDeferName,
+        hunksToLoad,
+        _deferredImportDescriptions);
   }
 
   /// Frees up strategy-specific temporary data.
@@ -846,62 +808,6 @@
   /// skipped by the new compiler pipeline.
   void checkForDeferredErrorCases(LibraryEntity library);
 
-  /// Returns a json-style map for describing what files that are loaded by a
-  /// given deferred import.
-  /// The mapping is structured as:
-  /// library uri -> {"name": library name, "files": (prefix -> list of files)}
-  /// Where
-  ///
-  /// - <library uri> is the relative uri of the library making a deferred
-  ///   import.
-  /// - <library name> is the name of the library, or "<unnamed>" if it is
-  ///   unnamed.
-  /// - <prefix> is the `as` prefix used for a given deferred import.
-  /// - <list of files> is a list of the filenames the must be loaded when that
-  ///   import is loaded.
-  Map<String, Map<String, dynamic>> computeDeferredMap(
-      {Set<OutputUnit> omittedUnits}) {
-    omittedUnits ??= Set();
-    Map<String, Map<String, dynamic>> mapping = {};
-
-    _deferredImportDescriptions.keys.forEach((ImportEntity import) {
-      List<OutputUnit> outputUnits = hunksToLoad[_importDeferName[import]];
-      ImportDescription description = _deferredImportDescriptions[import];
-      String getName(LibraryEntity library) {
-        var name = elementEnvironment.getLibraryName(library);
-        return name == '' ? '<unnamed>' : name;
-      }
-
-      Map<String, dynamic> libraryMap = mapping.putIfAbsent(
-          description.importingUri,
-          () => <String, dynamic>{
-                "name": getName(description._importingLibrary),
-                "imports": <String, List<String>>{}
-              });
-
-      List<String> partFileNames = outputUnits
-          .where((outputUnit) => !omittedUnits.contains(outputUnit))
-          .map((outputUnit) => deferredPartFileName(outputUnit.name))
-          .toList();
-      libraryMap["imports"][_importDeferName[import]] = partFileNames;
-    });
-    return mapping;
-  }
-
-  /// Returns the filename for the output-unit named [name].
-  ///
-  /// The filename is of the form "<main output file>_<name>.part.js".
-  /// If [addExtension] is false, the ".part.js" suffix is left out.
-  String deferredPartFileName(String name, {bool addExtension: true}) {
-    assert(name != "");
-    String outPath = compiler.options.outputUri != null
-        ? compiler.options.outputUri.path
-        : "out";
-    String outName = outPath.substring(outPath.lastIndexOf('/') + 1);
-    String extension = addExtension ? ".part.js" : "";
-    return "${outName}_$name$extension";
-  }
-
   bool ignoreEntityInDump(Entity element) => false;
 
   /// Creates a textual representation of the output unit content.
@@ -995,12 +901,16 @@
 
   final LibraryEntity _importingLibrary;
 
+  ImportDescription.internal(
+      this.importingUri, this.prefix, this._importingLibrary);
+
   ImportDescription(
       ImportEntity import, LibraryEntity importingLibrary, Uri mainLibraryUri)
-      : importingUri = uri_extras.relativize(
-            mainLibraryUri, importingLibrary.canonicalUri, false),
-        prefix = import.name,
-        _importingLibrary = importingLibrary;
+      : this.internal(
+            uri_extras.relativize(
+                mainLibraryUri, importingLibrary.canonicalUri, false),
+            import.name,
+            importingLibrary);
 }
 
 /// Indirectly represents a deferred import in an [ImportSet].
@@ -1283,6 +1193,20 @@
   final Map<Local, OutputUnit> _localFunctionToUnit;
   final Map<ConstantValue, OutputUnit> _constantToUnit;
   final Iterable<OutputUnit> outputUnits;
+  final Map<ImportEntity, String> _importDeferName;
+
+  /// A mapping from the name of a defer import to all the output units it
+  /// depends on in a list of lists to be loaded in the order they appear.
+  ///
+  /// For example {"lib1": [[lib1_lib2_lib3], [lib1_lib2, lib1_lib3],
+  /// [lib1]]} would mean that in order to load "lib1" first the hunk
+  /// lib1_lib2_lib2 should be loaded, then the hunks lib1_lib2 and lib1_lib3
+  /// can be loaded in parallel. And finally lib1 can be loaded.
+  final Map<String, List<OutputUnit>> hunksToLoad;
+
+  /// Because the token-stream is forgotten later in the program, we cache a
+  /// description of each deferred import.
+  final Map<ImportEntity, ImportDescription> _deferredImportDescriptions;
 
   OutputUnitData(
       this.isProgramSplit,
@@ -1291,11 +1215,15 @@
       this._memberToUnit,
       this._localFunctionToUnit,
       this._constantToUnit,
-      this.outputUnits);
+      this.outputUnits,
+      this._importDeferName,
+      this.hunksToLoad,
+      this._deferredImportDescriptions);
 
   // Creates J-world data from the K-world data.
-  OutputUnitData.from(
+  factory OutputUnitData.from(
       OutputUnitData other,
+      LibraryEntity convertLibrary(LibraryEntity library),
       Map<ClassEntity, OutputUnit> Function(
               Map<ClassEntity, OutputUnit>, Map<Local, OutputUnit>)
           convertClassMap,
@@ -1303,35 +1231,44 @@
               Map<MemberEntity, OutputUnit>, Map<Local, OutputUnit>)
           convertMemberMap,
       Map<ConstantValue, OutputUnit> Function(Map<ConstantValue, OutputUnit>)
-          convertConstantMap)
-      : isProgramSplit = other.isProgramSplit,
-        mainOutputUnit = other.mainOutputUnit,
-        this.outputUnits = other.outputUnits,
-        _memberToUnit =
-            convertMemberMap(other._memberToUnit, other._localFunctionToUnit),
-        _classToUnit =
-            convertClassMap(other._classToUnit, other._localFunctionToUnit),
+          convertConstantMap) {
+    Map<ClassEntity, OutputUnit> classToUnit =
+        convertClassMap(other._classToUnit, other._localFunctionToUnit);
+    Map<MemberEntity, OutputUnit> memberToUnit =
+        convertMemberMap(other._memberToUnit, other._localFunctionToUnit);
+    Map<ConstantValue, OutputUnit> constantToUnit =
+        convertConstantMap(other._constantToUnit);
+    Map<ImportEntity, ImportDescription> deferredImportDescriptions = {};
+    other._deferredImportDescriptions
+        .forEach((ImportEntity import, ImportDescription description) {
+      deferredImportDescriptions[import] = new ImportDescription.internal(
+          description.importingUri,
+          description.prefix,
+          convertLibrary(description._importingLibrary));
+    });
+
+    return new OutputUnitData(
+        other.isProgramSplit,
+        other.mainOutputUnit,
+        classToUnit,
+        memberToUnit,
         // Local functions only make sense in the K-world model.
-        _localFunctionToUnit = const <Local, OutputUnit>{},
-        _constantToUnit = convertConstantMap(other._constantToUnit);
+        const <Local, OutputUnit>{},
+        constantToUnit,
+        other.outputUnits,
+        other._importDeferName,
+        other.hunksToLoad,
+        deferredImportDescriptions);
+  }
 
   /// Deserializes an [OutputUnitData] object from [source].
   factory OutputUnitData.readFromDataSource(DataSource source) {
     source.begin(tag);
     bool isProgramSplit = source.readBool();
-    List<ImportEntity> imports = source.readList(() {
-      String name = source.readString();
-      Uri uri = source.readUri();
-      Uri enclosingLibraryUri = source.readUri();
-      bool isDeferred = source.readBool();
-      return new ImportEntity(isDeferred, name, uri, enclosingLibraryUri);
-    });
     List<OutputUnit> outputUnits = source.readList(() {
       bool isMainOutput = source.readBool();
       String name = source.readString();
-      Set<ImportEntity> importSet = source.readList(() {
-        return imports[source.readInt()];
-      }).toSet();
+      Set<ImportEntity> importSet = source.readImports().toSet();
       return new OutputUnit(isMainOutput, name, importSet);
     });
     OutputUnit mainOutputUnit = outputUnits[source.readInt()];
@@ -1345,6 +1282,21 @@
     Map<ConstantValue, OutputUnit> constantToUnit = source.readConstantMap(() {
       return outputUnits[source.readInt()];
     });
+    Map<ImportEntity, String> importDeferName =
+        source.readImportMap(source.readString);
+    Map<String, List<OutputUnit>> hunksToLoad = source.readStringMap(() {
+      return source.readList(() {
+        return outputUnits[source.readInt()];
+      });
+    });
+    Map<ImportEntity, ImportDescription> deferredImportDescriptions =
+        source.readImportMap(() {
+      String importingUri = source.readString();
+      String prefix = source.readString();
+      LibraryEntity importingLibrary = source.readLibrary();
+      return new ImportDescription.internal(
+          importingUri, prefix, importingLibrary);
+    });
     source.end(tag);
     return new OutputUnitData(
         isProgramSplit,
@@ -1354,33 +1306,22 @@
         // Local functions only make sense in the K-world model.
         const <Local, OutputUnit>{},
         constantToUnit,
-        outputUnits);
+        outputUnits,
+        importDeferName,
+        hunksToLoad,
+        deferredImportDescriptions);
   }
 
   /// Serializes this [OutputUnitData] to [sink].
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
     sink.writeBool(isProgramSplit);
-    Map<ImportEntity, int> importIndex = {};
-    for (OutputUnit outputUnit in outputUnits) {
-      for (ImportEntity import in outputUnit._imports) {
-        importIndex[import] ??= importIndex.length;
-      }
-    }
-    sink.writeList(importIndex.keys, (ImportEntity import) {
-      sink.writeString(import.name);
-      sink.writeUri(import.uri);
-      sink.writeUri(import.enclosingLibraryUri);
-      sink.writeBool(import.isDeferred);
-    });
     Map<OutputUnit, int> outputUnitIndices = {};
     sink.writeList(outputUnits, (OutputUnit outputUnit) {
       outputUnitIndices[outputUnit] = outputUnitIndices.length;
       sink.writeBool(outputUnit.isMainOutput);
       sink.writeString(outputUnit.name);
-      sink.writeList(outputUnit._imports, (ImportEntity import) {
-        sink.writeInt(importIndex[import]);
-      });
+      sink.writeImports(outputUnit._imports);
     });
     sink.writeInt(outputUnitIndices[mainOutputUnit]);
     sink.writeClassMap(_classToUnit, (OutputUnit outputUnit) {
@@ -1392,6 +1333,19 @@
     sink.writeConstantMap(_constantToUnit, (OutputUnit outputUnit) {
       sink.writeInt(outputUnitIndices[outputUnit]);
     });
+    sink.writeImportMap(_importDeferName, sink.writeString);
+    sink.writeStringMap(hunksToLoad, (List<OutputUnit> outputUnits) {
+      sink.writeList(
+          outputUnits,
+          (OutputUnit outputUnit) =>
+              sink.writeInt(outputUnitIndices[outputUnit]));
+    });
+    sink.writeImportMap(_deferredImportDescriptions,
+        (ImportDescription importDescription) {
+      sink.writeString(importDescription.importingUri);
+      sink.writeString(importDescription.prefix);
+      sink.writeLibrary(importDescription._importingLibrary);
+    });
     sink.end(tag);
   }
 
@@ -1459,6 +1413,77 @@
     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];
+    if (name == null) {
+      throw new SpannableAssertionFailure(
+          node, "No deferred name for $import.");
+    }
+    return name;
+  }
+
+  /// Returns the names associated with each deferred import in [unit].
+  Iterable<String> getImportNames(OutputUnit unit) {
+    return unit._imports.map((i) => _importDeferName[i]);
+  }
+
+  /// Returns a json-style map for describing what files that are loaded by a
+  /// given deferred import.
+  /// The mapping is structured as:
+  /// library uri -> {"name": library name, "files": (prefix -> list of files)}
+  /// Where
+  ///
+  /// - <library uri> is the relative uri of the library making a deferred
+  ///   import.
+  /// - <library name> is the name of the library, or "<unnamed>" if it is
+  ///   unnamed.
+  /// - <prefix> is the `as` prefix used for a given deferred import.
+  /// - <list of files> is a list of the filenames the must be loaded when that
+  ///   import is loaded.
+  Map<String, Map<String, dynamic>> computeDeferredMap(
+      CompilerOptions options, ElementEnvironment elementEnvironment,
+      {Set<OutputUnit> omittedUnits}) {
+    omittedUnits ??= Set();
+    Map<String, Map<String, dynamic>> mapping = {};
+
+    _deferredImportDescriptions.keys.forEach((ImportEntity import) {
+      List<OutputUnit> outputUnits = hunksToLoad[_importDeferName[import]];
+      ImportDescription description = _deferredImportDescriptions[import];
+      String getName(LibraryEntity library) {
+        var name = elementEnvironment.getLibraryName(library);
+        return name == '' ? '<unnamed>' : name;
+      }
+
+      Map<String, dynamic> libraryMap = mapping.putIfAbsent(
+          description.importingUri,
+          () => <String, dynamic>{
+                "name": getName(description._importingLibrary),
+                "imports": <String, List<String>>{}
+              });
+
+      List<String> partFileNames = outputUnits
+          .where((outputUnit) => !omittedUnits.contains(outputUnit))
+          .map((outputUnit) => deferredPartFileName(options, outputUnit.name))
+          .toList();
+      libraryMap["imports"][_importDeferName[import]] = partFileNames;
+    });
+    return mapping;
+  }
+}
+
+/// Returns the filename for the output-unit named [name].
+///
+/// The filename is of the form "<main output file>_<name>.part.js".
+/// If [addExtension] is false, the ".part.js" suffix is left out.
+String deferredPartFileName(CompilerOptions options, String name,
+    {bool addExtension: true}) {
+  assert(name != "");
+  String outPath = options.outputUri != null ? options.outputUri.path : "out";
+  String outName = outPath.substring(outPath.lastIndexOf('/') + 1);
+  String extension = addExtension ? ".part.js" : "";
+  return "${outName}_$name$extension";
 }
 
 class Dependencies {
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index f05939b..f9f6392 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -23,7 +23,7 @@
 import 'types/abstract_value_domain.dart';
 import 'types/types.dart'
     show GlobalTypeInferenceMemberResult, GlobalTypeInferenceResults;
-import 'universe/world_builder.dart' show CodegenWorldBuilder;
+import 'universe/codegen_world_builder.dart';
 import 'universe/world_impact.dart'
     show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl;
 import 'world.dart' show JClosedWorld;
@@ -353,7 +353,8 @@
       assert(outputUnit.name != null || outputUnit.isMainOutput);
       OutputUnitInfo info = new OutputUnitInfo(
           outputUnit.name, backend.emitter.emitter.generatedSize(outputUnit));
-      info.imports.addAll(compiler.deferredLoadTask.getImportNames(outputUnit));
+      info.imports
+          .addAll(closedWorld.outputUnitData.getImportNames(outputUnit));
       result.outputUnits.add(info);
       return info;
     });
@@ -613,7 +614,8 @@
       }
     }
 
-    result.deferredFiles = compiler.deferredLoadTask.computeDeferredMap();
+    result.deferredFiles = closedWorld.outputUnitData
+        .computeDeferredMap(compiler.options, closedWorld.elementEnvironment);
     stopwatch.stop();
 
     result.program = new ProgramInfo(
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index d869e48..e040474 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -571,7 +571,17 @@
       this.optionalParameterTypes,
       this.namedParameters,
       this.namedParameterTypes,
-      this.typeVariables);
+      this.typeVariables) {
+    assert(returnType != null, "Invalid return type in $this.");
+    assert(!parameterTypes.contains(null), "Invalid parameter types in $this.");
+    assert(!optionalParameterTypes.contains(null),
+        "Invalid optional parameter types in $this.");
+    assert(
+        !namedParameters.contains(null), "Invalid named parameters in $this.");
+    assert(!namedParameterTypes.contains(null),
+        "Invalid named parameter types in $this.");
+    assert(!typeVariables.contains(null), "Invalid type variables in $this.");
+  }
 
   bool get containsTypeVariables {
     return typeVariables.any((type) => type.bound.containsTypeVariables) ||
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 3cef111..69c7ca5 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -17,6 +17,8 @@
 import 'elements/types.dart';
 import 'js_backend/enqueuer.dart';
 import 'types/types.dart';
+import 'universe/member_usage.dart';
+import 'universe/resolution_world_builder.dart';
 import 'universe/world_builder.dart';
 import 'universe/use.dart'
     show
diff --git a/pkg/compiler/lib/src/frontend_strategy.dart b/pkg/compiler/lib/src/frontend_strategy.dart
index dcd11fc..3743e66 100644
--- a/pkg/compiler/lib/src/frontend_strategy.dart
+++ b/pkg/compiler/lib/src/frontend_strategy.dart
@@ -22,6 +22,7 @@
 import 'native/enqueue.dart' show NativeResolutionEnqueuer;
 import 'native/resolver.dart';
 import 'universe/class_hierarchy.dart';
+import 'universe/resolution_world_builder.dart';
 import 'universe/world_builder.dart';
 import 'universe/world_impact.dart';
 
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index c494d4d..7c2d111 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -15,7 +15,7 @@
 import '../js_backend/backend.dart';
 import '../js_model/element_map.dart';
 import '../js_model/locals.dart' show JumpVisitor;
-import '../js_model/js_strategy.dart';
+import '../js_model/js_world.dart';
 import '../native/behavior.dart';
 import '../options.dart';
 import '../types/abstract_value_domain.dart';
@@ -56,6 +56,7 @@
       <JumpTarget, List<LocalsHandler>>{};
   TypeInformation _returnType;
   final Set<Local> _capturedVariables = new Set<Local>();
+  final Map<Local, FieldEntity> _capturedAndBoxed;
 
   /// Whether we currently collect [IsCheck]s.
   bool _accumulateIsChecks = false;
@@ -69,7 +70,7 @@
 
   KernelTypeGraphBuilder(this._options, this._closedWorld, this._inferrer,
       this._analyzedMember, this._analyzedNode, this._localsMap,
-      [this._locals])
+      [this._locals, Map<Local, FieldEntity> capturedAndBoxed])
       : this._types = _inferrer.types,
         this._memberData = _inferrer.dataOfMember(_analyzedMember),
         // TODO(johnniwinther): Should side effects also be tracked for field
@@ -78,13 +79,15 @@
             ? _inferrer.inferredDataBuilder
                 .getSideEffectsBuilder(_analyzedMember)
             : new SideEffectsBuilder.free(_analyzedMember),
-        this._inGenerativeConstructor = _analyzedNode is ir.Constructor {
+        this._inGenerativeConstructor = _analyzedNode is ir.Constructor,
+        this._capturedAndBoxed = capturedAndBoxed != null
+            ? new Map<Local, FieldEntity>.from(capturedAndBoxed)
+            : <Local, FieldEntity>{} {
     if (_locals != null) return;
 
     FieldInitializationScope fieldScope =
-        _inGenerativeConstructor ? new FieldInitializationScope(_types) : null;
-    _locals = new LocalsHandler(
-        _inferrer, _types, _options, _analyzedNode, fieldScope);
+        _inGenerativeConstructor ? new FieldInitializationScope() : null;
+    _locals = new LocalsHandler(_analyzedNode, fieldScope);
   }
 
   JsToElementMap get _elementMap => _closedWorld.elementMap;
@@ -171,7 +174,7 @@
     // previous analysis of [outermostElement].
     ScopeInfo scopeInfo = _closureDataLookup.getScopeInfo(_analyzedMember);
     scopeInfo.forEachBoxedVariable((variable, field) {
-      _locals.setCapturedAndBoxed(variable, field);
+      _capturedAndBoxed[variable] = field;
     });
 
     return visit(_analyzedNode);
@@ -226,7 +229,8 @@
   void handleParameter(ir.VariableDeclaration node, {bool isOptional}) {
     Local local = _localsMap.getLocalVariable(node);
     DartType type = _localsMap.getLocalType(_elementMap, local);
-    _locals.update(local, _inferrer.typeOfParameter(local), node, type);
+    _locals.update(_inferrer, _capturedAndBoxed, local,
+        _inferrer.typeOfParameter(local), node, type);
     if (isOptional) {
       TypeInformation type;
       if (node.initializer != null) {
@@ -460,7 +464,7 @@
     if (simpleCondition) _updateIsChecks(negativeTests, positiveTests);
     visit(node.message);
     _locals.seenReturnOrThrow = true;
-    saved.mergeDiamondFlow(thenLocals, _locals);
+    saved.mergeDiamondFlow(_inferrer, thenLocals, _locals);
     _locals = saved;
     return null;
   }
@@ -489,7 +493,7 @@
       JumpTarget jumpTarget = _localsMap.getJumpTargetForLabel(node);
       _setupBreaksAndContinues(jumpTarget);
       visit(body);
-      _locals.mergeAfterBreaks(_getBreaks(jumpTarget));
+      _locals.mergeAfterBreaks(_inferrer, _getBreaks(jumpTarget));
       _clearBreaksAndContinues(jumpTarget);
     }
     return null;
@@ -517,18 +521,18 @@
       // visit all cases and update [locals] until we have reached a
       // fixed point.
       bool changed;
-      _locals.startLoop(node);
+      _locals.startLoop(_inferrer, node);
       do {
         changed = false;
         for (ir.SwitchCase switchCase in node.cases) {
           LocalsHandler saved = _locals;
           _locals = new LocalsHandler.from(_locals, switchCase);
           visit(switchCase);
-          changed = saved.mergeAll([_locals]) || changed;
+          changed = saved.mergeAll(_inferrer, [_locals]) || changed;
           _locals = saved;
         }
       } while (changed);
-      _locals.endLoop(node);
+      _locals.endLoop(_inferrer, node);
 
       continueTargets.forEach(_clearBreaksAndContinues);
     } else {
@@ -544,7 +548,8 @@
         visit(switchCase);
         localsToMerge.add(_locals);
       }
-      saved.mergeAfterBreaks(localsToMerge, keepOwnLocals: !hasDefaultCase);
+      saved.mergeAfterBreaks(_inferrer, localsToMerge,
+          keepOwnLocals: !hasDefaultCase);
       _locals = saved;
     }
     _clearBreaksAndContinues(jumpTarget);
@@ -682,9 +687,11 @@
     Local local = _localsMap.getLocalVariable(node);
     DartType type = _localsMap.getLocalType(_elementMap, local);
     if (node.initializer == null) {
-      _locals.update(local, _types.nullType, node, type);
+      _locals.update(
+          _inferrer, _capturedAndBoxed, local, _types.nullType, node, type);
     } else {
-      _locals.update(local, visit(node.initializer), node, type);
+      _locals.update(_inferrer, _capturedAndBoxed, local,
+          visit(node.initializer), node, type);
     }
     if (node.initializer is ir.ThisExpression) {
       _markThisAsExposed();
@@ -695,7 +702,7 @@
   @override
   TypeInformation visitVariableGet(ir.VariableGet node) {
     Local local = _localsMap.getLocalVariable(node.variable);
-    TypeInformation type = _locals.use(local);
+    TypeInformation type = _locals.use(_inferrer, _capturedAndBoxed, local);
     assert(type != null, "Missing type information for $local.");
     return type;
   }
@@ -708,7 +715,7 @@
     }
     Local local = _localsMap.getLocalVariable(node.variable);
     DartType type = _localsMap.getLocalType(_elementMap, local);
-    _locals.update(local, rhsType, node, type);
+    _locals.update(_inferrer, _capturedAndBoxed, local, rhsType, node, type);
     return rhsType;
   }
 
@@ -820,7 +827,8 @@
         TypeInformation refinedType = _types
             .refineReceiver(selector, mask, receiverType, isConditional: false);
         DartType type = _localsMap.getLocalType(_elementMap, local);
-        _locals.update(local, refinedType, node, type);
+        _locals.update(
+            _inferrer, _capturedAndBoxed, local, refinedType, node, type);
         List<Refinement> refinements = _localRefinementMap[variable];
         if (refinements != null) {
           refinements.add(new Refinement(selector, mask));
@@ -903,12 +911,14 @@
       if (refinements.isNotEmpty) {
         Local local = _localsMap.getLocalVariable(alias);
         DartType type = _localsMap.getLocalType(_elementMap, local);
-        TypeInformation localType = _locals.use(local);
+        TypeInformation localType =
+            _locals.use(_inferrer, _capturedAndBoxed, local);
         for (Refinement refinement in refinements) {
           localType = _types.refineReceiver(
               refinement.selector, refinement.mask, localType,
               isConditional: true);
-          _locals.update(local, localType, node, type);
+          _locals.update(
+              _inferrer, _capturedAndBoxed, local, localType, node, type);
         }
       }
     }
@@ -961,7 +971,8 @@
 
     Local variable = _localsMap.getLocalVariable(node.variable);
     DartType variableType = _localsMap.getLocalType(_elementMap, variable);
-    _locals.update(variable, currentType, node.variable, variableType);
+    _locals.update(_inferrer, _capturedAndBoxed, variable, currentType,
+        node.variable, variableType);
 
     JumpTarget target = _localsMap.getJumpTargetForForIn(node);
     return handleLoop(node, target, () {
@@ -1002,19 +1013,20 @@
     _loopLevel++;
     bool changed = false;
     LocalsHandler saved = _locals;
-    saved.startLoop(node);
+    saved.startLoop(_inferrer, node);
     do {
       // Setup (and clear in case of multiple iterations of the loop)
       // the lists of breaks and continues seen in the loop.
       _setupBreaksAndContinues(target);
       _locals = new LocalsHandler.from(saved, node);
       logic();
-      changed = saved.mergeAll(_getLoopBackEdges(target));
+      changed = saved.mergeAll(_inferrer, _getLoopBackEdges(target));
     } while (changed);
     _loopLevel--;
-    saved.endLoop(node);
+    saved.endLoop(_inferrer, node);
     bool keepOwnLocals = node is! ir.DoStatement;
-    saved.mergeAfterBreaks(_getBreaks(target), keepOwnLocals: keepOwnLocals);
+    saved.mergeAfterBreaks(_inferrer, _getBreaks(target),
+        keepOwnLocals: keepOwnLocals);
     _locals = saved;
     _clearBreaksAndContinues(target);
     return null;
@@ -1342,18 +1354,20 @@
       List<IsCheck> positiveTests, List<IsCheck> negativeTests) {
     for (IsCheck check in positiveTests) {
       if (check.type != null) {
-        _locals.narrow(check.local, check.type, check.node);
+        _locals.narrow(
+            _inferrer, _capturedAndBoxed, check.local, check.type, check.node);
       } else {
         DartType localType = _localsMap.getLocalType(_elementMap, check.local);
-        _locals.update(check.local, _types.nullType, check.node, localType);
+        _locals.update(_inferrer, _capturedAndBoxed, check.local,
+            _types.nullType, check.node, localType);
       }
     }
     for (IsCheck check in negativeTests) {
       if (check.type != null) {
         // TODO(johnniwinther): Use negative type knowledge.
       } else {
-        _locals.narrow(
-            check.local, _closedWorld.commonElements.objectType, check.node);
+        _locals.narrow(_inferrer, _capturedAndBoxed, check.local,
+            _closedWorld.commonElements.objectType, check.node);
       }
     }
   }
@@ -1374,7 +1388,7 @@
       _updateIsChecks(negativeTests, positiveTests);
     }
     visit(node.otherwise);
-    saved.mergeDiamondFlow(thenLocals, _locals);
+    saved.mergeDiamondFlow(_inferrer, thenLocals, _locals);
     _locals = saved;
     return null;
   }
@@ -1431,7 +1445,7 @@
         _positiveIsChecks.removeWhere(invalidatedInRightHandSide);
         _negativeIsChecks.removeWhere(invalidatedInRightHandSide);
       }
-      saved.mergeDiamondFlow(_locals, null);
+      saved.mergeDiamondFlow(_inferrer, _locals, null);
       _locals = saved;
       return _types.boolType;
     } else if (node.operator == '||') {
@@ -1446,7 +1460,7 @@
         _updateIsChecks(negativeIsChecks, positiveIsChecks);
       }
       visit(node.right, conditionContext: false);
-      saved.mergeDiamondFlow(_locals, null);
+      saved.mergeDiamondFlow(_inferrer, _locals, null);
       _locals = saved;
       return _types.boolType;
     }
@@ -1469,7 +1483,7 @@
     _locals = new LocalsHandler.from(saved, node);
     if (simpleCondition) _updateIsChecks(negativeTests, positiveTests);
     TypeInformation secondType = visit(node.otherwise);
-    saved.mergeDiamondFlow(thenLocals, _locals);
+    saved.mergeDiamondFlow(_inferrer, thenLocals, _locals);
     _locals = saved;
     return _types.allocateDiamondPhi(firstType, secondType);
   }
@@ -1489,8 +1503,8 @@
     // Record the types of captured non-boxed variables. Types of
     // these variables may already be there, because of an analysis of
     // a previous closure.
-    info.forEachFreeVariable((variable, field) {
-      if (!info.isVariableBoxed(variable)) {
+    info.forEachFreeVariable((Local variable, FieldEntity field) {
+      if (!info.isBoxedVariable(variable)) {
         if (variable == info.thisLocal) {
           _inferrer.recordTypeOfField(field, thisType);
         }
@@ -1508,7 +1522,8 @@
     if (variable != null) {
       Local local = _localsMap.getLocalVariable(variable);
       DartType type = _localsMap.getLocalType(_elementMap, local);
-      _locals.update(local, localFunctionType, node, type);
+      _locals.update(
+          _inferrer, _capturedAndBoxed, local, localFunctionType, node, type);
     }
 
     // We don't put the closure in the work queue of the
@@ -1523,7 +1538,8 @@
         info.callMethod,
         functionNode,
         _localsMap,
-        closureLocals);
+        closureLocals,
+        _capturedAndBoxed);
     visitor.run();
     _inferrer.recordReturnType(info.callMethod, visitor._returnType);
 
@@ -1590,13 +1606,13 @@
         isTry: true, useOtherTryBlock: false);
     initializationIsIndefinite();
     visit(node.body);
-    saved.mergeDiamondFlow(_locals, null);
+    saved.mergeDiamondFlow(_inferrer, _locals, null);
     _locals = saved;
     for (ir.Catch catchBlock in node.catches) {
       saved = _locals;
       _locals = new LocalsHandler.from(_locals, catchBlock);
       visit(catchBlock);
-      saved.mergeDiamondFlow(_locals, null);
+      saved.mergeDiamondFlow(_inferrer, _locals, null);
       _locals = saved;
     }
     return null;
@@ -1609,7 +1625,7 @@
         isTry: true, useOtherTryBlock: false);
     initializationIsIndefinite();
     visit(node.body);
-    saved.mergeDiamondFlow(_locals, null);
+    saved.mergeDiamondFlow(_inferrer, _locals, null);
     _locals = saved;
     visit(node.finalizer);
     return null;
@@ -1630,13 +1646,15 @@
         mask = _types.dynamicType;
       }
       Local local = _localsMap.getLocalVariable(exception);
-      _locals.update(local, mask, node, const DynamicType());
+      _locals.update(
+          _inferrer, _capturedAndBoxed, local, mask, node, const DynamicType());
     }
     ir.VariableDeclaration stackTrace = node.stackTrace;
     if (stackTrace != null) {
       Local local = _localsMap.getLocalVariable(stackTrace);
       // TODO(johnniwinther): Use a mask based on [StackTrace].
-      _locals.update(local, _types.dynamicType, node, const DynamicType());
+      _locals.update(_inferrer, _capturedAndBoxed, local, _types.dynamicType,
+          node, const DynamicType());
     }
     visit(node.body);
     return null;
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index 5ce0f07..835c405 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -17,7 +17,7 @@
 import '../js_backend/inferred_data.dart';
 import '../js_backend/no_such_method_registry.dart';
 import '../js_model/element_map.dart';
-import '../js_model/js_strategy.dart';
+import '../js_model/js_world.dart';
 import '../js_model/locals.dart';
 import '../native/behavior.dart' as native;
 import '../options.dart';
@@ -388,7 +388,7 @@
 
   void updateSelectorInMember(MemberEntity owner, CallType callType,
       ir.Node node, Selector selector, AbstractValue mask) {
-    GlobalTypeInferenceElementData data = dataOfMember(owner);
+    KernelGlobalTypeInferenceElementData data = dataOfMember(owner);
     assert(validCallType(callType, node));
     switch (callType) {
       case CallType.access:
@@ -473,10 +473,7 @@
   }
 
   void runOverAllElements() {
-    progress.startPhase();
-
     analyzeAllElements();
-
     TypeGraphDump dump =
         debug.PRINT_GRAPH ? new TypeGraphDump(_compilerOutput, this) : null;
 
@@ -648,6 +645,7 @@
     Iterable<MemberEntity> processedMembers = closedWorld.processedMembers
         .where((MemberEntity member) => !member.isAbstract);
 
+    progress.startPhase();
     processedMembers.forEach((MemberEntity member) {
       progress.showProgress(
           'Added ', addedInGraph, ' elements in inferencing graph.');
@@ -847,6 +845,7 @@
   }
 
   void refine() {
+    progress.startPhase();
     while (!workQueue.isEmpty) {
       progress.showProgress('Inferred ', overallRefineCount, ' types.');
       TypeInformation info = workQueue.remove();
@@ -1426,7 +1425,7 @@
   }
 
   @override
-  void compress() {
+  GlobalTypeInferenceElementData compress() {
     if (_sendMap != null) {
       _sendMap.removeWhere(_mapsToNull);
       if (_sendMap.isEmpty) {
@@ -1451,6 +1450,13 @@
         _moveNextMap = null;
       }
     }
+    if (_sendMap == null &&
+        _iteratorMap == null &&
+        _currentMap == null &&
+        _moveNextMap == null) {
+      return null;
+    }
+    return this;
   }
 
   @override
@@ -1459,23 +1465,17 @@
     return _sendMap[node];
   }
 
-  @override
-  void setCurrentTypeMask(
-      covariant ir.ForInStatement node, AbstractValue mask) {
+  void setCurrentTypeMask(ir.ForInStatement node, AbstractValue mask) {
     _currentMap ??= <ir.ForInStatement, AbstractValue>{};
     _currentMap[node] = mask;
   }
 
-  @override
-  void setMoveNextTypeMask(
-      covariant ir.ForInStatement node, AbstractValue mask) {
+  void setMoveNextTypeMask(ir.ForInStatement node, AbstractValue mask) {
     _moveNextMap ??= <ir.ForInStatement, AbstractValue>{};
     _moveNextMap[node] = mask;
   }
 
-  @override
-  void setIteratorTypeMask(
-      covariant ir.ForInStatement node, AbstractValue mask) {
+  void setIteratorTypeMask(ir.ForInStatement node, AbstractValue mask) {
     _iteratorMap ??= <ir.ForInStatement, AbstractValue>{};
     _iteratorMap[node] = mask;
   }
@@ -1498,7 +1498,6 @@
     return _iteratorMap[node];
   }
 
-  @override
   void setTypeMask(ir.TreeNode node, AbstractValue mask) {
     _sendMap ??= <ir.TreeNode, AbstractValue>{};
     _sendMap[node] = mask;
diff --git a/pkg/compiler/lib/src/inferrer/locals_handler.dart b/pkg/compiler/lib/src/inferrer/locals_handler.dart
index ae92797..a0ad009 100644
--- a/pkg/compiler/lib/src/inferrer/locals_handler.dart
+++ b/pkg/compiler/lib/src/inferrer/locals_handler.dart
@@ -6,13 +6,11 @@
 
 import 'dart:collection' show IterableMixin;
 import 'package:kernel/ast.dart' as ir;
-import '../options.dart' show CompilerOptions;
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../util/util.dart';
 import 'inferrer_engine.dart';
 import 'type_graph_nodes.dart';
-import 'type_system.dart';
 
 /**
  * A variable scope holds types for variables. It has a link to a
@@ -111,7 +109,6 @@
 
 /// Tracks initializers via initializations and assignments.
 class FieldInitializationScope {
-  final TypeSystem types;
   Map<FieldEntity, TypeInformation> fields;
   bool isThisExposed;
 
@@ -119,13 +116,12 @@
   /// e.g. an early return or caught exception.
   bool isIndefinite;
 
-  FieldInitializationScope(this.types)
+  FieldInitializationScope()
       : isThisExposed = false,
         isIndefinite = false;
 
   FieldInitializationScope.internalFrom(FieldInitializationScope other)
-      : types = other.types,
-        isThisExposed = other.isThisExposed,
+      : isThisExposed = other.isThisExposed,
         isIndefinite = other.isIndefinite;
 
   factory FieldInitializationScope.from(FieldInitializationScope other) {
@@ -148,7 +144,7 @@
     fields?.forEach(f);
   }
 
-  void mergeDiamondFlow(
+  void mergeDiamondFlow(InferrerEngine inferrer,
       FieldInitializationScope thenScope, FieldInitializationScope elseScope) {
     // Quick bailout check. If [isThisExposed] or [isIndefinite] is true, we
     // know the code following won'TypeInformation do anything.
@@ -161,7 +157,7 @@
     thenScope.forEach((FieldEntity field, TypeInformation type) {
       TypeInformation otherType = otherScope.readField(field);
       if (otherType == null) return;
-      updateField(field, types.allocateDiamondPhi(type, otherType));
+      updateField(field, inferrer.types.allocateDiamondPhi(type, otherType));
     });
 
     isThisExposed = thenScope.isThisExposed || elseScope.isThisExposed;
@@ -249,11 +245,7 @@
  * Placeholder for inferred types of local variables.
  */
 class LocalsHandler {
-  final CompilerOptions options;
-  final TypeSystem types;
-  final InferrerEngine inferrer;
   final VariableScope locals;
-  final Map<Local, FieldEntity> _capturedAndBoxed;
   final FieldInitializationScope fieldScope;
   LocalsHandler tryBlock;
   bool seenReturnOrThrow = false;
@@ -265,56 +257,46 @@
 
   bool get inTryBlock => tryBlock != null;
 
-  LocalsHandler(this.inferrer, this.types, this.options, ir.Node block,
-      [this.fieldScope])
+  LocalsHandler.internal(
+      ir.Node block, this.fieldScope, this.locals, this.tryBlock);
+
+  LocalsHandler(ir.Node block, [this.fieldScope])
       : locals = new VariableScope(block, isTry: false),
-        _capturedAndBoxed = new Map<Local, FieldEntity>(),
         tryBlock = null;
 
   LocalsHandler.from(LocalsHandler other, ir.Node block,
       {bool isTry: false, bool useOtherTryBlock: true})
       : locals = new VariableScope(block, isTry: isTry, parent: other.locals),
-        fieldScope = new FieldInitializationScope.from(other.fieldScope),
-        _capturedAndBoxed = other._capturedAndBoxed,
-        types = other.types,
-        inferrer = other.inferrer,
-        options = other.options {
+        fieldScope = new FieldInitializationScope.from(other.fieldScope) {
     tryBlock = useOtherTryBlock ? other.tryBlock : this;
   }
 
   LocalsHandler.deepCopyOf(LocalsHandler other)
       : locals = new VariableScope.deepCopyOf(other.locals),
         fieldScope = new FieldInitializationScope.from(other.fieldScope),
-        _capturedAndBoxed = other._capturedAndBoxed,
-        tryBlock = other.tryBlock,
-        types = other.types,
-        inferrer = other.inferrer,
-        options = other.options;
+        tryBlock = other.tryBlock;
 
   LocalsHandler.topLevelCopyOf(LocalsHandler other)
       : locals = new VariableScope.topLevelCopyOf(other.locals),
         fieldScope = new FieldInitializationScope.from(other.fieldScope),
-        _capturedAndBoxed = other._capturedAndBoxed,
-        tryBlock = other.tryBlock,
-        types = other.types,
-        inferrer = other.inferrer,
-        options = other.options;
+        tryBlock = other.tryBlock;
 
-  TypeInformation use(Local local) {
-    if (_capturedAndBoxed.containsKey(local)) {
-      FieldEntity field = _capturedAndBoxed[local];
+  TypeInformation use(InferrerEngine inferrer,
+      Map<Local, FieldEntity> capturedAndBoxed, Local local) {
+    FieldEntity field = capturedAndBoxed[local];
+    if (field != null) {
       return inferrer.typeOfMember(field);
     } else {
       return locals[local];
     }
   }
 
-  void update(
+  void update(InferrerEngine inferrer, Map<Local, FieldEntity> capturedAndBoxed,
       Local local, TypeInformation type, ir.Node node, DartType staticType,
       {bool isSetIfNull: false}) {
     assert(type != null);
-    if (!options.assignmentCheckPolicy.isIgnored) {
-      type = types.narrowType(type, staticType);
+    if (!inferrer.options.assignmentCheckPolicy.isIgnored) {
+      type = inferrer.types.narrowType(type, staticType);
     }
     updateLocal() {
       TypeInformation currentType = locals[local];
@@ -322,18 +304,19 @@
       if (isSetIfNull && currentType != null) {
         // If-null assignments may return either the new or the original value
         // narrowed to non-null.
-        type = types.addPhiInput(
+        type = inferrer.types.addPhiInput(
             local,
-            types.allocatePhi(
-                locals.block, local, types.narrowNotNull(currentType),
+            inferrer.types.allocatePhi(
+                locals.block, local, inferrer.types.narrowNotNull(currentType),
                 isTry: locals.isTry),
             type);
       }
       locals[local] = type;
     }
 
-    if (_capturedAndBoxed.containsKey(local)) {
-      inferrer.recordTypeOfField(_capturedAndBoxed[local], type);
+    FieldEntity field = capturedAndBoxed[local];
+    if (field != null) {
+      inferrer.recordTypeOfField(field, type);
     } else if (inTryBlock) {
       // We don't know if an assignment in a try block
       // will be executed, so all assignments in that block are
@@ -342,10 +325,11 @@
       // the right phi for it.
       TypeInformation existing = tryBlock.locals.parent[local];
       if (existing != null) {
-        TypeInformation phiType = types.allocatePhi(
+        TypeInformation phiType = inferrer.types.allocatePhi(
             tryBlock.locals.block, local, existing,
             isTry: tryBlock.locals.isTry);
-        TypeInformation inputType = types.addPhiInput(local, phiType, type);
+        TypeInformation inputType =
+            inferrer.types.addPhiInput(local, phiType, type);
         tryBlock.locals.parent[local] = inputType;
       }
       // Update the current handler unconditionally with the new
@@ -356,21 +340,21 @@
     }
   }
 
-  void narrow(Local local, DartType type, ir.Node node,
+  void narrow(InferrerEngine inferrer, Map<Local, FieldEntity> capturedAndBoxed,
+      Local local, DartType type, ir.Node node,
       {bool isSetIfNull: false}) {
-    TypeInformation existing = use(local);
+    TypeInformation existing = use(inferrer, capturedAndBoxed, local);
     TypeInformation newType =
-        types.narrowType(existing, type, isNullable: false);
-    update(local, newType, node, type, isSetIfNull: isSetIfNull);
+        inferrer.types.narrowType(existing, type, isNullable: false);
+    update(inferrer, capturedAndBoxed, local, newType, node, type,
+        isSetIfNull: isSetIfNull);
   }
 
-  void setCapturedAndBoxed(Local local, FieldEntity field) {
-    _capturedAndBoxed[local] = field;
-  }
-
-  void mergeDiamondFlow(LocalsHandler thenBranch, LocalsHandler elseBranch) {
+  void mergeDiamondFlow(InferrerEngine inferrer, LocalsHandler thenBranch,
+      LocalsHandler elseBranch) {
     if (fieldScope != null && elseBranch != null) {
-      fieldScope.mergeDiamondFlow(thenBranch.fieldScope, elseBranch.fieldScope);
+      fieldScope.mergeDiamondFlow(
+          inferrer, thenBranch.fieldScope, elseBranch.fieldScope);
     }
     seenReturnOrThrow = thenBranch.seenReturnOrThrow &&
         elseBranch != null &&
@@ -385,7 +369,7 @@
         TypeInformation myType = locals[local];
         if (myType == null) return; // Variable is only defined in [other].
         if (type == myType) return;
-        locals[local] = types.allocateDiamondPhi(myType, type);
+        locals[local] = inferrer.types.allocateDiamondPhi(myType, type);
       });
     }
 
@@ -414,7 +398,7 @@
         if (thenType == elseType) {
           locals[local] = thenType;
         } else {
-          locals[local] = types.allocateDiamondPhi(thenType, elseType);
+          locals[local] = inferrer.types.allocateDiamondPhi(thenType, elseType);
         }
       }
 
@@ -459,7 +443,7 @@
    * where [:this:] is the [LocalsHandler] for the paths through the
    * labeled statement that do not break out.
    */
-  void mergeAfterBreaks(List<LocalsHandler> handlers,
+  void mergeAfterBreaks(InferrerEngine inferrer, List<LocalsHandler> handlers,
       {bool keepOwnLocals: true}) {
     ir.Node level = locals.block;
     // Use a separate locals handler to perform the merge in, so that Phi
@@ -472,7 +456,7 @@
     // Merge all other handlers.
     for (LocalsHandler handler in handlers) {
       allBranchesAbort = allBranchesAbort && handler.seenReturnOrThrow;
-      merged.mergeHandler(handler, seenLocals);
+      merged.mergeHandler(inferrer, handler, seenLocals);
     }
     // If we want to keep own locals, we merge [seenLocals] from [this] into
     // [merged] to update the Phi nodes with original values.
@@ -480,15 +464,15 @@
       for (Local variable in seenLocals) {
         TypeInformation originalType = locals[variable];
         if (originalType != null) {
-          merged.locals[variable] = types.addPhiInput(
-              variable, merged.locals[variable], originalType);
+          merged.locals[variable] = inferrer.types
+              .addPhiInput(variable, merged.locals[variable], originalType);
         }
       }
     }
     // Clean up Phi nodes with single input and store back result into
     // actual locals handler.
     merged.locals.forEachOwnLocal((Local variable, TypeInformation type) {
-      locals[variable] = types.simplifyPhi(level, variable, type);
+      locals[variable] = inferrer.types.simplifyPhi(level, variable, type);
     });
     seenReturnOrThrow =
         allBranchesAbort && (!keepOwnLocals || seenReturnOrThrow);
@@ -500,7 +484,8 @@
    * unless the local is already present in the set [seen]. This effectively
    * overwrites the current type knowledge in this handler.
    */
-  bool mergeHandler(LocalsHandler other, [Set<Local> seen]) {
+  bool mergeHandler(InferrerEngine inferrer, LocalsHandler other,
+      [Set<Local> seen]) {
     if (other.seenReturnOrThrow) return false;
     bool changed = false;
     other.locals.forEachLocalUntilNode(locals.block, (local, otherType) {
@@ -508,11 +493,11 @@
       if (myType == null) return;
       TypeInformation newType;
       if (seen != null && !seen.contains(local)) {
-        newType = types.allocatePhi(locals.block, local, otherType,
-            isTry: locals.isTry);
+        newType = inferrer.types
+            .allocatePhi(locals.block, local, otherType, isTry: locals.isTry);
         seen.add(local);
       } else {
-        newType = types.addPhiInput(local, myType, otherType);
+        newType = inferrer.types.addPhiInput(local, myType, otherType);
       }
       if (newType != myType) {
         changed = true;
@@ -526,28 +511,29 @@
    * Merge all [LocalsHandler] in [handlers] into this handler.
    * Returns whether a local in this handler has changed.
    */
-  bool mergeAll(List<LocalsHandler> handlers) {
+  bool mergeAll(InferrerEngine inferrer, List<LocalsHandler> handlers) {
     bool changed = false;
     assert(!seenReturnOrThrow);
     handlers.forEach((other) {
-      changed = mergeHandler(other) || changed;
+      changed = mergeHandler(inferrer, other) || changed;
     });
     return changed;
   }
 
-  void startLoop(ir.Node loop) {
+  void startLoop(InferrerEngine inferrer, ir.Node loop) {
     locals.forEachLocal((Local variable, TypeInformation type) {
       TypeInformation newType =
-          types.allocateLoopPhi(loop, variable, type, isTry: false);
+          inferrer.types.allocateLoopPhi(loop, variable, type, isTry: false);
       if (newType != type) {
         locals[variable] = newType;
       }
     });
   }
 
-  void endLoop(ir.Node loop) {
+  void endLoop(InferrerEngine inferrer, ir.Node loop) {
     locals.forEachLocal((Local variable, TypeInformation type) {
-      TypeInformation newType = types.simplifyPhi(loop, variable, type);
+      TypeInformation newType =
+          inferrer.types.simplifyPhi(loop, variable, type);
       if (newType != type) {
         locals[variable] = newType;
       }
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index c8c20c2..b51384d 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -89,26 +89,14 @@
   GlobalTypeInferenceResults buildResults() {
     inferrer.close();
 
-    Map<ir.TreeNode, AbstractValue> allocatedLists =
-        <ir.TreeNode, AbstractValue>{};
-    Set<ir.TreeNode> checkedForGrowableLists = new Set<ir.TreeNode>();
-    inferrer.types.allocatedLists
-        .forEach((ir.TreeNode node, ListTypeInformation typeInformation) {
-      ListTypeInformation info = inferrer.types.allocatedLists[node];
-      if (info.checksGrowable) {
-        checkedForGrowableLists.add(node);
-      }
-      allocatedLists[node] = typeInformation.type;
-    });
-
     Map<MemberEntity, GlobalTypeInferenceMemberResult> memberResults =
         <MemberEntity, GlobalTypeInferenceMemberResult>{};
     Map<Local, AbstractValue> parameterResults = <Local, AbstractValue>{};
 
     void createMemberResults(
         MemberEntity member, MemberTypeInformation typeInformation) {
-      GlobalTypeInferenceElementData data = inferrer.dataOfMember(member);
-      data.compress();
+      GlobalTypeInferenceElementData data =
+          inferrer.dataOfMember(member).compress();
       bool isJsInterop = closedWorld.nativeData.isJsInteropMember(member);
 
       AbstractValue returnType;
@@ -132,7 +120,7 @@
           typeInformation.isCalledOnce(); //isMemberCalledOnce(member);
 
       memberResults[member] = new GlobalTypeInferenceMemberResultImpl(
-          data, allocatedLists, returnType, type,
+          data, returnType, type,
           throwsAlways: throwsAlways, isCalledOnce: isCalledOnce);
     }
 
@@ -163,13 +151,26 @@
       parameterResults[parameter] = type;
     });
 
+    Map<ir.TreeNode, AbstractValue> allocatedLists =
+        <ir.TreeNode, AbstractValue>{};
+    Set<ir.TreeNode> checkedForGrowableLists = new Set<ir.TreeNode>();
+    inferrer.types.allocatedLists
+        .forEach((ir.TreeNode node, ListTypeInformation typeInformation) {
+      ListTypeInformation info = inferrer.types.allocatedLists[node];
+      if (info.checksGrowable) {
+        checkedForGrowableLists.add(node);
+      }
+      allocatedLists[node] = typeInformation.type;
+    });
+
     GlobalTypeInferenceResults results = new GlobalTypeInferenceResultsImpl(
         closedWorld,
         _inferredDataBuilder.close(closedWorld),
         memberResults,
         parameterResults,
         checkedForGrowableLists,
-        inferrer.returnsListElementTypeSet);
+        inferrer.returnsListElementTypeSet,
+        allocatedLists);
 
     inferrer.clear();
 
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/constants.dart b/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
index 5003c72b..c539521 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
@@ -29,12 +29,6 @@
   }
 
   @override
-  TypeMask visitDeferred(
-      DeferredConstantValue constant, JClosedWorld closedWorld) {
-    return constant.referenced.accept(this, closedWorld);
-  }
-
-  @override
   TypeMask visitDeferredGlobal(
       DeferredGlobalConstantValue constant, JClosedWorld closedWorld) {
     return constant.referenced.accept(this, closedWorld);
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
index 9a64845..8b67ca6 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
@@ -34,8 +34,8 @@
       DataSource source, JClosedWorld closedWorld) {
     source.begin(tag);
     TypeMask forwardTo = new TypeMask.readFromDataSource(source, closedWorld);
-    ir.TreeNode allocationNode = source.readTreeNode();
-    MemberEntity allocationElement = source.readMember();
+    ir.TreeNode allocationNode = source.readTreeNodeOrNull();
+    MemberEntity allocationElement = source.readMemberOrNull();
     TypeMask keyType = new TypeMask.readFromDataSource(source, closedWorld);
     TypeMask valueType = new TypeMask.readFromDataSource(source, closedWorld);
     Map<String, AbstractValue> typeMap = source.readStringMap(
@@ -50,10 +50,10 @@
     sink.writeEnum(TypeMaskKind.dictionary);
     sink.begin(tag);
     forwardTo.writeToDataSink(sink);
-    sink.writeTreeNode(allocationNode);
-    sink.writeMember(allocationElement);
-    valueType.writeToDataSink(sink);
+    sink.writeTreeNodeOrNull(allocationNode);
+    sink.writeMemberOrNull(allocationElement);
     keyType.writeToDataSink(sink);
+    valueType.writeToDataSink(sink);
     sink.writeStringMap(_typeMap, (AbstractValue value) {
       TypeMask typeMask = value;
       typeMask.writeToDataSink(sink);
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
index 5e6e2fb..4a59fcd 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
@@ -36,8 +36,8 @@
       DataSource source, JClosedWorld closedWorld) {
     source.begin(tag);
     TypeMask forwardTo = new TypeMask.readFromDataSource(source, closedWorld);
-    ir.TreeNode allocationNode = source.readTreeNode();
-    MemberEntity allocationElement = source.readMember();
+    ir.TreeNode allocationNode = source.readTreeNodeOrNull();
+    MemberEntity allocationElement = source.readMemberOrNull();
     TypeMask keyType = new TypeMask.readFromDataSource(source, closedWorld);
     TypeMask valueType = new TypeMask.readFromDataSource(source, closedWorld);
     source.end(tag);
@@ -50,10 +50,10 @@
     sink.writeEnum(TypeMaskKind.map);
     sink.begin(tag);
     forwardTo.writeToDataSink(sink);
-    sink.writeTreeNode(allocationNode);
-    sink.writeMember(allocationElement);
-    valueType.writeToDataSink(sink);
+    sink.writeTreeNodeOrNull(allocationNode);
+    sink.writeMemberOrNull(allocationElement);
     keyType.writeToDataSink(sink);
+    valueType.writeToDataSink(sink);
     sink.end(tag);
   }
 
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
index 6987117..cdc8167 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
@@ -722,12 +722,14 @@
 
   @override
   TypeMask readAbstractValueFromDataSource(DataSource source) {
-    return new TypeMask.readFromDataSource(source, _closedWorld);
+    return source.readCached<TypeMask>(
+        () => new TypeMask.readFromDataSource(source, _closedWorld));
   }
 
   @override
   void writeAbstractValueToDataSink(DataSink sink, covariant TypeMask value) {
-    value.writeToDataSink(sink);
+    sink.writeCached<TypeMask>(
+        value, (TypeMask value) => value.writeToDataSink(sink));
   }
 }
 
diff --git a/pkg/compiler/lib/src/ir/cached_static_type.dart b/pkg/compiler/lib/src/ir/cached_static_type.dart
new file mode 100644
index 0000000..f1de29e
--- /dev/null
+++ b/pkg/compiler/lib/src/ir/cached_static_type.dart
@@ -0,0 +1,59 @@
+// 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:kernel/ast.dart' as ir;
+import 'package:kernel/class_hierarchy.dart' as ir;
+import 'package:kernel/core_types.dart' as ir;
+import 'package:kernel/type_algebra.dart' as ir;
+import 'package:kernel/type_environment.dart' as ir;
+import 'static_type_base.dart';
+
+/// Class that provides the static type of expression using the visitor pattern
+/// and a precomputed cache for complex expression type.
+class CachedStaticType extends StaticTypeBase {
+  final Map<ir.Expression, ir.DartType> _cache;
+
+  CachedStaticType(ir.TypeEnvironment typeEnvironment, this._cache)
+      : super(typeEnvironment);
+
+  ir.DartType _getStaticType(ir.Expression node) {
+    ir.DartType type = _cache[node];
+    assert(type != null, "No static type cached for ${node.runtimeType}.");
+    return type;
+  }
+
+  @override
+  ir.DartType visitPropertyGet(ir.PropertyGet node) => _getStaticType(node);
+
+  @override
+  ir.DartType visitDirectPropertyGet(ir.DirectPropertyGet node) =>
+      _getStaticType(node);
+
+  @override
+  ir.DartType visitSuperPropertyGet(ir.SuperPropertyGet node) =>
+      _getStaticType(node);
+
+  @override
+  ir.DartType visitMethodInvocation(ir.MethodInvocation node) =>
+      _getStaticType(node);
+
+  @override
+  ir.DartType visitDirectMethodInvocation(ir.DirectMethodInvocation node) =>
+      _getStaticType(node);
+
+  @override
+  ir.DartType visitStaticInvocation(ir.StaticInvocation node) =>
+      _getStaticType(node);
+
+  @override
+  ir.DartType visitSuperMethodInvocation(ir.SuperMethodInvocation node) =>
+      _getStaticType(node);
+
+  @override
+  ir.DartType visitConstructorInvocation(ir.ConstructorInvocation node) =>
+      _getStaticType(node);
+
+  @override
+  ir.DartType visitInstantiation(ir.Instantiation node) => _getStaticType(node);
+}
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index ce1bd2f..9b129d5 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -7,21 +7,45 @@
 import 'package:kernel/core_types.dart' as ir;
 import 'package:kernel/type_algebra.dart' as ir;
 import 'package:kernel/type_environment.dart' as ir;
+import 'static_type_base.dart';
 
-/// Visitor that computes the static type of an expression.
+/// Visitor that computes and caches the static type of expression while
+/// visiting the full tree at expression level.
 ///
-/// This visitor doesn't traverse subtrees that are not needed for computing
-/// the static type.
+/// To ensure that the traversal only visits and computes the expression type
+/// for each expression once, this class performs the traversal explicitly and
+/// adds 'handleX' hooks for subclasses to handle individual expressions using
+/// the readily compute static types of subexpressions.
 // TODO(johnniwinther): Add improved type promotion to handle negative
 // reasoning.
-abstract class StaticTypeVisitor extends ir.Visitor<ir.DartType> {
-  ir.TypeEnvironment _typeEnvironment;
+abstract class StaticTypeVisitor extends StaticTypeBase {
+  Map<ir.Expression, ir.DartType> _cache = {};
 
-  StaticTypeVisitor(this._typeEnvironment);
+  StaticTypeVisitor(ir.TypeEnvironment typeEnvironment)
+      : super(typeEnvironment);
 
-  fail(String message) => message;
+  @override
+  ir.DartType defaultNode(ir.Node node) =>
+      throw UnsupportedError('Unhandled node $node (${node.runtimeType})');
 
-  ir.TypeEnvironment get typeEnvironment => _typeEnvironment;
+  @override
+  Null visitComponent(ir.Component node) {
+    visitNodes(node.libraries);
+  }
+
+  @override
+  Null visitLibrary(ir.Library node) {
+    visitNodes(node.classes);
+    visitNodes(node.procedures);
+    visitNodes(node.fields);
+  }
+
+  @override
+  Null visitClass(ir.Class node) {
+    visitNodes(node.constructors);
+    visitNodes(node.procedures);
+    visitNodes(node.fields);
+  }
 
   /// Returns the static type of the expression as an instantiation of
   /// [superclass].
@@ -56,90 +80,12 @@
     return superclass.rawType;
   }
 
-  @override
-  ir.DartType defaultNode(ir.Node node) {
-    return null;
-  }
-
-  ir.DartType visitNode(ir.Node node) {
-    return node?.accept(this);
-  }
-
-  Null visitNodes(List<ir.Node> nodes) {
-    for (ir.Node node in nodes) {
-      visitNode(node);
-    }
-  }
-
-  ir.DartType defaultExpression(ir.Expression node) {
-    throw fail('Unhandled node $node (${node.runtimeType})');
-  }
-
-  @override
-  ir.DartType visitAsExpression(ir.AsExpression node) {
-    return node.type;
-  }
-
-  @override
-  ir.DartType visitAwaitExpression(ir.AwaitExpression node) {
-    return typeEnvironment.unfutureType(visitNode(node.operand));
-  }
-
-  @override
-  ir.DartType visitBoolLiteral(ir.BoolLiteral node) => typeEnvironment.boolType;
-
-  @override
-  ir.DartType visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded node) =>
-      typeEnvironment.objectType;
-
-  @override
-  ir.DartType visitStringLiteral(ir.StringLiteral node) =>
-      typeEnvironment.stringType;
-
-  @override
-  ir.DartType visitStringConcatenation(ir.StringConcatenation node) {
-    return typeEnvironment.stringType;
-  }
-
-  @override
-  ir.DartType visitNullLiteral(ir.NullLiteral node) => const ir.BottomType();
-
-  @override
-  ir.DartType visitIntLiteral(ir.IntLiteral node) => typeEnvironment.intType;
-
-  @override
-  ir.DartType visitDoubleLiteral(ir.DoubleLiteral node) =>
-      typeEnvironment.doubleType;
-
-  @override
-  ir.DartType visitSymbolLiteral(ir.SymbolLiteral node) =>
-      typeEnvironment.symbolType;
-
-  @override
-  ir.DartType visitListLiteral(ir.ListLiteral node) {
-    return typeEnvironment.literalListType(node.typeArgument);
-  }
-
-  @override
-  ir.DartType visitMapLiteral(ir.MapLiteral node) {
-    return typeEnvironment.literalMapType(node.keyType, node.valueType);
-  }
-
-  @override
-  ir.DartType visitVariableGet(ir.VariableGet node) =>
-      node.promotedType ?? node.variable.type;
-
-  @override
-  ir.DartType visitVariableSet(ir.VariableSet node) {
-    return visitNode(node.value);
-  }
-
   /// Computes the result type of the property access [node] on a receiver of
   /// type [receiverType].
   ///
   /// If the `node.interfaceTarget` is `null` but matches an `Object` member
   /// it is updated to target this member.
-  ir.DartType computePropertyGetType(
+  ir.DartType _computePropertyGetType(
       ir.PropertyGet node, ir.DartType receiverType) {
     ir.Member interfaceTarget = node.interfaceTarget;
     if (interfaceTarget != null) {
@@ -158,52 +104,86 @@
     return const ir.DynamicType();
   }
 
+  void handlePropertyGet(
+      ir.PropertyGet node, ir.DartType receiverType, ir.DartType resultType) {}
+
   @override
   ir.DartType visitPropertyGet(ir.PropertyGet node) {
     ir.DartType receiverType = visitNode(node.receiver);
-    return computePropertyGetType(node, receiverType);
+    ir.DartType resultType =
+        _cache[node] = _computePropertyGetType(node, receiverType);
+    receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
+    handlePropertyGet(node, receiverType, resultType);
+    return resultType;
   }
 
+  void handlePropertySet(
+      ir.PropertySet node, ir.DartType receiverType, ir.DartType valueType) {}
+
   @override
   ir.DartType visitPropertySet(ir.PropertySet node) {
-    return visitNode(node.value);
+    ir.DartType receiverType = visitNode(node.receiver);
+    ir.DartType valueType = super.visitPropertySet(node);
+    receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
+    handlePropertySet(node, receiverType, valueType);
+    return valueType;
   }
 
+  void handleDirectPropertyGet(ir.DirectPropertyGet node,
+      ir.DartType receiverType, ir.DartType resultType) {}
+
   @override
   ir.DartType visitDirectPropertyGet(ir.DirectPropertyGet node) {
     ir.DartType receiverType = visitNode(node.receiver);
     ir.Class superclass = node.target.enclosingClass;
     receiverType = getTypeAsInstanceOf(receiverType, superclass);
-    return ir.Substitution.fromInterfaceType(receiverType)
+    ir.DartType resultType = ir.Substitution.fromInterfaceType(receiverType)
         .substituteType(node.target.getterType);
+    _cache[node] = resultType;
+    handleDirectPropertyGet(node, receiverType, resultType);
+    return resultType;
   }
 
+  void handleDirectMethodInvocation(
+      ir.DirectMethodInvocation node,
+      ir.DartType receiverType,
+      ArgumentTypes argumentTypes,
+      ir.DartType returnType) {}
+
   @override
   ir.DartType visitDirectMethodInvocation(ir.DirectMethodInvocation node) {
     ir.DartType receiverType = visitNode(node.receiver);
+    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
+    ir.DartType returnType;
     if (typeEnvironment.isOverloadedArithmeticOperator(node.target)) {
-      ir.DartType argumentType = visitNode(node.arguments.positional[0]);
-      return typeEnvironment.getTypeOfOverloadedArithmetic(
+      ir.DartType argumentType = argumentTypes.positional[0];
+      returnType = typeEnvironment.getTypeOfOverloadedArithmetic(
           receiverType, argumentType);
+    } else {
+      ir.Class superclass = node.target.enclosingClass;
+      receiverType = getTypeAsInstanceOf(receiverType, superclass);
+      ir.DartType returnType = ir.Substitution.fromInterfaceType(receiverType)
+          .substituteType(node.target.function.returnType);
+      returnType = ir.Substitution.fromPairs(
+              node.target.function.typeParameters, node.arguments.types)
+          .substituteType(returnType);
     }
-    ir.Class superclass = node.target.enclosingClass;
-    receiverType = getTypeAsInstanceOf(receiverType, superclass);
-    ir.DartType returnType = ir.Substitution.fromInterfaceType(receiverType)
-        .substituteType(node.target.function.returnType);
-    return ir.Substitution.fromPairs(
-            node.target.function.typeParameters, node.arguments.types)
-        .substituteType(returnType);
+    _cache[node] = returnType;
+    handleDirectMethodInvocation(node, receiverType, argumentTypes, returnType);
+    return returnType;
   }
 
+  void handleDirectPropertySet(ir.DirectPropertySet node,
+      ir.DartType receiverType, ir.DartType valueType) {}
+
   @override
   ir.DartType visitDirectPropertySet(ir.DirectPropertySet node) {
-    return visitNode(node.value);
+    ir.DartType receiverType = visitNode(node.receiver);
+    ir.DartType valueType = super.visitDirectPropertySet(node);
+    handleDirectPropertySet(node, receiverType, valueType);
+    return valueType;
   }
 
-  @override
-  ir.DartType visitThisExpression(ir.ThisExpression node) =>
-      typeEnvironment.thisType;
-
   /// Returns `true` if [interfaceTarget] is an arithmetic operator whose result
   /// type is computed using both the receiver type and the argument type.
   ///
@@ -229,7 +209,7 @@
   ///
   /// If [interfaceTarget] is `null` or `receiverType` is _not_ `dynamic` no
   /// narrowing is performed.
-  ir.DartType narrowInstanceReceiver(
+  ir.DartType _narrowInstanceReceiver(
       ir.Member interfaceTarget, ir.DartType receiverType) {
     if (interfaceTarget != null && receiverType == const ir.DynamicType()) {
       receiverType = interfaceTarget.enclosingClass.thisType;
@@ -242,8 +222,8 @@
   ///
   /// If the `node.interfaceTarget` is `null` but matches an `Object` member
   /// it is updated to target this member.
-  ir.DartType computeMethodInvocationType(
-      ir.MethodInvocation node, ir.DartType receiverType) {
+  ir.DartType _computeMethodInvocationType(ir.MethodInvocation node,
+      ir.DartType receiverType, ArgumentTypes argumentTypes) {
     ir.Member interfaceTarget = node.interfaceTarget;
     // TODO(34602): Remove when `interfaceTarget` is set on synthetic calls to
     // ==.
@@ -256,7 +236,7 @@
     }
     if (interfaceTarget != null) {
       if (isSpecialCasedBinaryOperator(interfaceTarget)) {
-        ir.DartType argumentType = visitNode(node.arguments.positional[0]);
+        ir.DartType argumentType = argumentTypes.positional[0];
         return typeEnvironment.getTypeOfOverloadedArithmetic(
             receiverType, argumentType);
       }
@@ -289,259 +269,154 @@
     return const ir.DynamicType();
   }
 
-  @override
-  ir.DartType visitMethodInvocation(ir.MethodInvocation node) {
-    ir.DartType receiverType = visitNode(node.receiver);
-    return computeMethodInvocationType(node, receiverType);
+  ArgumentTypes _visitArguments(ir.Arguments arguments) {
+    List<ir.DartType> positional;
+    List<ir.DartType> named;
+    if (arguments.positional.isEmpty) {
+      positional = const <ir.DartType>[];
+    } else {
+      positional = new List<ir.DartType>(arguments.positional.length);
+      int index = 0;
+      for (ir.Expression argument in arguments.positional) {
+        positional[index++] = visitNode(argument);
+      }
+    }
+    if (arguments.named.isEmpty) {
+      named = const <ir.DartType>[];
+    } else {
+      named = new List<ir.DartType>(arguments.named.length);
+      int index = 0;
+      for (ir.NamedExpression argument in arguments.named) {
+        named[index++] = visitNode(argument);
+      }
+    }
+    return new ArgumentTypes(positional, named);
   }
 
+  void handleMethodInvocation(
+      ir.MethodInvocation node,
+      ir.DartType receiverType,
+      ArgumentTypes argumentTypes,
+      ir.DartType returnType) {}
+
   @override
-  ir.DartType visitStaticGet(ir.StaticGet node) => node.target.getterType;
+  ir.DartType visitMethodInvocation(ir.MethodInvocation node) {
+    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
+    ir.DartType receiverType = visitNode(node.receiver);
+    ir.DartType returnType =
+        _computeMethodInvocationType(node, receiverType, argumentTypes);
+    receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
+    _cache[node] = returnType;
+    handleMethodInvocation(node, receiverType, argumentTypes, returnType);
+    return returnType;
+  }
+
+  void handleStaticGet(ir.StaticGet node, ir.DartType resultType) {}
+
+  @override
+  ir.DartType visitStaticGet(ir.StaticGet node) {
+    ir.DartType resultType = super.visitStaticGet(node);
+    handleStaticGet(node, resultType);
+    return resultType;
+  }
+
+  void handleStaticSet(ir.StaticSet node, ir.DartType valueType) {}
 
   @override
   ir.DartType visitStaticSet(ir.StaticSet node) {
-    return visitNode(node.value);
+    ir.DartType valueType = super.visitStaticSet(node);
+    handleStaticSet(node, valueType);
+    return valueType;
   }
 
+  void handleStaticInvocation(ir.StaticInvocation node,
+      ArgumentTypes argumentTypes, ir.DartType returnType) {}
+
   @override
   ir.DartType visitStaticInvocation(ir.StaticInvocation node) {
-    return ir.Substitution.fromPairs(
+    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
+    ir.DartType returnType = ir.Substitution.fromPairs(
             node.target.function.typeParameters, node.arguments.types)
         .substituteType(node.target.function.returnType);
+    _cache[node] = returnType;
+    handleStaticInvocation(node, argumentTypes, returnType);
+    return returnType;
   }
 
+  void handleConstructorInvocation(ir.ConstructorInvocation node,
+      ArgumentTypes argumentTypes, ir.DartType resultType) {}
+
   @override
   ir.DartType visitConstructorInvocation(ir.ConstructorInvocation node) {
-    return node.arguments.types.isEmpty
+    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
+    ir.DartType resultType = node.arguments.types.isEmpty
         ? node.target.enclosingClass.rawType
         : new ir.InterfaceType(
             node.target.enclosingClass, node.arguments.types);
+    _cache[node] = resultType;
+    handleConstructorInvocation(node, argumentTypes, resultType);
+    return resultType;
   }
 
+  void handleSuperPropertyGet(
+      ir.SuperPropertyGet node, ir.DartType resultType) {}
+
   @override
   ir.DartType visitSuperPropertyGet(ir.SuperPropertyGet node) {
+    ir.DartType resultType;
     if (node.interfaceTarget == null) {
       // TODO(johnniwinther): Resolve and set the target here.
-      return const ir.DynamicType();
+      resultType = const ir.DynamicType();
+    } else {
+      ir.Class declaringClass = node.interfaceTarget.enclosingClass;
+      if (declaringClass.typeParameters.isEmpty) {
+        resultType = node.interfaceTarget.getterType;
+      } else {
+        ir.DartType receiver = typeEnvironment.hierarchy
+            .getTypeAsInstanceOf(typeEnvironment.thisType, declaringClass);
+        resultType = ir.Substitution.fromInterfaceType(receiver)
+            .substituteType(node.interfaceTarget.getterType);
+      }
     }
-    ir.Class declaringClass = node.interfaceTarget.enclosingClass;
-    if (declaringClass.typeParameters.isEmpty) {
-      return node.interfaceTarget.getterType;
-    }
-    ir.DartType receiver = typeEnvironment.hierarchy
-        .getTypeAsInstanceOf(typeEnvironment.thisType, declaringClass);
-    return ir.Substitution.fromInterfaceType(receiver)
-        .substituteType(node.interfaceTarget.getterType);
+    _cache[node] = resultType;
+    handleSuperPropertyGet(node, resultType);
+    return resultType;
   }
 
+  void handleSuperPropertySet(
+      ir.SuperPropertySet node, ir.DartType valueType) {}
+
   @override
   ir.DartType visitSuperPropertySet(ir.SuperPropertySet node) {
-    return visitNode(node.value);
+    ir.DartType valueType = super.visitSuperPropertySet(node);
+    handleSuperPropertySet(node, valueType);
+    return valueType;
   }
 
+  void handleSuperMethodInvocation(ir.SuperMethodInvocation node,
+      ArgumentTypes argumentTypes, ir.DartType returnType) {}
+
   @override
   ir.DartType visitSuperMethodInvocation(ir.SuperMethodInvocation node) {
+    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
+    ir.DartType returnType;
     if (node.interfaceTarget == null) {
       // TODO(johnniwinther): Resolve and set the target here.
-      return const ir.DynamicType();
-    }
-    ir.Class superclass = node.interfaceTarget.enclosingClass;
-    ir.InterfaceType receiverType = typeEnvironment.hierarchy
-        .getTypeAsInstanceOf(typeEnvironment.thisType, superclass);
-    ir.DartType returnType = ir.Substitution.fromInterfaceType(receiverType)
-        .substituteType(node.interfaceTarget.function.returnType);
-    return ir.Substitution.fromPairs(
-            node.interfaceTarget.function.typeParameters, node.arguments.types)
-        .substituteType(returnType);
-  }
-
-  @override
-  ir.DartType visitThrow(ir.Throw node) => const ir.BottomType();
-
-  @override
-  ir.DartType visitRethrow(ir.Rethrow node) => const ir.BottomType();
-
-  @override
-  ir.DartType visitLogicalExpression(ir.LogicalExpression node) =>
-      typeEnvironment.boolType;
-
-  @override
-  ir.DartType visitNot(ir.Not node) {
-    return typeEnvironment.boolType;
-  }
-
-  @override
-  ir.DartType visitConditionalExpression(ir.ConditionalExpression node) {
-    return node.staticType;
-  }
-
-  @override
-  ir.DartType visitIsExpression(ir.IsExpression node) {
-    return typeEnvironment.boolType;
-  }
-
-  @override
-  ir.DartType visitTypeLiteral(ir.TypeLiteral node) => typeEnvironment.typeType;
-
-  @override
-  ir.DartType visitFunctionExpression(ir.FunctionExpression node) {
-    return node.function.functionType;
-  }
-
-  @override
-  ir.DartType visitLet(ir.Let node) {
-    return visitNode(node.body);
-  }
-
-  ir.DartType computeInstantiationType(
-      ir.Instantiation node, ir.FunctionType expressionType) {
-    return ir.Substitution.fromPairs(
-            expressionType.typeParameters, node.typeArguments)
-        .substituteType(expressionType.withoutTypeParameters);
-  }
-
-  @override
-  ir.DartType visitInstantiation(ir.Instantiation node) {
-    ir.FunctionType expressionType = visitNode(node.expression);
-    return computeInstantiationType(node, expressionType);
-  }
-
-  @override
-  ir.DartType visitInvalidExpression(ir.InvalidExpression node) =>
-      const ir.BottomType();
-
-  @override
-  ir.DartType visitLoadLibrary(ir.LoadLibrary node) {
-    return typeEnvironment.futureType(const ir.DynamicType());
-  }
-}
-
-/// Visitor that computes the static type of an expression using a cache to
-/// avoid recomputations.
-class CachingStaticTypeVisitor extends StaticTypeVisitor {
-  Map<ir.Expression, ir.DartType> _cache = {};
-
-  CachingStaticTypeVisitor(ir.TypeEnvironment typeEnvironment)
-      : super(typeEnvironment);
-
-  @override
-  ir.DartType visitNode(ir.Node node) {
-    ir.DartType result;
-    if (node is ir.Expression) {
-      result = _cache[node];
-      if (result != null) return result;
-      result = super.visitNode(node);
-      _cache[node] = result;
+      returnType = const ir.DynamicType();
     } else {
-      result = super.visitNode(node);
+      ir.Class superclass = node.interfaceTarget.enclosingClass;
+      ir.InterfaceType receiverType = typeEnvironment.hierarchy
+          .getTypeAsInstanceOf(typeEnvironment.thisType, superclass);
+      returnType = ir.Substitution.fromInterfaceType(receiverType)
+          .substituteType(node.interfaceTarget.function.returnType);
+      returnType = ir.Substitution.fromPairs(
+              node.interfaceTarget.function.typeParameters,
+              node.arguments.types)
+          .substituteType(returnType);
     }
-    return result;
-  }
-}
-
-/// Visitor that traverse the whole tree while returning the static type of
-/// expressions.
-abstract class StaticTypeTraversalVisitor extends StaticTypeVisitor {
-  StaticTypeTraversalVisitor(ir.TypeEnvironment typeEnvironment)
-      : super(typeEnvironment);
-
-  @override
-  ir.DartType defaultNode(ir.Node node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  Null defaultMember(ir.Member node) {
-    typeEnvironment.thisType =
-        node.enclosingClass != null ? node.enclosingClass.thisType : null;
-    node.visitChildren(this);
-    typeEnvironment.thisType = null;
-    return null;
-  }
-
-  ir.DartType visitExpressionStatement(ir.ExpressionStatement node) {
-    visitNode(node.expression);
-    return null;
-  }
-
-  @override
-  ir.DartType visitAsExpression(ir.AsExpression node) {
-    visitNode(node.operand);
-    return super.visitAsExpression(node);
-  }
-
-  @override
-  ir.DartType visitStringConcatenation(ir.StringConcatenation node) {
-    visitNodes(node.expressions);
-    return super.visitStringConcatenation(node);
-  }
-
-  @override
-  ir.DartType visitListLiteral(ir.ListLiteral node) {
-    visitNodes(node.expressions);
-    return super.visitListLiteral(node);
-  }
-
-  @override
-  ir.DartType visitMapLiteral(ir.MapLiteral node) {
-    visitNodes(node.entries);
-    return super.visitMapLiteral(node);
-  }
-
-  @override
-  ir.DartType visitPropertySet(ir.PropertySet node) {
-    visitNode(node.receiver);
-    return super.visitPropertySet(node);
-  }
-
-  @override
-  ir.DartType visitDirectMethodInvocation(ir.DirectMethodInvocation node) {
-    visitNodes(node.arguments.positional);
-    visitNodes(node.arguments.named);
-    return super.visitDirectMethodInvocation(node);
-  }
-
-  @override
-  ir.DartType visitDirectPropertySet(ir.DirectPropertySet node) {
-    visitNode(node.receiver);
-    return super.visitDirectPropertySet(node);
-  }
-
-  @override
-  ir.DartType visitMethodInvocation(ir.MethodInvocation node) {
-    if (isSpecialCasedBinaryOperator(node.interfaceTarget)) {
-      return super.visitMethodInvocation(node);
-    }
-    visitNodes(node.arguments.positional);
-    visitNodes(node.arguments.named);
-    return super.visitMethodInvocation(node);
-  }
-
-  @override
-  ir.DartType visitStaticInvocation(ir.StaticInvocation node) {
-    visitNodes(node.arguments.positional);
-    visitNodes(node.arguments.named);
-    return super.visitStaticInvocation(node);
-  }
-
-  @override
-  ir.DartType visitConstructorInvocation(ir.ConstructorInvocation node) {
-    visitNodes(node.arguments.positional);
-    visitNodes(node.arguments.named);
-    return super.visitConstructorInvocation(node);
-  }
-
-  @override
-  ir.DartType visitSuperMethodInvocation(ir.SuperMethodInvocation node) {
-    visitNodes(node.arguments.positional);
-    visitNodes(node.arguments.named);
-    return super.visitSuperMethodInvocation(node);
-  }
-
-  @override
-  ir.DartType visitThrow(ir.Throw node) {
-    visitNode(node.expression);
-    return super.visitThrow(node);
+    _cache[node] = returnType;
+    handleSuperMethodInvocation(node, argumentTypes, returnType);
+    return returnType;
   }
 
   @override
@@ -565,21 +440,389 @@
     return super.visitConditionalExpression(node);
   }
 
+  void handleIsExpression(ir.IsExpression node) {}
+
   @override
   ir.DartType visitIsExpression(ir.IsExpression node) {
     visitNode(node.operand);
+    handleIsExpression(node);
     return super.visitIsExpression(node);
   }
 
   @override
-  ir.DartType visitFunctionExpression(ir.FunctionExpression node) {
-    visitNode(node.function.body);
-    return super.visitFunctionExpression(node);
-  }
-
-  @override
   ir.DartType visitLet(ir.Let node) {
     visitNode(node.variable.initializer);
     return super.visitLet(node);
   }
+
+  ir.DartType _computeInstantiationType(
+      ir.Instantiation node, ir.FunctionType expressionType) {
+    return ir.Substitution.fromPairs(
+            expressionType.typeParameters, node.typeArguments)
+        .substituteType(expressionType.withoutTypeParameters);
+  }
+
+  void handleInstantiation(ir.Instantiation node,
+      ir.FunctionType expressionType, ir.DartType resultType) {}
+
+  @override
+  ir.DartType visitInstantiation(ir.Instantiation node) {
+    ir.FunctionType expressionType = visitNode(node.expression);
+    ir.DartType resultType = _computeInstantiationType(node, expressionType);
+    _cache[node] = resultType;
+    handleInstantiation(node, expressionType, resultType);
+    return resultType;
+  }
+
+  @override
+  Null visitBlock(ir.Block node) => visitNodes(node.statements);
+
+  ir.DartType visitExpressionStatement(ir.ExpressionStatement node) {
+    visitNode(node.expression);
+    return null;
+  }
+
+  void handleAsExpression(ir.AsExpression node) {}
+
+  @override
+  ir.DartType visitAsExpression(ir.AsExpression node) {
+    visitNode(node.operand);
+    handleAsExpression(node);
+    return super.visitAsExpression(node);
+  }
+
+  void handleStringConcatenation(ir.StringConcatenation node) {}
+
+  @override
+  ir.DartType visitStringConcatenation(ir.StringConcatenation node) {
+    visitNodes(node.expressions);
+    handleStringConcatenation(node);
+    return super.visitStringConcatenation(node);
+  }
+
+  void handleIntLiteral(ir.IntLiteral node) {}
+
+  @override
+  ir.DartType visitIntLiteral(ir.IntLiteral node) {
+    handleIntLiteral(node);
+    return super.visitIntLiteral(node);
+  }
+
+  void handleDoubleLiteral(ir.DoubleLiteral node) {}
+
+  @override
+  ir.DartType visitDoubleLiteral(ir.DoubleLiteral node) {
+    handleDoubleLiteral(node);
+    return super.visitDoubleLiteral(node);
+  }
+
+  void handleBoolLiteral(ir.BoolLiteral node) {}
+
+  @override
+  ir.DartType visitBoolLiteral(ir.BoolLiteral node) {
+    handleBoolLiteral(node);
+    return super.visitBoolLiteral(node);
+  }
+
+  void handleStringLiteral(ir.StringLiteral node) {}
+
+  @override
+  ir.DartType visitStringLiteral(ir.StringLiteral node) {
+    handleStringLiteral(node);
+    return super.visitStringLiteral(node);
+  }
+
+  void handleSymbolLiteral(ir.SymbolLiteral node) {}
+
+  @override
+  ir.DartType visitSymbolLiteral(ir.SymbolLiteral node) {
+    handleSymbolLiteral(node);
+    return super.visitSymbolLiteral(node);
+  }
+
+  void handleNullLiteral(ir.NullLiteral node) {}
+
+  @override
+  ir.DartType visitNullLiteral(ir.NullLiteral node) {
+    handleNullLiteral(node);
+    return super.visitNullLiteral(node);
+  }
+
+  void handleListLiteral(ir.ListLiteral node) {}
+
+  @override
+  ir.DartType visitListLiteral(ir.ListLiteral node) {
+    visitNodes(node.expressions);
+    handleListLiteral(node);
+    return super.visitListLiteral(node);
+  }
+
+  void handleMapLiteral(ir.MapLiteral node) {}
+
+  @override
+  ir.DartType visitMapLiteral(ir.MapLiteral node) {
+    visitNodes(node.entries);
+    handleMapLiteral(node);
+    return super.visitMapLiteral(node);
+  }
+
+  @override
+  Null visitMapEntry(ir.MapEntry entry) {
+    visitNode(entry.key);
+    visitNode(entry.value);
+  }
+
+  void handleFunctionExpression(ir.FunctionExpression node) {}
+
+  @override
+  ir.DartType visitFunctionExpression(ir.FunctionExpression node) {
+    visitSignature(node.function);
+    visitNode(node.function.body);
+    handleFunctionExpression(node);
+    return super.visitFunctionExpression(node);
+  }
+
+  void handleThrow(ir.Throw node) {}
+
+  @override
+  ir.DartType visitThrow(ir.Throw node) {
+    visitNode(node.expression);
+    handleThrow(node);
+    return super.visitThrow(node);
+  }
+
+  @override
+  Null visitSwitchCase(ir.SwitchCase node) {
+    visitNodes(node.expressions);
+    visitNode(node.body);
+  }
+
+  @override
+  Null visitContinueSwitchStatement(ir.ContinueSwitchStatement node) {}
+
+  @override
+  Null visitLabeledStatement(ir.LabeledStatement node) {
+    visitNode(node.body);
+  }
+
+  @override
+  Null visitBreakStatement(ir.BreakStatement node) {}
+
+  @override
+  Null visitYieldStatement(ir.YieldStatement node) {
+    visitNode(node.expression);
+  }
+
+  @override
+  Null visitAssertInitializer(ir.AssertInitializer node) {
+    visitNode(node.statement);
+  }
+
+  void handleFieldInitializer(ir.FieldInitializer node) {}
+
+  @override
+  Null visitFieldInitializer(ir.FieldInitializer node) {
+    visitNode(node.value);
+    handleFieldInitializer(node);
+  }
+
+  void handleRedirectingInitializer(
+      ir.RedirectingInitializer node, ArgumentTypes argumentTypes) {}
+
+  @override
+  Null visitRedirectingInitializer(ir.RedirectingInitializer node) {
+    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
+    handleRedirectingInitializer(node, argumentTypes);
+  }
+
+  void handleSuperInitializer(
+      ir.SuperInitializer node, ArgumentTypes argumentTypes) {}
+
+  @override
+  Null visitSuperInitializer(ir.SuperInitializer node) {
+    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
+    handleSuperInitializer(node, argumentTypes);
+  }
+
+  @override
+  Null visitLocalInitializer(ir.LocalInitializer node) {
+    visitNode(node.variable);
+  }
+
+  @override
+  ir.DartType visitNamedExpression(ir.NamedExpression node) =>
+      visitNode(node.value);
+
+  @override
+  Null visitEmptyStatement(ir.EmptyStatement node) {}
+
+  @override
+  Null visitForStatement(ir.ForStatement node) {
+    visitNodes(node.variables);
+    visitNode(node.condition);
+    visitNodes(node.updates);
+    visitNode(node.body);
+  }
+
+  void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType) {}
+
+  @override
+  Null visitForInStatement(ir.ForInStatement node) {
+    visitNode(node.variable);
+    ir.DartType iterableType = visitNode(node.iterable);
+    visitNode(node.body);
+    handleForInStatement(node, iterableType);
+  }
+
+  @override
+  Null visitDoStatement(ir.DoStatement node) {
+    visitNode(node.body);
+    visitNode(node.condition);
+  }
+
+  @override
+  Null visitWhileStatement(ir.WhileStatement node) {
+    visitNode(node.condition);
+    visitNode(node.body);
+  }
+
+  void handleSwitchStatement(ir.SwitchStatement node) {}
+
+  @override
+  Null visitSwitchStatement(ir.SwitchStatement node) {
+    visitNode(node.expression);
+    visitNodes(node.cases);
+    handleSwitchStatement(node);
+  }
+
+  @override
+  Null visitReturnStatement(ir.ReturnStatement node) {
+    visitNode(node.expression);
+  }
+
+  @override
+  Null visitIfStatement(ir.IfStatement node) {
+    visitNode(node.condition);
+    visitNode(node.then);
+    visitNode(node.otherwise);
+  }
+
+  @override
+  Null visitTryCatch(ir.TryCatch node) {
+    visitNode(node.body);
+    visitNodes(node.catches);
+  }
+
+  void handleCatch(ir.Catch node) {}
+
+  @override
+  Null visitCatch(ir.Catch node) {
+    handleCatch(node);
+    visitNode(node.body);
+  }
+
+  @override
+  Null visitTryFinally(ir.TryFinally node) {
+    visitNode(node.body);
+    visitNode(node.finalizer);
+  }
+
+  void handleTypeLiteral(ir.TypeLiteral node) {}
+
+  @override
+  ir.DartType visitTypeLiteral(ir.TypeLiteral node) {
+    handleTypeLiteral(node);
+    return super.visitTypeLiteral(node);
+  }
+
+  void handleLoadLibrary(ir.LoadLibrary node) {}
+
+  @override
+  ir.DartType visitLoadLibrary(ir.LoadLibrary node) {
+    handleLoadLibrary(node);
+    return super.visitLoadLibrary(node);
+  }
+
+  void handleAssertStatement(ir.AssertStatement node) {}
+
+  @override
+  Null visitAssertStatement(ir.AssertStatement node) {
+    visitNode(node.condition);
+    visitNode(node.message);
+    handleAssertStatement(node);
+  }
+
+  void handleFunctionDeclaration(ir.FunctionDeclaration node) {}
+
+  @override
+  Null visitFunctionDeclaration(ir.FunctionDeclaration node) {
+    visitSignature(node.function);
+    visitNode(node.function.body);
+    handleFunctionDeclaration(node);
+  }
+
+  void handleParameter(ir.VariableDeclaration node) {}
+
+  void visitParameter(ir.VariableDeclaration node) {
+    visitNode(node.initializer);
+    handleParameter(node);
+  }
+
+  void handleSignature(ir.FunctionNode node) {}
+
+  void visitSignature(ir.FunctionNode node) {
+    node.positionalParameters.forEach(visitParameter);
+    node.namedParameters.forEach(visitParameter);
+    handleSignature(node);
+  }
+
+  void handleProcedure(ir.Procedure node) {}
+
+  @override
+  Null visitProcedure(ir.Procedure node) {
+    typeEnvironment.thisType =
+        node.enclosingClass != null ? node.enclosingClass.thisType : null;
+    visitSignature(node.function);
+    visitNode(node.function.body);
+    handleProcedure(node);
+    typeEnvironment.thisType = null;
+  }
+
+  void handleConstructor(ir.Constructor node) {}
+
+  @override
+  Null visitConstructor(ir.Constructor node) {
+    typeEnvironment.thisType = node.enclosingClass.thisType;
+    visitSignature(node.function);
+    visitNodes(node.initializers);
+    visitNode(node.function.body);
+    handleConstructor(node);
+    typeEnvironment.thisType = null;
+  }
+
+  void handleField(ir.Field node) {}
+
+  @override
+  Null visitField(ir.Field node) {
+    typeEnvironment.thisType =
+        node.enclosingClass != null ? node.enclosingClass.thisType : null;
+    visitNode(node.initializer);
+    handleField(node);
+    typeEnvironment.thisType = null;
+  }
+
+  void handleVariableDeclaration(ir.VariableDeclaration node) {}
+
+  @override
+  Null visitVariableDeclaration(ir.VariableDeclaration node) {
+    visitNode(node.initializer);
+    handleVariableDeclaration(node);
+  }
+}
+
+class ArgumentTypes {
+  final List<ir.DartType> positional;
+  final List<ir.DartType> named;
+
+  ArgumentTypes(this.positional, this.named);
 }
diff --git a/pkg/compiler/lib/src/ir/static_type_base.dart b/pkg/compiler/lib/src/ir/static_type_base.dart
new file mode 100644
index 0000000..9c4144b
--- /dev/null
+++ b/pkg/compiler/lib/src/ir/static_type_base.dart
@@ -0,0 +1,181 @@
+// 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:kernel/ast.dart' as ir;
+import 'package:kernel/class_hierarchy.dart' as ir;
+import 'package:kernel/core_types.dart' as ir;
+import 'package:kernel/type_algebra.dart' as ir;
+import 'package:kernel/type_environment.dart' as ir;
+
+/// Base class for computing static types.
+///
+/// This class uses the visitor pattern to compute the static type that are
+/// directly defined by the expression kind.
+///
+/// Subclasses will compute the static type or use a cache to look up the static
+/// type of expression whose static type is not directly defined by the
+/// expression kind. For instance method invocations whose static type depend
+/// on the static types of the receiver and type arguments and the signature
+/// of the targeted procedure.
+class StaticTypeBase extends ir.Visitor<ir.DartType> {
+  final ir.TypeEnvironment _typeEnvironment;
+
+  StaticTypeBase(this._typeEnvironment);
+
+  fail(String message) => message;
+
+  ir.TypeEnvironment get typeEnvironment => _typeEnvironment;
+
+  @override
+  ir.DartType defaultNode(ir.Node node) {
+    return null;
+  }
+
+  ir.DartType visitNode(ir.Node node) {
+    return node?.accept(this);
+  }
+
+  Null visitNodes(List<ir.Node> nodes) {
+    for (ir.Node node in nodes) {
+      visitNode(node);
+    }
+  }
+
+  ir.DartType defaultExpression(ir.Expression node) {
+    throw fail('Unhandled node $node (${node.runtimeType})');
+  }
+
+  @override
+  ir.DartType visitAsExpression(ir.AsExpression node) {
+    return node.type;
+  }
+
+  @override
+  ir.DartType visitAwaitExpression(ir.AwaitExpression node) {
+    return typeEnvironment.unfutureType(visitNode(node.operand));
+  }
+
+  @override
+  ir.DartType visitBoolLiteral(ir.BoolLiteral node) => typeEnvironment.boolType;
+
+  @override
+  ir.DartType visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded node) =>
+      typeEnvironment.objectType;
+
+  @override
+  ir.DartType visitStringLiteral(ir.StringLiteral node) =>
+      typeEnvironment.stringType;
+
+  @override
+  ir.DartType visitStringConcatenation(ir.StringConcatenation node) {
+    return typeEnvironment.stringType;
+  }
+
+  @override
+  ir.DartType visitNullLiteral(ir.NullLiteral node) => const ir.BottomType();
+
+  @override
+  ir.DartType visitIntLiteral(ir.IntLiteral node) => typeEnvironment.intType;
+
+  @override
+  ir.DartType visitDoubleLiteral(ir.DoubleLiteral node) =>
+      typeEnvironment.doubleType;
+
+  @override
+  ir.DartType visitSymbolLiteral(ir.SymbolLiteral node) =>
+      typeEnvironment.symbolType;
+
+  @override
+  ir.DartType visitListLiteral(ir.ListLiteral node) {
+    return typeEnvironment.literalListType(node.typeArgument);
+  }
+
+  @override
+  ir.DartType visitMapLiteral(ir.MapLiteral node) {
+    return typeEnvironment.literalMapType(node.keyType, node.valueType);
+  }
+
+  @override
+  ir.DartType visitVariableGet(ir.VariableGet node) =>
+      node.promotedType ?? node.variable.type;
+
+  @override
+  ir.DartType visitVariableSet(ir.VariableSet node) {
+    return visitNode(node.value);
+  }
+
+  @override
+  ir.DartType visitPropertySet(ir.PropertySet node) {
+    return visitNode(node.value);
+  }
+
+  @override
+  ir.DartType visitDirectPropertySet(ir.DirectPropertySet node) {
+    return visitNode(node.value);
+  }
+
+  @override
+  ir.DartType visitThisExpression(ir.ThisExpression node) =>
+      typeEnvironment.thisType;
+
+  @override
+  ir.DartType visitStaticGet(ir.StaticGet node) => node.target.getterType;
+
+  @override
+  ir.DartType visitStaticSet(ir.StaticSet node) {
+    return visitNode(node.value);
+  }
+
+  @override
+  ir.DartType visitSuperPropertySet(ir.SuperPropertySet node) {
+    return visitNode(node.value);
+  }
+
+  @override
+  ir.DartType visitThrow(ir.Throw node) => const ir.BottomType();
+
+  @override
+  ir.DartType visitRethrow(ir.Rethrow node) => const ir.BottomType();
+
+  @override
+  ir.DartType visitLogicalExpression(ir.LogicalExpression node) =>
+      typeEnvironment.boolType;
+
+  @override
+  ir.DartType visitNot(ir.Not node) {
+    return typeEnvironment.boolType;
+  }
+
+  @override
+  ir.DartType visitConditionalExpression(ir.ConditionalExpression node) {
+    return node.staticType;
+  }
+
+  @override
+  ir.DartType visitIsExpression(ir.IsExpression node) {
+    return typeEnvironment.boolType;
+  }
+
+  @override
+  ir.DartType visitTypeLiteral(ir.TypeLiteral node) => typeEnvironment.typeType;
+
+  @override
+  ir.DartType visitFunctionExpression(ir.FunctionExpression node) {
+    return node.function.functionType;
+  }
+
+  @override
+  ir.DartType visitLet(ir.Let node) {
+    return visitNode(node.body);
+  }
+
+  @override
+  ir.DartType visitInvalidExpression(ir.InvalidExpression node) =>
+      const ir.BottomType();
+
+  @override
+  ir.DartType visitLoadLibrary(ir.LoadLibrary node) {
+    return typeEnvironment.futureType(const ir.DynamicType());
+  }
+}
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index c65153b..9190a79 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -34,6 +34,7 @@
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/class_hierarchy.dart'
     show ClassHierarchyBuilder, ClassQueries;
+import '../universe/codegen_world_builder.dart';
 import '../universe/selector.dart' show Selector;
 import '../universe/use.dart' show StaticUse;
 import '../universe/world_builder.dart';
@@ -53,7 +54,6 @@
 import 'impact_transformer.dart';
 import 'inferred_data.dart';
 import 'interceptor_data.dart';
-import 'js_interop_analysis.dart' show JsInteropAnalysis;
 import 'namer.dart';
 import 'native_data.dart';
 import 'no_such_method_registry.dart';
@@ -364,9 +364,6 @@
 
   KAllocatorAnalysis _allocatorResolutionAnalysis;
 
-  /// Codegen support for typed JavaScript interop.
-  JsInteropAnalysis jsInteropAnalysis;
-
   /// Support for classifying `noSuchMethod` implementations.
   NoSuchMethodRegistry noSuchMethodRegistry;
 
@@ -410,7 +407,6 @@
     _checkedModeHelpers = new CheckedModeHelpers();
     emitter =
         new CodeEmitterTask(compiler, generateSourceMap, useStartupEmitter);
-    jsInteropAnalysis = new JsInteropAnalysis(this);
 
     noSuchMethodRegistry = new NoSuchMethodRegistryImpl(
         commonElements, compiler.frontendStrategy.createNoSuchMethodResolver());
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 2d2ddea..7afba73 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -12,7 +12,7 @@
 import '../js/js.dart' show js;
 import '../js_emitter/code_emitter_task.dart';
 import '../options.dart';
-import '../universe/world_builder.dart';
+import '../universe/codegen_world_builder.dart';
 import 'allocator_analysis.dart' show JAllocatorAnalysis;
 import 'constant_system_javascript.dart';
 import 'js_backend.dart';
@@ -385,11 +385,6 @@
   }
 
   @override
-  jsAst.Expression visitDeferred(DeferredConstantValue constant, [_]) {
-    return constantReferenceGenerator(constant.referenced);
-  }
-
-  @override
   jsAst.Expression visitDeferredGlobal(DeferredGlobalConstantValue constant,
       [_]) {
     return constantReferenceGenerator(constant.referenced);
diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart
index 7b8589b..72910ae 100644
--- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
+++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
@@ -14,7 +14,8 @@
 import '../elements/types.dart';
 import '../enqueue.dart';
 import '../options.dart';
-import '../universe/world_builder.dart';
+import '../universe/codegen_world_builder.dart';
+import '../universe/member_usage.dart';
 import '../universe/use.dart'
     show
         ConstantUse,
diff --git a/pkg/compiler/lib/src/js_backend/frequency_namer.dart b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
index 343d440..540ab3a 100644
--- a/pkg/compiler/lib/src/js_backend/frequency_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
@@ -21,6 +21,7 @@
   final String getterPrefix = 'g';
   final String setterPrefix = 's';
   final String callPrefix = ''; // this will create function names $<n>
+  String get callCatchAllName => r'$C';
   String get requiredParameterField => r'$R';
   String get defaultValuesField => r'$D';
   String get operatorSignature => r'$S';
diff --git a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
index 5e9c4cb..225d9b5 100644
--- a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
@@ -9,50 +9,46 @@
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show js;
 import '../universe/selector.dart' show Selector;
+import '../universe/codegen_world_builder.dart';
 import '../universe/world_builder.dart' show SelectorConstraints;
-import 'js_backend.dart' show JavaScriptBackend;
+import 'namer.dart';
+import 'native_data.dart';
 
-class JsInteropAnalysis {
-  final JavaScriptBackend backend;
+jsAst.Statement buildJsInteropBootstrap(CodegenWorldBuilder codegenWorldBuilder,
+    NativeBasicData nativeBasicData, Namer namer) {
+  if (!nativeBasicData.isJsInteropUsed) return null;
+  List<jsAst.Statement> statements = <jsAst.Statement>[];
+  codegenWorldBuilder.forEachInvokedName(
+      (String name, Map<Selector, SelectorConstraints> selectors) {
+    selectors.forEach((Selector selector, SelectorConstraints constraints) {
+      if (selector.isClosureCall) {
+        // TODO(jacobr): support named arguments.
+        if (selector.namedArgumentCount > 0) return;
+        int argumentCount = selector.argumentCount;
+        String candidateParameterNames =
+            'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+        List<String> parameters = new List<String>.generate(
+            argumentCount, (i) => candidateParameterNames[i]);
 
-  JsInteropAnalysis(this.backend);
-
-  jsAst.Statement buildJsInteropBootstrap() {
-    if (!backend.compiler.frontendStrategy.nativeBasicData.isJsInteropUsed)
-      return null;
-    List<jsAst.Statement> statements = <jsAst.Statement>[];
-    backend.compiler.codegenWorldBuilder.forEachInvokedName(
-        (String name, Map<Selector, SelectorConstraints> selectors) {
-      selectors.forEach((Selector selector, SelectorConstraints constraints) {
-        if (selector.isClosureCall) {
-          // TODO(jacobr): support named arguments.
-          if (selector.namedArgumentCount > 0) return;
-          int argumentCount = selector.argumentCount;
-          var candidateParameterNames =
-              'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
-          var parameters = new List<String>.generate(
-              argumentCount, (i) => candidateParameterNames[i]);
-
-          var name = backend.namer.invocationName(selector);
-          statements.add(js.statement(
-              'Function.prototype.# = function(#) { return this(#) }',
-              [name, parameters, parameters]));
-        }
-      });
+        jsAst.Name name = namer.invocationName(selector);
+        statements.add(js.statement(
+            'Function.prototype.# = function(#) { return this(#) }',
+            [name, parameters, parameters]));
+      }
     });
-    return new jsAst.Block(statements);
-  }
+  });
+  return new jsAst.Block(statements);
+}
 
-  FunctionType buildJsFunctionType() {
-    // TODO(jacobr): consider using codegenWorldBuilder.isChecks to determine the
-    // range of positional arguments that need to be supported by JavaScript
-    // function types.
-    return new FunctionType(
-        const DynamicType(),
-        const <DartType>[],
-        new List<DartType>.filled(16, const DynamicType()),
-        const <String>[],
-        const <DartType>[],
-        const <FunctionTypeVariable>[]);
-  }
+FunctionType buildJsFunctionType() {
+  // TODO(jacobr): consider using codegenWorldBuilder.isChecks to determine the
+  // range of positional arguments that need to be supported by JavaScript
+  // function types.
+  return new FunctionType(
+      const DynamicType(),
+      const <DartType>[],
+      new List<DartType>.filled(16, const DynamicType()),
+      const <String>[],
+      const <DartType>[],
+      const <FunctionTypeVariable>[]);
 }
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index b701376..69cbda8 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -27,6 +27,7 @@
   final String getterPrefix = 'g';
   final String setterPrefix = 's';
   final String callPrefix = ''; // this will create function names $<n>
+  String get callCatchAllName => r'$C';
   String get requiredParameterField => r'$R';
   String get defaultValuesField => r'$D';
   String get operatorSignature => r'$S';
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index a6674a7..dde4b63 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -26,8 +26,8 @@
 import '../js_model/closure.dart';
 import '../js_model/elements.dart' show JGeneratorBody;
 import '../universe/call_structure.dart' show CallStructure;
+import '../universe/codegen_world_builder.dart';
 import '../universe/selector.dart' show Selector, SelectorKind;
-import '../universe/world_builder.dart' show CodegenWorldBuilder;
 import '../util/util.dart';
 import '../world.dart' show JClosedWorld;
 import 'backend.dart';
@@ -447,8 +447,6 @@
   final String superPrefix = r'super$';
   final String metadataField = '@';
   final String callPrefix = 'call';
-  // Note: We can't shorten 'call*' in the minified namers because the catch-all
-  // formula `name + "*"` is used by mirrors.
   String get callCatchAllName => r'call*';
   final String callNameField = r'$callName';
   final String stubNameField = r'$stubName';
@@ -475,7 +473,6 @@
   jsAst.Name _literalAsyncPrefix;
   jsAst.Name _literalGetterPrefix;
   jsAst.Name _literalSetterPrefix;
-  jsAst.Name _literalLazyGetterPrefix;
 
   jsAst.Name _staticsPropertyName;
 
@@ -518,10 +515,12 @@
   /// Although global names are distributed across a number of global objects,
   /// (see [globalObjectFor]), we currently use a single namespace for all these
   /// names.
-  final NamingScope globalScope = new NamingScope();
-  final Map<Entity, jsAst.Name> userGlobals = new HashMap<Entity, jsAst.Name>();
-  final Map<String, jsAst.Name> internalGlobals =
-      new HashMap<String, jsAst.Name>();
+  final NamingScope globalScope = NamingScope();
+  final Map<Entity, jsAst.Name> userGlobals = {};
+  // [userGlobalsSecondName] is used when an entity has a second name, e.g. a
+  // lazily initialized static variable has a location and a getter.
+  final Map<Entity, jsAst.Name> userGlobalsSecondName = {};
+  final Map<String, jsAst.Name> internalGlobals = {};
 
   Map<String, String> createMinifiedGlobalNameMap() {
     var map = <String, String>{};
@@ -530,6 +529,11 @@
       if (jsName is TokenName && !jsName.isFinalized) return;
       map[jsName.name] = entity.name;
     });
+    userGlobalsSecondName.forEach((entity, jsName) {
+      // Non-finalized names are not present in the output program
+      if (jsName is TokenName && !jsName.isFinalized) return;
+      map[jsName.name] = entity.name;
+    });
     internalGlobals.forEach((name, jsName) {
       // Non-finalized names are not present in the output program
       if (jsName is TokenName && !jsName.isFinalized) return;
@@ -541,15 +545,11 @@
   /// Used disambiguated names in the instance namespace, issued by
   /// [_disambiguateMember], [_disambiguateInternalMember],
   /// [_disambiguateOperator], and [reservePublicMemberName].
-  final NamingScope instanceScope = new NamingScope();
-  final Map<String, jsAst.Name> userInstanceMembers =
-      new HashMap<String, jsAst.Name>();
-  final Map<String, String> userInstanceMembersOriginalName =
-      new HashMap<String, String>();
-  final Map<MemberEntity, jsAst.Name> internalInstanceMembers =
-      new HashMap<MemberEntity, jsAst.Name>();
-  final Map<String, jsAst.Name> userInstanceOperators =
-      new HashMap<String, jsAst.Name>();
+  final NamingScope instanceScope = NamingScope();
+  final Map<String, jsAst.Name> userInstanceMembers = HashMap();
+  final Map<String, String> userInstanceMembersOriginalName = HashMap();
+  final Map<MemberEntity, jsAst.Name> internalInstanceMembers = HashMap();
+  final Map<String, jsAst.Name> userInstanceOperators = HashMap();
 
   Map<String, String> createMinifiedInstanceNameMap() {
     var map = <String, String>{};
@@ -579,39 +579,29 @@
   final NamingScope constantScope = new NamingScope();
 
   /// Used to store scopes for instances of [PrivatelyNamedJsEntity]
-  final Map<Entity, NamingScope> _privateNamingScopes =
-      new Map<Entity, NamingScope>();
+  final Map<Entity, NamingScope> _privateNamingScopes = {};
 
-  final Map<String, int> popularNameCounters = <String, int>{};
+  final Map<String, int> popularNameCounters = {};
 
-  final Map<LibraryEntity, String> libraryLongNames =
-      new HashMap<LibraryEntity, String>();
+  final Map<LibraryEntity, String> libraryLongNames = HashMap();
 
-  final Map<ConstantValue, jsAst.Name> constantNames =
-      new HashMap<ConstantValue, jsAst.Name>();
-  final Map<ConstantValue, String> constantLongNames =
-      <ConstantValue, String>{};
+  final Map<ConstantValue, jsAst.Name> constantNames = HashMap();
+  final Map<ConstantValue, String> constantLongNames = {};
   ConstantCanonicalHasher _constantHasher;
 
   /// Maps private names to a library that may use that name without prefixing
   /// itself. Used for building proposed names.
-  final Map<String, LibraryEntity> shortPrivateNameOwners =
-      <String, LibraryEntity>{};
-
-  final Map<String, String> suggestedGlobalNames = <String, String>{};
-  final Map<String, String> suggestedInstanceNames = <String, String>{};
+  final Map<String, LibraryEntity> shortPrivateNameOwners = {};
 
   /// Used to store unique keys for library names. Keys are not used as names,
   /// nor are they visible in the output. The only serve as an internal
   /// key into maps.
-  final Map<LibraryEntity, String> _libraryKeys =
-      new HashMap<LibraryEntity, String>();
+  final Map<LibraryEntity, String> _libraryKeys = HashMap();
 
   Namer(this._closedWorld, this._codegenWorldBuilder) {
     _literalAsyncPrefix = new StringBackedName(asyncPrefix);
     _literalGetterPrefix = new StringBackedName(getterPrefix);
     _literalSetterPrefix = new StringBackedName(setterPrefix);
-    _literalLazyGetterPrefix = new StringBackedName(lazyGetterPrefix);
   }
 
   ElementEnvironment get elementEnvironment => _closedWorld.elementEnvironment;
@@ -1145,25 +1135,26 @@
   }
 
   jsAst.Name _disambiguateGlobalMember(MemberEntity element) {
-    return _disambiguateGlobal<MemberEntity>(element, _proposeNameForMember);
+    return _disambiguateGlobal<MemberEntity>(
+        element, _proposeNameForMember, userGlobals);
   }
 
   jsAst.Name _disambiguateGlobalType(Entity element) {
-    return _disambiguateGlobal(element, _proposeNameForType);
+    return _disambiguateGlobal(element, _proposeNameForType, userGlobals);
   }
 
   /// Returns the disambiguated name for a top-level or static element.
   ///
   /// The resulting name is unique within the global-member namespace.
-  jsAst.Name _disambiguateGlobal<T extends Entity>(
-      T element, String proposeName(T element)) {
+  jsAst.Name _disambiguateGlobal<T extends Entity>(T element,
+      String proposeName(T element), Map<Entity, jsAst.Name> globals) {
     // TODO(asgerf): We can reuse more short names if we disambiguate with
     // a separate namespace for each of the global holder objects.
-    jsAst.Name newName = userGlobals[element];
+    jsAst.Name newName = globals[element];
     if (newName == null) {
       String proposedName = proposeName(element);
       newName = getFreshName(globalScope, proposedName);
-      userGlobals[element] = newName;
+      globals[element] = newName;
     }
     return _newReference(newName);
   }
@@ -1402,6 +1393,10 @@
     return element.name.replaceAll('+', '_');
   }
 
+  String _proposeNameForLazyStaticGetter(MemberEntity element) {
+    return r'$get$' + _proposeNameForMember(element);
+  }
+
   String _proposeNameForConstructor(ConstructorEntity element) {
     String className = element.enclosingClass.name;
     if (element.isGenerativeConstructor) {
@@ -1643,16 +1638,11 @@
     return userGlobalObjects[library.name.hashCode % userGlobalObjects.length];
   }
 
-  jsAst.Name deriveLazyInitializerName(jsAst.Name name) {
-    // These are not real dart getters, so do not use GetterName;
-    return new CompoundName([_literalLazyGetterPrefix, name]);
-  }
-
   jsAst.Name lazyInitializerName(FieldEntity element) {
     assert(element.isTopLevel || element.isStatic);
-    jsAst.Name name = _disambiguateGlobalMember(element);
-    // These are not real dart getters, so do not use GetterName;
-    return deriveLazyInitializerName(name);
+    jsAst.Name name = _disambiguateGlobal<MemberEntity>(
+        element, _proposeNameForLazyStaticGetter, userGlobalsSecondName);
+    return name;
   }
 
   jsAst.Name staticClosureName(FunctionEntity element) {
@@ -1707,8 +1697,7 @@
   // parts with the fast-startup emitter.
   String get typesOffsetName => r'typesOffset';
 
-  Map<FunctionType, jsAst.Name> functionTypeNameMap =
-      new HashMap<FunctionType, jsAst.Name>();
+  Map<FunctionType, jsAst.Name> functionTypeNameMap = HashMap();
 
   FunctionTypeNamer _functionTypeNamer;
 
@@ -2087,11 +2076,6 @@
   }
 
   @override
-  void visitDeferred(DeferredConstantValue constant, [_]) {
-    addRoot('Deferred');
-  }
-
-  @override
   void visitDeferredGlobal(DeferredGlobalConstantValue constant, [_]) {
     addRoot('Deferred');
   }
@@ -2111,7 +2095,7 @@
 
   final RuntimeTypesEncoder rtiEncoder;
   final CodegenWorldBuilder codegenWorldBuilder;
-  final Map<ConstantValue, int> hashes = new Map<ConstantValue, int>();
+  final Map<ConstantValue, int> hashes = {};
 
   ConstantCanonicalHasher(this.rtiEncoder, this.codegenWorldBuilder);
 
@@ -2218,14 +2202,6 @@
   }
 
   @override
-  int visitDeferred(DeferredConstantValue constant, [_]) {
-    // TODO(sra): Investigate that the use of hashCode here is probably a source
-    // of instability.
-    int hash = constant.import.hashCode;
-    return _combine(hash, _visit(constant.referenced));
-  }
-
-  @override
   int visitDeferredGlobal(DeferredGlobalConstantValue constant, [_]) {
     int hash = constant.unit.hashCode;
     return _combine(hash, _visit(constant.referenced));
@@ -2374,8 +2350,8 @@
   ///
   /// This is currently used in [MinifyNamer] to assign very short minified
   /// names to things that tend to be used very often.
-  final Map<String, String> _suggestedNames = new Map<String, String>();
-  final Set<String> _usedNames = new Set<String>();
+  final Map<String, String> _suggestedNames = {};
+  final Set<String> _usedNames = Set();
 
   bool isUsed(String name) => _usedNames.contains(name);
   bool isUnused(String name) => !_usedNames.contains(name);
diff --git a/pkg/compiler/lib/src/js_backend/native_data.dart b/pkg/compiler/lib/src/js_backend/native_data.dart
index e41e541..a491286 100644
--- a/pkg/compiler/lib/src/js_backend/native_data.dart
+++ b/pkg/compiler/lib/src/js_backend/native_data.dart
@@ -326,10 +326,10 @@
     Map<LibraryEntity, String> jsInteropLibraries =
         source.readLibraryMap(source.readString);
     Map<ClassEntity, String> jsInteropClasses =
-        source.readLibraryMap(source.readString);
+        source.readClassMap(source.readString);
     Set<ClassEntity> anonymousJsInteropClasses = source.readClasses().toSet();
     Map<MemberEntity, String> jsInteropMembers =
-        source.readLibraryMap(source.readString);
+        source.readMemberMap(source.readString);
     source.end(tag);
     return new NativeBasicDataImpl(
         elementEnvironment,
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 3329424..45be0ee 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -21,7 +21,9 @@
 import '../options.dart';
 import '../serialization/serialization.dart';
 import '../universe/class_hierarchy.dart';
+import '../universe/codegen_world_builder.dart';
 import '../universe/feature.dart';
+import '../universe/resolution_world_builder.dart';
 import '../universe/selector.dart';
 import '../universe/world_builder.dart';
 import '../world.dart' show JClosedWorld, KClosedWorld;
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index ea23cbd..e088e03 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -12,9 +12,9 @@
 import '../js_backend/namer.dart' show Namer;
 import '../js_backend/interceptor_data.dart' show InterceptorData;
 import '../options.dart';
+import '../universe/codegen_world_builder.dart';
 import '../universe/selector.dart' show Selector;
-import '../universe/world_builder.dart'
-    show CodegenWorldBuilder, SelectorConstraints;
+import '../universe/world_builder.dart' show SelectorConstraints;
 import '../world.dart' show JClosedWorld;
 
 import 'code_emitter_task.dart';
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 063d03f..36f8a9f 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -15,7 +15,7 @@
 import '../js/js.dart' as jsAst;
 import '../js_backend/js_backend.dart' show JavaScriptBackend, Namer;
 import '../js_backend/inferred_data.dart';
-import '../universe/world_builder.dart' show CodegenWorldBuilder;
+import '../universe/codegen_world_builder.dart';
 import '../world.dart' show JClosedWorld;
 import 'full_emitter/emitter.dart' as full_js_emitter;
 import 'program_builder/program_builder.dart';
@@ -179,7 +179,6 @@
           compiler.reporter,
           closedWorld.elementEnvironment,
           closedWorld.commonElements,
-          compiler.deferredLoadTask,
           closedWorld.outputUnitData,
           compiler.codegenWorldBuilder,
           backend.nativeCodegenEnqueuer,
@@ -191,7 +190,6 @@
           backend.superMemberData,
           typeTestRegistry.rtiChecks,
           backend.rtiEncoder,
-          backend.jsInteropAnalysis,
           backend.oneShotInterceptorData,
           backend.customElementsCodegenAnalysis,
           backend.generatedCode,
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index a38df23..93b4e7d 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -7,7 +7,6 @@
 import '../constants/values.dart';
 import '../elements/entities.dart'
     show ClassEntity, FieldEntity, MemberEntity, TypedefEntity;
-import '../elements/entity_utils.dart' as utils;
 import '../elements/types.dart';
 import '../js_backend/js_backend.dart' show SyntheticConstantKind;
 import 'sorter.dart' show Sorter;
@@ -177,15 +176,6 @@
     }
   }
 
-  int visitDeferred(DeferredConstantValue a, DeferredConstantValue b) {
-    int r = compareValues(a.referenced, b.referenced);
-    if (r != 0) return r;
-    r = a.import.name.compareTo(b.import.name);
-    if (r != 0) return r;
-    return utils.compareLibrariesUris(
-        a.import.enclosingLibraryUri, b.import.enclosingLibraryUri);
-  }
-
   int visitDeferredGlobal(
       DeferredGlobalConstantValue a, DeferredGlobalConstantValue b) {
     int r = compareValues(a.referenced, b.referenced);
@@ -216,10 +206,9 @@
   static const int TYPE = 10;
   static const int INTERCEPTOR = 11;
   static const int SYNTHETIC = 12;
-  static const int DEFERRED = 13;
-  static const int DEFERRED_GLOBAL = 14;
-  static const int NONCONSTANT = 15;
-  static const int INSTANTIATION = 16;
+  static const int DEFERRED_GLOBAL = 13;
+  static const int NONCONSTANT = 14;
+  static const int INSTANTIATION = 15;
 
   static int kind(ConstantValue constant) =>
       constant.accept(const _KindVisitor(), null);
@@ -237,7 +226,6 @@
   int visitType(TypeConstantValue a, _) => TYPE;
   int visitInterceptor(InterceptorConstantValue a, _) => INTERCEPTOR;
   int visitSynthetic(SyntheticConstantValue a, _) => SYNTHETIC;
-  int visitDeferred(DeferredConstantValue a, _) => DEFERRED;
   int visitDeferredGlobal(DeferredGlobalConstantValue a, _) => DEFERRED_GLOBAL;
   int visitInstantiation(InstantiationConstantValue a, _) => INSTANTIATION;
 }
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
index d009d79..19fecf5 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -15,7 +15,8 @@
 import '../../common_elements.dart' show CommonElements, ElementEnvironment;
 import '../../compiler.dart' show Compiler;
 import '../../constants/values.dart';
-import '../../deferred_load.dart' show OutputUnit, OutputUnitData;
+import '../../deferred_load.dart'
+    show deferredPartFileName, OutputUnit, OutputUnitData;
 import '../../elements/entities.dart';
 import '../../hash/sha1.dart' show Hasher;
 import '../../io/code_output.dart';
@@ -26,8 +27,9 @@
 import '../../js_backend/js_backend.dart'
     show ConstantEmitter, JavaScriptBackend, Namer;
 import '../../js_backend/native_data.dart';
+import '../../js_backend/js_interop_analysis.dart' as jsInteropAnalysis;
 import '../../universe/call_structure.dart' show CallStructure;
-import '../../universe/world_builder.dart' show CodegenWorldBuilder;
+import '../../universe/codegen_world_builder.dart';
 import '../../util/uri_extras.dart' show relativize;
 import '../../world.dart' show JClosedWorld;
 import '../constant_ordering.dart' show ConstantOrdering;
@@ -557,7 +559,7 @@
     List<jsAst.Expression> laziesInfo = <jsAst.Expression>[];
     for (StaticField field in lazies) {
       laziesInfo.add(js.quoteName(field.name));
-      laziesInfo.add(js.quoteName(namer.deriveLazyInitializerName(field.name)));
+      laziesInfo.add(js.quoteName(field.getterName));
       laziesInfo.add(field.code);
       if (!compiler.options.enableMinification) {
         laziesInfo.add(js.quoteName(field.name));
@@ -1489,7 +1491,7 @@
     }
 
     createDeferredLoadingData(
-        compiler.deferredLoadTask.hunksToLoad, deferredLoadHashes, store);
+        _closedWorld.outputUnitData.hunksToLoad, deferredLoadHashes, store);
 
     return new jsAst.Block(parts);
   }
@@ -1516,8 +1518,10 @@
         if (index == null) {
           index = fragmentIndexes[fragment] = fragmentIndexes.length;
           uris.add(js.escapedString(
-              compiler.deferredLoadTask.deferredPartFileName(fragment.name)));
-          hashes.add(deferredLoadHashes[fragment]);
+              deferredPartFileName(compiler.options, fragment.name)));
+          _DeferredOutputUnitHash hash = deferredLoadHashes[fragment];
+          assert(hash != null, "No hash for $fragment in $deferredLoadHashes.");
+          hashes.add(hash);
         }
         indexes.add(js.number(index));
       }
@@ -1632,8 +1636,9 @@
         outputListeners.add(locationCollector);
       }
 
-      String partPrefix = compiler.deferredLoadTask
-          .deferredPartFileName(outputUnit.name, addExtension: false);
+      String partPrefix = deferredPartFileName(
+          compiler.options, outputUnit.name,
+          addExtension: false);
       CodeOutput output = new StreamCodeOutput(
           compiler.outputProvider
               .createOutputSink(partPrefix, 'part.js', OutputType.jsPart),
@@ -1710,7 +1715,8 @@
     // data.
     mapping["_comment"] = "This mapping shows which compiled `.js` files are "
         "needed for a given deferred library import.";
-    mapping.addAll(compiler.deferredLoadTask.computeDeferredMap());
+    mapping.addAll(_closedWorld.outputUnitData
+        .computeDeferredMap(compiler.options, _elementEnvironment));
     compiler.outputProvider.createOutputSink(
         compiler.options.deferredMapUri.path, '', OutputType.info)
       ..add(const JsonEncoder.withIndent("  ").convert(mapping))
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
index 4f1d533..b136d73 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
@@ -73,7 +73,7 @@
       int type, List argNames, Selector selector, jsAst.Name internalName) {
     if (!generateTrivialNsmHandlers) return false;
     // Check for named arguments.
-    if (argNames.length != 0) return false;
+    if (argNames.isNotEmpty) return false;
     if (selector.typeArgumentCount > 0) return false;
     // Check for unexpected name (this doesn't really happen).
     if (internalName is GetterName) return type == 1;
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
index a6a0143..0c1fda6 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
@@ -102,7 +102,8 @@
     'needsMixinSupport': emitter.needsMixinSupport,
     'needsNativeSupport': program.needsNativeSupport,
     'enabledJsInterop': closedWorld.nativeData.isJsInteropUsed,
-    'jsInteropBoostrap': backend.jsInteropAnalysis.buildJsInteropBootstrap(),
+    'jsInteropBoostrap': jsInteropAnalysis.buildJsInteropBootstrap(
+        compiler.codegenWorldBuilder, closedWorld.nativeData, namer),
     'isInterceptorClass':
         namer.operatorIs(closedWorld.commonElements.jsInterceptorClass),
     'isObject': namer.operatorIs(closedWorld.commonElements.objectClass),
@@ -118,7 +119,9 @@
         compiler.options, emitter, namer, closedWorld.commonElements),
     'nativeInfoHandler': nativeInfoHandler,
     'operatorIsPrefix': js.string(namer.operatorIsPrefix),
-    'deferredActionString': js.string(namer.deferredAction)
+    'deferredActionString': js.string(namer.deferredAction),
+    'callCatchAll':
+        js.quoteName(namer.getNameForJsGetName(null, JsGetName.CALL_CATCH_ALL)),
   };
   String skeleton = '''
 function $setupProgramName(programData, metadataOffset, typesOffset) {
@@ -709,7 +712,7 @@
           funcs[0].$metadataIndexField = unmangledNameIndex + 1;
           // The following line installs the [${JsGetName.CALL_CATCH_ALL}]
           // property for closures.
-          if (optionalParameterCount) prototype[unmangledName + "*"] = funcs[applyTrampolineIndex];
+          if (optionalParameterCount) prototype[#callCatchAll] = funcs[applyTrampolineIndex];
         }
       }
     }
diff --git a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
index f8dabcf..e6fbf87 100644
--- a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
@@ -12,9 +12,9 @@
 import '../js/js.dart' show js;
 import '../js_backend/namer.dart' show Namer;
 import '../universe/call_structure.dart' show CallStructure;
+import '../universe/codegen_world_builder.dart';
 import '../universe/selector.dart' show Selector;
-import '../universe/world_builder.dart'
-    show CodegenWorldBuilder, SelectorConstraints;
+import '../universe/world_builder.dart' show SelectorConstraints;
 import '../world.dart' show JClosedWorld;
 
 import 'model.dart';
diff --git a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
index 0e3bb18..d91972f 100644
--- a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
@@ -19,8 +19,8 @@
 import '../js_backend/interceptor_data.dart';
 import '../native/enqueue.dart';
 import '../options.dart';
+import '../universe/codegen_world_builder.dart';
 import '../universe/selector.dart' show Selector;
-import '../universe/world_builder.dart' show CodegenWorldBuilder;
 import '../world.dart' show JClosedWorld;
 
 import 'code_emitter_task.dart' show CodeEmitterTask, Emitter;
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index cdf72cb..db2d3c0 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -17,7 +17,7 @@
 import '../js/js.dart' show js;
 import '../js_backend/runtime_types.dart' show RuntimeTypesEncoder;
 import '../options.dart';
-import '../universe/world_builder.dart' show CodegenWorldBuilder;
+import '../universe/codegen_world_builder.dart';
 
 import 'code_emitter_task.dart' show Emitter;
 
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index 78d8585..ab6fbae 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -213,7 +213,8 @@
   /// Uses indicate missing information in the model.
   final FieldEntity element;
 
-  js.Name name;
+  final js.Name name;
+  final js.Name getterName;
   // TODO(floitsch): the holder for static fields is the isolate object. We
   // could remove this field and use the isolate object directly.
   final Holder holder;
@@ -221,8 +222,8 @@
   final bool isFinal;
   final bool isLazy;
 
-  StaticField(this.element, this.name, this.holder, this.code, this.isFinal,
-      this.isLazy);
+  StaticField(this.element, this.name, this.getterName, this.holder, this.code,
+      this.isFinal, this.isLazy);
 
   String toString() {
     return 'StaticField(name=${name.key},element=${element})';
@@ -447,8 +448,9 @@
   // this field holds a function computing the function signature.
   final js.Expression functionType;
 
-  // Signature information for this method. This is only required and stored
-  // here if the method [canBeApplied].
+  // Signature information for this method. [optionalParameterDefaultValues] is
+  // only required and stored here if the method [canBeApplied]. The count is
+  // always stored to help select specialized tear-off paths.
   final int requiredParameterCount;
   final /* Map | List */ optionalParameterDefaultValues;
 
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index 0a7ccef..85230aa 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -13,7 +13,7 @@
 import '../js_backend/interceptor_data.dart';
 import '../js_backend/native_data.dart';
 import '../native/enqueue.dart' show NativeCodegenEnqueuer;
-import '../universe/world_builder.dart' show CodegenWorldBuilder;
+import '../universe/codegen_world_builder.dart';
 import '../world.dart' show JClosedWorld;
 
 import 'code_emitter_task.dart' show CodeEmitterTask;
diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
index 0492ada..7076c68 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -15,9 +15,9 @@
 import '../js_backend/interceptor_data.dart';
 import '../js_backend/runtime_types.dart';
 import '../universe/call_structure.dart' show CallStructure;
+import '../universe/codegen_world_builder.dart';
 import '../universe/selector.dart' show Selector;
-import '../universe/world_builder.dart'
-    show CodegenWorldBuilder, SelectorConstraints;
+import '../universe/world_builder.dart' show SelectorConstraints;
 import '../world.dart' show JClosedWorld;
 
 import 'model.dart';
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 4780f74..d4f6901 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
@@ -13,7 +13,7 @@
     show ConstantValue, InterceptorConstantValue;
 import '../../common_elements.dart' show JCommonElements, JElementEnvironment;
 import '../../deferred_load.dart'
-    show DeferredLoadTask, OutputUnit, OutputUnitData;
+    show deferredPartFileName, OutputUnit, OutputUnitData;
 import '../../elements/entities.dart';
 import '../../elements/types.dart';
 import '../../io/source_information.dart';
@@ -26,7 +26,6 @@
 import '../../js_backend/custom_elements_analysis.dart';
 import '../../js_backend/inferred_data.dart';
 import '../../js_backend/interceptor_data.dart';
-import '../../js_backend/js_interop_analysis.dart';
 import '../../js_backend/namer.dart' show Namer, StringBackedName;
 import '../../js_backend/native_data.dart';
 import '../../js_backend/runtime_types.dart'
@@ -34,9 +33,9 @@
 import '../../js_model/elements.dart' show JGeneratorBody, JSignatureMethod;
 import '../../native/enqueue.dart' show NativeCodegenEnqueuer;
 import '../../options.dart';
+import '../../universe/codegen_world_builder.dart';
 import '../../universe/selector.dart' show Selector;
-import '../../universe/world_builder.dart'
-    show CodegenWorldBuilder, SelectorConstraints;
+import '../../universe/world_builder.dart' show SelectorConstraints;
 import '../../world.dart' show JClosedWorld;
 import '../js_emitter.dart'
     show
@@ -63,7 +62,6 @@
   final DiagnosticReporter _reporter;
   final JElementEnvironment _elementEnvironment;
   final JCommonElements _commonElements;
-  final DeferredLoadTask _deferredLoadTask;
   final OutputUnitData _outputUnitData;
   final CodegenWorldBuilder _worldBuilder;
   final NativeCodegenEnqueuer _nativeCodegenEnqueuer;
@@ -75,7 +73,6 @@
   final SuperMemberData _superMemberData;
   final RuntimeTypesChecks _rtiChecks;
   final RuntimeTypesEncoder _rtiEncoder;
-  final JsInteropAnalysis _jsInteropAnalysis;
   final OneShotInterceptorData _oneShotInterceptorData;
   final CustomElementsCodegenAnalysis _customElementsCodegenAnalysis;
   final Map<MemberEntity, js.Expression> _generatedCode;
@@ -109,7 +106,6 @@
       this._reporter,
       this._elementEnvironment,
       this._commonElements,
-      this._deferredLoadTask,
       this._outputUnitData,
       this._worldBuilder,
       this._nativeCodegenEnqueuer,
@@ -121,7 +117,6 @@
       this._superMemberData,
       this._rtiChecks,
       this._rtiEncoder,
-      this._jsInteropAnalysis,
       this._oneShotInterceptorData,
       this._customElementsCodegenAnalysis,
       this._generatedCode,
@@ -338,7 +333,7 @@
   /// Builds a map from loadId to outputs-to-load.
   Map<String, List<Fragment>> _buildLoadMap() {
     Map<String, List<Fragment>> loadMap = <String, List<Fragment>>{};
-    _deferredLoadTask.hunksToLoad
+    _closedWorld.outputUnitData.hunksToLoad
         .forEach((String loadId, List<OutputUnit> outputUnits) {
       loadMap[loadId] = outputUnits
           .map((OutputUnit unit) => _outputs[unit])
@@ -383,8 +378,7 @@
   DeferredFragment _buildDeferredFragment(LibrariesMap librariesMap) {
     DeferredFragment result = new DeferredFragment(
         librariesMap.outputUnit,
-        _deferredLoadTask.deferredPartFileName(librariesMap.name,
-            addExtension: false),
+        deferredPartFileName(_options, librariesMap.name, addExtension: false),
         librariesMap.name,
         _buildLibraries(librariesMap),
         _buildStaticNonFinalFields(librariesMap),
@@ -427,8 +421,8 @@
     // building a static field. (Note that the static-state holder was
     // already registered earlier, and that we just call the register to get
     // the holder-instance.
-    return new StaticField(
-        element, name, _registerStaticStateHolder(), code, isFinal, isLazy);
+    return new StaticField(element, name, null, _registerStaticStateHolder(),
+        code, isFinal, isLazy);
   }
 
   List<StaticField> _buildStaticLazilyInitializedFields(
@@ -453,14 +447,15 @@
     if (code == null) return null;
 
     js.Name name = _namer.globalPropertyNameForMember(element);
+    js.Name getterName = _namer.lazyInitializerName(element);
     bool isFinal = !element.isAssignable;
     bool isLazy = true;
     // TODO(floitsch): we shouldn't update the registry in the middle of
     // building a static field. (Note that the static-state holder was
     // already registered earlier, and that we just call the register to get
     // the holder-instance.
-    return new StaticField(
-        element, name, _registerStaticStateHolder(), code, isFinal, isLazy);
+    return new StaticField(element, name, getterName,
+        _registerStaticStateHolder(), code, isFinal, isLazy);
   }
 
   List<Library> _buildLibraries(LibrariesMap librariesMap) {
@@ -646,8 +641,7 @@
         _task,
         _namer,
         _rtiChecks,
-        _rtiEncoder,
-        _jsInteropAnalysis);
+        _rtiEncoder);
 
     void visitInstanceMember(MemberEntity member) {
       if (!member.isAbstract && !member.isField) {
@@ -919,17 +913,14 @@
       functionType = _generateFunctionType(memberType, outputUnit);
     }
 
-    int requiredParameterCount;
+    FunctionEntity method = element;
+    ParameterStructure parameterStructure = method.parameterStructure;
+    int requiredParameterCount = parameterStructure.requiredParameters;
     var /* List | Map */ optionalParameterDefaultValues;
     int applyIndex = 0;
     if (canBeApplied) {
-      // TODO(redemption): Handle function entities.
-      FunctionEntity method = element;
-      ParameterStructure parameterStructure = method.parameterStructure;
-      requiredParameterCount = parameterStructure.requiredParameters;
       optionalParameterDefaultValues = _computeParameterDefaultValues(method);
-
-      if (element.parameterStructure.typeParameters > 0) {
+      if (parameterStructure.typeParameters > 0) {
         applyIndex = 1;
       }
     }
@@ -1148,14 +1139,12 @@
       functionType = _generateFunctionType(type, outputUnit);
     }
 
-    int requiredParameterCount;
+    FunctionEntity method = element;
+    ParameterStructure parameterStructure = method.parameterStructure;
+    int requiredParameterCount = parameterStructure.requiredParameters;
     var /* List | Map */ optionalParameterDefaultValues;
     int applyIndex = 0;
     if (canBeApplied) {
-      // TODO(redemption): Support entities;
-      FunctionEntity method = element;
-      ParameterStructure parameterStructure = method.parameterStructure;
-      requiredParameterCount = parameterStructure.requiredParameters;
       optionalParameterDefaultValues = _computeParameterDefaultValues(method);
       if (parameterStructure.typeParameters > 0) {
         applyIndex = 1;
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index cd30c3d..7d974f3 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -10,7 +10,7 @@
 import '../elements/types.dart';
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show js;
-import '../js_backend/js_interop_analysis.dart';
+import '../js_backend/js_interop_analysis.dart' as jsInteropAnalysis;
 import '../js_backend/namer.dart' show Namer;
 import '../js_backend/runtime_types.dart'
     show
@@ -95,17 +95,10 @@
   final Namer _namer;
   final RuntimeTypesChecks _rtiChecks;
   final RuntimeTypesEncoder _rtiEncoder;
-  final JsInteropAnalysis _jsInteropAnalysis;
   final _TypeContainedInOutputUnitVisitor _outputUnitVisitor;
 
-  RuntimeTypeGenerator(
-      this._commonElements,
-      this._outputUnitData,
-      this.emitterTask,
-      this._namer,
-      this._rtiChecks,
-      this._rtiEncoder,
-      this._jsInteropAnalysis)
+  RuntimeTypeGenerator(this._commonElements, this._outputUnitData,
+      this.emitterTask, this._namer, this._rtiChecks, this._rtiEncoder)
       : _outputUnitVisitor = new _TypeContainedInOutputUnitVisitor(
             _commonElements, _outputUnitData);
 
@@ -206,7 +199,7 @@
         classElement, generateFunctionTypeSignature, generateTypeCheck);
 
     if (classElement == _commonElements.jsJavaScriptFunctionClass) {
-      var type = _jsInteropAnalysis.buildJsFunctionType();
+      var type = jsInteropAnalysis.buildJsFunctionType();
       if (type != null) {
         jsAst.Expression thisAccess = new jsAst.This();
         jsAst.Expression encoding = _rtiEncoder.getSignatureEncoding(
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index e13bf8f..266099f 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -69,16 +69,13 @@
 // copying properties) on platforms where we know it works well (Chrome / d8).
 var supportsDirectProtoAccess = #directAccessTestExpression;
 
-var functionsHaveName = (function() {
-  function t() {};
-  return (typeof t.name == 'string')
-})();
-
 // Sets the name property of functions, if the JS engine doesn't set the name
 // itself.
 // As of 2018 only IE11 doesn't set the name.
 function setFunctionNamesIfNecessary(holders) {
-  if (functionsHaveName) return;
+  function t(){};
+  if (typeof t.name == "string") return;
+
   for (var i = 0; i < holders.length; i++) {
     var holder = holders[i];
     var keys = Object.keys(holder);
@@ -250,6 +247,29 @@
   }
 }
 
+function installStaticTearOff(
+    container, getterName,
+    requiredParameterCount, optionalParameterDefaultValues,
+    callNames, funsOrNames, funType, applyIndex) {
+  // TODO(sra): Specialize installTearOff for static methods. It might be
+  // possible to handle some very common simple cases directly.
+  return installTearOff(
+      container, getterName, true, false,
+      requiredParameterCount, optionalParameterDefaultValues,
+      callNames, funsOrNames, funType, applyIndex);
+}
+
+function installInstanceTearOff(
+    container, getterName, isIntercepted,
+    requiredParameterCount, optionalParameterDefaultValues,
+    callNames, funsOrNames, funType, applyIndex) {
+  // TODO(sra): Specialize installTearOff for instance methods.
+  return installTearOff(
+      container, getterName, false, isIntercepted,
+      requiredParameterCount, optionalParameterDefaultValues,
+      callNames, funsOrNames, funType, applyIndex);
+}
+
 // Instead of setting the interceptor tags directly we use this update
 // function. This makes it easier for deferred fragments to contribute to the
 // embedded global.
@@ -292,6 +312,63 @@
   return holder;
 }
 
+var #hunkHelpers = (function(){
+  var mkInstance = function(
+      isIntercepted, requiredParameterCount, optionalParameterDefaultValues,
+      callNames, applyIndex) {
+    return function(container, getterName, name, funType) {
+      return installInstanceTearOff(
+          container, getterName, isIntercepted,
+          requiredParameterCount, optionalParameterDefaultValues,
+          callNames, [name], funType, applyIndex);
+    }
+  },
+
+  mkStatic = function(
+      requiredParameterCount, optionalParameterDefaultValues,
+      callNames, applyIndex) {
+    return function(container, getterName, name, funType) {
+      return installStaticTearOff(
+          container, getterName,
+          requiredParameterCount, optionalParameterDefaultValues,
+          callNames, [name], funType, applyIndex);
+    }
+  };
+
+  // TODO(sra): Minify properties of 'hunkHelpers'.
+  return {
+    inherit: inherit,
+    inheritMany: inheritMany,
+    mixin: mixin,
+    installStaticTearOff: installStaticTearOff,
+    installInstanceTearOff: installInstanceTearOff,
+
+        // Unintercepted methods.
+    _instance_0u: mkInstance(0, 0, null, [#call0selector], 0),
+    _instance_1u: mkInstance(0, 1, null, [#call1selector], 0),
+    _instance_2u: mkInstance(0, 2, null, [#call2selector], 0),
+
+        // Intercepted methods.
+    _instance_0i: mkInstance(1, 0, null, [#call0selector], 0),
+    _instance_1i: mkInstance(1, 1, null, [#call1selector], 0),
+    _instance_2i: mkInstance(1, 2, null, [#call2selector], 0),
+
+        // Static methods.
+    _static_0: mkStatic(0, null, [#call0selector], 0),
+    _static_1: mkStatic(1, null, [#call1selector], 0),
+    _static_2: mkStatic(2, null, [#call2selector], 0),
+
+    makeConstList: makeConstList,
+    lazy: lazy,
+    updateHolder: updateHolder,
+    convertToFastObject: convertToFastObject,
+    setFunctionNamesIfNecessary: setFunctionNamesIfNecessary,
+    updateTypes: updateTypes,
+    setOrUpdateInterceptorsByTag: setOrUpdateInterceptorsByTag,
+    setOrUpdateLeafTags: setOrUpdateLeafTags,
+  };
+})();
+
 // Every deferred hunk (i.e. fragment) is a function that we can invoke to
 // initialize it. At this moment it contributes its data to the main hunk.
 function initializeDeferredHunk(hunk) {
@@ -299,10 +376,7 @@
   typesOffset = #embeddedTypes.length;
 
   // TODO(floitsch): extend natives.
-  hunk(inherit, inheritMany, mixin, lazy, makeConstList, convertToFastObject, installTearOff,
-       setFunctionNamesIfNecessary, updateHolder, updateTypes,
-       setOrUpdateInterceptorsByTag, setOrUpdateLeafTags,
-       #embeddedGlobalsObject, holders, #staticState);
+  hunk(hunkHelpers, #embeddedGlobalsObject, holders, #staticState);
 }
 
 // Returns the global with the given [name].
@@ -325,8 +399,7 @@
     softDef = function(o) {};  // Replace ourselves.
     #deferredGlobal[#softId](
         holders, #embeddedGlobalsObject, #staticState,
-        inherit, inheritMany, mixin,
-        installTearOff);
+        hunkHelpers);
     if (o != null) {
       // TODO(29574): should we do something different for Firefox?
       // If we recommend that the program triggers the load by itself before
@@ -345,7 +418,7 @@
 #holders;
 
 // If the name is not set on the functions, do it now.
-setFunctionNamesIfNecessary(holders);
+hunkHelpers.setFunctionNamesIfNecessary(holders);
 
 // TODO(floitsch): we should build this object as a literal.
 var #staticStateDeclaration = {};
@@ -424,16 +497,13 @@
 ///
 /// This template is used for Dart 2.
 const String deferredBoilerplateDart2 = '''
-function(inherit, inheritMany, mixin, lazy, makeConstList, convertToFastObject,
-         installTearOff, setFunctionNamesIfNecessary, updateHolder, updateTypes,
-         setOrUpdateInterceptorsByTag, setOrUpdateLeafTags,
-         #embeddedGlobalsObject, holdersList, #staticState) {
+function(hunkHelpers, #embeddedGlobalsObject, holdersList, #staticState) {
 
 // Builds the holders. They only contain the data for new holders.
 #holders;
 
 // If the name is not set on the functions, do it now.
-setFunctionNamesIfNecessary(#deferredHoldersList);
+hunkHelpers.setFunctionNamesIfNecessary(#deferredHoldersList);
 
 // Updates the holders of the main-fragment. Uses the provided holdersList to
 // access the main holders.
@@ -446,7 +516,7 @@
 // These can only refer to regular classes and in Dart 2 only closures have
 // function types so the `typesOffset` has been safely computed before it's
 // referred in the signatures of the `closures` below.
-var #typesOffset = updateTypes(#types);
+var #typesOffset = hunkHelpers.updateTypes(#types);
 #closures;
 // Sets aliases of methods (on the prototypes of classes).
 #aliases;
@@ -475,8 +545,7 @@
 const String softDeferredBoilerplate = '''
 #deferredGlobal[#softId] =
   function(holdersList, #embeddedGlobalsObject, #staticState,
-           inherit, inheritMany, mixin,
-           installTearOff) {
+           hunkHelpers) {
 
 // Installs the holders as local variables.
 #installHoldersAsLocals;
@@ -506,6 +575,14 @@
   final ModelEmitter modelEmitter;
   final JClosedWorld _closedWorld;
 
+  js.Name _call0Name, _call1Name, _call2Name;
+  js.Name get call0Name =>
+      _call0Name ??= namer.getNameForJsGetName(null, JsGetName.CALL_PREFIX0);
+  js.Name get call1Name =>
+      _call1Name ??= namer.getNameForJsGetName(null, JsGetName.CALL_PREFIX1);
+  js.Name get call2Name =>
+      _call2Name ??= namer.getNameForJsGetName(null, JsGetName.CALL_PREFIX2);
+
   FragmentEmitter(this.compiler, this.namer, this.backend, this.constantEmitter,
       this.modelEmitter, this._closedWorld);
 
@@ -532,6 +609,8 @@
         emitHolders(program.holders, fragment, initializeEmptyHolders: true);
 
     js.Statement mainCode = js.js.statement(mainBoilerplate, {
+      // TODO(29455): 'hunkHelpers' displaces other names, so don't minify it.
+      'hunkHelpers': js.VariableDeclaration('hunkHelpers', allowRename: false),
       'directAccessTestExpression': js.js(directAccessTestExpression),
       'cyclicThrow': backend.emitter
           .staticFunctionAccess(_closedWorld.commonElements.cyclicThrowHelper),
@@ -568,10 +647,14 @@
       'nativeSupport': program.needsNativeSupport
           ? emitNativeSupport(fragment)
           : new js.EmptyStatement(),
-      'jsInteropSupport': _closedWorld.nativeData.isJsInteropUsed
-          ? backend.jsInteropAnalysis.buildJsInteropBootstrap()
-          : new js.EmptyStatement(),
+      'jsInteropSupport': jsInteropAnalysis.buildJsInteropBootstrap(
+              compiler.codegenWorldBuilder, _closedWorld.nativeData, namer) ??
+          new js.EmptyStatement(),
       'invokeMain': fragment.invokeMain,
+
+      'call0selector': js.quoteName(call0Name),
+      'call1selector': js.quoteName(call1Name),
+      'call2selector': js.quoteName(call2Name),
     });
     if (program.hasSoftDeferredClasses) {
       return new js.Block([
@@ -619,10 +702,11 @@
       Holder holder = nonStaticStateHolders[i];
       if (holderCode.activeHolders.contains(holder)) {
         updateHolderAssignments.add(js.js.statement(
-            '#holder = updateHolder(holdersList[#index], #holder)', {
-          'index': js.number(i),
-          'holder': new js.VariableUse(holder.name)
-        }));
+            '#holder = hunkHelpers.updateHolder(holdersList[#index], #holder)',
+            {
+              'index': js.number(i),
+              'holder': new js.VariableUse(holder.name)
+            }));
       } else {
         // TODO(sra): Change declaration followed by assignments to declarations
         // with initialization.
@@ -947,15 +1031,14 @@
     if (cls.superclass == null) {
       // TODO(sra): What is this doing? Document or remove.
       properties
-          .add(new js.Property(js.string("constructor"), classReference(cls)));
-      properties
-          .add(new js.Property(namer.operatorIs(cls.element), js.number(1)));
+          .add(js.Property(js.string("constructor"), classReference(cls)));
+      properties.add(js.Property(namer.operatorIs(cls.element), js.number(1)));
     }
 
     allMethods.forEach((Method method) {
       emitInstanceMethod(method)
           .forEach((js.Expression name, js.Expression code) {
-        var prop = new js.Property(name, code);
+        var prop = js.Property(name, code);
         compiler.dumpInfoTask.registerEntityAst(method.element, prop);
         properties.add(prop);
       });
@@ -965,8 +1048,14 @@
       // Closures extend a common base class, so we can put properties on the
       // prototype for common values.
 
+      // Closures taking exactly one argument are common.
+      properties.add(js.Property(
+          js.string(namer.callCatchAllName), js.quoteName(call1Name)));
+      properties.add(
+          js.Property(js.string(namer.requiredParameterField), js.number(1)));
+
       // Most closures have no optional arguments.
-      properties.add(new js.Property(
+      properties.add(js.Property(
           js.string(namer.defaultValuesField), new js.LiteralNull()));
     }
 
@@ -1049,12 +1138,22 @@
         // complex cases. [forceAdd] might be true when this is fixed.
         bool forceAdd = !method.isClosureCallMethod;
 
-        properties[js.string(namer.callCatchAllName)] = js.quoteName(
-            method.applyIndex == 0
-                ? method.name
-                : method.parameterStubs[method.applyIndex - 1].name);
-        properties[js.string(namer.requiredParameterField)] =
-            js.number(method.requiredParameterCount);
+        // Common case of "call*": "call$1" is stored on the Closure class.
+        if (method.applyIndex != 0 ||
+            method.parameterStubs.isNotEmpty ||
+            method.requiredParameterCount != 1 ||
+            forceAdd) {
+          js.Name applyName = method.applyIndex == 0
+              ? method.name
+              : method.parameterStubs[method.applyIndex - 1].name;
+          properties[js.string(namer.callCatchAllName)] =
+              js.quoteName(applyName);
+        }
+        // Common case of '1' is stored on the Closure class.
+        if (method.requiredParameterCount != 1 || forceAdd) {
+          properties[js.string(namer.requiredParameterField)] =
+              js.number(method.requiredParameterCount);
+        }
 
         js.Expression defaultValues =
             _encodeOptionalParameterDefaultValues(method);
@@ -1077,7 +1176,7 @@
     List<js.Statement> inheritCalls = [];
     List<js.Statement> mixinCalls = [];
     // local caches of functions to allow minifaction of function name in call.
-    Map<String, js.Expression> locals = {};
+    LocalAliases locals = LocalAliases();
 
     Set<Class> classesInFragment = Set();
     for (Library library in fragment.libraries) {
@@ -1105,11 +1204,12 @@
       for (Class cls in library.classes) {
         if (cls.isSoftDeferred != softDeferred) continue;
         collect(cls);
-
         if (cls.mixinClass != null) {
-          locals['_mixin'] ??= js.js('mixin');
-          mixinCalls.add(js.js.statement('_mixin(#, #)',
-              [classReference(cls), classReference(cls.mixinClass)]));
+          mixinCalls.add(js.js.statement('#(#, #)', [
+            locals.find('_mixin', 'hunkHelpers.mixin'),
+            classReference(cls),
+            classReference(cls.mixinClass),
+          ]));
         }
       }
     }
@@ -1120,26 +1220,24 @@
           ? new js.LiteralNull()
           : classReference(superclass);
       if (list.length == 1) {
-        locals['_inherit'] ??= js.js('inherit');
-        inheritCalls.add(js.js.statement('_inherit(#, #)',
-            [classReference(list.single), superclassReference]));
+        inheritCalls.add(js.js.statement('#(#, #)', [
+          locals.find('_inherit', 'hunkHelpers.inherit'),
+          classReference(list.single),
+          superclassReference
+        ]));
       } else {
-        locals['_inheritMany'] ??= js.js('inheritMany');
         var listElements = list.map(classReference).toList();
-        inheritCalls.add(js.js.statement('_inheritMany(#, #)',
-            [superclassReference, js.ArrayInitializer(listElements)]));
+        inheritCalls.add(js.js.statement('#(#, #)', [
+          locals.find('_inheritMany', 'hunkHelpers.inheritMany'),
+          superclassReference,
+          js.ArrayInitializer(listElements)
+        ]));
       }
     }
 
     List<js.Statement> statements = [];
     if (locals.isNotEmpty) {
-      List<js.VariableInitialization> initializations = [];
-      locals.forEach((local, value) {
-        initializations.add(
-            js.VariableInitialization(js.VariableDeclaration(local), value));
-      });
-      statements.add(
-          js.ExpressionStatement(js.VariableDeclarationList(initializations)));
+      statements.add(locals.toStatement());
     }
     statements.addAll(inheritCalls);
     statements.addAll(mixinCalls);
@@ -1204,75 +1302,6 @@
     }
   }
 
-  /// Emits the statement that installs a tear off for a method.
-  ///
-  /// Tear-offs might be passed to `Function.apply` which means that all
-  /// calling-conventions (with or without optional positional/named arguments)
-  /// are possible. As such, the tear-off needs enough information to fill in
-  /// missing parameters.
-  js.Statement emitInstallTearOff(js.Expression container, DartMethod method) {
-    List<js.Name> callNames = [];
-    List<js.Expression> funsOrNames = [];
-
-    /// Adds the stub-method's code or name to the [funsOrNames] array.
-    ///
-    /// Static methods don't need stub-methods except for tear-offs. As such,
-    /// they are not emitted in the prototype, but directly passed here.
-    ///
-    /// Instance-methods install the stub-methods in their prototype, and we
-    /// use string-based redirections to find them there.
-    void addFunOrName(StubMethod stubMethod) {
-      if (method.isStatic) {
-        funsOrNames.add(stubMethod.code);
-      } else {
-        funsOrNames.add(js.quoteName(stubMethod.name));
-      }
-    }
-
-    callNames.add(method.callName);
-    // The first entry in the funsOrNames-array must be a string.
-    funsOrNames.add(js.quoteName(method.name));
-    for (ParameterStubMethod stubMethod in method.parameterStubs) {
-      callNames.add(stubMethod.callName);
-      addFunOrName(stubMethod);
-    }
-
-    js.ArrayInitializer callNameArray =
-        new js.ArrayInitializer(callNames.map(js.quoteName).toList());
-    js.ArrayInitializer funsOrNamesArray = new js.ArrayInitializer(funsOrNames);
-
-    bool isIntercepted = false;
-    if (method is InstanceMethod) {
-      isIntercepted = method.isIntercepted;
-    }
-    int requiredParameterCount = 0;
-    js.Expression optionalParameterDefaultValues = new js.LiteralNull();
-    if (method.canBeApplied) {
-      requiredParameterCount = method.requiredParameterCount;
-      optionalParameterDefaultValues =
-          _encodeOptionalParameterDefaultValues(method);
-    }
-
-    var applyIndex = js.number(method.applyIndex);
-
-    return js.js.statement('''
-        installTearOff(#container, #getterName, #isStatic, #isIntercepted,
-                       #requiredParameterCount, #optionalParameterDefaultValues,
-                       #callNames, #funsOrNames, #funType, #applyIndex)''', {
-      "container": container,
-      "getterName": js.quoteName(method.tearOffName),
-      // 'Truthy' values are ok for `isStatic` and `isIntercepted`.
-      "isStatic": js.number(method.isStatic ? 1 : 0),
-      "isIntercepted": js.number(isIntercepted ? 1 : 0),
-      "requiredParameterCount": js.number(requiredParameterCount),
-      "optionalParameterDefaultValues": optionalParameterDefaultValues,
-      "callNames": callNameArray,
-      "funsOrNames": funsOrNamesArray,
-      "funType": method.functionType,
-      "applyIndex": applyIndex,
-    });
-  }
-
   /// Wraps the statement in a named function to that it shows up as a unit in
   /// profiles.
   // TODO(sra): Should this be conditional?
@@ -1292,6 +1321,149 @@
   /// Emits the section that installs tear-off getters.
   js.Statement emitInstallTearOffs(Fragment fragment,
       {bool softDeferred = false}) {
+    LocalAliases locals = LocalAliases();
+
+    /// Emits the statement that installs a tear off for a method.
+    ///
+    /// Tear-offs might be passed to `Function.apply` which means that all
+    /// calling-conventions (with or without optional positional/named
+    /// arguments) are possible. As such, the tear-off needs enough information
+    /// to fill in missing parameters.
+    js.Statement emitInstallTearOff(
+        js.Expression container, DartMethod method) {
+      List<js.Name> callNames = [];
+      List<js.Expression> funsOrNames = [];
+
+      /// Adds the stub-method's code or name to the [funsOrNames] array.
+      ///
+      /// Static methods don't need stub-methods except for tear-offs. As such,
+      /// they are not emitted in the prototype, but directly passed here.
+      ///
+      /// Instance-methods install the stub-methods in their prototype, and we
+      /// use string-based redirections to find them there.
+      void addFunOrName(StubMethod stubMethod) {
+        if (method.isStatic) {
+          funsOrNames.add(stubMethod.code);
+        } else {
+          funsOrNames.add(js.quoteName(stubMethod.name));
+        }
+      }
+
+      callNames.add(method.callName);
+      // The first entry in the funsOrNames-array must be a string.
+      funsOrNames.add(js.quoteName(method.name));
+      for (ParameterStubMethod stubMethod in method.parameterStubs) {
+        callNames.add(stubMethod.callName);
+        addFunOrName(stubMethod);
+      }
+
+      js.ArrayInitializer callNameArray =
+          new js.ArrayInitializer(callNames.map(js.quoteName).toList());
+      js.ArrayInitializer funsOrNamesArray =
+          new js.ArrayInitializer(funsOrNames);
+
+      bool isIntercepted = false;
+      if (method is InstanceMethod) {
+        isIntercepted = method.isIntercepted;
+      }
+
+      int requiredParameterCount = method.requiredParameterCount;
+      js.Expression optionalParameterDefaultValues = new js.LiteralNull();
+      if (method.canBeApplied) {
+        optionalParameterDefaultValues =
+            _encodeOptionalParameterDefaultValues(method);
+      }
+
+      var applyIndex = js.number(method.applyIndex);
+
+      if (method.isStatic) {
+        if (requiredParameterCount <= 2 &&
+            callNames.length == 1 &&
+            optionalParameterDefaultValues is js.LiteralNull &&
+            method.applyIndex == 0) {
+          js.Statement finish(int arity) {
+            // Short form for exactly 0/1/2 arguments.
+            var install =
+                locals.find('_static_${arity}', 'hunkHelpers._static_${arity}');
+            return js.js.statement('''
+                #install(#container, #getterName, #name, #funType)''', {
+              "install": install,
+              "container": container,
+              "getterName": js.quoteName(method.tearOffName),
+              "name": funsOrNames.single,
+              "funType": method.functionType,
+            });
+          }
+
+          var installedName = callNames.single;
+          if (installedName == call0Name) return finish(0);
+          if (installedName == call1Name) return finish(1);
+          if (installedName == call2Name) return finish(2);
+        }
+
+        var install =
+            locals.find('_static', 'hunkHelpers.installStaticTearOff');
+        return js.js.statement('''
+            #install(#container, #getterName,
+                     #requiredParameterCount, #optionalParameterDefaultValues,
+                      #callNames, #funsOrNames, #funType, #applyIndex)''', {
+          "install": install,
+          "container": container,
+          "getterName": js.quoteName(method.tearOffName),
+          "requiredParameterCount": js.number(requiredParameterCount),
+          "optionalParameterDefaultValues": optionalParameterDefaultValues,
+          "callNames": callNameArray,
+          "funsOrNames": funsOrNamesArray,
+          "funType": method.functionType,
+          "applyIndex": applyIndex,
+        });
+      } else {
+        if (requiredParameterCount <= 2 &&
+            callNames.length == 1 &&
+            optionalParameterDefaultValues is js.LiteralNull &&
+            method.applyIndex == 0) {
+          js.Statement finish(int arity) {
+            // Short form for exactly 0/1/2 arguments.
+            String isInterceptedTag = isIntercepted ? 'i' : 'u';
+            var install = locals.find('_instance_${arity}_${isInterceptedTag}',
+                'hunkHelpers._instance_${arity}${isInterceptedTag}');
+            return js.js.statement('''
+                #install(#container, #getterName, #name, #funType)''', {
+              "install": install,
+              "container": container,
+              "getterName": js.quoteName(method.tearOffName),
+              "name": funsOrNames.single,
+              "funType": method.functionType,
+            });
+          }
+
+          var installedName = callNames.single;
+          if (installedName == call0Name) return finish(0);
+          if (installedName == call1Name) return finish(1);
+          if (installedName == call2Name) return finish(2);
+        }
+
+        var install =
+            locals.find('_instance', 'hunkHelpers.installInstanceTearOff');
+        return js.js.statement('''
+            #install(#container, #getterName, #isIntercepted,
+                     #requiredParameterCount, #optionalParameterDefaultValues,
+                     #callNames, #funsOrNames, #funType, #applyIndex)''', {
+          "install": install,
+          "container": container,
+          "getterName": js.quoteName(method.tearOffName),
+          // 'Truthy' values are ok for `isIntercepted`.
+          "isIntercepted": js.number(isIntercepted ? 1 : 0),
+          "requiredParameterCount": js.number(requiredParameterCount),
+          "optionalParameterDefaultValues": optionalParameterDefaultValues,
+          "callNames": callNameArray,
+          "funsOrNames": funsOrNamesArray,
+          "funType": method.functionType,
+          "applyIndex": applyIndex,
+        });
+      }
+    }
+
     List<js.Statement> inits = [];
     js.Expression temp;
 
@@ -1325,17 +1497,21 @@
         }
       }
     }
+
+    if (locals.isNotEmpty) {
+      inits.insert(0, locals.toStatement());
+    }
+
     return wrapPhase('installTearOffs', inits);
   }
 
   /// Emits the constants section.
   js.Statement emitConstants(Fragment fragment) {
     List<js.Statement> assignments = [];
+    bool hasList = false;
     for (Constant constant in fragment.constants) {
-      // TODO(floitsch): instead of just updating the constant holder, we should
-      // find the constants that don't have any dependency on other constants
-      // and create an object-literal with them (and assign it to the
-      // constant-holder variable).
+      // TODO(25230): We only need to name constants that are used from function
+      // bodies or from other constants in a different part.
       var assignment = js.js.statement('#.# = #', [
         constant.holder.name,
         constant.name,
@@ -1343,6 +1519,11 @@
       ]);
       compiler.dumpInfoTask.registerConstantAst(constant.value, assignment);
       assignments.add(assignment);
+      if (constant.value.isList) hasList = true;
+    }
+    if (hasList) {
+      assignments.insert(
+          0, js.js.statement('var makeConstList = hunkHelpers.makeConstList;'));
     }
     return wrapPhase('constants', assignments);
   }
@@ -1353,11 +1534,12 @@
   /// an initializer.
   js.Statement emitStaticNonFinalFields(Fragment fragment) {
     List<StaticField> fields = fragment.staticNonFinalFields;
-    // TODO(floitsch): instead of assigning the fields one-by-one we should
-    // create a literal and assign it to the static-state holder.
-    // TODO(floitsch): if we don't make a literal we should at least initialize
-    // statics that have the same initial value in the same expression:
-    //    `$.x = $.y = $.z = null;`.
+    // TODO(sra): Chain assignments that have the same value, i.e.
+    //
+    //    $.x = null; $.y = null; $.z = null;
+    // -->
+    //    $.z = $.y = $.x = null;
+    //
     Iterable<js.Statement> statements = fields.map((StaticField field) {
       assert(field.holder.isStaticStateHolder);
       return js.js
@@ -1372,17 +1554,24 @@
   /// require an initializer.
   js.Statement emitLazilyInitializedStatics(Fragment fragment) {
     List<StaticField> fields = fragment.staticLazilyInitializedFields;
-    Iterable<js.Statement> statements = fields.map((StaticField field) {
+    List<js.Statement> statements = [];
+    LocalAliases locals = LocalAliases();
+    for (StaticField field in fields) {
       assert(field.holder.isStaticStateHolder);
-      return js.js.statement("lazy(#, #, #, #);", [
+      statements.add(js.js.statement("#(#, #, #, #);", [
+        locals.find('_lazy', 'hunkHelpers.lazy'),
         field.holder.name,
         js.quoteName(field.name),
-        js.quoteName(namer.deriveLazyInitializerName(field.name)),
+        js.quoteName(field.getterName),
         field.code
-      ]);
-    });
+      ]));
+    }
 
-    return wrapPhase('lazyInitializers', statements.toList());
+    if (locals.isNotEmpty) {
+      statements.insert(0, locals.toStatement());
+    }
+
+    return wrapPhase('lazyInitializers', statements);
   }
 
   /// Emits the embedded globals that are needed for deferred loading.
@@ -1599,10 +1788,11 @@
           _closedWorld.backendUsage, generateEmbeddedGlobalAccess, js.js("""
         // On V8, the 'intern' function converts a string to a symbol, which
         // makes property access much faster.
+        // TODO(sra): Use Symbol on non-IE11 browsers.
         function (s) {
           var o = {};
           o[s] = 1;
-          return Object.keys(convertToFastObject(o))[0];
+          return Object.keys(hunkHelpers.convertToFastObject(o))[0];
         }""", [])));
     }
 
@@ -1640,12 +1830,13 @@
     }
 
     if (interceptorsByTag.isNotEmpty) {
-      statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);",
+      statements.add(js.js.statement(
+          "hunkHelpers.setOrUpdateInterceptorsByTag(#);",
           js.objectLiteral(interceptorsByTag)));
     }
     if (leafTags.isNotEmpty) {
-      statements.add(js.js
-          .statement("setOrUpdateLeafTags(#);", js.objectLiteral(leafTags)));
+      statements.add(js.js.statement(
+          "hunkHelpers.setOrUpdateLeafTags(#);", js.objectLiteral(leafTags)));
     }
     statements.addAll(subclassAssignments);
 
@@ -1653,6 +1844,27 @@
   }
 }
 
+class LocalAliases {
+  final Map<String, js.Expression> _locals = {};
+
+  bool get isEmpty => _locals.isEmpty;
+  bool get isNotEmpty => !isEmpty;
+
+  String find(String alias, String expression) {
+    _locals[alias] ??= js.js(expression);
+    return alias;
+  }
+
+  js.Statement toStatement() {
+    List<js.VariableInitialization> initializations = [];
+    _locals.forEach((local, value) {
+      initializations
+          .add(js.VariableInitialization(js.VariableDeclaration(local), value));
+    });
+    return js.ExpressionStatement(js.VariableDeclarationList(initializations));
+  }
+}
+
 /// Code to initialize holder with ancillary information.
 class HolderCode {
   final List<Holder> activeHolders;
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index 1ba4a80..a5e2a7c 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -18,6 +18,7 @@
         INTERCEPTORS_BY_TAG,
         IS_HUNK_INITIALIZED,
         IS_HUNK_LOADED,
+        JsGetName,
         LEAF_TAGS,
         MANGLED_GLOBAL_NAMES,
         MANGLED_NAMES,
@@ -41,6 +42,7 @@
 import '../../js/js.dart' as js;
 import '../../js_backend/js_backend.dart'
     show JavaScriptBackend, Namer, ConstantEmitter, StringBackedName;
+import '../../js_backend/js_interop_analysis.dart' as jsInteropAnalysis;
 import '../../world.dart';
 import '../code_emitter_task.dart';
 import '../constant_ordering.dart' show ConstantOrdering;
@@ -405,7 +407,8 @@
     // data.
     mapping["_comment"] = "This mapping shows which compiled `.js` files are "
         "needed for a given deferred library import.";
-    mapping.addAll(compiler.deferredLoadTask.computeDeferredMap(
+    mapping.addAll(_closedWorld.outputUnitData.computeDeferredMap(
+        compiler.options, _closedWorld.elementEnvironment,
         omittedUnits:
             omittedFragments.map((fragemnt) => fragemnt.outputUnit).toSet()));
     compiler.outputProvider.createOutputSink(
diff --git a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
index f353ebb..fd5ffa3 100644
--- a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
+++ b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
@@ -13,7 +13,7 @@
         RuntimeTypesChecksBuilder,
         RuntimeTypesSubstitutions;
 import '../options.dart';
-import '../universe/world_builder.dart';
+import '../universe/codegen_world_builder.dart';
 
 class TypeTestRegistry {
   final ElementEnvironment _elementEnvironment;
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index a500d9d..f6d4e82 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -23,8 +23,8 @@
 import '../universe/selector.dart';
 import 'elements.dart';
 import 'closure_visitors.dart';
+import 'js_world_builder.dart' show JsClosedWorldBuilder;
 import 'locals.dart';
-import 'js_strategy.dart' show JsClosedWorldBuilder;
 
 class KernelClosureAnalysis {
   /// Inspect members and mark if those members capture any state that needs to
@@ -744,7 +744,7 @@
     return sb.toString();
   }
 
-  bool isBoxed(Local variable) => boxedVariables.containsKey(variable);
+  bool isBoxedVariable(Local variable) => boxedVariables.containsKey(variable);
 
   factory JsScopeInfo.readFromDataSource(DataSource source) {
     source.begin(tag);
@@ -1045,19 +1045,11 @@
 
   FieldEntity get thisFieldEntity => localToFieldMap[thisLocal];
 
-  @override
-  void forEachBoxedVariable(f(Local local, JField field)) {
-    boxedVariables.forEach(f);
-  }
-
   void forEachFreeVariable(f(Local variable, JField field)) {
     localToFieldMap.forEach(f);
     boxedVariables.forEach(f);
   }
 
-  bool isVariableBoxed(Local variable) =>
-      boxedVariables.keys.contains(variable);
-
   bool get isClosure => true;
 }
 
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index 22a306b..a25f8b1 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -187,7 +187,7 @@
       ir.PropertySet write, AbstractValueDomain abstractValueDomain);
 
   /// Returns the inferred type of [listLiteral].
-  AbstractValue typeOfListLiteral(MemberEntity owner,
+  AbstractValue typeOfListLiteral(
       ir.ListLiteral listLiteral, AbstractValueDomain abstractValueDomain);
 
   /// Returns the inferred type of iterator in [forInStatement].
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 dccda12..0ad7710 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -47,7 +47,6 @@
 import '../ssa/type_builder.dart';
 import '../universe/call_structure.dart';
 import '../universe/selector.dart';
-import '../universe/world_builder.dart';
 
 import 'closure.dart';
 import 'elements.dart';
@@ -69,7 +68,25 @@
       void f(DartType type, String name, ConstantValue defaultValue));
 }
 
-abstract class JsToElementMapBase implements IrToElementMap, JsToElementMap {
+class JsKernelToElementMap
+    implements JsToWorldBuilder, JsToElementMap, IrToElementMap {
+  /// Tag used for identifying serialized [JsKernelToElementMap] objects in a
+  /// debugging data stream.
+  static const String tag = 'js-kernel-to-element-map';
+
+  /// Tags used for identifying serialized subsections of a
+  /// [JsKernelToElementMap] object in a debugging data stream.
+  static const String libraryTag = 'libraries';
+  static const String classTag = 'classes';
+  static const String typedefTag = 'typedefs';
+  static const String memberTag = 'members';
+  static const String typeVariableTag = 'type-variables';
+  static const String libraryDataTag = 'library-data';
+  static const String classDataTag = 'class-data';
+  static const String typedefDataTag = 'typedef-data';
+  static const String memberDataTag = 'member-data';
+  static const String typeVariableDataTag = 'type-variable-data';
+
   final CompilerOptions options;
   final DiagnosticReporter reporter;
   CommonElementsImpl _commonElements;
@@ -93,15 +110,354 @@
   final EntityDataMap<IndexedTypedef, JTypedefData> typedefs =
       new EntityDataMap<IndexedTypedef, JTypedefData>();
 
-  JsToElementMapBase(this.options, this.reporter, Environment environment) {
+  final Map<ir.Library, IndexedLibrary> libraryMap = {};
+  final Map<ir.Class, IndexedClass> classMap = {};
+  final Map<ir.Typedef, IndexedTypedef> typedefMap = {};
+
+  /// Map from [ir.TypeParameter] nodes to the corresponding
+  /// [TypeVariableEntity].
+  ///
+  /// Normally the type variables are [IndexedTypeVariable]s, but for type
+  /// parameters on local function (in the frontend) these are _not_ since
+  /// their type declaration is neither a class nor a member. In the backend,
+  /// these type parameters belong to the call-method and are therefore indexed.
+  final Map<ir.TypeParameter, TypeVariableEntity> typeVariableMap = {};
+  final Map<ir.Member, IndexedConstructor> constructorMap = {};
+  final Map<ir.Procedure, IndexedFunction> methodMap = {};
+  final Map<ir.Field, IndexedField> fieldMap = {};
+  final Map<ir.TreeNode, Local> localFunctionMap = {};
+
+  /// Map from members to the call methods created for their nested closures.
+  Map<IndexedMember, List<IndexedFunction>> _nestedClosureMap = {};
+
+  /// NativeBasicData is need for computation of the default super class.
+  NativeBasicData nativeBasicData;
+
+  Map<IndexedFunction, JGeneratorBody> _generatorBodies = {};
+
+  Map<IndexedClass, List<IndexedMember>> _injectedClassMembers = {};
+
+  JsKernelToElementMap(this.reporter, Environment environment,
+      KernelToElementMapImpl _elementMap, Iterable<MemberEntity> liveMembers)
+      : this.options = _elementMap.options {
     _elementEnvironment = new JsElementEnvironment(this);
     _commonElements = new CommonElementsImpl(_elementEnvironment);
     _constantEnvironment = new JsConstantEnvironment(this, environment);
     _typeConverter = new DartTypeConverter(this);
     _types = new KernelDartTypes(this);
+
+    programEnv = _elementMap.env.convert();
+    for (int libraryIndex = 0;
+        libraryIndex < _elementMap.libraries.length;
+        libraryIndex++) {
+      IndexedLibrary oldLibrary = _elementMap.libraries.getEntity(libraryIndex);
+      KLibraryEnv oldEnv = _elementMap.libraries.getEnv(oldLibrary);
+      KLibraryData data = _elementMap.libraries.getData(oldLibrary);
+      IndexedLibrary newLibrary = convertLibrary(oldLibrary);
+      JLibraryEnv newEnv = oldEnv.convert(_elementMap, liveMembers);
+      libraryMap[oldEnv.library] =
+          libraries.register<IndexedLibrary, JLibraryData, JLibraryEnv>(
+              newLibrary, data.convert(), newEnv);
+      assert(newLibrary.libraryIndex == oldLibrary.libraryIndex);
+      programEnv.registerLibrary(newEnv);
+    }
+    // TODO(johnniwinther): Filter unused classes.
+    for (int classIndex = 0;
+        classIndex < _elementMap.classes.length;
+        classIndex++) {
+      IndexedClass oldClass = _elementMap.classes.getEntity(classIndex);
+      KClassEnv env = _elementMap.classes.getEnv(oldClass);
+      KClassData data = _elementMap.classes.getData(oldClass);
+      IndexedLibrary oldLibrary = oldClass.library;
+      LibraryEntity newLibrary = libraries.getEntity(oldLibrary.libraryIndex);
+      IndexedClass newClass = convertClass(newLibrary, oldClass);
+      JClassEnv newEnv = env.convert(_elementMap, liveMembers);
+      classMap[env.cls] = classes.register(newClass, data.convert(), newEnv);
+      assert(newClass.classIndex == oldClass.classIndex);
+      libraries.getEnv(newClass.library).registerClass(newClass.name, newEnv);
+    }
+    for (int typedefIndex = 0;
+        typedefIndex < _elementMap.typedefs.length;
+        typedefIndex++) {
+      IndexedTypedef oldTypedef = _elementMap.typedefs.getEntity(typedefIndex);
+      KTypedefData data = _elementMap.typedefs.getData(oldTypedef);
+      IndexedLibrary oldLibrary = oldTypedef.library;
+      LibraryEntity newLibrary = libraries.getEntity(oldLibrary.libraryIndex);
+      IndexedTypedef newTypedef = convertTypedef(newLibrary, oldTypedef);
+      typedefMap[data.node] = typedefs.register(
+          newTypedef,
+          new JTypedefData(
+              data.node,
+              new TypedefType(
+                  newTypedef,
+                  new List<DartType>.filled(
+                      data.node.typeParameters.length, const DynamicType()),
+                  getDartType(data.node.type))));
+      assert(newTypedef.typedefIndex == oldTypedef.typedefIndex);
+    }
+    for (int memberIndex = 0;
+        memberIndex < _elementMap.members.length;
+        memberIndex++) {
+      IndexedMember oldMember = _elementMap.members.getEntity(memberIndex);
+      if (!liveMembers.contains(oldMember)) {
+        members.skipIndex(oldMember.memberIndex);
+        continue;
+      }
+      KMemberData data = _elementMap.members.getData(oldMember);
+      IndexedLibrary oldLibrary = oldMember.library;
+      IndexedClass oldClass = oldMember.enclosingClass;
+      LibraryEntity newLibrary = libraries.getEntity(oldLibrary.libraryIndex);
+      ClassEntity newClass =
+          oldClass != null ? classes.getEntity(oldClass.classIndex) : null;
+      IndexedMember newMember = convertMember(newLibrary, newClass, oldMember);
+      members.register(newMember, data.convert());
+      assert(newMember.memberIndex == oldMember.memberIndex);
+      if (newMember.isField) {
+        fieldMap[data.node] = newMember;
+      } else if (newMember.isConstructor) {
+        constructorMap[data.node] = newMember;
+      } else {
+        methodMap[data.node] = newMember;
+      }
+    }
+    for (int typeVariableIndex = 0;
+        typeVariableIndex < _elementMap.typeVariables.length;
+        typeVariableIndex++) {
+      IndexedTypeVariable oldTypeVariable =
+          _elementMap.typeVariables.getEntity(typeVariableIndex);
+      KTypeVariableData oldTypeVariableData =
+          _elementMap.typeVariables.getData(oldTypeVariable);
+      Entity newTypeDeclaration;
+      if (oldTypeVariable.typeDeclaration is ClassEntity) {
+        IndexedClass cls = oldTypeVariable.typeDeclaration;
+        newTypeDeclaration = classes.getEntity(cls.classIndex);
+        // TODO(johnniwinther): Skip type variables of unused classes.
+      } else if (oldTypeVariable.typeDeclaration is MemberEntity) {
+        IndexedMember member = oldTypeVariable.typeDeclaration;
+        newTypeDeclaration = members.getEntity(member.memberIndex);
+        if (newTypeDeclaration == null) {
+          typeVariables.skipIndex(typeVariableIndex);
+          continue;
+        }
+      } else {
+        assert(oldTypeVariable.typeDeclaration is Local);
+      }
+      IndexedTypeVariable newTypeVariable = createTypeVariable(
+          newTypeDeclaration, oldTypeVariable.name, oldTypeVariable.index);
+      typeVariableMap[oldTypeVariableData.node] =
+          typeVariables.register<IndexedTypeVariable, JTypeVariableData>(
+              newTypeVariable, oldTypeVariableData.copy());
+      assert(newTypeVariable.typeVariableIndex ==
+          oldTypeVariable.typeVariableIndex);
+    }
+    // TODO(johnniwinther): We should close the environment in the beginning of
+    // this constructor but currently we need the [MemberEntity] to query if the
+    // member is live, thus potentially creating the [MemberEntity] in the
+    // process. Avoid this.
+    _elementMap.envIsClosed = true;
   }
 
-  bool checkFamily(Entity entity);
+  JsKernelToElementMap.readFromDataSource(this.options, this.reporter,
+      Environment environment, ir.Component component, DataSource source) {
+    _elementEnvironment = new JsElementEnvironment(this);
+    _commonElements = new CommonElementsImpl(_elementEnvironment);
+    _constantEnvironment = new JsConstantEnvironment(this, environment);
+    _typeConverter = new DartTypeConverter(this);
+    _types = new KernelDartTypes(this);
+
+    source.registerComponentLookup(new ComponentLookup(component));
+    _EntityLookup entityLookup = new _EntityLookup();
+    source.registerEntityLookup(entityLookup);
+
+    source.begin(tag);
+    source.begin(libraryTag);
+    int libraryCount = source.readInt();
+    for (int i = 0; i < libraryCount; i++) {
+      int index = source.readInt();
+      JLibrary library = new JLibrary.readFromDataSource(source);
+      entityLookup.registerLibrary(index, library);
+    }
+    source.end(libraryTag);
+
+    source.begin(classTag);
+    int classCount = source.readInt();
+    for (int i = 0; i < classCount; i++) {
+      int index = source.readInt();
+      JClass cls = new JClass.readFromDataSource(source);
+      entityLookup.registerClass(index, cls);
+    }
+    source.end(classTag);
+
+    source.begin(typedefTag);
+    int typedefCount = source.readInt();
+    for (int i = 0; i < typedefCount; i++) {
+      int index = source.readInt();
+      JTypedef typedef = new JTypedef.readFromDataSource(source);
+      entityLookup.registerTypedef(index, typedef);
+    }
+    source.end(typedefTag);
+
+    source.begin(memberTag);
+    int memberCount = source.readInt();
+    for (int i = 0; i < memberCount; i++) {
+      int index = source.readInt();
+      JMember member = new JMember.readFromDataSource(source);
+      entityLookup.registerMember(index, member);
+    }
+    source.end(memberTag);
+
+    source.begin(typeVariableTag);
+    int typeVariableCount = source.readInt();
+    for (int i = 0; i < typeVariableCount; i++) {
+      int index = source.readInt();
+      JTypeVariable typeVariable = new JTypeVariable.readFromDataSource(source);
+      entityLookup.registerTypeVariable(index, typeVariable);
+    }
+    source.end(typeVariableTag);
+
+    programEnv = new JProgramEnv([component]);
+    source.begin(libraryDataTag);
+    entityLookup.forEachLibrary((int index, JLibrary library) {
+      JLibraryEnv env = new JLibraryEnv.readFromDataSource(source);
+      JLibraryData data = new JLibraryData.readFromDataSource(source);
+      libraryMap[env.library] =
+          libraries.registerByIndex(index, library, data, env);
+      programEnv.registerLibrary(env);
+      assert(index == library.libraryIndex);
+    });
+    source.end(libraryDataTag);
+
+    source.begin(classDataTag);
+    entityLookup.forEachClass((int index, JClass cls) {
+      JClassEnv env = new JClassEnv.readFromDataSource(source);
+      JClassData data = new JClassData.readFromDataSource(source);
+      classMap[env.cls] = classes.registerByIndex(index, cls, data, env);
+      libraries.getEnv(cls.library).registerClass(cls.name, env);
+      assert(index == cls.classIndex);
+    });
+    source.end(classDataTag);
+
+    source.begin(typedefDataTag);
+    entityLookup.forEachTypedef((int index, JTypedef typedef) {
+      JTypedefData data = new JTypedefData.readFromDataSource(source);
+      typedefMap[data.node] = typedefs.registerByIndex(index, typedef, data);
+      assert(index == typedef.typedefIndex);
+    });
+    source.end(typedefDataTag);
+
+    source.begin(memberDataTag);
+    entityLookup.forEachMember((int index, IndexedMember member) {
+      JMemberData data = new JMemberData.readFromDataSource(source);
+      members.registerByIndex(index, member, data);
+      switch (data.definition.kind) {
+        case MemberKind.regular:
+        case MemberKind.constructor:
+          ir.Member node = data.definition.node;
+          if (member.isField) {
+            fieldMap[node] = member;
+          } else if (member.isConstructor) {
+            constructorMap[node] = member;
+          } else {
+            methodMap[node] = member;
+          }
+          break;
+        default:
+      }
+      assert(index == member.memberIndex);
+    });
+    source.end(memberDataTag);
+
+    source.begin(typeVariableDataTag);
+    entityLookup.forEachTypeVariable((int index, JTypeVariable typeVariable) {
+      JTypeVariableData data = new JTypeVariableData.readFromDataSource(source);
+      typeVariableMap[data.node] =
+          typeVariables.registerByIndex(index, typeVariable, data);
+      assert(index == typeVariable.typeVariableIndex);
+    });
+    source.end(typeVariableDataTag);
+    source.end(tag);
+  }
+
+  /// Serializes this [JsToElementMap] to [sink].
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+
+    // Serialize the entities before serializing the data.
+    sink.begin(libraryTag);
+    sink.writeInt(libraries.size);
+    libraries.forEach((JLibrary library, _, __) {
+      sink.writeInt(library.libraryIndex);
+      library.writeToDataSink(sink);
+    });
+    sink.end(libraryTag);
+
+    sink.begin(classTag);
+    sink.writeInt(classes.size);
+    classes.forEach((JClass cls, _, __) {
+      sink.writeInt(cls.classIndex);
+      cls.writeToDataSink(sink);
+    });
+    sink.end(classTag);
+
+    sink.begin(typedefTag);
+    sink.writeInt(typedefs.size);
+    typedefs.forEach((JTypedef typedef, _) {
+      sink.writeInt(typedef.typedefIndex);
+      typedef.writeToDataSink(sink);
+    });
+    sink.end(typedefTag);
+
+    sink.begin(memberTag);
+    sink.writeInt(members.size);
+    members.forEach((JMember member, _) {
+      sink.writeInt(member.memberIndex);
+      member.writeToDataSink(sink);
+    });
+    sink.end(memberTag);
+
+    sink.begin(typeVariableTag);
+    sink.writeInt(typeVariables.size);
+    typeVariables.forEach((JTypeVariable typeVariable, _) {
+      sink.writeInt(typeVariable.typeVariableIndex);
+      typeVariable.writeToDataSink(sink);
+    });
+    sink.end(typeVariableTag);
+
+    // Serialize the entity data after having serialized the entities.
+    sink.begin(libraryDataTag);
+    libraries.forEach((_, JLibraryData data, JLibraryEnv env) {
+      env.writeToDataSink(sink);
+      data.writeToDataSink(sink);
+    });
+    sink.end(libraryDataTag);
+
+    sink.begin(classDataTag);
+    classes.forEach((_, JClassData data, JClassEnv env) {
+      env.writeToDataSink(sink);
+      data.writeToDataSink(sink);
+    });
+    sink.end(classDataTag);
+
+    sink.begin(typedefDataTag);
+    typedefs.forEach((_, JTypedefData data) {
+      data.writeToDataSink(sink);
+    });
+    sink.end(typedefDataTag);
+
+    sink.begin(memberDataTag);
+    members.forEach((_, JMemberData data) {
+      data.writeToDataSink(sink);
+    });
+    sink.end(memberDataTag);
+
+    sink.begin(typeVariableDataTag);
+    typeVariables.forEach((_, JTypeVariableData data) {
+      data.writeToDataSink(sink);
+    });
+    sink.end(typeVariableDataTag);
+
+    sink.end(tag);
+  }
 
   DartTypes get types => _types;
 
@@ -110,9 +466,6 @@
   @override
   CommonElementsImpl get commonElements => _commonElements;
 
-  /// NativeBasicData is need for computation of the default super class.
-  NativeBasicData get nativeBasicData;
-
   FunctionEntity get _mainFunction {
     return programEnv.mainMethod != null
         ? getMethodInternal(programEnv.mainMethod)
@@ -125,8 +478,6 @@
         : null;
   }
 
-  Iterable<LibraryEntity> get libraryListInternal;
-
   SourceSpan getSourceSpan(Spannable spannable, Entity currentElement) {
     SourceSpan fromSpannable(Spannable spannable) {
       if (spannable is IndexedLibrary &&
@@ -224,13 +575,9 @@
 
   LibraryEntity getLibrary(ir.Library node) => getLibraryInternal(node);
 
-  LibraryEntity getLibraryInternal(ir.Library node, [JLibraryEnv libraryEnv]);
-
   @override
   ClassEntity getClass(ir.Class node) => getClassInternal(node);
 
-  ClassEntity getClassInternal(ir.Class node, [JClassEnv classEnv]);
-
   InterfaceType getSuperType(IndexedClass cls) {
     assert(checkFamily(cls));
     JClassData data = classes.getData(cls);
@@ -264,8 +611,6 @@
   TypeVariableEntity getTypeVariable(ir.TypeParameter node) =>
       getTypeVariableInternal(node);
 
-  TypeVariableEntity getTypeVariableInternal(ir.TypeParameter node);
-
   void _ensureSupertypes(ClassEntity cls, JClassData data) {
     assert(checkFamily(cls));
     if (data is JClassDataImpl && data.orderedTypeSet == null) {
@@ -347,8 +692,6 @@
     return typedefs.getData(typedef).rawType;
   }
 
-  TypedefEntity getTypedefInternal(ir.Typedef node);
-
   @override
   MemberEntity getMember(ir.Member node) {
     if (node is ir.Field) {
@@ -394,8 +737,6 @@
   ConstructorEntity getConstructor(ir.Member node) =>
       getConstructorInternal(node);
 
-  ConstructorEntity getConstructorInternal(ir.Member node);
-
   ConstructorEntity getSuperConstructor(
       ir.Constructor sourceNode, ir.Member targetNode) {
     ConstructorEntity source = getConstructor(sourceNode);
@@ -417,13 +758,9 @@
   @override
   FunctionEntity getMethod(ir.Procedure node) => getMethodInternal(node);
 
-  FunctionEntity getMethodInternal(ir.Procedure node);
-
   @override
   FieldEntity getField(ir.Field node) => getFieldInternal(node);
 
-  FieldEntity getFieldInternal(ir.Field node);
-
   @override
   DartType getDartType(ir.DartType type) => _typeConverter.convert(type);
 
@@ -618,15 +955,6 @@
     env.forEachConstructor(this, f);
   }
 
-  void forEachConstructorBody(
-      IndexedClass cls, void f(ConstructorBodyEntity member)) {
-    throw new UnsupportedError(
-        'KernelToElementMapBase._forEachConstructorBody');
-  }
-
-  void forEachNestedClosure(
-      MemberEntity member, void f(FunctionEntity closure));
-
   void _forEachLocalClassMember(IndexedClass cls, void f(MemberEntity member)) {
     assert(checkFamily(cls));
     JClassEnv env = classes.getEnv(cls);
@@ -635,13 +963,6 @@
     });
   }
 
-  void forEachInjectedClassMember(
-      IndexedClass cls, void f(MemberEntity member)) {
-    assert(checkFamily(cls));
-    throw new UnsupportedError(
-        'KernelToElementMapBase._forEachInjectedClassMember');
-  }
-
   void _forEachClassMember(
       IndexedClass cls, void f(ClassEntity cls, MemberEntity member)) {
     assert(checkFamily(cls));
@@ -1076,731 +1397,144 @@
         failedAt(cls, "No super noSuchMethod found for class $cls."));
     return function;
   }
-}
 
-class JsElementEnvironment extends ElementEnvironment
-    implements JElementEnvironment {
-  final JsToElementMapBase elementMap;
-
-  JsElementEnvironment(this.elementMap);
-
-  @override
-  DartType get dynamicType => const DynamicType();
-
-  @override
-  LibraryEntity get mainLibrary => elementMap._mainLibrary;
-
-  @override
-  FunctionEntity get mainFunction => elementMap._mainFunction;
-
-  @override
-  Iterable<LibraryEntity> get libraries => elementMap.libraryListInternal;
-
-  @override
-  String getLibraryName(LibraryEntity library) {
-    return elementMap._getLibraryName(library);
+  IndexedLibrary createLibrary(String name, Uri canonicalUri) {
+    return new JLibrary(name, canonicalUri);
   }
 
-  @override
-  InterfaceType getThisType(ClassEntity cls) {
-    return elementMap.getThisType(cls);
+  IndexedClass createClass(LibraryEntity library, String name,
+      {bool isAbstract}) {
+    return new JClass(library, name, isAbstract: isAbstract);
   }
 
-  @override
-  InterfaceType getRawType(ClassEntity cls) {
-    return elementMap._getRawType(cls);
+  IndexedTypedef createTypedef(LibraryEntity library, String name) {
+    return new JTypedef(library, name);
   }
 
-  @override
-  bool isGenericClass(ClassEntity cls) {
-    return getThisType(cls).typeArguments.isNotEmpty;
+  TypeVariableEntity createTypeVariable(
+      Entity typeDeclaration, String name, int index) {
+    return new JTypeVariable(typeDeclaration, name, index);
   }
 
-  @override
-  bool isMixinApplication(ClassEntity cls) {
-    return elementMap._isMixinApplication(cls);
+  IndexedConstructor createGenerativeConstructor(ClassEntity enclosingClass,
+      Name name, ParameterStructure parameterStructure,
+      {bool isExternal, bool isConst}) {
+    return new JGenerativeConstructor(enclosingClass, name, parameterStructure,
+        isExternal: isExternal, isConst: isConst);
   }
 
-  @override
-  bool isUnnamedMixinApplication(ClassEntity cls) {
-    return elementMap._isUnnamedMixinApplication(cls);
+  IndexedConstructor createFactoryConstructor(ClassEntity enclosingClass,
+      Name name, ParameterStructure parameterStructure,
+      {bool isExternal, bool isConst, bool isFromEnvironmentConstructor}) {
+    return new JFactoryConstructor(enclosingClass, name, parameterStructure,
+        isExternal: isExternal,
+        isConst: isConst,
+        isFromEnvironmentConstructor: isFromEnvironmentConstructor);
   }
 
-  @override
-  bool isSuperMixinApplication(ClassEntity cls) {
-    return elementMap._isSuperMixinApplication(cls);
+  JConstructorBody createConstructorBody(ConstructorEntity constructor) {
+    return new JConstructorBody(constructor);
   }
 
-  @override
-  ClassEntity getEffectiveMixinClass(ClassEntity cls) {
-    if (!isMixinApplication(cls)) return null;
-    do {
-      cls = elementMap.getAppliedMixin(cls);
-    } while (isMixinApplication(cls));
-    return cls;
+  JGeneratorBody createGeneratorBody(
+      FunctionEntity function, DartType elementType) {
+    return new JGeneratorBody(function, elementType);
   }
 
-  @override
-  DartType getTypeVariableBound(TypeVariableEntity typeVariable) {
-    return elementMap.getTypeVariableBound(typeVariable);
+  IndexedFunction createGetter(LibraryEntity library,
+      ClassEntity enclosingClass, Name name, AsyncMarker asyncMarker,
+      {bool isStatic, bool isExternal, bool isAbstract}) {
+    return new JGetter(library, enclosingClass, name, asyncMarker,
+        isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
   }
 
-  @override
-  DartType getTypeVariableDefaultType(TypeVariableEntity typeVariable) {
-    return elementMap._getTypeVariableDefaultType(typeVariable);
+  IndexedFunction createMethod(
+      LibraryEntity library,
+      ClassEntity enclosingClass,
+      Name name,
+      ParameterStructure parameterStructure,
+      AsyncMarker asyncMarker,
+      {bool isStatic,
+      bool isExternal,
+      bool isAbstract}) {
+    return new JMethod(
+        library, enclosingClass, name, parameterStructure, asyncMarker,
+        isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
   }
 
-  @override
-  InterfaceType createInterfaceType(
-      ClassEntity cls, List<DartType> typeArguments) {
-    return new InterfaceType(cls, typeArguments);
+  IndexedFunction createSetter(
+      LibraryEntity library, ClassEntity enclosingClass, Name name,
+      {bool isStatic, bool isExternal, bool isAbstract}) {
+    return new JSetter(library, enclosingClass, name,
+        isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
   }
 
-  @override
-  FunctionType getFunctionType(FunctionEntity function) {
-    return elementMap._getFunctionType(function);
+  IndexedField createField(
+      LibraryEntity library, ClassEntity enclosingClass, Name name,
+      {bool isStatic, bool isAssignable, bool isConst}) {
+    return new JField(library, enclosingClass, name,
+        isStatic: isStatic, isAssignable: isAssignable, isConst: isConst);
   }
 
-  @override
-  List<TypeVariableType> getFunctionTypeVariables(FunctionEntity function) {
-    return elementMap._getFunctionTypeVariables(function);
+  LibraryEntity convertLibrary(IndexedLibrary library) {
+    return createLibrary(library.name, library.canonicalUri);
   }
 
-  @override
-  DartType getFunctionAsyncOrSyncStarElementType(FunctionEntity function) {
-    // TODO(sra): Should be getting the DartType from the node.
-    DartType returnType = getFunctionType(function).returnType;
-    return getAsyncOrSyncStarElementType(function.asyncMarker, returnType);
+  ClassEntity convertClass(LibraryEntity library, IndexedClass cls) {
+    return createClass(library, cls.name, isAbstract: cls.isAbstract);
   }
 
-  @override
-  DartType getAsyncOrSyncStarElementType(
-      AsyncMarker asyncMarker, DartType returnType) {
-    switch (asyncMarker) {
-      case AsyncMarker.SYNC:
-        return returnType;
-      case AsyncMarker.SYNC_STAR:
-        if (returnType is InterfaceType) {
-          if (returnType.element == elementMap.commonElements.iterableClass) {
-            return returnType.typeArguments.first;
-          }
-        }
-        return dynamicType;
-      case AsyncMarker.ASYNC:
-        if (returnType is FutureOrType) return returnType.typeArgument;
-        if (returnType is InterfaceType) {
-          if (returnType.element == elementMap.commonElements.futureClass) {
-            return returnType.typeArguments.first;
-          }
-        }
-        return dynamicType;
-      case AsyncMarker.ASYNC_STAR:
-        if (returnType is InterfaceType) {
-          if (returnType.element == elementMap.commonElements.streamClass) {
-            return returnType.typeArguments.first;
-          }
-        }
-        return dynamicType;
-    }
-    assert(false, 'Unexpected marker ${asyncMarker}');
-    return null;
+  TypedefEntity convertTypedef(LibraryEntity library, IndexedTypedef typedef) {
+    return createTypedef(library, typedef.name);
   }
 
-  @override
-  DartType getFieldType(FieldEntity field) {
-    return elementMap._getFieldType(field);
-  }
-
-  @override
-  FunctionType getLocalFunctionType(covariant KLocalFunction function) {
-    return function.functionType;
-  }
-
-  @override
-  DartType getUnaliasedType(DartType type) => type;
-
-  @override
-  ConstructorEntity lookupConstructor(ClassEntity cls, String name,
-      {bool required: false}) {
-    ConstructorEntity constructor = elementMap.lookupConstructor(cls, name);
-    if (constructor == null && required) {
-      throw failedAt(
-          CURRENT_ELEMENT_SPANNABLE,
-          "The constructor '$name' was not found in class '${cls.name}' "
-          "in library ${cls.library.canonicalUri}.");
-    }
-    return constructor;
-  }
-
-  @override
-  MemberEntity lookupLocalClassMember(ClassEntity cls, String name,
-      {bool setter: false, bool required: false}) {
-    MemberEntity member =
-        elementMap.lookupClassMember(cls, name, setter: setter);
-    if (member == null && required) {
-      throw failedAt(CURRENT_ELEMENT_SPANNABLE,
-          "The member '$name' was not found in ${cls.name}.");
-    }
-    return member;
-  }
-
-  @override
-  ClassEntity getSuperClass(ClassEntity cls,
-      {bool skipUnnamedMixinApplications: false}) {
-    assert(elementMap.checkFamily(cls));
-    ClassEntity superclass = elementMap.getSuperType(cls)?.element;
-    if (skipUnnamedMixinApplications) {
-      while (superclass != null &&
-          elementMap._isUnnamedMixinApplication(superclass)) {
-        superclass = elementMap.getSuperType(superclass)?.element;
-      }
-    }
-    return superclass;
-  }
-
-  @override
-  void forEachSupertype(ClassEntity cls, void f(InterfaceType supertype)) {
-    elementMap._forEachSupertype(cls, f);
-  }
-
-  @override
-  void forEachLocalClassMember(ClassEntity cls, void f(MemberEntity member)) {
-    elementMap._forEachLocalClassMember(cls, f);
-  }
-
-  @override
-  void forEachInjectedClassMember(
-      ClassEntity cls, void f(MemberEntity member)) {
-    elementMap.forEachInjectedClassMember(cls, f);
-  }
-
-  @override
-  void forEachClassMember(
-      ClassEntity cls, void f(ClassEntity declarer, MemberEntity member)) {
-    elementMap._forEachClassMember(cls, f);
-  }
-
-  @override
-  void forEachConstructor(
-      ClassEntity cls, void f(ConstructorEntity constructor)) {
-    elementMap._forEachConstructor(cls, f);
-  }
-
-  @override
-  void forEachConstructorBody(
-      ClassEntity cls, void f(ConstructorBodyEntity constructor)) {
-    elementMap.forEachConstructorBody(cls, f);
-  }
-
-  @override
-  void forEachNestedClosure(
-      MemberEntity member, void f(FunctionEntity closure)) {
-    elementMap.forEachNestedClosure(member, f);
-  }
-
-  @override
-  void forEachLibraryMember(
-      LibraryEntity library, void f(MemberEntity member)) {
-    elementMap._forEachLibraryMember(library, f);
-  }
-
-  @override
-  MemberEntity lookupLibraryMember(LibraryEntity library, String name,
-      {bool setter: false, bool required: false}) {
-    MemberEntity member =
-        elementMap.lookupLibraryMember(library, name, setter: setter);
-    if (member == null && required) {
-      failedAt(CURRENT_ELEMENT_SPANNABLE,
-          "The member '${name}' was not found in library '${library.name}'.");
-    }
-    return member;
-  }
-
-  @override
-  ClassEntity lookupClass(LibraryEntity library, String name,
-      {bool required: false}) {
-    ClassEntity cls = elementMap.lookupClass(library, name);
-    if (cls == null && required) {
-      failedAt(CURRENT_ELEMENT_SPANNABLE,
-          "The class '$name'  was not found in library '${library.name}'.");
-    }
-    return cls;
-  }
-
-  @override
-  void forEachClass(LibraryEntity library, void f(ClassEntity cls)) {
-    elementMap._forEachClass(library, f);
-  }
-
-  @override
-  LibraryEntity lookupLibrary(Uri uri, {bool required: false}) {
-    LibraryEntity library = elementMap.lookupLibrary(uri);
-    if (library == null && required) {
-      failedAt(CURRENT_ELEMENT_SPANNABLE, "The library '$uri' was not found.");
-    }
-    return library;
-  }
-
-  @override
-  bool isEnumClass(ClassEntity cls) {
-    assert(elementMap.checkFamily(cls));
-    JClassData classData = elementMap.classes.getData(cls);
-    return classData.isEnumClass;
-  }
-}
-
-/// [native.BehaviorBuilder] for kernel based elements.
-class JsBehaviorBuilder extends native.BehaviorBuilder {
-  final ElementEnvironment elementEnvironment;
-  final CommonElements commonElements;
-  final DiagnosticReporter reporter;
-  final NativeBasicData nativeBasicData;
-  final CompilerOptions _options;
-
-  JsBehaviorBuilder(this.elementEnvironment, this.commonElements,
-      this.nativeBasicData, this.reporter, this._options);
-
-  @override
-  bool get trustJSInteropTypeAnnotations =>
-      _options.trustJSInteropTypeAnnotations;
-}
-
-/// Constant environment mapping [ConstantExpression]s to [ConstantValue]s using
-/// [_EvaluationEnvironment] for the evaluation.
-class JsConstantEnvironment implements ConstantEnvironment {
-  final JsToElementMapBase _elementMap;
-  final Environment _environment;
-
-  Map<ConstantExpression, ConstantValue> _valueMap =
-      <ConstantExpression, ConstantValue>{};
-
-  JsConstantEnvironment(this._elementMap, this._environment);
-
-  @override
-  ConstantSystem get constantSystem => JavaScriptConstantSystem.only;
-
-  ConstantValue _getConstantValue(
-      Spannable spannable, ConstantExpression expression,
-      {bool constantRequired}) {
-    return _valueMap.putIfAbsent(expression, () {
-      return expression.evaluate(
-          new JsEvaluationEnvironment(_elementMap, _environment, spannable,
-              constantRequired: constantRequired),
-          constantSystem);
-    });
-  }
-}
-
-/// Evaluation environment used for computing [ConstantValue]s for
-/// kernel based [ConstantExpression]s.
-class JsEvaluationEnvironment extends EvaluationEnvironmentBase {
-  final JsToElementMapBase _elementMap;
-  final Environment _environment;
-
-  JsEvaluationEnvironment(
-      this._elementMap, this._environment, Spannable spannable,
-      {bool constantRequired})
-      : super(spannable, constantRequired: constantRequired);
-
-  @override
-  CommonElements get commonElements => _elementMap.commonElements;
-
-  @override
-  DartTypes get types => _elementMap.types;
-
-  @override
-  DartType substByContext(DartType base, InterfaceType target) {
-    return _elementMap.substByContext(base, target);
-  }
-
-  @override
-  ConstantConstructor getConstructorConstant(ConstructorEntity constructor) {
-    return _elementMap._getConstructorConstant(constructor);
-  }
-
-  @override
-  ConstantExpression getFieldConstant(FieldEntity field) {
-    return _elementMap._getFieldConstantExpression(field);
-  }
-
-  @override
-  ConstantExpression getLocalConstant(Local local) {
-    throw new UnimplementedError("_EvaluationEnvironment.getLocalConstant");
-  }
-
-  @override
-  String readFromEnvironment(String name) {
-    return _environment.valueOf(name);
-  }
-
-  @override
-  DiagnosticReporter get reporter => _elementMap.reporter;
-
-  @override
-  bool get enableAssertions => _elementMap.options.enableUserAssertions;
-}
-
-class JsKernelToElementMap extends JsToElementMapBase
-    with JsElementCreatorMixin
-    implements JsToWorldBuilder, JsToElementMap {
-  /// Tag used for identifying serialized [JsKernelToElementMap] objects in a
-  /// debugging data stream.
-  static const String tag = 'js-kernel-to-element-map';
-
-  /// Tags used for identifying serialized subsections of a
-  /// [JsKernelToElementMap] object in a debugging data stream.
-  static const String libraryTag = 'libraries';
-  static const String classTag = 'classes';
-  static const String typedefTag = 'typedefs';
-  static const String memberTag = 'members';
-  static const String typeVariableTag = 'type-variables';
-  static const String libraryDataTag = 'library-data';
-  static const String classDataTag = 'class-data';
-  static const String typedefDataTag = 'typedef-data';
-  static const String memberDataTag = 'member-data';
-  static const String typeVariableDataTag = 'type-variable-data';
-
-  final Map<ir.Library, IndexedLibrary> libraryMap = {};
-  final Map<ir.Class, IndexedClass> classMap = {};
-  final Map<ir.Typedef, IndexedTypedef> typedefMap = {};
-
-  /// Map from [ir.TypeParameter] nodes to the corresponding
-  /// [TypeVariableEntity].
-  ///
-  /// Normally the type variables are [IndexedTypeVariable]s, but for type
-  /// parameters on local function (in the frontend) these are _not_ since
-  /// their type declaration is neither a class nor a member. In the backend,
-  /// these type parameters belong to the call-method and are therefore indexed.
-  final Map<ir.TypeParameter, TypeVariableEntity> typeVariableMap = {};
-  final Map<ir.Member, IndexedConstructor> constructorMap = {};
-  final Map<ir.Procedure, IndexedFunction> methodMap = {};
-  final Map<ir.Field, IndexedField> fieldMap = {};
-  final Map<ir.TreeNode, Local> localFunctionMap = {};
-
-  /// Map from members to the call methods created for their nested closures.
-  Map<IndexedMember, List<IndexedFunction>> _nestedClosureMap = {};
-
-  @override
-  NativeBasicData nativeBasicData;
-
-  Map<IndexedFunction, JGeneratorBody> _generatorBodies = {};
-
-  Map<IndexedClass, List<IndexedMember>> _injectedClassMembers = {};
-
-  JsKernelToElementMap(DiagnosticReporter reporter, Environment environment,
-      KernelToElementMapImpl _elementMap, Iterable<MemberEntity> liveMembers)
-      : super(_elementMap.options, reporter, environment) {
-    programEnv = _elementMap.env.convert();
-    for (int libraryIndex = 0;
-        libraryIndex < _elementMap.libraries.length;
-        libraryIndex++) {
-      IndexedLibrary oldLibrary = _elementMap.libraries.getEntity(libraryIndex);
-      KLibraryEnv oldEnv = _elementMap.libraries.getEnv(oldLibrary);
-      KLibraryData data = _elementMap.libraries.getData(oldLibrary);
-      IndexedLibrary newLibrary = convertLibrary(oldLibrary);
-      JLibraryEnv newEnv = oldEnv.convert(_elementMap, liveMembers);
-      libraryMap[oldEnv.library] =
-          libraries.register<IndexedLibrary, JLibraryData, JLibraryEnv>(
-              newLibrary, data.convert(), newEnv);
-      assert(newLibrary.libraryIndex == oldLibrary.libraryIndex);
-      programEnv.registerLibrary(newEnv);
-    }
-    // TODO(johnniwinther): Filter unused classes.
-    for (int classIndex = 0;
-        classIndex < _elementMap.classes.length;
-        classIndex++) {
-      IndexedClass oldClass = _elementMap.classes.getEntity(classIndex);
-      KClassEnv env = _elementMap.classes.getEnv(oldClass);
-      KClassData data = _elementMap.classes.getData(oldClass);
-      IndexedLibrary oldLibrary = oldClass.library;
-      LibraryEntity newLibrary = libraries.getEntity(oldLibrary.libraryIndex);
-      IndexedClass newClass = convertClass(newLibrary, oldClass);
-      JClassEnv newEnv = env.convert(_elementMap, liveMembers);
-      classMap[env.cls] = classes.register(newClass, data.convert(), newEnv);
-      assert(newClass.classIndex == oldClass.classIndex);
-      libraries.getEnv(newClass.library).registerClass(newClass.name, newEnv);
-    }
-    for (int typedefIndex = 0;
-        typedefIndex < _elementMap.typedefs.length;
-        typedefIndex++) {
-      IndexedTypedef oldTypedef = _elementMap.typedefs.getEntity(typedefIndex);
-      KTypedefData data = _elementMap.typedefs.getData(oldTypedef);
-      IndexedLibrary oldLibrary = oldTypedef.library;
-      LibraryEntity newLibrary = libraries.getEntity(oldLibrary.libraryIndex);
-      IndexedTypedef newTypedef = convertTypedef(newLibrary, oldTypedef);
-      typedefMap[data.node] = typedefs.register(
-          newTypedef,
-          new JTypedefData(new TypedefType(
-              newTypedef,
-              new List<DartType>.filled(
-                  data.node.typeParameters.length, const DynamicType()),
-              getDartType(data.node.type))));
-      assert(newTypedef.typedefIndex == oldTypedef.typedefIndex);
-    }
-    for (int memberIndex = 0;
-        memberIndex < _elementMap.members.length;
-        memberIndex++) {
-      IndexedMember oldMember = _elementMap.members.getEntity(memberIndex);
-      if (!liveMembers.contains(oldMember)) {
-        members.skipIndex(oldMember.memberIndex);
-        continue;
-      }
-      KMemberData data = _elementMap.members.getData(oldMember);
-      IndexedLibrary oldLibrary = oldMember.library;
-      IndexedClass oldClass = oldMember.enclosingClass;
-      LibraryEntity newLibrary = libraries.getEntity(oldLibrary.libraryIndex);
-      ClassEntity newClass =
-          oldClass != null ? classes.getEntity(oldClass.classIndex) : null;
-      IndexedMember newMember = convertMember(newLibrary, newClass, oldMember);
-      members.register(newMember, data.convert());
-      assert(newMember.memberIndex == oldMember.memberIndex);
-      if (newMember.isField) {
-        fieldMap[data.node] = newMember;
-      } else if (newMember.isConstructor) {
-        constructorMap[data.node] = newMember;
+  MemberEntity convertMember(
+      LibraryEntity library, ClassEntity cls, IndexedMember member) {
+    Name memberName = new Name(member.memberName.text, library,
+        isSetter: member.memberName.isSetter);
+    if (member.isField) {
+      IndexedField field = member;
+      return createField(library, cls, memberName,
+          isStatic: field.isStatic,
+          isAssignable: field.isAssignable,
+          isConst: field.isConst);
+    } else if (member.isConstructor) {
+      IndexedConstructor constructor = member;
+      if (constructor.isFactoryConstructor) {
+        // TODO(redemption): This should be a JFunction.
+        return createFactoryConstructor(
+            cls, memberName, constructor.parameterStructure,
+            isExternal: constructor.isExternal,
+            isConst: constructor.isConst,
+            isFromEnvironmentConstructor:
+                constructor.isFromEnvironmentConstructor);
       } else {
-        methodMap[data.node] = newMember;
+        return createGenerativeConstructor(
+            cls, memberName, constructor.parameterStructure,
+            isExternal: constructor.isExternal, isConst: constructor.isConst);
       }
+    } else if (member.isGetter) {
+      IndexedFunction getter = member;
+      return createGetter(library, cls, memberName, getter.asyncMarker,
+          isStatic: getter.isStatic,
+          isExternal: getter.isExternal,
+          isAbstract: getter.isAbstract);
+    } else if (member.isSetter) {
+      IndexedFunction setter = member;
+      return createSetter(library, cls, memberName,
+          isStatic: setter.isStatic,
+          isExternal: setter.isExternal,
+          isAbstract: setter.isAbstract);
+    } else {
+      IndexedFunction function = member;
+      return createMethod(library, cls, memberName, function.parameterStructure,
+          function.asyncMarker,
+          isStatic: function.isStatic,
+          isExternal: function.isExternal,
+          isAbstract: function.isAbstract);
     }
-    for (int typeVariableIndex = 0;
-        typeVariableIndex < _elementMap.typeVariables.length;
-        typeVariableIndex++) {
-      IndexedTypeVariable oldTypeVariable =
-          _elementMap.typeVariables.getEntity(typeVariableIndex);
-      KTypeVariableData oldTypeVariableData =
-          _elementMap.typeVariables.getData(oldTypeVariable);
-      Entity newTypeDeclaration;
-      if (oldTypeVariable.typeDeclaration is ClassEntity) {
-        IndexedClass cls = oldTypeVariable.typeDeclaration;
-        newTypeDeclaration = classes.getEntity(cls.classIndex);
-        // TODO(johnniwinther): Skip type variables of unused classes.
-      } else if (oldTypeVariable.typeDeclaration is MemberEntity) {
-        IndexedMember member = oldTypeVariable.typeDeclaration;
-        newTypeDeclaration = members.getEntity(member.memberIndex);
-        if (newTypeDeclaration == null) {
-          typeVariables.skipIndex(typeVariableIndex);
-          continue;
-        }
-      } else {
-        assert(oldTypeVariable.typeDeclaration is Local);
-      }
-      IndexedTypeVariable newTypeVariable = createTypeVariable(
-          newTypeDeclaration, oldTypeVariable.name, oldTypeVariable.index);
-      typeVariableMap[oldTypeVariableData.node] =
-          typeVariables.register<IndexedTypeVariable, JTypeVariableData>(
-              newTypeVariable, oldTypeVariableData.copy());
-      assert(newTypeVariable.typeVariableIndex ==
-          oldTypeVariable.typeVariableIndex);
-    }
-    // TODO(johnniwinther): We should close the environment in the beginning of
-    // this constructor but currently we need the [MemberEntity] to query if the
-    // member is live, thus potentially creating the [MemberEntity] in the
-    // process. Avoid this.
-    _elementMap.envIsClosed = true;
   }
 
-  JsKernelToElementMap.readFromDataSource(
-      CompilerOptions options,
-      DiagnosticReporter reporter,
-      Environment environment,
-      ir.Component component,
-      DataSource source)
-      : super(options, reporter, environment) {
-    source.registerComponentLookup(new ComponentLookup(component));
-    _EntityLookup entityLookup = new _EntityLookup();
-    source.registerEntityLookup(entityLookup);
-
-    source.begin(tag);
-    source.begin(libraryTag);
-    int libraryCount = source.readInt();
-    for (int i = 0; i < libraryCount; i++) {
-      int index = source.readInt();
-      JLibrary library = new JLibrary.readFromDataSource(source);
-      entityLookup.registerLibrary(index, library);
-    }
-    source.end(libraryTag);
-
-    source.begin(classTag);
-    int classCount = source.readInt();
-    for (int i = 0; i < classCount; i++) {
-      int index = source.readInt();
-      JClass cls = new JClass.readFromDataSource(source);
-      entityLookup.registerClass(index, cls);
-    }
-    source.end(classTag);
-
-    source.begin(typedefTag);
-    int typedefCount = source.readInt();
-    for (int i = 0; i < typedefCount; i++) {
-      int index = source.readInt();
-      JTypedef typedef = new JTypedef.readFromDataSource(source);
-      entityLookup.registerTypedef(index, typedef);
-    }
-    source.end(typedefTag);
-
-    source.begin(memberTag);
-    int memberCount = source.readInt();
-    for (int i = 0; i < memberCount; i++) {
-      int index = source.readInt();
-      JMember member = new JMember.readFromDataSource(source);
-      entityLookup.registerMember(index, member);
-    }
-    source.end(memberTag);
-
-    source.begin(typeVariableTag);
-    int typeVariableCount = source.readInt();
-    for (int i = 0; i < typeVariableCount; i++) {
-      int index = source.readInt();
-      JTypeVariable typeVariable = new JTypeVariable.readFromDataSource(source);
-      entityLookup.registerTypeVariable(index, typeVariable);
-    }
-    source.end(typeVariableTag);
-
-    programEnv = new JProgramEnv([component]);
-    source.begin(libraryDataTag);
-    entityLookup.forEachLibrary((int index, JLibrary library) {
-      JLibraryEnv env = new JLibraryEnv.readFromDataSource(source);
-      JLibraryData data = new JLibraryData.readFromDataSource(source);
-      libraryMap[env.library] =
-          libraries.registerByIndex(index, library, data, env);
-      programEnv.registerLibrary(env);
-      assert(index == library.libraryIndex);
-    });
-    source.end(libraryDataTag);
-
-    source.begin(classDataTag);
-    entityLookup.forEachClass((int index, JClass cls) {
-      JClassEnv env = new JClassEnv.readFromDataSource(source);
-      JClassData data = new JClassData.readFromDataSource(source);
-      classMap[env.cls] = classes.registerByIndex(index, cls, data, env);
-      libraries.getEnv(cls.library).registerClass(cls.name, env);
-      assert(index == cls.classIndex);
-    });
-    source.end(classDataTag);
-
-    source.begin(typedefDataTag);
-    entityLookup.forEachTypedef((int index, JTypedef typedef) {
-      JTypedefData data = new JTypedefData.readFromDataSource(source);
-      typedefs.registerByIndex(index, typedef, data);
-      assert(index == typedef.typedefIndex);
-    });
-    source.end(typedefDataTag);
-
-    source.begin(memberDataTag);
-    entityLookup.forEachMember((int index, IndexedMember member) {
-      JMemberData data = new JMemberData.readFromDataSource(source);
-      members.registerByIndex(index, member, data);
-      switch (data.definition.kind) {
-        case MemberKind.regular:
-        case MemberKind.constructor:
-          ir.Member node = data.definition.node;
-          if (member.isField) {
-            fieldMap[node] = member;
-          } else if (member.isConstructor) {
-            constructorMap[node] = member;
-          } else {
-            methodMap[node] = member;
-          }
-          break;
-        default:
-      }
-      assert(index == member.memberIndex);
-    });
-    source.end(memberDataTag);
-
-    source.begin(typeVariableDataTag);
-    entityLookup.forEachTypeVariable((int index, JTypeVariable typeVariable) {
-      JTypeVariableData data = new JTypeVariableData.readFromDataSource(source);
-      typeVariableMap[data.node] =
-          typeVariables.registerByIndex(index, typeVariable, data);
-      assert(index == typeVariable.typeVariableIndex);
-    });
-    source.end(typeVariableDataTag);
-    source.end(tag);
-  }
-
-  /// Serializes this [JsToElementMap] to [sink].
-  void writeToDataSink(DataSink sink) {
-    sink.begin(tag);
-
-    // Serialize the entities before serializing the data.
-    sink.begin(libraryTag);
-    sink.writeInt(libraries.size);
-    libraries.forEach((JLibrary library, _, __) {
-      sink.writeInt(library.libraryIndex);
-      library.writeToDataSink(sink);
-    });
-    sink.end(libraryTag);
-
-    sink.begin(classTag);
-    sink.writeInt(classes.size);
-    classes.forEach((JClass cls, _, __) {
-      sink.writeInt(cls.classIndex);
-      cls.writeToDataSink(sink);
-    });
-    sink.end(classTag);
-
-    sink.begin(typedefTag);
-    sink.writeInt(typedefs.size);
-    typedefs.forEach((JTypedef typedef, _) {
-      sink.writeInt(typedef.typedefIndex);
-      typedef.writeToDataSink(sink);
-    });
-    sink.end(typedefTag);
-
-    sink.begin(memberTag);
-    sink.writeInt(members.size);
-    members.forEach((JMember member, _) {
-      sink.writeInt(member.memberIndex);
-      member.writeToDataSink(sink);
-    });
-    sink.end(memberTag);
-
-    sink.begin(typeVariableTag);
-    sink.writeInt(typeVariables.size);
-    typeVariables.forEach((JTypeVariable typeVariable, _) {
-      sink.writeInt(typeVariable.typeVariableIndex);
-      typeVariable.writeToDataSink(sink);
-    });
-    sink.end(typeVariableTag);
-
-    // Serialize the entity data after having serialized the entities.
-    sink.begin(libraryDataTag);
-    libraries.forEach((_, JLibraryData data, JLibraryEnv env) {
-      env.writeToDataSink(sink);
-      data.writeToDataSink(sink);
-    });
-    sink.end(libraryDataTag);
-
-    sink.begin(classDataTag);
-    classes.forEach((_, JClassData data, JClassEnv env) {
-      env.writeToDataSink(sink);
-      data.writeToDataSink(sink);
-    });
-    sink.end(classDataTag);
-
-    sink.begin(typedefDataTag);
-    typedefs.forEach((_, JTypedefData data) {
-      data.writeToDataSink(sink);
-    });
-    sink.end(typedefDataTag);
-
-    sink.begin(memberDataTag);
-    members.forEach((_, JMemberData data) {
-      data.writeToDataSink(sink);
-    });
-    sink.end(memberDataTag);
-
-    sink.begin(typeVariableDataTag);
-    typeVariables.forEach((_, JTypeVariableData data) {
-      data.writeToDataSink(sink);
-    });
-    sink.end(typeVariableDataTag);
-
-    sink.end(tag);
-  }
-
-  @override
   void forEachNestedClosure(
       MemberEntity member, void f(FunctionEntity closure)) {
     assert(checkFamily(member));
@@ -1818,7 +1552,6 @@
     return members.getData(member).classTypeVariableAccess;
   }
 
-  @override
   bool checkFamily(Entity entity) {
     assert(
         '$entity'.startsWith(jsElementPrefix),
@@ -1837,47 +1570,40 @@
     return sourceSpan;
   }
 
-  @override
   Iterable<LibraryEntity> get libraryListInternal {
     return libraryMap.values;
   }
 
-  @override
   LibraryEntity getLibraryInternal(ir.Library node, [JLibraryEnv env]) {
     LibraryEntity library = libraryMap[node];
     assert(library != null, "No library entity for $node");
     return library;
   }
 
-  @override
   ClassEntity getClassInternal(ir.Class node, [JClassEnv env]) {
     ClassEntity cls = classMap[node];
     assert(cls != null, "No class entity for $node");
     return cls;
   }
 
-  @override
   FieldEntity getFieldInternal(ir.Field node) {
     FieldEntity field = fieldMap[node];
     assert(field != null, "No field entity for $node");
     return field;
   }
 
-  @override
   FunctionEntity getMethodInternal(ir.Procedure node) {
     FunctionEntity function = methodMap[node];
     assert(function != null, "No function entity for $node");
     return function;
   }
 
-  @override
   ConstructorEntity getConstructorInternal(ir.Member node) {
     ConstructorEntity constructor = constructorMap[node];
     assert(constructor != null, "No constructor entity for $node");
     return constructor;
   }
 
-  @override
   TypeVariableEntity getTypeVariableInternal(ir.TypeParameter node) {
     TypeVariableEntity typeVariable = typeVariableMap[node];
     if (typeVariable == null) {
@@ -1906,7 +1632,6 @@
     return typeVariable;
   }
 
-  @override
   TypedefEntity getTypedefInternal(ir.Typedef node) {
     TypedefEntity typedef = typedefMap[node];
     assert(typedef != null, "No typedef entity for $node");
@@ -1939,9 +1664,6 @@
   }
 
   @override
-  JConstructorBody createConstructorBody(ConstructorEntity constructor);
-
-  @override
   MemberDefinition getMemberDefinition(MemberEntity member) {
     return getMemberDefinitionInternal(member);
   }
@@ -1977,14 +1699,12 @@
     data.forEachParameter(this, f);
   }
 
-  @override
   void forEachConstructorBody(
       IndexedClass cls, void f(ConstructorBodyEntity member)) {
     JClassEnv env = classes.getEnv(cls);
     env.forEachConstructorBody(f);
   }
 
-  @override
   void forEachInjectedClassMember(
       IndexedClass cls, void f(MemberEntity member)) {
     _injectedClassMembers[cls]?.forEach(f);
@@ -2396,10 +2116,6 @@
   }
 
   @override
-  JGeneratorBody createGeneratorBody(
-      FunctionEntity function, DartType elementType);
-
-  @override
   js.Template getJsBuiltinTemplate(
       ConstantValue constant, CodeEmitterTask emitter) {
     int index = extractEnumIndexFromConstantValue(
@@ -2409,9 +2125,371 @@
   }
 }
 
+class JsElementEnvironment extends ElementEnvironment
+    implements JElementEnvironment {
+  final JsKernelToElementMap elementMap;
+
+  JsElementEnvironment(this.elementMap);
+
+  @override
+  DartType get dynamicType => const DynamicType();
+
+  @override
+  LibraryEntity get mainLibrary => elementMap._mainLibrary;
+
+  @override
+  FunctionEntity get mainFunction => elementMap._mainFunction;
+
+  @override
+  Iterable<LibraryEntity> get libraries => elementMap.libraryListInternal;
+
+  @override
+  String getLibraryName(LibraryEntity library) {
+    return elementMap._getLibraryName(library);
+  }
+
+  @override
+  InterfaceType getThisType(ClassEntity cls) {
+    return elementMap.getThisType(cls);
+  }
+
+  @override
+  InterfaceType getRawType(ClassEntity cls) {
+    return elementMap._getRawType(cls);
+  }
+
+  @override
+  bool isGenericClass(ClassEntity cls) {
+    return getThisType(cls).typeArguments.isNotEmpty;
+  }
+
+  @override
+  bool isMixinApplication(ClassEntity cls) {
+    return elementMap._isMixinApplication(cls);
+  }
+
+  @override
+  bool isUnnamedMixinApplication(ClassEntity cls) {
+    return elementMap._isUnnamedMixinApplication(cls);
+  }
+
+  @override
+  bool isSuperMixinApplication(ClassEntity cls) {
+    return elementMap._isSuperMixinApplication(cls);
+  }
+
+  @override
+  ClassEntity getEffectiveMixinClass(ClassEntity cls) {
+    if (!isMixinApplication(cls)) return null;
+    do {
+      cls = elementMap.getAppliedMixin(cls);
+    } while (isMixinApplication(cls));
+    return cls;
+  }
+
+  @override
+  DartType getTypeVariableBound(TypeVariableEntity typeVariable) {
+    return elementMap.getTypeVariableBound(typeVariable);
+  }
+
+  @override
+  DartType getTypeVariableDefaultType(TypeVariableEntity typeVariable) {
+    return elementMap._getTypeVariableDefaultType(typeVariable);
+  }
+
+  @override
+  InterfaceType createInterfaceType(
+      ClassEntity cls, List<DartType> typeArguments) {
+    return new InterfaceType(cls, typeArguments);
+  }
+
+  @override
+  FunctionType getFunctionType(FunctionEntity function) {
+    return elementMap._getFunctionType(function);
+  }
+
+  @override
+  List<TypeVariableType> getFunctionTypeVariables(FunctionEntity function) {
+    return elementMap._getFunctionTypeVariables(function);
+  }
+
+  @override
+  DartType getFunctionAsyncOrSyncStarElementType(FunctionEntity function) {
+    // TODO(sra): Should be getting the DartType from the node.
+    DartType returnType = getFunctionType(function).returnType;
+    return getAsyncOrSyncStarElementType(function.asyncMarker, returnType);
+  }
+
+  @override
+  DartType getAsyncOrSyncStarElementType(
+      AsyncMarker asyncMarker, DartType returnType) {
+    switch (asyncMarker) {
+      case AsyncMarker.SYNC:
+        return returnType;
+      case AsyncMarker.SYNC_STAR:
+        if (returnType is InterfaceType) {
+          if (returnType.element == elementMap.commonElements.iterableClass) {
+            return returnType.typeArguments.first;
+          }
+        }
+        return dynamicType;
+      case AsyncMarker.ASYNC:
+        if (returnType is FutureOrType) return returnType.typeArgument;
+        if (returnType is InterfaceType) {
+          if (returnType.element == elementMap.commonElements.futureClass) {
+            return returnType.typeArguments.first;
+          }
+        }
+        return dynamicType;
+      case AsyncMarker.ASYNC_STAR:
+        if (returnType is InterfaceType) {
+          if (returnType.element == elementMap.commonElements.streamClass) {
+            return returnType.typeArguments.first;
+          }
+        }
+        return dynamicType;
+    }
+    assert(false, 'Unexpected marker ${asyncMarker}');
+    return null;
+  }
+
+  @override
+  DartType getFieldType(FieldEntity field) {
+    return elementMap._getFieldType(field);
+  }
+
+  @override
+  FunctionType getLocalFunctionType(covariant KLocalFunction function) {
+    return function.functionType;
+  }
+
+  @override
+  DartType getUnaliasedType(DartType type) => type;
+
+  @override
+  ConstructorEntity lookupConstructor(ClassEntity cls, String name,
+      {bool required: false}) {
+    ConstructorEntity constructor = elementMap.lookupConstructor(cls, name);
+    if (constructor == null && required) {
+      throw failedAt(
+          CURRENT_ELEMENT_SPANNABLE,
+          "The constructor '$name' was not found in class '${cls.name}' "
+          "in library ${cls.library.canonicalUri}.");
+    }
+    return constructor;
+  }
+
+  @override
+  MemberEntity lookupLocalClassMember(ClassEntity cls, String name,
+      {bool setter: false, bool required: false}) {
+    MemberEntity member =
+        elementMap.lookupClassMember(cls, name, setter: setter);
+    if (member == null && required) {
+      throw failedAt(CURRENT_ELEMENT_SPANNABLE,
+          "The member '$name' was not found in ${cls.name}.");
+    }
+    return member;
+  }
+
+  @override
+  ClassEntity getSuperClass(ClassEntity cls,
+      {bool skipUnnamedMixinApplications: false}) {
+    assert(elementMap.checkFamily(cls));
+    ClassEntity superclass = elementMap.getSuperType(cls)?.element;
+    if (skipUnnamedMixinApplications) {
+      while (superclass != null &&
+          elementMap._isUnnamedMixinApplication(superclass)) {
+        superclass = elementMap.getSuperType(superclass)?.element;
+      }
+    }
+    return superclass;
+  }
+
+  @override
+  void forEachSupertype(ClassEntity cls, void f(InterfaceType supertype)) {
+    elementMap._forEachSupertype(cls, f);
+  }
+
+  @override
+  void forEachLocalClassMember(ClassEntity cls, void f(MemberEntity member)) {
+    elementMap._forEachLocalClassMember(cls, f);
+  }
+
+  @override
+  void forEachInjectedClassMember(
+      ClassEntity cls, void f(MemberEntity member)) {
+    elementMap.forEachInjectedClassMember(cls, f);
+  }
+
+  @override
+  void forEachClassMember(
+      ClassEntity cls, void f(ClassEntity declarer, MemberEntity member)) {
+    elementMap._forEachClassMember(cls, f);
+  }
+
+  @override
+  void forEachConstructor(
+      ClassEntity cls, void f(ConstructorEntity constructor)) {
+    elementMap._forEachConstructor(cls, f);
+  }
+
+  @override
+  void forEachConstructorBody(
+      ClassEntity cls, void f(ConstructorBodyEntity constructor)) {
+    elementMap.forEachConstructorBody(cls, f);
+  }
+
+  @override
+  void forEachNestedClosure(
+      MemberEntity member, void f(FunctionEntity closure)) {
+    elementMap.forEachNestedClosure(member, f);
+  }
+
+  @override
+  void forEachLibraryMember(
+      LibraryEntity library, void f(MemberEntity member)) {
+    elementMap._forEachLibraryMember(library, f);
+  }
+
+  @override
+  MemberEntity lookupLibraryMember(LibraryEntity library, String name,
+      {bool setter: false, bool required: false}) {
+    MemberEntity member =
+        elementMap.lookupLibraryMember(library, name, setter: setter);
+    if (member == null && required) {
+      failedAt(CURRENT_ELEMENT_SPANNABLE,
+          "The member '${name}' was not found in library '${library.name}'.");
+    }
+    return member;
+  }
+
+  @override
+  ClassEntity lookupClass(LibraryEntity library, String name,
+      {bool required: false}) {
+    ClassEntity cls = elementMap.lookupClass(library, name);
+    if (cls == null && required) {
+      failedAt(CURRENT_ELEMENT_SPANNABLE,
+          "The class '$name'  was not found in library '${library.name}'.");
+    }
+    return cls;
+  }
+
+  @override
+  void forEachClass(LibraryEntity library, void f(ClassEntity cls)) {
+    elementMap._forEachClass(library, f);
+  }
+
+  @override
+  LibraryEntity lookupLibrary(Uri uri, {bool required: false}) {
+    LibraryEntity library = elementMap.lookupLibrary(uri);
+    if (library == null && required) {
+      failedAt(CURRENT_ELEMENT_SPANNABLE, "The library '$uri' was not found.");
+    }
+    return library;
+  }
+
+  @override
+  bool isEnumClass(ClassEntity cls) {
+    assert(elementMap.checkFamily(cls));
+    JClassData classData = elementMap.classes.getData(cls);
+    return classData.isEnumClass;
+  }
+}
+
+/// [native.BehaviorBuilder] for kernel based elements.
+class JsBehaviorBuilder extends native.BehaviorBuilder {
+  final ElementEnvironment elementEnvironment;
+  final CommonElements commonElements;
+  final DiagnosticReporter reporter;
+  final NativeBasicData nativeBasicData;
+  final CompilerOptions _options;
+
+  JsBehaviorBuilder(this.elementEnvironment, this.commonElements,
+      this.nativeBasicData, this.reporter, this._options);
+
+  @override
+  bool get trustJSInteropTypeAnnotations =>
+      _options.trustJSInteropTypeAnnotations;
+}
+
+/// Constant environment mapping [ConstantExpression]s to [ConstantValue]s using
+/// [_EvaluationEnvironment] for the evaluation.
+class JsConstantEnvironment implements ConstantEnvironment {
+  final JsKernelToElementMap _elementMap;
+  final Environment _environment;
+
+  Map<ConstantExpression, ConstantValue> _valueMap =
+      <ConstantExpression, ConstantValue>{};
+
+  JsConstantEnvironment(this._elementMap, this._environment);
+
+  @override
+  ConstantSystem get constantSystem => JavaScriptConstantSystem.only;
+
+  ConstantValue _getConstantValue(
+      Spannable spannable, ConstantExpression expression,
+      {bool constantRequired}) {
+    return _valueMap.putIfAbsent(expression, () {
+      return expression.evaluate(
+          new JsEvaluationEnvironment(_elementMap, _environment, spannable,
+              constantRequired: constantRequired),
+          constantSystem);
+    });
+  }
+}
+
+/// Evaluation environment used for computing [ConstantValue]s for
+/// kernel based [ConstantExpression]s.
+class JsEvaluationEnvironment extends EvaluationEnvironmentBase {
+  final JsKernelToElementMap _elementMap;
+  final Environment _environment;
+
+  JsEvaluationEnvironment(
+      this._elementMap, this._environment, Spannable spannable,
+      {bool constantRequired})
+      : super(spannable, constantRequired: constantRequired);
+
+  @override
+  CommonElements get commonElements => _elementMap.commonElements;
+
+  @override
+  DartTypes get types => _elementMap.types;
+
+  @override
+  DartType substByContext(DartType base, InterfaceType target) {
+    return _elementMap.substByContext(base, target);
+  }
+
+  @override
+  ConstantConstructor getConstructorConstant(ConstructorEntity constructor) {
+    return _elementMap._getConstructorConstant(constructor);
+  }
+
+  @override
+  ConstantExpression getFieldConstant(FieldEntity field) {
+    return _elementMap._getFieldConstantExpression(field);
+  }
+
+  @override
+  ConstantExpression getLocalConstant(Local local) {
+    throw new UnimplementedError("_EvaluationEnvironment.getLocalConstant");
+  }
+
+  @override
+  String readFromEnvironment(String name) {
+    return _environment.valueOf(name);
+  }
+
+  @override
+  DiagnosticReporter get reporter => _elementMap.reporter;
+
+  @override
+  bool get enableAssertions => _elementMap.options.enableUserAssertions;
+}
+
 class JsToFrontendMapImpl extends JsToFrontendMapBase
     implements JsToFrontendMap {
-  final JsToElementMapBase _backend;
+  final JsKernelToElementMap _backend;
 
   JsToFrontendMapImpl(this._backend);
 
diff --git a/pkg/compiler/lib/src/js_model/elements.dart b/pkg/compiler/lib/src/js_model/elements.dart
index f964ef9..cc98750 100644
--- a/pkg/compiler/lib/src/js_model/elements.dart
+++ b/pkg/compiler/lib/src/js_model/elements.dart
@@ -106,146 +106,6 @@
   TypeVariableEntity toBackendTypeVariable(TypeVariableEntity typeVariable);
 }
 
-// TODO(johnniwinther): Merge this with [JsKernelToElementMap].
-class JsElementCreatorMixin {
-  IndexedLibrary createLibrary(String name, Uri canonicalUri) {
-    return new JLibrary(name, canonicalUri);
-  }
-
-  IndexedClass createClass(LibraryEntity library, String name,
-      {bool isAbstract}) {
-    return new JClass(library, name, isAbstract: isAbstract);
-  }
-
-  IndexedTypedef createTypedef(LibraryEntity library, String name) {
-    return new JTypedef(library, name);
-  }
-
-  TypeVariableEntity createTypeVariable(
-      Entity typeDeclaration, String name, int index) {
-    return new JTypeVariable(typeDeclaration, name, index);
-  }
-
-  IndexedConstructor createGenerativeConstructor(ClassEntity enclosingClass,
-      Name name, ParameterStructure parameterStructure,
-      {bool isExternal, bool isConst}) {
-    return new JGenerativeConstructor(enclosingClass, name, parameterStructure,
-        isExternal: isExternal, isConst: isConst);
-  }
-
-  IndexedConstructor createFactoryConstructor(ClassEntity enclosingClass,
-      Name name, ParameterStructure parameterStructure,
-      {bool isExternal, bool isConst, bool isFromEnvironmentConstructor}) {
-    return new JFactoryConstructor(enclosingClass, name, parameterStructure,
-        isExternal: isExternal,
-        isConst: isConst,
-        isFromEnvironmentConstructor: isFromEnvironmentConstructor);
-  }
-
-  JConstructorBody createConstructorBody(ConstructorEntity constructor) {
-    return new JConstructorBody(constructor);
-  }
-
-  JGeneratorBody createGeneratorBody(
-      FunctionEntity function, DartType elementType) {
-    return new JGeneratorBody(function, elementType);
-  }
-
-  IndexedFunction createGetter(LibraryEntity library,
-      ClassEntity enclosingClass, Name name, AsyncMarker asyncMarker,
-      {bool isStatic, bool isExternal, bool isAbstract}) {
-    return new JGetter(library, enclosingClass, name, asyncMarker,
-        isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
-  }
-
-  IndexedFunction createMethod(
-      LibraryEntity library,
-      ClassEntity enclosingClass,
-      Name name,
-      ParameterStructure parameterStructure,
-      AsyncMarker asyncMarker,
-      {bool isStatic,
-      bool isExternal,
-      bool isAbstract}) {
-    return new JMethod(
-        library, enclosingClass, name, parameterStructure, asyncMarker,
-        isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
-  }
-
-  IndexedFunction createSetter(
-      LibraryEntity library, ClassEntity enclosingClass, Name name,
-      {bool isStatic, bool isExternal, bool isAbstract}) {
-    return new JSetter(library, enclosingClass, name,
-        isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
-  }
-
-  IndexedField createField(
-      LibraryEntity library, ClassEntity enclosingClass, Name name,
-      {bool isStatic, bool isAssignable, bool isConst}) {
-    return new JField(library, enclosingClass, name,
-        isStatic: isStatic, isAssignable: isAssignable, isConst: isConst);
-  }
-
-  LibraryEntity convertLibrary(IndexedLibrary library) {
-    return createLibrary(library.name, library.canonicalUri);
-  }
-
-  ClassEntity convertClass(LibraryEntity library, IndexedClass cls) {
-    return createClass(library, cls.name, isAbstract: cls.isAbstract);
-  }
-
-  TypedefEntity convertTypedef(LibraryEntity library, IndexedTypedef typedef) {
-    return createTypedef(library, typedef.name);
-  }
-
-  MemberEntity convertMember(
-      LibraryEntity library, ClassEntity cls, IndexedMember member) {
-    Name memberName = new Name(member.memberName.text, library,
-        isSetter: member.memberName.isSetter);
-    if (member.isField) {
-      IndexedField field = member;
-      return createField(library, cls, memberName,
-          isStatic: field.isStatic,
-          isAssignable: field.isAssignable,
-          isConst: field.isConst);
-    } else if (member.isConstructor) {
-      IndexedConstructor constructor = member;
-      if (constructor.isFactoryConstructor) {
-        // TODO(redemption): This should be a JFunction.
-        return createFactoryConstructor(
-            cls, memberName, constructor.parameterStructure,
-            isExternal: constructor.isExternal,
-            isConst: constructor.isConst,
-            isFromEnvironmentConstructor:
-                constructor.isFromEnvironmentConstructor);
-      } else {
-        return createGenerativeConstructor(
-            cls, memberName, constructor.parameterStructure,
-            isExternal: constructor.isExternal, isConst: constructor.isConst);
-      }
-    } else if (member.isGetter) {
-      IndexedFunction getter = member;
-      return createGetter(library, cls, memberName, getter.asyncMarker,
-          isStatic: getter.isStatic,
-          isExternal: getter.isExternal,
-          isAbstract: getter.isAbstract);
-    } else if (member.isSetter) {
-      IndexedFunction setter = member;
-      return createSetter(library, cls, memberName,
-          isStatic: setter.isStatic,
-          isExternal: setter.isExternal,
-          isAbstract: setter.isAbstract);
-    } else {
-      IndexedFunction function = member;
-      return createMethod(library, cls, memberName, function.parameterStructure,
-          function.asyncMarker,
-          isStatic: function.isStatic,
-          isExternal: function.isExternal,
-          isAbstract: function.isAbstract);
-    }
-  }
-}
-
 typedef Entity EntityConverter(Entity cls);
 
 class TypeConverter implements DartTypeVisitor<DartType, EntityConverter> {
@@ -901,7 +761,8 @@
     bool isExternal = source.readBool();
     bool isAbstract = source.readBool();
     source.end(tag);
-    return new JSetter(library, enclosingClass, new Name(name, library),
+    return new JSetter(
+        library, enclosingClass, new Name(name, library, isSetter: true),
         isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
   }
 
diff --git a/pkg/compiler/lib/src/js_model/env.dart b/pkg/compiler/lib/src/js_model/env.dart
index 876106a..a941fbb 100644
--- a/pkg/compiler/lib/src/js_model/env.dart
+++ b/pkg/compiler/lib/src/js_model/env.dart
@@ -140,7 +140,12 @@
     int importCount = source.readInt();
     Map<ir.LibraryDependency, ImportEntity> imports;
     if (importCount > 0) {
-      // TODO(johnniwinther): Deserialize imports.
+      imports = {};
+      for (int i = 0; i < importCount; i++) {
+        int index = source.readInt();
+        ImportEntity import = source.readImport();
+        imports[library.dependencies[index]] = import;
+      }
     }
     source.end(tag);
     return new JLibraryData(library, imports);
@@ -153,7 +158,15 @@
       sink.writeInt(0);
     } else {
       sink.writeInt(imports.length);
-      // TODO(johnniwinther): Serialize imports.
+      int index = 0;
+      for (ir.LibraryDependency node in library.dependencies) {
+        ImportEntity import = imports[node];
+        if (import != null) {
+          sink.writeInt(index);
+          sink.writeImport(import);
+        }
+        index++;
+      }
     }
     sink.end(tag);
   }
@@ -557,7 +570,7 @@
   List<TypeVariableType> _typeVariables;
 
   List<TypeVariableType> getFunctionTypeVariables(
-      covariant JsToElementMapBase elementMap) {
+      covariant JsKernelToElementMap elementMap) {
     if (_typeVariables == null) {
       if (functionNode.typeParameters.isEmpty) {
         _typeVariables = const <TypeVariableType>[];
@@ -620,7 +633,7 @@
     sink.end(tag);
   }
 
-  FunctionType getFunctionType(covariant JsToElementMapBase elementMap) {
+  FunctionType getFunctionType(covariant JsKernelToElementMap elementMap) {
     return _type ??= elementMap.getFunctionType(functionNode);
   }
 
@@ -692,7 +705,7 @@
     sink.end(tag);
   }
 
-  FunctionType getFunctionType(covariant JsToElementMapBase elementMap) {
+  FunctionType getFunctionType(covariant JsKernelToElementMap elementMap) {
     throw new UnsupportedError("SignatureFunctionData.getFunctionType");
   }
 
@@ -718,7 +731,7 @@
 
   DelegatedFunctionData(this.baseData);
 
-  FunctionType getFunctionType(covariant JsToElementMapBase elementMap) {
+  FunctionType getFunctionType(covariant JsKernelToElementMap elementMap) {
     return baseData.getFunctionType(elementMap);
   }
 
@@ -770,7 +783,7 @@
 
 abstract class JConstructorData extends FunctionData {
   ConstantConstructor getConstructorConstant(
-      JsToElementMapBase elementMap, ConstructorEntity constructor);
+      JsKernelToElementMap elementMap, ConstructorEntity constructor);
 }
 
 class JConstructorDataImpl extends FunctionDataImpl
@@ -814,7 +827,7 @@
   }
 
   ConstantConstructor getConstructorConstant(
-      JsToElementMapBase elementMap, ConstructorEntity constructor) {
+      JsKernelToElementMap elementMap, ConstructorEntity constructor) {
     if (_constantConstructor == null) {
       if (node is ir.Constructor && constructor.isConst) {
         _constantConstructor =
@@ -879,15 +892,16 @@
 abstract class JFieldData extends JMemberData {
   DartType getFieldType(IrToElementMap elementMap);
 
-  ConstantExpression getFieldConstantExpression(JsToElementMapBase elementMap);
+  ConstantExpression getFieldConstantExpression(
+      JsKernelToElementMap elementMap);
 
   /// Return the [ConstantValue] the initial value of [field] or `null` if
   /// the initializer is not a constant expression.
-  ConstantValue getFieldConstantValue(JsToElementMapBase elementMap);
+  ConstantValue getFieldConstantValue(JsKernelToElementMap elementMap);
 
-  bool hasConstantFieldInitializer(JsToElementMapBase elementMap);
+  bool hasConstantFieldInitializer(JsKernelToElementMap elementMap);
 
-  ConstantValue getConstantFieldInitializer(JsToElementMapBase elementMap);
+  ConstantValue getConstantFieldInitializer(JsKernelToElementMap elementMap);
 }
 
 class JFieldDataImpl extends JMemberDataImpl implements JFieldData {
@@ -922,11 +936,12 @@
 
   ir.Field get node => super.node;
 
-  DartType getFieldType(covariant JsToElementMapBase elementMap) {
+  DartType getFieldType(covariant JsKernelToElementMap elementMap) {
     return _type ??= elementMap.getDartType(node.type);
   }
 
-  ConstantExpression getFieldConstantExpression(JsToElementMapBase elementMap) {
+  ConstantExpression getFieldConstantExpression(
+      JsKernelToElementMap elementMap) {
     if (_constantExpression == null) {
       if (node.isConst) {
         _constantExpression =
@@ -942,7 +957,7 @@
   }
 
   @override
-  ConstantValue getFieldConstantValue(JsToElementMapBase elementMap) {
+  ConstantValue getFieldConstantValue(JsKernelToElementMap elementMap) {
     if (!_isConstantComputed) {
       _constantValue = elementMap.getConstantValue(node.initializer,
           requireConstant: node.isConst, implicitNull: !node.isConst);
@@ -952,12 +967,12 @@
   }
 
   @override
-  bool hasConstantFieldInitializer(JsToElementMapBase elementMap) {
+  bool hasConstantFieldInitializer(JsKernelToElementMap elementMap) {
     return getFieldConstantValue(elementMap) != null;
   }
 
   @override
-  ConstantValue getConstantFieldInitializer(JsToElementMapBase elementMap) {
+  ConstantValue getConstantFieldInitializer(JsKernelToElementMap elementMap) {
     ConstantValue value = getFieldConstantValue(elementMap);
     assert(
         value != null,
@@ -980,19 +995,22 @@
   /// a debugging data stream.
   static const String tag = 'typedef-data';
 
+  final ir.Typedef node;
   final TypedefType rawType;
 
-  JTypedefData(this.rawType);
+  JTypedefData(this.node, this.rawType);
 
   factory JTypedefData.readFromDataSource(DataSource source) {
     source.begin(tag);
+    ir.Typedef node = source.readTypedefNode();
     TypedefType rawType = source.readDartType();
     source.end(tag);
-    return new JTypedefData(rawType);
+    return new JTypedefData(node, rawType);
   }
 
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
+    sink.writeTypedefNode(node);
     sink.writeDartType(rawType);
     sink.end(tag);
   }
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index 3421f91..6bc3f84 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -7,61 +7,40 @@
 import 'package:kernel/ast.dart' as ir;
 
 import '../backend_strategy.dart';
-import '../closure.dart';
 import '../common.dart';
 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
 import '../common/tasks.dart';
-import '../common_elements.dart';
 import '../compiler.dart';
-import '../constants/constant_system.dart';
-import '../constants/values.dart';
 import '../deferred_load.dart';
-import '../diagnostics/diagnostic_listener.dart';
 import '../elements/entities.dart';
-import '../elements/names.dart';
-import '../elements/types.dart';
-import '../elements/entity_utils.dart' as utils;
-import '../environment.dart';
 import '../enqueue.dart';
 import '../io/kernel_source_information.dart'
     show KernelSourceInformationStrategy;
 import '../io/source_information.dart';
 import '../inferrer/type_graph_inferrer.dart';
-import '../js_emitter/sorter.dart';
 import '../js/js_source_mapping.dart';
-import '../js_backend/annotations.dart';
-import '../js_backend/allocator_analysis.dart';
 import '../js_backend/backend.dart';
-import '../js_backend/backend_usage.dart';
-import '../js_backend/constant_system_javascript.dart';
 import '../js_backend/inferred_data.dart';
-import '../js_backend/interceptor_data.dart';
 import '../js_backend/native_data.dart';
-import '../js_backend/no_such_method_registry.dart';
-import '../js_backend/runtime_types.dart';
 import '../kernel/kernel_strategy.dart';
-import '../kernel/kelements.dart';
 import '../native/behavior.dart';
-import '../ordered_typeset.dart';
 import '../options.dart';
-import '../serialization/serialization.dart';
 import '../ssa/builder_kernel.dart';
 import '../ssa/nodes.dart';
 import '../ssa/ssa.dart';
 import '../ssa/types.dart';
 import '../types/abstract_value_domain.dart';
 import '../types/types.dart';
-import '../universe/class_hierarchy.dart';
-import '../universe/class_set.dart';
-import '../universe/feature.dart';
+import '../universe/codegen_world_builder.dart';
 import '../universe/selector.dart';
 import '../universe/world_builder.dart';
 import '../universe/world_impact.dart';
 import '../world.dart';
 import 'closure.dart';
-import 'elements.dart';
 import 'element_map.dart';
 import 'element_map_impl.dart';
+import 'js_world.dart';
+import 'js_world_builder.dart';
 import 'locals.dart';
 
 class JsBackendStrategy implements BackendStrategy {
@@ -77,9 +56,6 @@
     return _elementMap;
   }
 
-  ElementEnvironment get _elementEnvironment => _elementMap.elementEnvironment;
-  CommonElements get _commonElements => _elementMap.commonElements;
-
   @override
   JClosedWorld createJClosedWorld(
       KClosedWorld closedWorld, OutputUnitData outputUnitData) {
@@ -98,7 +74,7 @@
         closureDataBuilder,
         _compiler.options,
         _compiler.abstractValueStrategy);
-    return closedWorldBuilder._convertClosedWorld(
+    return closedWorldBuilder.convertClosedWorld(
         closedWorld, strategy.closureModels, outputUnitData);
   }
 
@@ -149,950 +125,6 @@
   }
 }
 
-class JsClosedWorldBuilder {
-  final JsKernelToElementMap _elementMap;
-  final Map<ClassEntity, ClassHierarchyNode> _classHierarchyNodes =
-      new ClassHierarchyNodesMap();
-  final Map<ClassEntity, ClassSet> _classSets = <ClassEntity, ClassSet>{};
-  final GlobalLocalsMap _globalLocalsMap;
-  final ClosureDataBuilder _closureDataBuilder;
-  final CompilerOptions _options;
-  final AbstractValueStrategy _abstractValueStrategy;
-
-  JsClosedWorldBuilder(this._elementMap, this._globalLocalsMap,
-      this._closureDataBuilder, this._options, this._abstractValueStrategy);
-
-  ElementEnvironment get _elementEnvironment => _elementMap.elementEnvironment;
-  CommonElements get _commonElements => _elementMap.commonElements;
-
-  JsClosedWorld _convertClosedWorld(
-      KClosedWorld closedWorld,
-      Map<MemberEntity, ScopeModel> closureModels,
-      OutputUnitData kOutputUnitData) {
-    JsToFrontendMap map = new JsToFrontendMapImpl(_elementMap);
-
-    BackendUsage backendUsage =
-        _convertBackendUsage(map, closedWorld.backendUsage);
-    NativeData nativeData = _convertNativeData(map, closedWorld.nativeData);
-    _elementMap.nativeBasicData = nativeData;
-    InterceptorData interceptorData =
-        _convertInterceptorData(map, nativeData, closedWorld.interceptorData);
-
-    Set<ClassEntity> implementedClasses = new Set<ClassEntity>();
-
-    /// Converts [node] from the frontend world to the corresponding
-    /// [ClassHierarchyNode] for the backend world.
-    ClassHierarchyNode convertClassHierarchyNode(ClassHierarchyNode node) {
-      ClassEntity cls = map.toBackendClass(node.cls);
-      if (closedWorld.isImplemented(node.cls)) {
-        implementedClasses.add(cls);
-      }
-      ClassHierarchyNode newNode = _classHierarchyNodes.putIfAbsent(cls, () {
-        ClassHierarchyNode parentNode;
-        if (node.parentNode != null) {
-          parentNode = convertClassHierarchyNode(node.parentNode);
-        }
-        return new ClassHierarchyNode(parentNode, cls, node.hierarchyDepth);
-      });
-      newNode.isAbstractlyInstantiated = node.isAbstractlyInstantiated;
-      newNode.isDirectlyInstantiated = node.isDirectlyInstantiated;
-      return newNode;
-    }
-
-    /// Converts [classSet] from the frontend world to the corresponding
-    /// [ClassSet] for the backend world.
-    ClassSet convertClassSet(ClassSet classSet) {
-      ClassEntity cls = map.toBackendClass(classSet.cls);
-      return _classSets.putIfAbsent(cls, () {
-        ClassHierarchyNode newNode = convertClassHierarchyNode(classSet.node);
-        ClassSet newClassSet = new ClassSet(newNode);
-        for (ClassHierarchyNode subtype in classSet.subtypeNodes) {
-          ClassHierarchyNode newSubtype = convertClassHierarchyNode(subtype);
-          newClassSet.addSubtype(newSubtype);
-        }
-        return newClassSet;
-      });
-    }
-
-    closedWorld.classHierarchy
-        .getClassHierarchyNode(closedWorld.commonElements.objectClass)
-        .forEachSubclass((ClassEntity cls) {
-      convertClassSet(closedWorld.classHierarchy.getClassSet(cls));
-    }, ClassHierarchyNode.ALL);
-
-    Set<MemberEntity> liveInstanceMembers =
-        map.toBackendMemberSet(closedWorld.liveInstanceMembers);
-
-    Map<ClassEntity, Set<ClassEntity>> mixinUses =
-        map.toBackendClassMap(closedWorld.mixinUses, map.toBackendClassSet);
-
-    Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses =
-        map.toBackendClassMap(
-            closedWorld.typesImplementedBySubclasses, map.toBackendClassSet);
-
-    Iterable<MemberEntity> assignedInstanceMembers =
-        map.toBackendMemberSet(closedWorld.assignedInstanceMembers);
-
-    Iterable<ClassEntity> liveNativeClasses =
-        map.toBackendClassSet(closedWorld.liveNativeClasses);
-
-    Iterable<MemberEntity> processedMembers =
-        map.toBackendMemberSet(closedWorld.processedMembers);
-
-    RuntimeTypesNeed rtiNeed;
-
-    List<FunctionEntity> callMethods = <FunctionEntity>[];
-    ClosureData closureData;
-    if (_options.disableRtiOptimization) {
-      rtiNeed = new TrivialRuntimeTypesNeed();
-      closureData = _closureDataBuilder.createClosureEntities(
-          this,
-          map.toBackendMemberMap(closureModels, identity),
-          const TrivialClosureRtiNeed(),
-          callMethods);
-    } else {
-      RuntimeTypesNeedImpl kernelRtiNeed = closedWorld.rtiNeed;
-      Set<ir.Node> localFunctionsNodesNeedingSignature = new Set<ir.Node>();
-      for (KLocalFunction localFunction
-          in kernelRtiNeed.localFunctionsNeedingSignature) {
-        ir.Node node = localFunction.node;
-        assert(node is ir.FunctionDeclaration || node is ir.FunctionExpression,
-            "Unexpected local function node: $node");
-        localFunctionsNodesNeedingSignature.add(node);
-      }
-      Set<ir.Node> localFunctionsNodesNeedingTypeArguments = new Set<ir.Node>();
-      for (KLocalFunction localFunction
-          in kernelRtiNeed.localFunctionsNeedingTypeArguments) {
-        ir.Node node = localFunction.node;
-        assert(node is ir.FunctionDeclaration || node is ir.FunctionExpression,
-            "Unexpected local function node: $node");
-        localFunctionsNodesNeedingTypeArguments.add(node);
-      }
-
-      RuntimeTypesNeedImpl jRtiNeed =
-          _convertRuntimeTypesNeed(map, backendUsage, kernelRtiNeed);
-      closureData = _closureDataBuilder.createClosureEntities(
-          this,
-          map.toBackendMemberMap(closureModels, identity),
-          new JsClosureRtiNeed(
-              jRtiNeed,
-              localFunctionsNodesNeedingTypeArguments,
-              localFunctionsNodesNeedingSignature),
-          callMethods);
-
-      List<FunctionEntity> callMethodsNeedingSignature = <FunctionEntity>[];
-      for (ir.Node node in localFunctionsNodesNeedingSignature) {
-        callMethodsNeedingSignature
-            .add(closureData.getClosureInfo(node).callMethod);
-      }
-      List<FunctionEntity> callMethodsNeedingTypeArguments = <FunctionEntity>[];
-      for (ir.Node node in localFunctionsNodesNeedingTypeArguments) {
-        callMethodsNeedingTypeArguments
-            .add(closureData.getClosureInfo(node).callMethod);
-      }
-      jRtiNeed.methodsNeedingSignature.addAll(callMethodsNeedingSignature);
-      jRtiNeed.methodsNeedingTypeArguments
-          .addAll(callMethodsNeedingTypeArguments);
-
-      rtiNeed = jRtiNeed;
-    }
-
-    NoSuchMethodDataImpl oldNoSuchMethodData = closedWorld.noSuchMethodData;
-    NoSuchMethodData noSuchMethodData = new NoSuchMethodDataImpl(
-        map.toBackendFunctionSet(oldNoSuchMethodData.throwingImpls),
-        map.toBackendFunctionSet(oldNoSuchMethodData.otherImpls),
-        map.toBackendFunctionSet(oldNoSuchMethodData.forwardingSyntaxImpls));
-
-    JAllocatorAnalysis allocatorAnalysis =
-        JAllocatorAnalysis.from(closedWorld.allocatorAnalysis, map, _options);
-
-    AnnotationsData annotationsData = new AnnotationsDataImpl(
-        map.toBackendFunctionSet(
-            closedWorld.annotationsData.nonInlinableFunctions),
-        map.toBackendFunctionSet(
-            closedWorld.annotationsData.tryInlineFunctions),
-        map.toBackendFunctionSet(
-            closedWorld.annotationsData.cannotThrowFunctions),
-        map.toBackendFunctionSet(
-            closedWorld.annotationsData.sideEffectFreeFunctions),
-        map.toBackendMemberSet(
-            closedWorld.annotationsData.trustTypeAnnotationsMembers),
-        map.toBackendMemberSet(
-            closedWorld.annotationsData.assumeDynamicMembers));
-
-    OutputUnitData outputUnitData =
-        _convertOutputUnitData(map, kOutputUnitData, closureData);
-
-    return new JsClosedWorld(_elementMap,
-        backendUsage: backendUsage,
-        noSuchMethodData: noSuchMethodData,
-        nativeData: nativeData,
-        interceptorData: interceptorData,
-        rtiNeed: rtiNeed,
-        classHierarchy: new ClassHierarchyImpl(
-            _elementMap.commonElements, _classHierarchyNodes, _classSets),
-        implementedClasses: implementedClasses,
-        liveNativeClasses: liveNativeClasses,
-        // TODO(johnniwinther): Include the call method when we can also
-        // represent the synthesized call methods for static and instance method
-        // closurizations.
-        liveInstanceMembers: liveInstanceMembers /*..addAll(callMethods)*/,
-        assignedInstanceMembers: assignedInstanceMembers,
-        processedMembers: processedMembers,
-        mixinUses: mixinUses,
-        typesImplementedBySubclasses: typesImplementedBySubclasses,
-        abstractValueStrategy: _abstractValueStrategy,
-        allocatorAnalysis: allocatorAnalysis,
-        annotationsData: annotationsData,
-        globalLocalsMap: _globalLocalsMap,
-        closureDataLookup: closureData,
-        outputUnitData: outputUnitData);
-  }
-
-  BackendUsage _convertBackendUsage(
-      JsToFrontendMap map, BackendUsageImpl backendUsage) {
-    Set<FunctionEntity> globalFunctionDependencies =
-        map.toBackendFunctionSet(backendUsage.globalFunctionDependencies);
-    Set<ClassEntity> globalClassDependencies =
-        map.toBackendClassSet(backendUsage.globalClassDependencies);
-    Set<FunctionEntity> helperFunctionsUsed =
-        map.toBackendFunctionSet(backendUsage.helperFunctionsUsed);
-    Set<ClassEntity> helperClassesUsed =
-        map.toBackendClassSet(backendUsage.helperClassesUsed);
-    Set<RuntimeTypeUse> runtimeTypeUses =
-        backendUsage.runtimeTypeUses.map((RuntimeTypeUse runtimeTypeUse) {
-      return new RuntimeTypeUse(
-          runtimeTypeUse.kind,
-          map.toBackendType(runtimeTypeUse.receiverType),
-          map.toBackendType(runtimeTypeUse.argumentType));
-    }).toSet();
-
-    return new BackendUsageImpl(
-        globalFunctionDependencies: globalFunctionDependencies,
-        globalClassDependencies: globalClassDependencies,
-        helperFunctionsUsed: helperFunctionsUsed,
-        helperClassesUsed: helperClassesUsed,
-        needToInitializeIsolateAffinityTag:
-            backendUsage.needToInitializeIsolateAffinityTag,
-        needToInitializeDispatchProperty:
-            backendUsage.needToInitializeDispatchProperty,
-        requiresPreamble: backendUsage.requiresPreamble,
-        runtimeTypeUses: runtimeTypeUses,
-        isFunctionApplyUsed: backendUsage.isFunctionApplyUsed,
-        isMirrorsUsed: backendUsage.isMirrorsUsed,
-        isNoSuchMethodUsed: backendUsage.isNoSuchMethodUsed);
-  }
-
-  NativeBasicData _convertNativeBasicData(
-      JsToFrontendMap map, NativeBasicDataImpl nativeBasicData) {
-    Map<ClassEntity, NativeClassTag> nativeClassTagInfo =
-        <ClassEntity, NativeClassTag>{};
-    nativeBasicData.nativeClassTagInfo
-        .forEach((ClassEntity cls, NativeClassTag tag) {
-      nativeClassTagInfo[map.toBackendClass(cls)] = tag;
-    });
-    Map<LibraryEntity, String> jsInteropLibraries =
-        map.toBackendLibraryMap(nativeBasicData.jsInteropLibraries, identity);
-    Map<ClassEntity, String> jsInteropClasses =
-        map.toBackendClassMap(nativeBasicData.jsInteropClasses, identity);
-    Set<ClassEntity> anonymousJsInteropClasses =
-        map.toBackendClassSet(nativeBasicData.anonymousJsInteropClasses);
-    Map<MemberEntity, String> jsInteropMembers =
-        map.toBackendMemberMap(nativeBasicData.jsInteropMembers, identity);
-    return new NativeBasicDataImpl(
-        _elementEnvironment,
-        nativeClassTagInfo,
-        jsInteropLibraries,
-        jsInteropClasses,
-        anonymousJsInteropClasses,
-        jsInteropMembers);
-  }
-
-  NativeData _convertNativeData(
-      JsToFrontendMap map, NativeDataImpl nativeData) {
-    convertNativeBehaviorType(type) {
-      if (type is DartType) return map.toBackendType(type);
-      assert(type is SpecialType);
-      return type;
-    }
-
-    NativeBehavior convertNativeBehavior(NativeBehavior behavior) {
-      NativeBehavior newBehavior = new NativeBehavior();
-
-      for (dynamic type in behavior.typesReturned) {
-        newBehavior.typesReturned.add(convertNativeBehaviorType(type));
-      }
-      for (dynamic type in behavior.typesInstantiated) {
-        newBehavior.typesInstantiated.add(convertNativeBehaviorType(type));
-      }
-
-      newBehavior.codeTemplateText = behavior.codeTemplateText;
-      newBehavior.codeTemplate = behavior.codeTemplate;
-      newBehavior.throwBehavior = behavior.throwBehavior;
-      newBehavior.isAllocation = behavior.isAllocation;
-      newBehavior.useGvn = behavior.useGvn;
-      return newBehavior;
-    }
-
-    NativeBasicData nativeBasicData = _convertNativeBasicData(map, nativeData);
-
-    Map<MemberEntity, String> nativeMemberName =
-        map.toBackendMemberMap(nativeData.nativeMemberName, identity);
-    Map<FunctionEntity, NativeBehavior> nativeMethodBehavior =
-        <FunctionEntity, NativeBehavior>{};
-    nativeData.nativeMethodBehavior
-        .forEach((FunctionEntity method, NativeBehavior behavior) {
-      FunctionEntity backendMethod = map.toBackendMember(method);
-      if (backendMethod != null) {
-        // If [method] isn't used it doesn't have a corresponding backend
-        // method.
-        nativeMethodBehavior[backendMethod] = convertNativeBehavior(behavior);
-      }
-    });
-    Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior =
-        map.toBackendMemberMap(
-            nativeData.nativeFieldLoadBehavior, convertNativeBehavior);
-    Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior =
-        map.toBackendMemberMap(
-            nativeData.nativeFieldStoreBehavior, convertNativeBehavior);
-    Map<LibraryEntity, String> jsInteropLibraryNames =
-        map.toBackendLibraryMap(nativeData.jsInteropLibraries, identity);
-    Set<ClassEntity> anonymousJsInteropClasses =
-        map.toBackendClassSet(nativeData.anonymousJsInteropClasses);
-    Map<ClassEntity, String> jsInteropClassNames =
-        map.toBackendClassMap(nativeData.jsInteropClasses, identity);
-    Map<MemberEntity, String> jsInteropMemberNames =
-        map.toBackendMemberMap(nativeData.jsInteropMembers, identity);
-
-    return new NativeDataImpl(
-        nativeBasicData,
-        nativeMemberName,
-        nativeMethodBehavior,
-        nativeFieldLoadBehavior,
-        nativeFieldStoreBehavior,
-        jsInteropLibraryNames,
-        anonymousJsInteropClasses,
-        jsInteropClassNames,
-        jsInteropMemberNames);
-  }
-
-  InterceptorData _convertInterceptorData(JsToFrontendMap map,
-      NativeData nativeData, InterceptorDataImpl interceptorData) {
-    Map<String, Set<MemberEntity>> interceptedMembers =
-        <String, Set<MemberEntity>>{};
-    interceptorData.interceptedMembers
-        .forEach((String name, Set<MemberEntity> members) {
-      interceptedMembers[name] = map.toBackendMemberSet(members);
-    });
-    return new InterceptorDataImpl(
-        nativeData,
-        _commonElements,
-        interceptedMembers,
-        map.toBackendClassSet(interceptorData.interceptedClasses),
-        map.toBackendClassSet(
-            interceptorData.classesMixedIntoInterceptedClasses));
-  }
-
-  RuntimeTypesNeed _convertRuntimeTypesNeed(JsToFrontendMap map,
-      BackendUsage backendUsage, RuntimeTypesNeedImpl rtiNeed) {
-    Set<ClassEntity> classesNeedingTypeArguments =
-        map.toBackendClassSet(rtiNeed.classesNeedingTypeArguments);
-    Set<FunctionEntity> methodsNeedingTypeArguments =
-        map.toBackendFunctionSet(rtiNeed.methodsNeedingTypeArguments);
-    Set<FunctionEntity> methodsNeedingSignature =
-        map.toBackendFunctionSet(rtiNeed.methodsNeedingSignature);
-    Set<Selector> selectorsNeedingTypeArguments =
-        rtiNeed.selectorsNeedingTypeArguments.map((Selector selector) {
-      if (selector.memberName.isPrivate) {
-        return new Selector(
-            selector.kind,
-            new PrivateName(selector.memberName.text,
-                map.toBackendLibrary(selector.memberName.library),
-                isSetter: selector.memberName.isSetter),
-            selector.callStructure);
-      }
-      return selector;
-    }).toSet();
-    return new RuntimeTypesNeedImpl(
-        _elementEnvironment,
-        classesNeedingTypeArguments,
-        methodsNeedingSignature,
-        methodsNeedingTypeArguments,
-        null,
-        null,
-        selectorsNeedingTypeArguments,
-        rtiNeed.instantiationsNeedingTypeArguments);
-  }
-
-  /// Construct a closure class and set up the necessary class inference
-  /// hierarchy.
-  KernelClosureClassInfo buildClosureClass(
-      MemberEntity member,
-      ir.FunctionNode originalClosureFunctionNode,
-      JLibrary enclosingLibrary,
-      Map<Local, JRecordField> boxedVariables,
-      KernelScopeInfo info,
-      KernelToLocalsMap localsMap,
-      {bool createSignatureMethod}) {
-    ClassEntity superclass = _commonElements.closureClass;
-
-    KernelClosureClassInfo closureClassInfo = _elementMap.constructClosureClass(
-        member,
-        originalClosureFunctionNode,
-        enclosingLibrary,
-        boxedVariables,
-        info,
-        localsMap,
-        new InterfaceType(superclass, const []),
-        createSignatureMethod: createSignatureMethod);
-
-    // Tell the hierarchy that this is the super class. then we can use
-    // .getSupertypes(class)
-    ClassHierarchyNode parentNode = _classHierarchyNodes[superclass];
-    ClassHierarchyNode node = new ClassHierarchyNode(parentNode,
-        closureClassInfo.closureClassEntity, parentNode.hierarchyDepth + 1);
-    _classHierarchyNodes[closureClassInfo.closureClassEntity] = node;
-    _classSets[closureClassInfo.closureClassEntity] = new ClassSet(node);
-    node.isDirectlyInstantiated = true;
-
-    return closureClassInfo;
-  }
-
-  OutputUnitData _convertOutputUnitData(JsToFrontendMapImpl map,
-      OutputUnitData data, ClosureData closureDataLookup) {
-    Entity toBackendEntity(Entity entity) {
-      if (entity is ClassEntity) return map.toBackendClass(entity);
-      if (entity is MemberEntity) return map.toBackendMember(entity);
-      if (entity is TypedefEntity) return map.toBackendTypedef(entity);
-      if (entity is TypeVariableEntity) {
-        return map.toBackendTypeVariable(entity);
-      }
-      assert(
-          entity is LibraryEntity, 'unexpected entity ${entity.runtimeType}');
-      return map.toBackendLibrary(entity);
-    }
-
-    // Convert front-end maps containing K-class and K-local function keys to a
-    // backend map using J-classes as keys.
-    Map<ClassEntity, OutputUnit> convertClassMap(
-        Map<ClassEntity, OutputUnit> classMap,
-        Map<Local, OutputUnit> localFunctionMap) {
-      var result = <ClassEntity, OutputUnit>{};
-      classMap.forEach((ClassEntity entity, OutputUnit unit) {
-        ClassEntity backendEntity = toBackendEntity(entity);
-        if (backendEntity != null) {
-          // If [entity] isn't used it doesn't have a corresponding backend
-          // entity.
-          result[backendEntity] = unit;
-        }
-      });
-      localFunctionMap.forEach((Local entity, OutputUnit unit) {
-        // Ensure closure classes are included in the output unit corresponding
-        // to the local function.
-        if (entity is KLocalFunction) {
-          var closureInfo = closureDataLookup.getClosureInfo(entity.node);
-          result[closureInfo.closureClassEntity] = unit;
-        }
-      });
-      return result;
-    }
-
-    // Convert front-end maps containing K-member and K-local function keys to
-    // a backend map using J-members as keys.
-    Map<MemberEntity, OutputUnit> convertMemberMap(
-        Map<MemberEntity, OutputUnit> memberMap,
-        Map<Local, OutputUnit> localFunctionMap) {
-      var result = <MemberEntity, OutputUnit>{};
-      memberMap.forEach((MemberEntity entity, OutputUnit unit) {
-        MemberEntity backendEntity = toBackendEntity(entity);
-        if (backendEntity != null) {
-          // If [entity] isn't used it doesn't have a corresponding backend
-          // entity.
-          result[backendEntity] = unit;
-        }
-      });
-      localFunctionMap.forEach((Local entity, OutputUnit unit) {
-        // Ensure closure call-methods are included in the output unit
-        // corresponding to the local function.
-        if (entity is KLocalFunction) {
-          var closureInfo = closureDataLookup.getClosureInfo(entity.node);
-          result[closureInfo.callMethod] = unit;
-        }
-      });
-      return result;
-    }
-
-    ConstantValue toBackendConstant(ConstantValue constant) {
-      return constant.accept(new ConstantConverter(toBackendEntity), null);
-    }
-
-    return new OutputUnitData.from(
-        data,
-        convertClassMap,
-        convertMemberMap,
-        (m) => convertMap<ConstantValue, OutputUnit>(
-            m, toBackendConstant, (v) => v));
-  }
-}
-
-class JsClosedWorld extends ClosedWorldBase {
-  static const String tag = 'closed-world';
-
-  final JsKernelToElementMap elementMap;
-  final RuntimeTypesNeed rtiNeed;
-  AbstractValueDomain _abstractValueDomain;
-  final JAllocatorAnalysis allocatorAnalysis;
-  final AnnotationsData annotationsData;
-  final GlobalLocalsMap globalLocalsMap;
-  final ClosureData closureDataLookup;
-  final OutputUnitData outputUnitData;
-  Sorter _sorter;
-
-  JsClosedWorld(this.elementMap,
-      {ConstantSystem constantSystem,
-      NativeData nativeData,
-      InterceptorData interceptorData,
-      BackendUsage backendUsage,
-      this.rtiNeed,
-      this.allocatorAnalysis,
-      NoSuchMethodData noSuchMethodData,
-      Iterable<ClassEntity> implementedClasses,
-      Iterable<ClassEntity> liveNativeClasses,
-      Iterable<MemberEntity> liveInstanceMembers,
-      Iterable<MemberEntity> assignedInstanceMembers,
-      Iterable<MemberEntity> processedMembers,
-      Map<ClassEntity, Set<ClassEntity>> mixinUses,
-      Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses,
-      ClassHierarchy classHierarchy,
-      AbstractValueStrategy abstractValueStrategy,
-      this.annotationsData,
-      this.globalLocalsMap,
-      this.closureDataLookup,
-      this.outputUnitData})
-      : super(
-            elementMap.elementEnvironment,
-            elementMap.types,
-            elementMap.commonElements,
-            JavaScriptConstantSystem.only,
-            nativeData,
-            interceptorData,
-            backendUsage,
-            noSuchMethodData,
-            implementedClasses,
-            liveNativeClasses,
-            liveInstanceMembers,
-            assignedInstanceMembers,
-            processedMembers,
-            mixinUses,
-            typesImplementedBySubclasses,
-            classHierarchy) {
-    _abstractValueDomain = abstractValueStrategy.createDomain(this);
-  }
-
-  /// Deserializes a [JsClosedWorld] object from [source].
-  factory JsClosedWorld.readFromDataSource(
-      CompilerOptions options,
-      DiagnosticReporter reporter,
-      Environment environment,
-      AbstractValueStrategy abstractValueStrategy,
-      ir.Component component,
-      DataSource source) {
-    source.begin(tag);
-
-    JsKernelToElementMap elementMap =
-        new JsKernelToElementMap.readFromDataSource(
-            options, reporter, environment, component, source);
-    GlobalLocalsMap globalLocalsMap =
-        new GlobalLocalsMap.readFromDataSource(source);
-    source.registerLocalLookup(new LocalLookupImpl(globalLocalsMap));
-    ClassHierarchy classHierarchy = new ClassHierarchy.readFromDataSource(
-        source, elementMap.commonElements);
-    NativeData nativeData = new NativeData.readFromDataSource(
-        source, elementMap.elementEnvironment);
-    elementMap.nativeBasicData = nativeData;
-    InterceptorData interceptorData = new InterceptorData.readFromDataSource(
-        source, nativeData, elementMap.commonElements);
-    BackendUsage backendUsage = new BackendUsage.readFromDataSource(source);
-    RuntimeTypesNeed rtiNeed = new RuntimeTypesNeed.readFromDataSource(
-        source, elementMap.elementEnvironment);
-    JAllocatorAnalysis allocatorAnalysis =
-        new JAllocatorAnalysis.readFromDataSource(source, options);
-    NoSuchMethodData noSuchMethodData =
-        new NoSuchMethodData.readFromDataSource(source);
-
-    Set<ClassEntity> implementedClasses = source.readClasses().toSet();
-    Iterable<ClassEntity> liveNativeClasses = source.readClasses();
-    Iterable<MemberEntity> liveInstanceMembers = source.readMembers();
-    Iterable<MemberEntity> assignedInstanceMembers = source.readMembers();
-    Iterable<MemberEntity> processedMembers = source.readMembers();
-    Map<ClassEntity, Set<ClassEntity>> mixinUses =
-        source.readClassMap(() => source.readClasses().toSet());
-    Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses =
-        source.readClassMap(() => source.readClasses().toSet());
-
-    AnnotationsData annotationsData =
-        new AnnotationsData.readFromDataSource(source);
-
-    ClosureData closureData =
-        new ClosureData.readFromDataSource(elementMap, source);
-
-    OutputUnitData outputUnitData =
-        new OutputUnitData.readFromDataSource(source);
-
-    source.end(tag);
-
-    return new JsClosedWorld(elementMap,
-        nativeData: nativeData,
-        interceptorData: interceptorData,
-        backendUsage: backendUsage,
-        rtiNeed: rtiNeed,
-        allocatorAnalysis: allocatorAnalysis,
-        noSuchMethodData: noSuchMethodData,
-        implementedClasses: implementedClasses,
-        liveNativeClasses: liveNativeClasses,
-        liveInstanceMembers: liveInstanceMembers,
-        assignedInstanceMembers: assignedInstanceMembers,
-        processedMembers: processedMembers,
-        mixinUses: mixinUses,
-        typesImplementedBySubclasses: typesImplementedBySubclasses,
-        classHierarchy: classHierarchy,
-        abstractValueStrategy: abstractValueStrategy,
-        annotationsData: annotationsData,
-        globalLocalsMap: globalLocalsMap,
-        closureDataLookup: closureData,
-        outputUnitData: outputUnitData);
-  }
-
-  /// Serializes this [JsClosedWorld] to [sink].
-  void writeToDataSink(DataSink sink) {
-    sink.begin(tag);
-    elementMap.writeToDataSink(sink);
-    globalLocalsMap.writeToDataSink(sink);
-
-    classHierarchy.writeToDataSink(sink);
-    nativeData.writeToDataSink(sink);
-    interceptorData.writeToDataSink(sink);
-    backendUsage.writeToDataSink(sink);
-    rtiNeed.writeToDataSink(sink);
-    allocatorAnalysis.writeToDataSink(sink);
-    noSuchMethodData.writeToDataSink(sink);
-    sink.writeClasses(implementedClasses);
-    sink.writeClasses(liveNativeClasses);
-    sink.writeMembers(liveInstanceMembers);
-    sink.writeMembers(assignedInstanceMembers);
-    sink.writeMembers(processedMembers);
-    sink.writeClassMap(
-        mixinUses, (Set<ClassEntity> set) => sink.writeClasses(set));
-    sink.writeClassMap(typesImplementedBySubclasses,
-        (Set<ClassEntity> set) => sink.writeClasses(set));
-    annotationsData.writeToDataSink(sink);
-    closureDataLookup.writeToDataSink(sink);
-    outputUnitData.writeToDataSink(sink);
-    sink.end(tag);
-  }
-
-  @override
-  Sorter get sorter {
-    return _sorter ??= new KernelSorter(elementMap);
-  }
-
-  @override
-  AbstractValueDomain get abstractValueDomain {
-    return _abstractValueDomain;
-  }
-
-  @override
-  bool hasElementIn(ClassEntity cls, Selector selector, Entity element) {
-    while (cls != null) {
-      MemberEntity member = elementEnvironment.lookupLocalClassMember(
-          cls, selector.name,
-          setter: selector.isSetter);
-      if (member != null &&
-          !member.isAbstract &&
-          (!selector.memberName.isPrivate ||
-              member.library == selector.library)) {
-        return member == element;
-      }
-      cls = elementEnvironment.getSuperClass(cls);
-    }
-    return false;
-  }
-
-  @override
-  bool hasConcreteMatch(ClassEntity cls, Selector selector,
-      {ClassEntity stopAtSuperclass}) {
-    assert(classHierarchy.isInstantiated(cls),
-        failedAt(cls, '$cls has not been instantiated.'));
-    MemberEntity element = elementEnvironment
-        .lookupClassMember(cls, selector.name, setter: selector.isSetter);
-    if (element == null) return false;
-
-    if (element.isAbstract) {
-      ClassEntity enclosingClass = element.enclosingClass;
-      return hasConcreteMatch(
-          elementEnvironment.getSuperClass(enclosingClass), selector);
-    }
-    return selector.appliesUntyped(element);
-  }
-
-  @override
-  bool isNamedMixinApplication(ClassEntity cls) {
-    return elementMap.elementEnvironment.isMixinApplication(cls) &&
-        !elementMap.elementEnvironment.isUnnamedMixinApplication(cls);
-  }
-
-  @override
-  ClassEntity getAppliedMixin(ClassEntity cls) {
-    return elementMap.getAppliedMixin(cls);
-  }
-
-  @override
-  Iterable<ClassEntity> getInterfaces(ClassEntity cls) {
-    return elementMap.getInterfaces(cls).map((t) => t.element);
-  }
-
-  @override
-  ClassEntity getSuperClass(ClassEntity cls) {
-    return elementMap.getSuperType(cls)?.element;
-  }
-
-  @override
-  int getHierarchyDepth(ClassEntity cls) {
-    return elementMap.getHierarchyDepth(cls);
-  }
-
-  @override
-  OrderedTypeSet getOrderedTypeSet(ClassEntity cls) {
-    return elementMap.getOrderedTypeSet(cls);
-  }
-}
-
-class ConstantConverter implements ConstantValueVisitor<ConstantValue, Null> {
-  final Entity Function(Entity) toBackendEntity;
-  final TypeConverter typeConverter;
-
-  ConstantConverter(this.toBackendEntity)
-      : typeConverter = new TypeConverter(toBackendEntity);
-
-  ConstantValue visitNull(NullConstantValue constant, _) => constant;
-  ConstantValue visitInt(IntConstantValue constant, _) => constant;
-  ConstantValue visitDouble(DoubleConstantValue constant, _) => constant;
-  ConstantValue visitBool(BoolConstantValue constant, _) => constant;
-  ConstantValue visitString(StringConstantValue constant, _) => constant;
-  ConstantValue visitSynthetic(SyntheticConstantValue constant, _) => constant;
-  ConstantValue visitNonConstant(NonConstantValue constant, _) => constant;
-
-  ConstantValue visitFunction(FunctionConstantValue constant, _) {
-    return new FunctionConstantValue(toBackendEntity(constant.element),
-        typeConverter.convert(constant.type));
-  }
-
-  ConstantValue visitList(ListConstantValue constant, _) {
-    var type = typeConverter.convert(constant.type);
-    List<ConstantValue> entries = _handleValues(constant.entries);
-    if (identical(entries, constant.entries) && type == constant.type) {
-      return constant;
-    }
-    return new ListConstantValue(type, entries);
-  }
-
-  ConstantValue visitMap(MapConstantValue constant, _) {
-    var type = typeConverter.convert(constant.type);
-    List<ConstantValue> keys = _handleValues(constant.keys);
-    List<ConstantValue> values = _handleValues(constant.values);
-    if (identical(keys, constant.keys) &&
-        identical(values, constant.values) &&
-        type == constant.type) {
-      return constant;
-    }
-    return new MapConstantValue(type, keys, values);
-  }
-
-  ConstantValue visitConstructed(ConstructedConstantValue constant, _) {
-    var type = typeConverter.convert(constant.type);
-    if (type == constant.type && constant.fields.isEmpty) {
-      return constant;
-    }
-    var fields = <FieldEntity, ConstantValue>{};
-    constant.fields.forEach((f, v) {
-      fields[toBackendEntity(f)] = v.accept(this, null);
-    });
-    return new ConstructedConstantValue(type, fields);
-  }
-
-  ConstantValue visitType(TypeConstantValue constant, _) {
-    var type = typeConverter.convert(constant.type);
-    var representedType = typeConverter.convert(constant.representedType);
-    if (type == constant.type && representedType == constant.representedType) {
-      return constant;
-    }
-    return new TypeConstantValue(representedType, type);
-  }
-
-  ConstantValue visitInterceptor(InterceptorConstantValue constant, _) {
-    return new InterceptorConstantValue(toBackendEntity(constant.cls));
-  }
-
-  ConstantValue visitDeferred(DeferredConstantValue constant, _) {
-    throw new UnsupportedError("DeferredConstantValue with --use-kernel");
-  }
-
-  ConstantValue visitDeferredGlobal(DeferredGlobalConstantValue constant, _) {
-    var referenced = constant.referenced.accept(this, null);
-    if (referenced == constant.referenced) return constant;
-    return new DeferredGlobalConstantValue(referenced, constant.unit);
-  }
-
-  ConstantValue visitInstantiation(InstantiationConstantValue constant, _) {
-    ConstantValue function = constant.function.accept(this, null);
-    List<DartType> typeArguments =
-        typeConverter.convertTypes(constant.typeArguments);
-    return new InstantiationConstantValue(typeArguments, function);
-  }
-
-  List<ConstantValue> _handleValues(List<ConstantValue> values) {
-    List<ConstantValue> result;
-    for (int i = 0; i < values.length; i++) {
-      var value = values[i];
-      var newValue = value.accept(this, null);
-      if (newValue != value && result == null) {
-        result = values.sublist(0, i).toList();
-      }
-      result?.add(newValue);
-    }
-    return result ?? values;
-  }
-}
-
-class TypeConverter extends DartTypeVisitor<DartType, Null> {
-  final Entity Function(Entity) toBackendEntity;
-  TypeConverter(this.toBackendEntity);
-
-  Map<FunctionTypeVariable, FunctionTypeVariable> _functionTypeVariables =
-      <FunctionTypeVariable, FunctionTypeVariable>{};
-
-  DartType convert(DartType type) => type.accept(this, null);
-
-  List<DartType> convertTypes(List<DartType> types) => _visitList(types);
-
-  DartType visitVoidType(VoidType type, _) => type;
-  DartType visitDynamicType(DynamicType type, _) => type;
-
-  DartType visitTypeVariableType(TypeVariableType type, _) {
-    return new TypeVariableType(toBackendEntity(type.element));
-  }
-
-  DartType visitFunctionTypeVariable(FunctionTypeVariable type, _) {
-    return _functionTypeVariables[type];
-  }
-
-  DartType visitFunctionType(FunctionType type, _) {
-    var returnType = type.returnType.accept(this, null);
-    var parameterTypes = _visitList(type.parameterTypes);
-    var optionalParameterTypes = _visitList(type.optionalParameterTypes);
-    var namedParameterTypes = _visitList(type.namedParameterTypes);
-    List<FunctionTypeVariable> typeVariables = <FunctionTypeVariable>[];
-    for (FunctionTypeVariable typeVariable in type.typeVariables) {
-      typeVariables.add(_functionTypeVariables[typeVariable] =
-          new FunctionTypeVariable(typeVariable.index));
-    }
-    for (FunctionTypeVariable typeVariable in type.typeVariables) {
-      _functionTypeVariables[typeVariable].bound =
-          typeVariable.bound?.accept(this, null);
-    }
-    for (FunctionTypeVariable typeVariable in type.typeVariables) {
-      _functionTypeVariables.remove(typeVariable);
-    }
-    return new FunctionType(returnType, parameterTypes, optionalParameterTypes,
-        type.namedParameters, namedParameterTypes, typeVariables);
-  }
-
-  DartType visitInterfaceType(InterfaceType type, _) {
-    var element = toBackendEntity(type.element);
-    var args = _visitList(type.typeArguments);
-    return new InterfaceType(element, args);
-  }
-
-  DartType visitTypedefType(TypedefType type, _) {
-    var element = toBackendEntity(type.element);
-    var args = _visitList(type.typeArguments);
-    var unaliased = convert(type.unaliased);
-    return new TypedefType(element, args, unaliased);
-  }
-
-  List<DartType> _visitList(List<DartType> list) =>
-      list.map<DartType>((t) => t.accept(this, null)).toList();
-}
-
-class TrivialClosureRtiNeed implements ClosureRtiNeed {
-  const TrivialClosureRtiNeed();
-
-  @override
-  bool localFunctionNeedsSignature(ir.Node node) => true;
-
-  @override
-  bool classNeedsTypeArguments(ClassEntity cls) => true;
-
-  @override
-  bool methodNeedsTypeArguments(FunctionEntity method) => true;
-
-  @override
-  bool localFunctionNeedsTypeArguments(ir.Node node) => true;
-
-  @override
-  bool selectorNeedsTypeArguments(Selector selector) => true;
-
-  @override
-  bool methodNeedsSignature(MemberEntity method) => true;
-
-  @override
-  bool instantiationNeedsTypeArguments(
-          DartType functionType, int typeArgumentCount) =>
-      true;
-}
-
-class JsClosureRtiNeed implements ClosureRtiNeed {
-  final RuntimeTypesNeed rtiNeed;
-  final Set<ir.Node> localFunctionsNodesNeedingTypeArguments;
-  final Set<ir.Node> localFunctionsNodesNeedingSignature;
-
-  JsClosureRtiNeed(this.rtiNeed, this.localFunctionsNodesNeedingTypeArguments,
-      this.localFunctionsNodesNeedingSignature);
-
-  @override
-  bool localFunctionNeedsSignature(ir.Node node) {
-    assert(node is ir.FunctionDeclaration || node is ir.FunctionExpression);
-    return localFunctionsNodesNeedingSignature.contains(node);
-  }
-
-  @override
-  bool classNeedsTypeArguments(ClassEntity cls) =>
-      rtiNeed.classNeedsTypeArguments(cls);
-
-  @override
-  bool methodNeedsTypeArguments(FunctionEntity method) =>
-      rtiNeed.methodNeedsTypeArguments(method);
-
-  @override
-  bool localFunctionNeedsTypeArguments(ir.Node node) {
-    assert(node is ir.FunctionDeclaration || node is ir.FunctionExpression);
-    return localFunctionsNodesNeedingTypeArguments.contains(node);
-  }
-
-  @override
-  bool selectorNeedsTypeArguments(Selector selector) =>
-      rtiNeed.selectorNeedsTypeArguments(selector);
-
-  @override
-  bool methodNeedsSignature(MemberEntity method) =>
-      rtiNeed.methodNeedsSignature(method);
-
-  @override
-  bool instantiationNeedsTypeArguments(
-          DartType functionType, int typeArgumentCount) =>
-      rtiNeed.instantiationNeedsTypeArguments(functionType, typeArgumentCount);
-}
-
 class KernelCodegenWorkItemBuilder implements WorkItemBuilder {
   final JavaScriptBackend _backend;
   final JClosedWorld _closedWorld;
@@ -1206,9 +238,9 @@
     return _targetResults.typeOfSend(node);
   }
 
-  AbstractValue typeOfListLiteral(MemberEntity owner,
+  AbstractValue typeOfListLiteral(
       ir.ListLiteral listLiteral, AbstractValueDomain abstractValueDomain) {
-    return _resultOf(owner).typeOfListLiteral(listLiteral) ??
+    return _globalInferenceResults.typeOfListLiteral(listLiteral) ??
         abstractValueDomain.dynamicType;
   }
 
@@ -1255,109 +287,3 @@
     return AbstractValueFactory.fromNativeBehavior(nativeBehavior, closedWorld);
   }
 }
-
-class KernelSorter implements Sorter {
-  final JsToElementMap elementMap;
-
-  KernelSorter(this.elementMap);
-
-  int _compareLibraries(LibraryEntity a, LibraryEntity b) {
-    return utils.compareLibrariesUris(a.canonicalUri, b.canonicalUri);
-  }
-
-  int _compareSourceSpans(Entity entity1, SourceSpan sourceSpan1,
-      Entity entity2, SourceSpan sourceSpan2) {
-    int r = utils.compareSourceUris(sourceSpan1.uri, sourceSpan2.uri);
-    if (r != 0) return r;
-    return utils.compareEntities(
-        entity1, sourceSpan1.begin, null, entity2, sourceSpan2.begin, null);
-  }
-
-  @override
-  Iterable<LibraryEntity> sortLibraries(Iterable<LibraryEntity> libraries) {
-    return libraries.toList()..sort(_compareLibraries);
-  }
-
-  @override
-  Iterable<T> sortMembers<T extends MemberEntity>(Iterable<T> members) {
-    return members.toList()..sort(compareMembersByLocation);
-  }
-
-  @override
-  Iterable<ClassEntity> sortClasses(Iterable<ClassEntity> classes) {
-    List<ClassEntity> regularClasses = <ClassEntity>[];
-    List<ClassEntity> unnamedMixins = <ClassEntity>[];
-    for (ClassEntity cls in classes) {
-      if (elementMap.elementEnvironment.isUnnamedMixinApplication(cls)) {
-        unnamedMixins.add(cls);
-      } else {
-        regularClasses.add(cls);
-      }
-    }
-    List<ClassEntity> sorted = <ClassEntity>[];
-    regularClasses.sort(compareClassesByLocation);
-    sorted.addAll(regularClasses);
-    unnamedMixins.sort((a, b) {
-      int result = _compareLibraries(a.library, b.library);
-      if (result != 0) return result;
-      result = a.name.compareTo(b.name);
-      assert(result != 0,
-          failedAt(a, "Multiple mixins named ${a.name}: $a vs $b."));
-      return result;
-    });
-    sorted.addAll(unnamedMixins);
-    return sorted;
-  }
-
-  @override
-  Iterable<TypedefEntity> sortTypedefs(Iterable<TypedefEntity> typedefs) {
-    // TODO(redemption): Support this.
-    assert(typedefs.isEmpty);
-    return typedefs;
-  }
-
-  @override
-  int compareLibrariesByLocation(LibraryEntity a, LibraryEntity b) {
-    return _compareLibraries(a, b);
-  }
-
-  @override
-  int compareClassesByLocation(ClassEntity a, ClassEntity b) {
-    int r = _compareLibraries(a.library, b.library);
-    if (r != 0) return r;
-    ClassDefinition definition1 = elementMap.getClassDefinition(a);
-    ClassDefinition definition2 = elementMap.getClassDefinition(b);
-    return _compareSourceSpans(
-        a, definition1.location, b, definition2.location);
-  }
-
-  @override
-  int compareTypedefsByLocation(TypedefEntity a, TypedefEntity b) {
-    // TODO(redemption): Support this.
-    failedAt(a, 'KernelSorter.compareTypedefsByLocation unimplemented');
-    return 0;
-  }
-
-  @override
-  int compareMembersByLocation(MemberEntity a, MemberEntity b) {
-    int r = _compareLibraries(a.library, b.library);
-    if (r != 0) return r;
-    MemberDefinition definition1 = elementMap.getMemberDefinition(a);
-    MemberDefinition definition2 = elementMap.getMemberDefinition(b);
-    return _compareSourceSpans(
-        a, definition1.location, b, definition2.location);
-  }
-}
-
-/// [LocalLookup] implementation used to deserialize [JsClosedWorld].
-class LocalLookupImpl implements LocalLookup {
-  final GlobalLocalsMap _globalLocalsMap;
-
-  LocalLookupImpl(this._globalLocalsMap);
-
-  @override
-  Local getLocalByIndex(MemberEntity memberContext, int index) {
-    KernelToLocalsMapImpl map = _globalLocalsMap.getLocalsMap(memberContext);
-    return map.getLocalByIndex(index);
-  }
-}
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
new file mode 100644
index 0000000..59b621d
--- /dev/null
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -0,0 +1,644 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart' as ir;
+import 'package:front_end/src/api_unstable/dart2js.dart' show Link;
+
+import '../closure.dart';
+import '../common.dart';
+import '../common/names.dart';
+import '../common_elements.dart' show JCommonElements, JElementEnvironment;
+import '../constants/constant_system.dart';
+import '../deferred_load.dart';
+import '../diagnostics/diagnostic_listener.dart';
+import '../elements/entities.dart';
+import '../elements/entity_utils.dart' as utils;
+import '../elements/types.dart';
+import '../environment.dart';
+import '../js_emitter/sorter.dart';
+import '../js_backend/annotations.dart';
+import '../js_backend/allocator_analysis.dart';
+import '../js_backend/backend_usage.dart';
+import '../js_backend/constant_system_javascript.dart';
+import '../js_backend/interceptor_data.dart';
+import '../js_backend/native_data.dart';
+import '../js_backend/no_such_method_registry.dart';
+import '../js_backend/runtime_types.dart';
+import '../js_model/locals.dart';
+import '../ordered_typeset.dart';
+import '../options.dart';
+import '../serialization/serialization.dart';
+import '../types/abstract_value_domain.dart';
+import '../universe/class_hierarchy.dart';
+import '../universe/class_set.dart';
+import '../universe/function_set.dart' show FunctionSet;
+import '../universe/selector.dart';
+import '../world.dart';
+import 'element_map.dart';
+import 'element_map_impl.dart';
+import 'locals.dart';
+
+class JsClosedWorld implements JClosedWorld {
+  static const String tag = 'closed-world';
+
+  final NativeData nativeData;
+  final InterceptorData interceptorData;
+  final BackendUsage backendUsage;
+  final NoSuchMethodData noSuchMethodData;
+
+  FunctionSet _allFunctions;
+
+  final Map<ClassEntity, Set<ClassEntity>> mixinUses;
+  Map<ClassEntity, List<ClassEntity>> _liveMixinUses;
+
+  final Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses;
+
+  final Map<ClassEntity, Map<ClassEntity, bool>> _subtypeCoveredByCache =
+      <ClassEntity, Map<ClassEntity, bool>>{};
+
+  // TODO(johnniwinther): Can this be derived from [ClassSet]s?
+  final Set<ClassEntity> implementedClasses;
+
+  final Set<MemberEntity> liveInstanceMembers;
+
+  /// Members that are written either directly or through a setter selector.
+  final Set<MemberEntity> assignedInstanceMembers;
+
+  final Set<ClassEntity> liveNativeClasses;
+
+  final Set<MemberEntity> processedMembers;
+
+  final ClassHierarchy classHierarchy;
+
+  final JsKernelToElementMap elementMap;
+  final RuntimeTypesNeed rtiNeed;
+  AbstractValueDomain _abstractValueDomain;
+  final JAllocatorAnalysis allocatorAnalysis;
+  final AnnotationsData annotationsData;
+  final GlobalLocalsMap globalLocalsMap;
+  final ClosureData closureDataLookup;
+  final OutputUnitData outputUnitData;
+  Sorter _sorter;
+
+  JsClosedWorld(
+      this.elementMap,
+      this.nativeData,
+      this.interceptorData,
+      this.backendUsage,
+      this.rtiNeed,
+      this.allocatorAnalysis,
+      this.noSuchMethodData,
+      this.implementedClasses,
+      this.liveNativeClasses,
+      this.liveInstanceMembers,
+      this.assignedInstanceMembers,
+      this.processedMembers,
+      this.mixinUses,
+      this.typesImplementedBySubclasses,
+      this.classHierarchy,
+      AbstractValueStrategy abstractValueStrategy,
+      this.annotationsData,
+      this.globalLocalsMap,
+      this.closureDataLookup,
+      this.outputUnitData) {
+    _abstractValueDomain = abstractValueStrategy.createDomain(this);
+  }
+
+  /// Deserializes a [JsClosedWorld] object from [source].
+  factory JsClosedWorld.readFromDataSource(
+      CompilerOptions options,
+      DiagnosticReporter reporter,
+      Environment environment,
+      AbstractValueStrategy abstractValueStrategy,
+      ir.Component component,
+      DataSource source) {
+    source.begin(tag);
+
+    JsKernelToElementMap elementMap =
+        new JsKernelToElementMap.readFromDataSource(
+            options, reporter, environment, component, source);
+    GlobalLocalsMap globalLocalsMap =
+        new GlobalLocalsMap.readFromDataSource(source);
+    source.registerLocalLookup(new LocalLookupImpl(globalLocalsMap));
+    ClassHierarchy classHierarchy = new ClassHierarchy.readFromDataSource(
+        source, elementMap.commonElements);
+    NativeData nativeData = new NativeData.readFromDataSource(
+        source, elementMap.elementEnvironment);
+    elementMap.nativeBasicData = nativeData;
+    InterceptorData interceptorData = new InterceptorData.readFromDataSource(
+        source, nativeData, elementMap.commonElements);
+    BackendUsage backendUsage = new BackendUsage.readFromDataSource(source);
+    RuntimeTypesNeed rtiNeed = new RuntimeTypesNeed.readFromDataSource(
+        source, elementMap.elementEnvironment);
+    JAllocatorAnalysis allocatorAnalysis =
+        new JAllocatorAnalysis.readFromDataSource(source, options);
+    NoSuchMethodData noSuchMethodData =
+        new NoSuchMethodData.readFromDataSource(source);
+
+    Set<ClassEntity> implementedClasses = source.readClasses().toSet();
+    Set<ClassEntity> liveNativeClasses = source.readClasses().toSet();
+    Set<MemberEntity> liveInstanceMembers = source.readMembers().toSet();
+    Set<MemberEntity> assignedInstanceMembers = source.readMembers().toSet();
+    Set<MemberEntity> processedMembers = source.readMembers().toSet();
+    Map<ClassEntity, Set<ClassEntity>> mixinUses =
+        source.readClassMap(() => source.readClasses().toSet());
+    Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses =
+        source.readClassMap(() => source.readClasses().toSet());
+
+    AnnotationsData annotationsData =
+        new AnnotationsData.readFromDataSource(source);
+
+    ClosureData closureData =
+        new ClosureData.readFromDataSource(elementMap, source);
+
+    OutputUnitData outputUnitData =
+        new OutputUnitData.readFromDataSource(source);
+
+    source.end(tag);
+
+    return new JsClosedWorld(
+        elementMap,
+        nativeData,
+        interceptorData,
+        backendUsage,
+        rtiNeed,
+        allocatorAnalysis,
+        noSuchMethodData,
+        implementedClasses,
+        liveNativeClasses,
+        liveInstanceMembers,
+        assignedInstanceMembers,
+        processedMembers,
+        mixinUses,
+        typesImplementedBySubclasses,
+        classHierarchy,
+        abstractValueStrategy,
+        annotationsData,
+        globalLocalsMap,
+        closureData,
+        outputUnitData);
+  }
+
+  /// Serializes this [JsClosedWorld] to [sink].
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+    elementMap.writeToDataSink(sink);
+    globalLocalsMap.writeToDataSink(sink);
+
+    classHierarchy.writeToDataSink(sink);
+    nativeData.writeToDataSink(sink);
+    interceptorData.writeToDataSink(sink);
+    backendUsage.writeToDataSink(sink);
+    rtiNeed.writeToDataSink(sink);
+    allocatorAnalysis.writeToDataSink(sink);
+    noSuchMethodData.writeToDataSink(sink);
+    sink.writeClasses(implementedClasses);
+    sink.writeClasses(liveNativeClasses);
+    sink.writeMembers(liveInstanceMembers);
+    sink.writeMembers(assignedInstanceMembers);
+    sink.writeMembers(processedMembers);
+    sink.writeClassMap(
+        mixinUses, (Set<ClassEntity> set) => sink.writeClasses(set));
+    sink.writeClassMap(typesImplementedBySubclasses,
+        (Set<ClassEntity> set) => sink.writeClasses(set));
+    annotationsData.writeToDataSink(sink);
+    closureDataLookup.writeToDataSink(sink);
+    outputUnitData.writeToDataSink(sink);
+    sink.end(tag);
+  }
+
+  ConstantSystem get constantSystem => JavaScriptConstantSystem.only;
+
+  JElementEnvironment get elementEnvironment => elementMap.elementEnvironment;
+
+  JCommonElements get commonElements => elementMap.commonElements;
+
+  DartTypes get dartTypes => elementMap.types;
+
+  /// Returns `true` if [cls] is implemented by an instantiated class.
+  bool isImplemented(ClassEntity cls) {
+    return implementedClasses.contains(cls);
+  }
+
+  @override
+  ClassEntity getLubOfInstantiatedSubclasses(ClassEntity cls) {
+    if (nativeData.isJsInteropClass(cls)) {
+      return commonElements.jsJavaScriptObjectClass;
+    }
+    ClassHierarchyNode hierarchy = classHierarchy.getClassHierarchyNode(cls);
+    return hierarchy != null
+        ? hierarchy.getLubOfInstantiatedSubclasses()
+        : null;
+  }
+
+  @override
+  ClassEntity getLubOfInstantiatedSubtypes(ClassEntity cls) {
+    if (nativeData.isJsInteropClass(cls)) {
+      return commonElements.jsJavaScriptObjectClass;
+    }
+    ClassSet classSet = classHierarchy.getClassSet(cls);
+    return classSet != null ? classSet.getLubOfInstantiatedSubtypes() : null;
+  }
+
+  /// Returns `true` if [cls] is mixed into a live class.
+  bool isUsedAsMixin(ClassEntity cls) {
+    return !mixinUsesOf(cls).isEmpty;
+  }
+
+  /// Returns `true` if any live class that mixes in [cls] implements [type].
+  bool hasAnySubclassOfMixinUseThatImplements(
+      ClassEntity cls, ClassEntity type) {
+    return mixinUsesOf(cls)
+        .any((use) => hasAnySubclassThatImplements(use, type));
+  }
+
+  /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass
+  /// of a mixin application of [y].
+  bool everySubtypeIsSubclassOfOrMixinUseOf(ClassEntity x, ClassEntity y) {
+    Map<ClassEntity, bool> secondMap =
+        _subtypeCoveredByCache[x] ??= <ClassEntity, bool>{};
+    return secondMap[y] ??= classHierarchy.subtypesOf(x).every(
+        (ClassEntity cls) =>
+            classHierarchy.isSubclassOf(cls, y) ||
+            isSubclassOfMixinUseOf(cls, y));
+  }
+
+  /// Returns `true` if any subclass of [superclass] implements [type].
+  bool hasAnySubclassThatImplements(ClassEntity superclass, ClassEntity type) {
+    Set<ClassEntity> subclasses = typesImplementedBySubclasses[superclass];
+    if (subclasses == null) return false;
+    return subclasses.contains(type);
+  }
+
+  @override
+  bool needsNoSuchMethod(
+      ClassEntity base, Selector selector, ClassQuery query) {
+    /// Returns `true` if subclasses in the [rootNode] tree needs noSuchMethod
+    /// handling.
+    bool subclassesNeedNoSuchMethod(ClassHierarchyNode rootNode) {
+      if (!rootNode.isInstantiated) {
+        // No subclass needs noSuchMethod handling since they are all
+        // uninstantiated.
+        return false;
+      }
+      ClassEntity rootClass = rootNode.cls;
+      if (_hasConcreteMatch(rootClass, selector)) {
+        // The root subclass has a concrete implementation so no subclass needs
+        // noSuchMethod handling.
+        return false;
+      } else if (rootNode.isExplicitlyInstantiated) {
+        // The root class need noSuchMethod handling.
+        return true;
+      }
+      IterationStep result = rootNode.forEachSubclass((ClassEntity subclass) {
+        if (_hasConcreteMatch(subclass, selector,
+            stopAtSuperclass: rootClass)) {
+          // Found a match - skip all subclasses.
+          return IterationStep.SKIP_SUBCLASSES;
+        } else {
+          // Stop fast - we found a need for noSuchMethod handling.
+          return IterationStep.STOP;
+        }
+      }, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, strict: true);
+      // We stopped fast so we need noSuchMethod handling.
+      return result == IterationStep.STOP;
+    }
+
+    ClassSet classSet = classHierarchy.getClassSet(base);
+    assert(classSet != null, failedAt(base, "No class set for $base."));
+    ClassHierarchyNode node = classSet.node;
+    if (query == ClassQuery.EXACT) {
+      return node.isExplicitlyInstantiated &&
+          !_hasConcreteMatch(base, selector);
+    } else if (query == ClassQuery.SUBCLASS) {
+      return subclassesNeedNoSuchMethod(node);
+    } else {
+      if (subclassesNeedNoSuchMethod(node)) return true;
+      for (ClassHierarchyNode subtypeNode in classSet.subtypeNodes) {
+        if (subclassesNeedNoSuchMethod(subtypeNode)) return true;
+      }
+      return false;
+    }
+  }
+
+  /// Returns an iterable over the common supertypes of the [classes].
+  Iterable<ClassEntity> commonSupertypesOf(Iterable<ClassEntity> classes) {
+    Iterator<ClassEntity> iterator = classes.iterator;
+    if (!iterator.moveNext()) return const <ClassEntity>[];
+
+    ClassEntity cls = iterator.current;
+    OrderedTypeSet typeSet = elementMap.getOrderedTypeSet(cls);
+    if (!iterator.moveNext()) return typeSet.types.map((type) => type.element);
+
+    int depth = typeSet.maxDepth;
+    Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>();
+    do {
+      ClassEntity otherClass = iterator.current;
+      OrderedTypeSet otherTypeSet = elementMap.getOrderedTypeSet(otherClass);
+      otherTypeSets = otherTypeSets.prepend(otherTypeSet);
+      if (otherTypeSet.maxDepth < depth) {
+        depth = otherTypeSet.maxDepth;
+      }
+    } while (iterator.moveNext());
+
+    List<ClassEntity> commonSupertypes = <ClassEntity>[];
+    OUTER:
+    for (Link<InterfaceType> link = typeSet[depth];
+        link.head.element != commonElements.objectClass;
+        link = link.tail) {
+      ClassEntity cls = link.head.element;
+      for (Link<OrderedTypeSet> link = otherTypeSets;
+          !link.isEmpty;
+          link = link.tail) {
+        if (link.head.asInstanceOf(cls, elementMap.getHierarchyDepth(cls)) ==
+            null) {
+          continue OUTER;
+        }
+      }
+      commonSupertypes.add(cls);
+    }
+    commonSupertypes.add(commonElements.objectClass);
+    return commonSupertypes;
+  }
+
+  /// Returns an iterable over the live mixin applications that mixin [cls].
+  Iterable<ClassEntity> mixinUsesOf(ClassEntity cls) {
+    if (_liveMixinUses == null) {
+      _liveMixinUses = new Map<ClassEntity, List<ClassEntity>>();
+      for (ClassEntity mixin in mixinUses.keys) {
+        List<ClassEntity> uses = <ClassEntity>[];
+
+        void addLiveUse(ClassEntity mixinApplication) {
+          if (classHierarchy.isInstantiated(mixinApplication)) {
+            uses.add(mixinApplication);
+          } else if (_isNamedMixinApplication(mixinApplication)) {
+            Set<ClassEntity> next = mixinUses[mixinApplication];
+            if (next != null) {
+              next.forEach(addLiveUse);
+            }
+          }
+        }
+
+        mixinUses[mixin].forEach(addLiveUse);
+        if (uses.isNotEmpty) {
+          _liveMixinUses[mixin] = uses;
+        }
+      }
+    }
+    Iterable<ClassEntity> uses = _liveMixinUses[cls];
+    return uses != null ? uses : const <ClassEntity>[];
+  }
+
+  /// Returns `true` if any live class that mixes in [mixin] is also a subclass
+  /// of [superclass].
+  bool hasAnySubclassThatMixes(ClassEntity superclass, ClassEntity mixin) {
+    return mixinUsesOf(mixin).any((ClassEntity each) {
+      return classHierarchy.isSubclassOf(each, superclass);
+    });
+  }
+
+  /// Returns `true` if [cls] or any superclass mixes in [mixin].
+  bool isSubclassOfMixinUseOf(ClassEntity cls, ClassEntity mixin) {
+    if (isUsedAsMixin(mixin)) {
+      ClassEntity current = cls;
+      while (current != null) {
+        ClassEntity currentMixin = elementMap.getAppliedMixin(current);
+        if (currentMixin == mixin) return true;
+        current = elementEnvironment.getSuperClass(current);
+      }
+    }
+    return false;
+  }
+
+  void _ensureFunctionSet() {
+    if (_allFunctions == null) {
+      // [FunctionSet] is created lazily because it is not used when we switch
+      // from a frontend to a backend model before inference.
+      _allFunctions = new FunctionSet(liveInstanceMembers);
+    }
+  }
+
+  /// Returns `true` if [selector] on [receiver] can hit a `call` method on a
+  /// subclass of `Closure`.
+  ///
+  /// Every implementation of `Closure` has a 'call' method with its own
+  /// signature so it cannot be modelled by a [FunctionEntity]. Also,
+  /// call-methods for tear-off are not part of the element model.
+  bool includesClosureCall(Selector selector, AbstractValue receiver) {
+    return selector.name == Identifiers.call &&
+        (receiver == null ||
+            // TODO(johnniwinther): Should this have been `intersects` instead?
+            abstractValueDomain.contains(
+                receiver, abstractValueDomain.functionType));
+  }
+
+  AbstractValue computeReceiverType(Selector selector, AbstractValue receiver) {
+    _ensureFunctionSet();
+    if (includesClosureCall(selector, receiver)) {
+      return abstractValueDomain.dynamicType;
+    }
+    return _allFunctions.receiverType(selector, receiver, abstractValueDomain);
+  }
+
+  Iterable<MemberEntity> locateMembers(
+      Selector selector, AbstractValue receiver) {
+    _ensureFunctionSet();
+    return _allFunctions.filter(selector, receiver, abstractValueDomain);
+  }
+
+  bool hasAnyUserDefinedGetter(Selector selector, AbstractValue receiver) {
+    _ensureFunctionSet();
+    return _allFunctions
+        .filter(selector, receiver, abstractValueDomain)
+        .any((each) => each.isGetter);
+  }
+
+  FieldEntity locateSingleField(Selector selector, AbstractValue receiver) {
+    MemberEntity result = locateSingleMember(selector, receiver);
+    return (result != null && result.isField) ? result : null;
+  }
+
+  MemberEntity locateSingleMember(Selector selector, AbstractValue receiver) {
+    if (includesClosureCall(selector, receiver)) {
+      return null;
+    }
+    receiver ??= abstractValueDomain.dynamicType;
+    return abstractValueDomain.locateSingleMember(receiver, selector);
+  }
+
+  bool fieldNeverChanges(MemberEntity element) {
+    if (!element.isField) return false;
+    if (nativeData.isNativeMember(element)) {
+      // Some native fields are views of data that may be changed by operations.
+      // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2).
+      // TODO(sra): Refine the effect classification so that native effects are
+      // distinct from ordinary Dart effects.
+      return false;
+    }
+
+    if (!element.isAssignable) {
+      return true;
+    }
+    if (element.isInstanceMember) {
+      return !assignedInstanceMembers.contains(element);
+    }
+    return false;
+  }
+
+  @override
+  Sorter get sorter {
+    return _sorter ??= new KernelSorter(elementMap);
+  }
+
+  @override
+  AbstractValueDomain get abstractValueDomain {
+    return _abstractValueDomain;
+  }
+
+  @override
+  bool hasElementIn(ClassEntity cls, Selector selector, Entity element) {
+    while (cls != null) {
+      MemberEntity member = elementEnvironment.lookupLocalClassMember(
+          cls, selector.name,
+          setter: selector.isSetter);
+      if (member != null &&
+          !member.isAbstract &&
+          (!selector.memberName.isPrivate ||
+              member.library == selector.library)) {
+        return member == element;
+      }
+      cls = elementEnvironment.getSuperClass(cls);
+    }
+    return false;
+  }
+
+  /// Returns whether a [selector] call on an instance of [cls]
+  /// will hit a method at runtime, and not go through [noSuchMethod].
+  bool _hasConcreteMatch(ClassEntity cls, Selector selector,
+      {ClassEntity stopAtSuperclass}) {
+    assert(classHierarchy.isInstantiated(cls),
+        failedAt(cls, '$cls has not been instantiated.'));
+    MemberEntity element = elementEnvironment
+        .lookupClassMember(cls, selector.name, setter: selector.isSetter);
+    if (element == null) return false;
+
+    if (element.isAbstract) {
+      ClassEntity enclosingClass = element.enclosingClass;
+      return _hasConcreteMatch(
+          elementEnvironment.getSuperClass(enclosingClass), selector);
+    }
+    return selector.appliesUntyped(element);
+  }
+
+  bool _isNamedMixinApplication(ClassEntity cls) {
+    return elementEnvironment.isMixinApplication(cls) &&
+        !elementEnvironment.isUnnamedMixinApplication(cls);
+  }
+}
+
+class KernelSorter implements Sorter {
+  final JsToElementMap elementMap;
+
+  KernelSorter(this.elementMap);
+
+  int _compareLibraries(LibraryEntity a, LibraryEntity b) {
+    return utils.compareLibrariesUris(a.canonicalUri, b.canonicalUri);
+  }
+
+  int _compareSourceSpans(Entity entity1, SourceSpan sourceSpan1,
+      Entity entity2, SourceSpan sourceSpan2) {
+    int r = utils.compareSourceUris(sourceSpan1.uri, sourceSpan2.uri);
+    if (r != 0) return r;
+    return utils.compareEntities(
+        entity1, sourceSpan1.begin, null, entity2, sourceSpan2.begin, null);
+  }
+
+  @override
+  Iterable<LibraryEntity> sortLibraries(Iterable<LibraryEntity> libraries) {
+    return libraries.toList()..sort(_compareLibraries);
+  }
+
+  @override
+  Iterable<T> sortMembers<T extends MemberEntity>(Iterable<T> members) {
+    return members.toList()..sort(compareMembersByLocation);
+  }
+
+  @override
+  Iterable<ClassEntity> sortClasses(Iterable<ClassEntity> classes) {
+    List<ClassEntity> regularClasses = <ClassEntity>[];
+    List<ClassEntity> unnamedMixins = <ClassEntity>[];
+    for (ClassEntity cls in classes) {
+      if (elementMap.elementEnvironment.isUnnamedMixinApplication(cls)) {
+        unnamedMixins.add(cls);
+      } else {
+        regularClasses.add(cls);
+      }
+    }
+    List<ClassEntity> sorted = <ClassEntity>[];
+    regularClasses.sort(compareClassesByLocation);
+    sorted.addAll(regularClasses);
+    unnamedMixins.sort((a, b) {
+      int result = _compareLibraries(a.library, b.library);
+      if (result != 0) return result;
+      result = a.name.compareTo(b.name);
+      assert(result != 0,
+          failedAt(a, "Multiple mixins named ${a.name}: $a vs $b."));
+      return result;
+    });
+    sorted.addAll(unnamedMixins);
+    return sorted;
+  }
+
+  @override
+  Iterable<TypedefEntity> sortTypedefs(Iterable<TypedefEntity> typedefs) {
+    // TODO(redemption): Support this.
+    assert(typedefs.isEmpty);
+    return typedefs;
+  }
+
+  @override
+  int compareLibrariesByLocation(LibraryEntity a, LibraryEntity b) {
+    return _compareLibraries(a, b);
+  }
+
+  @override
+  int compareClassesByLocation(ClassEntity a, ClassEntity b) {
+    int r = _compareLibraries(a.library, b.library);
+    if (r != 0) return r;
+    ClassDefinition definition1 = elementMap.getClassDefinition(a);
+    ClassDefinition definition2 = elementMap.getClassDefinition(b);
+    return _compareSourceSpans(
+        a, definition1.location, b, definition2.location);
+  }
+
+  @override
+  int compareTypedefsByLocation(TypedefEntity a, TypedefEntity b) {
+    // TODO(redemption): Support this.
+    failedAt(a, 'KernelSorter.compareTypedefsByLocation unimplemented');
+    return 0;
+  }
+
+  @override
+  int compareMembersByLocation(MemberEntity a, MemberEntity b) {
+    int r = _compareLibraries(a.library, b.library);
+    if (r != 0) return r;
+    MemberDefinition definition1 = elementMap.getMemberDefinition(a);
+    MemberDefinition definition2 = elementMap.getMemberDefinition(b);
+    return _compareSourceSpans(
+        a, definition1.location, b, definition2.location);
+  }
+}
+
+/// [LocalLookup] implementation used to deserialize [JsClosedWorld].
+class LocalLookupImpl implements LocalLookup {
+  final GlobalLocalsMap _globalLocalsMap;
+
+  LocalLookupImpl(this._globalLocalsMap);
+
+  @override
+  Local getLocalByIndex(MemberEntity memberContext, int index) {
+    KernelToLocalsMapImpl map = _globalLocalsMap.getLocalsMap(memberContext);
+    return map.getLocalByIndex(index);
+  }
+}
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
new file mode 100644
index 0000000..9632b29
--- /dev/null
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -0,0 +1,756 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart' as ir;
+
+import '../closure.dart';
+import '../common_elements.dart';
+import '../constants/values.dart';
+import '../deferred_load.dart';
+import '../elements/entities.dart';
+import '../elements/names.dart';
+import '../elements/types.dart';
+import '../js_backend/annotations.dart';
+import '../js_backend/allocator_analysis.dart';
+import '../js_backend/backend_usage.dart';
+import '../js_backend/interceptor_data.dart';
+import '../js_backend/native_data.dart';
+import '../js_backend/no_such_method_registry.dart';
+import '../js_backend/runtime_types.dart';
+import '../kernel/kelements.dart';
+import '../native/behavior.dart';
+import '../options.dart';
+import '../types/abstract_value_domain.dart';
+import '../universe/class_hierarchy.dart';
+import '../universe/class_set.dart';
+import '../universe/feature.dart';
+import '../universe/selector.dart';
+import '../world.dart';
+import 'closure.dart';
+import 'elements.dart';
+import 'element_map.dart';
+import 'element_map_impl.dart';
+import 'js_world.dart';
+import 'locals.dart';
+
+class JsClosedWorldBuilder {
+  final JsKernelToElementMap _elementMap;
+  final Map<ClassEntity, ClassHierarchyNode> _classHierarchyNodes =
+      new ClassHierarchyNodesMap();
+  final Map<ClassEntity, ClassSet> _classSets = <ClassEntity, ClassSet>{};
+  final GlobalLocalsMap _globalLocalsMap;
+  final ClosureDataBuilder _closureDataBuilder;
+  final CompilerOptions _options;
+  final AbstractValueStrategy _abstractValueStrategy;
+
+  JsClosedWorldBuilder(this._elementMap, this._globalLocalsMap,
+      this._closureDataBuilder, this._options, this._abstractValueStrategy);
+
+  ElementEnvironment get _elementEnvironment => _elementMap.elementEnvironment;
+  CommonElements get _commonElements => _elementMap.commonElements;
+
+  JsClosedWorld convertClosedWorld(
+      KClosedWorld closedWorld,
+      Map<MemberEntity, ScopeModel> closureModels,
+      OutputUnitData kOutputUnitData) {
+    JsToFrontendMap map = new JsToFrontendMapImpl(_elementMap);
+
+    BackendUsage backendUsage =
+        _convertBackendUsage(map, closedWorld.backendUsage);
+    NativeData nativeData = _convertNativeData(map, closedWorld.nativeData);
+    _elementMap.nativeBasicData = nativeData;
+    InterceptorData interceptorData =
+        _convertInterceptorData(map, nativeData, closedWorld.interceptorData);
+
+    Set<ClassEntity> implementedClasses = new Set<ClassEntity>();
+
+    /// Converts [node] from the frontend world to the corresponding
+    /// [ClassHierarchyNode] for the backend world.
+    ClassHierarchyNode convertClassHierarchyNode(ClassHierarchyNode node) {
+      ClassEntity cls = map.toBackendClass(node.cls);
+      if (closedWorld.isImplemented(node.cls)) {
+        implementedClasses.add(cls);
+      }
+      ClassHierarchyNode newNode = _classHierarchyNodes.putIfAbsent(cls, () {
+        ClassHierarchyNode parentNode;
+        if (node.parentNode != null) {
+          parentNode = convertClassHierarchyNode(node.parentNode);
+        }
+        return new ClassHierarchyNode(parentNode, cls, node.hierarchyDepth);
+      });
+      newNode.isAbstractlyInstantiated = node.isAbstractlyInstantiated;
+      newNode.isDirectlyInstantiated = node.isDirectlyInstantiated;
+      return newNode;
+    }
+
+    /// Converts [classSet] from the frontend world to the corresponding
+    /// [ClassSet] for the backend world.
+    ClassSet convertClassSet(ClassSet classSet) {
+      ClassEntity cls = map.toBackendClass(classSet.cls);
+      return _classSets.putIfAbsent(cls, () {
+        ClassHierarchyNode newNode = convertClassHierarchyNode(classSet.node);
+        ClassSet newClassSet = new ClassSet(newNode);
+        for (ClassHierarchyNode subtype in classSet.subtypeNodes) {
+          ClassHierarchyNode newSubtype = convertClassHierarchyNode(subtype);
+          newClassSet.addSubtype(newSubtype);
+        }
+        return newClassSet;
+      });
+    }
+
+    closedWorld.classHierarchy
+        .getClassHierarchyNode(closedWorld.commonElements.objectClass)
+        .forEachSubclass((ClassEntity cls) {
+      convertClassSet(closedWorld.classHierarchy.getClassSet(cls));
+    }, ClassHierarchyNode.ALL);
+
+    Set<MemberEntity> liveInstanceMembers =
+        map.toBackendMemberSet(closedWorld.liveInstanceMembers);
+
+    Map<ClassEntity, Set<ClassEntity>> mixinUses =
+        map.toBackendClassMap(closedWorld.mixinUses, map.toBackendClassSet);
+
+    Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses =
+        map.toBackendClassMap(
+            closedWorld.typesImplementedBySubclasses, map.toBackendClassSet);
+
+    Set<MemberEntity> assignedInstanceMembers =
+        map.toBackendMemberSet(closedWorld.assignedInstanceMembers);
+
+    Set<ClassEntity> liveNativeClasses =
+        map.toBackendClassSet(closedWorld.liveNativeClasses);
+
+    Set<MemberEntity> processedMembers =
+        map.toBackendMemberSet(closedWorld.processedMembers);
+
+    RuntimeTypesNeed rtiNeed;
+
+    List<FunctionEntity> callMethods = <FunctionEntity>[];
+    ClosureData closureData;
+    if (_options.disableRtiOptimization) {
+      rtiNeed = new TrivialRuntimeTypesNeed();
+      closureData = _closureDataBuilder.createClosureEntities(
+          this,
+          map.toBackendMemberMap(closureModels, identity),
+          const TrivialClosureRtiNeed(),
+          callMethods);
+    } else {
+      RuntimeTypesNeedImpl kernelRtiNeed = closedWorld.rtiNeed;
+      Set<ir.Node> localFunctionsNodesNeedingSignature = new Set<ir.Node>();
+      for (KLocalFunction localFunction
+          in kernelRtiNeed.localFunctionsNeedingSignature) {
+        ir.Node node = localFunction.node;
+        assert(node is ir.FunctionDeclaration || node is ir.FunctionExpression,
+            "Unexpected local function node: $node");
+        localFunctionsNodesNeedingSignature.add(node);
+      }
+      Set<ir.Node> localFunctionsNodesNeedingTypeArguments = new Set<ir.Node>();
+      for (KLocalFunction localFunction
+          in kernelRtiNeed.localFunctionsNeedingTypeArguments) {
+        ir.Node node = localFunction.node;
+        assert(node is ir.FunctionDeclaration || node is ir.FunctionExpression,
+            "Unexpected local function node: $node");
+        localFunctionsNodesNeedingTypeArguments.add(node);
+      }
+
+      RuntimeTypesNeedImpl jRtiNeed =
+          _convertRuntimeTypesNeed(map, backendUsage, kernelRtiNeed);
+      closureData = _closureDataBuilder.createClosureEntities(
+          this,
+          map.toBackendMemberMap(closureModels, identity),
+          new JsClosureRtiNeed(
+              jRtiNeed,
+              localFunctionsNodesNeedingTypeArguments,
+              localFunctionsNodesNeedingSignature),
+          callMethods);
+
+      List<FunctionEntity> callMethodsNeedingSignature = <FunctionEntity>[];
+      for (ir.Node node in localFunctionsNodesNeedingSignature) {
+        callMethodsNeedingSignature
+            .add(closureData.getClosureInfo(node).callMethod);
+      }
+      List<FunctionEntity> callMethodsNeedingTypeArguments = <FunctionEntity>[];
+      for (ir.Node node in localFunctionsNodesNeedingTypeArguments) {
+        callMethodsNeedingTypeArguments
+            .add(closureData.getClosureInfo(node).callMethod);
+      }
+      jRtiNeed.methodsNeedingSignature.addAll(callMethodsNeedingSignature);
+      jRtiNeed.methodsNeedingTypeArguments
+          .addAll(callMethodsNeedingTypeArguments);
+
+      rtiNeed = jRtiNeed;
+    }
+
+    NoSuchMethodDataImpl oldNoSuchMethodData = closedWorld.noSuchMethodData;
+    NoSuchMethodData noSuchMethodData = new NoSuchMethodDataImpl(
+        map.toBackendFunctionSet(oldNoSuchMethodData.throwingImpls),
+        map.toBackendFunctionSet(oldNoSuchMethodData.otherImpls),
+        map.toBackendFunctionSet(oldNoSuchMethodData.forwardingSyntaxImpls));
+
+    JAllocatorAnalysis allocatorAnalysis =
+        JAllocatorAnalysis.from(closedWorld.allocatorAnalysis, map, _options);
+
+    AnnotationsData annotationsData = new AnnotationsDataImpl(
+        map.toBackendFunctionSet(
+            closedWorld.annotationsData.nonInlinableFunctions),
+        map.toBackendFunctionSet(
+            closedWorld.annotationsData.tryInlineFunctions),
+        map.toBackendFunctionSet(
+            closedWorld.annotationsData.cannotThrowFunctions),
+        map.toBackendFunctionSet(
+            closedWorld.annotationsData.sideEffectFreeFunctions),
+        map.toBackendMemberSet(
+            closedWorld.annotationsData.trustTypeAnnotationsMembers),
+        map.toBackendMemberSet(
+            closedWorld.annotationsData.assumeDynamicMembers));
+
+    OutputUnitData outputUnitData =
+        _convertOutputUnitData(map, kOutputUnitData, closureData);
+
+    return new JsClosedWorld(
+        _elementMap,
+        nativeData,
+        interceptorData,
+        backendUsage,
+        rtiNeed,
+        allocatorAnalysis,
+        noSuchMethodData,
+        implementedClasses,
+        liveNativeClasses,
+        // TODO(johnniwinther): Include the call method when we can also
+        // represent the synthesized call methods for static and instance method
+        // closurizations.
+        liveInstanceMembers /*..addAll(callMethods)*/,
+        assignedInstanceMembers,
+        processedMembers,
+        mixinUses,
+        typesImplementedBySubclasses,
+        new ClassHierarchyImpl(
+            _elementMap.commonElements, _classHierarchyNodes, _classSets),
+        _abstractValueStrategy,
+        annotationsData,
+        _globalLocalsMap,
+        closureData,
+        outputUnitData);
+  }
+
+  BackendUsage _convertBackendUsage(
+      JsToFrontendMap map, BackendUsageImpl backendUsage) {
+    Set<FunctionEntity> globalFunctionDependencies =
+        map.toBackendFunctionSet(backendUsage.globalFunctionDependencies);
+    Set<ClassEntity> globalClassDependencies =
+        map.toBackendClassSet(backendUsage.globalClassDependencies);
+    Set<FunctionEntity> helperFunctionsUsed =
+        map.toBackendFunctionSet(backendUsage.helperFunctionsUsed);
+    Set<ClassEntity> helperClassesUsed =
+        map.toBackendClassSet(backendUsage.helperClassesUsed);
+    Set<RuntimeTypeUse> runtimeTypeUses =
+        backendUsage.runtimeTypeUses.map((RuntimeTypeUse runtimeTypeUse) {
+      return new RuntimeTypeUse(
+          runtimeTypeUse.kind,
+          map.toBackendType(runtimeTypeUse.receiverType),
+          map.toBackendType(runtimeTypeUse.argumentType));
+    }).toSet();
+
+    return new BackendUsageImpl(
+        globalFunctionDependencies: globalFunctionDependencies,
+        globalClassDependencies: globalClassDependencies,
+        helperFunctionsUsed: helperFunctionsUsed,
+        helperClassesUsed: helperClassesUsed,
+        needToInitializeIsolateAffinityTag:
+            backendUsage.needToInitializeIsolateAffinityTag,
+        needToInitializeDispatchProperty:
+            backendUsage.needToInitializeDispatchProperty,
+        requiresPreamble: backendUsage.requiresPreamble,
+        runtimeTypeUses: runtimeTypeUses,
+        isFunctionApplyUsed: backendUsage.isFunctionApplyUsed,
+        isMirrorsUsed: backendUsage.isMirrorsUsed,
+        isNoSuchMethodUsed: backendUsage.isNoSuchMethodUsed);
+  }
+
+  NativeBasicData _convertNativeBasicData(
+      JsToFrontendMap map, NativeBasicDataImpl nativeBasicData) {
+    Map<ClassEntity, NativeClassTag> nativeClassTagInfo =
+        <ClassEntity, NativeClassTag>{};
+    nativeBasicData.nativeClassTagInfo
+        .forEach((ClassEntity cls, NativeClassTag tag) {
+      nativeClassTagInfo[map.toBackendClass(cls)] = tag;
+    });
+    Map<LibraryEntity, String> jsInteropLibraries =
+        map.toBackendLibraryMap(nativeBasicData.jsInteropLibraries, identity);
+    Map<ClassEntity, String> jsInteropClasses =
+        map.toBackendClassMap(nativeBasicData.jsInteropClasses, identity);
+    Set<ClassEntity> anonymousJsInteropClasses =
+        map.toBackendClassSet(nativeBasicData.anonymousJsInteropClasses);
+    Map<MemberEntity, String> jsInteropMembers =
+        map.toBackendMemberMap(nativeBasicData.jsInteropMembers, identity);
+    return new NativeBasicDataImpl(
+        _elementEnvironment,
+        nativeClassTagInfo,
+        jsInteropLibraries,
+        jsInteropClasses,
+        anonymousJsInteropClasses,
+        jsInteropMembers);
+  }
+
+  NativeData _convertNativeData(
+      JsToFrontendMap map, NativeDataImpl nativeData) {
+    convertNativeBehaviorType(type) {
+      if (type is DartType) return map.toBackendType(type);
+      assert(type is SpecialType);
+      return type;
+    }
+
+    NativeBehavior convertNativeBehavior(NativeBehavior behavior) {
+      NativeBehavior newBehavior = new NativeBehavior();
+
+      for (dynamic type in behavior.typesReturned) {
+        newBehavior.typesReturned.add(convertNativeBehaviorType(type));
+      }
+      for (dynamic type in behavior.typesInstantiated) {
+        newBehavior.typesInstantiated.add(convertNativeBehaviorType(type));
+      }
+
+      newBehavior.codeTemplateText = behavior.codeTemplateText;
+      newBehavior.codeTemplate = behavior.codeTemplate;
+      newBehavior.throwBehavior = behavior.throwBehavior;
+      newBehavior.isAllocation = behavior.isAllocation;
+      newBehavior.useGvn = behavior.useGvn;
+      return newBehavior;
+    }
+
+    NativeBasicData nativeBasicData = _convertNativeBasicData(map, nativeData);
+
+    Map<MemberEntity, String> nativeMemberName =
+        map.toBackendMemberMap(nativeData.nativeMemberName, identity);
+    Map<FunctionEntity, NativeBehavior> nativeMethodBehavior =
+        <FunctionEntity, NativeBehavior>{};
+    nativeData.nativeMethodBehavior
+        .forEach((FunctionEntity method, NativeBehavior behavior) {
+      FunctionEntity backendMethod = map.toBackendMember(method);
+      if (backendMethod != null) {
+        // If [method] isn't used it doesn't have a corresponding backend
+        // method.
+        nativeMethodBehavior[backendMethod] = convertNativeBehavior(behavior);
+      }
+    });
+    Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior =
+        map.toBackendMemberMap(
+            nativeData.nativeFieldLoadBehavior, convertNativeBehavior);
+    Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior =
+        map.toBackendMemberMap(
+            nativeData.nativeFieldStoreBehavior, convertNativeBehavior);
+    Map<LibraryEntity, String> jsInteropLibraryNames =
+        map.toBackendLibraryMap(nativeData.jsInteropLibraries, identity);
+    Set<ClassEntity> anonymousJsInteropClasses =
+        map.toBackendClassSet(nativeData.anonymousJsInteropClasses);
+    Map<ClassEntity, String> jsInteropClassNames =
+        map.toBackendClassMap(nativeData.jsInteropClasses, identity);
+    Map<MemberEntity, String> jsInteropMemberNames =
+        map.toBackendMemberMap(nativeData.jsInteropMembers, identity);
+
+    return new NativeDataImpl(
+        nativeBasicData,
+        nativeMemberName,
+        nativeMethodBehavior,
+        nativeFieldLoadBehavior,
+        nativeFieldStoreBehavior,
+        jsInteropLibraryNames,
+        anonymousJsInteropClasses,
+        jsInteropClassNames,
+        jsInteropMemberNames);
+  }
+
+  InterceptorData _convertInterceptorData(JsToFrontendMap map,
+      NativeData nativeData, InterceptorDataImpl interceptorData) {
+    Map<String, Set<MemberEntity>> interceptedMembers =
+        <String, Set<MemberEntity>>{};
+    interceptorData.interceptedMembers
+        .forEach((String name, Set<MemberEntity> members) {
+      interceptedMembers[name] = map.toBackendMemberSet(members);
+    });
+    return new InterceptorDataImpl(
+        nativeData,
+        _commonElements,
+        interceptedMembers,
+        map.toBackendClassSet(interceptorData.interceptedClasses),
+        map.toBackendClassSet(
+            interceptorData.classesMixedIntoInterceptedClasses));
+  }
+
+  RuntimeTypesNeed _convertRuntimeTypesNeed(JsToFrontendMap map,
+      BackendUsage backendUsage, RuntimeTypesNeedImpl rtiNeed) {
+    Set<ClassEntity> classesNeedingTypeArguments =
+        map.toBackendClassSet(rtiNeed.classesNeedingTypeArguments);
+    Set<FunctionEntity> methodsNeedingTypeArguments =
+        map.toBackendFunctionSet(rtiNeed.methodsNeedingTypeArguments);
+    Set<FunctionEntity> methodsNeedingSignature =
+        map.toBackendFunctionSet(rtiNeed.methodsNeedingSignature);
+    Set<Selector> selectorsNeedingTypeArguments =
+        rtiNeed.selectorsNeedingTypeArguments.map((Selector selector) {
+      if (selector.memberName.isPrivate) {
+        return new Selector(
+            selector.kind,
+            new PrivateName(selector.memberName.text,
+                map.toBackendLibrary(selector.memberName.library),
+                isSetter: selector.memberName.isSetter),
+            selector.callStructure);
+      }
+      return selector;
+    }).toSet();
+    return new RuntimeTypesNeedImpl(
+        _elementEnvironment,
+        classesNeedingTypeArguments,
+        methodsNeedingSignature,
+        methodsNeedingTypeArguments,
+        null,
+        null,
+        selectorsNeedingTypeArguments,
+        rtiNeed.instantiationsNeedingTypeArguments);
+  }
+
+  /// Construct a closure class and set up the necessary class inference
+  /// hierarchy.
+  KernelClosureClassInfo buildClosureClass(
+      MemberEntity member,
+      ir.FunctionNode originalClosureFunctionNode,
+      JLibrary enclosingLibrary,
+      Map<Local, JRecordField> boxedVariables,
+      KernelScopeInfo info,
+      KernelToLocalsMap localsMap,
+      {bool createSignatureMethod}) {
+    ClassEntity superclass = _commonElements.closureClass;
+
+    KernelClosureClassInfo closureClassInfo = _elementMap.constructClosureClass(
+        member,
+        originalClosureFunctionNode,
+        enclosingLibrary,
+        boxedVariables,
+        info,
+        localsMap,
+        new InterfaceType(superclass, const []),
+        createSignatureMethod: createSignatureMethod);
+
+    // Tell the hierarchy that this is the super class. then we can use
+    // .getSupertypes(class)
+    ClassHierarchyNode parentNode = _classHierarchyNodes[superclass];
+    ClassHierarchyNode node = new ClassHierarchyNode(parentNode,
+        closureClassInfo.closureClassEntity, parentNode.hierarchyDepth + 1);
+    _classHierarchyNodes[closureClassInfo.closureClassEntity] = node;
+    _classSets[closureClassInfo.closureClassEntity] = new ClassSet(node);
+    node.isDirectlyInstantiated = true;
+
+    return closureClassInfo;
+  }
+
+  OutputUnitData _convertOutputUnitData(JsToFrontendMapImpl map,
+      OutputUnitData data, ClosureData closureDataLookup) {
+    Entity toBackendEntity(Entity entity) {
+      if (entity is ClassEntity) return map.toBackendClass(entity);
+      if (entity is MemberEntity) return map.toBackendMember(entity);
+      if (entity is TypedefEntity) return map.toBackendTypedef(entity);
+      if (entity is TypeVariableEntity) {
+        return map.toBackendTypeVariable(entity);
+      }
+      assert(
+          entity is LibraryEntity, 'unexpected entity ${entity.runtimeType}');
+      return map.toBackendLibrary(entity);
+    }
+
+    // Convert front-end maps containing K-class and K-local function keys to a
+    // backend map using J-classes as keys.
+    Map<ClassEntity, OutputUnit> convertClassMap(
+        Map<ClassEntity, OutputUnit> classMap,
+        Map<Local, OutputUnit> localFunctionMap) {
+      var result = <ClassEntity, OutputUnit>{};
+      classMap.forEach((ClassEntity entity, OutputUnit unit) {
+        ClassEntity backendEntity = toBackendEntity(entity);
+        if (backendEntity != null) {
+          // If [entity] isn't used it doesn't have a corresponding backend
+          // entity.
+          result[backendEntity] = unit;
+        }
+      });
+      localFunctionMap.forEach((Local entity, OutputUnit unit) {
+        // Ensure closure classes are included in the output unit corresponding
+        // to the local function.
+        if (entity is KLocalFunction) {
+          var closureInfo = closureDataLookup.getClosureInfo(entity.node);
+          result[closureInfo.closureClassEntity] = unit;
+        }
+      });
+      return result;
+    }
+
+    // Convert front-end maps containing K-member and K-local function keys to
+    // a backend map using J-members as keys.
+    Map<MemberEntity, OutputUnit> convertMemberMap(
+        Map<MemberEntity, OutputUnit> memberMap,
+        Map<Local, OutputUnit> localFunctionMap) {
+      var result = <MemberEntity, OutputUnit>{};
+      memberMap.forEach((MemberEntity entity, OutputUnit unit) {
+        MemberEntity backendEntity = toBackendEntity(entity);
+        if (backendEntity != null) {
+          // If [entity] isn't used it doesn't have a corresponding backend
+          // entity.
+          result[backendEntity] = unit;
+        }
+      });
+      localFunctionMap.forEach((Local entity, OutputUnit unit) {
+        // Ensure closure call-methods are included in the output unit
+        // corresponding to the local function.
+        if (entity is KLocalFunction) {
+          var closureInfo = closureDataLookup.getClosureInfo(entity.node);
+          result[closureInfo.callMethod] = unit;
+        }
+      });
+      return result;
+    }
+
+    ConstantValue toBackendConstant(ConstantValue constant) {
+      return constant.accept(new ConstantConverter(toBackendEntity), null);
+    }
+
+    return new OutputUnitData.from(
+        data,
+        map.toBackendLibrary,
+        convertClassMap,
+        convertMemberMap,
+        (m) => convertMap<ConstantValue, OutputUnit>(
+            m, toBackendConstant, (v) => v));
+  }
+}
+
+class TrivialClosureRtiNeed implements ClosureRtiNeed {
+  const TrivialClosureRtiNeed();
+
+  @override
+  bool localFunctionNeedsSignature(ir.Node node) => true;
+
+  @override
+  bool classNeedsTypeArguments(ClassEntity cls) => true;
+
+  @override
+  bool methodNeedsTypeArguments(FunctionEntity method) => true;
+
+  @override
+  bool localFunctionNeedsTypeArguments(ir.Node node) => true;
+
+  @override
+  bool selectorNeedsTypeArguments(Selector selector) => true;
+
+  @override
+  bool methodNeedsSignature(MemberEntity method) => true;
+
+  @override
+  bool instantiationNeedsTypeArguments(
+          DartType functionType, int typeArgumentCount) =>
+      true;
+}
+
+class JsClosureRtiNeed implements ClosureRtiNeed {
+  final RuntimeTypesNeed rtiNeed;
+  final Set<ir.Node> localFunctionsNodesNeedingTypeArguments;
+  final Set<ir.Node> localFunctionsNodesNeedingSignature;
+
+  JsClosureRtiNeed(this.rtiNeed, this.localFunctionsNodesNeedingTypeArguments,
+      this.localFunctionsNodesNeedingSignature);
+
+  @override
+  bool localFunctionNeedsSignature(ir.Node node) {
+    assert(node is ir.FunctionDeclaration || node is ir.FunctionExpression);
+    return localFunctionsNodesNeedingSignature.contains(node);
+  }
+
+  @override
+  bool classNeedsTypeArguments(ClassEntity cls) =>
+      rtiNeed.classNeedsTypeArguments(cls);
+
+  @override
+  bool methodNeedsTypeArguments(FunctionEntity method) =>
+      rtiNeed.methodNeedsTypeArguments(method);
+
+  @override
+  bool localFunctionNeedsTypeArguments(ir.Node node) {
+    assert(node is ir.FunctionDeclaration || node is ir.FunctionExpression);
+    return localFunctionsNodesNeedingTypeArguments.contains(node);
+  }
+
+  @override
+  bool selectorNeedsTypeArguments(Selector selector) =>
+      rtiNeed.selectorNeedsTypeArguments(selector);
+
+  @override
+  bool methodNeedsSignature(MemberEntity method) =>
+      rtiNeed.methodNeedsSignature(method);
+
+  @override
+  bool instantiationNeedsTypeArguments(
+          DartType functionType, int typeArgumentCount) =>
+      rtiNeed.instantiationNeedsTypeArguments(functionType, typeArgumentCount);
+}
+
+class ConstantConverter implements ConstantValueVisitor<ConstantValue, Null> {
+  final Entity Function(Entity) toBackendEntity;
+  final TypeConverter typeConverter;
+
+  ConstantConverter(this.toBackendEntity)
+      : typeConverter = new TypeConverter(toBackendEntity);
+
+  ConstantValue visitNull(NullConstantValue constant, _) => constant;
+  ConstantValue visitInt(IntConstantValue constant, _) => constant;
+  ConstantValue visitDouble(DoubleConstantValue constant, _) => constant;
+  ConstantValue visitBool(BoolConstantValue constant, _) => constant;
+  ConstantValue visitString(StringConstantValue constant, _) => constant;
+  ConstantValue visitSynthetic(SyntheticConstantValue constant, _) => constant;
+  ConstantValue visitNonConstant(NonConstantValue constant, _) => constant;
+
+  ConstantValue visitFunction(FunctionConstantValue constant, _) {
+    return new FunctionConstantValue(
+        toBackendEntity(constant.element), typeConverter.visit(constant.type));
+  }
+
+  ConstantValue visitList(ListConstantValue constant, _) {
+    DartType type = typeConverter.visit(constant.type);
+    List<ConstantValue> entries = _handleValues(constant.entries);
+    if (identical(entries, constant.entries) && type == constant.type) {
+      return constant;
+    }
+    return new ListConstantValue(type, entries);
+  }
+
+  ConstantValue visitMap(MapConstantValue constant, _) {
+    var type = typeConverter.visit(constant.type);
+    List<ConstantValue> keys = _handleValues(constant.keys);
+    List<ConstantValue> values = _handleValues(constant.values);
+    if (identical(keys, constant.keys) &&
+        identical(values, constant.values) &&
+        type == constant.type) {
+      return constant;
+    }
+    return new MapConstantValue(type, keys, values);
+  }
+
+  ConstantValue visitConstructed(ConstructedConstantValue constant, _) {
+    DartType type = typeConverter.visit(constant.type);
+    Map<FieldEntity, ConstantValue> fields = {};
+    constant.fields.forEach((f, v) {
+      FieldEntity backendField = toBackendEntity(f);
+      assert(backendField != null, "No backend field for $f.");
+      fields[backendField] = v.accept(this, null);
+    });
+    return new ConstructedConstantValue(type, fields);
+  }
+
+  ConstantValue visitType(TypeConstantValue constant, _) {
+    DartType type = typeConverter.visit(constant.type);
+    DartType representedType = typeConverter.visit(constant.representedType);
+    if (type == constant.type && representedType == constant.representedType) {
+      return constant;
+    }
+    return new TypeConstantValue(representedType, type);
+  }
+
+  ConstantValue visitInterceptor(InterceptorConstantValue constant, _) {
+    // Interceptor constants are only created in the SSA graph builder.
+    throw new UnsupportedError(
+        "Unexpected visitInterceptor ${constant.toStructuredText()}");
+  }
+
+  ConstantValue visitDeferredGlobal(DeferredGlobalConstantValue constant, _) {
+    // Deferred global constants are only created in the SSA graph builder.
+    throw new UnsupportedError(
+        "Unexpected DeferredGlobalConstantValue ${constant.toStructuredText()}");
+  }
+
+  ConstantValue visitInstantiation(InstantiationConstantValue constant, _) {
+    ConstantValue function = constant.function.accept(this, null);
+    List<DartType> typeArguments =
+        typeConverter.convertTypes(constant.typeArguments);
+    return new InstantiationConstantValue(typeArguments, function);
+  }
+
+  List<ConstantValue> _handleValues(List<ConstantValue> values) {
+    List<ConstantValue> result;
+    for (int i = 0; i < values.length; i++) {
+      var value = values[i];
+      var newValue = value.accept(this, null);
+      if (newValue != value && result == null) {
+        result = values.sublist(0, i).toList();
+      }
+      result?.add(newValue);
+    }
+    return result ?? values;
+  }
+}
+
+class TypeConverter implements DartTypeVisitor<DartType, Null> {
+  final Entity Function(Entity) toBackendEntity;
+
+  TypeConverter(this.toBackendEntity);
+
+  Map<FunctionTypeVariable, FunctionTypeVariable> _functionTypeVariables =
+      <FunctionTypeVariable, FunctionTypeVariable>{};
+
+  DartType visit(DartType type, [_]) => type.accept(this, null);
+
+  List<DartType> convertTypes(List<DartType> types) => _visitList(types);
+
+  DartType visitVoidType(VoidType type, _) => type;
+  DartType visitDynamicType(DynamicType type, _) => type;
+
+  DartType visitTypeVariableType(TypeVariableType type, _) {
+    return new TypeVariableType(toBackendEntity(type.element));
+  }
+
+  DartType visitFunctionTypeVariable(FunctionTypeVariable type, _) {
+    DartType result = _functionTypeVariables[type];
+    assert(result != null,
+        "Function type variable $type not found in $_functionTypeVariables");
+    return result;
+  }
+
+  DartType visitFunctionType(FunctionType type, _) {
+    List<FunctionTypeVariable> typeVariables = <FunctionTypeVariable>[];
+    for (FunctionTypeVariable typeVariable in type.typeVariables) {
+      typeVariables.add(_functionTypeVariables[typeVariable] =
+          new FunctionTypeVariable(typeVariable.index));
+    }
+    for (FunctionTypeVariable typeVariable in type.typeVariables) {
+      _functionTypeVariables[typeVariable].bound =
+          typeVariable.bound?.accept(this, null);
+    }
+    DartType returnType = type.returnType.accept(this, null);
+    List<DartType> parameterTypes = _visitList(type.parameterTypes);
+    List<DartType> optionalParameterTypes =
+        _visitList(type.optionalParameterTypes);
+    List<DartType> namedParameterTypes = _visitList(type.namedParameterTypes);
+    for (FunctionTypeVariable typeVariable in type.typeVariables) {
+      _functionTypeVariables.remove(typeVariable);
+    }
+    return new FunctionType(returnType, parameterTypes, optionalParameterTypes,
+        type.namedParameters, namedParameterTypes, typeVariables);
+  }
+
+  DartType visitInterfaceType(InterfaceType type, _) {
+    ClassEntity element = toBackendEntity(type.element);
+    List<DartType> args = _visitList(type.typeArguments);
+    return new InterfaceType(element, args);
+  }
+
+  DartType visitTypedefType(TypedefType type, _) {
+    TypedefEntity element = toBackendEntity(type.element);
+    List<DartType> args = _visitList(type.typeArguments);
+    DartType unaliased = visit(type.unaliased);
+    return new TypedefType(element, args, unaliased);
+  }
+
+  @override
+  DartType visitFutureOrType(FutureOrType type, _) {
+    return new FutureOrType(visit(type.typeArgument));
+  }
+
+  List<DartType> _visitList(List<DartType> list) =>
+      list.map<DartType>((t) => t.accept(this, null)).toList();
+}
diff --git a/pkg/compiler/lib/src/js_model/locals.dart b/pkg/compiler/lib/src/js_model/locals.dart
index 6f66920..cfeede7 100644
--- a/pkg/compiler/lib/src/js_model/locals.dart
+++ b/pkg/compiler/lib/src/js_model/locals.dart
@@ -456,9 +456,14 @@
   List<LabelDefinition> _labels;
   final bool isSwitch;
   final bool isSwitchCase;
+  bool isBreakTarget;
+  bool isContinueTarget;
 
   JJumpTarget(this.memberContext, this.nestingLevel,
-      {this.isSwitch: false, this.isSwitchCase: false});
+      {this.isSwitch: false,
+      this.isSwitchCase: false,
+      this.isBreakTarget: false,
+      this.isContinueTarget: false});
 
   /// Deserializes a [JJumpTarget] object from [source].
   factory JJumpTarget.readFromDataSource(DataSource source) {
@@ -467,8 +472,13 @@
     int nestingLevel = source.readInt();
     bool isSwitch = source.readBool();
     bool isSwitchCase = source.readBool();
+    bool isBreakTarget = source.readBool();
+    bool isContinueTarget = source.readBool();
     JJumpTarget target = new JJumpTarget(memberContext, nestingLevel,
-        isSwitch: isSwitch, isSwitchCase: isSwitchCase);
+        isSwitch: isSwitch,
+        isSwitchCase: isSwitchCase,
+        isBreakTarget: isBreakTarget,
+        isContinueTarget: isContinueTarget);
     int labelCount = source.readInt();
     for (int i = 0; i < labelCount; i++) {
       String labelName = source.readString();
@@ -488,6 +498,8 @@
     sink.writeInt(nestingLevel);
     sink.writeBool(isSwitch);
     sink.writeBool(isSwitchCase);
+    sink.writeBool(isBreakTarget);
+    sink.writeBool(isContinueTarget);
     if (_labels != null) {
       sink.writeInt(_labels.length);
       for (LabelDefinition definition in _labels) {
@@ -501,9 +513,6 @@
     sink.end(tag);
   }
 
-  bool isBreakTarget = false;
-  bool isContinueTarget = false;
-
   @override
   LabelDefinition addLabel(String labelName,
       {bool isBreakTarget: false, bool isContinueTarget: false}) {
diff --git a/pkg/compiler/lib/src/kernel/deferred_load.dart b/pkg/compiler/lib/src/kernel/deferred_load.dart
index 4310396..7c1604f 100644
--- a/pkg/compiler/lib/src/kernel/deferred_load.dart
+++ b/pkg/compiler/lib/src/kernel/deferred_load.dart
@@ -8,7 +8,7 @@
 
 import '../common_elements.dart';
 import '../compiler.dart' show Compiler;
-import '../constants/values.dart' show ConstantValue;
+import '../constants/values.dart';
 import '../deferred_load.dart';
 import '../elements/entities.dart';
 import 'element_map.dart';
@@ -186,6 +186,20 @@
   }
 
   @override
+  void visitTypeParameter(ir.TypeParameter node) {
+    // We avoid visiting metadata on the type parameter declaration. The bound
+    // cannot hold constants so we skip that as well.
+  }
+
+  @override
+  void visitVariableDeclaration(ir.VariableDeclaration node) {
+    // We avoid visiting metadata on the parameter declaration by only visiting
+    // the initializer. The type cannot hold constants so can kan skip that
+    // as well.
+    node.initializer?.accept(this);
+  }
+
+  @override
   void visitTypeLiteral(ir.TypeLiteral node) {
     if (node.type is! ir.TypeParameterType) add(node);
   }
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index aeee682..fa90a2d 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -34,16 +34,11 @@
 import '../ir/visitors.dart';
 import '../ir/util.dart';
 import '../js/js.dart' as js;
-import '../js_backend/annotations.dart';
-import '../js_backend/allocator_analysis.dart' show KAllocatorAnalysis;
 import '../js_backend/backend.dart' show JavaScriptBackend;
-import '../js_backend/backend_usage.dart';
 import '../js_backend/constant_system_javascript.dart';
-import '../js_backend/interceptor_data.dart';
 import '../js_backend/namer.dart';
 import '../js_backend/native_data.dart';
 import '../js_backend/no_such_method_registry.dart';
-import '../js_backend/runtime_types.dart';
 import '../js_model/closure.dart';
 import '../js_model/locals.dart';
 import '../native/native.dart' as native;
@@ -52,10 +47,7 @@
 import '../ordered_typeset.dart';
 import '../universe/call_structure.dart';
 import '../universe/class_hierarchy.dart';
-import '../universe/class_set.dart';
 import '../universe/selector.dart';
-import '../universe/world_builder.dart';
-import '../world.dart';
 
 import 'element_map.dart';
 import 'env.dart';
@@ -65,7 +57,9 @@
 part 'native_basic_data.dart';
 part 'no_such_method_resolver.dart';
 
-abstract class KernelToElementMapBase implements IrToElementMap {
+/// Implementation of [KernelToElementMap] that only supports world
+/// impact computation.
+class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
   final CompilerOptions options;
   final DiagnosticReporter reporter;
   CommonElementsImpl _commonElements;
@@ -89,7 +83,32 @@
   final EntityDataMap<IndexedTypedef, KTypedefData> typedefs =
       new EntityDataMap<IndexedTypedef, KTypedefData>();
 
-  KernelToElementMapBase(this.options, this.reporter, Environment environment) {
+  /// Set to `true` before creating the J-World from the K-World to assert that
+  /// no entities are created late.
+  bool envIsClosed = false;
+
+  final Map<ir.Library, IndexedLibrary> libraryMap = {};
+  final Map<ir.Class, IndexedClass> classMap = {};
+  final Map<ir.Typedef, IndexedTypedef> typedefMap = {};
+
+  /// Map from [ir.TypeParameter] nodes to the corresponding
+  /// [TypeVariableEntity].
+  ///
+  /// Normally the type variables are [IndexedTypeVariable]s, but for type
+  /// parameters on local function (in the frontend) these are _not_ since
+  /// their type declaration is neither a class nor a member. In the backend,
+  /// these type parameters belong to the call-method and are therefore indexed.
+  final Map<ir.TypeParameter, TypeVariableEntity> typeVariableMap = {};
+  final Map<ir.Member, IndexedConstructor> constructorMap = {};
+  final Map<ir.Procedure, IndexedFunction> methodMap = {};
+  final Map<ir.Field, IndexedField> fieldMap = {};
+  final Map<ir.TreeNode, Local> localFunctionMap = {};
+
+  native.BehaviorBuilder _nativeBehaviorBuilder;
+  FrontendStrategy _frontendStrategy;
+
+  KernelToElementMapImpl(this.reporter, Environment environment,
+      this._frontendStrategy, this.options) {
     _elementEnvironment = new KernelElementEnvironment(this);
     _commonElements = new CommonElementsImpl(_elementEnvironment);
     _constantEnvironment = new KernelConstantEnvironment(this, environment);
@@ -97,8 +116,6 @@
     _types = new KernelDartTypes(this);
   }
 
-  bool checkFamily(Entity entity);
-
   DartTypes get types => _types;
 
   KernelElementEnvironment get elementEnvironment => _elementEnvironment;
@@ -106,9 +123,6 @@
   @override
   CommonElementsImpl get commonElements => _commonElements;
 
-  /// NativeBasicData is need for computation of the default super class.
-  NativeBasicData get nativeBasicData;
-
   FunctionEntity get _mainFunction {
     return env.mainMethod != null ? getMethodInternal(env.mainMethod) : null;
   }
@@ -119,8 +133,6 @@
         : null;
   }
 
-  Iterable<LibraryEntity> get libraryListInternal;
-
   SourceSpan getSourceSpan(Spannable spannable, Entity currentElement) {
     SourceSpan fromSpannable(Spannable spannable) {
       if (spannable is IndexedLibrary &&
@@ -224,13 +236,9 @@
 
   LibraryEntity getLibrary(ir.Library node) => getLibraryInternal(node);
 
-  LibraryEntity getLibraryInternal(ir.Library node, [KLibraryEnv libraryEnv]);
-
   @override
   ClassEntity getClass(ir.Class node) => getClassInternal(node);
 
-  ClassEntity getClassInternal(ir.Class node, [KClassEnv classEnv]);
-
   InterfaceType getSuperType(IndexedClass cls) {
     assert(checkFamily(cls));
     KClassData data = classes.getData(cls);
@@ -264,8 +272,6 @@
   TypeVariableEntity getTypeVariable(ir.TypeParameter node) =>
       getTypeVariableInternal(node);
 
-  TypeVariableEntity getTypeVariableInternal(ir.TypeParameter node);
-
   void _ensureSupertypes(ClassEntity cls, KClassData data) {
     assert(checkFamily(cls));
     if (data is KClassDataImpl && data.orderedTypeSet == null) {
@@ -347,8 +353,6 @@
     return typedefs.getData(typedef).rawType;
   }
 
-  TypedefEntity getTypedefInternal(ir.Typedef node);
-
   @override
   MemberEntity getMember(ir.Member node) {
     if (node is ir.Field) {
@@ -394,8 +398,6 @@
   ConstructorEntity getConstructor(ir.Member node) =>
       getConstructorInternal(node);
 
-  ConstructorEntity getConstructorInternal(ir.Member node);
-
   ConstructorEntity getSuperConstructor(
       ir.Constructor sourceNode, ir.Member targetNode) {
     ConstructorEntity source = getConstructor(sourceNode);
@@ -417,13 +419,9 @@
   @override
   FunctionEntity getMethod(ir.Procedure node) => getMethodInternal(node);
 
-  FunctionEntity getMethodInternal(ir.Procedure node);
-
   @override
   FieldEntity getField(ir.Field node) => getFieldInternal(node);
 
-  FieldEntity getFieldInternal(ir.Field node);
-
   @override
   DartType getDartType(ir.DartType type) => _typeConverter.convert(type);
 
@@ -510,9 +508,9 @@
 
   ConstantValue computeConstantValue(
       Spannable spannable, ConstantExpression constant,
-      {bool requireConstant: true}) {
+      {bool requireConstant: true, bool checkCasts: true}) {
     return _constantEnvironment._getConstantValue(spannable, constant,
-        constantRequired: requireConstant);
+        constantRequired: requireConstant, checkCasts: checkCasts);
   }
 
   DartType substByContext(DartType type, InterfaceType context) {
@@ -573,12 +571,6 @@
     return data.getBound(this);
   }
 
-  DartType _getTypeVariableDefaultType(IndexedTypeVariable typeVariable) {
-    assert(checkFamily(typeVariable));
-    KTypeVariableData data = typeVariables.getData(typeVariable);
-    return data.getDefaultType(this);
-  }
-
   ClassEntity getAppliedMixin(IndexedClass cls) {
     assert(checkFamily(cls));
     KClassData data = classes.getData(cls);
@@ -624,15 +616,6 @@
     env.forEachConstructor(this, f);
   }
 
-  void forEachConstructorBody(
-      IndexedClass cls, void f(ConstructorBodyEntity member)) {
-    throw new UnsupportedError(
-        'KernelToElementMapBase._forEachConstructorBody');
-  }
-
-  void forEachNestedClosure(
-      MemberEntity member, void f(FunctionEntity closure));
-
   void _forEachLocalClassMember(IndexedClass cls, void f(MemberEntity member)) {
     assert(checkFamily(cls));
     KClassEnv env = classes.getEnv(cls);
@@ -1025,7 +1008,9 @@
   }
 
   ConstantValue getConstantValue(ir.Expression node,
-      {bool requireConstant: true, bool implicitNull: false}) {
+      {bool requireConstant: true,
+      bool implicitNull: false,
+      bool checkCasts: true}) {
     ConstantExpression constant;
     if (node == null) {
       if (!implicitNull) {
@@ -1046,7 +1031,7 @@
     }
     ConstantValue value = computeConstantValue(
         computeSourceSpanFromTreeNode(node), constant,
-        requireConstant: requireConstant);
+        requireConstant: requireConstant, checkCasts: checkCasts);
     if (!value.isConstant && !requireConstant) {
       return null;
     }
@@ -1058,7 +1043,9 @@
     if (annotations.isEmpty) return const <ConstantValue>[];
     List<ConstantValue> metadata = <ConstantValue>[];
     annotations.forEach((ir.Expression node) {
-      metadata.add(getConstantValue(node));
+      // We skip the implicit cast checks for metadata to avoid circular
+      // dependencies in the js-interop class registration.
+      metadata.add(getConstantValue(node, checkCasts: false));
     });
     return metadata;
   }
@@ -1086,41 +1073,6 @@
         failedAt(cls, "No super noSuchMethod found for class $cls."));
     return function;
   }
-}
-
-/// Mixin that implements the abstract methods in [KernelToElementMapBase].
-abstract class ElementCreatorMixin implements KernelToElementMapBase {
-  /// Set to `true` before creating the J-World from the K-World to assert that
-  /// no entities are created late.
-  bool envIsClosed = false;
-  KProgramEnv get env;
-  EntityDataEnvMap<IndexedLibrary, KLibraryData, KLibraryEnv> get libraries;
-  EntityDataEnvMap<IndexedClass, KClassData, KClassEnv> get classes;
-  EntityDataMap<IndexedMember, KMemberData> get members;
-  EntityDataMap<IndexedTypeVariable, KTypeVariableData> get typeVariables;
-  EntityDataMap<IndexedTypedef, KTypedefData> get typedefs;
-
-  final Map<ir.Library, IndexedLibrary> libraryMap = {};
-  final Map<ir.Class, IndexedClass> classMap = {};
-  final Map<ir.Typedef, IndexedTypedef> typedefMap = {};
-
-  /// Map from [ir.TypeParameter] nodes to the corresponding
-  /// [TypeVariableEntity].
-  ///
-  /// Normally the type variables are [IndexedTypeVariable]s, but for type
-  /// parameters on local function (in the frontend) these are _not_ since
-  /// their type declaration is neither a class nor a member. In the backend,
-  /// these type parameters belong to the call-method and are therefore indexed.
-  final Map<ir.TypeParameter, TypeVariableEntity> typeVariableMap = {};
-  final Map<ir.Member, IndexedConstructor> constructorMap = {};
-  final Map<ir.Procedure, IndexedFunction> methodMap = {};
-  final Map<ir.Field, IndexedField> fieldMap = {};
-  final Map<ir.TreeNode, Local> localFunctionMap = {};
-
-  Name getName(ir.Name node);
-  FunctionType getFunctionType(ir.FunctionNode node);
-  MemberEntity getMember(ir.Member node);
-  Entity getClosure(ir.FunctionDeclaration node);
 
   Iterable<LibraryEntity> get libraryListInternal {
     if (env.length != libraryMap.length) {
@@ -1225,6 +1177,11 @@
                   getMethodInternal(procedure), node.name, index),
               new KTypeVariableData(node));
         }
+      } else if (func.parent is ir.FunctionDeclaration ||
+          func.parent is ir.FunctionExpression) {
+        // Ensure that local function type variables have been created.
+        getLocalFunction(func.parent);
+        return typeVariableMap[node];
       } else {
         throw new UnsupportedError('Unsupported function type parameter parent '
             'node ${func.parent}.');
@@ -1354,60 +1311,6 @@
         field, new KFieldDataImpl(node));
   }
 
-  IndexedLibrary createLibrary(String name, Uri canonicalUri);
-
-  IndexedClass createClass(LibraryEntity library, String name,
-      {bool isAbstract});
-
-  IndexedTypedef createTypedef(LibraryEntity library, String name);
-
-  TypeVariableEntity createTypeVariable(
-      Entity typeDeclaration, String name, int index);
-
-  IndexedConstructor createGenerativeConstructor(ClassEntity enclosingClass,
-      Name name, ParameterStructure parameterStructure,
-      {bool isExternal, bool isConst});
-
-  IndexedConstructor createFactoryConstructor(ClassEntity enclosingClass,
-      Name name, ParameterStructure parameterStructure,
-      {bool isExternal, bool isConst, bool isFromEnvironmentConstructor});
-
-  IndexedFunction createGetter(LibraryEntity library,
-      ClassEntity enclosingClass, Name name, AsyncMarker asyncMarker,
-      {bool isStatic, bool isExternal, bool isAbstract});
-
-  IndexedFunction createMethod(
-      LibraryEntity library,
-      ClassEntity enclosingClass,
-      Name name,
-      ParameterStructure parameterStructure,
-      AsyncMarker asyncMarker,
-      {bool isStatic,
-      bool isExternal,
-      bool isAbstract});
-
-  IndexedFunction createSetter(
-      LibraryEntity library, ClassEntity enclosingClass, Name name,
-      {bool isStatic, bool isExternal, bool isAbstract});
-
-  IndexedField createField(
-      LibraryEntity library, ClassEntity enclosingClass, Name name,
-      {bool isStatic, bool isAssignable, bool isConst});
-}
-
-/// Implementation of [KernelToElementMap] that only supports world
-/// impact computation.
-class KernelToElementMapImpl extends KernelToElementMapBase
-    with ElementCreatorMixin
-    implements KernelToElementMap {
-  native.BehaviorBuilder _nativeBehaviorBuilder;
-  FrontendStrategy _frontendStrategy;
-
-  KernelToElementMapImpl(DiagnosticReporter reporter, Environment environment,
-      this._frontendStrategy, CompilerOptions options)
-      : super(options, reporter, environment);
-
-  @override
   bool checkFamily(Entity entity) {
     assert(
         '$entity'.startsWith(kElementPrefix),
@@ -1416,24 +1319,7 @@
     return true;
   }
 
-  DartType getTypeVariableBound(TypeVariableEntity typeVariable) {
-    if (typeVariable is KLocalTypeVariable) return typeVariable.bound;
-    return super.getTypeVariableBound(typeVariable);
-  }
-
-  DartType _getTypeVariableDefaultType(TypeVariableEntity typeVariable) {
-    if (typeVariable is KLocalTypeVariable) return typeVariable.defaultType;
-    return super._getTypeVariableDefaultType(typeVariable);
-  }
-
-  @override
-  void forEachNestedClosure(
-      MemberEntity member, void f(FunctionEntity closure)) {
-    throw new UnsupportedError(
-        "KernelToElementMapForImpactImpl._forEachNestedClosure");
-  }
-
-  @override
+  /// NativeBasicData is need for computation of the default super class.
   NativeBasicData get nativeBasicData => _frontendStrategy.nativeBasicData;
 
   /// Adds libraries in [component] to the set of libraries.
@@ -1469,11 +1355,6 @@
   }
 
   @override
-  Entity getClosure(ir.FunctionDeclaration node) {
-    return getLocalFunction(node);
-  }
-
-  @override
   Local getLocalFunction(ir.TreeNode node) {
     assert(
         node is ir.FunctionDeclaration || node is ir.FunctionExpression,
@@ -1657,7 +1538,6 @@
     return new KClass(library, name, isAbstract: isAbstract);
   }
 
-  @override
   IndexedTypedef createTypedef(LibraryEntity library, String name) {
     return new KTypedef(library, name);
   }
@@ -1721,7 +1601,7 @@
 
 class KernelElementEnvironment extends ElementEnvironment
     implements KElementEnvironment {
-  final KernelToElementMapBase elementMap;
+  final KernelToElementMapImpl elementMap;
 
   KernelElementEnvironment(this.elementMap);
 
@@ -1769,6 +1649,7 @@
 
   @override
   DartType getTypeVariableBound(TypeVariableEntity typeVariable) {
+    if (typeVariable is KLocalTypeVariable) return typeVariable.bound;
     return elementMap.getTypeVariableBound(typeVariable);
   }
 
@@ -2019,7 +1900,7 @@
 /// Constant environment mapping [ConstantExpression]s to [ConstantValue]s using
 /// [_EvaluationEnvironment] for the evaluation.
 class KernelConstantEnvironment implements ConstantEnvironment {
-  final KernelToElementMapBase _elementMap;
+  final KernelToElementMapImpl _elementMap;
   final Environment _environment;
 
   Map<ConstantExpression, ConstantValue> _valueMap =
@@ -2032,11 +1913,11 @@
 
   ConstantValue _getConstantValue(
       Spannable spannable, ConstantExpression expression,
-      {bool constantRequired}) {
+      {bool constantRequired, bool checkCasts: true}) {
     return _valueMap.putIfAbsent(expression, () {
       return expression.evaluate(
           new KernelEvaluationEnvironment(_elementMap, _environment, spannable,
-              constantRequired: constantRequired),
+              constantRequired: constantRequired, checkCasts: checkCasts),
           constantSystem);
     });
   }
@@ -2045,12 +1926,13 @@
 /// Evaluation environment used for computing [ConstantValue]s for
 /// kernel based [ConstantExpression]s.
 class KernelEvaluationEnvironment extends EvaluationEnvironmentBase {
-  final KernelToElementMapBase _elementMap;
+  final KernelToElementMapImpl _elementMap;
   final Environment _environment;
+  final bool checkCasts;
 
   KernelEvaluationEnvironment(
       this._elementMap, this._environment, Spannable spannable,
-      {bool constantRequired})
+      {bool constantRequired, this.checkCasts: true})
       : super(spannable, constantRequired: constantRequired);
 
   @override
@@ -2091,71 +1973,6 @@
   bool get enableAssertions => _elementMap.options.enableUserAssertions;
 }
 
-class KClosedWorldImpl extends ClosedWorldRtiNeedMixin implements KClosedWorld {
-  final KernelToElementMapImpl elementMap;
-  final KElementEnvironment elementEnvironment;
-  final DartTypes dartTypes;
-  final KCommonElements commonElements;
-  final NativeData nativeData;
-  final InterceptorData interceptorData;
-  final BackendUsage backendUsage;
-  final NoSuchMethodData noSuchMethodData;
-
-  final Map<ClassEntity, Set<ClassEntity>> mixinUses;
-
-  final Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses;
-
-  // TODO(johnniwinther): Can this be derived from [ClassSet]s?
-  final Set<ClassEntity> _implementedClasses;
-
-  final Iterable<MemberEntity> liveInstanceMembers;
-
-  /// Members that are written either directly or through a setter selector.
-  final Iterable<MemberEntity> assignedInstanceMembers;
-  final KAllocatorAnalysis allocatorAnalysis;
-
-  final Iterable<ClassEntity> liveNativeClasses;
-
-  final Iterable<MemberEntity> processedMembers;
-
-  final ClassHierarchy classHierarchy;
-
-  final AnnotationsData annotationsData;
-
-  KClosedWorldImpl(this.elementMap,
-      {CompilerOptions options,
-      this.elementEnvironment,
-      this.dartTypes,
-      this.commonElements,
-      this.nativeData,
-      this.interceptorData,
-      this.backendUsage,
-      this.noSuchMethodData,
-      ResolutionWorldBuilder resolutionWorldBuilder,
-      RuntimeTypesNeedBuilder rtiNeedBuilder,
-      this.allocatorAnalysis,
-      Set<ClassEntity> implementedClasses,
-      this.liveNativeClasses,
-      this.liveInstanceMembers,
-      this.assignedInstanceMembers,
-      this.processedMembers,
-      this.mixinUses,
-      this.typesImplementedBySubclasses,
-      Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes,
-      Map<ClassEntity, ClassSet> classSets,
-      this.annotationsData})
-      : _implementedClasses = implementedClasses,
-        classHierarchy = new ClassHierarchyImpl(
-            commonElements, classHierarchyNodes, classSets) {
-    computeRtiNeed(resolutionWorldBuilder, rtiNeedBuilder, options);
-  }
-
-  /// Returns `true` if [cls] is implemented by an instantiated class.
-  bool isImplemented(ClassEntity cls) {
-    return _implementedClasses.contains(cls);
-  }
-}
-
 class KernelNativeMemberResolver extends NativeMemberResolverBase {
   final KernelToElementMap elementMap;
   final NativeBasicData nativeBasicData;
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index e82ef91..95845cb 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -10,7 +10,7 @@
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/clone.dart';
 import 'package:kernel/type_algebra.dart';
-import 'package:collection/algorithms.dart' show mergeSort; // a stable sort.
+import 'package:collection/collection.dart' show mergeSort; // a stable sort.
 
 import '../common.dart';
 import '../constants/constructors.dart';
@@ -200,11 +200,11 @@
 
   KLibraryData(this.library);
 
-  Iterable<ConstantValue> getMetadata(KernelToElementMapBase elementMap) {
+  Iterable<ConstantValue> getMetadata(KernelToElementMapImpl elementMap) {
     return _metadata ??= elementMap.getMetadata(library.annotations);
   }
 
-  Iterable<ImportEntity> getImports(KernelToElementMapBase elementMap) {
+  Iterable<ImportEntity> getImports(KernelToElementMapImpl elementMap) {
     if (imports == null) {
       List<ir.LibraryDependency> dependencies = library.dependencies;
       if (dependencies.isEmpty) {
@@ -244,7 +244,7 @@
   bool get isSuperMixinApplication;
 
   /// Ensures that all members have been computed for [cls].
-  void ensureMembers(KernelToElementMapBase elementMap);
+  void ensureMembers(KernelToElementMapImpl elementMap);
 
   /// Return the [MemberEntity] for the member [name] in the class. If [setter]
   /// is `true`, the setter or assignable field corresponding to [name] is
@@ -353,11 +353,11 @@
         initializers: <ir.Initializer>[superInitializer]);
   }
 
-  void ensureMembers(KernelToElementMapBase elementMap) {
+  void ensureMembers(KernelToElementMapImpl elementMap) {
     _ensureMaps(elementMap);
   }
 
-  void _ensureMaps(KernelToElementMapBase elementMap) {
+  void _ensureMaps(KernelToElementMapImpl elementMap) {
     if (_memberMap != null) return;
 
     _memberMap = <String, ir.Member>{};
@@ -640,7 +640,7 @@
   DartType get callType => null;
 
   Iterable<ConstantValue> getMetadata(
-      covariant KernelToElementMapBase elementMap) {
+      covariant KernelToElementMapImpl elementMap) {
     return _metadata ??= elementMap.getMetadata(node.annotations);
   }
 
@@ -670,7 +670,7 @@
   KMemberDataImpl(this.node);
 
   Iterable<ConstantValue> getMetadata(
-      covariant KernelToElementMapBase elementMap) {
+      covariant KernelToElementMapImpl elementMap) {
     return _metadata ??= elementMap.getMetadata(node.annotations);
   }
 
@@ -698,7 +698,7 @@
   List<TypeVariableType> _typeVariables;
 
   List<TypeVariableType> getFunctionTypeVariables(
-      covariant KernelToElementMapBase elementMap) {
+      covariant KernelToElementMapImpl elementMap) {
     if (_typeVariables == null) {
       if (functionNode.typeParameters.isEmpty) {
         _typeVariables = const <TypeVariableType>[];
@@ -729,7 +729,7 @@
 
   KFunctionDataImpl(ir.Member node, this.functionNode) : super(node);
 
-  FunctionType getFunctionType(covariant KernelToElementMapBase elementMap) {
+  FunctionType getFunctionType(covariant KernelToElementMapImpl elementMap) {
     return _type ??= elementMap.getFunctionType(functionNode);
   }
 
@@ -773,7 +773,7 @@
 
 abstract class KConstructorData extends KFunctionData {
   ConstantConstructor getConstructorConstant(
-      KernelToElementMapBase elementMap, ConstructorEntity constructor);
+      KernelToElementMapImpl elementMap, ConstructorEntity constructor);
 }
 
 class KConstructorDataImpl extends KFunctionDataImpl
@@ -785,7 +785,7 @@
       : super(node, functionNode);
 
   ConstantConstructor getConstructorConstant(
-      KernelToElementMapBase elementMap, ConstructorEntity constructor) {
+      KernelToElementMapImpl elementMap, ConstructorEntity constructor) {
     if (_constantConstructor == null) {
       if (node is ir.Constructor && constructor.isConst) {
         _constantConstructor =
@@ -820,15 +820,15 @@
   DartType getFieldType(IrToElementMap elementMap);
 
   ConstantExpression getFieldConstantExpression(
-      KernelToElementMapBase elementMap);
+      KernelToElementMapImpl elementMap);
 
   /// Return the [ConstantValue] the initial value of [field] or `null` if
   /// the initializer is not a constant expression.
-  ConstantValue getFieldConstantValue(KernelToElementMapBase elementMap);
+  ConstantValue getFieldConstantValue(KernelToElementMapImpl elementMap);
 
-  bool hasConstantFieldInitializer(KernelToElementMapBase elementMap);
+  bool hasConstantFieldInitializer(KernelToElementMapImpl elementMap);
 
-  ConstantValue getConstantFieldInitializer(KernelToElementMapBase elementMap);
+  ConstantValue getConstantFieldInitializer(KernelToElementMapImpl elementMap);
 }
 
 class KFieldDataImpl extends KMemberDataImpl implements KFieldData {
@@ -841,12 +841,12 @@
 
   ir.Field get node => super.node;
 
-  DartType getFieldType(covariant KernelToElementMapBase elementMap) {
+  DartType getFieldType(covariant KernelToElementMapImpl elementMap) {
     return _type ??= elementMap.getDartType(node.type);
   }
 
   ConstantExpression getFieldConstantExpression(
-      KernelToElementMapBase elementMap) {
+      KernelToElementMapImpl elementMap) {
     if (_constantExpression == null) {
       if (node.isConst) {
         _constantExpression =
@@ -862,7 +862,7 @@
   }
 
   @override
-  ConstantValue getFieldConstantValue(KernelToElementMapBase elementMap) {
+  ConstantValue getFieldConstantValue(KernelToElementMapImpl elementMap) {
     if (!_isConstantComputed) {
       _constantValue = elementMap.getConstantValue(node.initializer,
           requireConstant: node.isConst, implicitNull: !node.isConst);
@@ -872,12 +872,12 @@
   }
 
   @override
-  bool hasConstantFieldInitializer(KernelToElementMapBase elementMap) {
+  bool hasConstantFieldInitializer(KernelToElementMapImpl elementMap) {
     return getFieldConstantValue(elementMap) != null;
   }
 
   @override
-  ConstantValue getConstantFieldInitializer(KernelToElementMapBase elementMap) {
+  ConstantValue getConstantFieldInitializer(KernelToElementMapImpl elementMap) {
     ConstantValue value = getFieldConstantValue(elementMap);
     assert(
         value != null,
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index 7aa7324..340f2b8 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -35,14 +35,8 @@
     CompilerOptions options) {
   KernelImpactBuilder builder = new KernelImpactBuilder(
       elementMap, elementMap.getMember(member), reporter, options);
-  if (member is ir.Procedure) {
-    return builder.buildProcedure(member);
-  } else if (member is ir.Constructor) {
-    return builder.buildConstructor(member);
-  } else if (member is ir.Field) {
-    return builder.buildField(member);
-  }
-  throw new UnsupportedError("Unsupported member: $member");
+  member.accept(builder);
+  return builder.impactBuilder;
 }
 
 class KernelImpactBuilder extends StaticTypeVisitor {
@@ -80,28 +74,31 @@
     return type;
   }
 
+  List<DartType> _getTypeArguments(ir.Arguments arguments) {
+    if (arguments.types.isEmpty) return null;
+    return arguments.types.map(elementMap.getDartType).toList();
+  }
+
   /// Add checked-mode type use for the parameter type and constant for the
   /// default value of [parameter].
+  @override
   void handleParameter(ir.VariableDeclaration parameter) {
     checkType(parameter.type, TypeUseKind.PARAMETER_CHECK);
-    visitNode(parameter.initializer);
   }
 
   /// Add checked-mode type use for parameter and return types, and add
   /// constants for default values.
+  @override
   void handleSignature(ir.FunctionNode node) {
-    node.positionalParameters.forEach(handleParameter);
-    node.namedParameters.forEach(handleParameter);
     for (ir.TypeParameter parameter in node.typeParameters) {
       checkType(parameter.bound, TypeUseKind.PARAMETER_CHECK);
     }
   }
 
-  ResolutionImpact buildField(ir.Field field) {
-    typeEnvironment.thisType = field.enclosingClass?.thisType;
+  @override
+  void handleField(ir.Field field) {
     checkType(field.type, TypeUseKind.PARAMETER_CHECK);
     if (field.initializer != null) {
-      visitNode(field.initializer);
       if (!field.isInstanceMember &&
           !field.isConst &&
           field.initializer is! ir.NullLiteral) {
@@ -120,23 +117,16 @@
       impactBuilder
           .registerNativeData(elementMap.getNativeBehaviorForFieldStore(field));
     }
-    typeEnvironment.thisType = null;
-    return impactBuilder;
   }
 
-  ResolutionImpact buildConstructor(ir.Constructor constructor) {
-    typeEnvironment.thisType = constructor.enclosingClass.thisType;
-    handleSignature(constructor.function);
-    visitNodes(constructor.initializers);
-    visitNode(constructor.function.body);
+  @override
+  void handleConstructor(ir.Constructor constructor) {
     MemberEntity member = elementMap.getMember(constructor);
     if (constructor.isExternal && !commonElements.isForeignHelper(member)) {
       bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
       impactBuilder.registerNativeData(elementMap
           .getNativeBehaviorForMethod(constructor, isJsInterop: isJsInterop));
     }
-    typeEnvironment.thisType = null;
-    return impactBuilder;
   }
 
   void handleAsyncMarker(ir.FunctionNode function) {
@@ -181,10 +171,8 @@
     }
   }
 
-  ResolutionImpact buildProcedure(ir.Procedure procedure) {
-    typeEnvironment.thisType = procedure.enclosingClass?.thisType;
-    handleSignature(procedure.function);
-    visitNode(procedure.function.body);
+  @override
+  void handleProcedure(ir.Procedure procedure) {
     handleAsyncMarker(procedure.function);
     MemberEntity member = elementMap.getMember(procedure);
     if (procedure.isExternal && !commonElements.isForeignHelper(member)) {
@@ -192,124 +180,70 @@
       impactBuilder.registerNativeData(elementMap
           .getNativeBehaviorForMethod(procedure, isJsInterop: isJsInterop));
     }
-    typeEnvironment.thisType = null;
-    return impactBuilder;
   }
 
   @override
-  Null visitBlock(ir.Block node) => visitNodes(node.statements);
-
-  @override
-  Null visitExpressionStatement(ir.ExpressionStatement node) {
-    visitNode(node.expression);
-  }
-
-  @override
-  Null visitReturnStatement(ir.ReturnStatement node) {
-    visitNode(node.expression);
-  }
-
-  @override
-  Null visitIfStatement(ir.IfStatement node) {
-    visitNode(node.condition);
-    visitNode(node.then);
-    visitNode(node.otherwise);
-  }
-
-  @override
-  ir.DartType visitIntLiteral(ir.IntLiteral node) {
+  void handleIntLiteral(ir.IntLiteral node) {
     impactBuilder.registerConstantLiteral(
         new IntConstantExpression(new BigInt.from(node.value).toUnsigned(64)));
-    return super.visitIntLiteral(node);
   }
 
   @override
-  ir.DartType visitDoubleLiteral(ir.DoubleLiteral node) {
+  void handleDoubleLiteral(ir.DoubleLiteral node) {
     impactBuilder
         .registerConstantLiteral(new DoubleConstantExpression(node.value));
-    return super.visitDoubleLiteral(node);
   }
 
   @override
-  ir.DartType visitBoolLiteral(ir.BoolLiteral node) {
+  void handleBoolLiteral(ir.BoolLiteral node) {
     impactBuilder
         .registerConstantLiteral(new BoolConstantExpression(node.value));
-    return super.visitBoolLiteral(node);
   }
 
   @override
-  ir.DartType visitStringLiteral(ir.StringLiteral node) {
+  void handleStringLiteral(ir.StringLiteral node) {
     impactBuilder
         .registerConstantLiteral(new StringConstantExpression(node.value));
-    return super.visitStringLiteral(node);
   }
 
   @override
-  ir.DartType visitSymbolLiteral(ir.SymbolLiteral node) {
+  void handleSymbolLiteral(ir.SymbolLiteral node) {
     impactBuilder.registerConstSymbolName(node.value);
-    return super.visitSymbolLiteral(node);
   }
 
   @override
-  ir.DartType visitNullLiteral(ir.NullLiteral node) {
+  void handleNullLiteral(ir.NullLiteral node) {
     impactBuilder.registerConstantLiteral(new NullConstantExpression());
-    return super.visitNullLiteral(node);
   }
 
   @override
-  ir.DartType visitListLiteral(ir.ListLiteral node) {
-    visitNodes(node.expressions);
+  void handleListLiteral(ir.ListLiteral node) {
     DartType elementType = elementMap.getDartType(node.typeArgument);
 
     impactBuilder.registerListLiteral(new ListLiteralUse(
         commonElements.listType(elementType),
         isConstant: node.isConst,
         isEmpty: node.expressions.isEmpty));
-    return super.visitListLiteral(node);
   }
 
   @override
-  ir.DartType visitMapLiteral(ir.MapLiteral node) {
-    visitNodes(node.entries);
+  void handleMapLiteral(ir.MapLiteral node) {
     DartType keyType = elementMap.getDartType(node.keyType);
     DartType valueType = elementMap.getDartType(node.valueType);
     impactBuilder.registerMapLiteral(new MapLiteralUse(
         commonElements.mapType(keyType, valueType),
         isConstant: node.isConst,
         isEmpty: node.entries.isEmpty));
-    return super.visitMapLiteral(node);
   }
 
   @override
-  Null visitMapEntry(ir.MapEntry entry) {
-    visitNode(entry.key);
-    visitNode(entry.value);
-  }
-
-  @override
-  ir.DartType visitConditionalExpression(ir.ConditionalExpression node) {
-    visitNode(node.condition);
-    visitNode(node.then);
-    visitNode(node.otherwise);
-    return super.visitConditionalExpression(node);
-  }
-
-  List<DartType> _visitArguments(ir.Arguments arguments) {
-    visitNodes(arguments.positional);
-    visitNodes(arguments.named);
-    if (arguments.types.isEmpty) return null;
-    return arguments.types.map(elementMap.getDartType).toList();
-  }
-
-  @override
-  ir.DartType visitConstructorInvocation(ir.ConstructorInvocation node) {
+  void handleConstructorInvocation(ir.ConstructorInvocation node,
+      ArgumentTypes argumentTypes, ir.DartType resultType) {
     handleNew(node, node.target, isConst: node.isConst);
-    return super.visitConstructorInvocation(node);
   }
 
   void handleNew(ir.InvocationExpression node, ir.Member target,
       {bool isConst: false}) {
-    _visitArguments(node.arguments);
     ConstructorEntity constructor = elementMap.getConstructor(target);
     if (commonElements.isSymbolConstructor(constructor)) {
       impactBuilder.registerFeature(Feature.SYMBOL_CONSTRUCTOR);
@@ -350,20 +284,20 @@
   }
 
   @override
-  Null visitSuperInitializer(ir.SuperInitializer node) {
+  Null handleSuperInitializer(
+      ir.SuperInitializer node, ArgumentTypes argumentTypes) {
     // TODO(johnniwinther): Maybe rewrite `node.target` to point to a
     // synthesized unnamed mixin constructor when needed. This would require us
     // to consider impact building a required pre-step for inference and
     // ssa-building.
     ConstructorEntity target =
         elementMap.getSuperConstructor(node.parent, node.target);
-    _visitArguments(node.arguments);
     impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke(
         target, elementMap.getCallStructure(node.arguments)));
   }
 
-  @override
-  ir.DartType visitStaticInvocation(ir.StaticInvocation node) {
+  void handleStaticInvocation(ir.StaticInvocation node,
+      ArgumentTypes argumentTypes, ir.DartType returnType) {
     if (node.target.kind == ir.ProcedureKind.Factory) {
       // TODO(johnniwinther): We should not mark the type as instantiated but
       // rather follow the type arguments directly.
@@ -390,10 +324,10 @@
       handleNew(node, node.target, isConst: node.isConst);
     } else {
       FunctionEntity target = elementMap.getMethod(node.target);
-      List<DartType> typeArguments = _visitArguments(node.arguments);
+      List<DartType> typeArguments = _getTypeArguments(node.arguments);
       if (commonElements.isExtractTypeArguments(target)) {
         _handleExtractTypeArguments(node, target, typeArguments);
-        return super.visitStaticInvocation(node);
+        return;
       }
       impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
           target, elementMap.getCallStructure(node.arguments), typeArguments));
@@ -421,7 +355,6 @@
       case ForeignKind.NONE:
         break;
     }
-    return super.visitStaticInvocation(node);
   }
 
   void _handleExtractTypeArguments(ir.StaticInvocation node,
@@ -453,7 +386,7 @@
   }
 
   @override
-  ir.DartType visitStaticGet(ir.StaticGet node) {
+  void handleStaticGet(ir.StaticGet node, ir.DartType resultType) {
     ir.Member target = node.target;
     if (target is ir.Procedure && target.kind == ir.ProcedureKind.Method) {
       FunctionEntity method = elementMap.getMethod(target);
@@ -462,20 +395,18 @@
       MemberEntity member = elementMap.getMember(target);
       impactBuilder.registerStaticUse(new StaticUse.staticGet(member));
     }
-    return super.visitStaticGet(node);
   }
 
   @override
-  ir.DartType visitStaticSet(ir.StaticSet node) {
+  void handleStaticSet(ir.StaticSet node, ir.DartType valueType) {
     MemberEntity member = elementMap.getMember(node.target);
     impactBuilder.registerStaticUse(new StaticUse.staticSet(member));
-    return super.visitStaticSet(node);
   }
 
   void handleSuperInvocation(ir.Name name, ir.Node arguments) {
     FunctionEntity method =
         elementMap.getSuperMember(currentMember, name, setter: false);
-    List<DartType> typeArguments = _visitArguments(arguments);
+    List<DartType> typeArguments = _getTypeArguments(arguments);
     if (method != null) {
       impactBuilder.registerStaticUse(new StaticUse.superInvoke(
           method, elementMap.getCallStructure(arguments), typeArguments));
@@ -488,8 +419,12 @@
   }
 
   @override
-  ir.DartType visitDirectMethodInvocation(ir.DirectMethodInvocation node) {
-    List<DartType> typeArguments = _visitArguments(node.arguments);
+  void handleDirectMethodInvocation(
+      ir.DirectMethodInvocation node,
+      ir.DartType receiverType,
+      ArgumentTypes argumentTypes,
+      ir.DartType returnType) {
+    List<DartType> typeArguments = _getTypeArguments(node.arguments);
     MemberEntity member = elementMap.getMember(node.target);
     // TODO(johnniwinther): Restrict the dynamic use to only match the known
     // target.
@@ -501,15 +436,14 @@
             member.memberName, elementMap.getCallStructure(node.arguments)),
         constraint,
         typeArguments));
-    return super.visitDirectMethodInvocation(node);
   }
 
   @override
-  ir.DartType visitSuperMethodInvocation(ir.SuperMethodInvocation node) {
+  void handleSuperMethodInvocation(ir.SuperMethodInvocation node,
+      ArgumentTypes argumentTypes, ir.DartType returnType) {
     // TODO(johnniwinther): Should we support this or always use the
     // [MixinFullResolution] transformer?
     handleSuperInvocation(node.name, node.arguments);
-    return super.visitSuperMethodInvocation(node);
   }
 
   void handleSuperGet(ir.Name name, ir.Member target) {
@@ -530,18 +464,18 @@
   }
 
   @override
-  ir.DartType visitDirectPropertyGet(ir.DirectPropertyGet node) {
+  void handleDirectPropertyGet(ir.DirectPropertyGet node,
+      ir.DartType receiverType, ir.DartType resultType) {
     // TODO(johnniwinther): Restrict the dynamic use to only match the known
     // target.
     impactBuilder.registerDynamicUse(new DynamicUse(
         new Selector.getter(elementMap.getMember(node.target).memberName)));
-    return super.visitDirectPropertyGet(node);
   }
 
   @override
-  ir.DartType visitSuperPropertyGet(ir.SuperPropertyGet node) {
+  void handleSuperPropertyGet(
+      ir.SuperPropertyGet node, ir.DartType resultType) {
     handleSuperGet(node.name, node.interfaceTarget);
-    return super.visitSuperPropertyGet(node);
   }
 
   void handleSuperSet(ir.Name name, ir.Node target, ir.Node value) {
@@ -562,32 +496,27 @@
   }
 
   @override
-  ir.DartType visitDirectPropertySet(ir.DirectPropertySet node) {
+  void handleDirectPropertySet(ir.DirectPropertySet node,
+      ir.DartType receiverType, ir.DartType valueType) {
     // TODO(johnniwinther): Restrict the dynamic use to only match the known
     // target.
     impactBuilder.registerDynamicUse(new DynamicUse(
         new Selector.setter(elementMap.getMember(node.target).memberName)));
-    return super.visitDirectPropertySet(node);
   }
 
   @override
-  ir.DartType visitSuperPropertySet(ir.SuperPropertySet node) {
+  void handleSuperPropertySet(ir.SuperPropertySet node, ir.DartType valueType) {
     handleSuperSet(node.name, node.interfaceTarget, node.value);
-    return super.visitSuperPropertySet(node);
   }
 
   @override
-  ir.DartType visitMethodInvocation(ir.MethodInvocation node) {
+  void handleMethodInvocation(
+      ir.MethodInvocation node,
+      ir.DartType receiverType,
+      ArgumentTypes argumentTypes,
+      ir.DartType returnType) {
     Selector selector = elementMap.getSelector(node);
-    List<DartType> typeArguments;
-    if (isSpecialCasedBinaryOperator(node.interfaceTarget)) {
-      typeArguments = <DartType>[];
-    } else {
-      typeArguments = _visitArguments(node.arguments);
-    }
-    ir.DartType receiverType = visitNode(node.receiver);
-    ir.DartType returnType = computeMethodInvocationType(node, receiverType);
-    receiverType = narrowInstanceReceiver(node.interfaceTarget, receiverType);
+    List<DartType> typeArguments = _getTypeArguments(node.arguments);
     var receiver = node.receiver;
     if (receiver is ir.VariableGet &&
         receiver.variable.isFinal &&
@@ -648,16 +577,12 @@
         }
       }
     }
-    return returnType;
   }
 
   @override
-  ir.DartType visitPropertyGet(ir.PropertyGet node) {
+  void handlePropertyGet(
+      ir.PropertyGet node, ir.DartType receiverType, ir.DartType resultType) {
     Object constraint;
-    ir.DartType receiverType = visitNode(node.receiver);
-    ir.DartType resultType = computePropertyGetType(node, receiverType);
-    receiverType = narrowInstanceReceiver(node.interfaceTarget, receiverType);
-
     DartType receiverDartType = elementMap.getDartType(receiverType);
     if (receiverDartType is InterfaceType) {
       constraint = new StrongModeConstraint(
@@ -691,14 +616,12 @@
       }
       impactBuilder.registerRuntimeTypeUse(runtimeTypeUse);
     }
-    return resultType;
   }
 
   @override
-  ir.DartType visitPropertySet(ir.PropertySet node) {
+  void handlePropertySet(
+      ir.PropertySet node, ir.DartType receiverType, ir.DartType valueType) {
     Object constraint;
-    ir.DartType receiverType = visitNode(node.receiver);
-    receiverType = narrowInstanceReceiver(node.interfaceTarget, receiverType);
     DartType receiverDartType = elementMap.getDartType(receiverType);
     if (receiverDartType is InterfaceType) {
       constraint = new StrongModeConstraint(
@@ -707,95 +630,73 @@
     impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
         new Selector.setter(elementMap.getName(node.name)),
         constraint, const <DartType>[]));
-    return super.visitPropertySet(node);
   }
 
   @override
-  Null visitAssertStatement(ir.AssertStatement node) {
+  void handleAssertStatement(ir.AssertStatement node) {
     impactBuilder.registerFeature(
         node.message != null ? Feature.ASSERT_WITH_MESSAGE : Feature.ASSERT);
-    visitNode(node.condition);
-    visitNode(node.message);
   }
 
   @override
-  ir.DartType visitInstantiation(ir.Instantiation node) {
+  void handleInstantiation(ir.Instantiation node,
+      ir.FunctionType expressionType, ir.DartType resultType) {
     // TODO(johnniwinther): Track which arities are used in instantiation.
-    ir.FunctionType expressionType = visitNode(node.expression);
     impactBuilder.registerInstantiation(new GenericInstantiation(
         elementMap.getDartType(expressionType),
         node.typeArguments.map(elementMap.getDartType).toList()));
-    return computeInstantiationType(node, expressionType);
   }
 
   @override
-  ir.DartType visitStringConcatenation(ir.StringConcatenation node) {
+  void handleStringConcatenation(ir.StringConcatenation node) {
     impactBuilder.registerFeature(Feature.STRING_INTERPOLATION);
     impactBuilder.registerFeature(Feature.STRING_JUXTAPOSITION);
-    visitNodes(node.expressions);
-    return super.visitStringConcatenation(node);
   }
 
   @override
-  Null visitFunctionDeclaration(ir.FunctionDeclaration node) {
+  Null handleFunctionDeclaration(ir.FunctionDeclaration node) {
     Local function = elementMap.getLocalFunction(node);
     impactBuilder.registerStaticUse(new StaticUse.closure(function));
-    handleSignature(node.function);
     handleAsyncMarker(node.function);
-    visitNode(node.function.body);
   }
 
   @override
-  ir.DartType visitFunctionExpression(ir.FunctionExpression node) {
+  void handleFunctionExpression(ir.FunctionExpression node) {
     Local function = elementMap.getLocalFunction(node);
     impactBuilder.registerStaticUse(new StaticUse.closure(function));
-    handleSignature(node.function);
     handleAsyncMarker(node.function);
-    visitNode(node.function.body);
-    return super.visitFunctionExpression(node);
   }
 
   @override
-  Null visitVariableDeclaration(ir.VariableDeclaration node) {
-    if (node.initializer != null) {
-      visitNode(node.initializer);
-    } else {
+  void handleVariableDeclaration(ir.VariableDeclaration node) {
+    if (node.initializer == null) {
       impactBuilder.registerFeature(Feature.LOCAL_WITHOUT_INITIALIZER);
     }
   }
 
   @override
-  ir.DartType visitIsExpression(ir.IsExpression node) {
+  void handleIsExpression(ir.IsExpression node) {
     impactBuilder.registerTypeUse(
         new TypeUse.isCheck(elementMap.getDartType(node.type)));
-    visitNode(node.operand);
-    return super.visitIsExpression(node);
   }
 
   @override
-  ir.DartType visitAsExpression(ir.AsExpression node) {
+  void handleAsExpression(ir.AsExpression node) {
     DartType type = elementMap.getDartType(node.type);
     if (node.isTypeError) {
       impactBuilder.registerTypeUse(new TypeUse.implicitCast(type));
     } else {
       impactBuilder.registerTypeUse(new TypeUse.asCast(type));
     }
-    visitNode(node.operand);
-    return super.visitAsExpression(node);
   }
 
   @override
-  ir.DartType visitThrow(ir.Throw node) {
+  void handleThrow(ir.Throw node) {
     impactBuilder.registerFeature(Feature.THROW_EXPRESSION);
-    visitNode(node.expression);
-    return super.visitThrow(node);
   }
 
   @override
-  Null visitForInStatement(ir.ForInStatement node) {
-    visitNode(node.variable);
-    visitNode(node.iterable);
-    visitNode(node.body);
+  void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType) {
     // TODO(johnniwinther): Use receiver constraints for the dynamic uses in
     // strong mode.
     if (node.isAsync) {
@@ -810,13 +711,7 @@
   }
 
   @override
-  Null visitTryCatch(ir.TryCatch node) {
-    visitNode(node.body);
-    visitNodes(node.catches);
-  }
-
-  @override
-  Null visitCatch(ir.Catch node) {
+  void handleCatch(ir.Catch node) {
     impactBuilder.registerFeature(Feature.CATCH_STATEMENT);
     if (node.stackTrace != null) {
       impactBuilder.registerFeature(Feature.STACK_TRACE_IN_CATCH);
@@ -825,17 +720,10 @@
       impactBuilder.registerTypeUse(
           new TypeUse.catchType(elementMap.getDartType(node.guard)));
     }
-    visitNode(node.body);
   }
 
   @override
-  Null visitTryFinally(ir.TryFinally node) {
-    visitNode(node.body);
-    visitNode(node.finalizer);
-  }
-
-  @override
-  ir.DartType visitTypeLiteral(ir.TypeLiteral node) {
+  void handleTypeLiteral(ir.TypeLiteral node) {
     impactBuilder.registerTypeUse(
         new TypeUse.typeLiteral(elementMap.getDartType(node.type)));
     if (node.type is ir.FunctionType) {
@@ -845,72 +733,31 @@
       // We need to ensure that the typedef is live.
       elementMap.getTypedefType(functionType.typedef);
     }
-    return super.visitTypeLiteral(node);
   }
 
   @override
-  Null visitFieldInitializer(ir.FieldInitializer node) {
+  void handleFieldInitializer(ir.FieldInitializer node) {
     impactBuilder.registerStaticUse(
         new StaticUse.fieldInit(elementMap.getField(node.field)));
-    visitNode(node.value);
   }
 
   @override
-  Null visitRedirectingInitializer(ir.RedirectingInitializer node) {
-    _visitArguments(node.arguments);
+  void handleRedirectingInitializer(
+      ir.RedirectingInitializer node, ArgumentTypes argumentTypes) {
     ConstructorEntity target = elementMap.getConstructor(node.target);
     impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke(
         target, elementMap.getCallStructure(node.arguments)));
   }
 
   @override
-  ir.DartType visitLogicalExpression(ir.LogicalExpression node) {
-    visitNode(node.left);
-    visitNode(node.right);
-    return super.visitLogicalExpression(node);
-  }
-
-  ir.DartType visitNot(ir.Not node) {
-    visitNode(node.operand);
-    return super.visitNot(node);
-  }
-
-  @override
-  ir.DartType visitLoadLibrary(ir.LoadLibrary node) {
+  void handleLoadLibrary(ir.LoadLibrary node) {
     impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
         commonElements.loadDeferredLibrary, CallStructure.ONE_ARG));
     impactBuilder.registerFeature(Feature.LOAD_LIBRARY);
-    return super.visitLoadLibrary(node);
   }
 
   @override
-  Null visitEmptyStatement(ir.EmptyStatement node) {}
-
-  @override
-  Null visitForStatement(ir.ForStatement node) {
-    visitNodes(node.variables);
-    visitNode(node.condition);
-    visitNodes(node.updates);
-    visitNode(node.body);
-  }
-
-  @override
-  Null visitDoStatement(ir.DoStatement node) {
-    visitNode(node.body);
-    visitNode(node.condition);
-  }
-
-  @override
-  Null visitWhileStatement(ir.WhileStatement node) {
-    visitNode(node.condition);
-    visitNode(node.body);
-  }
-
-  @override
-  Null visitSwitchStatement(ir.SwitchStatement node) {
-    visitNode(node.expression);
-    visitNodes(node.cases);
-
+  void handleSwitchStatement(ir.SwitchStatement node) {
     // TODO(32557): Remove this when issue 32557 is fixed.
     ir.TreeNode firstCase;
     DartType firstCaseType;
@@ -985,47 +832,4 @@
       reporter.reportError(error, infos);
     }
   }
-
-  @override
-  Null visitSwitchCase(ir.SwitchCase node) {
-    visitNodes(node.expressions);
-    visitNode(node.body);
-  }
-
-  @override
-  Null visitContinueSwitchStatement(ir.ContinueSwitchStatement node) {}
-
-  @override
-  Null visitLabeledStatement(ir.LabeledStatement node) {
-    visitNode(node.body);
-  }
-
-  @override
-  Null visitBreakStatement(ir.BreakStatement node) {}
-
-  @override
-  Null visitYieldStatement(ir.YieldStatement node) {
-    visitNode(node.expression);
-  }
-
-  @override
-  ir.DartType visitLet(ir.Let node) {
-    visitNode(node.variable);
-    return super.visitLet(node);
-  }
-
-  @override
-  Null visitAssertInitializer(ir.AssertInitializer node) {
-    visitNode(node.statement);
-  }
-
-  @override
-  ir.DartType visitNamedExpression(ir.NamedExpression node) =>
-      visitNode(node.value);
-
-  // TODO(johnniwinther): Make this throw and visit child nodes explicitly
-  // instead to ensure that we don't visit unwanted parts of the ir.
-  @override
-  ir.DartType defaultNode(ir.Node node) =>
-      throw UnsupportedError('Unhandled node $node (${node.runtimeType})');
 }
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index 6eca5ad..3c2e81a 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -29,6 +29,7 @@
 import '../native/resolver.dart';
 import '../options.dart';
 import '../universe/class_hierarchy.dart';
+import '../universe/resolution_world_builder.dart';
 import '../universe/world_builder.dart';
 import '../universe/world_impact.dart';
 import 'deferred_load.dart';
diff --git a/pkg/compiler/lib/src/kernel/kernel_world.dart b/pkg/compiler/lib/src/kernel/kernel_world.dart
new file mode 100644
index 0000000..563fc9c
--- /dev/null
+++ b/pkg/compiler/lib/src/kernel/kernel_world.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../common_elements.dart';
+
+import '../elements/entities.dart';
+
+import '../elements/types.dart';
+import '../js_backend/annotations.dart';
+import '../js_backend/allocator_analysis.dart' show KAllocatorAnalysis;
+import '../js_backend/backend_usage.dart';
+import '../js_backend/interceptor_data.dart';
+import '../js_backend/native_data.dart';
+import '../js_backend/no_such_method_registry.dart';
+import '../js_backend/runtime_types.dart';
+import '../options.dart';
+import '../universe/class_hierarchy.dart';
+import '../universe/class_set.dart';
+import '../universe/resolution_world_builder.dart';
+import '../world.dart';
+
+import 'element_map_impl.dart';
+
+class KClosedWorldImpl implements KClosedWorld {
+  final KernelToElementMapImpl elementMap;
+  final KElementEnvironment elementEnvironment;
+  final DartTypes dartTypes;
+  final KCommonElements commonElements;
+  final NativeData nativeData;
+  final InterceptorData interceptorData;
+  final BackendUsage backendUsage;
+  final NoSuchMethodData noSuchMethodData;
+
+  final Map<ClassEntity, Set<ClassEntity>> mixinUses;
+
+  final Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses;
+
+  // TODO(johnniwinther): Can this be derived from [ClassSet]s?
+  final Set<ClassEntity> _implementedClasses;
+
+  final Iterable<MemberEntity> liveInstanceMembers;
+
+  /// Members that are written either directly or through a setter selector.
+  final Iterable<MemberEntity> assignedInstanceMembers;
+  final KAllocatorAnalysis allocatorAnalysis;
+
+  final Iterable<ClassEntity> liveNativeClasses;
+
+  final Iterable<MemberEntity> processedMembers;
+
+  final ClassHierarchy classHierarchy;
+
+  final AnnotationsData annotationsData;
+
+  RuntimeTypesNeed _rtiNeed;
+
+  KClosedWorldImpl(this.elementMap,
+      {CompilerOptions options,
+      this.elementEnvironment,
+      this.dartTypes,
+      this.commonElements,
+      this.nativeData,
+      this.interceptorData,
+      this.backendUsage,
+      this.noSuchMethodData,
+      ResolutionWorldBuilder resolutionWorldBuilder,
+      RuntimeTypesNeedBuilder rtiNeedBuilder,
+      this.allocatorAnalysis,
+      Set<ClassEntity> implementedClasses,
+      this.liveNativeClasses,
+      this.liveInstanceMembers,
+      this.assignedInstanceMembers,
+      this.processedMembers,
+      this.mixinUses,
+      this.typesImplementedBySubclasses,
+      Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes,
+      Map<ClassEntity, ClassSet> classSets,
+      this.annotationsData})
+      : _implementedClasses = implementedClasses,
+        classHierarchy = new ClassHierarchyImpl(
+            commonElements, classHierarchyNodes, classSets) {
+    _rtiNeed = rtiNeedBuilder.computeRuntimeTypesNeed(
+        resolutionWorldBuilder, this, options);
+  }
+
+  RuntimeTypesNeed get rtiNeed => _rtiNeed;
+
+  /// Returns `true` if [cls] is implemented by an instantiated class.
+  bool isImplemented(ClassEntity cls) {
+    return _implementedClasses.contains(cls);
+  }
+}
diff --git a/pkg/compiler/lib/src/library_loader.dart b/pkg/compiler/lib/src/library_loader.dart
index b7ab8cc..e9baa28 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/library_loader.dart
@@ -6,9 +6,11 @@
 
 import 'dart:async';
 
-import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
+import 'package:front_end/src/fasta/kernel/utils.dart';
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
+
+import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
 import 'package:kernel/kernel.dart' hide LibraryDependency, Combinator;
 import 'package:kernel/target/targets.dart';
 
@@ -36,6 +38,12 @@
   /// Shared state between compilations.
   fe.InitializedCompilerState initializedCompilerState;
 
+  // TODO(johnniwinther): Remove this when #34942 is fixed.
+  /// Force in-memory serialization/deserialization of the loaded component.
+  ///
+  /// This is used for testing.
+  bool forceSerialization = false;
+
   LibraryLoaderTask(
       this._options, this._compilerInput, this._reporter, Measurer measurer)
       : initializedCompilerState = _options.kernelInitializedCompilerState,
@@ -71,6 +79,12 @@
             resolvedUri);
       }
       if (component == null) return null;
+      if (forceSerialization) {
+        // TODO(johnniwinther): Remove this when #34942 is fixed.
+        List<int> data = serializeComponent(component);
+        component = new ir.Component();
+        new BinaryBuilder(data).readComponent(component);
+      }
       return _createLoadedLibraries(component);
     });
   }
diff --git a/pkg/compiler/lib/src/null_compiler_output.dart b/pkg/compiler/lib/src/null_compiler_output.dart
index 0b71a1ac..95206bb 100644
--- a/pkg/compiler/lib/src/null_compiler_output.dart
+++ b/pkg/compiler/lib/src/null_compiler_output.dart
@@ -16,6 +16,11 @@
   OutputSink createOutputSink(String name, String extension, OutputType type) {
     return NullSink.outputProvider(name, extension, type);
   }
+
+  @override
+  BinaryOutputSink createBinarySink(Uri uri) {
+    return new NullBinarySink(uri);
+  }
 }
 
 /// A sink that drains into /dev/null.
@@ -24,11 +29,11 @@
 
   NullSink(this.name);
 
-  add(String value) {}
+  void add(String value) {}
 
   void close() {}
 
-  toString() => name;
+  String toString() => name;
 
   /// Convenience method for getting an [api.CompilerOutputProvider].
   static NullSink outputProvider(
@@ -36,3 +41,17 @@
     return new NullSink('$name.$extension.$type');
   }
 }
+
+class NullBinarySink implements BinaryOutputSink {
+  final Uri uri;
+
+  NullBinarySink(this.uri);
+
+  @override
+  void write(List<int> buffer, [int start = 0, int end]) {}
+
+  @override
+  void close() {}
+
+  String toString() => 'NullBinarySink($uri)';
+}
diff --git a/pkg/compiler/lib/src/old_to_new_api.dart b/pkg/compiler/lib/src/old_to_new_api.dart
index 0363419..c7ab17f 100644
--- a/pkg/compiler/lib/src/old_to_new_api.dart
+++ b/pkg/compiler/lib/src/old_to_new_api.dart
@@ -83,6 +83,11 @@
     }
     return NullSink.outputProvider(name, extension, type);
   }
+
+  @override
+  BinaryOutputSink createBinarySink(Uri uri) {
+    throw new UnsupportedError("LegacyCompilerOutput.createBinarySink");
+  }
 }
 
 class LegacyOutputSink implements OutputSink {
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 586171e..eada831 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -6,7 +6,6 @@
 
 import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
 
-import '../compiler.dart' show PackagesDiscoveryProvider;
 import 'commandline_options.dart' show Flags;
 
 /// Options used for controlling diagnostic messages.
@@ -42,9 +41,6 @@
   /// The entry point of the application that is being compiled.
   Uri entryPoint;
 
-  /// Root location where SDK libraries are found.
-  Uri libraryRoot;
-
   /// Package root location.
   ///
   /// If not null then [packageConfig] should be null.
@@ -55,9 +51,16 @@
   /// If not null then [packageRoot] should be null.
   Uri packageConfig;
 
-  // TODO(sigmund): Move out of here, maybe to CompilerInput. Options should not
-  // hold code, just configuration options.
-  PackagesDiscoveryProvider packagesDiscoveryProvider;
+  /// Location from which serialized inference data is read.
+  ///
+  /// If this is set, the [entryPoint] is expected to be a .dill file and the
+  /// frontend work is skipped.
+  Uri readDataUri;
+
+  /// Location to which inference data is serialized.
+  ///
+  /// If this is set, the compilation stops after type inference.
+  Uri writeDataUri;
 
   /// Resolved constant "environment" values passed to the compiler via the `-D`
   /// flags.
@@ -157,10 +160,6 @@
   /// URI of the main output if the compiler is generating source maps.
   Uri outputUri;
 
-  /// Location of the platform configuration file.
-  // TODO(sigmund): deprecate and remove, use only [librariesSpecificationUri]
-  Uri platformConfigUri;
-
   /// Location of the libraries specification file.
   Uri librariesSpecificationUri;
 
@@ -223,10 +222,14 @@
   /// emitter might still be used if the program uses dart:mirrors.
   bool useStartupEmitter = false;
 
-  /// Enable verbose printing during compilation. Includes progress messages
-  /// during each phase and a time-breakdown between phases at the end.
+  /// Enable verbose printing during compilation. Includes a time-breakdown
+  /// between phases at the end.
   bool verbose = false;
 
+  /// On top of --verbose, enable more verbose printing, like progress messages
+  /// during each phase of compilation.
+  bool showInternalProgress = false;
+
   /// Track allocations in the JS output.
   ///
   /// This is an experimental feature.
@@ -256,15 +259,15 @@
 
   /// Create an options object by parsing flags from [options].
   static CompilerOptions parse(List<String> options,
-      {Uri libraryRoot, Uri platformBinaries}) {
+      {Uri librariesSpecificationUri, Uri platformBinaries}) {
     return new CompilerOptions()
-      ..libraryRoot = libraryRoot
+      ..librariesSpecificationUri = librariesSpecificationUri
       ..allowMockCompilation = _hasOption(options, Flags.allowMockCompilation)
       ..benchmarkingProduction =
           _hasOption(options, Flags.benchmarkingProduction)
       ..buildId =
           _extractStringOption(options, '--build-id=', _UNDETERMINED_BUILD_ID)
-      ..compileForServer = _resolveCompileForServerFromOptions(options)
+      ..compileForServer = _hasOption(options, Flags.serverMode)
       ..deferredMapUri = _extractUriOption(options, '--deferred-map=')
       ..fatalWarnings = _hasOption(options, Flags.fatalWarnings)
       ..terseDiagnostics = _hasOption(options, Flags.terse)
@@ -294,9 +297,6 @@
           _hasOption(options, Flags.generateCodeWithCompileTimeErrors)
       ..generateSourceMap = !_hasOption(options, Flags.noSourceMaps)
       ..outputUri = _extractUriOption(options, '--out=')
-      ..platformConfigUri =
-          _resolvePlatformConfigFromOptions(libraryRoot, options)
-      ..librariesSpecificationUri = _resolveLibrariesSpecification(libraryRoot)
       ..platformBinaries =
           platformBinaries ?? _extractUriOption(options, '--platform-binaries=')
       ..sourceMapUri = _extractUriOption(options, '--source-map=')
@@ -316,18 +316,22 @@
       ..useNewSourceInfo = _hasOption(options, Flags.useNewSourceInfo)
       ..useStartupEmitter = _hasOption(options, Flags.fastStartup)
       ..startAsyncSynchronously = !_hasOption(options, Flags.noSyncAsync)
-      ..verbose = _hasOption(options, Flags.verbose);
+      ..verbose = _hasOption(options, Flags.verbose)
+      ..showInternalProgress = _hasOption(options, Flags.progress)
+      ..readDataUri = _extractUriOption(options, '${Flags.readData}=')
+      ..writeDataUri = _extractUriOption(options, '${Flags.writeData}=');
   }
 
   void validate() {
     // TODO(sigmund): should entrypoint be here? should we validate it is not
     // null? In unittests we use the same compiler to analyze or build multiple
     // entrypoints.
-    if (libraryRoot == null) {
-      throw new ArgumentError("[libraryRoot] is null.");
+    if (librariesSpecificationUri == null) {
+      throw new ArgumentError("[librariesSpecificationUri] is null.");
     }
-    if (!libraryRoot.path.endsWith("/")) {
-      throw new ArgumentError("[libraryRoot] must end with a /");
+    if (librariesSpecificationUri.path.endsWith('/')) {
+      throw new ArgumentError(
+          "[librariesSpecificationUri] should be a file: $librariesSpecificationUri");
     }
     if (packageRoot != null && packageConfig != null) {
       throw new ArgumentError("Only one of [packageRoot] or [packageConfig] "
@@ -368,10 +372,6 @@
 
     // TODO(johnniwinther): Should we support this in the future?
     generateCodeWithCompileTimeErrors = false;
-    if (platformConfigUri == null) {
-      platformConfigUri = _resolvePlatformConfig(libraryRoot, null, const []);
-    }
-    librariesSpecificationUri = _resolveLibrariesSpecification(libraryRoot);
 
     // Strong mode always trusts type annotations (inferred or explicit), so
     // assignments checks should be trusted.
@@ -446,16 +446,6 @@
   return (option == null) ? null : Uri.parse(option);
 }
 
-// CSV: Comma separated values.
-List<String> _extractCsvOption(List<String> options, String prefix) {
-  for (String option in options) {
-    if (option.startsWith(prefix)) {
-      return option.substring(prefix.length).split(',');
-    }
-  }
-  return const <String>[];
-}
-
 bool _hasOption(List<String> options, String option) {
   return options.indexOf(option) >= 0;
 }
@@ -476,44 +466,4 @@
   return null;
 }
 
-Uri _resolvePlatformConfig(
-    Uri libraryRoot, String platformConfigPath, Iterable<String> categories) {
-  if (platformConfigPath != null) {
-    return libraryRoot.resolve(platformConfigPath);
-  } else {
-    if (categories.length == 0) {
-      return libraryRoot.resolve(_clientPlatform);
-    }
-    assert(categories.length <= 2);
-    if (categories.contains("Client")) {
-      if (categories.contains("Server")) {
-        return libraryRoot.resolve(_sharedPlatform);
-      }
-      return libraryRoot.resolve(_clientPlatform);
-    }
-    assert(categories.contains("Server"));
-    return libraryRoot.resolve(_serverPlatform);
-  }
-}
-
-bool _resolveCompileForServerFromOptions(List<String> options) {
-  var categories = _extractCsvOption(options, '--categories=');
-  return categories.length == 1 && categories.single == 'Server';
-}
-
-Uri _resolvePlatformConfigFromOptions(Uri libraryRoot, List<String> options) {
-  return _resolvePlatformConfig(
-      libraryRoot,
-      _extractStringOption(options, "--platform-config=", null),
-      _extractCsvOption(options, '--categories='));
-}
-
-Uri _resolveLibrariesSpecification(Uri libraryRoot) =>
-    libraryRoot.resolve('lib/libraries.json');
-
-/// Locations of the platform descriptor files relative to the library root.
-const String _clientPlatform = "lib/dart_client.platform";
-const String _serverPlatform = "lib/dart_server.platform";
-const String _sharedPlatform = "lib/dart_shared.platform";
-
 const String _UNDETERMINED_BUILD_ID = "build number could not be determined";
diff --git a/pkg/compiler/lib/src/platform_configuration.dart b/pkg/compiler/lib/src/platform_configuration.dart
deleted file mode 100644
index 0f61ca4..0000000
--- a/pkg/compiler/lib/src/platform_configuration.dart
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE.md file.
-
-/// Tools for loading and parsing platform-configuration files.
-library platform_configuration;
-
-import "dart:async";
-
-import "package:charcode/ascii.dart";
-
-import "../compiler_new.dart" as api;
-
-/// Parses an Ini-like format.
-///
-/// Sections are initialized with a name enclosed in brackets.
-/// Each section contain zero or more properties of the form "name:value".
-/// Empty lines are ignored.
-/// Lines starting with # are ignored.
-/// Duplicate names are not allowed.
-/// All keys and values will be passed through [String.trim].
-///
-/// If an error is found, a [FormatException] is thrown, using [sourceUri] in
-/// the error message.
-///
-/// Example
-/// ```
-/// [a]
-/// b:c
-///
-/// [d]
-/// e:file:///tmp/bla
-/// ```
-/// Will parse to {"a": {"b":"c"}, "d": {"e": "file:///tmp/bla"}}.
-
-Map<String, Map<String, String>> parseIni(List<int> source,
-    {Set<String> allowedSections, Uri sourceUri}) {
-  int startOfLine = 0;
-  int currentLine = 0;
-
-  error(String message, int index) {
-    int column = index - startOfLine + 1;
-    throw new FormatException(
-        "$sourceUri:$currentLine:$column: $message", sourceUri, index);
-  }
-
-  Map<String, Map<String, String>> result =
-      new Map<String, Map<String, String>>();
-  Map<String, String> currentSection = null;
-
-  if (source.length == 0) return result;
-  bool endOfFile = false;
-
-  // Iterate once per $lf in file.
-  while (!endOfFile) {
-    currentLine += 1;
-    int endOfLine = source.indexOf($lf, startOfLine);
-    if (endOfLine == -1) {
-      // The dart2js provider adds a final 0 to the file.
-      endOfLine = source.last == 0 ? source.length - 1 : source.length;
-      endOfFile = true;
-    }
-    if (startOfLine != endOfLine) {
-      int firstChar = source[startOfLine];
-      if (firstChar == $hash) {
-        // Comment, do nothing.
-      } else if (firstChar == $open_bracket) {
-        // Section header
-        int endOfHeader = source.indexOf($close_bracket, startOfLine);
-        if (endOfHeader == -1) {
-          error("'[' must be matched by ']' on the same line.", startOfLine);
-        }
-        if (endOfHeader == startOfLine + 1) {
-          error("Empty header name", startOfLine + 1);
-        }
-        if (endOfHeader != endOfLine - 1) {
-          error("Section heading lines must end with ']'", endOfHeader + 1);
-        }
-        int startOfSectionName = startOfLine + 1;
-        String sectionName =
-            new String.fromCharCodes(source, startOfSectionName, endOfHeader)
-                .trim();
-        currentSection = new Map<String, String>();
-        if (result.containsKey(sectionName)) {
-          error("Duplicate section name '$sectionName'", startOfSectionName);
-        }
-        if (allowedSections != null && !allowedSections.contains(sectionName)) {
-          error("Unrecognized section name '$sectionName'", startOfSectionName);
-        }
-        result[sectionName] = currentSection;
-      } else {
-        // Property line
-        if (currentSection == null) {
-          error("Property outside section", startOfLine);
-        }
-        int separator = source.indexOf($colon, startOfLine);
-        if (separator == startOfLine) {
-          error("Empty property name", startOfLine);
-        }
-        if (separator == -1 || separator > endOfLine) {
-          error("Property line without ':'", startOfLine);
-        }
-        String propertyName =
-            new String.fromCharCodes(source, startOfLine, separator).trim();
-        if (currentSection.containsKey(propertyName)) {
-          error("Duplicate property name '$propertyName'", startOfLine);
-        }
-        String propertyValue =
-            new String.fromCharCodes(source, separator + 1, endOfLine).trim();
-        currentSection[propertyName] = propertyValue;
-      }
-    }
-    startOfLine = endOfLine + 1;
-  }
-  return result;
-}
-
-const String librariesSection = "libraries";
-const String dartSpecSection = "dart-spec";
-const String featuresSection = "features";
-
-Map<String, Uri> libraryMappings(
-    Map<String, Map<String, String>> sections, Uri baseLocation) {
-  assert(sections.containsKey(librariesSection));
-  Map<String, Uri> result = new Map<String, Uri>();
-  sections[librariesSection].forEach((String name, String value) {
-    result[name] = baseLocation.resolve(value);
-  });
-  return result;
-}
-
-final Set<String> allowedSections =
-    new Set.from([librariesSection, dartSpecSection, featuresSection]);
-
-Future<Map<String, Uri>> load(Uri location, api.CompilerInput provider) {
-  return provider
-      .readFromUri(location, inputKind: api.InputKind.binary)
-      .then((api.Input input) {
-    return libraryMappings(
-        parseIni(input.data,
-            allowedSections: allowedSections, sourceUri: location),
-        location);
-  });
-}
diff --git a/pkg/compiler/lib/src/resolved_uri_translator.dart b/pkg/compiler/lib/src/resolved_uri_translator.dart
deleted file mode 100644
index ded9161..0000000
--- a/pkg/compiler/lib/src/resolved_uri_translator.dart
+++ /dev/null
@@ -1,43 +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.
-
-/// API used by the library loader to translate internal SDK URIs into file
-/// system readable URIs.
-abstract class ResolvedUriTranslator {
-  factory ResolvedUriTranslator(Map<String, Uri> sdkLibraries) =
-      _ResolvedUriTranslator;
-
-  /// A mapping from dart: library names to their location.
-  Map<String, Uri> get sdkLibraries;
-}
-
-/// A translator that forwards all methods to an internal
-/// [ResolvedUriTranslator].
-///
-/// The translator to forward to may be set after the instance is constructed.
-/// This is useful for the compiler because some tasks that are instantiated at
-/// compiler construction time need a [ResolvedUriTranslator], but the data
-/// required to instantiate it cannot be obtained at construction time. So a
-/// [ForwardingResolvedUriTranslator] may be passed instead, and the translator
-/// to forward to can be set once the required data has been retrieved.
-class ForwardingResolvedUriTranslator implements ResolvedUriTranslator {
-  ResolvedUriTranslator resolvedUriTranslator;
-
-  /// Returns `true` if [resolvedUriTranslator] is not `null`.
-  bool get isSet => resolvedUriTranslator != null;
-
-  /// The opposite of [isSet].
-  bool get isNotSet => resolvedUriTranslator == null;
-
-  @override
-  Map<String, Uri> get sdkLibraries => resolvedUriTranslator.sdkLibraries;
-}
-
-class _ResolvedUriTranslator implements ResolvedUriTranslator {
-  final Map<String, Uri> _sdkLibraries;
-
-  _ResolvedUriTranslator(this._sdkLibraries);
-
-  Map<String, Uri> get sdkLibraries => _sdkLibraries;
-}
diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart
index b63b9a2..1cb80e6 100644
--- a/pkg/compiler/lib/src/serialization/abstract_sink.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart
@@ -24,8 +24,19 @@
   /// Map of [_MemberData] object for serialized kernel member nodes.
   Map<ir.Member, _MemberData> _memberData = {};
 
+  IndexedSink<String> _stringIndex;
+  IndexedSink<Uri> _uriIndex;
+  IndexedSink<ir.Member> _memberNodeIndex;
+  IndexedSink<ImportEntity> _importIndex;
+
+  Map<Type, IndexedSink> _generalCaches = {};
+
   AbstractDataSink({this.useDataKinds: false}) {
     _dartTypeWriter = new DartTypeWriter(this);
+    _stringIndex = new IndexedSink<String>(this);
+    _uriIndex = new IndexedSink<Uri>(this);
+    _memberNodeIndex = new IndexedSink<ir.Member>(this);
+    _importIndex = new IndexedSink<ImportEntity>(this);
   }
 
   void begin(String tag) {
@@ -47,11 +58,17 @@
   }
 
   @override
+  void writeCached<E>(E value, void f(E value)) {
+    IndexedSink sink = _generalCaches[E] ??= new IndexedSink<E>(this);
+    sink.write(value, (v) => f(v));
+  }
+
+  @override
   void writeSourceSpan(SourceSpan value) {
     _writeDataKind(DataKind.sourceSpan);
     _writeUri(value.uri);
-    _writeInt(value.begin);
-    _writeInt(value.end);
+    _writeIntInternal(value.begin);
+    _writeIntInternal(value.end);
   }
 
   @override
@@ -80,13 +97,17 @@
   }
 
   void _writeMemberNode(ir.Member value) {
+    _memberNodeIndex.write(value, _writeMemberNodeInternal);
+  }
+
+  void _writeMemberNodeInternal(ir.Member value) {
     ir.Class cls = value.enclosingClass;
     if (cls != null) {
-      _writeEnum(MemberContextKind.cls);
+      _writeEnumInternal(MemberContextKind.cls);
       _writeClassNode(cls);
       _writeString(_computeMemberName(value));
     } else {
-      _writeEnum(MemberContextKind.library);
+      _writeEnumInternal(MemberContextKind.library);
       _writeLibraryNode(value.enclosingLibrary);
       _writeString(_computeMemberName(value));
     }
@@ -104,6 +125,17 @@
   }
 
   @override
+  void writeTypedefNode(ir.Typedef value) {
+    _writeDataKind(DataKind.typedefNode);
+    _writeTypedefNode(value);
+  }
+
+  void _writeTypedefNode(ir.Typedef value) {
+    _writeLibraryNode(value.enclosingLibrary);
+    _writeString(value.name);
+  }
+
+  @override
   void writeLibraryNode(ir.Library value) {
     _writeDataKind(DataKind.libraryNode);
     _writeLibraryNode(value);
@@ -116,14 +148,18 @@
   @override
   void writeEnum(dynamic value) {
     _writeDataKind(DataKind.enumValue);
-    _writeEnum(value);
+    _writeEnumInternal(value);
   }
 
   @override
   void writeBool(bool value) {
     assert(value != null);
     _writeDataKind(DataKind.bool);
-    _writeInt(value ? 1 : 0);
+    _writeBool(value);
+  }
+
+  void _writeBool(bool value) {
+    _writeIntInternal(value ? 1 : 0);
   }
 
   @override
@@ -145,7 +181,7 @@
     assert(value != null);
     assert(value >= 0 && value >> 30 == 0);
     _writeDataKind(DataKind.int);
-    _writeInt(value);
+    _writeIntInternal(value);
   }
 
   void writeTreeNode(ir.TreeNode value) {
@@ -155,23 +191,23 @@
 
   void _writeTreeNode(ir.TreeNode value) {
     if (value is ir.Class) {
-      _writeEnum(_TreeNodeKind.cls);
+      _writeEnumInternal(_TreeNodeKind.cls);
       _writeClassNode(value);
     } else if (value is ir.Member) {
-      _writeEnum(_TreeNodeKind.member);
+      _writeEnumInternal(_TreeNodeKind.member);
       _writeMemberNode(value);
     } else if (value is ir.VariableDeclaration &&
         value.parent is ir.FunctionDeclaration) {
-      _writeEnum(_TreeNodeKind.functionDeclarationVariable);
+      _writeEnumInternal(_TreeNodeKind.functionDeclarationVariable);
       _writeTreeNode(value.parent);
     } else if (value is ir.FunctionNode) {
-      _writeEnum(_TreeNodeKind.functionNode);
+      _writeEnumInternal(_TreeNodeKind.functionNode);
       _writeFunctionNode(value);
     } else if (value is ir.TypeParameter) {
-      _writeEnum(_TreeNodeKind.typeParameter);
+      _writeEnumInternal(_TreeNodeKind.typeParameter);
       _writeTypeParameter(value);
     } else {
-      _writeEnum(_TreeNodeKind.node);
+      _writeEnumInternal(_TreeNodeKind.node);
       ir.TreeNode member = value;
       while (member is! ir.Member) {
         if (member == null) {
@@ -184,23 +220,23 @@
       _MemberData memberData = _memberData[member] ??= new _MemberData(member);
       int index = memberData.getIndexByTreeNode(value);
       assert(index != null, "No index found for ${value.runtimeType}.");
-      _writeInt(index);
+      _writeIntInternal(index);
     }
   }
 
   void _writeFunctionNode(ir.FunctionNode value) {
     ir.TreeNode parent = value.parent;
     if (parent is ir.Procedure) {
-      _writeEnum(_FunctionNodeKind.procedure);
+      _writeEnumInternal(_FunctionNodeKind.procedure);
       _writeMemberNode(parent);
     } else if (parent is ir.Constructor) {
-      _writeEnum(_FunctionNodeKind.constructor);
+      _writeEnumInternal(_FunctionNodeKind.constructor);
       _writeMemberNode(parent);
     } else if (parent is ir.FunctionExpression) {
-      _writeEnum(_FunctionNodeKind.functionExpression);
+      _writeEnumInternal(_FunctionNodeKind.functionExpression);
       _writeTreeNode(parent);
     } else if (parent is ir.FunctionDeclaration) {
-      _writeEnum(_FunctionNodeKind.functionDeclaration);
+      _writeEnumInternal(_FunctionNodeKind.functionDeclaration);
       _writeTreeNode(parent);
     } else {
       throw new UnsupportedError(
@@ -217,13 +253,13 @@
   void _writeTypeParameter(ir.TypeParameter value) {
     ir.TreeNode parent = value.parent;
     if (parent is ir.Class) {
-      _writeEnum(_TypeParameterKind.cls);
+      _writeEnumInternal(_TypeParameterKind.cls);
       _writeClassNode(parent);
-      _writeInt(parent.typeParameters.indexOf(value));
+      _writeIntInternal(parent.typeParameters.indexOf(value));
     } else if (parent is ir.FunctionNode) {
-      _writeEnum(_TypeParameterKind.functionNode);
+      _writeEnumInternal(_TypeParameterKind.functionNode);
       _writeFunctionNode(parent);
-      _writeInt(parent.typeParameters.indexOf(value));
+      _writeIntInternal(parent.typeParameters.indexOf(value));
     } else {
       throw new UnsupportedError(
           "Unsupported TypeParameter parent ${parent.runtimeType}");
@@ -231,7 +267,7 @@
   }
 
   void _writeDataKind(DataKind kind) {
-    if (useDataKinds) _writeEnum(kind);
+    if (useDataKinds) _writeEnumInternal(kind);
   }
 
   void writeLibrary(IndexedLibrary value) {
@@ -279,7 +315,7 @@
   }
 
   void _writeConstant(ConstantValue value) {
-    _writeEnum(value.kind);
+    _writeEnumInternal(value.kind);
     switch (value.kind) {
       case ConstantValueKind.BOOL:
         BoolConstantValue constant = value;
@@ -304,13 +340,75 @@
         break;
       case ConstantValueKind.NULL:
         break;
-      default:
-        // TODO(johnniwinther): Support remaining constant values.
+      case ConstantValueKind.FUNCTION:
+        FunctionConstantValue constant = value;
+        IndexedFunction function = constant.element;
+        writeMember(function);
+        writeDartType(constant.type);
+        break;
+      case ConstantValueKind.LIST:
+        ListConstantValue constant = value;
+        writeDartType(constant.type);
+        writeConstants(constant.entries);
+        break;
+      case ConstantValueKind.MAP:
+        MapConstantValue constant = value;
+        writeDartType(constant.type);
+        writeConstants(constant.keys);
+        writeConstants(constant.values);
+        break;
+      case ConstantValueKind.CONSTRUCTED:
+        ConstructedConstantValue constant = value;
+        writeDartType(constant.type);
+        writeMemberMap(constant.fields, writeConstant);
+        break;
+      case ConstantValueKind.TYPE:
+        TypeConstantValue constant = value;
+        writeDartType(constant.representedType);
+        writeDartType(constant.type);
+        break;
+      case ConstantValueKind.INSTANTIATION:
+        InstantiationConstantValue constant = value;
+        writeDartTypes(constant.typeArguments);
+        writeConstant(constant.function);
+        break;
+      case ConstantValueKind.NON_CONSTANT:
+        break;
+      case ConstantValueKind.DEFERRED_GLOBAL:
+      case ConstantValueKind.INTERCEPTOR:
+      case ConstantValueKind.SYNTHETIC:
+        // These are only created in the SSA graph builder.
         throw new UnsupportedError(
-            "Unexpected constant value kind ${value.kind}.");
+            "Unsupported constant value kind ${value.kind}.");
     }
   }
 
+  void _writeString(String value) {
+    _stringIndex.write(value, _writeStringInternal);
+  }
+
+  void _writeUri(Uri value) {
+    _uriIndex.write(value, _writeUriInternal);
+  }
+
+  @override
+  void writeImport(ImportEntity value) {
+    _writeDataKind(DataKind.import);
+    _writeImport(value);
+  }
+
+  void _writeImport(ImportEntity value) {
+    _importIndex.write(value, _writeImportInternal);
+  }
+
+  void _writeImportInternal(ImportEntity value) {
+    // TODO(johnniwinther): Do we need to serialize non-deferred imports?
+    writeStringOrNull(value.name);
+    _writeUri(value.uri);
+    _writeUri(value.enclosingLibraryUri);
+    _writeBool(value.isDeferred);
+  }
+
   /// Actual serialization of a section begin tag, implemented by subclasses.
   void _begin(String tag);
 
@@ -318,15 +416,15 @@
   void _end(String tag);
 
   /// Actual serialization of a URI value, implemented by subclasses.
-  void _writeUri(Uri value);
+  void _writeUriInternal(Uri value);
 
   /// Actual serialization of a String value, implemented by subclasses.
-  void _writeString(String value);
+  void _writeStringInternal(String value);
 
   /// Actual serialization of a non-negative integer value, implemented by
   /// subclasses.
-  void _writeInt(int value);
+  void _writeIntInternal(int value);
 
   /// Actual serialization of an enum value, implemented by subclasses.
-  void _writeEnum(dynamic value);
+  void _writeEnumInternal(dynamic value);
 }
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index f258917..9022b28 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -13,7 +13,19 @@
   EntityLookup _entityLookup;
   LocalLookup _localLookup;
 
-  AbstractDataSource({this.useDataKinds: false});
+  IndexedSource<String> _stringIndex;
+  IndexedSource<Uri> _uriIndex;
+  IndexedSource<_MemberData> _memberNodeIndex;
+  IndexedSource<ImportEntity> _importIndex;
+
+  Map<Type, IndexedSource> _generalCaches = {};
+
+  AbstractDataSource({this.useDataKinds: false}) {
+    _stringIndex = new IndexedSource<String>(this);
+    _uriIndex = new IndexedSource<Uri>(this);
+    _memberNodeIndex = new IndexedSource<_MemberData>(this);
+    _importIndex = new IndexedSource<ImportEntity>(this);
+  }
 
   void begin(String tag) {
     if (useDataKinds) _begin(tag);
@@ -53,6 +65,12 @@
     return _localLookup;
   }
 
+  @override
+  E readCached<E>(E f()) {
+    IndexedSource source = _generalCaches[E] ??= new IndexedSource<E>(this);
+    return source.read(f);
+  }
+
   IndexedLibrary readLibrary() {
     return getIndexedLibrary(readInt());
   }
@@ -98,8 +116,8 @@
   SourceSpan readSourceSpan() {
     _checkDataKind(DataKind.sourceSpan);
     Uri uri = _readUri();
-    int begin = _readInt();
-    int end = _readInt();
+    int begin = _readIntInternal();
+    int end = _readIntInternal();
     return new SourceSpan(uri, begin, end);
   }
 
@@ -173,7 +191,11 @@
   }
 
   _MemberData _readMemberData() {
-    MemberContextKind kind = _readEnum(MemberContextKind.values);
+    return _memberNodeIndex.read(_readMemberDataInternal);
+  }
+
+  _MemberData _readMemberDataInternal() {
+    MemberContextKind kind = _readEnumInternal(MemberContextKind.values);
     switch (kind) {
       case MemberContextKind.cls:
         _ClassData cls = _readClassData();
@@ -205,6 +227,18 @@
     return _readClassData().node;
   }
 
+  ir.Typedef _readTypedefNode() {
+    _LibraryData library = _readLibraryData();
+    String name = _readString();
+    return library.lookupTypedef(name);
+  }
+
+  @override
+  ir.Typedef readTypedefNode() {
+    _checkDataKind(DataKind.typedefNode);
+    return _readTypedefNode();
+  }
+
   _LibraryData _readLibraryData() {
     Uri canonicalUri = _readUri();
     return componentLookup.getLibraryDataByUri(canonicalUri);
@@ -219,7 +253,7 @@
   @override
   E readEnum<E>(List<E> values) {
     _checkDataKind(DataKind.enumValue);
-    return _readEnum(values);
+    return _readEnumInternal(values);
   }
 
   @override
@@ -228,10 +262,18 @@
     return _readUri();
   }
 
+  Uri _readUri() {
+    return _uriIndex.read(_readUriInternal);
+  }
+
   @override
   bool readBool() {
     _checkDataKind(DataKind.bool);
-    int value = _readInt();
+    return _readBool();
+  }
+
+  bool _readBool() {
+    int value = _readIntInternal();
     assert(value == 0 || value == 1);
     return value == 1;
   }
@@ -242,10 +284,14 @@
     return _readString();
   }
 
+  String _readString() {
+    return _stringIndex.read(_readStringInternal);
+  }
+
   @override
   int readInt() {
     _checkDataKind(DataKind.int);
-    return _readInt();
+    return _readIntInternal();
   }
 
   @override
@@ -261,17 +307,14 @@
   }
 
   ConstantValue _readConstant() {
-    ConstantValueKind kind = _readEnum(ConstantValueKind.values);
-    ConstantValue constant;
+    ConstantValueKind kind = _readEnumInternal(ConstantValueKind.values);
     switch (kind) {
       case ConstantValueKind.BOOL:
         bool value = readBool();
-        constant = new BoolConstantValue(value);
-        break;
+        return new BoolConstantValue(value);
       case ConstantValueKind.INT:
         BigInt value = BigInt.parse(readString());
-        constant = new IntConstantValue(value);
-        break;
+        return new IntConstantValue(value);
       case ConstantValueKind.DOUBLE:
         ByteData data = new ByteData(8);
         data.setUint16(0, readInt());
@@ -279,24 +322,51 @@
         data.setUint16(4, readInt());
         data.setUint16(6, readInt());
         double value = data.getFloat64(0);
-        constant = new DoubleConstantValue(value);
-        break;
+        return new DoubleConstantValue(value);
       case ConstantValueKind.STRING:
         String value = readString();
-        constant = new StringConstantValue(value);
-        break;
+        return new StringConstantValue(value);
       case ConstantValueKind.NULL:
-        constant = const NullConstantValue();
-        break;
-      default:
-        // TODO(johnniwinther): Support remaining constant values.
-        throw new UnsupportedError("Unexpected constant value kind ${kind}.");
+        return const NullConstantValue();
+      case ConstantValueKind.FUNCTION:
+        IndexedFunction function = readMember();
+        DartType type = readDartType();
+        return new FunctionConstantValue(function, type);
+      case ConstantValueKind.LIST:
+        DartType type = readDartType();
+        List<ConstantValue> entries = readConstants();
+        return new ListConstantValue(type, entries);
+      case ConstantValueKind.MAP:
+        DartType type = readDartType();
+        List<ConstantValue> keys = readConstants();
+        List<ConstantValue> values = readConstants();
+        return new MapConstantValue(type, keys, values);
+      case ConstantValueKind.CONSTRUCTED:
+        InterfaceType type = readDartType();
+        Map<FieldEntity, ConstantValue> fields =
+            readMemberMap<FieldEntity, ConstantValue>(() => readConstant());
+        return new ConstructedConstantValue(type, fields);
+      case ConstantValueKind.TYPE:
+        DartType representedType = readDartType();
+        DartType type = readDartType();
+        return new TypeConstantValue(representedType, type);
+      case ConstantValueKind.INSTANTIATION:
+        List<DartType> typeArguments = readDartTypes();
+        ConstantValue function = readConstant();
+        return new InstantiationConstantValue(typeArguments, function);
+      case ConstantValueKind.NON_CONSTANT:
+        return new NonConstantValue();
+      case ConstantValueKind.DEFERRED_GLOBAL:
+      case ConstantValueKind.INTERCEPTOR:
+      case ConstantValueKind.SYNTHETIC:
+        // These are only created in the SSA graph builder.
+        throw new UnsupportedError("Unsupported constant value kind ${kind}.");
     }
-    return constant;
+    throw new UnsupportedError("Unexpexted constant value kind ${kind}.");
   }
 
   ir.TreeNode _readTreeNode() {
-    _TreeNodeKind kind = _readEnum(_TreeNodeKind.values);
+    _TreeNodeKind kind = _readEnumInternal(_TreeNodeKind.values);
     switch (kind) {
       case _TreeNodeKind.cls:
         return _readClassData().node;
@@ -311,7 +381,7 @@
         return _readTypeParameter();
       case _TreeNodeKind.node:
         _MemberData data = _readMemberData();
-        int index = _readInt();
+        int index = _readIntInternal();
         ir.TreeNode treeNode = data.getTreeNodeByIndex(index);
         assert(treeNode != null,
             "No TreeNode found for index $index in ${data.node}.$_errorContext");
@@ -321,7 +391,7 @@
   }
 
   ir.FunctionNode _readFunctionNode() {
-    _FunctionNodeKind kind = _readEnum(_FunctionNodeKind.values);
+    _FunctionNodeKind kind = _readEnumInternal(_FunctionNodeKind.values);
     switch (kind) {
       case _FunctionNodeKind.procedure:
         ir.Procedure procedure = _readMemberData().node;
@@ -346,21 +416,21 @@
   }
 
   ir.TypeParameter _readTypeParameter() {
-    _TypeParameterKind kind = _readEnum(_TypeParameterKind.values);
+    _TypeParameterKind kind = _readEnumInternal(_TypeParameterKind.values);
     switch (kind) {
       case _TypeParameterKind.cls:
         ir.Class cls = _readClassData().node;
-        return cls.typeParameters[_readInt()];
+        return cls.typeParameters[_readIntInternal()];
       case _TypeParameterKind.functionNode:
         ir.FunctionNode functionNode = _readFunctionNode();
-        return functionNode.typeParameters[_readInt()];
+        return functionNode.typeParameters[_readIntInternal()];
     }
     throw new UnsupportedError("Unexpected _TypeParameterKind kind $kind");
   }
 
   void _checkDataKind(DataKind expectedKind) {
     if (!useDataKinds) return;
-    DataKind actualKind = _readEnum(DataKind.values);
+    DataKind actualKind = _readEnumInternal(DataKind.values);
     assert(
         actualKind == expectedKind,
         "Invalid data kind. "
@@ -391,6 +461,24 @@
     throw new UnsupportedError("Unexpected local kind $kind");
   }
 
+  @override
+  ImportEntity readImport() {
+    _checkDataKind(DataKind.import);
+    return _readImport();
+  }
+
+  ImportEntity _readImport() {
+    return _importIndex.read(_readImportInternal);
+  }
+
+  ImportEntity _readImportInternal() {
+    String name = readStringOrNull();
+    Uri uri = _readUri();
+    Uri enclosingLibraryUri = _readUri();
+    bool isDeferred = _readBool();
+    return new ImportEntity(isDeferred, name, uri, enclosingLibraryUri);
+  }
+
   /// Actual deserialization of a section begin tag, implemented by subclasses.
   void _begin(String tag);
 
@@ -398,18 +486,18 @@
   void _end(String tag);
 
   /// Actual deserialization of a string value, implemented by subclasses.
-  String _readString();
+  String _readStringInternal();
 
   /// Actual deserialization of a non-negative integer value, implemented by
   /// subclasses.
-  int _readInt();
+  int _readIntInternal();
 
   /// Actual deserialization of a URI value, implemented by subclasses.
-  Uri _readUri();
+  Uri _readUriInternal();
 
   /// Actual deserialization of an enum value in [values], implemented by
   /// subclasses.
-  E _readEnum<E>(List<E> values);
+  E _readEnumInternal<E>(List<E> values);
 
   /// Returns a string representation of the current state of the data source
   /// useful for debugging in consistencies between serialization and
diff --git a/pkg/compiler/lib/src/serialization/binary_sink.dart b/pkg/compiler/lib/src/serialization/binary_sink.dart
index e7c2114..ae11f9b 100644
--- a/pkg/compiler/lib/src/serialization/binary_sink.dart
+++ b/pkg/compiler/lib/src/serialization/binary_sink.dart
@@ -10,6 +10,7 @@
 class BinarySink extends AbstractDataSink {
   final Sink<List<int>> sink;
   BufferedSink _bufferedSink;
+  int _length = 0;
 
   BinarySink(this.sink, {bool useDataKinds: false})
       : _bufferedSink = new BufferedSink(sink),
@@ -23,33 +24,37 @@
   }
 
   @override
-  void _writeUri(Uri value) {
+  void _writeUriInternal(Uri value) {
     _writeString(value.toString());
   }
 
   @override
-  void _writeString(String value) {
+  void _writeStringInternal(String value) {
     List<int> bytes = utf8.encode(value);
-    _writeInt(bytes.length);
+    _writeIntInternal(bytes.length);
     _bufferedSink.addBytes(bytes);
+    _length += bytes.length;
   }
 
   @override
-  void _writeInt(int value) {
+  void _writeIntInternal(int value) {
     assert(value >= 0 && value >> 30 == 0);
     if (value < 0x80) {
       _bufferedSink.addByte(value);
+      _length += 1;
     } else if (value < 0x4000) {
       _bufferedSink.addByte2((value >> 8) | 0x80, value & 0xFF);
+      _length += 2;
     } else {
       _bufferedSink.addByte4((value >> 24) | 0xC0, (value >> 16) & 0xFF,
           (value >> 8) & 0xFF, value & 0xFF);
+      _length += 4;
     }
   }
 
   @override
-  void _writeEnum(dynamic value) {
-    _writeInt(value.index);
+  void _writeEnumInternal(dynamic value) {
+    _writeIntInternal(value.index);
   }
 
   void close() {
@@ -57,4 +62,7 @@
     _bufferedSink = null;
     sink.close();
   }
+
+  /// Returns the number of bytes written to this data sink.
+  int get length => _length;
 }
diff --git a/pkg/compiler/lib/src/serialization/binary_source.dart b/pkg/compiler/lib/src/serialization/binary_source.dart
index 0836209..c68e4c9 100644
--- a/pkg/compiler/lib/src/serialization/binary_source.dart
+++ b/pkg/compiler/lib/src/serialization/binary_source.dart
@@ -20,8 +20,8 @@
   int _readByte() => _bytes[_byteOffset++];
 
   @override
-  String _readString() {
-    int length = _readInt();
+  String _readStringInternal() {
+    int length = _readIntInternal();
     List<int> bytes = new Uint8List(length);
     bytes.setRange(0, bytes.length, _bytes, _byteOffset);
     _byteOffset += bytes.length;
@@ -29,7 +29,7 @@
   }
 
   @override
-  int _readInt() {
+  int _readIntInternal() {
     var byte = _readByte();
     if (byte & 0x80 == 0) {
       // 0xxxxxxx
@@ -47,14 +47,14 @@
   }
 
   @override
-  Uri _readUri() {
+  Uri _readUriInternal() {
     String text = _readString();
     return Uri.parse(text);
   }
 
   @override
-  E _readEnum<E>(List<E> values) {
-    int index = _readInt();
+  E _readEnumInternal<E>(List<E> values) {
+    int index = _readIntInternal();
     assert(
         0 <= index && index < values.length,
         "Invalid data kind index. "
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index 14446a1..d6ad16b 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -16,12 +16,14 @@
   uri,
   libraryNode,
   classNode,
+  typedefNode,
   memberNode,
   treeNode,
   typeParameterNode,
   dartType,
   sourceSpan,
   constant,
+  import,
 }
 
 /// Enum used for identifying the enclosing entity of a member in serialization.
@@ -123,10 +125,14 @@
 
   void visitFunctionTypeVariable(covariant FunctionTypeVariable type,
       List<FunctionTypeVariable> functionTypeVariables) {
-    _sink.writeEnum(DartTypeKind.functionTypeVariable);
     int index = functionTypeVariables.indexOf(type);
-    assert(index != -1);
-    _sink.writeInt(index);
+    if (index == -1) {
+      // TODO(johnniwinther): Avoid free variables.
+      _sink._writeDartType(const DynamicType(), functionTypeVariables);
+    } else {
+      _sink.writeEnum(DartTypeKind.functionTypeVariable);
+      _sink.writeInt(index);
+    }
   }
 
   void visitFunctionType(covariant FunctionType type,
@@ -174,3 +180,50 @@
     _sink._writeDartType(type.typeArgument, functionTypeVariables);
   }
 }
+
+/// Data sink helper that canonicalizes [E] values using indices.
+class IndexedSink<E> {
+  final AbstractDataSink _sink;
+  final Map<E, int> _cache = {};
+
+  IndexedSink(this._sink);
+
+  /// Write a reference to [value] to the data sink.
+  ///
+  /// If [value] has not been canonicalized yet, [writeValue] is called to
+  /// serialize the [value] itself.
+  void write(E value, void writeValue(E value)) {
+    int index = _cache[value];
+    if (index == null) {
+      index = _cache.length;
+      _cache[value] = index;
+      _sink._writeIntInternal(index);
+      writeValue(value);
+    } else {
+      _sink._writeIntInternal(index);
+    }
+  }
+}
+
+/// Data source helper reads canonicalized [E] values through indices.
+class IndexedSource<E> {
+  final AbstractDataSource _source;
+  final List<E> _cache = [];
+
+  IndexedSource(this._source);
+
+  /// Reads a reference to an [E] value from the data source.
+  ///
+  /// If the value hasn't yet been read, [readValue] is called to deserialize
+  /// the value itself.
+  E read(E readValue()) {
+    int index = _source._readIntInternal();
+    if (index >= _cache.length) {
+      E value = readValue();
+      _cache.add(value);
+      return value;
+    } else {
+      return _cache[index];
+    }
+  }
+}
diff --git a/pkg/compiler/lib/src/serialization/member_data.dart b/pkg/compiler/lib/src/serialization/member_data.dart
index 08fa9a3..69bb187 100644
--- a/pkg/compiler/lib/src/serialization/member_data.dart
+++ b/pkg/compiler/lib/src/serialization/member_data.dart
@@ -35,8 +35,14 @@
     return null;
   }
   String name = member.name.name;
-  if (member is ir.Procedure && member.kind == ir.ProcedureKind.Setter) {
-    name += "=";
+  if (member is ir.Constructor) {
+    name = '.$name';
+  } else if (member is ir.Procedure) {
+    if (member.kind == ir.ProcedureKind.Factory) {
+      name = '.$name';
+    } else if (member.kind == ir.ProcedureKind.Setter) {
+      name += "=";
+    }
   }
   return name;
 }
@@ -49,6 +55,9 @@
   /// Cache of [_ClassData] for classes in this library.
   Map<String, _ClassData> _classes;
 
+  /// Cache of [ir.Typedef] nodes for typedefs in this library.
+  Map<String, ir.Typedef> _typedefs;
+
   /// Cache of [_MemberData] for members in this library.
   Map<String, _MemberData> _members;
 
@@ -67,6 +76,20 @@
     return _classes[name];
   }
 
+  ir.Typedef lookupTypedef(String name) {
+    if (_typedefs == null) {
+      _typedefs = {};
+      for (ir.Typedef typedef in node.typedefs) {
+        assert(
+            !_typedefs.containsKey(typedef.name),
+            "Duplicate typedef '${typedef.name}' in $_typedefs "
+            "trying to add $typedef.");
+        _typedefs[typedef.name] = typedef;
+      }
+    }
+    return _typedefs[name];
+  }
+
   /// Returns the [_MemberData] for the member uniquely identified by [name] in
   /// this library.
   _MemberData lookupMember(String name) {
diff --git a/pkg/compiler/lib/src/serialization/mixins.dart b/pkg/compiler/lib/src/serialization/mixins.dart
index e5b009f..eb86a2a 100644
--- a/pkg/compiler/lib/src/serialization/mixins.dart
+++ b/pkg/compiler/lib/src/serialization/mixins.dart
@@ -256,6 +256,18 @@
   }
 
   @override
+  List<E> readConstants<E extends ConstantValue>({bool emptyAsNull: false}) {
+    int count = readInt();
+    if (count == 0 && emptyAsNull) return null;
+    List<E> list = new List<E>(count);
+    for (int i = 0; i < count; i++) {
+      ConstantValue value = readConstant();
+      list[i] = value;
+    }
+    return list;
+  }
+
+  @override
   Map<K, V> readConstantMap<K extends ConstantValue, V>(V f(),
       {bool emptyAsNull: false}) {
     int count = readInt();
@@ -277,6 +289,30 @@
     }
     return null;
   }
+
+  @override
+  List<ImportEntity> readImports({bool emptyAsNull: false}) {
+    int count = readInt();
+    if (count == 0 && emptyAsNull) return null;
+    List<ImportEntity> list = new List<ImportEntity>(count);
+    for (int i = 0; i < count; i++) {
+      list[i] = readImport();
+    }
+    return list;
+  }
+
+  @override
+  Map<ImportEntity, V> readImportMap<V>(V f(), {bool emptyAsNull: false}) {
+    int count = readInt();
+    if (count == 0 && emptyAsNull) return null;
+    Map<ImportEntity, V> map = {};
+    for (int i = 0; i < count; i++) {
+      ImportEntity key = readImport();
+      V value = f();
+      map[key] = value;
+    }
+    return map;
+  }
 }
 
 /// Mixin that implements all convenience methods of [DataSink].
@@ -545,6 +581,19 @@
   }
 
   @override
+  void writeConstants(Iterable<ConstantValue> values, {bool allowNull: false}) {
+    if (values == null) {
+      assert(allowNull);
+      writeInt(0);
+    } else {
+      writeInt(values.length);
+      for (ConstantValue value in values) {
+        writeConstant(value);
+      }
+    }
+  }
+
+  @override
   void writeConstantMap<V>(Map<ConstantValue, V> map, void f(V value),
       {bool allowNull: false}) {
     if (map == null) {
@@ -566,4 +615,32 @@
       writeLibrary(value);
     }
   }
+
+  @override
+  void writeImports(Iterable<ImportEntity> values, {bool allowNull: false}) {
+    if (values == null) {
+      assert(allowNull);
+      writeInt(0);
+    } else {
+      writeInt(values.length);
+      for (ImportEntity value in values) {
+        writeImport(value);
+      }
+    }
+  }
+
+  @override
+  void writeImportMap<V>(Map<ImportEntity, V> map, void f(V value),
+      {bool allowNull: false}) {
+    if (map == null) {
+      assert(allowNull);
+      writeInt(0);
+    } else {
+      writeInt(map.length);
+      map.forEach((ImportEntity key, V value) {
+        writeImport(key);
+        f(value);
+      });
+    }
+  }
 }
diff --git a/pkg/compiler/lib/src/serialization/node_indexer.dart b/pkg/compiler/lib/src/serialization/node_indexer.dart
index c9370f1..719390e 100644
--- a/pkg/compiler/lib/src/serialization/node_indexer.dart
+++ b/pkg/compiler/lib/src/serialization/node_indexer.dart
@@ -139,4 +139,22 @@
     registerNode(node);
     super.visitStaticInvocation(node);
   }
+
+  @override
+  void visitLabeledStatement(ir.LabeledStatement node) {
+    registerNode(node);
+    super.visitLabeledStatement(node);
+  }
+
+  @override
+  void visitSwitchCase(ir.SwitchCase node) {
+    registerNode(node);
+    super.visitSwitchCase(node);
+  }
+
+  @override
+  void visitContinueSwitchStatement(ir.ContinueSwitchStatement node) {
+    registerNode(node);
+    super.visitContinueSwitchStatement(node);
+  }
 }
diff --git a/pkg/compiler/lib/src/serialization/object_sink.dart b/pkg/compiler/lib/src/serialization/object_sink.dart
index 195db2a..3246b9f 100644
--- a/pkg/compiler/lib/src/serialization/object_sink.dart
+++ b/pkg/compiler/lib/src/serialization/object_sink.dart
@@ -23,25 +23,25 @@
   }
 
   @override
-  void _writeEnum(dynamic value) {
+  void _writeEnumInternal(dynamic value) {
     assert(value != null);
     _data.add(value);
   }
 
   @override
-  void _writeInt(int value) {
+  void _writeIntInternal(int value) {
     assert(value != null);
     _data.add(value);
   }
 
   @override
-  void _writeString(String value) {
+  void _writeStringInternal(String value) {
     assert(value != null);
     _data.add(value);
   }
 
   @override
-  void _writeUri(Uri value) {
+  void _writeUriInternal(Uri value) {
     assert(value != null);
     _data.add(value);
   }
@@ -50,4 +50,8 @@
   void close() {
     _data = null;
   }
+
+  /// Returns the number of objects written to this data sink.
+  @override
+  int get length => _data.length;
 }
diff --git a/pkg/compiler/lib/src/serialization/object_source.dart b/pkg/compiler/lib/src/serialization/object_source.dart
index cae965b..4ce571e 100644
--- a/pkg/compiler/lib/src/serialization/object_source.dart
+++ b/pkg/compiler/lib/src/serialization/object_source.dart
@@ -40,16 +40,16 @@
   }
 
   @override
-  String _readString() => _read();
+  String _readStringInternal() => _read();
 
   @override
-  E _readEnum<E>(List<E> values) => _read();
+  E _readEnumInternal<E>(List<E> values) => _read();
 
   @override
-  Uri _readUri() => _read();
+  Uri _readUriInternal() => _read();
 
   @override
-  int _readInt() => _read();
+  int _readIntInternal() => _read();
 
   @override
   String get _errorContext {
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index a5b738a..3c2c52d 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -6,6 +6,8 @@
 import 'dart:typed_data';
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/binary/ast_to_binary.dart';
+import 'package:kernel/binary/ast_from_binary.dart' as ir;
+import 'package:kernel/binary/ast_to_binary.dart' as ir;
 import '../closure.dart';
 import '../constants/values.dart';
 import '../diagnostics/source_span.dart';
@@ -28,6 +30,11 @@
 
 /// Interface for serialization.
 abstract class DataSink {
+  /// The amount of data written to this data sink.
+  ///
+  /// The units is based on the underlying data structure for this data sink.
+  int get length;
+
   /// Flushes any pending data and closes this data sink.
   ///
   /// The data sink can no longer be written to after closing.
@@ -45,6 +52,10 @@
   /// between serialization and deserialization.
   void end(String tag);
 
+  /// Writes a reference to [value] to this data sink. If [value] has not yet
+  /// been serialized, [f] is called to serialize the value itself.
+  void writeCached<E>(E value, void f(E value));
+
   /// Writes the potentially `null` [value] to this data sink. If [value] is
   /// non-null [f] is called to write the non-null value to the data sink.
   ///
@@ -112,6 +123,9 @@
   /// Writes a reference to the kernel class node [value] to this data sink.
   void writeClassNode(ir.Class value);
 
+  /// Writes a reference to the kernel typedef node [value] to this data sink.
+  void writeTypedefNode(ir.Typedef value);
+
   /// Writes a reference to the kernel member node [value] to this data sink.
   void writeMemberNode(ir.Member value);
 
@@ -264,7 +278,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSource.readLocals].
-  void writeLocals(Iterable<Local> locals, {bool allowNull: false});
+  void writeLocals(Iterable<Local> values, {bool allowNull: false});
 
   /// Writes the [map] from references to locals to [V] values to this data
   /// sink, calling [f] to write each value to the data sink. If [allowNull] is
@@ -278,6 +292,13 @@
   /// Writes the constant [value] to this data sink.
   void writeConstant(ConstantValue value);
 
+  /// Writes constant [values] to this data sink. If [allowNull] is `true`,
+  /// [values] is allowed to be `null`.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSource.readConstants].
+  void writeConstants(Iterable<ConstantValue> values, {bool allowNull: false});
+
   /// Writes the [map] from constant values to [V] values to this data sink,
   /// calling [f] to write each value to the data sink. If [allowNull] is
   /// `true`, [map] is allowed to be `null`.
@@ -286,6 +307,25 @@
   /// [DataSource.readConstantMap].
   void writeConstantMap<V>(Map<ConstantValue, V> map, void f(V value),
       {bool allowNull: false});
+
+  /// Writes the import [value] to this data sink.
+  void writeImport(ImportEntity value);
+
+  /// Writes import [values] to this data sink. If [allowNull] is `true`,
+  /// [values] is allowed to be `null`.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSource.readImports].
+  void writeImports(Iterable<ImportEntity> values, {bool allowNull: false});
+
+  /// Writes the [map] from imports to [V] values to this data sink,
+  /// calling [f] to write each value to the data sink. If [allowNull] is
+  /// `true`, [map] is allowed to be `null`.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSource.readImportMap].
+  void writeImportMap<V>(Map<ImportEntity, V> map, void f(V value),
+      {bool allowNull: false});
 }
 
 /// Interface for deserialization.
@@ -314,6 +354,10 @@
   /// deserialization of references to locals.
   void registerLocalLookup(LocalLookup localLookup);
 
+  /// 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.
+  E readCached<E>(E f());
+
   /// Reads a potentially `null` [E] value from this data source, calling [f] to
   /// read the non-null value from the data source.
   ///
@@ -385,6 +429,9 @@
   /// Reads a reference to a kernel class node from this data source.
   ir.Class readClassNode();
 
+  /// Reads a reference to a kernel class node from this data source.
+  ir.Typedef readTypedefNode();
+
   /// Reads a reference to a kernel member node from this data source.
   ir.Member readMemberNode();
 
@@ -526,6 +573,13 @@
   /// Reads a constant value from this data source.
   ConstantValue readConstant();
 
+  /// Reads a list of constant values from this data source. If [emptyAsNull] is
+  /// `true`, `null` is returned instead of an empty list.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSink.writeConstants].
+  List<E> readConstants<E extends ConstantValue>({bool emptyAsNull: false});
+
   /// Reads a map from constant values to [V] values from this data source,
   /// calling [f] to read each value from the data source. If [emptyAsNull] is
   /// `true`, `null` is returned instead of an empty map.
@@ -534,6 +588,24 @@
   /// [DataSink.writeConstantMap].
   Map<K, V> readConstantMap<K extends ConstantValue, V>(V f(),
       {bool emptyAsNull: false});
+
+  /// Reads a import from this data source.
+  ImportEntity readImport();
+
+  /// Reads a list of imports from this data source. If [emptyAsNull] is
+  /// `true`, `null` is returned instead of an empty list.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSink.writeImports].
+  List<ImportEntity> readImports({bool emptyAsNull: false});
+
+  /// Reads a map from imports to [V] values from this data source,
+  /// calling [f] to read each value from the data source. If [emptyAsNull] is
+  /// `true`, `null` is returned instead of an empty map.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSink.writeImportMap].
+  Map<ImportEntity, V> readImportMap<V>(V f(), {bool emptyAsNull: false});
 }
 
 /// Interface used for looking up entities by index during deserialization.
diff --git a/pkg/compiler/lib/src/serialization/strategies.dart b/pkg/compiler/lib/src/serialization/strategies.dart
new file mode 100644
index 0000000..f4a03db
--- /dev/null
+++ b/pkg/compiler/lib/src/serialization/strategies.dart
@@ -0,0 +1,148 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:front_end/src/fasta/kernel/utils.dart' as ir
+    show serializeComponent;
+import 'package:front_end/src/fasta/kernel/utils.dart';
+import 'package:kernel/ast.dart' as ir;
+import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
+
+import '../../compiler_new.dart' as api;
+import '../diagnostics/diagnostic_listener.dart';
+import '../environment.dart';
+import '../js_model/js_world.dart';
+import '../options.dart';
+import '../source_file_provider.dart';
+import '../types/abstract_value_domain.dart';
+import '../types/types.dart';
+import 'serialization.dart';
+import 'task.dart';
+
+abstract class SerializationStrategy<T> {
+  const SerializationStrategy();
+
+  List<int> serializeComponent(GlobalTypeInferenceResults results) {
+    JsClosedWorld closedWorld = results.closedWorld;
+    ir.Component component = closedWorld.elementMap.programEnv.mainComponent;
+    return ir.serializeComponent(component);
+  }
+
+  List<T> serializeData(GlobalTypeInferenceResults results);
+
+  ir.Component deserializeComponent(List<int> data) {
+    ir.Component component = new ir.Component();
+    new BinaryBuilder(data).readComponent(component);
+    return component;
+  }
+
+  GlobalTypeInferenceResults deserializeData(
+      CompilerOptions options,
+      DiagnosticReporter reporter,
+      Environment environment,
+      AbstractValueStrategy abstractValueStrategy,
+      ir.Component component,
+      List<T> data);
+}
+
+class BytesInMemorySerializationStrategy extends SerializationStrategy<int> {
+  final bool useDataKinds;
+
+  const BytesInMemorySerializationStrategy({this.useDataKinds: false});
+
+  @override
+  List<int> serializeData(GlobalTypeInferenceResults results) {
+    ByteSink byteSink = new ByteSink();
+    DataSink sink = new BinarySink(byteSink, useDataKinds: useDataKinds);
+    serializeGlobalTypeInferenceResults(results, sink);
+    return byteSink.builder.takeBytes();
+  }
+
+  @override
+  GlobalTypeInferenceResults deserializeData(
+      CompilerOptions options,
+      DiagnosticReporter reporter,
+      Environment environment,
+      AbstractValueStrategy abstractValueStrategy,
+      ir.Component component,
+      List<int> data) {
+    DataSource source = new BinarySourceImpl(data, useDataKinds: useDataKinds);
+    return deserializeGlobalTypeInferenceResults(options, reporter, environment,
+        abstractValueStrategy, component, source);
+  }
+}
+
+class BytesOnDiskSerializationStrategy extends SerializationStrategy<int> {
+  final bool useDataKinds;
+
+  const BytesOnDiskSerializationStrategy({this.useDataKinds: false});
+
+  @override
+  List<int> serializeData(GlobalTypeInferenceResults results) {
+    Uri uri = Uri.base.resolve('world.data');
+    DataSink sink = new BinarySink(
+        new BinaryOutputSinkAdapter(new RandomAccessBinaryOutputSink(uri)),
+        useDataKinds: useDataKinds);
+    serializeGlobalTypeInferenceResults(results, sink);
+    return new File.fromUri(uri).readAsBytesSync();
+  }
+
+  @override
+  GlobalTypeInferenceResults deserializeData(
+      CompilerOptions options,
+      DiagnosticReporter reporter,
+      Environment environment,
+      AbstractValueStrategy abstractValueStrategy,
+      ir.Component component,
+      List<int> data) {
+    DataSource source = new BinarySourceImpl(data, useDataKinds: useDataKinds);
+    return deserializeGlobalTypeInferenceResults(options, reporter, environment,
+        abstractValueStrategy, component, source);
+  }
+}
+
+class ObjectsInMemorySerializationStrategy
+    extends SerializationStrategy<Object> {
+  final bool useDataKinds;
+
+  const ObjectsInMemorySerializationStrategy({this.useDataKinds: true});
+
+  @override
+  List<Object> serializeData(GlobalTypeInferenceResults results) {
+    List<Object> data = [];
+    DataSink sink = new ObjectSink(data, useDataKinds: useDataKinds);
+    serializeGlobalTypeInferenceResults(results, sink);
+    return data;
+  }
+
+  @override
+  GlobalTypeInferenceResults deserializeData(
+      CompilerOptions options,
+      DiagnosticReporter reporter,
+      Environment environment,
+      AbstractValueStrategy abstractValueStrategy,
+      ir.Component component,
+      List<Object> data) {
+    DataSource source = new ObjectSource(data, useDataKinds: useDataKinds);
+    return deserializeGlobalTypeInferenceResults(options, reporter, environment,
+        abstractValueStrategy, component, source);
+  }
+}
+
+class BinaryOutputSinkAdapter implements Sink<List<int>> {
+  api.BinaryOutputSink output;
+
+  BinaryOutputSinkAdapter(this.output);
+
+  @override
+  void add(List<int> data) {
+    output.write(data);
+  }
+
+  @override
+  void close() {
+    output.close();
+  }
+}
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
new file mode 100644
index 0000000..b2ce9e1
--- /dev/null
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'package:kernel/ast.dart' as ir;
+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 '../common/tasks.dart';
+import '../compiler.dart';
+import '../diagnostics/diagnostic_listener.dart';
+import '../environment.dart';
+import '../js_backend/inferred_data.dart';
+import '../js_model/js_world.dart';
+import '../options.dart';
+import '../types/abstract_value_domain.dart';
+import '../types/types.dart';
+import 'strategies.dart';
+import 'serialization.dart';
+
+void serializeGlobalTypeInferenceResults(
+    GlobalTypeInferenceResults results, DataSink sink) {
+  JsClosedWorld closedWorld = results.closedWorld;
+  InferredData inferredData = results.inferredData;
+  closedWorld.writeToDataSink(sink);
+  inferredData.writeToDataSink(sink);
+  results.writeToDataSink(sink);
+  sink.close();
+}
+
+GlobalTypeInferenceResults deserializeGlobalTypeInferenceResults(
+    CompilerOptions options,
+    DiagnosticReporter reporter,
+    Environment environment,
+    AbstractValueStrategy abstractValueStrategy,
+    ir.Component component,
+    DataSource source) {
+  JsClosedWorld newClosedWorld = new JsClosedWorld.readFromDataSource(
+      options, reporter, environment, abstractValueStrategy, component, source);
+  InferredData newInferredData =
+      new InferredData.readFromDataSource(source, newClosedWorld);
+  return new GlobalTypeInferenceResults.readFromDataSource(
+      source, newClosedWorld, newInferredData);
+}
+
+class SerializationTask extends CompilerTask {
+  final Compiler compiler;
+
+  SerializationTask(this.compiler, Measurer measurer) : super(measurer);
+
+  String get name => 'Serialization';
+
+  void serialize(GlobalTypeInferenceResults results) {
+    measureSubtask('serialize dill', () {
+      compiler.reporter.log('Writing dill to ${compiler.options.outputUri}');
+      api.BinaryOutputSink dillOutput =
+          compiler.outputProvider.createBinarySink(compiler.options.outputUri);
+      JsClosedWorld closedWorld = results.closedWorld;
+      ir.Component component = closedWorld.elementMap.programEnv.mainComponent;
+      BinaryOutputSinkAdapter irSink = new BinaryOutputSinkAdapter(dillOutput);
+      ir.BinaryPrinter printer = new ir.BinaryPrinter(irSink);
+      printer.writeComponentFile(component);
+      irSink.close();
+    });
+
+    measureSubtask('serialize data', () {
+      compiler.reporter.log('Writing data to ${compiler.options.writeDataUri}');
+      api.BinaryOutputSink dataOutput = compiler.outputProvider
+          .createBinarySink(compiler.options.writeDataUri);
+      DataSink sink = new BinarySink(new BinaryOutputSinkAdapter(dataOutput));
+      serializeGlobalTypeInferenceResults(results, sink);
+    });
+  }
+
+  Future<GlobalTypeInferenceResults> deserialize() 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);
+      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);
+      DataSource source = new BinarySourceImpl(dataInput.data);
+      return deserializeGlobalTypeInferenceResults(
+          compiler.options,
+          compiler.reporter,
+          compiler.environment,
+          compiler.abstractValueStrategy,
+          component,
+          source);
+    });
+  }
+}
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index c2d2fd0..986b990 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -27,6 +27,9 @@
 
   Future<api.Input<List<int>>> readBytesFromUri(
       Uri resourceUri, api.InputKind inputKind) {
+    if (!resourceUri.isAbsolute) {
+      resourceUri = cwd.resolveUri(resourceUri);
+    }
     api.Input<List<int>> input;
     switch (inputKind) {
       case api.InputKind.UTF8:
@@ -320,6 +323,7 @@
   int totalCharactersWritten = 0;
   int totalCharactersWrittenPrimary = 0;
   int totalCharactersWrittenJavaScript = 0;
+  int totalDataWritten = 0;
 
   List<String> allOutputFiles = <String>[];
 
@@ -386,7 +390,7 @@
 
     int charactersWritten = 0;
 
-    writeStringSync(String data) {
+    void writeStringSync(String data) {
       // Write the data in chunks of 8kb, otherwise we risk running OOM.
       int chunkSize = 8 * 1024;
 
@@ -399,7 +403,7 @@
       charactersWritten += data.length;
     }
 
-    onDone() {
+    void onDone() {
       output.closeSync();
       totalCharactersWritten += charactersWritten;
       if (isPrimaryOutput) {
@@ -412,10 +416,60 @@
 
     return new _OutputSinkWrapper(writeStringSync, onDone);
   }
+
+  @override
+  BinaryOutputSink createBinarySink(Uri uri) {
+    uri = currentDirectory.resolveUri(uri);
+
+    allOutputFiles.add(relativize(currentDirectory, uri, Platform.isWindows));
+
+    if (uri.scheme != 'file') {
+      onFailure('Unhandled scheme ${uri.scheme} in $uri.');
+    }
+
+    RandomAccessFile output;
+    try {
+      output = new File(uri.toFilePath()).openSync(mode: FileMode.WRITE);
+    } on FileSystemException catch (e) {
+      onFailure('$e');
+    }
+
+    int bytesWritten = 0;
+
+    void writeBytesSync(List<int> data, [int start = 0, int end]) {
+      output.writeFromSync(data, start, end);
+      bytesWritten += (end ?? data.length) - start;
+    }
+
+    void onDone() {
+      output.closeSync();
+      totalDataWritten += bytesWritten;
+    }
+
+    return new _BinaryOutputSinkWrapper(writeBytesSync, onDone);
+  }
+}
+
+class RandomAccessBinaryOutputSink implements api.BinaryOutputSink {
+  final RandomAccessFile output;
+
+  RandomAccessBinaryOutputSink(Uri uri)
+      : output = new File.fromUri(uri).openSync(mode: FileMode.write);
+
+  @override
+  void write(List<int> buffer, [int start = 0, int end]) {
+    output.writeFromSync(buffer, start, end);
+  }
+
+  @override
+  void close() {
+    output.closeSync();
+  }
 }
 
 class _OutputSinkWrapper extends OutputSink {
-  var onAdd, onClose;
+  void Function(String) onAdd;
+  void Function() onClose;
 
   _OutputSinkWrapper(this.onAdd, this.onClose);
 
@@ -424,6 +478,18 @@
   void close() => onClose();
 }
 
+class _BinaryOutputSinkWrapper extends BinaryOutputSink {
+  void Function(List<int>, [int, int]) onWrite;
+  void Function() onClose;
+
+  _BinaryOutputSinkWrapper(this.onWrite, this.onClose);
+
+  void write(List<int> data, [int start = 0, int end]) =>
+      onWrite(data, start, end);
+
+  void close() => onClose();
+}
+
 /// Adapter to integrate dart2js in bazel.
 ///
 /// To handle bazel's special layout:
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 262a7ea..25993e7 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -36,12 +36,12 @@
 import '../types/abstract_value_domain.dart';
 import '../types/types.dart';
 import '../universe/call_structure.dart';
+import '../universe/codegen_world_builder.dart';
 import '../universe/feature.dart';
 import '../universe/selector.dart';
 import '../universe/side_effects.dart' show SideEffects;
 import '../universe/target_checks.dart' show TargetChecks;
 import '../universe/use.dart' show ConstantUse, StaticUse;
-import '../universe/world_builder.dart' show CodegenWorldBuilder;
 import '../world.dart';
 import 'graph_builder.dart';
 import 'jump_handler.dart';
@@ -260,7 +260,7 @@
               initialTargetElement, _functionNodeOf(definition.node));
           break;
       }
-      assert(graph.isValid());
+      assert(graph.isValid(), "Invalid graph for $initialTargetElement.");
 
       if (backend.tracer.isEnabled) {
         MemberEntity member = initialTargetElement;
@@ -1149,7 +1149,9 @@
     void _handleParameter(ir.VariableDeclaration variable) {
       Local local = localsMap.getLocalVariable(variable);
       if (nodeIsConstructorBody &&
-          closureDataLookup.getCapturedScope(targetElement).isBoxed(local)) {
+          closureDataLookup
+              .getCapturedScope(targetElement)
+              .isBoxedVariable(local)) {
         // If local is boxed, then `variable` will be a field inside the box
         // passed as the last parameter, so no need to update our locals
         // handler or check types at this point.
@@ -1370,7 +1372,7 @@
   @override
   void visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded checkLoad) {
     ImportEntity import = _elementMap.getImport(checkLoad.import);
-    String loadId = deferredLoadTask.getImportDeferName(
+    String loadId = closedWorld.outputUnitData.getImportDeferName(
         _elementMap.getSpannable(targetElement, checkLoad), import);
     HInstruction prefixConstant = graph.addConstantString(loadId, closedWorld);
     HInstruction uriConstant =
@@ -1386,7 +1388,7 @@
 
   @override
   void visitLoadLibrary(ir.LoadLibrary loadLibrary) {
-    String loadId = deferredLoadTask.getImportDeferName(
+    String loadId = closedWorld.outputUnitData.getImportDeferName(
         _elementMap.getSpannable(targetElement, loadLibrary),
         _elementMap.getImport(loadLibrary.import));
     // TODO(efortuna): Source information!
@@ -2594,7 +2596,7 @@
           new SubGraph(defaultCase, defaultCase)));
     }
     assert(caseHandlers.length == joinBlock.predecessors.length);
-    if (caseHandlers.length != 0) {
+    if (caseHandlers.isNotEmpty) {
       graph.addBlock(joinBlock);
       open(joinBlock);
       if (caseHandlers.length == 1) {
@@ -2738,8 +2740,8 @@
           listInstruction, type, sourceInformation);
     }
 
-    AbstractValue type = _typeInferenceMap.typeOfListLiteral(
-        targetElement, node, abstractValueDomain);
+    AbstractValue type =
+        _typeInferenceMap.typeOfListLiteral(node, abstractValueDomain);
     if (!abstractValueDomain.containsAll(type)) {
       listInstruction.instructionType = type;
     }
@@ -3369,13 +3371,7 @@
         function == commonElements.jsArrayTypedConstructor;
 
     _inferredTypeOfNewList(ir.StaticInvocation node) {
-      MemberEntity element = sourceElement is ConstructorBodyEntity
-          ? (sourceElement as ConstructorBodyEntity).constructor
-          : sourceElement;
-
-      return globalInferenceResults
-              .resultOfMember(element)
-              .typeOfNewList(node) ??
+      return globalInferenceResults.typeOfNewList(node) ??
           abstractValueDomain.dynamicType;
     }
 
@@ -5325,7 +5321,8 @@
     bool hasBox = false;
     forEachOrderedParameter(closedWorld.globalLocalsMap, _elementMap, function,
         (Local parameter) {
-      if (forGenerativeConstructorBody && scopeData.isBoxed(parameter)) {
+      if (forGenerativeConstructorBody &&
+          scopeData.isBoxedVariable(parameter)) {
         // The parameter will be a field in the box passed as the last
         // parameter. So no need to have it.
         hasBox = true;
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 83d7920..bcfe386 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -1710,25 +1710,49 @@
   }
 
   void generateIf(HIf node, HIfBlockInformation info) {
-    use(node.inputs[0]);
-    js.Expression test = pop();
-
     HStatementInformation thenGraph = info.thenGraph;
     HStatementInformation elseGraph = info.elseGraph;
-    js.Statement thenPart =
-        unwrapStatement(generateStatementsInNewBlock(thenGraph));
-    js.Statement elsePart =
-        unwrapStatement(generateStatementsInNewBlock(elseGraph));
+    HInstruction condition = node.inputs.single;
 
-    js.Statement code;
+    js.Expression test;
+    js.Statement thenPart;
+    js.Statement elsePart;
+
+    HBasicBlock thenBlock = node.block.successors[0];
+    // If we believe we will generate S1 as empty, try to generate
+    //
+    //     if (e) S1; else S2;
+    // as
+    //     if (!e) S2; else S1;
+    //
+    // It is better to generate `!e` rather than try and negate it later.
+    // Recognize a single then-block with no code and no controlled phis.
+    if (isGenerateAtUseSite(condition) &&
+        thenBlock.successors.length == 1 &&
+        thenBlock.successors.single == node.joinBlock &&
+        node.joinBlock.phis.isEmpty &&
+        thenBlock.first is HGoto) {
+      generateNot(condition, condition.sourceInformation);
+      test = pop();
+      // Swap branches but visit in same order as register allocator.
+      elsePart = unwrapStatement(generateStatementsInNewBlock(thenGraph));
+      thenPart = unwrapStatement(generateStatementsInNewBlock(elseGraph));
+      assert(elsePart is js.EmptyStatement);
+    } else {
+      use(condition);
+      test = pop();
+      thenPart = unwrapStatement(generateStatementsInNewBlock(thenGraph));
+      elsePart = unwrapStatement(generateStatementsInNewBlock(elseGraph));
+    }
+
     // Peephole rewrites:
     //
     //     if (e); else S;   -->   if(!e) S;
     //
     //     if (e);   -->   e;
     //
-    // TODO(sra): This peephole optimization would be better done as an SSA
-    // optimization.
+    // TODO(sra): We might be able to do better with reshaping the CFG.
+    js.Statement code;
     if (thenPart is js.EmptyStatement) {
       if (elsePart is js.EmptyStatement) {
         code = new js.ExpressionStatement(test);
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index 8c86276..38e6d68 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -83,38 +83,43 @@
   }
 
   /// Returns the single JavaScript comparison (`==` or `===`) if that
-  /// implements `identical(left, right)`, or returns `null` if a more complex
-  /// expression is needed.
+  /// implements `identical(left, right)`, or returns `null` if the more complex
+  /// ternary `left == null ? right == null : left === right` is required.
   String simpleOp(HInstruction left, HInstruction right) {
     AbstractValue leftType = left.instructionType;
     AbstractValue rightType = right.instructionType;
-    if (_abstractValueDomain.canBeNull(leftType) &&
-        _abstractValueDomain.canBeNull(rightType)) {
-      // Can't use `===` on Dart `null` since it is implemented by JavaScript
-      // `null` and `undefined`.
-      if (left.isConstantNull() || right.isConstantNull()) {
-        return '==';
-      }
-      if (_abstractValueDomain.isNumberOrNull(leftType) &&
-          _abstractValueDomain.isNumberOrNull(rightType)) {
-        return '==';
-      }
-      if (_abstractValueDomain.isStringOrNull(leftType) &&
-          _abstractValueDomain.isStringOrNull(rightType)) {
-        return '==';
-      }
-      if (_abstractValueDomain.isBooleanOrNull(leftType) &&
-          _abstractValueDomain.isBooleanOrNull(rightType)) {
-        return '==';
-      }
+    if (!_abstractValueDomain.canBeNull(leftType)) return '===';
+    if (!_abstractValueDomain.canBeNull(rightType)) return '===';
 
-      // TODO(34439): There are more cases that can compile to `==` without
-      // triggering a conversion in the JavaScript evaluation. `==` will work
-      // for most Dart objects, but we have to ensure neither side can be a
-      // JavaScript Number, String, Symbol or Boolean.
-      return null;
+    // Dart `null` is implemented by JavaScript `null` and `undefined` which are
+    // not strict-equals, so we can't use `===`. We would like to use `==` but
+    // need to avoid any cases from ES6 7.2.14 that involve conversions.
+    if (left.isConstantNull() || right.isConstantNull()) {
+      return '==';
     }
-    return '===';
+
+    if (_abstractValueDomain.isNumberOrNull(leftType) &&
+        _abstractValueDomain.isNumberOrNull(rightType)) {
+      return '==';
+    }
+    if (_abstractValueDomain.isStringOrNull(leftType) &&
+        _abstractValueDomain.isStringOrNull(rightType)) {
+      return '==';
+    }
+    if (_abstractValueDomain.isBooleanOrNull(leftType) &&
+        _abstractValueDomain.isBooleanOrNull(rightType)) {
+      return '==';
+    }
+
+    // ToPrimitive conversions of an object occur when the other operand is a
+    // primitive (Number, String, Symbol and, indirectly, Boolean). We use
+    // 'intercepted' types as a proxy for all the primitive types.
+    bool intercepted(AbstractValue type) => _abstractValueDomain
+        .canBeInterceptor(_abstractValueDomain.excludeNull(type));
+
+    if (intercepted(leftType)) return null;
+    if (intercepted(rightType)) return null;
+    return '==';
   }
 
   HInstruction visitInvokeDynamic(HInvokeDynamic node) {
diff --git a/pkg/compiler/lib/src/ssa/graph_builder.dart b/pkg/compiler/lib/src/ssa/graph_builder.dart
index 8bafdc8..207326e 100644
--- a/pkg/compiler/lib/src/ssa/graph_builder.dart
+++ b/pkg/compiler/lib/src/ssa/graph_builder.dart
@@ -17,7 +17,6 @@
 import '../js_backend/constant_handler_javascript.dart';
 import '../js_backend/interceptor_data.dart';
 import '../js_backend/inferred_data.dart';
-import '../js_backend/js_interop_analysis.dart';
 import '../js_backend/namer.dart';
 import '../js_backend/native_data.dart';
 import '../js_backend/runtime_types.dart';
@@ -84,8 +83,6 @@
 
   RuntimeTypesEncoder get rtiEncoder => backend.rtiEncoder;
 
-  JsInteropAnalysis get jsInteropAnalysis => backend.jsInteropAnalysis;
-
   InferredData get inferredData => globalInferenceResults.inferredData;
 
   DeferredLoadTask get deferredLoadTask => compiler.deferredLoadTask;
diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart
index 57f2d1d..98e128f 100644
--- a/pkg/compiler/lib/src/ssa/locals_handler.dart
+++ b/pkg/compiler/lib/src/ssa/locals_handler.dart
@@ -202,7 +202,7 @@
 
     parameters.forEach((Local local, AbstractValue typeMask) {
       if (isGenerativeConstructorBody) {
-        if (scopeData.isBoxed(local)) {
+        if (scopeData.isBoxedVariable(local)) {
           // The parameter will be a field in the box passed as the
           // last parameter. So no need to have it.
           return;
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 104c919..67455a8 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -207,6 +207,7 @@
   }
 
   visitBasicBlock(HBasicBlock block) {
+    simplifyPhis(block);
     HInstruction instruction = block.first;
     while (instruction != null) {
       HInstruction next = instruction.next;
@@ -248,6 +249,123 @@
     }
   }
 
+  // Simplify some CFG diamonds to equivalent expressions.
+  simplifyPhis(HBasicBlock block) {
+    // Is [block] the join point for a simple diamond that generates a single
+    // phi node?
+    if (block.phis.isEmpty) return;
+    HPhi phi = block.phis.first;
+    if (phi.next != null) return;
+    if (block.predecessors.length != 2) return;
+    assert(phi.inputs.length == 2);
+    HBasicBlock b1 = block.predecessors[0];
+    HBasicBlock b2 = block.predecessors[1];
+    HBasicBlock dominator = block.dominator;
+    if (!(b1.dominator == dominator && b2.dominator == dominator)) return;
+
+    // Extract the controlling condition.
+    HInstruction controlFlow = dominator.last;
+    if (controlFlow is! HIf) return;
+    HInstruction test = controlFlow.inputs.single;
+    if (test.usedBy.length > 1) return;
+
+    bool negated = false;
+    while (test is HNot) {
+      test = test.inputs.single;
+      if (test.usedBy.length > 1) return;
+      negated = !negated;
+    }
+
+    if (test is! HIdentity) return;
+    HInstruction tested;
+    if (test.inputs[0].isNull(_abstractValueDomain)) {
+      tested = test.inputs[1];
+    } else if (test.inputs[1].isNull(_abstractValueDomain)) {
+      tested = test.inputs[0];
+    } else {
+      return;
+    }
+
+    HInstruction whenNullValue = phi.inputs[negated ? 1 : 0];
+    HInstruction whenNotNullValue = phi.inputs[negated ? 0 : 1];
+    HBasicBlock whenNullBlock = block.predecessors[negated ? 1 : 0];
+    HBasicBlock whenNotNullBlock = block.predecessors[negated ? 0 : 1];
+
+    // If 'x' is nullable boolean,
+    //
+    //     x == null ? false : x  --->  x == true
+    //
+    // This ofen comes from the dart code `x ?? false`.
+    if (_sameOrRefinementOf(tested, whenNotNullValue) &&
+        _isBoolConstant(whenNullValue, false) &&
+        whenNotNullValue.isBooleanOrNull(_abstractValueDomain) &&
+        _mostlyEmpty(whenNullBlock) &&
+        _mostlyEmpty(whenNotNullBlock)) {
+      HInstruction trueConstant = _graph.addConstantBool(true, _closedWorld);
+      HInstruction replacement = new HIdentity(
+          tested, trueConstant, null, _abstractValueDomain.boolType)
+        ..sourceElement = phi.sourceElement
+        ..sourceInformation = phi.sourceInformation;
+      block.rewrite(phi, replacement);
+      block.addAtEntry(replacement);
+      block.removePhi(phi);
+      return;
+    }
+    // If 'x'is nullable boolean,
+    //
+    //     x == null ? true : x  --->  !(x == false)
+    //
+    // This ofen comes from the dart code `x ?? true`.
+    if (_sameOrRefinementOf(tested, whenNotNullValue) &&
+        _isBoolConstant(whenNullValue, true) &&
+        whenNotNullValue.isBooleanOrNull(_abstractValueDomain) &&
+        _mostlyEmpty(whenNullBlock) &&
+        _mostlyEmpty(whenNotNullBlock)) {
+      HInstruction falseConstant = _graph.addConstantBool(false, _closedWorld);
+      HInstruction compare = new HIdentity(
+          tested, falseConstant, null, _abstractValueDomain.boolType);
+      block.addAtEntry(compare);
+      HInstruction replacement =
+          new HNot(compare, _abstractValueDomain.boolType)
+            ..sourceElement = phi.sourceElement
+            ..sourceInformation = phi.sourceInformation;
+      block.rewrite(phi, replacement);
+      block.addAfter(compare, replacement);
+      block.removePhi(phi);
+      return;
+    }
+
+    // TODO(sra): Consider other simple diamonds, e.g. with the addition of a special instruction,
+    //
+    //     s == null ? "" : s  --->  s || "".
+    return;
+  }
+
+  bool _isBoolConstant(HInstruction node, bool value) {
+    if (node is HConstant) {
+      ConstantValue c = node.constant;
+      if (c is BoolConstantValue) {
+        return c.boolValue == value;
+      }
+    }
+    return false;
+  }
+
+  bool _sameOrRefinementOf(HInstruction base, HInstruction insn) {
+    if (base == insn) return true;
+    if (insn is HTypeKnown) return _sameOrRefinementOf(base, insn.checkedInput);
+    return false;
+  }
+
+  bool _mostlyEmpty(HBasicBlock block) {
+    for (HInstruction insn = block.first; insn != null; insn = insn.next) {
+      if (insn is HTypeKnown) continue;
+      if (insn is HGoto) return true;
+      return false;
+    }
+    return true;
+  }
+
   HInstruction visitInstruction(HInstruction node) {
     return node;
   }
diff --git a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
index 0038d5b..075ee0e 100644
--- a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
+++ b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
@@ -684,9 +684,7 @@
       return info.newUnboundRange();
     ConstantValue constant = hConstant.constant;
     NumConstantValue constantNum;
-    if (constant is DeferredConstantValue) {
-      constantNum = constant.referenced;
-    } else if (constant is DeferredGlobalConstantValue) {
+    if (constant is DeferredGlobalConstantValue) {
       constantNum = constant.referenced;
     } else {
       constantNum = constant;
diff --git a/pkg/compiler/lib/src/types/types.dart b/pkg/compiler/lib/src/types/types.dart
index 03ed29e5..6a1017b 100644
--- a/pkg/compiler/lib/src/types/types.dart
+++ b/pkg/compiler/lib/src/types/types.dart
@@ -50,28 +50,22 @@
   /// The inferred return type when this result belongs to a function element.
   AbstractValue get returnType;
 
-  /// Returns the type of a list new expression [node].
-  AbstractValue typeOfNewList(ir.Node node);
-
-  /// Returns the type of a list literal [node].
-  AbstractValue typeOfListLiteral(ir.Node node);
-
   /// Returns the type of a send [node].
   // TODO(johnniwinther): Rename this.
-  AbstractValue typeOfSend(ir.Node node);
+  AbstractValue typeOfSend(ir.TreeNode node);
 
   /// Returns the type of the getter in a complex send-set [node], for example,
   /// the type of the `a.f` getter in `a.f += b`.
-  AbstractValue typeOfGetter(ir.Node node);
+  AbstractValue typeOfGetter(ir.TreeNode node);
 
   /// Returns the type of the iterator in a [loop].
-  AbstractValue typeOfIterator(ir.Node node);
+  AbstractValue typeOfIterator(ir.TreeNode node);
 
   /// Returns the type of the `moveNext` call of an iterator in a [loop].
-  AbstractValue typeOfIteratorMoveNext(ir.Node node);
+  AbstractValue typeOfIteratorMoveNext(ir.TreeNode node);
 
   /// Returns the type of the `current` getter of an iterator in a [loop].
-  AbstractValue typeOfIteratorCurrent(ir.Node node);
+  AbstractValue typeOfIteratorCurrent(ir.TreeNode node);
 }
 
 /// Internal data used during type-inference to store intermediate results about
@@ -86,26 +80,19 @@
   void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain);
 
   /// Compresses the inner representation by removing [AbstractValue] mappings
-  /// to `null`.
-  void compress();
+  /// to `null`. Returns the data object itself or `null` if the data object
+  /// was empty after compression.
+  GlobalTypeInferenceElementData compress();
 
   // TODO(johnniwinther): Remove this. Maybe split by access/invoke.
   AbstractValue typeOfSend(ir.TreeNode node);
   AbstractValue typeOfGetter(ir.TreeNode node);
 
-  void setTypeMask(ir.TreeNode node, AbstractValue mask);
-
   AbstractValue typeOfIterator(ir.TreeNode node);
 
   AbstractValue typeOfIteratorMoveNext(ir.TreeNode node);
 
   AbstractValue typeOfIteratorCurrent(ir.TreeNode node);
-
-  void setIteratorTypeMask(ir.TreeNode node, AbstractValue mask);
-
-  void setMoveNextTypeMask(ir.TreeNode node, AbstractValue mask);
-
-  void setCurrentTypeMask(ir.TreeNode node, AbstractValue mask);
 }
 
 /// API to interact with the global type-inference engine.
@@ -148,7 +135,13 @@
 
   /// Returns whether a fixed-length constructor call goes through a growable
   /// check.
-  bool isFixedArrayCheckedForGrowable(ir.Node node);
+  bool isFixedArrayCheckedForGrowable(ir.TreeNode node);
+
+  /// Returns the type of a list new expression [node].
+  AbstractValue typeOfNewList(ir.TreeNode node);
+
+  /// Returns the type of a list literal [node].
+  AbstractValue typeOfListLiteral(ir.TreeNode node);
 }
 
 /// Global analysis that infers concrete types.
@@ -204,6 +197,7 @@
   final Map<Local, AbstractValue> parameterResults;
   final Set<ir.TreeNode> checkedForGrowableLists;
   final Set<Selector> returnsListElementTypeSet;
+  final Map<ir.TreeNode, AbstractValue> _allocatedLists;
 
   GlobalTypeInferenceResultsImpl(
       this.closedWorld,
@@ -211,7 +205,8 @@
       this.memberResults,
       this.parameterResults,
       this.checkedForGrowableLists,
-      this.returnsListElementTypeSet)
+      this.returnsListElementTypeSet,
+      this._allocatedLists)
       : _deadFieldResult = new DeadFieldGlobalTypeInferenceResult(
             closedWorld.abstractValueDomain),
         _deadMethodResult = new DeadMethodGlobalTypeInferenceResult(
@@ -231,6 +226,9 @@
     Set<ir.TreeNode> checkedForGrowableLists = source.readTreeNodes().toSet();
     Set<Selector> returnsListElementTypeSet =
         source.readList(() => new Selector.readFromDataSource(source)).toSet();
+    Map<ir.TreeNode, AbstractValue> allocatedLists = source.readTreeNodeMap(
+        () => closedWorld.abstractValueDomain
+            .readAbstractValueFromDataSource(source));
     source.end(tag);
     return new GlobalTypeInferenceResultsImpl(
         closedWorld,
@@ -238,7 +236,8 @@
         memberResults,
         parameterResults,
         checkedForGrowableLists,
-        returnsListElementTypeSet);
+        returnsListElementTypeSet,
+        allocatedLists);
   }
 
   void writeToDataSink(DataSink sink) {
@@ -255,6 +254,10 @@
     sink.writeTreeNodes(checkedForGrowableLists);
     sink.writeList(returnsListElementTypeSet,
         (Selector selector) => selector.writeToDataSink(sink));
+    sink.writeTreeNodeMap(
+        _allocatedLists,
+        (AbstractValue value) => closedWorld.abstractValueDomain
+            .writeAbstractValueToDataSink(sink, value));
     sink.end(tag);
   }
 
@@ -361,23 +364,25 @@
   @override
   bool isFixedArrayCheckedForGrowable(ir.Node ctorCall) =>
       checkedForGrowableLists.contains(ctorCall);
+
+  AbstractValue typeOfNewList(ir.Node node) => _allocatedLists[node];
+
+  AbstractValue typeOfListLiteral(ir.Node node) => _allocatedLists[node];
 }
 
 class GlobalTypeInferenceMemberResultImpl
     implements GlobalTypeInferenceMemberResult {
   /// Tag used for identifying serialized [GlobalTypeInferenceMemberResult]
   /// objects in a debugging data stream.
-  static const String tag = 'global-type-inference-mebmer-result';
+  static const String tag = 'global-type-inference-member-result';
 
   final GlobalTypeInferenceElementData _data;
-  final Map<ir.TreeNode, AbstractValue> _allocatedLists;
   final AbstractValue returnType;
   final AbstractValue type;
   final bool throwsAlways;
   final bool isCalledOnce;
 
-  GlobalTypeInferenceMemberResultImpl(
-      this._data, this._allocatedLists, this.returnType, this.type,
+  GlobalTypeInferenceMemberResultImpl(this._data, this.returnType, this.type,
       {this.throwsAlways, this.isCalledOnce});
 
   factory GlobalTypeInferenceMemberResultImpl.readFromDataSource(
@@ -387,8 +392,6 @@
       return new GlobalTypeInferenceElementData.readFromDataSource(
           source, abstractValueDomain);
     });
-    Map<ir.TreeNode, AbstractValue> allocatedLists = source.readTreeNodeMap(
-        () => abstractValueDomain.readAbstractValueFromDataSource(source));
     AbstractValue returnType =
         abstractValueDomain.readAbstractValueFromDataSource(source);
     AbstractValue type =
@@ -396,8 +399,7 @@
     bool throwsAlways = source.readBool();
     bool isCalledOnce = source.readBool();
     source.end(tag);
-    return new GlobalTypeInferenceMemberResultImpl(
-        data, allocatedLists, returnType, type,
+    return new GlobalTypeInferenceMemberResultImpl(data, returnType, type,
         throwsAlways: throwsAlways, isCalledOnce: isCalledOnce);
   }
 
@@ -406,10 +408,6 @@
     sink.writeValueOrNull(_data, (GlobalTypeInferenceElementData data) {
       data.writeToDataSink(sink, abstractValueDomain);
     });
-    sink.writeTreeNodeMap(
-        _allocatedLists,
-        (AbstractValue value) =>
-            abstractValueDomain.writeAbstractValueToDataSink(sink, value));
     abstractValueDomain.writeAbstractValueToDataSink(sink, returnType);
     abstractValueDomain.writeAbstractValueToDataSink(sink, type);
     sink.writeBool(throwsAlways);
@@ -424,10 +422,6 @@
       _data?.typeOfIteratorMoveNext(node);
   AbstractValue typeOfIteratorCurrent(ir.Node node) =>
       _data?.typeOfIteratorCurrent(node);
-
-  AbstractValue typeOfNewList(ir.Node node) => _allocatedLists[node];
-
-  AbstractValue typeOfListLiteral(ir.Node node) => _allocatedLists[node];
 }
 
 class TrivialGlobalTypeInferenceResults implements GlobalTypeInferenceResults {
@@ -462,6 +456,12 @@
   GlobalTypeInferenceMemberResult resultOfMember(MemberEntity member) {
     return _trivialMemberResult;
   }
+
+  @override
+  AbstractValue typeOfListLiteral(ir.TreeNode node) => null;
+
+  @override
+  AbstractValue typeOfNewList(ir.TreeNode node) => null;
 }
 
 class TrivialGlobalTypeInferenceMemberResult
@@ -495,12 +495,6 @@
   AbstractValue typeOfSend(ir.Node node) => null;
 
   @override
-  AbstractValue typeOfListLiteral(ir.Node node) => null;
-
-  @override
-  AbstractValue typeOfNewList(ir.Node node) => null;
-
-  @override
   bool get isCalledOnce => false;
 
   void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
@@ -543,12 +537,6 @@
   AbstractValue typeOfSend(ir.Node node) => null;
 
   @override
-  AbstractValue typeOfListLiteral(ir.Node node) => null;
-
-  @override
-  AbstractValue typeOfNewList(ir.Node node) => null;
-
-  @override
   bool get isCalledOnce => false;
 
   void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
@@ -591,12 +579,6 @@
   AbstractValue typeOfSend(ir.Node node) => null;
 
   @override
-  AbstractValue typeOfListLiteral(ir.Node node) => null;
-
-  @override
-  AbstractValue typeOfNewList(ir.Node node) => null;
-
-  @override
   bool get isCalledOnce => false;
 
   void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart
index 6431ab6..85d96a2 100644
--- a/pkg/compiler/lib/src/universe/class_set.dart
+++ b/pkg/compiler/lib/src/universe/class_set.dart
@@ -6,8 +6,6 @@
 
 import 'dart:collection' show IterableBase, MapBase;
 
-import 'package:front_end/src/api_unstable/dart2js.dart' show Link;
-
 import '../elements/entities.dart' show ClassEntity;
 import '../elements/indexed.dart' show IndexedClass;
 import '../serialization/serialization.dart';
@@ -206,7 +204,7 @@
   }
 
   /// The nodes for the direct subclasses of [cls].
-  Link<ClassHierarchyNode> _directSubclasses = const Link<ClassHierarchyNode>();
+  List<ClassHierarchyNode> _directSubclasses = <ClassHierarchyNode>[];
 
   ClassHierarchyNode(this.parentNode, this.cls, this.hierarchyDepth) {
     if (parentNode != null) {
@@ -249,7 +247,7 @@
   /// Adds [subclass] as a direct subclass of [cls].
   void addDirectSubclass(ClassHierarchyNode subclass) {
     assert(!_directSubclasses.contains(subclass));
-    _directSubclasses = _directSubclasses.prepend(subclass);
+    _directSubclasses.add(subclass);
   }
 
   Iterable<ClassHierarchyNode> get directSubclasses => _directSubclasses;
@@ -360,12 +358,10 @@
       return null;
     }
     ClassHierarchyNode subclass;
-    for (Link<ClassHierarchyNode> link = _directSubclasses;
-        !link.isEmpty;
-        link = link.tail) {
-      if (link.head.isInstantiated) {
+    for (ClassHierarchyNode node in _directSubclasses) {
+      if (node.isInstantiated) {
         if (subclass == null) {
-          subclass = link.head;
+          subclass = node;
         } else {
           return cls;
         }
@@ -894,7 +890,7 @@
   /// Stack of pending class nodes.
   ///
   /// This is `null` before the first call to [moveNext].
-  Link<ClassHierarchyNode> stack;
+  List<ClassHierarchyNode> stack;
 
   ClassHierarchyNodeIterator(this.iterable);
 
@@ -917,7 +913,7 @@
   bool moveNext() {
     if (stack == null) {
       // First call to moveNext
-      stack = const Link<ClassHierarchyNode>().prepend(root);
+      stack = [root];
       return _findNext();
     } else {
       // Initialized state.
@@ -935,17 +931,16 @@
         currentNode = null;
         return false;
       }
-      currentNode = stack.head;
-      stack = stack.tail;
+      currentNode = stack.removeLast();
       if (!includeUninstantiated && !currentNode.isInstantiated) {
         // We're only iterating instantiated classes so there is no use in
         // visiting the current node and its subtree.
         continue;
       }
-      for (Link<ClassHierarchyNode> link = currentNode._directSubclasses;
-          !link.isEmpty;
-          link = link.tail) {
-        stack = stack.prepend(link.head);
+      // Add direct subclasses in reverse order so will visit them in the list
+      // order.
+      for (int i = currentNode._directSubclasses.length - 1; i >= 0; i--) {
+        stack.add(currentNode._directSubclasses[i]);
       }
       if (_isValid(currentNode)) {
         return true;
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index 5869501..5a42501 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -2,7 +2,30 @@
 // 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 world_builder;
+import 'dart:collection';
+
+import '../common/names.dart' show Identifiers;
+import '../common_elements.dart';
+import '../constants/values.dart';
+import '../elements/entities.dart';
+import '../elements/types.dart';
+import '../js_backend/native_data.dart' show NativeBasicData;
+import '../js_model/locals.dart';
+import '../js_model/element_map_impl.dart';
+import '../util/enumset.dart';
+import '../util/util.dart';
+import '../world.dart' show JClosedWorld;
+import 'member_usage.dart';
+import 'selector.dart' show Selector;
+import 'use.dart'
+    show
+        ConstantUse,
+        ConstantUseKind,
+        DynamicUse,
+        DynamicUseKind,
+        StaticUse,
+        StaticUseKind;
+import 'world_builder.dart';
 
 /// World builder specific to codegen.
 ///
@@ -131,34 +154,34 @@
   final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters =
       <String, Map<Selector, SelectorConstraints>>{};
 
-  final Map<ClassEntity, _ClassUsage> _processedClasses =
-      <ClassEntity, _ClassUsage>{};
+  final Map<ClassEntity, ClassUsage> _processedClasses =
+      <ClassEntity, ClassUsage>{};
 
-  Map<ClassEntity, _ClassUsage> get classUsageForTesting => _processedClasses;
+  Map<ClassEntity, ClassUsage> get classUsageForTesting => _processedClasses;
 
   /// Map of registered usage of static members of live classes.
-  final Map<Entity, _StaticMemberUsage> _staticMemberUsage =
-      <Entity, _StaticMemberUsage>{};
+  final Map<Entity, StaticMemberUsage> _staticMemberUsage =
+      <Entity, StaticMemberUsage>{};
 
-  Map<Entity, _StaticMemberUsage> get staticMemberUsageForTesting =>
+  Map<Entity, StaticMemberUsage> get staticMemberUsageForTesting =>
       _staticMemberUsage;
 
   /// Map of registered usage of instance members of live classes.
-  final Map<MemberEntity, _MemberUsage> _instanceMemberUsage =
-      <MemberEntity, _MemberUsage>{};
+  final Map<MemberEntity, MemberUsage> _instanceMemberUsage =
+      <MemberEntity, MemberUsage>{};
 
-  Map<MemberEntity, _MemberUsage> get instanceMemberUsageForTesting =>
+  Map<MemberEntity, MemberUsage> get instanceMemberUsageForTesting =>
       _instanceMemberUsage;
 
   /// Map containing instance members of live classes that are not yet live
   /// themselves.
-  final Map<String, Set<_MemberUsage>> _instanceMembersByName =
-      <String, Set<_MemberUsage>>{};
+  final Map<String, Set<MemberUsage>> _instanceMembersByName =
+      <String, Set<MemberUsage>>{};
 
   /// Map containing instance methods of live classes that are not yet
   /// closurized.
-  final Map<String, Set<_MemberUsage>> _instanceFunctionsByName =
-      <String, Set<_MemberUsage>>{};
+  final Map<String, Set<MemberUsage>> _instanceFunctionsByName =
+      <String, Set<MemberUsage>>{};
 
   final Set<DartType> isChecks = new Set<DartType>();
 
@@ -263,9 +286,9 @@
     Selector selector = dynamicUse.selector;
     String methodName = selector.name;
 
-    void _process(Map<String, Set<_MemberUsage>> memberMap,
-        EnumSet<MemberUse> action(_MemberUsage usage)) {
-      _processSet(memberMap, methodName, (_MemberUsage usage) {
+    void _process(Map<String, Set<MemberUsage>> memberMap,
+        EnumSet<MemberUse> action(MemberUsage usage)) {
+      _processSet(memberMap, methodName, (MemberUsage usage) {
         if (selectorConstraintsStrategy.appliedUnnamed(
             dynamicUse, usage.entity, _world)) {
           memberUsed(usage.entity, action(usage));
@@ -387,13 +410,13 @@
   void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) {
     Entity element = staticUse.element;
     _registerStaticUse(staticUse);
-    _StaticMemberUsage usage = _staticMemberUsage.putIfAbsent(element, () {
+    StaticMemberUsage usage = _staticMemberUsage.putIfAbsent(element, () {
       if (element is MemberEntity &&
           (element.isStatic || element.isTopLevel) &&
           element.isFunction) {
-        return new _StaticFunctionUsage(element);
+        return new StaticFunctionUsage(element);
       } else {
-        return new _GeneralStaticMemberUsage(element);
+        return new GeneralStaticMemberUsage(element);
       }
     });
     EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
@@ -431,7 +454,7 @@
         break;
       case StaticUseKind.DIRECT_INVOKE:
         MemberEntity member = staticUse.element;
-        _MemberUsage instanceUsage = _getMemberUsage(member, memberUsed);
+        MemberUsage instanceUsage = _getMemberUsage(member, memberUsed);
         memberUsed(instanceUsage.entity, instanceUsage.invoke());
         _instanceMembersByName[instanceUsage.entity.name]
             ?.remove(instanceUsage);
@@ -469,7 +492,7 @@
     _getMemberUsage(member, memberUsed);
   }
 
-  _MemberUsage _getMemberUsage(
+  MemberUsage _getMemberUsage(
       covariant MemberEntity member, MemberUsedCallback memberUsed) {
     // TODO(johnniwinther): Change [TypeMask] to not apply to a superclass
     // member unless the class has been instantiated. Similar to
@@ -478,7 +501,7 @@
       String memberName = member.name;
       ClassEntity cls = member.enclosingClass;
       bool isNative = _nativeBasicData.isNativeClass(cls);
-      _MemberUsage usage = new _MemberUsage(member, isNative: isNative);
+      MemberUsage usage = new MemberUsage(member, isNative: isNative);
       EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
       useSet.addAll(usage.appliedUse);
       if (!usage.hasRead && hasInvokedGetter(member, _world)) {
@@ -495,14 +518,14 @@
         // Store the member in [instanceFunctionsByName] to catch
         // getters on the function.
         _instanceFunctionsByName
-            .putIfAbsent(usage.entity.name, () => new Set<_MemberUsage>())
+            .putIfAbsent(usage.entity.name, () => new Set<MemberUsage>())
             .add(usage);
       }
       if (usage.pendingUse.contains(MemberUse.NORMAL)) {
         // The element is not yet used. Add it to the list of instance
         // members to still be processed.
         _instanceMembersByName
-            .putIfAbsent(memberName, () => new Set<_MemberUsage>())
+            .putIfAbsent(memberName, () => new Set<MemberUsage>())
             .add(usage);
       }
       memberUsed(member, useSet);
@@ -510,24 +533,24 @@
     });
   }
 
-  void _processSet(Map<String, Set<_MemberUsage>> map, String memberName,
-      bool f(_MemberUsage e)) {
-    Set<_MemberUsage> members = map[memberName];
+  void _processSet(Map<String, Set<MemberUsage>> map, String memberName,
+      bool f(MemberUsage e)) {
+    Set<MemberUsage> members = map[memberName];
     if (members == null) return;
     // [f] might add elements to [: map[memberName] :] during the loop below
     // so we create a new list for [: map[memberName] :] and prepend the
     // [remaining] members after the loop.
-    map[memberName] = new Set<_MemberUsage>();
-    Set<_MemberUsage> remaining = new Set<_MemberUsage>();
-    for (_MemberUsage member in members) {
+    map[memberName] = new Set<MemberUsage>();
+    Set<MemberUsage> remaining = new Set<MemberUsage>();
+    for (MemberUsage member in members) {
       if (!f(member)) remaining.add(member);
     }
     map[memberName].addAll(remaining);
   }
 
-  /// Return the canonical [_ClassUsage] for [cls].
-  _ClassUsage _getClassUsage(ClassEntity cls) {
-    return _processedClasses.putIfAbsent(cls, () => new _ClassUsage(cls));
+  /// Return the canonical [ClassUsage] for [cls].
+  ClassUsage _getClassUsage(ClassEntity cls) {
+    return _processedClasses.putIfAbsent(cls, () => new ClassUsage(cls));
   }
 
   void _processInstantiatedClass(ClassEntity cls, ClassUsedCallback classUsed) {
@@ -535,7 +558,7 @@
     // already instantiated and we therefore have to process its superclass as
     // well.
     bool processClass(ClassEntity superclass) {
-      _ClassUsage usage = _getClassUsage(superclass);
+      ClassUsage usage = _getClassUsage(superclass);
       if (!usage.isInstantiated) {
         classUsed(usage.cls, usage.instantiate());
         return true;
@@ -596,7 +619,7 @@
   Iterable<FunctionEntity> get genericInstanceMethods {
     List<FunctionEntity> functions = <FunctionEntity>[];
 
-    void processMemberUse(MemberEntity member, _MemberUsage memberUsage) {
+    void processMemberUse(MemberEntity member, MemberUsage memberUsage) {
       if (member.isInstanceMember &&
           member is FunctionEntity &&
           memberUsage.hasUse &&
@@ -613,7 +636,7 @@
   Iterable<FunctionEntity> get userNoSuchMethods {
     List<FunctionEntity> functions = <FunctionEntity>[];
 
-    void processMemberUse(MemberEntity member, _MemberUsage memberUsage) {
+    void processMemberUse(MemberEntity member, MemberUsage memberUsage) {
       if (member.isInstanceMember &&
           member is FunctionEntity &&
           memberUsage.hasUse &&
diff --git a/pkg/compiler/lib/src/universe/member_usage.dart b/pkg/compiler/lib/src/universe/member_usage.dart
index de15737..6b166f8 100644
--- a/pkg/compiler/lib/src/universe/member_usage.dart
+++ b/pkg/compiler/lib/src/universe/member_usage.dart
@@ -2,7 +2,10 @@
 // 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 world_builder;
+import '../common.dart';
+import '../elements/entities.dart';
+import '../js_model/elements.dart' show JSignatureMethod;
+import '../util/enumset.dart';
 
 abstract class AbstractUsage<T> {
   final EnumSet<T> _pendingUse = new EnumSet<T>();
@@ -31,27 +34,27 @@
 }
 
 /// Registry for the observed use of a member [entity] in the open world.
-abstract class _MemberUsage extends AbstractUsage<MemberUse> {
+abstract class MemberUsage extends AbstractUsage<MemberUse> {
   final MemberEntity entity;
 
-  _MemberUsage.internal(this.entity);
+  MemberUsage.internal(this.entity);
 
-  factory _MemberUsage(MemberEntity member, {bool isNative: false}) {
+  factory MemberUsage(MemberEntity member, {bool isNative: false}) {
     if (member.isField) {
       if (member.isAssignable) {
-        return new _FieldUsage(member, isNative: isNative);
+        return new FieldUsage(member, isNative: isNative);
       } else {
-        return new _FinalFieldUsage(member, isNative: isNative);
+        return new FinalFieldUsage(member, isNative: isNative);
       }
     } else if (member.isGetter) {
-      return new _GetterUsage(member);
+      return new GetterUsage(member);
     } else if (member.isSetter) {
-      return new _SetterUsage(member);
+      return new SetterUsage(member);
     } else if (member.isConstructor) {
-      return new _ConstructorUsage(member);
+      return new ConstructorUsage(member);
     } else {
       assert(member.isFunction, failedAt(member, "Unexpected member: $member"));
-      return new _FunctionUsage(member);
+      return new FunctionUsage(member);
     }
   }
 
@@ -106,18 +109,18 @@
 
   bool operator ==(other) {
     if (identical(this, other)) return true;
-    if (other is! _MemberUsage) return false;
+    if (other is! MemberUsage) return false;
     return entity == other.entity;
   }
 
   String toString() => '$entity:${appliedUse.iterable(MemberUse.values)}';
 }
 
-class _FieldUsage extends _MemberUsage {
+class FieldUsage extends MemberUsage {
   bool hasRead = false;
   bool hasWrite = false;
 
-  _FieldUsage(FieldEntity field, {bool isNative: false})
+  FieldUsage(FieldEntity field, {bool isNative: false})
       : super.internal(field) {
     if (!isNative) {
       // All field initializers must be resolved as they could
@@ -164,10 +167,10 @@
   }
 }
 
-class _FinalFieldUsage extends _MemberUsage {
+class FinalFieldUsage extends MemberUsage {
   bool hasRead = false;
 
-  _FinalFieldUsage(FieldEntity field, {bool isNative: false})
+  FinalFieldUsage(FieldEntity field, {bool isNative: false})
       : super.internal(field) {
     if (!isNative) {
       // All field initializers must be resolved as they could
@@ -199,11 +202,11 @@
   EnumSet<MemberUse> fullyUse() => read();
 }
 
-class _FunctionUsage extends _MemberUsage {
+class FunctionUsage extends MemberUsage {
   bool hasInvoke = false;
   bool hasRead = false;
 
-  _FunctionUsage(FunctionEntity function) : super.internal(function) {
+  FunctionUsage(FunctionEntity function) : super.internal(function) {
     if (function is JSignatureMethod) {
       // We mark signature methods as "always used" to prevent them from being
       // optimized away.
@@ -253,10 +256,10 @@
   bool get fullyUsed => hasInvoke && hasRead;
 }
 
-class _GetterUsage extends _MemberUsage {
+class GetterUsage extends MemberUsage {
   bool hasRead = false;
 
-  _GetterUsage(FunctionEntity getter) : super.internal(getter);
+  GetterUsage(FunctionEntity getter) : super.internal(getter);
 
   @override
   bool get fullyUsed => hasRead;
@@ -277,10 +280,10 @@
   EnumSet<MemberUse> fullyUse() => read();
 }
 
-class _SetterUsage extends _MemberUsage {
+class SetterUsage extends MemberUsage {
   bool hasWrite = false;
 
-  _SetterUsage(FunctionEntity setter) : super.internal(setter);
+  SetterUsage(FunctionEntity setter) : super.internal(setter);
 
   @override
   bool get fullyUsed => hasWrite;
@@ -298,11 +301,10 @@
   EnumSet<MemberUse> fullyUse() => write();
 }
 
-class _ConstructorUsage extends _MemberUsage {
+class ConstructorUsage extends MemberUsage {
   bool hasInvoke = false;
 
-  _ConstructorUsage(ConstructorEntity constructor)
-      : super.internal(constructor);
+  ConstructorUsage(ConstructorEntity constructor) : super.internal(constructor);
 
   EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY;
 
@@ -345,13 +347,13 @@
 
 /// Registry for the observed use of a class [entity] in the open world.
 // TODO(johnniwinther): Merge this with [InstantiationInfo].
-class _ClassUsage extends AbstractUsage<ClassUse> {
+class ClassUsage extends AbstractUsage<ClassUse> {
   bool isInstantiated = false;
   bool isImplemented = false;
 
   final ClassEntity cls;
 
-  _ClassUsage(this.cls);
+  ClassUsage(this.cls);
 
   EnumSet<ClassUse> instantiate() {
     if (isInstantiated) {
@@ -390,15 +392,15 @@
 
 typedef void ClassUsedCallback(ClassEntity cls, EnumSet<ClassUse> useSet);
 
-// TODO(johnniwinther): Merge this with [_MemberUsage].
-abstract class _StaticMemberUsage extends AbstractUsage<MemberUse>
-    implements _MemberUsage {
+// TODO(johnniwinther): Merge this with [MemberUsage].
+abstract class StaticMemberUsage extends AbstractUsage<MemberUse>
+    implements MemberUsage {
   final MemberEntity entity;
 
   bool hasNormalUse = false;
   bool get hasClosurization => false;
 
-  _StaticMemberUsage.internal(this.entity);
+  StaticMemberUsage.internal(this.entity);
 
   EnumSet<MemberUse> normalUse() {
     if (hasNormalUse) {
@@ -426,8 +428,8 @@
   String toString() => '$entity:${appliedUse.iterable(MemberUse.values)}';
 }
 
-class _GeneralStaticMemberUsage extends _StaticMemberUsage {
-  _GeneralStaticMemberUsage(MemberEntity entity) : super.internal(entity);
+class GeneralStaticMemberUsage extends StaticMemberUsage {
+  GeneralStaticMemberUsage(MemberEntity entity) : super.internal(entity);
 
   EnumSet<MemberUse> tearOff() => normalUse();
 
@@ -444,10 +446,10 @@
   bool get hasRead => hasNormalUse;
 }
 
-class _StaticFunctionUsage extends _StaticMemberUsage {
+class StaticFunctionUsage extends StaticMemberUsage {
   bool hasClosurization = false;
 
-  _StaticFunctionUsage(MemberEntity entity) : super.internal(entity);
+  StaticFunctionUsage(MemberEntity entity) : super.internal(entity);
 
   EnumSet<MemberUse> tearOff() {
     if (hasClosurization) {
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index b203dc9..88cee2e 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -2,7 +2,35 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of world_builder;
+import '../common.dart';
+import '../common/names.dart' show Identifiers, Names;
+import '../common_elements.dart';
+import '../constants/values.dart';
+import '../elements/entities.dart';
+import '../elements/types.dart';
+import '../js_backend/annotations.dart';
+import '../js_backend/allocator_analysis.dart' show KAllocatorAnalysis;
+import '../js_backend/backend_usage.dart'
+    show BackendUsage, BackendUsageBuilder;
+import '../js_backend/interceptor_data.dart' show InterceptorDataBuilder;
+import '../js_backend/native_data.dart' show NativeBasicData, NativeDataBuilder;
+import '../js_backend/no_such_method_registry.dart';
+import '../js_backend/runtime_types.dart';
+import '../kernel/element_map_impl.dart';
+import '../kernel/kelements.dart';
+import '../kernel/kernel_world.dart';
+import '../native/enqueue.dart' show NativeResolutionEnqueuer;
+import '../options.dart';
+import '../universe/class_set.dart';
+import '../util/enumset.dart';
+import '../util/util.dart';
+import '../world.dart' show KClosedWorld, OpenWorld;
+import 'class_hierarchy.dart' show ClassHierarchyBuilder, ClassQueries;
+import 'member_usage.dart';
+import 'selector.dart' show Selector;
+import 'use.dart'
+    show ConstantUse, DynamicUse, DynamicUseKind, StaticUse, StaticUseKind;
+import 'world_builder.dart';
 
 abstract class ResolutionWorldBuilder implements WorldBuilder, OpenWorld {
   /// Calls [f] for all local functions in the program together with the member
@@ -296,18 +324,18 @@
   final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters =
       <String, Map<Selector, SelectorConstraints>>{};
 
-  final Map<ClassEntity, _ClassUsage> _processedClasses =
-      <ClassEntity, _ClassUsage>{};
+  final Map<ClassEntity, ClassUsage> _processedClasses =
+      <ClassEntity, ClassUsage>{};
 
-  Map<ClassEntity, _ClassUsage> get classUsageForTesting => _processedClasses;
+  Map<ClassEntity, ClassUsage> get classUsageForTesting => _processedClasses;
 
   /// Map of registered usage of static members of live classes.
-  final Map<MemberEntity, _MemberUsage> _memberUsage =
-      <MemberEntity, _MemberUsage>{};
+  final Map<MemberEntity, MemberUsage> _memberUsage =
+      <MemberEntity, MemberUsage>{};
 
-  Map<MemberEntity, _MemberUsage> get staticMemberUsageForTesting {
-    Map<MemberEntity, _MemberUsage> map = <MemberEntity, _MemberUsage>{};
-    _memberUsage.forEach((MemberEntity member, _MemberUsage usage) {
+  Map<MemberEntity, MemberUsage> get staticMemberUsageForTesting {
+    Map<MemberEntity, MemberUsage> map = <MemberEntity, MemberUsage>{};
+    _memberUsage.forEach((MemberEntity member, MemberUsage usage) {
       if (!member.isInstanceMember) {
         map[member] = usage;
       }
@@ -315,9 +343,9 @@
     return map;
   }
 
-  Map<MemberEntity, _MemberUsage> get instanceMemberUsageForTesting {
-    Map<MemberEntity, _MemberUsage> map = <MemberEntity, _MemberUsage>{};
-    _memberUsage.forEach((MemberEntity member, _MemberUsage usage) {
+  Map<MemberEntity, MemberUsage> get instanceMemberUsageForTesting {
+    Map<MemberEntity, MemberUsage> map = <MemberEntity, MemberUsage>{};
+    _memberUsage.forEach((MemberEntity member, MemberUsage usage) {
       if (member.isInstanceMember) {
         map[member] = usage;
       }
@@ -327,13 +355,13 @@
 
   /// Map containing instance members of live classes that are not yet live
   /// themselves.
-  final Map<String, Set<_MemberUsage>> _instanceMembersByName =
-      <String, Set<_MemberUsage>>{};
+  final Map<String, Set<MemberUsage>> _instanceMembersByName =
+      <String, Set<MemberUsage>>{};
 
   /// Map containing instance methods of live classes that are not yet
   /// closurized.
-  final Map<String, Set<_MemberUsage>> _instanceFunctionsByName =
-      <String, Set<_MemberUsage>>{};
+  final Map<String, Set<MemberUsage>> _instanceFunctionsByName =
+      <String, Set<MemberUsage>>{};
 
   /// Fields set.
   final Set<FieldEntity> fieldSetters = new Set<FieldEntity>();
@@ -589,9 +617,9 @@
     Selector selector = dynamicUse.selector;
     String methodName = selector.name;
 
-    void _process(Map<String, Set<_MemberUsage>> memberMap,
-        EnumSet<MemberUse> action(_MemberUsage usage)) {
-      _processSet(memberMap, methodName, (_MemberUsage usage) {
+    void _process(Map<String, Set<MemberUsage>> memberMap,
+        EnumSet<MemberUse> action(MemberUsage usage)) {
+      _processSet(memberMap, methodName, (MemberUsage usage) {
         if (_selectorConstraintsStrategy.appliedUnnamed(
             dynamicUse, usage.entity, this)) {
           memberUsed(usage.entity, action(usage));
@@ -669,8 +697,8 @@
 
     MemberEntity element = staticUse.element;
     EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
-    _MemberUsage usage = _memberUsage.putIfAbsent(element, () {
-      _MemberUsage usage = new _MemberUsage(element);
+    MemberUsage usage = _memberUsage.putIfAbsent(element, () {
+      MemberUsage usage = new MemberUsage(element);
       useSet.addAll(usage.appliedUse);
       return usage;
     });
@@ -738,14 +766,14 @@
     }
   }
 
-  /// Called to create a [_ClassUsage] for [cls].
+  /// Called to create a [ClassUsage] for [cls].
   ///
   /// Subclasses override this to ensure needed invariants on [cls].
-  _ClassUsage _createClassUsage(covariant ClassEntity cls) =>
-      new _ClassUsage(cls);
+  ClassUsage _createClassUsage(covariant ClassEntity cls) =>
+      new ClassUsage(cls);
 
-  /// Return the canonical [_ClassUsage] for [cls].
-  _ClassUsage _getClassUsage(ClassEntity cls) {
+  /// Return the canonical [ClassUsage] for [cls].
+  ClassUsage _getClassUsage(ClassEntity cls) {
     return _processedClasses.putIfAbsent(cls, () {
       return _createClassUsage(cls);
     });
@@ -757,7 +785,7 @@
     // already instantiated and we therefore have to process its superclass as
     // well.
     bool processClass(ClassEntity superclass) {
-      _ClassUsage usage = _getClassUsage(superclass);
+      ClassUsage usage = _getClassUsage(superclass);
       if (!usage.isInstantiated) {
         classUsed(usage.cls, usage.instantiate());
         return true;
@@ -779,19 +807,19 @@
     });
   }
 
-  /// Call [updateUsage] on all [_MemberUsage]s in the set in [map] for
+  /// Call [updateUsage] on all [MemberUsage]s in the set in [map] for
   /// [memberName]. If [updateUsage] returns `true` the usage is removed from
   /// the set.
-  void _processSet(Map<String, Set<_MemberUsage>> map, String memberName,
-      bool updateUsage(_MemberUsage e)) {
-    Set<_MemberUsage> members = map[memberName];
+  void _processSet(Map<String, Set<MemberUsage>> map, String memberName,
+      bool updateUsage(MemberUsage e)) {
+    Set<MemberUsage> members = map[memberName];
     if (members == null) return;
     // [f] might add elements to [: map[memberName] :] during the loop below
     // so we create a new list for [: map[memberName] :] and prepend the
     // [remaining] members after the loop.
-    map[memberName] = new Set<_MemberUsage>();
-    Set<_MemberUsage> remaining = new Set<_MemberUsage>();
-    for (_MemberUsage usage in members) {
+    map[memberName] = new Set<MemberUsage>();
+    Set<MemberUsage> remaining = new Set<MemberUsage>();
+    for (MemberUsage usage in members) {
       if (!updateUsage(usage)) remaining.add(usage);
     }
     map[memberName].addAll(remaining);
@@ -809,11 +837,11 @@
     // Note: this assumes that there are no non-native fields on native
     // classes, which may not be the case when a native class is subclassed.
     bool newUsage = false;
-    _MemberUsage usage = _memberUsage.putIfAbsent(member, () {
+    MemberUsage usage = _memberUsage.putIfAbsent(member, () {
       newUsage = true;
       bool isNative = _nativeBasicData.isNativeClass(cls);
       EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
-      _MemberUsage usage = new _MemberUsage(member, isNative: isNative);
+      MemberUsage usage = new MemberUsage(member, isNative: isNative);
       useSet.addAll(usage.appliedUse);
       if (member.isField && isNative) {
         registerUsedElement(member);
@@ -838,14 +866,14 @@
         // The element is not yet used. Add it to the list of instance
         // members to still be processed.
         _instanceMembersByName
-            .putIfAbsent(memberName, () => new Set<_MemberUsage>())
+            .putIfAbsent(memberName, () => new Set<MemberUsage>())
             .add(usage);
       }
       if (usage.pendingUse.contains(MemberUse.CLOSURIZE_INSTANCE)) {
         // Store the member in [instanceFunctionsByName] to catch
         // getters on the function.
         _instanceFunctionsByName
-            .putIfAbsent(memberName, () => new Set<_MemberUsage>())
+            .putIfAbsent(memberName, () => new Set<MemberUsage>())
             .add(usage);
       }
       memberUsed(usage.entity, useSet);
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index 84aa6d3..31838fc 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -4,47 +4,13 @@
 
 library world_builder;
 
-import 'dart:collection';
-
-import '../common.dart';
-import '../common/names.dart' show Identifiers, Names;
 import '../common_elements.dart';
-import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
-import '../js_backend/annotations.dart';
-import '../js_backend/allocator_analysis.dart' show KAllocatorAnalysis;
-import '../js_backend/backend_usage.dart'
-    show BackendUsage, BackendUsageBuilder;
-import '../js_backend/interceptor_data.dart' show InterceptorDataBuilder;
-import '../js_backend/native_data.dart' show NativeBasicData, NativeDataBuilder;
-import '../js_backend/no_such_method_registry.dart';
-import '../js_backend/runtime_types.dart';
-import '../js_model/locals.dart';
-import '../js_model/element_map_impl.dart';
-import '../js_model/elements.dart' show JSignatureMethod;
-import '../kernel/element_map_impl.dart';
-import '../kernel/kelements.dart';
-import '../native/enqueue.dart' show NativeResolutionEnqueuer;
-import '../options.dart';
-import '../universe/class_set.dart';
-import '../util/enumset.dart';
-import '../util/util.dart';
-import '../world.dart' show World, JClosedWorld, KClosedWorld, OpenWorld;
-import 'class_hierarchy.dart' show ClassHierarchyBuilder, ClassQueries;
+import '../js_backend/native_data.dart' show NativeBasicData;
+import '../world.dart' show World, JClosedWorld, OpenWorld;
 import 'selector.dart' show Selector;
-import 'use.dart'
-    show
-        ConstantUse,
-        ConstantUseKind,
-        DynamicUse,
-        DynamicUseKind,
-        StaticUse,
-        StaticUseKind;
-
-part 'codegen_world_builder.dart';
-part 'member_usage.dart';
-part 'resolution_world_builder.dart';
+import 'use.dart' show DynamicUse, StaticUse;
 
 /// The combined constraints on receivers all the dynamic call sites of the same
 /// selector.
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index cb83743..01ba8f9 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -4,11 +4,8 @@
 
 library dart2js.world;
 
-import 'package:front_end/src/api_unstable/dart2js.dart' show Link;
-
 import 'closure.dart';
 import 'common.dart';
-import 'common/names.dart';
 import 'common_elements.dart'
     show
         JCommonElements,
@@ -27,18 +24,12 @@
 import 'js_backend/interceptor_data.dart' show InterceptorData;
 import 'js_backend/native_data.dart' show NativeData;
 import 'js_backend/no_such_method_registry.dart' show NoSuchMethodData;
-import 'js_backend/runtime_types.dart'
-    show RuntimeTypesNeed, RuntimeTypesNeedBuilder;
+import 'js_backend/runtime_types.dart' show RuntimeTypesNeed;
 import 'js_model/locals.dart';
-import 'ordered_typeset.dart';
-import 'options.dart';
 import 'js_emitter/sorter.dart';
 import 'types/abstract_value_domain.dart';
 import 'universe/class_hierarchy.dart';
-import 'universe/class_set.dart';
-import 'universe/function_set.dart' show FunctionSet;
 import 'universe/selector.dart' show Selector;
-import 'universe/world_builder.dart';
 
 /// Common superinterface for [OpenWorld] and [JClosedWorld].
 abstract class World {}
@@ -240,356 +231,6 @@
   bool isInheritedInSubtypeOf(MemberEntity member, ClassEntity type);
 }
 
-abstract class ClosedWorldBase implements JClosedWorld {
-  final ConstantSystem constantSystem;
-  final NativeData nativeData;
-  final InterceptorData interceptorData;
-  final BackendUsage backendUsage;
-  final NoSuchMethodData noSuchMethodData;
-
-  FunctionSet _allFunctions;
-
-  final Map<ClassEntity, Set<ClassEntity>> mixinUses;
-  Map<ClassEntity, List<ClassEntity>> _liveMixinUses;
-
-  final Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses;
-
-  final Map<ClassEntity, Map<ClassEntity, bool>> _subtypeCoveredByCache =
-      <ClassEntity, Map<ClassEntity, bool>>{};
-
-  final JElementEnvironment elementEnvironment;
-  final DartTypes dartTypes;
-  final JCommonElements commonElements;
-
-  // TODO(johnniwinther): Can this be derived from [ClassSet]s?
-  final Set<ClassEntity> implementedClasses;
-
-  final Iterable<MemberEntity> liveInstanceMembers;
-
-  /// Members that are written either directly or through a setter selector.
-  final Iterable<MemberEntity> assignedInstanceMembers;
-
-  final Iterable<ClassEntity> liveNativeClasses;
-
-  final Iterable<MemberEntity> processedMembers;
-
-  final ClassHierarchy classHierarchy;
-
-  ClosedWorldBase(
-      this.elementEnvironment,
-      this.dartTypes,
-      this.commonElements,
-      this.constantSystem,
-      this.nativeData,
-      this.interceptorData,
-      this.backendUsage,
-      this.noSuchMethodData,
-      this.implementedClasses,
-      this.liveNativeClasses,
-      this.liveInstanceMembers,
-      this.assignedInstanceMembers,
-      this.processedMembers,
-      this.mixinUses,
-      this.typesImplementedBySubclasses,
-      this.classHierarchy);
-
-  OrderedTypeSet getOrderedTypeSet(covariant ClassEntity cls);
-
-  int getHierarchyDepth(covariant ClassEntity cls);
-
-  ClassEntity getSuperClass(covariant ClassEntity cls);
-
-  Iterable<ClassEntity> getInterfaces(covariant ClassEntity cls);
-
-  ClassEntity getAppliedMixin(covariant ClassEntity cls);
-
-  bool isNamedMixinApplication(covariant ClassEntity cls);
-
-  /// Returns `true` if [cls] is implemented by an instantiated class.
-  bool isImplemented(ClassEntity cls) {
-    return implementedClasses.contains(cls);
-  }
-
-  @override
-  ClassEntity getLubOfInstantiatedSubclasses(ClassEntity cls) {
-    if (nativeData.isJsInteropClass(cls)) {
-      return commonElements.jsJavaScriptObjectClass;
-    }
-    ClassHierarchyNode hierarchy = classHierarchy.getClassHierarchyNode(cls);
-    return hierarchy != null
-        ? hierarchy.getLubOfInstantiatedSubclasses()
-        : null;
-  }
-
-  @override
-  ClassEntity getLubOfInstantiatedSubtypes(ClassEntity cls) {
-    if (nativeData.isJsInteropClass(cls)) {
-      return commonElements.jsJavaScriptObjectClass;
-    }
-    ClassSet classSet = classHierarchy.getClassSet(cls);
-    return classSet != null ? classSet.getLubOfInstantiatedSubtypes() : null;
-  }
-
-  /// Returns `true` if [cls] is mixed into a live class.
-  bool isUsedAsMixin(ClassEntity cls) {
-    return !mixinUsesOf(cls).isEmpty;
-  }
-
-  /// Returns `true` if any live class that mixes in [cls] implements [type].
-  bool hasAnySubclassOfMixinUseThatImplements(
-      ClassEntity cls, ClassEntity type) {
-    return mixinUsesOf(cls)
-        .any((use) => hasAnySubclassThatImplements(use, type));
-  }
-
-  /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass
-  /// of a mixin application of [y].
-  bool everySubtypeIsSubclassOfOrMixinUseOf(ClassEntity x, ClassEntity y) {
-    Map<ClassEntity, bool> secondMap =
-        _subtypeCoveredByCache[x] ??= <ClassEntity, bool>{};
-    return secondMap[y] ??= classHierarchy.subtypesOf(x).every(
-        (ClassEntity cls) =>
-            classHierarchy.isSubclassOf(cls, y) ||
-            isSubclassOfMixinUseOf(cls, y));
-  }
-
-  /// Returns `true` if any subclass of [superclass] implements [type].
-  bool hasAnySubclassThatImplements(ClassEntity superclass, ClassEntity type) {
-    Set<ClassEntity> subclasses = typesImplementedBySubclasses[superclass];
-    if (subclasses == null) return false;
-    return subclasses.contains(type);
-  }
-
-  /// Returns whether a [selector] call on an instance of [cls]
-  /// will hit a method at runtime, and not go through [noSuchMethod].
-  bool hasConcreteMatch(covariant ClassEntity cls, Selector selector,
-      {covariant ClassEntity stopAtSuperclass});
-
-  @override
-  bool needsNoSuchMethod(
-      ClassEntity base, Selector selector, ClassQuery query) {
-    /// Returns `true` if subclasses in the [rootNode] tree needs noSuchMethod
-    /// handling.
-    bool subclassesNeedNoSuchMethod(ClassHierarchyNode rootNode) {
-      if (!rootNode.isInstantiated) {
-        // No subclass needs noSuchMethod handling since they are all
-        // uninstantiated.
-        return false;
-      }
-      ClassEntity rootClass = rootNode.cls;
-      if (hasConcreteMatch(rootClass, selector)) {
-        // The root subclass has a concrete implementation so no subclass needs
-        // noSuchMethod handling.
-        return false;
-      } else if (rootNode.isExplicitlyInstantiated) {
-        // The root class need noSuchMethod handling.
-        return true;
-      }
-      IterationStep result = rootNode.forEachSubclass((ClassEntity subclass) {
-        if (hasConcreteMatch(subclass, selector, stopAtSuperclass: rootClass)) {
-          // Found a match - skip all subclasses.
-          return IterationStep.SKIP_SUBCLASSES;
-        } else {
-          // Stop fast - we found a need for noSuchMethod handling.
-          return IterationStep.STOP;
-        }
-      }, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, strict: true);
-      // We stopped fast so we need noSuchMethod handling.
-      return result == IterationStep.STOP;
-    }
-
-    ClassSet classSet = classHierarchy.getClassSet(base);
-    assert(classSet != null, failedAt(base, "No class set for $base."));
-    ClassHierarchyNode node = classSet.node;
-    if (query == ClassQuery.EXACT) {
-      return node.isExplicitlyInstantiated && !hasConcreteMatch(base, selector);
-    } else if (query == ClassQuery.SUBCLASS) {
-      return subclassesNeedNoSuchMethod(node);
-    } else {
-      if (subclassesNeedNoSuchMethod(node)) return true;
-      for (ClassHierarchyNode subtypeNode in classSet.subtypeNodes) {
-        if (subclassesNeedNoSuchMethod(subtypeNode)) return true;
-      }
-      return false;
-    }
-  }
-
-  /// Returns an iterable over the common supertypes of the [classes].
-  Iterable<ClassEntity> commonSupertypesOf(Iterable<ClassEntity> classes) {
-    Iterator<ClassEntity> iterator = classes.iterator;
-    if (!iterator.moveNext()) return const <ClassEntity>[];
-
-    ClassEntity cls = iterator.current;
-    OrderedTypeSet typeSet = getOrderedTypeSet(cls);
-    if (!iterator.moveNext()) return typeSet.types.map((type) => type.element);
-
-    int depth = typeSet.maxDepth;
-    Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>();
-    do {
-      ClassEntity otherClass = iterator.current;
-      OrderedTypeSet otherTypeSet = getOrderedTypeSet(otherClass);
-      otherTypeSets = otherTypeSets.prepend(otherTypeSet);
-      if (otherTypeSet.maxDepth < depth) {
-        depth = otherTypeSet.maxDepth;
-      }
-    } while (iterator.moveNext());
-
-    List<ClassEntity> commonSupertypes = <ClassEntity>[];
-    OUTER:
-    for (Link<InterfaceType> link = typeSet[depth];
-        link.head.element != commonElements.objectClass;
-        link = link.tail) {
-      ClassEntity cls = link.head.element;
-      for (Link<OrderedTypeSet> link = otherTypeSets;
-          !link.isEmpty;
-          link = link.tail) {
-        if (link.head.asInstanceOf(cls, getHierarchyDepth(cls)) == null) {
-          continue OUTER;
-        }
-      }
-      commonSupertypes.add(cls);
-    }
-    commonSupertypes.add(commonElements.objectClass);
-    return commonSupertypes;
-  }
-
-  /// Returns an iterable over the live mixin applications that mixin [cls].
-  Iterable<ClassEntity> mixinUsesOf(ClassEntity cls) {
-    if (_liveMixinUses == null) {
-      _liveMixinUses = new Map<ClassEntity, List<ClassEntity>>();
-      for (ClassEntity mixin in mixinUses.keys) {
-        List<ClassEntity> uses = <ClassEntity>[];
-
-        void addLiveUse(ClassEntity mixinApplication) {
-          if (classHierarchy.isInstantiated(mixinApplication)) {
-            uses.add(mixinApplication);
-          } else if (isNamedMixinApplication(mixinApplication)) {
-            Set<ClassEntity> next = mixinUses[mixinApplication];
-            if (next != null) {
-              next.forEach(addLiveUse);
-            }
-          }
-        }
-
-        mixinUses[mixin].forEach(addLiveUse);
-        if (uses.isNotEmpty) {
-          _liveMixinUses[mixin] = uses;
-        }
-      }
-    }
-    Iterable<ClassEntity> uses = _liveMixinUses[cls];
-    return uses != null ? uses : const <ClassEntity>[];
-  }
-
-  /// Returns `true` if any live class that mixes in [mixin] is also a subclass
-  /// of [superclass].
-  bool hasAnySubclassThatMixes(ClassEntity superclass, ClassEntity mixin) {
-    return mixinUsesOf(mixin).any((ClassEntity each) {
-      return classHierarchy.isSubclassOf(each, superclass);
-    });
-  }
-
-  /// Returns `true` if [cls] or any superclass mixes in [mixin].
-  bool isSubclassOfMixinUseOf(ClassEntity cls, ClassEntity mixin) {
-    if (isUsedAsMixin(mixin)) {
-      ClassEntity current = cls;
-      while (current != null) {
-        ClassEntity currentMixin = getAppliedMixin(current);
-        if (currentMixin == mixin) return true;
-        current = getSuperClass(current);
-      }
-    }
-    return false;
-  }
-
-  void _ensureFunctionSet() {
-    if (_allFunctions == null) {
-      // [FunctionSet] is created lazily because it is not used when we switch
-      // from a frontend to a backend model before inference.
-      _allFunctions = new FunctionSet(liveInstanceMembers);
-    }
-  }
-
-  /// Returns `true` if [selector] on [receiver] can hit a `call` method on a
-  /// subclass of `Closure`.
-  ///
-  /// Every implementation of `Closure` has a 'call' method with its own
-  /// signature so it cannot be modelled by a [FunctionEntity]. Also,
-  /// call-methods for tear-off are not part of the element model.
-  bool includesClosureCall(Selector selector, AbstractValue receiver) {
-    return selector.name == Identifiers.call &&
-        (receiver == null ||
-            // TODO(johnniwinther): Should this have been `intersects` instead?
-            abstractValueDomain.contains(
-                receiver, abstractValueDomain.functionType));
-  }
-
-  AbstractValue computeReceiverType(Selector selector, AbstractValue receiver) {
-    _ensureFunctionSet();
-    if (includesClosureCall(selector, receiver)) {
-      return abstractValueDomain.dynamicType;
-    }
-    return _allFunctions.receiverType(selector, receiver, abstractValueDomain);
-  }
-
-  Iterable<MemberEntity> locateMembers(
-      Selector selector, AbstractValue receiver) {
-    _ensureFunctionSet();
-    return _allFunctions.filter(selector, receiver, abstractValueDomain);
-  }
-
-  bool hasAnyUserDefinedGetter(Selector selector, AbstractValue receiver) {
-    _ensureFunctionSet();
-    return _allFunctions
-        .filter(selector, receiver, abstractValueDomain)
-        .any((each) => each.isGetter);
-  }
-
-  FieldEntity locateSingleField(Selector selector, AbstractValue receiver) {
-    MemberEntity result = locateSingleMember(selector, receiver);
-    return (result != null && result.isField) ? result : null;
-  }
-
-  MemberEntity locateSingleMember(Selector selector, AbstractValue receiver) {
-    if (includesClosureCall(selector, receiver)) {
-      return null;
-    }
-    receiver ??= abstractValueDomain.dynamicType;
-    return abstractValueDomain.locateSingleMember(receiver, selector);
-  }
-
-  bool fieldNeverChanges(MemberEntity element) {
-    if (!element.isField) return false;
-    if (nativeData.isNativeMember(element)) {
-      // Some native fields are views of data that may be changed by operations.
-      // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2).
-      // TODO(sra): Refine the effect classification so that native effects are
-      // distinct from ordinary Dart effects.
-      return false;
-    }
-
-    if (!element.isAssignable) {
-      return true;
-    }
-    if (element.isInstanceMember) {
-      return !assignedInstanceMembers.contains(element);
-    }
-    return false;
-  }
-}
-
-abstract class ClosedWorldRtiNeedMixin implements KClosedWorld {
-  RuntimeTypesNeed _rtiNeed;
-
-  void computeRtiNeed(ResolutionWorldBuilder resolutionWorldBuilder,
-      RuntimeTypesNeedBuilder rtiNeedBuilder, CompilerOptions options) {
-    _rtiNeed = rtiNeedBuilder.computeRuntimeTypesNeed(
-        resolutionWorldBuilder, this, options);
-  }
-
-  RuntimeTypesNeed get rtiNeed => _rtiNeed;
-}
-
 abstract class KClosedWorld {
   DartTypes get dartTypes;
   KAllocatorAnalysis get allocatorAnalysis;
diff --git a/pkg/compiler/tool/dart2js_stress.dart b/pkg/compiler/tool/dart2js_stress.dart
index 8327964..3a458e9 100644
--- a/pkg/compiler/tool/dart2js_stress.dart
+++ b/pkg/compiler/tool/dart2js_stress.dart
@@ -24,8 +24,8 @@
   args = [
     "--suppress-warnings",
     "--suppress-hints",
-    "--library-root="
-        "${Platform.script.resolve('../../../sdk').toFilePath()}"
+    "--libraries-spec="
+        "${Platform.script.resolve('../../../sdk/lib/libraries.json').toFilePath()}"
   ]..addAll(args);
   void iterate() {
     count++;
diff --git a/pkg/dart2js_tools/bin/deobfuscate.dart b/pkg/dart2js_tools/bin/deobfuscate.dart
index 69319ea..df2729f 100644
--- a/pkg/dart2js_tools/bin/deobfuscate.dart
+++ b/pkg/dart2js_tools/bin/deobfuscate.dart
@@ -3,13 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io';
-import 'package:source_maps/source_maps.dart';
-import 'package:source_maps/src/utils.dart';
+import 'dart:math' show max;
+import 'package:stack_trace/stack_trace.dart';
 import 'package:dart2js_tools/src/trace.dart';
-import 'package:dart2js_tools/src/sourcemap_helper.dart';
 import 'package:dart2js_tools/src/name_decoder.dart';
-import 'package:dart2js_tools/src/dart2js_mapping.dart';
 import 'package:dart2js_tools/src/util.dart';
+import 'package:dart2js_tools/src/trace_decoder.dart';
 
 /// Script that deobuscates a stack-trace given in a text file.
 ///
@@ -47,91 +46,36 @@
   }
   var sb = new StringBuffer();
   try {
-    deobfuscate(new File(args[0]).readAsStringSync(), sb);
+    String obfuscatedTrace = new File(args[0]).readAsStringSync();
+    String error = extractErrorMessage(obfuscatedTrace);
+    var provider = new CachingFileProvider();
+    StackDeobfuscationResult result =
+        deobfuscateStack(obfuscatedTrace, provider);
+    Frame firstFrame = result.original.frames.first;
+    String translatedError =
+        translate(error, provider.mappingFor(firstFrame.uri));
+    if (translatedError == null) translatedError = '<no error message found>';
+    printPadded(translatedError, error, sb);
+    int longest =
+        result.deobfuscated.frames.fold(0, (m, f) => max(f.member.length, m));
+    for (var originalFrame in result.original.frames) {
+      var deobfuscatedFrames = result.frameMap[originalFrame];
+      if (deobfuscatedFrames == null) {
+        printPadded('no mapping', '${originalFrame.location}', sb);
+      } else {
+        for (var frame in deobfuscatedFrames) {
+          printPadded('${frame.member.padRight(longest)} ${frame.location}',
+              '${originalFrame.location}', sb);
+        }
+      }
+    }
   } finally {
     print('$sb');
   }
 }
 
-void deobfuscate(trace, StringBuffer sb) {
-  String error = extractErrorMessage(trace);
-  String translatedError;
-  var provider = new CachingFileProvider();
-
-  List<StackTraceLine> jsStackTrace = parseStackTrace(trace);
-
-  for (StackTraceLine line in jsStackTrace) {
-    var uri = resolveUri(line.fileName);
-    var mapping = provider.mappingFor(uri);
-    if (mapping == null) {
-      printPadded('no mapping', line.inlineString, sb);
-      continue;
-    }
-
-    TargetEntry targetEntry = findColumn(line.lineNo - 1, line.columnNo - 1,
-        findLine(mapping.sourceMap, line.lineNo - 1));
-    if (targetEntry == null) {
-      printPadded('no entry', line.inlineString, sb);
-      continue;
-    }
-
-    if (translatedError == null) {
-      translatedError = translate(error, mapping, line, targetEntry);
-      if (translatedError == null) translatedError = '<no error message found>';
-      printPadded(translatedError, error, sb);
-    }
-
-    int offset =
-        provider.fileFor(uri).getOffset(line.lineNo - 1, line.columnNo - 1);
-
-    String nameOf(id) => id != 0 ? mapping.sourceMap.names[id] : null;
-    String urlOf(id) => id != 0 ? mapping.sourceMap.urls[id] : null;
-
-    String fileName = urlOf(targetEntry.sourceUrlId ?? 0);
-    int targetLine = (targetEntry.sourceLine ?? 0) + 1;
-    int targetColumn = (targetEntry.sourceColumn ?? 0) + 1;
-
-    // Expand inlined frames.
-    Map<int, List<FrameEntry>> frames = mapping.frames;
-    List<int> index = mapping.frameIndex;
-    int key = binarySearch(index, (i) => i > offset) - 1;
-    int depth = 0;
-    outer:
-    while (key >= 0) {
-      for (var frame in frames[index[key]].reversed) {
-        if (frame.isEmpty) break outer;
-        if (frame.isPush) {
-          if (depth <= 0) {
-            var mappedLine = new StackTraceLine(
-                frame.inlinedMethodName + "(inlined)",
-                fileName,
-                targetLine,
-                targetColumn);
-            printPadded(mappedLine.inlineString, "", sb);
-            fileName = frame.callUri;
-            targetLine = (frame.callLine ?? 0) + 1;
-            targetColumn = (frame.callColumn ?? 0) + 1;
-          } else {
-            depth--;
-          }
-        }
-        if (frame.isPop) {
-          depth++;
-        }
-      }
-      key--;
-    }
-
-    var functionEntry = findEnclosingFunction(provider, uri, offset);
-    String methodName = nameOf(functionEntry.sourceNameId ?? 0);
-    var mappedLine =
-        new StackTraceLine(methodName, fileName, targetLine, targetColumn);
-    printPadded(mappedLine.inlineString, line.inlineString, sb);
-  }
-}
-
-final green = stdout.hasTerminal ? '' : '';
-final none = stdout.hasTerminal ? '' : '';
+final green = stdout.hasTerminal ? '\x1b[32m' : '';
+final none = stdout.hasTerminal ? '\x1b[0m' : '';
 
 printPadded(String mapping, String original, sb) {
   var len = mapping.length;
@@ -140,12 +84,3 @@
   var pad = ' ' * (50 - len);
   sb.writeln('$green$mapping$none$pad ... $original');
 }
-
-Uri resolveUri(String filename) {
-  var uri = Uri.base.resolve(filename);
-  if (uri.scheme == 'http' || uri.scheme == 'https') {
-    filename = uri.path.substring(uri.path.lastIndexOf('/') + 1);
-    uri = Uri.base.resolve(filename);
-  }
-  return uri;
-}
diff --git a/pkg/dart2js_tools/lib/src/name_decoder.dart b/pkg/dart2js_tools/lib/src/name_decoder.dart
index 746c511..306bead 100644
--- a/pkg/dart2js_tools/lib/src/name_decoder.dart
+++ b/pkg/dart2js_tools/lib/src/name_decoder.dart
@@ -9,8 +9,8 @@
 import 'dart2js_mapping.dart';
 import 'trace.dart';
 
-String translate(String error, Dart2jsMapping mapping, StackTraceLine line,
-    TargetEntry entry) {
+String translate(String error, Dart2jsMapping mapping,
+    [StackTraceLine line, TargetEntry entry]) {
   for (var decoder in _errorMapDecoders) {
     var result = decoder.decode(error, mapping, line, entry);
     // More than one decoder might be applied on a single error message. This
@@ -33,12 +33,20 @@
   String decode(String error, Dart2jsMapping mapping, StackTraceLine line,
       TargetEntry entry) {
     if (error == null) return null;
-    var match = _matcher.firstMatch(error);
-    if (match == null) return null;
-    var result = _decodeInternal(match, mapping, line, entry);
-    if (result == null) return null;
-    return '${error.substring(0, match.start)}'
-        '$result${error.substring(match.end, error.length)}';
+    Match lastMatch = null;
+    var result = new StringBuffer();
+    for (var match in _matcher.allMatches(error)) {
+      var decodedMatch = _decodeInternal(match, mapping, line, entry);
+      if (decodedMatch == null) {
+        continue;
+      }
+      result.write(error.substring(lastMatch?.end ?? 0, match.start));
+      result.write(decodedMatch);
+      lastMatch = match;
+    }
+    if (lastMatch == null) return null;
+    result.write(error.substring(lastMatch.end, error.length));
+    return '$result';
   }
 
   String _decodeInternal(Match match, Dart2jsMapping mapping,
@@ -49,14 +57,12 @@
     StackTraceLine line, TargetEntry entry);
 
 class MinifiedNameDecoder extends ErrorMapDecoder {
-  final RegExp _matcher = new RegExp("minified:([a-zA-Z]*)");
+  final RegExp _matcher = new RegExp("minified:([a-zA-Z0-9_\$]*)");
 
   String _decodeInternal(Match match, Dart2jsMapping mapping,
       StackTraceLine line, TargetEntry entry) {
     var minifiedName = match.group(1);
-    var name = mapping.globalNames[minifiedName];
-    if (name == null) return null;
-    return name;
+    return mapping.globalNames[minifiedName];
   }
 }
 
@@ -72,7 +78,103 @@
   }
 }
 
+abstract class NoSuchMethodDecoderBase extends ErrorMapDecoder {
+  String _translateMinifiedName(Dart2jsMapping mapping, String minifiedName) {
+    var name = mapping.instanceNames[minifiedName];
+    if (name != null) return "'$name'";
+    if (minifiedName.startsWith(new RegExp(r'(call)?\$[0-9]'))) {
+      int first$ = minifiedName.indexOf(r'$');
+      return _expandCallSignature(minifiedName.substring(first$));
+    }
+    return null;
+  }
+
+  String _expandCallSignature(String callSignature) {
+    // Minified names are one of these forms:
+    //   $0         // positional arguments only
+    //   $1$2       // type parameters and positional arguments
+    //   $3$name    // positional and named arguments
+    //   $1$3$name  // type parameters and positional and named args
+    var signature = callSignature.split(r'$');
+    var typeArgs = null;
+    var totalArgs = null;
+    var namedArgs = <String>[];
+    for (var arg in signature) {
+      if (arg == "") continue;
+      var count = int.tryParse(arg);
+      if (count != null) {
+        if (totalArgs != null) {
+          if (typeArgs != null) {
+            // unexpected format, leave it unchanged.
+            return null;
+          }
+          typeArgs = totalArgs;
+        }
+        totalArgs = count;
+      } else {
+        namedArgs.add(arg);
+      }
+    }
+    var sb = new StringBuffer();
+    sb.write("'call'");
+    sb.write(" (with ");
+    if (typeArgs != null) {
+      sb.write("$typeArgs type arguments");
+      sb.write(namedArgs.isNotEmpty ? ", " : " and ");
+    }
+    sb.write("${totalArgs - namedArgs.length} positional arguments");
+    if (namedArgs.isNotEmpty) {
+      sb.write(typeArgs != null ? "," : "");
+      sb.write(" and named arguments '${namedArgs.join("', '")}'");
+    }
+    sb.write(')');
+    return "$sb";
+  }
+}
+
+class NoSuchMethodDecoder1 extends NoSuchMethodDecoderBase {
+  final RegExp _matcher = new RegExp(
+      "NoSuchMethodError: method not found: '([^']*)'( on [^\\(]*)? \\(.*\\)");
+
+  String _decodeInternal(Match match, Dart2jsMapping mapping,
+      StackTraceLine line, TargetEntry entry) {
+    var minifiedName = match.group(1);
+    var suffix = match.group(2) ?? '';
+    var name = _translateMinifiedName(mapping, minifiedName);
+    if (name == null) return null;
+    return "NoSuchMethodError: method not found: $name$suffix";
+  }
+}
+
+class NoSuchMethodDecoder2 extends NoSuchMethodDecoderBase {
+  final RegExp _matcher =
+      new RegExp("NoSuchMethodError: method not found: '([^']*)'");
+
+  String _decodeInternal(Match match, Dart2jsMapping mapping,
+      StackTraceLine line, TargetEntry entry) {
+    var minifiedName = match.group(1);
+    var name = _translateMinifiedName(mapping, minifiedName);
+    if (name == null) return null;
+    return "NoSuchMethodError: method not found: $name";
+  }
+}
+
+class UnhandledNotAFunctionError extends ErrorMapDecoder {
+  final RegExp _matcher = new RegExp("Error: ([^']*) is not a function");
+
+  String _decodeInternal(Match match, Dart2jsMapping mapping,
+      StackTraceLine line, TargetEntry entry) {
+    var minifiedName = match.group(1);
+    var name = mapping.instanceNames[minifiedName];
+    if (name == null) return null;
+    return "Error: $name is not a function";
+  }
+}
+
 List<ErrorMapDecoder> _errorMapDecoders = [
   new MinifiedNameDecoder(),
-  new CannotReadPropertyDecoder()
+  new CannotReadPropertyDecoder(),
+  new NoSuchMethodDecoder1(),
+  new NoSuchMethodDecoder2(),
+  new UnhandledNotAFunctionError(),
 ];
diff --git a/pkg/dart2js_tools/lib/src/sourcemap_helper.dart b/pkg/dart2js_tools/lib/src/sourcemap_helper.dart
index 7e01953..5b146b8 100644
--- a/pkg/dart2js_tools/lib/src/sourcemap_helper.dart
+++ b/pkg/dart2js_tools/lib/src/sourcemap_helper.dart
@@ -13,15 +13,24 @@
 TargetEntry findEnclosingFunction(FileProvider provider, Uri uri, int start) {
   String sources = provider.sourcesFor(uri);
   if (sources == null) return null;
-  int index = sources.lastIndexOf(': function(', start);
-  if (index < 0) index = sources.lastIndexOf(':function(', start);
-  if (index < 0) return null;
-  index += 2;
   SourceFile file = provider.fileFor(uri);
   SingleMapping mapping = provider.mappingFor(uri).sourceMap;
-  var line = file.getLine(index);
-  var lineEntry = findLine(mapping, line);
-  return findColumn(line, file.getColumn(index), lineEntry);
+  int index = start;
+  while (true) {
+    index = sources.lastIndexOf('function', index);
+    if (index < 0) return null;
+    var line = file.getLine(index);
+    var lineEntry = findLine(mapping, line);
+    var column = file.getColumn(index);
+    TargetEntry result = findColumn(line, column, lineEntry);
+    // If the name entry doesn't start exactly at the column corresponding to
+    // `index`, we must be in the middle of a string or code that uses the word
+    // "function", but that doesn't have a corresponding mapping. In those
+    // cases, we keep searching backwards until we find the actual definition of
+    // a function.
+    if (result?.column == column) return result;
+    index--;
+  }
 }
 
 /// Returns [TargetLineEntry] which includes the location in the target [line]
diff --git a/pkg/dart2js_tools/lib/src/trace_decoder.dart b/pkg/dart2js_tools/lib/src/trace_decoder.dart
new file mode 100644
index 0000000..cae4c22
--- /dev/null
+++ b/pkg/dart2js_tools/lib/src/trace_decoder.dart
@@ -0,0 +1,114 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Logic to expand and deobuscate stack traces.
+
+import 'package:stack_trace/stack_trace.dart';
+import 'package:source_span/source_span.dart';
+import 'package:source_maps/src/utils.dart';
+import 'sourcemap_helper.dart';
+import 'dart2js_mapping.dart';
+import 'util.dart';
+
+/// Provides the result of deobfuscating a stack trace.
+class StackDeobfuscationResult {
+  /// Representation of the obfuscated stack trace.
+  final Trace original;
+
+  /// Representation of the deobfsucated stack trace.
+  final Trace deobfuscated;
+
+  /// Details about how one original frame maps to deobfuscated frames. A single
+  /// frame might map to many frames (in the case of inlining), or to a null
+  /// value (when we were unabled to deobfuscate it).
+  final Map<Frame, List<Frame>> frameMap;
+
+  StackDeobfuscationResult(this.original, this.deobfuscated, this.frameMap);
+}
+
+/// Parse [stackTrace] and deobfuscate it using source-map data available from
+/// [provider].
+StackDeobfuscationResult deobfuscateStack(
+    String stackTrace, FileProvider provider) {
+  var trace = Trace.parse(stackTrace.trim());
+  var deobfuscatedFrames = <Frame>[];
+  var frameMap = <Frame, List<Frame>>{};
+  for (var frame in trace.frames) {
+    // If there's no line information, there's no way to translate this frame.
+    // We could return it as-is, but these lines are usually not useful anyways.
+    if (frame.line == null) {
+      continue;
+    }
+
+    // If there's no column, try using the first column of the line.
+    var column = frame.column ?? 0;
+
+    Dart2jsMapping mapping = provider.mappingFor(frame.uri);
+    if (mapping == null) continue;
+
+    // Subtract 1 because stack traces use 1-indexed lines and columns and
+    // source maps uses 0-indexed.
+    SourceSpan span = mapping.sourceMap
+        .spanFor(frame.line - 1, column - 1, uri: frame.uri?.toString());
+
+    // If we can't find a source span, ignore the frame. It's probably something
+    // internal that the user doesn't care about.
+    if (span == null) continue;
+
+    List<Frame> mappedFrames = frameMap[frame] = [];
+
+    SourceFile jsFile = provider.fileFor(frame.uri);
+    int offset = jsFile.getOffset(frame.line - 1, column - 1);
+    String nameOf(id) =>
+        _normalizeName(id >= 0 ? mapping.sourceMap.names[id] : null);
+
+    Uri fileName = span.sourceUrl;
+    int targetLine = span.start.line + 1;
+    int targetColumn = span.start.column + 1;
+
+    // Expand inlining data.  When present, the fileName, line and column above
+    // correspond to the deepest inlined function, as we expand each frame we
+    // consume the location information, and retrieve the location information
+    // of the caller frame until we reach the actual function that dart2js
+    // inlined all the code into.
+    Map<int, List<FrameEntry>> frames = mapping.frames;
+    List<int> index = mapping.frameIndex;
+    int key = binarySearch(index, (i) => i > offset) - 1;
+    int depth = 0;
+    outer:
+    while (key >= 0) {
+      for (var frame in frames[index[key]].reversed) {
+        if (frame.isEmpty) break outer;
+        if (frame.isPush) {
+          if (depth <= 0) {
+            mappedFrames.add(new Frame(fileName, targetLine, targetColumn,
+                _normalizeName(frame.inlinedMethodName) + "(inlined)"));
+            fileName = Uri.parse(frame.callUri);
+            targetLine = (frame.callLine ?? 0) + 1;
+            targetColumn = (frame.callColumn ?? 0) + 1;
+          } else {
+            depth--;
+          }
+        }
+        if (frame.isPop) {
+          depth++;
+        }
+      }
+      key--;
+    }
+
+    var functionEntry = findEnclosingFunction(provider, frame.uri, offset);
+    String methodName = nameOf(functionEntry?.sourceNameId ?? -1);
+    mappedFrames.add(new Frame(fileName, targetLine, targetColumn, methodName));
+    deobfuscatedFrames.addAll(mappedFrames);
+  }
+  return new StackDeobfuscationResult(
+      trace, new Trace(deobfuscatedFrames), frameMap);
+}
+
+/// Ensure we don't use spaces in method names. At this time, they are only
+/// introduced by `<anonymous function>`.
+_normalizeName(String methodName) =>
+    methodName?.replaceAll("<anonymous function>", "<anonymous>") ??
+    '<unknown>';
diff --git a/pkg/dart2js_tools/lib/src/util.dart b/pkg/dart2js_tools/lib/src/util.dart
index 947c4ad..a68cf6e 100644
--- a/pkg/dart2js_tools/lib/src/util.dart
+++ b/pkg/dart2js_tools/lib/src/util.dart
@@ -22,6 +22,27 @@
   Dart2jsMapping mappingFor(Uri uri) => _mappings[uri] ??= parseMappingFor(uri);
 }
 
+/// A provider that converts `http:` URLs to a `file:` URI assuming that all
+/// files were downloaded on the current working directory.
+///
+/// Typically used when downloading the source and source-map files and applying
+/// deobfuscation locally for debugging purposes.
+class DownloadedFileProvider extends CachingFileProvider {
+  _localize(uri) {
+    if (uri.scheme == 'http' || uri.scheme == 'https') {
+      String filename = uri.path.substring(uri.path.lastIndexOf('/') + 1);
+      return Uri.base.resolve(filename);
+    }
+    return uri;
+  }
+
+  String sourcesFor(Uri uri) => super.sourcesFor(_localize(uri));
+
+  SourceFile fileFor(Uri uri) => super.fileFor(_localize(uri));
+
+  Dart2jsMapping mappingFor(Uri uri) => super.mappingFor(_localize(uri));
+}
+
 warn(String message) {
   if (_seenMessages.add(message)) {
     print(message);
diff --git a/pkg/dart2js_tools/pubspec.yaml b/pkg/dart2js_tools/pubspec.yaml
index caf79e9..889e6f4 100644
--- a/pkg/dart2js_tools/pubspec.yaml
+++ b/pkg/dart2js_tools/pubspec.yaml
@@ -5,5 +5,6 @@
   information, deobfuscation of stack-traces and minified names.
 dependencies:
   source_maps: ^0.10.7
+  stack_trace: ^1.9.3
 environment:
   sdk: '>=2.0.0 <3.0.0'
diff --git a/pkg/dartfix/CHANGELOG.md b/pkg/dartfix/CHANGELOG.md
new file mode 100644
index 0000000..5499be8
--- /dev/null
+++ b/pkg/dartfix/CHANGELOG.md
@@ -0,0 +1,2 @@
+# 0.1.0
+ * Initial version
diff --git a/pkg/dartfix/LICENSE b/pkg/dartfix/LICENSE
new file mode 100644
index 0000000..a9ab5f8
--- /dev/null
+++ b/pkg/dartfix/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2018, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/pkg/dartfix/README.md b/pkg/dartfix/README.md
new file mode 100644
index 0000000..9ad39f3
--- /dev/null
+++ b/pkg/dartfix/README.md
@@ -0,0 +1,22 @@
+# dartfix
+
+dartfix is a tool for migrating Dart source to newer versions of the Dart SDK,
+and fixing common issues.
+
+## Usage
+
+To activate the package
+```
+  pub global activate dartfix
+```
+
+Once activated, dart fix can be run using
+```
+  pub global run dartfix:fix <target directory>
+```
+or if you have
+[setup your path](https://www.dartlang.org/tools/pub/cmd/pub-global#running-a-script-from-your-path)
+to include the pub bin directory, then simply
+```
+  dartfix <target directory>
+```
diff --git a/pkg/dartfix/bin/fix.dart b/pkg/dartfix/bin/fix.dart
index da176a1..0e2a489 100644
--- a/pkg/dartfix/bin/fix.dart
+++ b/pkg/dartfix/bin/fix.dart
@@ -1,5 +1,5 @@
 #!/usr/bin/env dart
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
diff --git a/pkg/dartfix/lib/handler/analysis_complete_handler.dart b/pkg/dartfix/lib/handler/analysis_complete_handler.dart
new file mode 100644
index 0000000..939f703
--- /dev/null
+++ b/pkg/dartfix/lib/handler/analysis_complete_handler.dart
@@ -0,0 +1,31 @@
+// 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.
+//
+// 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".
+
+import 'dart:async';
+
+import 'package:analysis_server_client/handler/notification_handler.dart';
+import 'package:analysis_server_client/protocol.dart';
+
+/// [AnalysisCompleteHandler] listens to analysis server notifications
+/// and detects when analysis has finished.
+mixin AnalysisCompleteHandler on NotificationHandler {
+  Completer<void> _analysisComplete;
+
+  @override
+  void onServerStatus(ServerStatusParams params) {
+    if (params.analysis != null && !params.analysis.isAnalyzing) {
+      _analysisComplete?.complete();
+      _analysisComplete = null;
+    }
+  }
+
+  Future<void> analysisComplete() {
+    _analysisComplete ??= new Completer<void>();
+    return _analysisComplete.future;
+  }
+}
diff --git a/pkg/dartfix/lib/listener/bad_message_listener.dart b/pkg/dartfix/lib/listener/bad_message_listener.dart
new file mode 100644
index 0000000..fc46ed9
--- /dev/null
+++ b/pkg/dartfix/lib/listener/bad_message_listener.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:analysis_server_client/listener/server_listener.dart';
+
+/// [BadMessageListener] throws an exception if the [Client] receives bad data.
+mixin BadMessageListener on ServerListener {
+  /// True if we've received bad data from the server.
+  bool _receivedBadDataFromServer = false;
+
+  void throwDelayedException(String prefix, String details) {
+    if (!_receivedBadDataFromServer) {
+      _receivedBadDataFromServer = true;
+      // Give the server 1 second to continue outputting bad data
+      // such as outputting a stacktrace.
+      new Future.delayed(new Duration(seconds: 1), () {
+        throw '$prefix $details';
+      });
+    }
+  }
+
+  @override
+  void badMessage(String trimmedLine, exception) {
+    super.badMessage(trimmedLine, exception);
+    throwDelayedException('JSON decode failure', '$exception');
+  }
+
+  @override
+  void errorMessage(String line) {
+    super.errorMessage(line);
+    throwDelayedException('ERR:', line);
+  }
+
+  @override
+  void unexpectedMessage(Map<String, dynamic> message) {
+    super.unexpectedMessage(message);
+    throwDelayedException(
+        'BAD DATA FROM SERVER:', 'Unexpected message from server');
+  }
+
+  @override
+  void unexpectedResponse(Map<String, dynamic> message, id) {
+    super.unexpectedResponse(message, id);
+    throw 'Unexpected response from server: id=$id';
+  }
+
+  @override
+  void unexpectedStop(int exitCode) {
+    super.unexpectedStop(exitCode);
+    throwDelayedException('Server terminated with exit code', '$exitCode');
+  }
+}
diff --git a/pkg/dartfix/lib/listener/recording_listener.dart b/pkg/dartfix/lib/listener/recording_listener.dart
new file mode 100644
index 0000000..7ac4a12
--- /dev/null
+++ b/pkg/dartfix/lib/listener/recording_listener.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server_client/server.dart';
+import 'package:analysis_server_client/listener/server_listener.dart';
+import 'package:dartfix/listener/bad_message_listener.dart';
+import 'package:dartfix/listener/timed_listener.dart';
+
+/// [RecordingListener] caches all messages exchanged with the server
+/// and print them if a problem occurs.
+///
+/// This is primarily used when testing and debugging the analysis server.
+class RecordingListener with ServerListener, BadMessageListener, TimedListener {
+  /// True if we are currently printing out messages exchanged with the server.
+  bool _echoMessages = false;
+
+  /// Messages which have been exchanged with the server; we buffer these
+  /// up until the test finishes, so that they can be examined in the debugger
+  /// or printed out in response to a call to [echoMessages].
+  final _messages = <String>[];
+
+  /// Print out any messages exchanged with the server.  If some messages have
+  /// already been exchanged with the server, they are printed out immediately.
+  void echoMessages() {
+    if (_echoMessages) {
+      return;
+    }
+    _echoMessages = true;
+    for (String line in _messages) {
+      print(line);
+    }
+  }
+
+  /// Called when the [Server] is terminating the server process
+  /// rather than requesting that the server stop itself.
+  void killingServerProcess(String reason) {
+    echoMessages();
+    super.killingServerProcess(reason);
+  }
+
+  /// Log a timed message about interaction with the server.
+  void logTimed(double elapseTime, String prefix, String details) {
+    String line = '$elapseTime: $prefix $details';
+    if (_echoMessages) {
+      print(line);
+    }
+    _messages.add(line);
+  }
+
+  @override
+  void throwDelayedException(String prefix, String details) {
+    echoMessages();
+    super.throwDelayedException(prefix, details);
+  }
+}
diff --git a/pkg/dartfix/lib/listener/timed_listener.dart b/pkg/dartfix/lib/listener/timed_listener.dart
new file mode 100644
index 0000000..56a6555
--- /dev/null
+++ b/pkg/dartfix/lib/listener/timed_listener.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server_client/listener/server_listener.dart';
+
+/// [TimedListener] appends a timestamp (seconds since server startup)
+/// to each logged interaction with the server.
+mixin TimedListener on ServerListener {
+  /// Stopwatch that we use to generate timing information for debug output.
+  Stopwatch _time = new Stopwatch();
+
+  /// The [currentElapseTime] at which the last communication was received from
+  /// the server or `null` if no communication has been received.
+  double lastCommunicationTime;
+
+  /// The current elapse time (seconds) since the server was started.
+  double get currentElapseTime => _time.elapsedTicks / _time.frequency;
+
+  @override
+  void log(String prefix, String details) {
+    logTimed(currentElapseTime, prefix, details);
+  }
+
+  /// Log a timed message about interaction with the server.
+  void logTimed(double elapseTime, String prefix, String details);
+
+  @override
+  void messageReceived(String json) {
+    lastCommunicationTime = currentElapseTime;
+    super.messageReceived(json);
+  }
+
+  @override
+  void startingServer(String dartBinary, List<String> arguments) {
+    _time.start();
+    super.startingServer(dartBinary, arguments);
+  }
+}
diff --git a/pkg/dartfix/lib/src/context.dart b/pkg/dartfix/lib/src/context.dart
index 0869830..e6bb598 100644
--- a/pkg/dartfix/lib/src/context.dart
+++ b/pkg/dartfix/lib/src/context.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
diff --git a/pkg/dartfix/lib/src/driver.dart b/pkg/dartfix/lib/src/driver.dart
index 80e7a05..0c685d1 100644
--- a/pkg/dartfix/lib/src/driver.dart
+++ b/pkg/dartfix/lib/src/driver.dart
@@ -1,85 +1,80 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:io' show File, Directory;
+import 'dart:io' show File, Platform;
 
+import 'package:analysis_server_client/server.dart';
+import 'package:analysis_server_client/handler/connection_handler.dart';
+import 'package:analysis_server_client/handler/notification_handler.dart';
+import 'package:analysis_server_client/listener/server_listener.dart';
 import 'package:analysis_server_client/protocol.dart';
 import 'package:cli_util/cli_logging.dart';
+import 'package:dartfix/handler/analysis_complete_handler.dart';
+import 'package:dartfix/listener/bad_message_listener.dart';
 import 'package:dartfix/src/context.dart';
 import 'package:dartfix/src/options.dart';
-import 'package:dartfix/src/server.dart';
-import 'package:path/path.dart' as path;
+import 'package:dartfix/src/util.dart';
+import 'package:pub_semver/pub_semver.dart';
 
 class Driver {
   Context context;
+  _Handler handler;
   Logger logger;
   Server server;
 
-  Completer serverConnected;
-  Completer analysisComplete;
   bool force;
   bool overwrite;
   List<String> targets;
 
   Ansi get ansi => logger.ansi;
 
-  bool get runAnalysisServerFromSource {
-    // Automatically run analysis server from source
-    // if this command line tool is being run from source
-    // within the source tree.
-    return Server.findRoot() != null;
-  }
-
   Future start(List<String> args) async {
     final Options options = Options.parse(args);
 
     force = options.force;
     overwrite = options.overwrite;
     targets = options.targets;
-
     context = options.context;
     logger = options.logger;
+    server = new Server(listener: new _Listener(logger));
+    handler = new _Handler(this);
+
+    if (!await startServer(options)) {
+      context.exit(15);
+    }
 
     EditDartfixResult result;
-
-    await startServer(options);
-
-    bool normalShutdown = false;
     try {
       final progress = await setupAnalysis(options);
       result = await requestFixes(options, progress);
-      normalShutdown = true;
     } finally {
-      try {
-        await stopServer(server);
-      } catch (_) {
-        if (normalShutdown) {
-          rethrow;
-        }
-      }
+      await server.stop();
     }
     if (result != null) {
       applyFixes(result);
     }
   }
 
-  Future startServer(Options options) async {
-    server = new Server(logger);
-    const connectTimeout = const Duration(seconds: 15);
-    serverConnected = new Completer();
+  Future<bool> startServer(Options options) async {
     if (options.verbose) {
-      server.debugStdio();
+      logger.trace('Dart SDK version ${Platform.version}');
+      logger.trace('  ${Platform.resolvedExecutable}');
+      logger.trace('dartfix');
+      logger.trace('  ${Platform.script.toFilePath()}');
     }
-    logger.trace('Starting...');
+    // Automatically run analysis server from source
+    // if this command line tool is being run from source within the SDK repo.
+    String serverPath = findServerPath();
     await server.start(
-        sdkPath: options.sdkPath, useSnapshot: !runAnalysisServerFromSource);
-    server.listenToOutput(dispatchNotification);
-    return serverConnected.future.timeout(connectTimeout, onTimeout: () {
-      logger.stderr('Failed to connect to server');
-      context.exit(15);
-    });
+      clientId: 'dartfix',
+      clientVersion: pubspecVersion,
+      sdkPath: options.sdkPath,
+      serverPath: serverPath,
+    );
+    server.listenToOutput(notificationProcessor: handler.handleEvent);
+    return handler.serverConnected(timeLimit: const Duration(seconds: 15));
   }
 
   Future<Progress> setupAnalysis(Options options) async {
@@ -100,27 +95,21 @@
   Future<EditDartfixResult> requestFixes(
       Options options, Progress progress) async {
     logger.trace('Requesting fixes');
-    analysisComplete = new Completer();
+    Future isAnalysisComplete = handler.analysisComplete();
     Map<String, dynamic> json = await server.send(
         EDIT_REQUEST_DARTFIX, new EditDartfixParams(options.targets).toJson());
-    await analysisComplete?.future;
+
+    // TODO(danrubel): This is imprecise signal for determining when all
+    // analysis error notifications have been received. Consider adding a new
+    // notification indicating that the server is idle (all requests processed,
+    // all analysis complete, all notifications sent).
+    await isAnalysisComplete;
+
     progress.finish(showTiming: true);
     ResponseDecoder decoder = new ResponseDecoder(null);
     return EditDartfixResult.fromJson(decoder, 'result', json);
   }
 
-  Future stopServer(Server server) async {
-    logger.trace('Stopping...');
-    const timeout = const Duration(seconds: 5);
-    await server.send(SERVER_REQUEST_SHUTDOWN, null).timeout(timeout,
-        onTimeout: () {
-      // fall through to wait for exit.
-    });
-    await server.exitCode.timeout(timeout, onTimeout: () {
-      return server.kill('server failed to exit');
-    });
-  }
-
   Future applyFixes(EditDartfixResult result) async {
     showDescriptions('Recommended changes', result.suggestions);
     showDescriptions('Recommended changes that cannot be automatically applied',
@@ -135,7 +124,7 @@
     logger.stdout('');
     logger.stdout(ansi.emphasized('Files to be changed:'));
     for (SourceFileEdit fileEdit in result.edits) {
-      logger.stdout('  ${_relativePath(fileEdit.file)}');
+      logger.stdout('  ${relativePath(fileEdit.file)}');
     }
     if (shouldApplyChanges(result)) {
       for (SourceFileEdit fileEdit in result.edits) {
@@ -146,7 +135,7 @@
         }
         await file.writeAsString(code);
       }
-      logger.stdout('Changes applied.');
+      logger.stdout(ansi.emphasized('Changes applied.'));
     }
   }
 
@@ -157,9 +146,14 @@
       List<DartFixSuggestion> sorted = new List.from(suggestions)
         ..sort(compareSuggestions);
       for (DartFixSuggestion suggestion in sorted) {
-        Location loc = suggestion.location;
-        logger.stdout('  ${_toSentenceFragment(suggestion.description)}'
-            '${loc == null ? "" : " • ${loc.startLine}:${loc.startColumn}"}');
+        final msg = new StringBuffer();
+        msg.write('  ${toSentenceFragment(suggestion.description)}');
+        final loc = suggestion.location;
+        if (loc != null) {
+          msg.write(' • ${relativePath(loc.file)}');
+          msg.write(' • ${loc.startLine}:${loc.startColumn}');
+        }
+        logger.stdout(msg.toString());
       }
     }
   }
@@ -181,193 +175,78 @@
     return true;
   }
 
-  /// Dispatch the notification named [event], and containing parameters
-  /// [params], to the appropriate stream.
-  void dispatchNotification(String event, params) {
-    ResponseDecoder decoder = new ResponseDecoder(null);
-    switch (event) {
-      case SERVER_NOTIFICATION_CONNECTED:
-        onServerConnected(
-            new ServerConnectedParams.fromJson(decoder, 'params', params));
-        break;
-      case SERVER_NOTIFICATION_ERROR:
-        onServerError(
-            new ServerErrorParams.fromJson(decoder, 'params', params));
-        break;
-      case SERVER_NOTIFICATION_STATUS:
-        onServerStatus(
-            new ServerStatusParams.fromJson(decoder, 'params', params));
-        break;
-//      case ANALYSIS_NOTIFICATION_ANALYZED_FILES:
-//        outOfTestExpect(params, isAnalysisAnalyzedFilesParams);
-//        _onAnalysisAnalyzedFiles.add(new AnalysisAnalyzedFilesParams.fromJson(
-//            decoder, 'params', params));
-//        break;
-//      case ANALYSIS_NOTIFICATION_CLOSING_LABELS:
-//        outOfTestExpect(params, isAnalysisClosingLabelsParams);
-//        _onAnalysisClosingLabels.add(new AnalysisClosingLabelsParams.fromJson(
-//            decoder, 'params', params));
-//        break;
-      case ANALYSIS_NOTIFICATION_ERRORS:
-        onAnalysisErrors(
-            new AnalysisErrorsParams.fromJson(decoder, 'params', params));
-        break;
-//      case ANALYSIS_NOTIFICATION_FLUSH_RESULTS:
-//        outOfTestExpect(params, isAnalysisFlushResultsParams);
-//        _onAnalysisFlushResults.add(
-//            new AnalysisFlushResultsParams.fromJson(decoder, 'params', params));
-//        break;
-//      case ANALYSIS_NOTIFICATION_FOLDING:
-//        outOfTestExpect(params, isAnalysisFoldingParams);
-//        _onAnalysisFolding
-//            .add(new AnalysisFoldingParams.fromJson(decoder, 'params', params));
-//        break;
-//      case ANALYSIS_NOTIFICATION_HIGHLIGHTS:
-//        outOfTestExpect(params, isAnalysisHighlightsParams);
-//        _onAnalysisHighlights.add(
-//            new AnalysisHighlightsParams.fromJson(decoder, 'params', params));
-//        break;
-//      case ANALYSIS_NOTIFICATION_IMPLEMENTED:
-//        outOfTestExpect(params, isAnalysisImplementedParams);
-//        _onAnalysisImplemented.add(
-//            new AnalysisImplementedParams.fromJson(decoder, 'params', params));
-//        break;
-//      case ANALYSIS_NOTIFICATION_INVALIDATE:
-//        outOfTestExpect(params, isAnalysisInvalidateParams);
-//        _onAnalysisInvalidate.add(
-//            new AnalysisInvalidateParams.fromJson(decoder, 'params', params));
-//        break;
-//      case ANALYSIS_NOTIFICATION_NAVIGATION:
-//        outOfTestExpect(params, isAnalysisNavigationParams);
-//        _onAnalysisNavigation.add(
-//            new AnalysisNavigationParams.fromJson(decoder, 'params', params));
-//        break;
-//      case ANALYSIS_NOTIFICATION_OCCURRENCES:
-//        outOfTestExpect(params, isAnalysisOccurrencesParams);
-//        _onAnalysisOccurrences.add(
-//            new AnalysisOccurrencesParams.fromJson(decoder, 'params', params));
-//        break;
-//      case ANALYSIS_NOTIFICATION_OUTLINE:
-//        outOfTestExpect(params, isAnalysisOutlineParams);
-//        _onAnalysisOutline
-//            .add(new AnalysisOutlineParams.fromJson(decoder, 'params', params));
-//        break;
-//      case ANALYSIS_NOTIFICATION_OVERRIDES:
-//        outOfTestExpect(params, isAnalysisOverridesParams);
-//        _onAnalysisOverrides.add(
-//            new AnalysisOverridesParams.fromJson(decoder, 'params', params));
-//        break;
-//      case COMPLETION_NOTIFICATION_RESULTS:
-//        outOfTestExpect(params, isCompletionResultsParams);
-//        _onCompletionResults.add(
-//            new CompletionResultsParams.fromJson(decoder, 'params', params));
-//        break;
-//      case SEARCH_NOTIFICATION_RESULTS:
-//        outOfTestExpect(params, isSearchResultsParams);
-//        _onSearchResults
-//            .add(new SearchResultsParams.fromJson(decoder, 'params', params));
-//        break;
-//      case EXECUTION_NOTIFICATION_LAUNCH_DATA:
-//        outOfTestExpect(params, isExecutionLaunchDataParams);
-//        _onExecutionLaunchData.add(
-//            new ExecutionLaunchDataParams.fromJson(decoder, 'params', params));
-//        break;
-//      case FLUTTER_NOTIFICATION_OUTLINE:
-//        outOfTestExpect(params, isFlutterOutlineParams);
-//        _onFlutterOutline
-//            .add(new FlutterOutlineParams.fromJson(decoder, 'params', params));
-//        break;
-//      default:
-//        printAndFail('Unexpected notification: $event');
-//        break;
-    }
-  }
-
-  void onAnalysisErrors(AnalysisErrorsParams params) {
-    List<AnalysisError> errors = params.errors;
-    bool foundAtLeastOneError = false;
-    if (errors.isNotEmpty && isTarget(params.file)) {
-      for (AnalysisError error in errors) {
-        if (!shouldFilterError(error)) {
-          if (!foundAtLeastOneError) {
-            foundAtLeastOneError = true;
-            logger.stdout('${_relativePath(params.file)}:');
-          }
-          Location loc = error.location;
-          logger.stdout('  ${_toSentenceFragment(error.message)}'
-              ' • ${loc.startLine}:${loc.startColumn}');
-        }
-      }
-    }
-  }
-
-  void onServerConnected(ServerConnectedParams params) {
-    logger.trace('Connected to server');
-    serverConnected.complete();
-  }
-
-  void onServerError(ServerErrorParams params) async {
-    try {
-      await stopServer(server);
-    } catch (e) {
-      // ignored
-    }
-    final message = new StringBuffer('Server Error: ')..writeln(params.message);
-    if (params.stackTrace != null) {
-      message.writeln(params.stackTrace);
-    }
-    logger.stderr(message.toString());
-    context.exit(15);
-  }
-
-  void onServerStatus(ServerStatusParams params) {
-    if (params.analysis != null && !params.analysis.isAnalyzing) {
-      logger.trace('Analysis complete');
-      analysisComplete?.complete();
-      analysisComplete = null;
-    }
-  }
-
-  int compareSuggestions(DartFixSuggestion s1, DartFixSuggestion s2) {
-    int result = s1.description.compareTo(s2.description);
-    if (result != 0) {
-      return result;
-    }
-    return (s2.location?.offset ?? 0) - (s1.location?.offset ?? 0);
-  }
-
-  bool shouldFilterError(AnalysisError error) {
-    // Do not show TODOs or errors that will be automatically fixed.
-
-    // TODO(danrubel): Rather than checking the error.code with
-    // specific strings, add something to the error indicating that
-    // it will be automatically fixed by edit.dartfix.
-    return error.type.name == 'TODO' ||
-        error.code == 'wrong_number_of_type_arguments_constructor';
-  }
-
-  bool isTarget(String filePath) {
+  String relativePath(String filePath) {
     for (String target in targets) {
-      if (filePath == target || path.isWithin(target, filePath)) {
-        return true;
+      if (filePath.startsWith(target)) {
+        return filePath.substring(target.length + 1);
       }
     }
-    return false;
-  }
-}
-
-String _relativePath(String filePath) {
-  final String currentPath = Directory.current.absolute.path;
-
-  if (filePath.startsWith(currentPath)) {
-    return filePath.substring(currentPath.length + 1);
-  } else {
     return filePath;
   }
 }
 
-String _toSentenceFragment(String message) {
-  return message.endsWith('.')
-      ? message.substring(0, message.length - 1)
-      : message;
+class _Listener with ServerListener, BadMessageListener {
+  final Logger logger;
+  final bool verbose;
+
+  _Listener(this.logger) : verbose = logger.isVerbose;
+
+  @override
+  void log(String prefix, String details) {
+    if (verbose) {
+      logger.trace('$prefix $details');
+    }
+  }
+}
+
+class _Handler
+    with NotificationHandler, ConnectionHandler, AnalysisCompleteHandler {
+  final Driver driver;
+  final Logger logger;
+  final Server server;
+
+  _Handler(this.driver)
+      : logger = driver.logger,
+        server = driver.server;
+
+  @override
+  void onFailedToConnect() {
+    logger.stderr('Failed to connect to server');
+  }
+
+  @override
+  void onProtocolNotSupported(Version version) {
+    logger.stderr('Expected protocol version $PROTOCOL_VERSION,'
+        ' but found $version');
+  }
+
+  @override
+  void onServerError(ServerErrorParams params) {
+    if (params.isFatal) {
+      logger.stderr('Fatal Server Error: ${params.message}');
+    } else {
+      logger.stderr('Server Error: ${params.message}');
+    }
+    if (params.stackTrace != null) {
+      logger.stderr(params.stackTrace);
+    }
+    super.onServerError(params);
+  }
+
+  @override
+  void onAnalysisErrors(AnalysisErrorsParams params) {
+    List<AnalysisError> errors = params.errors;
+    bool foundAtLeastOneError = false;
+    for (AnalysisError error in errors) {
+      if (shouldShowError(error)) {
+        if (!foundAtLeastOneError) {
+          foundAtLeastOneError = true;
+          logger.stdout('${driver.relativePath(params.file)}:');
+        }
+        Location loc = error.location;
+        logger.stdout('  ${toSentenceFragment(error.message)}'
+            ' • ${loc.startLine}:${loc.startColumn}');
+      }
+    }
+  }
 }
diff --git a/pkg/dartfix/lib/src/options.dart b/pkg/dartfix/lib/src/options.dart
index bd51025..2353b66 100644
--- a/pkg/dartfix/lib/src/options.dart
+++ b/pkg/dartfix/lib/src/options.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
diff --git a/pkg/dartfix/lib/src/server.dart b/pkg/dartfix/lib/src/server.dart
deleted file mode 100644
index 525610e..0000000
--- a/pkg/dartfix/lib/src/server.dart
+++ /dev/null
@@ -1,360 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io';
-
-import 'package:cli_util/cli_logging.dart';
-import 'package:path/path.dart';
-
-/**
- * Type of callbacks used to process notifications.
- */
-typedef void NotificationProcessor(String event, params);
-
-/**
- * Instances of the class [Server] manage a connection to a server process, and
- * facilitate communication to and from the server.
- */
-class Server {
-  /**
-   * Server process object, or null if server hasn't been started yet.
-   */
-  Process _process;
-
-  /**
-   * Commands that have been sent to the server but not yet acknowledged, and
-   * the [Completer] objects which should be completed when acknowledgement is
-   * received.
-   */
-  final Map<String, Completer<Map<String, dynamic>>> _pendingCommands =
-      <String, Completer<Map<String, dynamic>>>{};
-
-  /**
-   * Number which should be used to compute the 'id' to send in the next command
-   * sent to the server.
-   */
-  int _nextId = 0;
-
-  /**
-   * Messages which have been exchanged with the server; we buffer these
-   * up until the test finishes, so that they can be examined in the debugger
-   * or printed out in response to a call to [debugStdio].
-   */
-  final List<String> _recordedStdio = <String>[];
-
-  /**
-   * True if we are currently printing out messages exchanged with the server.
-   */
-  bool _debuggingStdio = false;
-
-  /**
-   * True if we've received bad data from the server, and we are aborting the
-   * test.
-   */
-  bool _receivedBadDataFromServer = false;
-
-  /**
-   * Stopwatch that we use to generate timing information for debug output.
-   */
-  Stopwatch _time = new Stopwatch();
-
-  /**
-   * The [currentElapseTime] at which the last communication was received from the server
-   * or `null` if no communication has been received.
-   */
-  double lastCommunicationTime;
-
-  /**
-   * The current elapse time (seconds) since the server was started.
-   */
-  double get currentElapseTime => _time.elapsedTicks / _time.frequency;
-
-  /**
-   * Future that completes when the server process exits.
-   */
-  Future<int> get exitCode => _process.exitCode;
-
-  final Logger logger;
-
-  Server(this.logger);
-
-  /**
-   * Print out any messages exchanged with the server.  If some messages have
-   * already been exchanged with the server, they are printed out immediately.
-   */
-  void debugStdio() {
-    if (_debuggingStdio) {
-      return;
-    }
-    _debuggingStdio = true;
-    for (String line in _recordedStdio) {
-      logger.trace(line);
-    }
-  }
-
-  /**
-   * Find the root directory of the analysis_server package by proceeding
-   * upward until finding the Dart SDK repository root then returning
-   * the analysis_server package root within the repository.
-   * Return `null` if it cannot be found.
-   */
-  static String findRoot([String pathname]) {
-    pathname ??= Platform.script.toFilePath(windows: Platform.isWindows);
-    while (true) {
-      String parent = dirname(pathname);
-      if (parent.length >= pathname.length) {
-        return null;
-      }
-      String root = normalize(join(parent, 'pkg', 'analysis_server'));
-      String server = join(root, 'bin', 'server.dart');
-      if (new File(server).existsSync()) {
-        return root;
-      }
-      pathname = parent;
-    }
-  }
-
-  /**
-   * Return a future that will complete when all commands that have been sent
-   * to the server so far have been flushed to the OS buffer.
-   */
-  Future flushCommands() {
-    return _process.stdin.flush();
-  }
-
-  /**
-   * Stop the server.
-   */
-  Future<int> kill(String reason) {
-    debugStdio();
-    _recordStdio('FORCIBLY TERMINATING PROCESS: $reason');
-    _process.kill();
-    return _process.exitCode;
-  }
-
-  /**
-   * Start listening to output from the server, and deliver notifications to
-   * [notificationProcessor].
-   */
-  void listenToOutput(NotificationProcessor notificationProcessor) {
-    _process.stdout
-        .transform(utf8.decoder)
-        .transform(new LineSplitter())
-        .listen((String line) {
-      lastCommunicationTime = currentElapseTime;
-      String trimmedLine = line.trim();
-
-      // Guard against lines like:
-      //   {"event":"server.connected","params":{...}}Observatory listening on ...
-      final String observatoryMessage = 'Observatory listening on ';
-      if (trimmedLine.contains(observatoryMessage)) {
-        trimmedLine = trimmedLine
-            .substring(0, trimmedLine.indexOf(observatoryMessage))
-            .trim();
-      }
-      if (trimmedLine.isEmpty) {
-        return;
-      }
-
-      _recordStdio('<== $trimmedLine');
-      var message;
-      try {
-        message = json.decoder.convert(trimmedLine);
-      } catch (exception) {
-        _badDataFromServer('JSON decode failure: $exception');
-        return;
-      }
-      Map messageAsMap = message;
-      if (messageAsMap.containsKey('id')) {
-        String id = message['id'];
-        Completer<Map<String, dynamic>> completer = _pendingCommands[id];
-        if (completer == null) {
-          throw 'Unexpected response from server: id=$id';
-        } else {
-          _pendingCommands.remove(id);
-        }
-        if (messageAsMap.containsKey('error')) {
-          completer.completeError(new ServerErrorMessage(messageAsMap));
-        } else {
-          Map<String, dynamic> result = messageAsMap['result'];
-          completer.complete(result);
-        }
-      } else {
-        String event = messageAsMap['event'];
-        notificationProcessor(event, messageAsMap['params']);
-      }
-    });
-    _process.stderr
-        .transform((new Utf8Codec()).decoder)
-        .transform(new LineSplitter())
-        .listen((String line) {
-      String trimmedLine = line.trim();
-      _recordStdio('ERR:  $trimmedLine');
-      _badDataFromServer('Message received on stderr', silent: true);
-    });
-  }
-
-  /**
-   * Send a command to the server.  An 'id' will be automatically assigned.
-   * The returned [Future] will be completed when the server acknowledges the
-   * command with a response.  If the server acknowledges the command with a
-   * normal (non-error) response, the future will be completed with the 'result'
-   * field from the response.  If the server acknowledges the command with an
-   * error response, the future will be completed with an error.
-   */
-  Future<Map<String, dynamic>> send(
-      String method, Map<String, dynamic> params) {
-    String id = '${_nextId++}';
-    Map<String, dynamic> command = <String, dynamic>{
-      'id': id,
-      'method': method
-    };
-    if (params != null) {
-      command['params'] = params;
-    }
-    Completer<Map<String, dynamic>> completer =
-        new Completer<Map<String, dynamic>>();
-    _pendingCommands[id] = completer;
-    String line = json.encode(command);
-    _recordStdio('==> $line');
-    _process.stdin.add(utf8.encoder.convert("$line\n"));
-    return completer.future;
-  }
-
-  /**
-   * Start the server. If [profileServer] is `true`, the server will be started
-   * with "--observe" and "--pause-isolates-on-exit", allowing the observatory
-   * to be used.
-   */
-  Future start({
-    int diagnosticPort,
-    String instrumentationLogFile,
-    bool profileServer: false,
-    String sdkPath,
-    int servicesPort,
-    bool useAnalysisHighlight2: false,
-    bool useSnapshot: true,
-  }) async {
-    if (_process != null) {
-      throw new Exception('Process already started');
-    }
-    _time.start();
-    String dartBinary = Platform.executable;
-
-    String serverPath;
-
-    // The integration tests run 3x faster when run from snapshots (you need to
-    // run test.py with --use-sdk).
-    if (useSnapshot) {
-      // Look for snapshots/analysis_server.dart.snapshot.
-      serverPath = normalize(join(dirname(Platform.resolvedExecutable),
-          'snapshots', 'analysis_server.dart.snapshot'));
-
-      if (!FileSystemEntity.isFileSync(serverPath)) {
-        // Look for dart-sdk/bin/snapshots/analysis_server.dart.snapshot.
-        serverPath = normalize(join(dirname(Platform.resolvedExecutable),
-            'dart-sdk', 'bin', 'snapshots', 'analysis_server.dart.snapshot'));
-      }
-    } else {
-      String rootDir = Server.findRoot();
-      if (rootDir == null) {
-        throw new Exception("Can't find analysis server root directory");
-      }
-      serverPath = normalize(join(rootDir, 'bin', 'server.dart'));
-    }
-
-    List<String> arguments = [];
-    //
-    // Add VM arguments.
-    //
-    if (profileServer) {
-      if (servicesPort == null) {
-        arguments.add('--observe');
-      } else {
-        arguments.add('--observe=$servicesPort');
-      }
-      arguments.add('--pause-isolates-on-exit');
-    } else if (servicesPort != null) {
-      arguments.add('--enable-vm-service=$servicesPort');
-    }
-    if (Platform.packageConfig != null) {
-      arguments.add('--packages=${Platform.packageConfig}');
-    }
-    //
-    // Add the server executable.
-    //
-    arguments.add(serverPath);
-    //
-    // Add server arguments.
-    //
-    arguments.add('--suppress-analytics');
-    if (diagnosticPort != null) {
-      arguments.add('--port');
-      arguments.add(diagnosticPort.toString());
-    }
-    if (instrumentationLogFile != null) {
-      arguments.add('--instrumentation-log-file=$instrumentationLogFile');
-    }
-    if (sdkPath != null) {
-      arguments.add('--sdk=$sdkPath');
-    }
-    if (useAnalysisHighlight2) {
-      arguments.add('--useAnalysisHighlight2');
-    }
-    _process = await Process.start(dartBinary, arguments);
-    _process.exitCode.then((int code) {
-      if (code != 0) {
-        _badDataFromServer('server terminated with exit code $code');
-      }
-    });
-  }
-
-  /**
-   * Deal with bad data received from the server.
-   */
-  void _badDataFromServer(String details, {bool silent: false}) {
-    if (!silent) {
-      _recordStdio('BAD DATA FROM SERVER: $details');
-    }
-    if (_receivedBadDataFromServer) {
-      // We're already dealing with it.
-      return;
-    }
-    _receivedBadDataFromServer = true;
-    debugStdio();
-    // Give the server 1 second to continue outputting bad data
-    // such as outputting a stacktrace.
-    new Future.delayed(new Duration(seconds: 1), () {
-      throw 'Bad data received from server: $details';
-    });
-  }
-
-  /**
-   * Record a message that was exchanged with the server, and print it out if
-   * [debugStdio] has been called.
-   */
-  void _recordStdio(String line) {
-    double elapsedTime = currentElapseTime;
-    line = "$elapsedTime: $line";
-    if (_debuggingStdio) {
-      logger.trace(line);
-    }
-    _recordedStdio.add(line);
-  }
-}
-
-/**
- * An error result from a server request.
- */
-class ServerErrorMessage {
-  final Map message;
-
-  ServerErrorMessage(this.message);
-
-  dynamic get error => message['error'];
-
-  String toString() => message.toString();
-}
diff --git a/pkg/dartfix/lib/src/util.dart b/pkg/dartfix/lib/src/util.dart
new file mode 100644
index 0000000..eb8f046
--- /dev/null
+++ b/pkg/dartfix/lib/src/util.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io' show File, Platform;
+
+import 'package:analysis_server_client/protocol.dart';
+import 'package:path/path.dart' as path;
+
+/// Read pubspec.yaml and return the version in that file.
+String get pubspecVersion {
+  String dir = path.dirname(Platform.script.toFilePath());
+  File pubspec = new File(path.join(dir, '..', 'pubspec.yaml'));
+
+  List<String> lines = pubspec.readAsLinesSync();
+  if (lines[0] != 'name: dartfix') {
+    throw 'Expected dartfix pubspec in: ${pubspec.path}';
+  }
+  String version;
+  if (lines[1].startsWith('version:')) {
+    version = lines[1].substring(8).trim();
+  }
+  if (version == null || version.isEmpty) {
+    throw 'Failed to find dartfix pubspec version in ${pubspec.path}';
+  }
+  return version;
+}
+
+int compareSuggestions(DartFixSuggestion s1, DartFixSuggestion s2) {
+  int result = s1.description.compareTo(s2.description);
+  if (result != 0) {
+    return result;
+  }
+  return (s2.location?.offset ?? 0) - (s1.location?.offset ?? 0);
+}
+
+/// Return the analysis_server executable by proceeding upward
+/// until finding the Dart SDK repository root then returning
+/// the analysis_server executable within the repository.
+/// Return `null` if it cannot be found.
+String findServerPath() {
+  String pathname = Platform.script.toFilePath();
+  while (true) {
+    String parent = path.dirname(pathname);
+    if (parent.length >= pathname.length) {
+      return null;
+    }
+    String serverPath =
+        path.join(parent, 'pkg', 'analysis_server', 'bin', 'server.dart');
+    if (new File(serverPath).existsSync()) {
+      return serverPath;
+    }
+    pathname = parent;
+  }
+}
+
+bool shouldShowError(AnalysisError error) {
+  // Only show diagnostics that will affect the fixes.
+  return error.type.name != 'HINT' &&
+      error.type.name != 'LINT' &&
+      error.type.name != 'TODO' &&
+      // TODO(danrubel): Rather than checking the error.code with
+      // specific strings, add something to the error indicating that
+      // it will be automatically fixed by edit.dartfix.
+      error.code != 'wrong_number_of_type_arguments_constructor';
+}
+
+String toSentenceFragment(String message) {
+  return message.endsWith('.')
+      ? message.substring(0, message.length - 1)
+      : message;
+}
diff --git a/pkg/dartfix/pubspec.yaml b/pkg/dartfix/pubspec.yaml
index 2349956..c657775 100644
--- a/pkg/dartfix/pubspec.yaml
+++ b/pkg/dartfix/pubspec.yaml
@@ -4,13 +4,17 @@
 description:
   A tool for migrating Dart source to newer versions of the Dart SDK,
   and fixing common issues.
+homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dartfix
+executables:
+  dartfix: fix
 environment:
-  sdk: '>=2.0.0 <3.0.0'
+  sdk: '>=2.1.0-dev.9.2 <2.1.0'
 dependencies:
-  analysis_server_client: ^2.0.0
-  args: any
-  cli_util: any
-  path: any
+  analysis_server_client: ^1.1.0
+  args: ^1.4.0
+  cli_util: ^0.1.3
+  path: ^1.6.0
+  pub_semver: ^1.4.2
 dev_dependencies:
   analyzer: ^0.33.0
   test: ^1.3.0
diff --git a/pkg/dartfix/test/all.dart b/pkg/dartfix/test/all.dart
index c27aa48..50a0ab0 100644
--- a/pkg/dartfix/test/all.dart
+++ b/pkg/dartfix/test/all.dart
@@ -1,9 +1,11 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:test/test.dart';
+
 import 'src/options_test.dart' as options_test;
 
 main() {
-  options_test.main();
+  group('options', options_test.main);
 }
diff --git a/pkg/dartfix/test/src/options_test.dart b/pkg/dartfix/test/src/options_test.dart
index 269ebff..7ce0e1a 100644
--- a/pkg/dartfix/test/src/options_test.dart
+++ b/pkg/dartfix/test/src/options_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -9,103 +9,101 @@
 import 'test_context.dart';
 
 main() {
-  group('Options', () {
-    TestContext context;
-    TestLogger logger;
+  TestContext context;
+  TestLogger logger;
 
-    setUp(() {
-      context = new TestContext();
-      logger = new TestLogger();
-    });
+  setUp(() {
+    context = new TestContext();
+    logger = new TestLogger();
+  });
 
-    String p(String filePath) => context.convertPath(filePath);
+  String p(String filePath) => context.convertPath(filePath);
 
-    Options parse(
-      List<String> args, {
-      String errorOut,
-      int exitCode,
-      bool force = false,
-      String normalOut,
-      bool overwrite = false,
-      List<String> targetSuffixes,
-      bool verbose = false,
-    }) {
-      Options options;
-      int actualExitCode;
-      try {
-        options = Options.parse(args, context: context, logger: logger);
-      } on TestExit catch (e) {
-        actualExitCode = e.code;
-      }
-      expect(logger.stderrBuffer.toString(),
-          errorOut != null ? contains(errorOut) : isEmpty);
-      expect(logger.stdoutBuffer.toString(),
-          normalOut != null ? contains(normalOut) : isEmpty);
-      if (exitCode != null) {
-        expect(actualExitCode, exitCode, reason: 'exit code');
-        return null;
-      } else {
-        expect(actualExitCode, isNull, reason: 'exit code');
-      }
-      expect(options.force, force);
-      expect(options.overwrite, overwrite);
-      expect(options.verbose, verbose);
-      expect(path.isAbsolute(options.sdkPath), isTrue, reason: options.sdkPath);
-      for (String target in options.targets) {
-        expect(target, isNotNull);
-        expect(path.isAbsolute(target), isTrue, reason: '$target');
-      }
-      if (targetSuffixes != null) {
-        for (String suffix in targetSuffixes) {
-          expectContains(options.targets, suffix);
-        }
-      }
-      return options;
+  Options parse(
+    List<String> args, {
+    String errorOut,
+    int exitCode,
+    bool force = false,
+    String normalOut,
+    bool overwrite = false,
+    List<String> targetSuffixes,
+    bool verbose = false,
+  }) {
+    Options options;
+    int actualExitCode;
+    try {
+      options = Options.parse(args, context: context, logger: logger);
+    } on TestExit catch (e) {
+      actualExitCode = e.code;
     }
-
-    test('force', () {
-      parse(['--force', 'foo'], force: true, targetSuffixes: ['foo']);
-    });
-
-    test('help', () {
-      parse(['--help'], errorOut: 'Display this help message', exitCode: 1);
-    });
-
-    test('invalid option', () {
-      parse(['--foo'],
-          errorOut: 'Could not find an option named "foo"', exitCode: 15);
-    });
-
-    test('invalid option no logger', () {
-      try {
-        Options.parse(['--foo'], context: context);
-        fail('Expected exception');
-      } on TestExit catch (e) {
-        expect(e.code, 15, reason: 'exit code');
+    expect(logger.stderrBuffer.toString(),
+        errorOut != null ? contains(errorOut) : isEmpty);
+    expect(logger.stdoutBuffer.toString(),
+        normalOut != null ? contains(normalOut) : isEmpty);
+    if (exitCode != null) {
+      expect(actualExitCode, exitCode, reason: 'exit code');
+      return null;
+    } else {
+      expect(actualExitCode, isNull, reason: 'exit code');
+    }
+    expect(options.force, force);
+    expect(options.overwrite, overwrite);
+    expect(options.verbose, verbose);
+    expect(path.isAbsolute(options.sdkPath), isTrue, reason: options.sdkPath);
+    for (String target in options.targets) {
+      expect(target, isNotNull);
+      expect(path.isAbsolute(target), isTrue, reason: '$target');
+    }
+    if (targetSuffixes != null) {
+      for (String suffix in targetSuffixes) {
+        expectContains(options.targets, suffix);
       }
-    });
+    }
+    return options;
+  }
 
-    test('invalid target', () {
-      parse(['foo.dart'],
-          errorOut: 'Expected directory, but found', exitCode: 15);
-    });
+  test('force', () {
+    parse(['--force', 'foo'], force: true, targetSuffixes: ['foo']);
+  });
 
-    test('overwrite', () {
-      parse(['--overwrite', 'foo'], overwrite: true, targetSuffixes: ['foo']);
-    });
+  test('help', () {
+    parse(['--help'], errorOut: 'Display this help message', exitCode: 1);
+  });
 
-    test('simple', () {
-      parse(['foo'], targetSuffixes: ['foo']);
-    });
+  test('invalid option', () {
+    parse(['--foo'],
+        errorOut: 'Could not find an option named "foo"', exitCode: 15);
+  });
 
-    test('two targets', () {
-      parse([p('one/foo'), p('two/bar')],
-          targetSuffixes: [p('one/foo'), p('two/bar')]);
-    });
+  test('invalid option no logger', () {
+    try {
+      Options.parse(['--foo'], context: context);
+      fail('Expected exception');
+    } on TestExit catch (e) {
+      expect(e.code, 15, reason: 'exit code');
+    }
+  });
 
-    test('verbose', () {
-      parse(['--verbose', 'foo'], verbose: true);
-    });
+  test('invalid target', () {
+    parse(['foo.dart'],
+        errorOut: 'Expected directory, but found', exitCode: 15);
+  });
+
+  test('overwrite', () {
+    parse(['--overwrite', 'foo'], overwrite: true, targetSuffixes: ['foo']);
+  });
+
+  test('simple', () {
+    parse(['foo'], targetSuffixes: ['foo']);
+  });
+
+  test('two targets', () {
+    parse([p('one/foo'), p('two/bar')],
+        targetSuffixes: [p('one/foo'), p('two/bar')]);
+  });
+
+  test('verbose', () {
+    parse(['--verbose', 'foo'], verbose: true);
   });
 }
 
diff --git a/pkg/dartfix/test/src/test_context.dart b/pkg/dartfix/test/src/test_context.dart
index 1298b9a..61faf26 100644
--- a/pkg/dartfix/test/src/test_context.dart
+++ b/pkg/dartfix/test/src/test_context.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
diff --git a/pkg/dev_compiler/README.md b/pkg/dev_compiler/README.md
index 4f6e803..565ac17 100644
--- a/pkg/dev_compiler/README.md
+++ b/pkg/dev_compiler/README.md
@@ -3,7 +3,7 @@
 
 [![Build Status](https://travis-ci.org/dart-lang/sdk.svg?branch=master)](https://travis-ci.org/dart-lang/sdk)
 
-The Dart Dev Compiler (DDC) is a fast, modular compiler that generates modern JavaScript (EcmaScript 6).  Its primary use today is to support fast, iterative development of Dart web applications for Chrome and other modern browers.
+The Dart Dev Compiler (DDC) is a fast, modular compiler that generates modern JavaScript (EcmaScript 6).  Its primary use today is to support fast, iterative development of Dart web applications for Chrome and other modern browsers.
 
 Most users will use DDC via [pub](https://webdev.dartlang.org/tools/pub/pub-serve).  It is supported by pub starting with the Dart 1.24 release.
 
@@ -32,12 +32,12 @@
 
 # Modularity
 
-DDC provides fast, incremental compilation based on standard JavaScript modules.  Unlike Dart2JS, DDC does not require an entire Dart application.  Instead, it operates modularly: it compiles a set of Dart files into a JavaScript module.  A DDC compilation step requires a set of input Dart files and a set of *summaries* of dependencies.  It performs modular type checking as part of this compilation step, and, if the input type checks, it generates a JavaScript module (e.g., [*ES6*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import), [*AMD*](https://github.com/amdjs/amdjs-api/blob/master/AMD.md), or [*CommonJS*](https://nodejs.org/docs/latest/api/modules.html).  The browser (i.e., the JavaScript runtime) loads and links the generated modules when running the application.  
-During development, a compilation step only needs to be rerun if the Dart files or summaries it relies upon change.  For most changes, only a very small part of your code will require recompilation.  Morever, modules that are unchanged can be cached in the browser.
+DDC provides fast, incremental compilation based on standard JavaScript modules.  Unlike Dart2JS, DDC does not require an entire Dart application.  Instead, it operates modularly: it compiles a set of Dart files into a JavaScript module.  A DDC compilation step requires a set of input Dart files and a set of *summaries* of dependencies.  It performs modular type checking as part of this compilation step, and, if the input type checks, it generates a JavaScript module (e.g., [*ES6*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import), [*AMD*](https://github.com/amdjs/amdjs-api/blob/master/AMD.md), or [*CommonJS*](https://nodejs.org/docs/latest/api/modules.html)).  The browser (i.e., the JavaScript runtime) loads and links the generated modules when running the application.
+During development, a compilation step only needs to be rerun if the Dart files or summaries it relies upon change.  For most changes, only a very small part of your code will require recompilation.  Moreover, modules that are unchanged can be cached in the browser.
 
 Most users invoke DDC indirectly via [pub](https://webdev.dartlang.org/tools/pub/pub-serve).  Pub computes module structure and build steps automatically and invoke DDC accordingly.  Pub configures DDC to use AMD modules and uses the standard [AMD `require.js` loader](http://requirejs.org/) to bootstrap and load the application.
 
-More advanced users may want to configure or invoke DDC directly.  In general, the mapping of Dart files to JS modules is flexible.  The key requirement is that module dependences (i.e., `require` in AMD or CommonJS or `import` in ES6) must be acyclic.  In practice, this means that individual Dart libraries cannot each be mapped to a corresponding JS module (as Dart imports can be and often are cyclic).  See the [usage document](USAGE.md) for more details.
+More advanced users may want to configure or invoke DDC directly.  In general, the mapping of Dart files to JS modules is flexible.  The key requirement is that module dependencies (i.e., `require` in AMD or CommonJS or `import` in ES6) must be acyclic.  In practice, this means that individual Dart libraries cannot each be mapped to a corresponding JS module (as Dart imports can be and often are cyclic).  See the [usage document](USAGE.md) for more details.
 
 # EcmaScript 6
 
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index e6d3e29..e247077 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -1756,13 +1756,16 @@
     if (!mocks.containsKey(element.name + '=')) {
       var args = field.isFinal ? [JS.Super(), name] : [JS.This(), virtualField];
 
-      var setter = element.setter;
-      var covariantParams = _classProperties.covariantParameters;
       JS.Expression value = JS.Identifier('value');
-      if (setter != null &&
-          covariantParams != null &&
-          covariantParams.contains(setter.parameters[0])) {
-        value = _emitCast(setter.parameters[0].type, value);
+
+      var setter = element.setter;
+      if (setter != null) {
+        var covariantParams = _classProperties.covariantParameters;
+        var param = setter.parameters[0];
+        if (param.isCovariant ||
+            covariantParams != null && covariantParams.contains(param)) {
+          value = _emitCast(param.type, value);
+        }
       }
       args.add(value);
 
diff --git a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
index 2d2480c..62221b7 100644
--- a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
@@ -8,7 +8,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart'
-    show DartType, InterfaceType, ParameterizedType, FunctionType;
+    show DartType, InterfaceType, FunctionType;
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/constant.dart'
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 b51b297..a94f7f6 100644
--- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
+++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
@@ -478,7 +478,7 @@
     }
     t.typeParameters.addAll(typeParams.map(visitTypeParameterElement));
     setParents(t.typeParameters, t);
-    t.type = _visitDartType(type);
+    t.type = _visitDartType(type, originTypedef: t.thisType);
     _visitAnnotations(e.metadata, t.addAnnotation);
     return t;
   }
@@ -616,7 +616,8 @@
   /// populated with the node (creating it if needed). Many members on
   /// [InterfaceType] and [TypedefType] rely on having a node present, so this
   /// enables the use of those members if they're needed by the converter.
-  DartType _visitDartType(a.DartType type, {bool ensureNode = false}) {
+  DartType _visitDartType(a.DartType type,
+      {bool ensureNode = false, TypedefType originTypedef}) {
     if (type.isVoid) {
       return const VoidType();
     } else if (type.isDynamic) {
@@ -659,7 +660,8 @@
     return FunctionType(positional, visit(f.returnType),
         typeParameters: f.typeFormals.map(visitTypeParameterElement).toList(),
         namedParameters: named,
-        requiredParameterCount: params.where((p) => !p.isOptional).length);
+        requiredParameterCount: params.where((p) => !p.isOptional).length,
+        typedefType: originTypedef);
   }
 
   Supertype _typeToSupertype(a.InterfaceType t) {
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index 0d0dfa9..11958a0 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -217,8 +217,9 @@
   var target = compilerState.options.target as DevCompilerTarget;
   var compiler =
       ProgramCompiler(component, target.hierarchy, options, declaredVariables);
-  var jsModule =
-      compiler.emitModule(component, result.inputSummaries, summaryModules);
+
+  var jsModule = compiler.emitModule(component, result.inputSummaries,
+      compilerState.options.inputSummaries, summaryModules);
 
   // TODO(jmesserly): support for multiple output formats?
   //
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 5f5d60d..6351180 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -198,7 +198,7 @@
   factory ProgramCompiler(Component component, ClassHierarchy hierarchy,
       SharedCompilerOptions options, Map<String, String> declaredVariables) {
     var coreTypes = CoreTypes(component);
-    var types = TypeSchemaEnvironment(coreTypes, hierarchy, true);
+    var types = TypeSchemaEnvironment(coreTypes, hierarchy, false);
     var constants = DevCompilerConstants(types, declaredVariables);
     var nativeTypes = NativeTypeSet(coreTypes, constants);
     var jsTypeRep = JSTypeRep(types);
@@ -235,16 +235,15 @@
   bool get emitMetadata => options.emitMetadata;
 
   JS.Program emitModule(Component component, List<Component> summaries,
-      Map<Uri, String> summaryModules) {
+      List<Uri> summaryUris, Map<Uri, String> moduleImportForSummary) {
     if (moduleItems.isNotEmpty) {
       throw StateError('Can only call emitModule once.');
     }
     _component = component;
 
-    var moduleImports = summaryModules.values.toList();
     for (var i = 0; i < summaries.length; i++) {
       var summary = summaries[i];
-      var moduleImport = moduleImports[i];
+      var moduleImport = moduleImportForSummary[summaryUris[i]];
       for (var l in summary.libraries) {
         assert(!_importToSummary.containsKey(l));
         _importToSummary[l] = summary;
@@ -1370,12 +1369,12 @@
       return (member as Field).type;
     }
     FunctionType result;
-    if (!f.positionalParameters.any(isCovariant) &&
-        !f.namedParameters.any(isCovariant)) {
+    if (!f.positionalParameters.any(isCovariantParameter) &&
+        !f.namedParameters.any(isCovariantParameter)) {
       result = f.functionType;
     } else {
       reifyParameter(VariableDeclaration p) =>
-          isCovariant(p) ? coreTypes.objectClass.thisType : p.type;
+          isCovariantParameter(p) ? coreTypes.objectClass.thisType : p.type;
       reifyNamedParameter(VariableDeclaration p) =>
           NamedType(p.name, reifyParameter(p));
 
@@ -1772,9 +1771,10 @@
 
     var name = _declareMemberName(member);
     if (member.isSetter) {
-      if (superMember is Field && superMember.isGenericCovariantImpl ||
+      if (superMember is Field && isCovariantField(superMember) ||
           superMember is Procedure &&
-              isCovariant(superMember.function.positionalParameters[0])) {
+              isCovariantParameter(
+                  superMember.function.positionalParameters[0])) {
         return const [];
       }
       var setterType = substituteType(superMember.setterType);
@@ -1807,8 +1807,8 @@
       var jsParam = JS.Identifier(param.name);
       jsParams.add(jsParam);
 
-      if (isCovariant(param) &&
-          !isCovariant(superMember.function.positionalParameters[i])) {
+      if (isCovariantParameter(param) &&
+          !isCovariantParameter(superMember.function.positionalParameters[i])) {
         var check = _emitCast(jsParam, superMethodType.positionalParameters[i]);
         if (i >= function.requiredParameterCount) {
           body.add(js.statement('if (# !== void 0) #;', [jsParam, check]));
@@ -1819,8 +1819,8 @@
     }
     var namedParameters = function.namedParameters;
     for (var param in namedParameters) {
-      if (isCovariant(param) &&
-          !isCovariant(superMember.function.namedParameters
+      if (isCovariantParameter(param) &&
+          !isCovariantParameter(superMember.function.namedParameters
               .firstWhere((n) => n.name == param.name))) {
         var name = _propertyName(param.name);
         var paramType = superMethodType.namedParameters
@@ -1874,7 +1874,7 @@
     var args = field.isFinal ? [JS.Super(), name] : [JS.This(), virtualField];
 
     JS.Expression value = JS.Identifier('value');
-    if (!field.isFinal && field.isGenericCovariantImpl) {
+    if (!field.isFinal && isCovariantField(field)) {
       value = _emitCast(value, field.type);
     }
     args.add(value);
@@ -2884,7 +2884,7 @@
     _emitCovarianceBoundsCheck(f.typeParameters, body);
 
     initParameter(VariableDeclaration p, JS.Identifier jsParam) {
-      if (isCovariant(p)) {
+      if (isCovariantParameter(p)) {
         var castExpr = _emitCast(jsParam, p.type);
         if (!identical(castExpr, jsParam)) body.add(castExpr.toStatement());
       }
diff --git a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
index 945e41a..498bf51 100644
--- a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
+++ b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
@@ -170,10 +170,17 @@
     e.name.name == 'JS' &&
     e.enclosingLibrary.importUri.toString() == 'dart:_foreign_helper';
 
-// Check whether we have any covariant parameters.
-// Usually we don't, so we can use the same type.
-bool isCovariant(VariableDeclaration p) =>
-    p.isCovariant || p.isGenericCovariantImpl;
+/// Whether the parameter [p] is covariant (either explicitly `covariant` or
+/// implicitly due to generics) and needs a check for soundness.
+bool isCovariantParameter(VariableDeclaration p) {
+  return p.isCovariant || p.isGenericCovariantImpl;
+}
+
+/// Whether the field [p] is covariant (either explicitly `covariant` or
+/// implicitly due to generics) and needs a check for soundness.
+bool isCovariantField(Field f) {
+  return f.isCovariant || f.isGenericCovariantImpl;
+}
 
 /// Returns true iff this factory constructor just throws [UnsupportedError]/
 ///
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index f215ae7..8652983 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -2,11 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:collection';
 import 'dart:core' hide MapEntry;
 import 'package:kernel/kernel.dart';
 import 'package:kernel/core_types.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/target/targets.dart';
+import 'kernel_helpers.dart';
 
 /// A kernel [Target] to configure the Dart Front End for dartdevc.
 class DevCompilerTarget extends Target {
@@ -72,6 +74,9 @@
       CoreTypes coreTypes, ClassHierarchy hierarchy, List<Library> libraries,
       {void logger(String msg)}) {
     this.hierarchy = hierarchy;
+    for (var library in libraries) {
+      _CovarianceTransformer(library).transform();
+    }
   }
 
   @override
@@ -138,3 +143,184 @@
     return InvalidExpression(null);
   }
 }
+
+/// Analyzes a component to determine if any covariance checks in private
+/// members can be eliminated, and adjusts the flags to remove those checks.
+///
+/// See [_CovarianceTransformer.transform].
+class _CovarianceTransformer extends RecursiveVisitor<void> {
+  /// The set of private instance members in [_library] that (potentially) need
+  /// covariance checks.
+  ///
+  /// Members need checks if they are accessed through a receiver whose type is
+  /// not exactly known (i.e. the actual receiver could be a subtype of its
+  /// static type). If the receiver expression is `this`, `super` or non-factory
+  /// instance creation, it is known to have an exact type.
+  final _checkedMembers = HashSet<Member>();
+
+  /// List of private instance procedures.
+  ///
+  /// [transform] uses this list to eliminate covariance flags for members that
+  /// aren't in [_checkedMembers].
+  final _privateProcedures = List<Procedure>();
+
+  /// List of private instance fields.
+  ///
+  /// [transform] uses this list to eliminate covariance flags for members that
+  /// aren't in [_checkedMembers].
+  final _privateFields = List<Field>();
+
+  final Library _library;
+
+  _CovarianceTransformer(this._library);
+
+  /// Transforms [_library], eliminating unncessary checks for private members.
+  ///
+  /// Kernel will mark covariance checks on members, for example:
+  /// - a field with [Field.isGenericCovariantImpl] or [Field.isCovariant].
+  /// - a method/setter with parameter(s) or type parameter(s) that have
+  ///   `isGenericCovariantImpl` or `isCovariant` set.
+  ///
+  /// If the check can be safely eliminanted, those properties will be set to
+  /// false so the JS compiler does not emit checks.
+  ///
+  /// Public members always need covariance checks (we cannot see all potential
+  /// call sites), but in some cases we can eliminate these checks for private
+  /// members.
+  ///
+  /// Private members only need covariance checks if they are accessed through a
+  /// receiver whose type is not exactly known (i.e. the actual receiver could
+  /// be a subtype of its static type). If the receiver expression is `this`,
+  /// `super` or non-factory instance creation, it is known to have an exact
+  /// type, so no callee check is necessary to ensure soundness (normal
+  /// subtyping checks at the call site are sufficient).
+  ///
+  /// However to eliminate a check, we must know that all call sites are safe.
+  /// So the first pass is to collect any potentially-unsafe call sites, this
+  /// is done by [_checkTarget] and [_checkTearoff].
+  ///
+  /// Method tearoffs must also be marked potentially-unsafe, regardless of
+  /// whether the receiver type is known, because they could escape. Also their
+  /// runtime type must store `Object` in for covariant parameters (this
+  /// affects `is`, casts, and the `.runtimeType` property).
+  ///
+  /// Note 1: dynamic calls do not need to be considered here, because they
+  /// will be checked based on runtime type information.
+  ///
+  /// Node 2: public members in private classes cannot be treated as private
+  /// unless we know that the member is not exposed via some public interface
+  /// (implemented by their class or a subclass) that needs a covariance check.
+  /// That is somewhat complex to analyze, so for now we ignore it.
+  void transform() {
+    _library.visitChildren(this);
+
+    // Update the tree based on the methods that need checks.
+    for (var field in _privateFields) {
+      if (!_checkedMembers.contains(field)) {
+        field.isCovariant = false;
+        field.isGenericCovariantImpl = false;
+      }
+    }
+    void clearCovariant(VariableDeclaration parameter) {
+      parameter.isCovariant = false;
+      parameter.isGenericCovariantImpl = false;
+    }
+
+    for (var member in _privateProcedures) {
+      if (!_checkedMembers.contains(member)) {
+        var function = member.function;
+        function.positionalParameters.forEach(clearCovariant);
+        function.namedParameters.forEach(clearCovariant);
+        for (var t in function.typeParameters) {
+          t.isGenericCovariantImpl = false;
+        }
+      }
+    }
+  }
+
+  /// Checks if [target] is a private member called through a [receiver] that
+  /// will potentially need a covariance check.
+  ///
+  /// If the member needs a check it will be stored in [_checkedMembers].
+  ///
+  /// See [transform] for more information.
+  void _checkTarget(Expression receiver, Member target) {
+    if (target != null &&
+        target.name.isPrivate &&
+        target.isInstanceMember &&
+        receiver is! ThisExpression &&
+        receiver is! ConstructorInvocation) {
+      assert(target.enclosingLibrary == _library,
+          'call to private member must be in same library');
+      _checkedMembers.add(target);
+    }
+  }
+
+  /// Checks if [target] is a tearoff of a private member.
+  ///
+  /// In this case we will need a covariance check, because the method could
+  /// escape, and it also has a different runtime type.
+  ///
+  /// See [transform] for more information.
+  void _checkTearoff(Member target) {
+    if (target != null &&
+        target.name.isPrivate &&
+        target.isInstanceMember &&
+        target is Procedure &&
+        !target.isAccessor) {
+      assert(target.enclosingLibrary == _library,
+          'tearoff of private member must be in same library');
+      _checkedMembers.add(target);
+    }
+  }
+
+  @override
+  void visitProcedure(Procedure node) {
+    if (node.name.isPrivate && node.isInstanceMember && node.function != null) {
+      _privateProcedures.add(node);
+    }
+    super.visitProcedure(node);
+  }
+
+  @override
+  void visitField(Field node) {
+    if (node.name.isPrivate && isCovariantField(node)) _privateFields.add(node);
+    super.visitField(node);
+  }
+
+  @override
+  void visitPropertyGet(PropertyGet node) {
+    _checkTearoff(node.interfaceTarget);
+    super.visitPropertyGet(node);
+  }
+
+  @override
+  void visitDirectPropertyGet(DirectPropertyGet node) {
+    _checkTearoff(node.target);
+    super.visitDirectPropertyGet(node);
+  }
+
+  @override
+  void visitPropertySet(PropertySet node) {
+    _checkTarget(node.receiver, node.interfaceTarget);
+    super.visitPropertySet(node);
+  }
+
+  @override
+  void visitDirectPropertySet(DirectPropertySet node) {
+    _checkTarget(node.receiver, node.target);
+    super.visitDirectPropertySet(node);
+  }
+
+  @override
+  void visitMethodInvocation(MethodInvocation node) {
+    _checkTarget(node.receiver, node.interfaceTarget);
+    super.visitMethodInvocation(node);
+  }
+
+  @override
+  void visitDirectMethodInvocation(DirectMethodInvocation node) {
+    _checkTarget(node.receiver, node.target);
+    super.visitDirectMethodInvocation(node);
+  }
+}
diff --git a/pkg/dev_compiler/test/nullable_inference_test.dart b/pkg/dev_compiler/test/nullable_inference_test.dart
index f096c90..3a1c819 100644
--- a/pkg/dev_compiler/test/nullable_inference_test.dart
+++ b/pkg/dev_compiler/test/nullable_inference_test.dart
@@ -488,7 +488,7 @@
   @override
   visitComponent(Component node) {
     inference ??= NullableInference(JSTypeRep(
-      fe.TypeSchemaEnvironment(CoreTypes(node), ClassHierarchy(node), true),
+      fe.TypeSchemaEnvironment(CoreTypes(node), ClassHierarchy(node), false),
     ));
 
     if (useAnnotations) {
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/async_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/async_patch.dart
index ae23c11..62b34428 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/async_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/async_patch.dart
@@ -377,7 +377,6 @@
       iterResult = JS('', '#.next(#)', jsIterator, awaitValue);
     } catch (e, s) {
       addError(e, s);
-      close();
       return null;
     }
 
@@ -466,18 +465,17 @@
       // If the stream has been cancelled, complete the cancellation future
       // with the error.
       cancellationCompleter.completeError(error, stackTrace);
-      return;
+    } else if (controller.hasListener) {
+      controller.addError(error, stackTrace);
     }
-    // If stream is cancelled, tell caller to exit the async generator.
-    if (!controller.hasListener) return;
-    controller.addError(error, stackTrace);
     // No need to schedule the generator body here. This code is only
     // called from the catch clause of the implicit try-catch-finally
     // around the generator body. That is, we are on the error path out
     // of the generator and do not need to run the generator again.
+    close();
   }
 
-  close() {
+  void close() {
     if (cancellationCompleter != null && !cancellationCompleter.isCompleted) {
       // If the stream has been cancelled, complete the cancellation future
       // with the error.
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 f506a42..bfaf8ac 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
@@ -342,6 +342,26 @@
 
   @patch
   int get weekday => Primitives.getWeekday(this);
+
+  @patch
+  bool operator ==(dynamic other) =>
+      other is DateTime &&
+      _value == other.millisecondsSinceEpoch &&
+      isUtc == other.isUtc;
+
+  @patch
+  bool isBefore(DateTime other) => _value < other.millisecondsSinceEpoch;
+
+  @patch
+  bool isAfter(DateTime other) => _value > other.millisecondsSinceEpoch;
+
+  @patch
+  bool isAtSameMomentAs(DateTime other) =>
+      _value == other.millisecondsSinceEpoch;
+
+  @patch
+  int compareTo(DateTime other) =>
+      _value.compareTo(other.millisecondsSinceEpoch);
 }
 
 // Patch for Stopwatch implementation.
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 46eb700..9c7142d 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
@@ -432,9 +432,7 @@
   } else {
     result = t1 is FunctionType && t2 is FunctionType ||
         isSubtypeOf(t2, unwrapType(Iterable)) &&
-            isSubtypeOf(t1, unwrapType(Iterable)) ||
-        isSubtypeOf(t2, unwrapType(Future)) &&
-            isSubtypeOf(t1, unwrapType(Future));
+            isSubtypeOf(t1, unwrapType(Iterable));
     if (result) {
       _warn('Ignoring cast fail from ${typeName(t1)} to ${typeName(t2)}');
     }
diff --git a/pkg/dev_compiler/tool/kernel_sdk.dart b/pkg/dev_compiler/tool/kernel_sdk.dart
index bd401c2..feacbc7 100755
--- a/pkg/dev_compiler/tool/kernel_sdk.dart
+++ b/pkg/dev_compiler/tool/kernel_sdk.dart
@@ -56,7 +56,7 @@
       component,
       target.hierarchy,
       SharedCompilerOptions(moduleName: 'dart_sdk'),
-      {}).emitModule(component, [], {});
+      {}).emitModule(component, [], [], {});
   var moduleFormats = {
     'amd': ModuleFormat.amd,
     'common': ModuleFormat.common,
diff --git a/pkg/front_end/analysis_options.yaml b/pkg/front_end/analysis_options.yaml
index 39409d5..d5ea4fe 100644
--- a/pkg/front_end/analysis_options.yaml
+++ b/pkg/front_end/analysis_options.yaml
@@ -3,8 +3,6 @@
 # BSD-style license that can be found in the LICENSE file.
 
 analyzer:
-  language:
-    enableSuperMixins: false
   exclude:
     - testcases/**
   errors:
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index 5f2036e..24624f1 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -39,6 +39,8 @@
 
 export '../api_prototype/standard_file_system.dart' show DataFileSystemEntity;
 
+export '../base/libraries_specification.dart';
+
 export '../compute_platform_binaries_location.dart'
     show computePlatformBinariesLocation;
 
diff --git a/pkg/front_end/lib/src/api_unstable/vm.dart b/pkg/front_end/lib/src/api_unstable/vm.dart
index 710b58a..e9c843d 100644
--- a/pkg/front_end/lib/src/api_unstable/vm.dart
+++ b/pkg/front_end/lib/src/api_unstable/vm.dart
@@ -37,6 +37,7 @@
         messageConstEvalContext,
         messageConstEvalFailedAssertion,
         noLength,
+        templateConstEvalFreeTypeParameter,
         templateConstEvalDeferredLibrary,
         templateConstEvalDuplicateKey,
         templateConstEvalFailedAssertionWithMessage,
@@ -44,6 +45,7 @@
         templateConstEvalInvalidMethodInvocation,
         templateConstEvalInvalidStaticInvocation,
         templateConstEvalInvalidStringInterpolationOperand,
+        templateConstEvalInvalidSymbolName,
         templateConstEvalInvalidType,
         templateConstEvalNegativeShift,
         templateConstEvalNonConstantLiteral,
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 9858ea16..a1517be 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -103,16 +103,16 @@
   ///
   /// A summary, also referred to as "outline" internally, is a [Component]
   /// where all method bodies are left out. In essence, it contains just API
-  /// signatures and constants. When strong-mode is enabled, the summary
-  /// already includes inferred types.
+  /// signatures and constants. The summary should include inferred top-level
+  /// types unless legacy mode is enabled.
   Component _sdkSummaryComponent;
 
   /// The summary for each uri in `options.inputSummaries`.
   ///
   /// A summary, also referred to as "outline" internally, is a [Component]
   /// where all method bodies are left out. In essence, it contains just API
-  /// signatures and constants. When strong-mode is enabled, the summary
-  /// already includes inferred types.
+  /// signatures and constants. The summaries should include inferred top-level
+  /// types unless legacy mode is enabled.
   List<Component> _inputSummariesComponents;
 
   /// Other components that are meant to be linked and compiled with the input
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
index 355da1a..4671069 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
@@ -12,6 +12,7 @@
         DartType,
         DynamicType,
         Field,
+        FunctionType,
         Library,
         ListLiteral,
         Member,
@@ -131,8 +132,17 @@
   }
 
   void addTypedef(Typedef typedef) {
-    var typedefBuilder = new DillFunctionTypeAliasBuilder(typedef, this);
-    addBuilder(typedef.name, typedefBuilder, typedef.fileOffset);
+    DartType alias = typedef.type;
+    if (alias is FunctionType) {
+      if (alias.typedefType == null) {
+        unhandled("null", "addTypedef", typedef.fileOffset, typedef.fileUri);
+      }
+      addBuilder(typedef.name, new DillFunctionTypeAliasBuilder(typedef, this),
+          typedef.fileOffset);
+    } else {
+      unhandled("${alias.runtimeType}", "addTypedef", typedef.fileOffset,
+          typedef.fileUri);
+    }
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_typedef_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_typedef_builder.dart
index 63616f8..a395dca 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_typedef_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_typedef_builder.dart
@@ -4,7 +4,7 @@
 
 library fasta.dill_typedef_builder;
 
-import 'package:kernel/ast.dart' show DartType, FunctionType, Typedef;
+import 'package:kernel/ast.dart' show DartType, Typedef;
 
 import '../kernel/kernel_builder.dart'
     show
@@ -36,17 +36,7 @@
   }
 
   @override
-  DartType buildThisType(LibraryBuilder library) {
-    if (thisType != null) return thisType;
-
-    DartType targetType = target.type;
-    if (targetType is FunctionType) {
-      // TODO(34655):  The line below is a workaround.  Find the place where the
-      // reference is lost and fix it.
-      targetType.typedefReference = target.reference;
-    }
-    return thisType = targetType;
-  }
+  DartType buildThisType(LibraryBuilder library) => thisType ??= target.type;
 
   @override
   List<DartType> buildTypeArguments(
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 6769e5c..5e23ccb 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -1098,6 +1098,37 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
+        DartType
+            _type)> templateConstEvalFreeTypeParameter = const Template<
+        Message Function(DartType _type)>(
+    messageTemplate:
+        r"""The type '#type' is not a constant because it depends on a type parameter, only instantiated types are allowed.""",
+    withArguments: _withArgumentsConstEvalFreeTypeParameter);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type)> codeConstEvalFreeTypeParameter =
+    const Code<Message Function(DartType _type)>(
+  "ConstEvalFreeTypeParameter",
+  templateConstEvalFreeTypeParameter,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalFreeTypeParameter(DartType _type) {
+  NameSystem nameSystem = new NameSystem();
+  StringBuffer buffer;
+  buffer = new StringBuffer();
+  new Printer(buffer, syntheticNames: nameSystem).writeNode(_type);
+  String type = '$buffer';
+
+  return new Message(codeConstEvalFreeTypeParameter,
+      message:
+          """The type '${type}' is not a constant because it depends on a type parameter, only instantiated types are allowed.""",
+      arguments: {'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
         String string,
         Constant _constant,
         DartType _type,
@@ -1245,6 +1276,37 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
+        Constant
+            _constant)> templateConstEvalInvalidSymbolName = const Template<
+        Message Function(Constant _constant)>(
+    messageTemplate:
+        r"""The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '#constant'.""",
+    withArguments: _withArgumentsConstEvalInvalidSymbolName);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Constant _constant)>
+    codeConstEvalInvalidSymbolName =
+    const Code<Message Function(Constant _constant)>(
+        "ConstEvalInvalidSymbolName", templateConstEvalInvalidSymbolName,
+        analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalInvalidSymbolName(Constant _constant) {
+  NameSystem nameSystem = new NameSystem();
+  StringBuffer buffer;
+  buffer = new StringBuffer();
+  new Printer(buffer, syntheticNames: nameSystem).writeNode(_constant);
+  String constant = '$buffer';
+
+  return new Message(codeConstEvalInvalidSymbolName,
+      message:
+          """The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '${constant}'.""",
+      arguments: {'constant': _constant});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
         Constant _constant,
         DartType _type,
         DartType
@@ -4527,9 +4589,9 @@
             _type2)> templateInitializingFormalTypeMismatch = const Template<
         Message Function(String name, DartType _type, DartType _type2)>(
     messageTemplate:
-        r"""The type of parameter '#name' (#type) is not a subtype of the corresponding field's type (#type2).""",
+        r"""The type of parameter '#name', '#type' is not a subtype of the corresponding field's type, '#type2'.""",
     tipTemplate:
-        r"""Try changing the type of parameter '#name' to a subtype of #type2.""",
+        r"""Try changing the type of parameter '#name' to a subtype of '#type2'.""",
     withArguments: _withArgumentsInitializingFormalTypeMismatch);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4558,8 +4620,8 @@
 
   return new Message(codeInitializingFormalTypeMismatch,
       message:
-          """The type of parameter '${name}' (${type}) is not a subtype of the corresponding field's type (${type2}).""",
-      tip: """Try changing the type of parameter '${name}' to a subtype of ${type2}.""",
+          """The type of parameter '${name}', '${type}' is not a subtype of the corresponding field's type, '${type2}'.""",
+      tip: """Try changing the type of parameter '${name}' to a subtype of '${type2}'.""",
       arguments: {'name': name, 'type': _type, 'type2': _type2});
 }
 
@@ -4752,6 +4814,17 @@
         message: r"""Can't extend an unmodifiable scope.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInternalProblemLabelUsageInVariablesDeclaration =
+    messageInternalProblemLabelUsageInVariablesDeclaration;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInternalProblemLabelUsageInVariablesDeclaration =
+    const MessageCode("InternalProblemLabelUsageInVariablesDeclaration",
+        severity: Severity.internalProblem,
+        message:
+            r"""Unexpected usage of label inside declaration of variables.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeInternalProblemMissingContext =
     messageInternalProblemMissingContext;
 
@@ -4906,7 +4979,7 @@
     templateInternalProblemStoringMultipleInferredTypes =
     const Template<Message Function(DartType _type, String name)>(
         messageTemplate:
-            r"""There's already an inferred type (#type) for '#name'.""",
+            r"""There's already an inferred type, '#type', for '#name'.""",
         withArguments:
             _withArgumentsInternalProblemStoringMultipleInferredTypes);
 
@@ -4930,7 +5003,8 @@
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
   return new Message(codeInternalProblemStoringMultipleInferredTypes,
-      message: """There's already an inferred type (${type}) for '${name}'.""",
+      message:
+          """There's already an inferred type, '${type}', for '${name}'.""",
       arguments: {'type': _type, 'name': name});
 }
 
@@ -6797,9 +6871,9 @@
         Message Function(String name, String name2, DartType _type,
             DartType _type2)>(
     messageTemplate:
-        r"""The parameter '#name' of the method '#name2' has type #type, which does not match the corresponding type in the overridden method (#type2).""",
+        r"""The parameter '#name' of the method '#name2' has type '#type', which does not match the corresponding type in the overridden method, '#type2'.""",
     tipTemplate:
-        r"""Change to a supertype of #type2 (or, for a covariant parameter, a subtype).""",
+        r"""Change to a supertype of '#type2', or, for a covariant parameter, a subtype.""",
     withArguments: _withArgumentsOverrideTypeMismatchParameter);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6831,8 +6905,8 @@
 
   return new Message(codeOverrideTypeMismatchParameter,
       message:
-          """The parameter '${name}' of the method '${name2}' has type ${type}, which does not match the corresponding type in the overridden method (${type2}).""",
-      tip: """Change to a supertype of ${type2} (or, for a covariant parameter, a subtype).""",
+          """The parameter '${name}' of the method '${name2}' has type '${type}', which does not match the corresponding type in the overridden method, '${type2}'.""",
+      tip: """Change to a supertype of '${type2}', or, for a covariant parameter, a subtype.""",
       arguments: {
         'name': name,
         'name2': name2,
@@ -6850,8 +6924,8 @@
             _type2)> templateOverrideTypeMismatchReturnType = const Template<
         Message Function(String name, DartType _type, DartType _type2)>(
     messageTemplate:
-        r"""The return type of the method '#name' is #type, which does not match the return type of the overridden method (#type2).""",
-    tipTemplate: r"""Change to a subtype of #type2.""",
+        r"""The return type of the method '#name' is '#type', which does not match the return type of the overridden method, '#type2'.""",
+    tipTemplate: r"""Change to a subtype of '#type2'.""",
     withArguments: _withArgumentsOverrideTypeMismatchReturnType);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6879,8 +6953,8 @@
 
   return new Message(codeOverrideTypeMismatchReturnType,
       message:
-          """The return type of the method '${name}' is ${type}, which does not match the return type of the overridden method (${type2}).""",
-      tip: """Change to a subtype of ${type2}.""",
+          """The return type of the method '${name}' is '${type}', which does not match the return type of the overridden method, '${type2}'.""",
+      tip: """Change to a subtype of '${type2}'.""",
       arguments: {'name': name, 'type': _type, 'type2': _type2});
 }
 
@@ -7368,7 +7442,7 @@
     templateRedirectingFactoryInvalidNamedParameterType = const Template<
             Message Function(String name, DartType _type, DartType _type2)>(
         messageTemplate:
-            r"""The type of the named parameter '#name' (#type) is not a subtype of the redirection target's corresponding named parameter type (#type2).""",
+            r"""The type of the named parameter '#name', '#type' is not a subtype of the redirection target's corresponding named parameter type, '#type2'.""",
         tipTemplate:
             r"""Try changing either the type of the parameter or the redirection target.""",
         withArguments:
@@ -7399,7 +7473,7 @@
 
   return new Message(codeRedirectingFactoryInvalidNamedParameterType,
       message:
-          """The type of the named parameter '${name}' (${type}) is not a subtype of the redirection target's corresponding named parameter type (${type2}).""",
+          """The type of the named parameter '${name}', '${type}' is not a subtype of the redirection target's corresponding named parameter type, '${type2}'.""",
       tip: """Try changing either the type of the parameter or the redirection target.""",
       arguments: {'name': name, 'type': _type, 'type2': _type2});
 }
@@ -7409,7 +7483,7 @@
     templateRedirectingFactoryInvalidPositionalParameterType = const Template<
             Message Function(String name, DartType _type, DartType _type2)>(
         messageTemplate:
-            r"""The type of parameter '#name' (#type) is not a subtype of the redirection target's corresponding parameter type (#type2).""",
+            r"""The type of parameter '#name', '#type' is not a subtype of the redirection target's corresponding parameter type, '#type2'.""",
         tipTemplate:
             r"""Try changing either the type of the parameter or the redirection target.""",
         withArguments:
@@ -7440,7 +7514,7 @@
 
   return new Message(codeRedirectingFactoryInvalidPositionalParameterType,
       message:
-          """The type of parameter '${name}' (${type}) is not a subtype of the redirection target's corresponding parameter type (${type2}).""",
+          """The type of parameter '${name}', '${type}' is not a subtype of the redirection target's corresponding parameter type, '${type2}'.""",
       tip: """Try changing either the type of the parameter or the redirection target.""",
       arguments: {'name': name, 'type': _type, 'type2': _type2});
 }
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 090af34..3358be6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -31,7 +31,8 @@
         offsetForToken,
         optional;
 
-import '../problems.dart' show unexpected, unhandled, unsupported;
+import '../problems.dart'
+    show internalProblem, unexpected, unhandled, unsupported;
 
 import '../quote.dart'
     show
@@ -600,8 +601,12 @@
                       .desugared,
                   formal.charOffset);
             } else {
-              initializer = buildFieldInitializer(true, formal.name,
-                  formal.charOffset, new VariableGet(formal.declaration),
+              initializer = buildFieldInitializer(
+                  true,
+                  formal.name,
+                  formal.charOffset,
+                  formal.charOffset,
+                  new VariableGet(formal.declaration),
                   formalType: formal.declaration.type);
             }
             member.addInitializer(initializer, this);
@@ -714,17 +719,17 @@
     _typeInferrer.inferFunctionBody(
         this, _computeReturnTypeContext(member), asyncModifier, body);
 
-    // For async, async*, and sync* functions with declared return types, we need
-    // to determine whether those types are valid.
-    // TODO(hillerstrom): currently, we need to check whether [strongMode] is
+    // For async, async*, and sync* functions with declared return types, we
+    // need to determine whether those types are valid.
+    // TODO(hillerstrom): currently, we need to check whether [legacyMode] is
     // enabled for two reasons:
-    // 1) the [isSubtypeOf] predicate produces false-negatives when [strongMode]
-    // is false.
-    // 2) the member [typeEnvironment] might be null when [strongMode] is false.
+    // 1) the [isSubtypeOf] predicate produces false-negatives when
+    // [legacyMode] is enabled.
+    // 2) the member [typeEnvironment] might be null when [legacyMode] is
+    // enabled.
     // This particular behaviour can be observed when running the fasta perf
     // benchmarks.
-    bool strongMode = library.loader.target.strongMode;
-    if (strongMode && builder.returnType != null) {
+    if (!library.loader.target.legacyMode && builder.returnType != null) {
       DartType returnType = builder.function.returnType;
       // We use the same trick in each case below. For example to decide whether
       // Future<T> <: [returnType] for every T, we rely on Future<Bot> and
@@ -842,7 +847,7 @@
       Expression replacementNode;
 
       RedirectionTarget redirectionTarget = getRedirectionTarget(initialTarget,
-          strongMode: library.loader.target.strongMode);
+          legacyMode: library.loader.target.legacyMode);
       Member resolvedTarget = redirectionTarget?.target;
 
       if (resolvedTarget == null) {
@@ -1388,7 +1393,7 @@
             .withLocation(uri, charOffset, length);
       }
     }
-    if (!library.loader.target.strongMode &&
+    if (library.loader.target.legacyMode &&
         constantContext == ConstantContext.none) {
       addProblem(message.messageObject, message.charOffset, message.length,
           wasHandled: true, context: context);
@@ -1844,7 +1849,7 @@
   void handleLiteralInt(Token token) {
     debugEvent("LiteralInt");
     int value = int.tryParse(token.lexeme);
-    if (!library.loader.target.strongMode) {
+    if (library.loader.target.legacyMode) {
       if (value == null) {
         push(unhandled(
             'large integer', 'handleLiteralInt', token.charOffset, uri));
@@ -2148,6 +2153,22 @@
   }
 
   @override
+  void handleForInitializerEmptyStatement(Token token) {
+    debugEvent("ForInitializerEmptyStatement");
+    push(NullValue.Expression);
+  }
+
+  @override
+  void handleForInitializerExpressionStatement(Token token) {
+    debugEvent("ForInitializerExpressionStatement");
+  }
+
+  @override
+  void handleForInitializerLocalVariableDeclaration(Token token) {
+    debugEvent("ForInitializerLocalVariableDeclaration");
+  }
+
+  @override
   void endForStatement(Token forKeyword, Token leftParen, Token leftSeparator,
       int updateExpressionCount, Token endToken) {
     debugEvent("ForStatement");
@@ -2156,6 +2177,8 @@
     Statement conditionStatement = popStatement();
     Object variableOrExpression = pop();
 
+    // TODO(ahe): This can be simplified now that we have the events
+    // `handleForInitializer...` events.
     variableOrExpression = variableOrExpression is Generator
         ? variableOrExpression.buildForEffect()
         : variableOrExpression;
@@ -2229,7 +2252,7 @@
             lengthOfSpan(leftBracket, leftBracket.endGroup));
       } else {
         typeArgument = buildDartType(typeArguments.single);
-        if (library.loader.target.strongMode) {
+        if (!library.loader.target.legacyMode) {
           typeArgument =
               instantiateToBounds(typeArgument, coreTypes.objectClass);
         }
@@ -2285,7 +2308,7 @@
       } else {
         keyType = buildDartType(typeArguments[0]);
         valueType = buildDartType(typeArguments[1]);
-        if (library.loader.target.strongMode) {
+        if (!library.loader.target.legacyMode) {
           keyType = instantiateToBounds(keyType, coreTypes.objectClass);
           valueType = instantiateToBounds(valueType, coreTypes.objectClass);
         }
@@ -2829,12 +2852,6 @@
   }
 
   @override
-  void handleNoExpression(Token token) {
-    debugEvent("NoExpression");
-    push(NullValue.Expression);
-  }
-
-  @override
   void handleIndexedExpression(
       Token openSquareBracket, Token closeSquareBracket) {
     debugEvent("IndexedExpression");
@@ -3000,7 +3017,7 @@
       int charLength: noLength}) {
     // The argument checks for the initial target of redirecting factories
     // invocations are skipped in Dart 1.
-    if (library.loader.target.strongMode || !isRedirectingFactory(target)) {
+    if (!library.loader.target.legacyMode || !isRedirectingFactory(target)) {
       List<TypeParameter> typeParameters = target.function.typeParameters;
       if (target is Constructor) {
         assert(!target.enclosingClass.isAbstract);
@@ -3102,9 +3119,8 @@
     if (typeParameters.length != types.length) {
       if (types.length == 0) {
         // Expected `typeParameters.length` type arguments, but none given, so
-        // we fill in dynamic in legacy mode, and use type inference in strong
-        // mode.
-        if (!library.loader.target.strongMode) {
+        // we fill in dynamic in legacy mode, and use type inference otherwise.
+        if (library.loader.target.legacyMode) {
           for (int i = 0; i < typeParameters.length; i++) {
             types.add(const DynamicType());
           }
@@ -3302,11 +3318,11 @@
           (target is Procedure && target.kind == ProcedureKind.Factory)) {
         Expression invocation;
 
-        if (!library.loader.target.strongMode && isRedirectingFactory(target)) {
-          // In non-strong mode the checks that are done in
-          // [buildStaticInvocation] on the initial target of a redirecting
-          // factory invocation should be skipped.  So, we build the invocation
-          // nodes directly here without doing any checks.
+        if (library.loader.target.legacyMode && isRedirectingFactory(target)) {
+          // In legacy mode the checks that are done in [buildStaticInvocation]
+          // on the initial target of a redirecting factory invocation should
+          // be skipped. So we build the invocation nodes directly here without
+          // doing any checks.
           if (target.function.typeParameters != null &&
               target.function.typeParameters.length !=
                   forest.argumentsTypeArguments(arguments).length) {
@@ -3706,20 +3722,20 @@
   @override
   void endLabeledStatement(int labelCount) {
     debugEvent("LabeledStatement");
-    Statement statement = popStatement();
+    Statement statement = pop();
     LabelTarget target = pop();
     exitLocalScope();
-    if (target.breakTarget.hasUsers) {
+    if (target.breakTarget.hasUsers || target.continueTarget.hasUsers) {
+      if (forest.isVariablesDeclaration(statement)) {
+        internalProblem(
+            fasta.messageInternalProblemLabelUsageInVariablesDeclaration,
+            statement.fileOffset,
+            uri);
+      }
       if (statement is! LabeledStatement) {
-        statement = forest.syntheticLabeledStatement(statement);
+        statement = new LabeledStatementJudgment(statement);
       }
       target.breakTarget.resolveBreaks(forest, statement);
-    }
-    statement = forest.labeledStatement(target, statement);
-    if (target.continueTarget.hasUsers) {
-      if (statement is! LabeledStatement) {
-        statement = forest.syntheticLabeledStatement(statement);
-      }
       target.continueTarget.resolveContinues(forest, statement);
     }
     push(statement);
@@ -4116,7 +4132,7 @@
     // Peek to leave type parameters on top of stack.
     List<KernelTypeVariableBuilder> typeVariables = peek();
 
-    if (library.loader.target.strongMode) {
+    if (!library.loader.target.legacyMode) {
       List<KernelTypeBuilder> calculatedBounds = calculateBounds(
           typeVariables,
           library.loader.target.dynamicType,
@@ -4190,7 +4206,7 @@
     Severity severity = message.code.severity;
     if (severity == Severity.error ||
         severity == Severity.errorLegacyWarning &&
-            library.loader.target.strongMode) {
+            !library.loader.target.legacyMode) {
       return wrapInLocatedProblem(
           expression, message.withLocation(uri, charOffset, length),
           context: context);
@@ -4318,30 +4334,41 @@
   /// immediately enclosing class.  It is a static warning if the static type of
   /// _id_ is not a subtype of _Tid_."
   @override
-  Initializer buildFieldInitializer(
-      bool isSynthetic, String name, int offset, Expression expression,
+  Initializer buildFieldInitializer(bool isSynthetic, String name,
+      int fieldNameOffset, int assignmentOffset, Expression expression,
       {DartType formalType}) {
     Declaration builder =
         classBuilder.scope.local[name] ?? classBuilder.origin.scope.local[name];
-    if (builder is KernelFieldBuilder && builder.isInstanceMember) {
+    if (builder?.next != null) {
+      // Duplicated name, already reported.
+      return new LocalInitializer(
+          new VariableDeclaration.forValue(
+              buildProblem(
+                      fasta.templateDuplicatedDeclarationUse
+                          .withArguments(name),
+                      fieldNameOffset,
+                      name.length)
+                  .desugared
+                ..fileOffset = fieldNameOffset)
+            ..fileOffset = fieldNameOffset)
+        ..fileOffset = fieldNameOffset;
+    } else if (builder is KernelFieldBuilder && builder.isInstanceMember) {
       initializedFields ??= <String, int>{};
       if (initializedFields.containsKey(name)) {
-        return buildDuplicatedInitializer(
-            builder.field, expression, name, offset, initializedFields[name]);
+        return buildDuplicatedInitializer(builder.field, expression, name,
+            assignmentOffset, initializedFields[name]);
       }
-      initializedFields[name] = offset;
+      initializedFields[name] = assignmentOffset;
       if (builder.isFinal && builder.hasInitializer) {
-        // TODO(ahe): If CL 2843733002 is landed, this becomes a compile-time
-        // error. Also, this is a compile-time error in strong mode.
         addProblem(
             fasta.templateFinalInstanceVariableAlreadyInitialized
                 .withArguments(name),
-            offset,
+            assignmentOffset,
             noLength,
             context: [
               fasta.templateFinalInstanceVariableAlreadyInitializedCause
                   .withArguments(name)
-                  .withLocation(uri, builder.charOffset, noLength)
+                  .withLocation(uri, builder.charOffset, name.length)
             ]);
         Declaration constructor =
             library.loader.getDuplicatedFieldInitializerError();
@@ -4353,20 +4380,21 @@
                 buildStaticInvocation(
                     constructor.target,
                     forest.arguments(<Expression>[
-                      forest.literalString(name, null)..fileOffset = offset
+                      forest.literalString(name, null)
+                        ..fileOffset = assignmentOffset
                     ], noLocation)
-                      ..fileOffset = offset,
-                    charOffset: offset))
-              ..fileOffset = offset))
-          ..fileOffset = offset;
+                      ..fileOffset = assignmentOffset,
+                    charOffset: assignmentOffset))
+              ..fileOffset = assignmentOffset))
+          ..fileOffset = assignmentOffset;
       } else {
-        if (library.loader.target.strongMode &&
+        if (!library.loader.target.legacyMode &&
             formalType != null &&
             !typeEnvironment.isSubtypeOf(formalType, builder.field.type)) {
           library.addProblem(
               fasta.templateInitializingFormalTypeMismatch
                   .withArguments(name, formalType, builder.field.type),
-              offset,
+              assignmentOffset,
               noLength,
               uri,
               context: [
@@ -4375,17 +4403,17 @@
               ]);
         }
         return new ShadowFieldInitializer(builder.field, expression)
-          ..fileOffset = offset
+          ..fileOffset = assignmentOffset
           ..isSynthetic = isSynthetic;
       }
     } else {
       return buildInvalidInitializer(
           buildProblem(
                   fasta.templateInitializerForStaticField.withArguments(name),
-                  offset,
+                  fieldNameOffset,
                   name.length)
               .desugared,
-          offset);
+          fieldNameOffset);
     }
   }
 
@@ -4473,7 +4501,7 @@
             typeParameter.name.length);
         if (!nonInstanceAccessIsError &&
             !isConstant &&
-            !library.loader.target.strongMode) {
+            library.loader.target.legacyMode) {
           // This is a warning in legacy mode.
           addProblem(message.messageObject, message.charOffset, message.length);
           suppressMessage = true;
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 3621504..b3c0434 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -976,8 +976,8 @@
         !generator.isThisPropertyAccess) {
       return generator.buildFieldInitializer(initializedFields);
     }
-    return helper.buildFieldInitializer(
-        false, generator.plainNameForRead, offsetForToken(token), value);
+    return helper.buildFieldInitializer(false, generator.plainNameForRead,
+        offsetForToken(generator.token), offsetForToken(token), value);
   }
 }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
index 095ae58..61e8b57 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
@@ -70,8 +70,8 @@
 
   Initializer buildInvalidInitializer(Expression expression, [int offset]);
 
-  Initializer buildFieldInitializer(
-      bool isSynthetic, String name, int offset, Expression expression,
+  Initializer buildFieldInitializer(bool isSynthetic, String name,
+      int fieldNameOffset, int assignmentOffset, Expression expression,
       {DartType formalType});
 
   Initializer buildSuperInitializer(
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 7aaef01..3b44e55 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -91,7 +91,7 @@
   void visitCascadeJudgment(CascadeJudgment node, DartType typeContext) {
     node.inferredType =
         inferrer.inferExpression(node.targetJudgment, typeContext, true);
-    if (inferrer.strongMode) {
+    if (!inferrer.legacyMode) {
       node.variable.type = getInferredType(node, inferrer);
     }
     for (var judgment in node.cascadeJudgments) {
@@ -120,7 +120,7 @@
     DartType inferredType = inferrer.typeSchemaEnvironment
         .getStandardUpperBound(getInferredType(then, inferrer),
             getInferredType(otherwise, inferrer));
-    if (inferrer.strongMode) {
+    if (!inferrer.legacyMode) {
       node.staticType = inferredType;
     }
   }
@@ -259,7 +259,7 @@
     DartType syntheticWriteType;
     if (node._declaresVariable) {
       variable = node.variableJudgment;
-      if (inferrer.strongMode && variable._implicitlyTyped) {
+      if (!inferrer.legacyMode && variable._implicitlyTyped) {
         typeNeeded = true;
         context = const UnknownType();
       } else {
@@ -389,7 +389,7 @@
   void visitFunctionDeclarationJudgment(FunctionDeclarationJudgment node) {
     inferrer.inferMetadataKeepingHelper(node.variable.annotations);
     DartType returnContext = node._hasImplicitReturnType
-        ? (inferrer.strongMode ? null : const DynamicType())
+        ? (inferrer.legacyMode ? const DynamicType() : null)
         : node.function.returnType;
     var inferenceResult = visitFunctionNodeJudgment(
         node.functionJudgment, null, returnContext, node.fileOffset);
@@ -425,7 +425,7 @@
     // - Infer e0 in context K to get T0
     inferrer.inferExpression(leftJudgment, typeContext, true);
     var lhsType = getInferredType(leftJudgment, inferrer);
-    if (inferrer.strongMode) {
+    if (!inferrer.legacyMode) {
       node.variable.type = lhsType;
     }
     // - Let J = T0 if K is `?` else K.
@@ -443,7 +443,7 @@
     // - Then the inferred type is T.
     node.inferredType =
         inferrer.typeSchemaEnvironment.getStandardUpperBound(lhsType, rhsType);
-    if (inferrer.strongMode) {
+    if (!inferrer.legacyMode) {
       node.body.staticType = getInferredType(node, inferrer);
     }
     return null;
@@ -625,7 +625,7 @@
     List<DartType> formalTypes;
     List<DartType> actualTypes;
     bool inferenceNeeded =
-        node._declaredTypeArgument == null && inferrer.strongMode;
+        node._declaredTypeArgument == null && !inferrer.legacyMode;
     bool typeChecksNeeded = !inferrer.isTopLevel;
     if (inferenceNeeded || typeChecksNeeded) {
       formalTypes = [];
@@ -725,7 +725,8 @@
     List<DartType> actualTypes;
     assert(
         (node._declaredKeyType == null) == (node._declaredValueType == null));
-    bool inferenceNeeded = node._declaredKeyType == null && inferrer.strongMode;
+    bool inferenceNeeded =
+        node._declaredKeyType == null && !inferrer.legacyMode;
     bool typeChecksNeeded = !inferrer.isTopLevel;
     if (inferenceNeeded || typeChecksNeeded) {
       formalTypes = [];
@@ -887,7 +888,7 @@
     Expression initializer = node.variableJudgment.initializer;
     inferrer.inferExpression(initializer, typeContext, true);
     node.inferredType = getInferredType(initializer, inferrer);
-    if (inferrer.strongMode) node.variable.type = node.inferredType;
+    if (!inferrer.legacyMode) node.variable.type = node.inferredType;
     return null;
   }
 
@@ -907,7 +908,7 @@
         receiverVariable: node.variable,
         desugaredInvocation: node._desugaredInvocation);
     node.inferredType = inferenceResult.type;
-    if (inferrer.strongMode) {
+    if (!inferrer.legacyMode) {
       node.body.staticType = node.inferredType;
     }
     return null;
@@ -918,7 +919,7 @@
     inferrer.inferPropertyGet(
         node, node.receiverJudgment, node.fileOffset, typeContext,
         receiverVariable: node.variable, desugaredGet: node._desugaredGet);
-    if (inferrer.strongMode) {
+    if (!inferrer.legacyMode) {
       node.body.staticType = node.inferredType;
     }
     return null;
@@ -969,7 +970,7 @@
     // doing compound assignment?
     var writeContext = inferrer.getSetterType(writeMember, receiverType);
     node._inferRhs(inferrer, readType, writeContext);
-    if (inferrer.strongMode)
+    if (!inferrer.legacyMode)
       node.nullAwareGuard?.staticType = node.inferredType;
     node._replaceWithDesugared();
     return null;
@@ -1297,7 +1298,7 @@
     } else {
       inferredType = const DynamicType();
     }
-    if (inferrer.strongMode && node._implicitlyTyped) {
+    if (!inferrer.legacyMode && node._implicitlyTyped) {
       inferrer.instrumentation?.record(inferrer.uri, node.fileOffset, 'type',
           new InstrumentationValueForType(inferredType));
       node.type = inferredType;
diff --git a/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart
index 2c23370..9a49c47 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart
@@ -73,7 +73,7 @@
   @override
   DartType visitConditionalExpression(
       ConditionalExpression node, TypeInferrerImpl inferrer) {
-    return inferrer.strongMode ? node.staticType : const DynamicType();
+    return inferrer.legacyMode ? const DynamicType() : node.staticType;
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
index c66a5e6..7e7ddca 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
@@ -42,6 +42,7 @@
         LibraryDependency,
         LibraryPart,
         ListLiteral,
+        LocalInitializer,
         Location,
         MapEntry,
         MapLiteral,
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 56bc3b2..6e5e7a4 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
@@ -41,6 +41,9 @@
 
 import 'package:kernel/core_types.dart' show CoreTypes;
 
+import 'package:kernel/src/bounds_checks.dart'
+    show TypeArgumentIssue, findTypeArgumentIssues, getGenericTypeName;
+
 import 'package:kernel/type_algebra.dart' show Substitution, substitute;
 
 import 'package:kernel/type_algebra.dart' as type_algebra
@@ -288,17 +291,15 @@
       Supertype supertype, TypeEnvironment typeEnvironment) {
     KernelLibraryBuilder library = this.library;
 
-    List<Object> boundViolations = typeEnvironment.findBoundViolations(
+    List<TypeArgumentIssue> issues = findTypeArgumentIssues(
         new InterfaceType(supertype.classNode, supertype.typeArguments),
-        allowSuperBounded: false,
-        typedefInstantiations: library.typedefInstantiations);
-    if (boundViolations != null) {
-      for (int i = 0; i < boundViolations.length; i += 3) {
-        DartType argument = boundViolations[i];
-        TypeParameter variable = boundViolations[i + 1];
-        DartType enclosingType = boundViolations[i + 2];
-
+        typeEnvironment,
+        allowSuperBounded: false);
+    if (issues != null) {
+      for (TypeArgumentIssue issue in issues) {
         Message message;
+        DartType argument = issue.argument;
+        TypeParameter typeParameter = issue.typeParameter;
         bool inferred = library.inferredTypes.contains(argument);
         if (argument is FunctionType && argument.typeParameters.length > 0) {
           if (inferred) {
@@ -307,25 +308,25 @@
           } else {
             message = messageGenericFunctionTypeUsedAsActualTypeArgument;
           }
-          variable = null;
+          typeParameter = null;
         } else {
           if (inferred) {
             message =
                 templateIncorrectTypeArgumentInSupertypeInferred.withArguments(
                     argument,
-                    typeEnvironment.getGenericTypeName(enclosingType),
+                    getGenericTypeName(issue.enclosingType),
                     supertype.classNode.name,
                     name);
           } else {
             message = templateIncorrectTypeArgumentInSupertype.withArguments(
                 argument,
-                typeEnvironment.getGenericTypeName(enclosingType),
+                getGenericTypeName(issue.enclosingType),
                 supertype.classNode.name,
                 name);
           }
         }
 
-        library.reportBoundViolation(message, charOffset, variable);
+        library.reportTypeArgumentIssues(message, charOffset, typeParameter);
       }
     }
   }
@@ -335,15 +336,13 @@
 
     // Check in bounds of own type variables.
     for (TypeParameter parameter in cls.typeParameters) {
-      List<Object> violations = typeEnvironment.findBoundViolations(
-          parameter.bound,
-          allowSuperBounded: false,
-          typedefInstantiations: library.typedefInstantiations);
-      if (violations != null) {
-        for (int i = 0; i < violations.length; i += 3) {
-          DartType argument = violations[i];
-          TypeParameter variable = violations[i + 1];
-          DartType enclosingType = violations[i + 2];
+      List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+          parameter.bound, typeEnvironment,
+          allowSuperBounded: false);
+      if (issues != null) {
+        for (TypeArgumentIssue issue in issues) {
+          DartType argument = issue.argument;
+          TypeParameter typeParameter = issue.typeParameter;
           if (library.inferredTypes.contains(argument)) {
             // Inference in type expressions in the supertypes boils down to
             // instantiate-to-bound which shouldn't produce anything that breaks
@@ -356,13 +355,14 @@
           Message message;
           if (argument is FunctionType && argument.typeParameters.length > 0) {
             message = messageGenericFunctionTypeUsedAsActualTypeArgument;
-            variable = null;
+            typeParameter = null;
           } else {
             message = templateIncorrectTypeArgument.withArguments(
-                argument, typeEnvironment.getGenericTypeName(enclosingType));
+                argument, getGenericTypeName(issue.enclosingType));
           }
 
-          library.reportBoundViolation(message, parameter.fileOffset, variable);
+          library.reportTypeArgumentIssues(
+              message, parameter.fileOffset, typeParameter);
         }
       }
     }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart
index de60d54..1e174f4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart
@@ -34,6 +34,8 @@
         MetadataBuilder,
         TypeVariableBuilder;
 
+final InvalidType cyclicTypeAliasMarker = new InvalidType();
+
 class KernelFunctionTypeAliasBuilder
     extends FunctionTypeAliasBuilder<KernelFunctionTypeBuilder, DartType> {
   final Typedef target;
@@ -49,7 +51,11 @@
       int charOffset,
       [Typedef target])
       : target = target ??
-            (new Typedef(name, null, fileUri: parent.target.fileUri)
+            (new Typedef(name, null,
+                typeParameters:
+                    KernelTypeVariableBuilder.kernelTypeParametersFromBuilders(
+                        typeVariables),
+                fileUri: parent.target.fileUri)
               ..fileOffset = charOffset),
         super(metadata, name, typeVariables, type, parent, charOffset);
 
@@ -86,27 +92,28 @@
 
   DartType buildThisType(LibraryBuilder library) {
     if (thisType != null) {
-      if (const InvalidType() == thisType) {
+      if (identical(thisType, cyclicTypeAliasMarker)) {
         library.addProblem(templateCyclicTypedef.withArguments(name),
             charOffset, noLength, fileUri);
-        return const DynamicType();
+        return const InvalidType();
       }
       return thisType;
     }
-    thisType = const InvalidType();
-    FunctionType builtType = type?.build(library);
+    // It is a compile-time error for an alias (typedef) to refer to itself. We
+    // detect cycles by detecting recursive calls to this method using an
+    // instance of InvalidType that isn't identical to `const InvalidType()`.
+    thisType = cyclicTypeAliasMarker;
+    FunctionType builtType = type?.build(library, target.thisType);
     if (builtType != null) {
-      builtType.typedefReference = target.reference;
       if (typeVariables != null) {
         for (KernelTypeVariableBuilder tv in typeVariables) {
           // Follow bound in order to find all cycles
           tv.bound?.build(library);
-          target.typeParameters.add(tv.parameter..parent = target);
         }
       }
       return thisType = builtType;
     } else {
-      return thisType = const DynamicType();
+      return thisType = const InvalidType();
     }
   }
 
@@ -121,11 +128,7 @@
     for (int i = 0; i < target.typeParameters.length; i++) {
       substitution[target.typeParameters[i]] = arguments[i];
     }
-    result = substitute(result, substitution);
-    if (library is KernelLibraryBuilder) {
-      library.typedefInstantiations[result] = arguments;
-    }
-    return result;
+    return substitute(result, substitution);
   }
 
   List<DartType> buildTypeArguments(
@@ -174,7 +177,7 @@
   DartType buildType(
       LibraryBuilder library, List<KernelTypeBuilder> arguments) {
     var thisType = buildThisType(library);
-    if (thisType is DynamicType) return thisType;
+    if (thisType is InvalidType) return thisType;
     FunctionType result = thisType;
     if (target.typeParameters.isEmpty && arguments == null) return result;
     // Otherwise, substitute.
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart
index 5b67a52..edebe4a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart
@@ -11,7 +11,8 @@
         FunctionType,
         NamedType,
         Supertype,
-        TypeParameter;
+        TypeParameter,
+        TypedefType;
 
 import '../fasta_codes.dart'
     show LocatedMessage, messageSupertypeIsFunction, noLength;
@@ -37,7 +38,7 @@
       List<FormalParameterBuilder> formals)
       : super(returnType, typeVariables, formals);
 
-  FunctionType build(LibraryBuilder library) {
+  FunctionType build(LibraryBuilder library, [TypedefType origin]) {
     DartType builtReturnType =
         returnType?.build(library) ?? const DynamicType();
     List<DartType> positionalParameters = <DartType>[];
@@ -68,7 +69,8 @@
     return new FunctionType(positionalParameters, builtReturnType,
         namedParameters: namedParameters ?? const <NamedType>[],
         typeParameters: typeParameters ?? const <TypeParameter>[],
-        requiredParameterCount: requiredParameterCount);
+        requiredParameterCount: requiredParameterCount,
+        typedefType: origin);
   }
 
   Supertype buildSupertype(
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 982bed4..ffd5b41 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
@@ -39,6 +39,13 @@
 
 import 'package:kernel/clone.dart' show CloneVisitor;
 
+import 'package:kernel/src/bounds_checks.dart'
+    show
+        TypeArgumentIssue,
+        findTypeArgumentIssues,
+        findTypeArgumentIssuesForInvocation,
+        getGenericTypeName;
+
 import 'package:kernel/type_algebra.dart' show substitute;
 
 import 'package:kernel/type_environment.dart' show TypeEnvironment;
@@ -168,12 +175,6 @@
   // TODO(dmitryas):  Find a way to mark inferred types.
   final Set<DartType> inferredTypes = new Set<DartType>.identity();
 
-  // List of typedef instantiations built for this library.  They are needed to
-  // perform type argument checks.
-  // TODO(dmitryas):  Find a way to keep type arguments of typedefs around.
-  final Map<FunctionType, List<DartType>> typedefInstantiations =
-      new Map<FunctionType, List<DartType>>.identity();
-
   /// Exports that can't be serialized.
   ///
   /// The key is the name of the exported member.
@@ -1162,11 +1163,11 @@
 
     int computeDefaultTypesForVariables(
         List<TypeVariableBuilder<TypeBuilder, Object>> variables,
-        bool strongMode) {
+        bool legacyMode) {
       if (variables == null) return 0;
 
       bool haveErroneousBounds = false;
-      if (strongMode) {
+      if (!legacyMode) {
         for (int i = 0; i < variables.length; ++i) {
           TypeVariableBuilder<TypeBuilder, Object> variable = variables[i];
           List<TypeBuilder> genericFunctionTypes = <TypeBuilder>[];
@@ -1188,7 +1189,7 @@
         }
       }
 
-      if (!strongMode || haveErroneousBounds) {
+      if (legacyMode || haveErroneousBounds) {
         // In Dart 1, put `dynamic` everywhere.
         for (int i = 0; i < variables.length; ++i) {
           variables[i].defaultType = dynamicType;
@@ -1210,47 +1211,47 @@
       }
     }
 
-    bool strongMode = loader.target.strongMode;
+    bool legacyMode = loader.target.legacyMode;
     for (var declaration in libraryDeclaration.members.values) {
       if (declaration is KernelClassBuilder) {
         {
-          List<Object> issues = strongMode
-              ? getNonSimplicityIssuesForDeclaration(declaration,
-                  performErrorRecovery: true)
-              : const <Object>[];
+          List<Object> issues = legacyMode
+              ? const <Object>[]
+              : getNonSimplicityIssuesForDeclaration(declaration,
+                  performErrorRecovery: true);
           reportIssues(issues);
-          // In case of issues, use non-strong mode for error recovery.
+          // In case of issues, use legacy mode for error recovery.
           count += computeDefaultTypesForVariables(
-              declaration.typeVariables, strongMode && issues.length == 0);
+              declaration.typeVariables, legacyMode || issues.isNotEmpty);
         }
         declaration.forEach((String name, Declaration member) {
           if (member is KernelProcedureBuilder) {
-            List<Object> issues = strongMode
-                ? getNonSimplicityIssuesForTypeVariables(member.typeVariables)
-                : const <Object>[];
+            List<Object> issues = legacyMode
+                ? const <Object>[]
+                : getNonSimplicityIssuesForTypeVariables(member.typeVariables);
             reportIssues(issues);
-            // In case of issues, use non-strong mode for error recovery.
+            // In case of issues, use legacy mode for error recovery.
             count += computeDefaultTypesForVariables(
-                member.typeVariables, strongMode && issues.length == 0);
+                member.typeVariables, legacyMode || issues.isNotEmpty);
           }
         });
       } else if (declaration is KernelFunctionTypeAliasBuilder) {
-        List<Object> issues = strongMode
-            ? getNonSimplicityIssuesForDeclaration(declaration,
-                performErrorRecovery: true)
-            : const <Object>[];
+        List<Object> issues = legacyMode
+            ? const <Object>[]
+            : getNonSimplicityIssuesForDeclaration(declaration,
+                performErrorRecovery: true);
         reportIssues(issues);
-        // In case of issues, use non-strong mode for error recovery.
+        // In case of issues, use legacy mode for error recovery.
         count += computeDefaultTypesForVariables(
-            declaration.typeVariables, strongMode && issues.length == 0);
+            declaration.typeVariables, legacyMode || issues.isNotEmpty);
       } else if (declaration is KernelFunctionBuilder) {
-        List<Object> issues = strongMode
-            ? getNonSimplicityIssuesForTypeVariables(declaration.typeVariables)
-            : const <Object>[];
+        List<Object> issues = legacyMode
+            ? const <Object>[]
+            : getNonSimplicityIssuesForTypeVariables(declaration.typeVariables);
         reportIssues(issues);
-        // In case of issues, use non-strong mode for error recovery.
+        // In case of issues, use legacy mode for error recovery.
         count += computeDefaultTypesForVariables(
-            declaration.typeVariables, strongMode && issues.length == 0);
+            declaration.typeVariables, legacyMode || issues.isNotEmpty);
       }
     }
 
@@ -1358,31 +1359,29 @@
     addToExportScope(name, member);
   }
 
-  void reportBoundViolation(
-      Message message, int fileOffset, TypeParameter violated) {
+  void reportTypeArgumentIssues(
+      Message message, int fileOffset, TypeParameter typeParameter) {
     List<LocatedMessage> context;
-    if (violated != null && violated.fileOffset != -1) {
+    if (typeParameter != null && typeParameter.fileOffset != -1) {
       // It looks like when parameters come from patch files, they don't
       // have a reportable location.
       context = <LocatedMessage>[
         messageIncorrectTypeArgumentVariable.withLocation(
-            violated.location.file, violated.fileOffset, noLength)
+            typeParameter.location.file, typeParameter.fileOffset, noLength)
       ];
     }
     addProblem(message, fileOffset, noLength, fileUri, context: context);
   }
 
   void checkBoundsInField(Field field, TypeEnvironment typeEnvironment) {
-    if (!loader.target.strongMode) return;
-    List<Object> boundViolations = typeEnvironment.findBoundViolations(
-        field.type,
-        allowSuperBounded: true,
-        typedefInstantiations: typedefInstantiations);
-    if (boundViolations != null) {
-      for (int i = 0; i < boundViolations.length; i += 3) {
-        DartType argument = boundViolations[i];
-        TypeParameter variable = boundViolations[i + 1];
-        DartType enclosingType = boundViolations[i + 2];
+    if (loader.target.legacyMode) return;
+    List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+        field.type, typeEnvironment,
+        allowSuperBounded: true);
+    if (issues != null) {
+      for (TypeArgumentIssue issue in issues) {
+        DartType argument = issue.argument;
+        TypeParameter typeParameter = issue.typeParameter;
 
         Message message;
         bool inferred = inferredTypes.contains(argument);
@@ -1393,18 +1392,18 @@
           } else {
             message = messageGenericFunctionTypeUsedAsActualTypeArgument;
           }
-          variable = null;
+          typeParameter = null;
         } else {
           if (inferred) {
             message = templateIncorrectTypeArgumentInferred.withArguments(
-                argument, typeEnvironment.getGenericTypeName(enclosingType));
+                argument, getGenericTypeName(issue.enclosingType));
           } else {
             message = templateIncorrectTypeArgument.withArguments(
-                argument, typeEnvironment.getGenericTypeName(enclosingType));
+                argument, getGenericTypeName(issue.enclosingType));
           }
         }
 
-        reportBoundViolation(message, field.fileOffset, variable);
+        reportTypeArgumentIssues(message, field.fileOffset, typeParameter);
       }
     }
   }
@@ -1415,19 +1414,17 @@
       List<VariableDeclaration> positionalParameters,
       List<VariableDeclaration> namedParameters,
       DartType returnType}) {
-    if (!loader.target.strongMode) return;
+    if (loader.target.legacyMode) return;
     if (typeParameters != null) {
       for (TypeParameter parameter in typeParameters) {
-        List<Object> violations = typeEnvironment.findBoundViolations(
-            parameter.bound,
-            allowSuperBounded: false,
-            typedefInstantiations: typedefInstantiations);
-        if (violations != null) {
+        List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+            parameter.bound, typeEnvironment,
+            allowSuperBounded: false);
+        if (issues != null) {
           int offset = parameter.fileOffset;
-          for (int i = 0; i < violations.length; i += 3) {
-            DartType argument = violations[i];
-            TypeParameter variable = violations[i + 1];
-            DartType enclosingType = violations[i + 2];
+          for (TypeArgumentIssue issue in issues) {
+            DartType argument = issue.argument;
+            TypeParameter typeParameter = issue.typeParameter;
 
             Message message;
             bool inferred = inferredTypes.contains(argument);
@@ -1440,35 +1437,32 @@
               } else {
                 message = messageGenericFunctionTypeUsedAsActualTypeArgument;
               }
-              variable = null;
+              typeParameter = null;
             } else {
               if (inferred) {
                 message = templateIncorrectTypeArgumentInferred.withArguments(
-                    argument,
-                    typeEnvironment.getGenericTypeName(enclosingType));
+                    argument, getGenericTypeName(issue.enclosingType));
               } else {
-                message = templateIncorrectTypeArgument.withArguments(argument,
-                    typeEnvironment.getGenericTypeName(enclosingType));
+                message = templateIncorrectTypeArgument.withArguments(
+                    argument, getGenericTypeName(issue.enclosingType));
               }
             }
 
-            reportBoundViolation(message, offset, variable);
+            reportTypeArgumentIssues(message, offset, typeParameter);
           }
         }
       }
     }
     if (positionalParameters != null) {
       for (VariableDeclaration formal in positionalParameters) {
-        List<Object> violations = typeEnvironment.findBoundViolations(
-            formal.type,
-            allowSuperBounded: true,
-            typedefInstantiations: typedefInstantiations);
-        if (violations != null) {
+        List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+            formal.type, typeEnvironment,
+            allowSuperBounded: true);
+        if (issues != null) {
           int offset = formal.fileOffset;
-          for (int i = 0; i < violations.length; i += 3) {
-            DartType argument = violations[i];
-            TypeParameter variable = violations[i + 1];
-            DartType enclosingType = violations[i + 2];
+          for (TypeArgumentIssue issue in issues) {
+            DartType argument = issue.argument;
+            TypeParameter typeParameter = issue.typeParameter;
 
             Message message;
             bool inferred = inferredTypes.contains(argument);
@@ -1481,35 +1475,32 @@
               } else {
                 message = messageGenericFunctionTypeUsedAsActualTypeArgument;
               }
-              variable = null;
+              typeParameter = null;
             } else {
               if (inferred) {
                 message = templateIncorrectTypeArgumentInferred.withArguments(
-                    argument,
-                    typeEnvironment.getGenericTypeName(enclosingType));
+                    argument, getGenericTypeName(issue.enclosingType));
               } else {
-                message = templateIncorrectTypeArgument.withArguments(argument,
-                    typeEnvironment.getGenericTypeName(enclosingType));
+                message = templateIncorrectTypeArgument.withArguments(
+                    argument, getGenericTypeName(issue.enclosingType));
               }
             }
 
-            reportBoundViolation(message, offset, variable);
+            reportTypeArgumentIssues(message, offset, typeParameter);
           }
         }
       }
     }
     if (namedParameters != null) {
       for (VariableDeclaration named in namedParameters) {
-        List<Object> violations = typeEnvironment.findBoundViolations(
-            named.type,
-            allowSuperBounded: true,
-            typedefInstantiations: typedefInstantiations);
-        if (violations != null) {
+        List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+            named.type, typeEnvironment,
+            allowSuperBounded: true);
+        if (issues != null) {
           int offset = named.fileOffset;
-          for (int i = 0; i < violations.length; i += 3) {
-            DartType argument = violations[i];
-            TypeParameter variable = violations[i + 1];
-            DartType enclosingType = violations[i + 2];
+          for (TypeArgumentIssue issue in issues) {
+            DartType argument = issue.argument;
+            TypeParameter typeParameter = issue.typeParameter;
 
             Message message;
             bool inferred = inferredTypes.contains(argument);
@@ -1522,33 +1513,31 @@
               } else {
                 message = messageGenericFunctionTypeUsedAsActualTypeArgument;
               }
-              variable = null;
+              typeParameter = null;
             } else {
               if (inferred) {
                 message = templateIncorrectTypeArgumentInferred.withArguments(
-                    argument,
-                    typeEnvironment.getGenericTypeName(enclosingType));
+                    argument, getGenericTypeName(issue.enclosingType));
               } else {
-                message = templateIncorrectTypeArgument.withArguments(argument,
-                    typeEnvironment.getGenericTypeName(enclosingType));
+                message = templateIncorrectTypeArgument.withArguments(
+                    argument, getGenericTypeName(issue.enclosingType));
               }
             }
 
-            reportBoundViolation(message, offset, variable);
+            reportTypeArgumentIssues(message, offset, typeParameter);
           }
         }
       }
     }
     if (returnType != null) {
-      List<Object> violations = typeEnvironment.findBoundViolations(returnType,
-          allowSuperBounded: true,
-          typedefInstantiations: typedefInstantiations);
-      if (violations != null) {
+      List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+          returnType, typeEnvironment,
+          allowSuperBounded: true);
+      if (issues != null) {
         int offset = fileOffset;
-        for (int i = 0; i < violations.length; i += 3) {
-          DartType argument = violations[i];
-          TypeParameter variable = violations[i + 1];
-          DartType enclosingType = violations[i + 2];
+        for (TypeArgumentIssue issue in issues) {
+          DartType argument = issue.argument;
+          TypeParameter typeParameter = issue.typeParameter;
 
           // We don't need to check if [argument] was inferred or specified
           // here, because inference in return types boils down to instantiate-
@@ -1556,13 +1545,13 @@
           Message message;
           if (argument is FunctionType && argument.typeParameters.length > 0) {
             message = messageGenericFunctionTypeUsedAsActualTypeArgument;
-            variable = null;
+            typeParameter = null;
           } else {
             message = templateIncorrectTypeArgumentInReturnType.withArguments(
-                argument, typeEnvironment.getGenericTypeName(enclosingType));
+                argument, getGenericTypeName(issue.enclosingType));
           }
 
-          reportBoundViolation(message, offset, variable);
+          reportTypeArgumentIssues(message, offset, typeParameter);
         }
       }
     }
@@ -1570,7 +1559,7 @@
 
   void checkBoundsInFunctionNode(
       FunctionNode function, TypeEnvironment typeEnvironment) {
-    if (!loader.target.strongMode) return;
+    if (loader.target.legacyMode) return;
     checkBoundsInFunctionNodeParts(typeEnvironment, function.fileOffset,
         typeParameters: function.typeParameters,
         positionalParameters: function.positionalParameters,
@@ -1581,14 +1570,14 @@
   void checkBoundsInListLiteral(
       ListLiteral node, TypeEnvironment typeEnvironment,
       {bool inferred = false}) {
-    if (!loader.target.strongMode) return;
+    if (loader.target.legacyMode) return;
     checkBoundsInType(node.typeArgument, typeEnvironment, node.fileOffset,
         inferred: inferred, allowSuperBounded: true);
   }
 
   void checkBoundsInMapLiteral(MapLiteral node, TypeEnvironment typeEnvironment,
       {bool inferred = false}) {
-    if (!loader.target.strongMode) return;
+    if (loader.target.legacyMode) return;
     checkBoundsInType(node.keyType, typeEnvironment, node.fileOffset,
         inferred: inferred, allowSuperBounded: true);
     checkBoundsInType(node.valueType, typeEnvironment, node.fileOffset,
@@ -1598,15 +1587,14 @@
   void checkBoundsInType(
       DartType type, TypeEnvironment typeEnvironment, int offset,
       {bool inferred = false, bool allowSuperBounded = true}) {
-    if (!loader.target.strongMode) return;
-    List<Object> violations = typeEnvironment.findBoundViolations(type,
-        allowSuperBounded: allowSuperBounded,
-        typedefInstantiations: typedefInstantiations);
-    if (violations != null) {
-      for (int i = 0; i < violations.length; i += 3) {
-        DartType argument = violations[i];
-        TypeParameter variable = violations[i + 1];
-        DartType enclosingType = violations[i + 2];
+    if (loader.target.legacyMode) return;
+    List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+        type, typeEnvironment,
+        allowSuperBounded: allowSuperBounded);
+    if (issues != null) {
+      for (TypeArgumentIssue issue in issues) {
+        DartType argument = issue.argument;
+        TypeParameter typeParameter = issue.typeParameter;
 
         Message message;
         if (argument is FunctionType && argument.typeParameters.length > 0) {
@@ -1616,18 +1604,18 @@
           } else {
             message = messageGenericFunctionTypeUsedAsActualTypeArgument;
           }
-          variable = null;
+          typeParameter = null;
         } else {
           if (inferred) {
             message = templateIncorrectTypeArgumentInferred.withArguments(
-                argument, typeEnvironment.getGenericTypeName(enclosingType));
+                argument, getGenericTypeName(issue.enclosingType));
           } else {
             message = templateIncorrectTypeArgument.withArguments(
-                argument, typeEnvironment.getGenericTypeName(enclosingType));
+                argument, getGenericTypeName(issue.enclosingType));
           }
         }
 
-        reportBoundViolation(message, offset, variable);
+        reportTypeArgumentIssues(message, offset, typeParameter);
       }
     }
   }
@@ -1635,15 +1623,15 @@
   void checkBoundsInVariableDeclaration(
       VariableDeclaration node, TypeEnvironment typeEnvironment,
       {bool inferred = false}) {
-    if (!loader.target.strongMode) return;
+    if (loader.target.legacyMode) return;
     if (node.type == null) return;
-    List<Object> violations = typeEnvironment.findBoundViolations(node.type,
-        allowSuperBounded: true, typedefInstantiations: typedefInstantiations);
-    if (violations != null) {
-      for (int i = 0; i < violations.length; i += 3) {
-        DartType argument = violations[i];
-        TypeParameter variable = violations[i + 1];
-        DartType enclosingType = violations[i + 2];
+    List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+        node.type, typeEnvironment,
+        allowSuperBounded: true);
+    if (issues != null) {
+      for (TypeArgumentIssue issue in issues) {
+        DartType argument = issue.argument;
+        TypeParameter typeParameter = issue.typeParameter;
 
         Message message;
         if (argument is FunctionType && argument.typeParameters.length > 0) {
@@ -1653,18 +1641,18 @@
           } else {
             message = messageGenericFunctionTypeUsedAsActualTypeArgument;
           }
-          variable = null;
+          typeParameter = null;
         } else {
           if (inferred) {
             message = templateIncorrectTypeArgumentInferred.withArguments(
-                argument, typeEnvironment.getGenericTypeName(enclosingType));
+                argument, getGenericTypeName(issue.enclosingType));
           } else {
             message = templateIncorrectTypeArgument.withArguments(
-                argument, typeEnvironment.getGenericTypeName(enclosingType));
+                argument, getGenericTypeName(issue.enclosingType));
           }
         }
 
-        reportBoundViolation(message, node.fileOffset, variable);
+        reportTypeArgumentIssues(message, node.fileOffset, typeParameter);
       }
     }
   }
@@ -1672,24 +1660,22 @@
   void checkBoundsInConstructorInvocation(
       ConstructorInvocation node, TypeEnvironment typeEnvironment,
       {bool inferred = false}) {
-    if (!loader.target.strongMode) return;
+    if (loader.target.legacyMode) return;
     if (node.arguments.types.isEmpty) return;
     Constructor constructor = node.target;
     Class klass = constructor.enclosingClass;
     DartType constructedType = new InterfaceType(klass, node.arguments.types);
-    List<Object> violations = typeEnvironment.findBoundViolations(
-        constructedType,
-        allowSuperBounded: false,
-        typedefInstantiations: typedefInstantiations);
-    if (violations != null) {
+    List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+        constructedType, typeEnvironment,
+        allowSuperBounded: false);
+    if (issues != null) {
       String constructedTypeName = "${klass.name}::${constructor.name.name}";
-      for (int i = 0; i < violations.length; i += 3) {
-        DartType argument = violations[i];
-        TypeParameter variable = violations[i + 1];
-        DartType enclosingType = violations[i + 2];
-        String enclosingName = enclosingType == constructedType
+      for (TypeArgumentIssue issue in issues) {
+        DartType argument = issue.argument;
+        TypeParameter typeParameter = issue.typeParameter;
+        String enclosingName = issue.enclosingType == constructedType
             ? constructedTypeName
-            : typeEnvironment.getGenericTypeName(enclosingType);
+            : getGenericTypeName(issue.enclosingType);
 
         Message message;
         if (argument is FunctionType && argument.typeParameters.length > 0) {
@@ -1699,7 +1685,7 @@
           } else {
             message = messageGenericFunctionTypeUsedAsActualTypeArgument;
           }
-          variable = null;
+          typeParameter = null;
         } else {
           if (inferred) {
             message = templateIncorrectTypeArgumentInferred.withArguments(
@@ -1710,7 +1696,7 @@
           }
         }
 
-        reportBoundViolation(message, node.fileOffset, variable);
+        reportTypeArgumentIssues(message, node.fileOffset, typeParameter);
       }
     }
   }
@@ -1718,25 +1704,23 @@
   void checkBoundsInFactoryInvocation(
       StaticInvocation node, TypeEnvironment typeEnvironment,
       {bool inferred = false}) {
-    if (!loader.target.strongMode) return;
+    if (loader.target.legacyMode) return;
     if (node.arguments.types.isEmpty) return;
     Procedure factory = node.target;
     assert(factory.isFactory);
     Class klass = factory.enclosingClass;
     DartType constructedType = new InterfaceType(klass, node.arguments.types);
-    List<Object> violations = typeEnvironment.findBoundViolations(
-        constructedType,
-        allowSuperBounded: false,
-        typedefInstantiations: typedefInstantiations);
-    if (violations != null) {
+    List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+        constructedType, typeEnvironment,
+        allowSuperBounded: false);
+    if (issues != null) {
       String constructedTypeName = "${klass.name}::${factory.name.name}";
-      for (int i = 0; i < violations.length; i += 3) {
-        DartType argument = violations[i];
-        TypeParameter variable = violations[i + 1];
-        DartType enclosingType = violations[i + 2];
-        String enclosingName = enclosingType == constructedType
+      for (TypeArgumentIssue issue in issues) {
+        DartType argument = issue.argument;
+        TypeParameter typeParameter = issue.typeParameter;
+        String enclosingName = issue.enclosingType == constructedType
             ? constructedTypeName
-            : typeEnvironment.getGenericTypeName(enclosingType);
+            : getGenericTypeName(issue.enclosingType);
 
         Message message;
         if (argument is FunctionType && argument.typeParameters.length > 0) {
@@ -1746,7 +1730,7 @@
           } else {
             message = messageGenericFunctionTypeUsedAsActualTypeArgument;
           }
-          variable = null;
+          typeParameter = null;
         } else {
           if (inferred) {
             message = templateIncorrectTypeArgumentInferred.withArguments(
@@ -1757,7 +1741,7 @@
           }
         }
 
-        reportBoundViolation(message, node.fileOffset, variable);
+        reportTypeArgumentIssues(message, node.fileOffset, typeParameter);
       }
     }
   }
@@ -1765,30 +1749,28 @@
   void checkBoundsInStaticInvocation(
       StaticInvocation node, TypeEnvironment typeEnvironment,
       {bool inferred = false}) {
-    if (!loader.target.strongMode) return;
+    if (loader.target.legacyMode) return;
     if (node.arguments.types.isEmpty) return;
     Class klass = node.target.enclosingClass;
     List<TypeParameter> parameters = node.target.function.typeParameters;
     List<DartType> arguments = node.arguments.types;
     // The following error is to be reported elsewhere.
     if (parameters.length != arguments.length) return;
-    List<Object> violations = typeEnvironment.findBoundViolationsElementwise(
-        parameters, arguments,
-        typedefInstantiations: typedefInstantiations);
-    if (violations != null) {
+    List<TypeArgumentIssue> issues = findTypeArgumentIssuesForInvocation(
+        parameters, arguments, typeEnvironment);
+    if (issues != null) {
       String targetName;
       if (klass == null) {
         targetName = "${node.target.name.name}";
       } else {
         targetName = "${klass.name}::${node.target.name.name}";
       }
-      for (int i = 0; i < violations.length; i += 3) {
-        DartType argument = violations[i];
-        TypeParameter variable = violations[i + 1];
-        DartType enclosingType = violations[i + 2];
-        String enclosingName = enclosingType == null
+      for (TypeArgumentIssue issue in issues) {
+        DartType argument = issue.argument;
+        TypeParameter typeParameter = issue.typeParameter;
+        String enclosingName = issue.enclosingType == null
             ? targetName
-            : typeEnvironment.getGenericTypeName(enclosingType);
+            : getGenericTypeName(issue.enclosingType);
 
         Message message;
         if (argument is FunctionType) {
@@ -1798,7 +1780,7 @@
           } else {
             message = messageGenericFunctionTypeUsedAsActualTypeArgument;
           }
-          variable = null;
+          typeParameter = null;
         } else {
           if (inferred) {
             message = templateIncorrectTypeArgumentInferred.withArguments(
@@ -1809,7 +1791,7 @@
           }
         }
 
-        reportBoundViolation(message, node.fileOffset, variable);
+        reportTypeArgumentIssues(message, node.fileOffset, typeParameter);
       }
     }
   }
@@ -1823,7 +1805,7 @@
       Arguments arguments,
       int offset,
       {bool inferred = false}) {
-    if (!loader.target.strongMode) return;
+    if (loader.target.legacyMode) return;
     if (arguments.types.isEmpty) return;
     Class klass;
     List<DartType> klassArguments;
@@ -1858,10 +1840,9 @@
       instantiatedMethodParameters[i].bound =
           substitute(methodParameters[i].bound, substitutionMap);
     }
-    List<Object> violations = typeEnvironment.findBoundViolationsElementwise(
-        instantiatedMethodParameters, arguments.types,
-        typedefInstantiations: typedefInstantiations);
-    if (violations != null) {
+    List<TypeArgumentIssue> issues = findTypeArgumentIssuesForInvocation(
+        instantiatedMethodParameters, arguments.types, typeEnvironment);
+    if (issues != null) {
       String targetName = "${klass.name}";
       if (klassArguments.length > 0) {
         targetName += "<${klassArguments[0]}";
@@ -1871,13 +1852,12 @@
         targetName += ">";
       }
       targetName += "::${name.name}";
-      for (int i = 0; i < violations.length; i += 3) {
-        DartType argument = violations[i];
-        TypeParameter variable = violations[i + 1];
-        DartType enclosingType = violations[i + 2];
-        String enclosingName = enclosingType == null
+      for (TypeArgumentIssue issue in issues) {
+        DartType argument = issue.argument;
+        TypeParameter typeParameter = issue.typeParameter;
+        String enclosingName = issue.enclosingType == null
             ? targetName
-            : typeEnvironment.getGenericTypeName(enclosingType);
+            : getGenericTypeName(issue.enclosingType);
 
         Message message;
         if (argument is FunctionType && argument.typeParameters.length > 0) {
@@ -1887,7 +1867,7 @@
           } else {
             message = messageGenericFunctionTypeUsedAsActualTypeArgument;
           }
-          variable = null;
+          typeParameter = null;
         } else {
           if (inferred) {
             message = templateIncorrectTypeArgumentInferred.withArguments(
@@ -1898,13 +1878,13 @@
           }
         }
 
-        reportBoundViolation(message, offset, variable);
+        reportTypeArgumentIssues(message, offset, typeParameter);
       }
     }
   }
 
   void checkBoundsInOutline(TypeEnvironment typeEnvironment) {
-    if (!loader.target.strongMode) return;
+    if (loader.target.legacyMode) return;
     forEach((String name, Declaration declaration) {
       if (declaration is KernelFieldBuilder) {
         checkBoundsInField(declaration.target, typeEnvironment);
@@ -1915,7 +1895,6 @@
       }
     });
 
-    typedefInstantiations.clear();
     inferredTypes.clear();
   }
 }
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 aa98c01..96ed4c1 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
@@ -332,7 +332,7 @@
       procedure.isConst = isConst;
       procedure.name = new Name(name, library.target);
     }
-    if (library.loader.target.strongMode &&
+    if (!library.loader.target.legacyMode &&
         (isSetter || (isOperator && name == '[]=')) &&
         returnType == null) {
       procedure.function.returnType = const VoidType();
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index 80afd41..a78410a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -63,11 +63,7 @@
         TypeInferenceEngine;
 
 import '../type_inference/type_inferrer.dart'
-    show
-        ExpressionInferenceResult,
-        TypeInferrer,
-        TypeInferrerDisabled,
-        TypeInferrerImpl;
+    show ExpressionInferenceResult, TypeInferrer, TypeInferrerImpl;
 
 import '../type_inference/type_promotion.dart'
     show TypePromoter, TypePromoterImpl, TypePromotionFact, TypePromotionScope;
@@ -491,7 +487,7 @@
             ? rhsType
             : inferrer.typeSchemaEnvironment
                 .getStandardUpperBound(readType, rhsType);
-        if (inferrer.strongMode) {
+        if (!inferrer.legacyMode) {
           nullAwareCombiner.staticType = combinedType;
         }
       } else {
@@ -1487,7 +1483,7 @@
   /// fact that [expression] has the given [type].
   void _storeLetType(
       TypeInferrerImpl inferrer, Expression expression, DartType type) {
-    if (!inferrer.strongMode) return;
+    if (inferrer.legacyMode) return;
     Expression desugared = this.desugared;
     while (true) {
       if (desugared is Let) {
@@ -1562,24 +1558,24 @@
 /// Concrete implementation of [TypeInferenceEngine] specialized to work with
 /// kernel objects.
 class ShadowTypeInferenceEngine extends TypeInferenceEngine {
-  ShadowTypeInferenceEngine(Instrumentation instrumentation, bool strongMode)
-      : super(instrumentation, strongMode);
+  ShadowTypeInferenceEngine(Instrumentation instrumentation, bool legacyMode)
+      : super(instrumentation, legacyMode);
 
   @override
   TypeInferrer createDisabledTypeInferrer() =>
-      new TypeInferrerDisabled(typeSchemaEnvironment);
+      new TypeInferrer.disabled(typeSchemaEnvironment);
 
   @override
   ShadowTypeInferrer createLocalTypeInferrer(
       Uri uri, InterfaceType thisType, KernelLibraryBuilder library) {
-    return new ShadowTypeInferrer._(this, uri, false, thisType, library);
+    return new TypeInferrer(this, uri, false, thisType, library);
   }
 
   @override
   ShadowTypeInferrer createTopLevelTypeInferrer(
       InterfaceType thisType, ShadowField field, KernelLibraryBuilder library) {
     return field._typeInferrer =
-        new ShadowTypeInferrer._(this, field.fileUri, true, thisType, library);
+        new TypeInferrer(this, field.fileUri, true, thisType, library);
   }
 
   @override
@@ -1594,10 +1590,10 @@
   @override
   final typePromoter;
 
-  ShadowTypeInferrer._(ShadowTypeInferenceEngine engine, Uri uri, bool topLevel,
-      InterfaceType thisType, KernelLibraryBuilder library)
-      : typePromoter = new ShadowTypePromoter(engine.typeSchemaEnvironment),
-        super(engine, uri, topLevel, thisType, library);
+  ShadowTypeInferrer.private(ShadowTypeInferenceEngine engine, Uri uri,
+      bool topLevel, InterfaceType thisType, KernelLibraryBuilder library)
+      : typePromoter = new TypePromoter(engine.typeSchemaEnvironment),
+        super.private(engine, uri, topLevel, thisType, library);
 
   @override
   Expression getFieldInitializer(ShadowField field) {
@@ -1700,8 +1696,8 @@
 /// Concrete implementation of [TypePromoter] specialized to work with kernel
 /// objects.
 class ShadowTypePromoter extends TypePromoterImpl {
-  ShadowTypePromoter(TypeSchemaEnvironment typeSchemaEnvironment)
-      : super(typeSchemaEnvironment);
+  ShadowTypePromoter.private(TypeSchemaEnvironment typeSchemaEnvironment)
+      : super.private(typeSchemaEnvironment);
 
   @override
   int getVariableFunctionNestingLevel(VariableDeclaration variable) {
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 8354ddb..1342714 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -123,7 +123,7 @@
 
   final TypeBuilder bottomType = new KernelNamedTypeBuilder("Null", null);
 
-  bool get strongMode => !backendTarget.legacyMode;
+  bool get legacyMode => backendTarget.legacyMode;
 
   bool get disableTypeInference => backendTarget.disableTypeInference;
 
@@ -413,7 +413,7 @@
     Class objectClass = this.objectClass;
     for (SourceClassBuilder builder in builders) {
       if (builder.target != objectClass) {
-        if (builder.isPatch) continue;
+        if (builder.isPatch || builder.isMixinDeclaration) continue;
         if (builder.isMixinApplication) {
           installForwardingConstructors(builder);
         } else {
@@ -727,7 +727,8 @@
     for (Field field in uninitializedFields) {
       if (initializedFields == null || !initializedFields.contains(field)) {
         field.initializer = new NullLiteral()..parent = field;
-        if (field.isFinal && cls.constructors.isNotEmpty) {
+        if (field.isFinal &&
+            (cls.constructors.isNotEmpty || cls.isMixinDeclaration)) {
           builder.library.addProblem(
               templateFinalFieldNotInitialized.withArguments(field.name.name),
               field.fileOffset,
@@ -809,7 +810,7 @@
           KernelLibraryBuilder part =
               library.loader.read(patch, -1, fileUri: patch, accessor: first);
           first.parts.add(part);
-          part.addPartOf(null, null, "${first.uri}", -1);
+          part.partOfUri = first.uri;
         }
       }
     }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_type_variable_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_type_variable_builder.dart
index 6d1bca2..241bb28 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_type_variable_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_type_variable_builder.dart
@@ -82,10 +82,16 @@
   void finish(LibraryBuilder library, KernelClassBuilder object,
       TypeBuilder dynamicType) {
     if (isPatch) return;
-    parameter.bound ??=
-        bound?.build(library) ?? object.buildType(library, null);
-    parameter.defaultType ??=
-        defaultType?.build(library) ?? dynamicType.build(library);
+    DartType objectType = object.buildType(library, null);
+    parameter.bound ??= bound?.build(library) ?? objectType;
+    // If defaultType is not set, initialize it to dynamic, unless the bound is
+    // explicitly specified as Object, in which case defaultType should also be
+    // Object. This makes sure instantiation of generic function types with an
+    // explicit Object bound results in Object as the instantiated type.
+    parameter.defaultType ??= defaultType?.build(library) ??
+        (bound != null && parameter.bound == objectType
+            ? objectType
+            : dynamicType.build(library));
   }
 
   void applyPatch(covariant KernelTypeVariableBuilder patch) {
@@ -99,4 +105,15 @@
     return new KernelTypeVariableBuilder(
         name, parent, charOffset, bound.clone(newTypes));
   }
+
+  static List<TypeParameter> kernelTypeParametersFromBuilders(
+      List<TypeVariableBuilder> builders) {
+    if (builders == null) return null;
+    List<TypeParameter> result =
+        new List<TypeParameter>.filled(builders.length, null, growable: true);
+    for (int i = 0; i < builders.length; i++) {
+      result[i] = builders[i].target;
+    }
+    return result;
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
index 62248a4..bcd7cca 100644
--- a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
@@ -129,7 +129,7 @@
   RedirectionTarget(this.target, this.typeArguments);
 }
 
-RedirectionTarget getRedirectionTarget(Procedure member, {bool strongMode}) {
+RedirectionTarget getRedirectionTarget(Procedure member, {bool legacyMode}) {
   List<DartType> typeArguments = <DartType>[]..length =
       member.function.typeParameters.length;
   for (int i = 0; i < typeArguments.length; i++) {
@@ -148,11 +148,11 @@
       return new RedirectionTarget(tortoise, typeArguments);
     Member nextTortoise = tortoiseBody.target;
     List<DartType> nextTypeArguments = tortoiseBody.typeArguments;
-    if (strongMode && nextTypeArguments == null) {
+    if (!legacyMode && nextTypeArguments == null) {
       nextTypeArguments = <DartType>[];
     }
 
-    if (strongMode || nextTypeArguments != null) {
+    if (!legacyMode || nextTypeArguments != null) {
       Substitution sub = Substitution.fromPairs(
           tortoise.function.typeParameters, typeArguments);
       typeArguments = <DartType>[]..length = nextTypeArguments.length;
diff --git a/pkg/front_end/lib/src/fasta/loader.dart b/pkg/front_end/lib/src/fasta/loader.dart
index 3da7e4f..1dcea9d 100644
--- a/pkg/front_end/lib/src/fasta/loader.dart
+++ b/pkg/front_end/lib/src/fasta/loader.dart
@@ -157,6 +157,7 @@
     } else {
       builder.recordAccess(charOffset, noLength, accessor.fileUri);
       if (!accessor.isPatch &&
+          !accessor.isPart &&
           !target.backendTarget
               .allowPlatformPrivateLibraryAccess(accessor.uri, uri)) {
         accessor.addProblem(messagePlatformPrivateLibraryAccess, charOffset,
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 8c3478e..5e15224 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -996,6 +996,12 @@
   }
 
   @override
+  void handleEmptyLiteralSetOrMap(
+      Token leftBrace, Token constKeyword, Token rightBrace) {
+    listener?.handleEmptyLiteralSetOrMap(leftBrace, constKeyword, rightBrace);
+  }
+
+  @override
   void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
     listener?.handleExpressionFunctionBody(arrowToken, endToken);
   }
@@ -1128,6 +1134,12 @@
   }
 
   @override
+  void handleLiteralSet(
+      int count, Token beginToken, Token constKeyword, Token token) {
+    listener?.handleLiteralSet(count, beginToken, constKeyword, token);
+  }
+
+  @override
   void handleMixinHeader(Token mixinKeyword) {
     listener?.handleMixinHeader(mixinKeyword);
   }
@@ -1183,8 +1195,18 @@
   }
 
   @override
-  void handleNoExpression(Token token) {
-    listener?.handleNoExpression(token);
+  void handleForInitializerEmptyStatement(Token token) {
+    listener?.handleForInitializerEmptyStatement(token);
+  }
+
+  @override
+  void handleForInitializerExpressionStatement(Token token) {
+    listener?.handleForInitializerExpressionStatement(token);
+  }
+
+  @override
+  void handleForInitializerLocalVariableDeclaration(Token token) {
+    listener?.handleForInitializerLocalVariableDeclaration(token);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index bbdfe7f..9078ced 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -301,6 +301,24 @@
     logEvent("Fields");
   }
 
+  /// Marks that the grammar term `forInitializerStatement` has been parsed and
+  /// it was an empty statement.
+  void handleForInitializerEmptyStatement(Token token) {
+    logEvent("ForInitializerEmptyStatement");
+  }
+
+  /// Marks that the grammar term `forInitializerStatement` has been parsed and
+  /// it was an expression statement.
+  void handleForInitializerExpressionStatement(Token token) {
+    logEvent("ForInitializerExpressionStatement");
+  }
+
+  /// Marks that the grammar term `forInitializerStatement` has been parsed and
+  /// it was a `localVariableDeclaration`.
+  void handleForInitializerLocalVariableDeclaration(Token token) {
+    logEvent("ForInitializerLocalVariableDeclaration");
+  }
+
   /// Marks the start of a for statement which is ended by either
   /// [endForStatement] or [endForIn].
   void beginForStatement(Token token) {}
@@ -1123,6 +1141,16 @@
     logEvent("LiteralMap");
   }
 
+  void handleLiteralSet(
+      int count, Token beginToken, Token constKeyword, Token token) {
+    logEvent("LiteralSet");
+  }
+
+  void handleEmptyLiteralSetOrMap(
+      Token leftBrace, Token constKeyword, Token rightBrace) {
+    logEvent('EmptyLiteralSetOrMap');
+  }
+
   void handleLiteralNull(Token token) {
     logEvent("LiteralNull");
   }
@@ -1145,10 +1173,6 @@
     logEvent("NoArguments");
   }
 
-  void handleNoExpression(Token token) {
-    logEvent("NoExpression");
-  }
-
   void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
     logEvent("NoConstructorReferenceContinuationAfterTypeArguments");
   }
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 7cb645c..2617420 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -261,6 +261,10 @@
 
   bool mayParseFunctionExpressions = true;
 
+  /// Experimental flag for enabling set literal support.
+  /// See https://github.com/dart-lang/sdk/issues/35121
+  bool parseSetLiterals = false;
+
   /// Represents parser state: what asynchronous syntax is allowed in the
   /// function being currently parsed. In rare situations, this can be set by
   /// external clients, for example, to parse an expression outside a function.
@@ -2985,8 +2989,10 @@
       token = parseOperatorName(token);
     } else {
       token = ensureIdentifier(token, IdentifierContext.methodDeclaration);
-      token = parseQualifiedRestOpt(
-          token, IdentifierContext.methodDeclarationContinuation);
+      if (getOrSet == null) {
+        token = parseQualifiedRestOpt(
+            token, IdentifierContext.methodDeclarationContinuation);
+      }
     }
 
     bool isGetter = false;
@@ -3935,6 +3941,7 @@
           listener.handleNoTypeArguments(next);
         }
         token = parseArguments(token);
+        listener.handleSend(beginToken, token);
         typeArg = computeMethodTypeArguments(token);
         if (typeArg != noTypeParamOrArg) {
           // For example a(b)<T>(c), where token is before '<'.
@@ -3942,7 +3949,6 @@
           assert(optional('(', token.next));
         }
         next = token.next;
-        listener.handleSend(beginToken, next);
       } else {
         break;
       }
@@ -4001,7 +4007,7 @@
       return parseLiteralListSuffix(token, null);
     } else if (kind == OPEN_CURLY_BRACKET_TOKEN) {
       listener.handleNoTypeArguments(token.next);
-      return parseLiteralMapSuffix(token, null);
+      return parseLiteralSetOrMapSuffix(token, null);
     } else if (kind == LT_TOKEN) {
       return parseLiteralListOrMapOrFunction(token, null);
     } else {
@@ -4189,12 +4195,55 @@
     return token;
   }
 
+  /// This method parses the portion of a set or map literal that starts with
+  /// the left curly brace.
+  Token parseLiteralSetOrMapSuffix(final Token start, Token constKeyword) {
+    if (!parseSetLiterals) {
+      // TODO(danrubel): remove this once set literals are permanent
+      return parseLiteralMapSuffix(start, constKeyword);
+    }
+
+    Token leftBrace = start.next;
+    assert(optional('{', leftBrace));
+    if (optional('}', leftBrace.next)) {
+      Token rightBrace = leftBrace.next;
+      listener.handleEmptyLiteralSetOrMap(leftBrace, constKeyword, rightBrace);
+      return rightBrace;
+    }
+
+    final old = mayParseFunctionExpressions;
+    mayParseFunctionExpressions = true;
+    final originalListener = listener;
+    listener = new ForwardingListener();
+
+    // Skip over the first expression to determine if this is a set or map.
+    // TODO(danrubel): Consider removing listener.beginLiteralMapEntry
+    // so that the expression could be parsed without lookahead
+    // regardless of whether this is a set or map literal.
+    Token token = parseExpression(leftBrace);
+    Token next = token.next;
+
+    listener = originalListener;
+    mayParseFunctionExpressions = old;
+
+    if (optional(',', next) || optional('}', next)) {
+      return parseLiteralSetSuffix(start, constKeyword);
+    } else if (optional(':', next)) {
+      return parseLiteralMapSuffix(start, constKeyword);
+    } else {
+      // Recovery: This could be either a literal set or a literal map
+      // TODO(danrubel): Consider better recovery
+      // rather than just assuming this is a malformed literal map.
+      return parseLiteralMapSuffix(start, constKeyword);
+    }
+  }
+
   /// This method parses the portion of a map literal that starts with the left
   /// curly brace.
   ///
   /// ```
   /// mapLiteral:
-  ///   'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
+  ///   'const'? typeArguments? '{' mapLiteralEntry (',' mapLiteralEntry)* ','? '}'
   /// ;
   /// ```
   ///
@@ -4244,6 +4293,66 @@
     return token;
   }
 
+  /// This method parses the portion of a set literal that starts with the left
+  /// curly brace.
+  ///
+  /// ```
+  /// setLiteral:
+  ///   'const'?  typeArguments? '{' expression (',' expression)* ','? '}'
+  /// ;
+  /// ```
+  ///
+  /// Provide a [constKeyword] if the literal is preceded by 'const', or `null`
+  /// if not. This is a suffix parser because it is assumed that type arguments
+  /// have been parsed, or `listener.handleNoTypeArguments` has been executed.
+  Token parseLiteralSetSuffix(Token token, Token constKeyword) {
+    if (!parseSetLiterals) {
+      // TODO(danrubel): remove this once set literals are permanent
+      return parseLiteralMapSuffix(token, constKeyword);
+    }
+
+    Token beginToken = token = token.next;
+    assert(optional('{', beginToken));
+    int count = 0;
+    bool old = mayParseFunctionExpressions;
+    mayParseFunctionExpressions = true;
+    while (true) {
+      if (optional('}', token.next)) {
+        token = token.next;
+        break;
+      }
+      token = parseExpression(token);
+      Token next = token.next;
+      ++count;
+      if (!optional(',', next)) {
+        if (optional('}', next)) {
+          token = next;
+          break;
+        }
+        // Recovery
+        if (looksLikeExpressionStart(next)) {
+          // If this looks like the start of an expression,
+          // then report an error, insert the comma, and continue parsing.
+          next = rewriteAndRecover(
+              token,
+              fasta.templateExpectedButGot.withArguments(','),
+              new SyntheticToken(TokenType.COMMA, next.offset));
+        } else {
+          reportRecoverableError(
+              next, fasta.templateExpectedButGot.withArguments('}'));
+          // Scanner guarantees a closing curly bracket
+          token = beginToken.endGroup;
+          break;
+        }
+      }
+      token = next;
+    }
+    assert(optional('}', token));
+    mayParseFunctionExpressions = old;
+    listener.handleLiteralSet(count, beginToken, constKeyword, token);
+    return token;
+  }
+
   /// formalParameterList functionBody.
   ///
   /// This is a suffix parser because it is assumed that type arguments have
@@ -4286,7 +4395,18 @@
     }
     token = typeParamOrArg.parseArguments(start, this);
     if (optional('{', next)) {
-      return parseLiteralMapSuffix(token, constKeyword);
+      switch (typeParamOrArg.typeArgumentCount) {
+        case 0:
+          return parseLiteralSetOrMapSuffix(token, constKeyword);
+        case 1:
+          return parseLiteralSetSuffix(token, constKeyword);
+        case 2:
+          return parseLiteralMapSuffix(token, constKeyword);
+        default:
+          // TODO(danrubel): Add a compile time warning that set literals
+          // require one type argument and map literals require two.
+          return parseLiteralSetOrMapSuffix(token, constKeyword);
+      }
     }
     if (!optional('[', next) && !optional('[]', next)) {
       // TODO(danrubel): Improve this error message.
@@ -4429,7 +4549,7 @@
     if (identical(value, '{')) {
       listener.beginConstLiteral(next);
       listener.handleNoTypeArguments(next);
-      token = parseLiteralMapSuffix(token, constKeyword);
+      token = parseLiteralSetOrMapSuffix(token, constKeyword);
       listener.endConstLiteral(token.next);
       return token;
     }
@@ -5062,10 +5182,12 @@
     // or an expression if no local variable declaration was found.
     if (token != leftParenthesis) {
       token = parseVariablesDeclarationRest(token, false);
+      listener.handleForInitializerLocalVariableDeclaration(token);
     } else if (optional(';', token.next)) {
-      listener.handleNoExpression(token.next);
+      listener.handleForInitializerEmptyStatement(token.next);
     } else {
       token = parseExpression(token);
+      listener.handleForInitializerExpressionStatement(token);
     }
 
     Token next = token.next;
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info.dart b/pkg/front_end/lib/src/fasta/parser/type_info.dart
index b2c407e..9e43321 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info.dart
@@ -64,6 +64,9 @@
   /// Return `true` if the receiver represents a single type argument
   bool get isSimpleTypeArgument => false;
 
+  /// Return the number of type arguments
+  int get typeArgumentCount;
+
   /// Return the simple type associated with this simple type argument
   /// or throw an exception if this is not a simple type argument.
   TypeInfo get typeInfo {
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
index e76bcff..7f959e9 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
@@ -533,6 +533,9 @@
   const NoTypeParamOrArg();
 
   @override
+  int get typeArgumentCount => 0;
+
+  @override
   Token parseArguments(Token token, Parser parser) {
     parser.listener.handleNoTypeArguments(token.next);
     return token;
@@ -555,6 +558,9 @@
   bool get isSimpleTypeArgument => true;
 
   @override
+  int get typeArgumentCount => 1;
+
+  @override
   TypeInfo get typeInfo => simpleTypeWith1Argument;
 
   @override
@@ -664,6 +670,9 @@
   /// given unbalanced `<` `>` and invalid parameters or arguments.
   final bool inDeclaration;
 
+  @override
+  int typeArgumentCount;
+
   /// The `>` token which ends the type parameter or argument.
   /// This closer may be synthetic, points to the next token in the stream,
   /// is only used when skipping over the type parameters or arguments,
@@ -681,6 +690,7 @@
   TypeParamOrArgInfo compute() {
     Token token;
     Token next = start;
+    typeArgumentCount = 0;
     while (true) {
       TypeInfo typeInfo = computeType(next, true, inDeclaration);
       if (typeInfo == noType) {
@@ -701,6 +711,7 @@
         assert(typeInfo != noType || optional(',', next.next));
         // Fall through to process type (if any) and consume `,`
       }
+      ++typeArgumentCount;
       token = typeInfo.skipType(next);
       next = token.next;
       if (optional('extends', next)) {
diff --git a/pkg/front_end/lib/src/fasta/scanner/token_constants.dart b/pkg/front_end/lib/src/fasta/scanner/token_constants.dart
index 14a99e9..6ac1842 100644
--- a/pkg/front_end/lib/src/fasta/scanner/token_constants.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/token_constants.dart
@@ -86,3 +86,4 @@
 const int QUESTION_QUESTION_EQ_TOKEN = QUESTION_QUESTION_TOKEN + 1;
 const int GENERIC_METHOD_TYPE_ASSIGN_TOKEN = QUESTION_QUESTION_EQ_TOKEN + 1;
 const int GENERIC_METHOD_TYPE_LIST_TOKEN = GENERIC_METHOD_TYPE_ASSIGN_TOKEN + 1;
+const int GT_GT_GT_TOKEN = GENERIC_METHOD_TYPE_LIST_TOKEN + 1;
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 b8e875c..1517023 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
@@ -5,7 +5,7 @@
 library fasta.source_class_builder;
 
 import 'package:kernel/ast.dart'
-    show Class, Constructor, Member, Supertype, TreeNode, setParents;
+    show Class, Constructor, Member, Supertype, TreeNode;
 
 import '../../base/instrumentation.dart' show Instrumentation;
 
@@ -51,7 +51,11 @@
     int startCharOffset,
     int charOffset,
     int charEndOffset) {
-  cls ??= new ShadowClass(name: name);
+  cls ??= new ShadowClass(
+      name: name,
+      typeParameters:
+          KernelTypeVariableBuilder.kernelTypeParametersFromBuilders(
+              typeVariables));
   cls.fileUri ??= parent.fileUri;
   if (cls.startFileOffset == TreeNode.noOffset) {
     cls.startFileOffset = startCharOffset;
@@ -63,13 +67,6 @@
     cls.fileEndOffset = charEndOffset;
   }
 
-  if (typeVariables != null) {
-    for (KernelTypeVariableBuilder t in typeVariables) {
-      cls.typeParameters.add(t.parameter);
-    }
-    setParents(cls.typeParameters, cls);
-  }
-
   return cls;
 }
 
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 16a1b45..f1cb326 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
@@ -350,6 +350,14 @@
     partOfName = name;
     if (uri != null) {
       partOfUri = resolve(this.uri, uri, uriOffset);
+      Uri newFileUri = resolve(fileUri, uri, uriOffset);
+      LibraryBuilder library = loader.read(partOfUri, uriOffset,
+          fileUri: newFileUri, accessor: this);
+      if (loader.first == this) {
+        // This is a part, and it was the first input. Let the loader know
+        // about that.
+        loader.first = library;
+      }
     }
   }
 
@@ -777,7 +785,7 @@
     int typeCount = types.length;
     for (UnresolvedType<T> t in types) {
       t.resolveIn(scope, this);
-      if (loader.target.strongMode) {
+      if (!loader.target.legacyMode) {
         t.checkType();
       } else {
         t.normalizeType();
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 f1f468a..9c6178f 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -782,9 +782,9 @@
     if (hierarchy == null) {
       hierarchy = new ClassHierarchy(computeFullComponent(),
           onAmbiguousSupertypes: onAmbiguousSupertypes,
-          mixinInferrer: target.strongMode
-              ? new StrongModeMixinInferrer(this)
-              : new LegacyModeMixinInferrer());
+          mixinInferrer: target.legacyMode
+              ? new LegacyModeMixinInferrer()
+              : new StrongModeMixinInferrer(this));
     } else {
       hierarchy.onAmbiguousSupertypes = onAmbiguousSupertypes;
       Component component = computeFullComponent();
@@ -832,11 +832,14 @@
   }
 
   void checkBounds() {
-    if (!target.strongMode) return;
+    if (target.legacyMode) return;
 
     builders.forEach((Uri uri, LibraryBuilder library) {
       if (library is SourceLibraryBuilder) {
-        library.checkBoundsInOutline(typeInferenceEngine.typeSchemaEnvironment);
+        if (library.loader == this) {
+          library
+              .checkBoundsInOutline(typeInferenceEngine.typeSchemaEnvironment);
+        }
       }
     });
     ticker.logMs("Checked type arguments of supers against the bounds");
@@ -854,7 +857,7 @@
   }
 
   void checkAbstractMembers(List<SourceClassBuilder> sourceClasses) {
-    if (!target.strongMode) return;
+    if (target.legacyMode) return;
     assert(hierarchy != null);
     for (SourceClassBuilder builder in sourceClasses) {
       if (builder.library.loader == this) {
@@ -866,7 +869,7 @@
   }
 
   void checkRedirectingFactories(List<SourceClassBuilder> sourceClasses) {
-    if (!target.strongMode) return;
+    if (target.legacyMode) return;
     for (SourceClassBuilder builder in sourceClasses) {
       if (builder.library.loader == this) {
         builder.checkRedirectingFactories(
@@ -909,7 +912,7 @@
 
   void createTypeInferenceEngine() {
     typeInferenceEngine =
-        new ShadowTypeInferenceEngine(instrumentation, target.strongMode);
+        new ShadowTypeInferenceEngine(instrumentation, target.legacyMode);
   }
 
   void performTopLevelInference(List<SourceClassBuilder> sourceClasses) {
@@ -924,7 +927,7 @@
         typeInferenceEngine,
         typeInferenceEngine.typeSchemaEnvironment,
         instrumentation,
-        target.strongMode);
+        target.legacyMode);
     builders.forEach((Uri uri, LibraryBuilder library) {
       if (library.loader == this) {
         library.forEach((String name, Declaration member) {
diff --git a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
new file mode 100644
index 0000000..3b60139
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
@@ -0,0 +1,1340 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library fasta.type_promotion_look_ahead_listener;
+
+import '../builder/builder.dart' show Declaration;
+
+import '../messages.dart' show LocatedMessage, Message;
+
+import '../parser.dart'
+    show Assert, IdentifierContext, FormalParameterKind, Listener, MemberKind;
+
+import '../problems.dart' as problems show unhandled;
+
+import '../scanner.dart' show Token;
+
+import '../scope.dart' show Scope;
+
+import '../severity.dart' show Severity;
+
+final NoArguments noArgumentsSentinel = new NoArguments();
+
+abstract class TypePromotionState {
+  final Uri uri;
+
+  final List<Scope> scopes = <Scope>[new Scope.top(isModifiable: true)];
+
+  final List<Declaration> stack = <Declaration>[];
+
+  TypePromotionState(this.uri);
+
+  Scope get currentScope => scopes.last;
+
+  void enterScope(String debugName) {
+    scopes.add(new Scope.nested(currentScope, "block"));
+  }
+
+  Scope exitScope(Token token) {
+    return scopes.removeLast();
+  }
+
+  void declareIdentifier(Token token) {
+    String name = token.lexeme;
+    LocatedMessage error = currentScope.declare(
+        name, new UnspecifiedDeclaration(name, uri, token.charOffset), uri);
+    if (error != null) {
+      report(error, Severity.error);
+    }
+    pushNull(token.lexeme, token);
+  }
+
+  void registerWrite(UnspecifiedDeclaration declaration, Token token) {}
+
+  void registerPromotionCandidate(
+      UnspecifiedDeclaration declaration, Token token) {}
+
+  void pushReference(Token token) {
+    String name = token.lexeme;
+    Declaration declaration = currentScope.lookup(name, token.charOffset, uri);
+    stack.add(declaration);
+  }
+
+  Declaration pop() => stack.removeLast();
+
+  void push(Declaration declaration) {
+    stack.add(declaration);
+  }
+
+  Declaration popPushNull(String name, Token token) {
+    int last = stack.length - 1;
+    Declaration declaration = stack[last];
+    stack[last] = nullValue(name, token);
+    return declaration;
+  }
+
+  void discard(int count) {
+    stack.length = stack.length - count;
+  }
+
+  void pushNull(String name, Token token) {
+    stack.add(nullValue(name, token));
+  }
+
+  Declaration nullValue(String name, Token token) => null;
+
+  void report(LocatedMessage message, Severity severity,
+      {List<LocatedMessage> context});
+
+  void trace(String message, Token token) {}
+
+  void checkEmpty(Token token) {}
+}
+
+class UnspecifiedDeclaration extends Declaration {
+  final String name;
+
+  @override
+  final Uri fileUri;
+
+  @override
+  int charOffset;
+
+  UnspecifiedDeclaration(this.name, this.fileUri, this.charOffset);
+
+  @override
+  Declaration get parent => null;
+
+  @override
+  String get fullNameForErrors => name;
+
+  @override
+  String toString() => "UnspecifiedDeclaration($name)";
+}
+
+class NoArguments extends Declaration {
+  NoArguments();
+
+  @override
+  Uri get fileUri => null;
+
+  @override
+  int get charOffset => -1;
+
+  @override
+  Declaration get parent => null;
+
+  @override
+  String get fullNameForErrors => "<<no arguments>>";
+
+  @override
+  String toString() => fullNameForErrors;
+}
+
+class TypePromotionLookAheadListener extends Listener {
+  final TypePromotionState state;
+
+  TypePromotionLookAheadListener(this.state);
+
+  Uri get uri => state.uri;
+
+  void debugEvent(String name, Token token) {
+    // state.trace(name, token);
+  }
+
+  @override
+  void endArguments(int count, Token beginToken, Token endToken) {
+    debugEvent("Arguments", beginToken);
+    state.discard(count);
+    state.pushNull("%Arguments%", endToken);
+  }
+
+  @override
+  void handleNoArguments(Token token) {
+    debugEvent("NoArguments", token);
+    state.push(noArgumentsSentinel);
+  }
+
+  @override
+  void handleAsOperator(Token operator) {
+    debugEvent("AsOperator", operator);
+    state.popPushNull(operator.lexeme, operator);
+  }
+
+  @override
+  void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
+      Token commaToken, Token semicolonToken) {
+    debugEvent("Assert", assertKeyword);
+    if (commaToken != null) {
+      state.pop(); // Message.
+    }
+    state.pop(); // Condition.
+    switch (kind) {
+      case Assert.Expression:
+        state.pushNull("%AssertExpression%", assertKeyword);
+        break;
+
+      case Assert.Initializer:
+        state.pushNull("%AssertInitializer%", assertKeyword);
+        break;
+
+      case Assert.Statement:
+        break;
+    }
+  }
+
+  @override
+  void handleAssignmentExpression(Token token) {
+    debugEvent("AssignmentExpression", token);
+    state.pop(); // Right-hand side.
+    Declaration lhs = state.popPushNull(token.lexeme, token);
+    if (lhs is UnspecifiedDeclaration) {
+      state.registerWrite(lhs, token);
+    }
+  }
+
+  @override
+  void handleAsyncModifier(Token asyncToken, Token starToken) {
+    debugEvent("AsyncModifier", asyncToken);
+  }
+
+  @override
+  void endAwaitExpression(Token beginToken, Token endToken) {
+    debugEvent("AwaitExpression", beginToken);
+    state.popPushNull(beginToken.lexeme, beginToken); // Expression.
+  }
+
+  @override
+  void endBinaryExpression(Token token) {
+    debugEvent("BinaryExpression", token);
+    state.pop(); // Right-hand side.
+    state.popPushNull(token.lexeme, token); // Left-hand side.
+  }
+
+  @override
+  void beginBlock(Token token) {
+    debugEvent("beginBlock", token);
+    state.enterScope("block");
+  }
+
+  @override
+  void endBlock(int count, Token beginToken, Token endToken) {
+    debugEvent("Block", beginToken);
+    state.exitScope(endToken);
+  }
+
+  @override
+  void beginBlockFunctionBody(Token token) {
+    debugEvent("beginBlockFunctionBody", token);
+    state.enterScope("block-function-body");
+  }
+
+  @override
+  void endBlockFunctionBody(int count, Token beginToken, Token endToken) {
+    debugEvent("BlockFunctionBody", beginToken);
+    state.exitScope(endToken);
+  }
+
+  @override
+  void handleBreakStatement(
+      bool hasTarget, Token breakKeyword, Token endToken) {
+    debugEvent("BreakStatement", breakKeyword);
+    if (hasTarget) {
+      state.pop(); // Target.
+    }
+  }
+
+  @override
+  void endCascade() {
+    debugEvent("Cascade", null);
+    state.popPushNull("%Cascade%", null);
+  }
+
+  @override
+  void endCaseExpression(Token colon) {
+    debugEvent("CaseExpression", colon);
+    state.pop(); // Expression.
+  }
+
+  @override
+  void handleCaseMatch(Token caseKeyword, Token colon) {
+    debugEvent("CaseMatch", caseKeyword);
+  }
+
+  @override
+  void handleCatchBlock(Token onKeyword, Token catchKeyword, Token comma) {
+    debugEvent("CatchBlock", catchKeyword);
+  }
+
+  @override
+  void endCatchClause(Token token) {
+    debugEvent("CatchClause", token);
+  }
+
+  @override
+  void endClassDeclaration(Token beginToken, Token endToken) {
+    debugEvent("ClassDeclaration", beginToken);
+    state.checkEmpty(endToken);
+  }
+
+  @override
+  void handleClassExtends(Token extendsKeyword) {
+    debugEvent("ClassExtends", extendsKeyword);
+  }
+
+  @override
+  void handleClassHeader(Token begin, Token classKeyword, Token nativeToken) {
+    debugEvent("ClassHeader", begin);
+    state.pop(); // Class name.
+    state.checkEmpty(classKeyword);
+  }
+
+  @override
+  void handleClassNoWithClause() {
+    debugEvent("ClassNoWithClause", null);
+  }
+
+  @override
+  void endClassOrMixinBody(int memberCount, Token beginToken, Token endToken) {
+    debugEvent("ClassOrMixinBody", beginToken);
+    state.checkEmpty(endToken);
+  }
+
+  @override
+  void handleClassOrMixinImplements(
+      Token implementsKeyword, int interfacesCount) {
+    debugEvent("ClassOrMixinImplements", implementsKeyword);
+  }
+
+  @override
+  void handleClassWithClause(Token withKeyword) {
+    debugEvent("ClassWithClause", withKeyword);
+  }
+
+  @override
+  void endCombinators(int count) {
+    debugEvent("Combinators", null);
+  }
+
+  @override
+  void handleCommentReference(
+      Token newKeyword, Token prefix, Token period, Token token) {
+    debugEvent("CommentReference", newKeyword);
+    unhandled("CommentReference", newKeyword);
+  }
+
+  @override
+  void handleNoCommentReference() {
+    debugEvent("NoCommentReference", null);
+    unhandled("NoCommentReference", null);
+  }
+
+  @override
+  void handleCommentReferenceText(String referenceSource, int referenceOffset) {
+    debugEvent("CommentReferenceText", null);
+    unhandled("CommentReferenceText", null);
+  }
+
+  @override
+  void endCompilationUnit(int count, Token token) {
+    debugEvent("CompilationUnit", token);
+    print(state.stack);
+  }
+
+  @override
+  void endConditionalExpression(Token question, Token colon) {
+    debugEvent("ConditionalExpression", question);
+    state.pop(); // Otherwise expression.
+    state.pop(); // Then expression.
+    state.popPushNull(question.lexeme, question); // Condition.
+  }
+
+  @override
+  void handleConditionalExpressionColon() {
+    debugEvent("ConditionalExpressionColon", null);
+    // TODO(ahe): Rename this event. This is not handling any colons as it
+    // isn't being passed a colon. One alternative is
+    // handleConditionalThenExpression, but check the specification for naming
+    // conventions. Kernel uses "then" and "otherwise".
+  }
+
+  @override
+  void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
+    debugEvent("ConditionalUri", ifKeyword);
+    unhandled("ConditionalUri", ifKeyword);
+  }
+
+  @override
+  void endConditionalUris(int count) {
+    debugEvent("ConditionalUris", null);
+  }
+
+  @override
+  void endConstExpression(Token token) {
+    debugEvent("ConstExpression", token);
+    doConstuctorInvocation(token, true);
+  }
+
+  void doConstuctorInvocation(Token token, bool isConst) {
+    state.pop(); // Arguments.
+    state.popPushNull(token.lexeme, token); // Constructor reference.
+  }
+
+  @override
+  void endConstLiteral(Token token) {
+    debugEvent("ConstLiteral", token);
+    state.popPushNull("%ConstLiteral%", token);
+  }
+
+  @override
+  void endConstructorReference(
+      Token start, Token periodBeforeName, Token endToken) {
+    debugEvent("ConstructorReference", start);
+    if (periodBeforeName != null) {
+      state.pop(); // Prefix.
+    }
+    state.popPushNull("%ConstructorReference%", start);
+  }
+
+  @override
+  void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
+    debugEvent("NoConstructorReferenceContinuationAfterTypeArguments", token);
+  }
+
+  @override
+  void handleContinueStatement(
+      bool hasTarget, Token continueKeyword, Token endToken) {
+    debugEvent("ContinueStatement", continueKeyword);
+    if (hasTarget) {
+      state.pop(); // Target.
+    }
+  }
+
+  @override
+  void handleDirectivesOnly() {
+    debugEvent("DirectivesOnly", null);
+    unhandled("DirectivesOnly", null);
+  }
+
+  @override
+  void endDoWhileStatement(
+      Token doKeyword, Token whileKeyword, Token endToken) {
+    debugEvent("DoWhileStatement", doKeyword);
+    state.pop(); // Condition.
+  }
+
+  @override
+  void endDoWhileStatementBody(Token token) {
+    debugEvent("DoWhileStatementBody", token);
+  }
+
+  @override
+  void handleDottedName(int count, Token firstIdentifier) {
+    debugEvent("DottedName", firstIdentifier);
+    unhandled("DottedName", firstIdentifier);
+  }
+
+  @override
+  void endElseStatement(Token token) {
+    debugEvent("ElseStatement", token);
+  }
+
+  @override
+  void handleEmptyFunctionBody(Token semicolon) {
+    debugEvent("EmptyFunctionBody", semicolon);
+  }
+
+  @override
+  void handleEmptyStatement(Token token) {
+    debugEvent("EmptyStatement", token);
+  }
+
+  @override
+  void beginEnum(Token enumKeyword) {
+    debugEvent("beginEnum", enumKeyword);
+    state.checkEmpty(enumKeyword);
+  }
+
+  @override
+  void endEnum(Token enumKeyword, Token leftBrace, int count) {
+    debugEvent("endEnum", enumKeyword);
+    state.discard(count); // Enum values.
+    state.pop(); // Enum name.
+    state.checkEmpty(enumKeyword);
+  }
+
+  @override
+  void endExport(Token exportKeyword, Token semicolon) {
+    debugEvent("Export", exportKeyword);
+    state.pop(); // Export URI.
+    state.checkEmpty(semicolon);
+  }
+
+  @override
+  void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
+    debugEvent("ExpressionFunctionBody", arrowToken);
+    state.pop();
+  }
+
+  @override
+  void endExpressionStatement(Token token) {
+    debugEvent("ExpressionStatement", token);
+    state.pop();
+  }
+
+  @override
+  void handleExtraneousExpression(Token token, Message message) {
+    debugEvent("ExtraneousExpression", token);
+    unhandled("ExtraneousExpression", token);
+  }
+
+  @override
+  void endFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    debugEvent("FactoryMethod", beginToken);
+    state.pop(); // Name.
+    state.checkEmpty(endToken);
+  }
+
+  @override
+  void endFieldInitializer(Token assignment, Token token) {
+    debugEvent("FieldInitializer", assignment);
+    state.pop(); // Initializer.
+  }
+
+  @override
+  void handleNoFieldInitializer(Token token) {
+    debugEvent("NoFieldInitializer", token);
+  }
+
+  @override
+  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+      int count, Token beginToken, Token endToken) {
+    debugEvent("Fields", staticToken);
+    state.discard(count); // Field names.
+    state.checkEmpty(endToken);
+  }
+
+  @override
+  void handleFinallyBlock(Token finallyKeyword) {
+    debugEvent("FinallyBlock", finallyKeyword);
+  }
+
+  @override
+  void endForIn(Token awaitToken, Token forToken, Token leftParenthesis,
+      Token inKeyword, Token endToken) {
+    debugEvent("ForIn", awaitToken);
+  }
+
+  @override
+  void endForInBody(Token token) {
+    debugEvent("ForInBody", token);
+  }
+
+  @override
+  void endForInExpression(Token token) {
+    debugEvent("ForInExpression", token);
+    state.pop(); // Expression.
+  }
+
+  @override
+  void handleForInitializerEmptyStatement(Token token) {
+    debugEvent("ForInitializerEmptyStatement", token);
+  }
+
+  @override
+  void handleForInitializerExpressionStatement(Token token) {
+    debugEvent("ForInitializerExpressionStatement", token);
+    state.pop(); // Expression.
+  }
+
+  @override
+  void handleForInitializerLocalVariableDeclaration(Token token) {
+    debugEvent("ForInitializerLocalVariableDeclaration", token);
+  }
+
+  @override
+  void endForStatement(Token forKeyword, Token leftParen, Token leftSeparator,
+      int updateExpressionCount, Token endToken) {
+    debugEvent("ForStatement", forKeyword);
+    state.discard(updateExpressionCount);
+  }
+
+  @override
+  void endForStatementBody(Token token) {
+    debugEvent("ForStatementBody", token);
+  }
+
+  @override
+  void endFormalParameter(Token thisKeyword, Token periodAfterThis,
+      Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
+    debugEvent("FormalParameter", thisKeyword);
+    state.pop(); // Parameter name.
+  }
+
+  @override
+  void endFormalParameterDefaultValueExpression() {
+    debugEvent("FormalParameterDefaultValueExpression", null);
+    state.pop();
+  }
+
+  @override
+  void handleFormalParameterWithoutValue(Token token) {
+    debugEvent("FormalParameterWithoutValue", token);
+  }
+
+  @override
+  void endFormalParameters(
+      int count, Token beginToken, Token endToken, MemberKind kind) {
+    debugEvent("FormalParameters", beginToken);
+  }
+
+  @override
+  void handleNoFormalParameters(Token token, MemberKind kind) {
+    debugEvent("NoFormalParameters", token);
+  }
+
+  @override
+  void handleNoFunctionBody(Token token) {
+    debugEvent("NoFunctionBody", token);
+    unhandled("NoFunctionBody", token);
+  }
+
+  @override
+  void handleFunctionBodySkipped(Token token, bool isExpressionBody) {
+    debugEvent("FunctionBodySkipped", token);
+    unhandled("FunctionBodySkipped", token);
+  }
+
+  @override
+  void endFunctionExpression(Token beginToken, Token token) {
+    debugEvent("FunctionExpression", beginToken);
+    state.pushNull("%function%", token);
+  }
+
+  @override
+  void endFunctionName(Token beginToken, Token token) {
+    debugEvent("FunctionName", beginToken);
+  }
+
+  @override
+  void endFunctionType(Token functionToken) {
+    debugEvent("FunctionType", functionToken);
+  }
+
+  @override
+  void endFunctionTypeAlias(
+      Token typedefKeyword, Token equals, Token endToken) {
+    debugEvent("FunctionTypeAlias", typedefKeyword);
+    state.pop(); // Name.
+    state.checkEmpty(endToken);
+  }
+
+  @override
+  void endFunctionTypedFormalParameter(Token nameToken) {
+    debugEvent("FunctionTypedFormalParameter", nameToken);
+  }
+
+  @override
+  void endHide(Token hideKeyword) {
+    debugEvent("Hide", hideKeyword);
+  }
+
+  @override
+  void handleIdentifier(Token token, IdentifierContext context) {
+    debugEvent("Identifier ${context}", token);
+    if (context.inSymbol) {
+      // Do nothing.
+    } else if (context.inDeclaration) {
+      if (identical(IdentifierContext.localVariableDeclaration, context) ||
+          identical(IdentifierContext.formalParameterDeclaration, context)) {
+        state.declareIdentifier(token);
+      } else {
+        state.pushNull(token.lexeme, token);
+      }
+    } else if (context.isContinuation) {
+      state.pushNull(token.lexeme, token);
+    } else if (context.isScopeReference) {
+      state.pushReference(token);
+    } else {
+      state.pushNull(token.lexeme, token);
+    }
+  }
+
+  @override
+  void handleIdentifierList(int count) {
+    debugEvent("IdentifierList", null);
+    state.discard(count);
+  }
+
+  @override
+  void endIfStatement(Token ifToken, Token elseToken) {
+    debugEvent("IfStatement", ifToken);
+    state.pop(); // Condition.
+  }
+
+  @override
+  void endImplicitCreationExpression(Token token) {
+    debugEvent("ImplicitCreationExpression", token);
+    doConstuctorInvocation(token, false);
+  }
+
+  @override
+  void endImport(Token importKeyword, Token semicolon) {
+    debugEvent("Import", importKeyword);
+    state.pop(); // Import URI.
+    state.checkEmpty(semicolon);
+  }
+
+  @override
+  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+    debugEvent("ImportPrefix", deferredKeyword);
+    if (asKeyword != null) {
+      state.pop(); // Prefix name.
+    }
+  }
+
+  @override
+  void handleIndexedExpression(
+      Token openSquareBracket, Token closeSquareBracket) {
+    debugEvent("IndexedExpression", openSquareBracket);
+    state.pop(); // Index.
+    state.popPushNull("%indexed%", closeSquareBracket); // Expression.
+  }
+
+  @override
+  void endInitializedIdentifier(Token nameToken) {
+    debugEvent("InitializedIdentifier", nameToken);
+  }
+
+  @override
+  void endInitializer(Token token) {
+    debugEvent("Initializer", token);
+    state.pop(); // Initializer.
+  }
+
+  @override
+  void endInitializers(int count, Token beginToken, Token endToken) {
+    debugEvent("Initializers", beginToken);
+  }
+
+  @override
+  void handleNoInitializers() {
+    debugEvent("NoInitializers", null);
+  }
+
+  @override
+  void handleInterpolationExpression(Token leftBracket, Token rightBracket) {
+    debugEvent("InterpolationExpression", leftBracket);
+    state.popPushNull(r"$", leftBracket);
+  }
+
+  @override
+  void handleInvalidExpression(Token token) {
+    // TODO(ahe): The parser doesn't generate this event anymore.
+    debugEvent("InvalidExpression", token);
+    unhandled("InvalidExpression", token);
+  }
+
+  @override
+  void handleInvalidFunctionBody(Token token) {
+    debugEvent("InvalidFunctionBody", token);
+  }
+
+  @override
+  void handleInvalidMember(Token endToken) {
+    debugEvent("InvalidMember", endToken);
+    state.checkEmpty(endToken);
+  }
+
+  @override
+  void handleInvalidOperatorName(Token operatorKeyword, Token token) {
+    debugEvent("InvalidOperatorName", operatorKeyword);
+    state.checkEmpty(operatorKeyword);
+  }
+
+  @override
+  void handleInvalidStatement(Token token, Message message) {
+    debugEvent("InvalidStatement", token);
+  }
+
+  @override
+  void handleInvalidTopLevelBlock(Token token) {
+    debugEvent("InvalidTopLevelBlock", token);
+    state.checkEmpty(token);
+  }
+
+  @override
+  void handleInvalidTopLevelDeclaration(Token endToken) {
+    debugEvent("InvalidTopLevelDeclaration", endToken);
+    state.checkEmpty(endToken);
+  }
+
+  @override
+  void handleInvalidTypeArguments(Token token) {
+    debugEvent("InvalidTypeArguments", token);
+  }
+
+  @override
+  void handleInvalidTypeReference(Token token) {
+    debugEvent("InvalidTypeReference", token);
+    unhandled("InvalidTypeReference", token);
+  }
+
+  @override
+  void handleIsOperator(Token isOperator, Token not) {
+    debugEvent("IsOperator", isOperator);
+    Declaration lhs = state.popPushNull(isOperator.lexeme, isOperator);
+    if (not == null && lhs is UnspecifiedDeclaration) {
+      state.registerPromotionCandidate(lhs, isOperator);
+    }
+  }
+
+  @override
+  void handleLabel(Token token) {
+    debugEvent("Label", token);
+    state.pop(); // Label.
+  }
+
+  @override
+  void endLabeledStatement(int labelCount) {
+    debugEvent("LabeledStatement", null);
+  }
+
+  @override
+  void endLibraryName(Token libraryKeyword, Token semicolon) {
+    debugEvent("LibraryName", libraryKeyword);
+    state.pop(); // Library name.
+    state.checkEmpty(semicolon);
+  }
+
+  @override
+  void handleLiteralBool(Token token) {
+    debugEvent("LiteralBool", token);
+    state.pushNull(token.lexeme, token);
+  }
+
+  @override
+  void handleLiteralDouble(Token token) {
+    debugEvent("LiteralDouble", token);
+    state.pushNull(token.lexeme, token);
+  }
+
+  @override
+  void handleLiteralInt(Token token) {
+    debugEvent("LiteralInt", token);
+    state.pushNull(token.lexeme, token);
+  }
+
+  @override
+  void handleLiteralList(
+      int count, Token leftBracket, Token constKeyword, Token rightBracket) {
+    debugEvent("LiteralList", leftBracket);
+    state.discard(count);
+    state.pushNull("[]", leftBracket);
+  }
+
+  @override
+  void handleLiteralMap(
+      int count, Token leftBrace, Token constKeyword, Token rightBrace) {
+    debugEvent("LiteralMap", leftBrace);
+    state.discard(count);
+    state.pushNull("{}", leftBrace);
+  }
+
+  @override
+  void endLiteralMapEntry(Token colon, Token endToken) {
+    debugEvent("LiteralMapEntry", colon);
+    state.pop(); // Value.
+    state.popPushNull("%LiteralMapEntry%", colon); // Key.
+  }
+
+  @override
+  void handleLiteralNull(Token token) {
+    debugEvent("LiteralNull", token);
+    state.pushNull(token.lexeme, token);
+  }
+
+  @override
+  void beginLiteralString(Token token) {
+    debugEvent("beginLiteralString", token);
+    state.pushNull(token.lexeme, token);
+  }
+
+  @override
+  void endLiteralString(int interpolationCount, Token endToken) {
+    debugEvent("LiteralString", endToken);
+    state.discard(interpolationCount * 2);
+    state.popPushNull("%string%", endToken);
+  }
+
+  @override
+  void endLiteralSymbol(Token hashToken, int identifierCount) {
+    debugEvent("LiteralSymbol", hashToken);
+    state.pushNull(hashToken.lexeme, hashToken);
+  }
+
+  @override
+  void endLocalFunctionDeclaration(Token endToken) {
+    debugEvent("LocalFunctionDeclaration", endToken);
+    state.pop(); // Function name.
+  }
+
+  @override
+  void endMember() {
+    debugEvent("Member", null);
+    state.checkEmpty(null);
+  }
+
+  @override
+  void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
+    debugEvent("Metadata", beginToken);
+    state.pop(); // Arguments.
+    if (periodBeforeName != null) {
+      state.pop(); // Suffix.
+    }
+    state.pop(); // Qualifier.
+  }
+
+  @override
+  void endMetadataStar(int count) {
+    debugEvent("MetadataStar", null);
+  }
+
+  @override
+  void beginMethod(Token externalToken, Token staticToken, Token covariantToken,
+      Token varFinalOrConst, Token getOrSet, Token name) {
+    debugEvent("beginMethod", name);
+    state.checkEmpty(name);
+  }
+
+  @override
+  void endMethod(
+      Token getOrSet, Token beginToken, Token beginParam, Token endToken) {
+    debugEvent("endMethod", endToken);
+    state.pop(); // Method name.
+    state.checkEmpty(endToken);
+  }
+
+  @override
+  void endMixinDeclaration(Token mixinKeyword, Token endToken) {
+    debugEvent("MixinDeclaration", mixinKeyword);
+    state.checkEmpty(endToken);
+  }
+
+  @override
+  void handleMixinHeader(Token mixinKeyword) {
+    debugEvent("MixinHeader", mixinKeyword);
+    state.pop(); // Mixin name.
+    state.checkEmpty(mixinKeyword);
+  }
+
+  @override
+  void handleMixinOn(Token onKeyword, int typeCount) {
+    debugEvent("MixinOn", onKeyword);
+  }
+
+  @override
+  void handleNoName(Token token) {
+    debugEvent("NoName", token);
+    state.pushNull("%NoName%", token);
+  }
+
+  @override
+  void handleNamedArgument(Token colon) {
+    debugEvent("NamedArgument", colon);
+    state.pop(); // Expression.
+    state.popPushNull("%NamedArgument%", colon); // Identifier.
+  }
+
+  @override
+  void endNamedFunctionExpression(Token endToken) {
+    debugEvent("NamedFunctionExpression", endToken);
+    state.popPushNull(
+        "%named function expression%", endToken); // Function name.
+  }
+
+  @override
+  void endNamedMixinApplication(Token begin, Token classKeyword, Token equals,
+      Token implementsKeyword, Token endToken) {
+    debugEvent("NamedMixinApplication", begin);
+    state.pop(); // Mixin application name.
+    state.checkEmpty(endToken);
+  }
+
+  @override
+  void handleNamedMixinApplicationWithClause(Token withKeyword) {
+    debugEvent("NamedMixinApplicationWithClause", withKeyword);
+  }
+
+  @override
+  void handleNativeClause(Token nativeToken, bool hasName) {
+    debugEvent("NativeClause", nativeToken);
+    if (hasName) {
+      state.pop(); // Name.
+    }
+  }
+
+  @override
+  void handleNativeFunctionBody(Token nativeToken, Token semicolon) {
+    debugEvent("NativeFunctionBody", nativeToken);
+  }
+
+  @override
+  void handleNativeFunctionBodyIgnored(Token nativeToken, Token semicolon) {
+    debugEvent("NativeFunctionBodyIgnored", nativeToken);
+  }
+
+  @override
+  void handleNativeFunctionBodySkipped(Token nativeToken, Token semicolon) {
+    debugEvent("NativeFunctionBodySkipped", nativeToken);
+  }
+
+  @override
+  void endNewExpression(Token token) {
+    debugEvent("NewExpression", token);
+    doConstuctorInvocation(token, false);
+  }
+
+  @override
+  void handleOperator(Token token) {
+    debugEvent("Operator", token);
+    unhandled("Operator", token);
+  }
+
+  @override
+  void handleOperatorName(Token operatorKeyword, Token token) {
+    debugEvent("OperatorName", operatorKeyword);
+    state.pushNull(token.lexeme, token);
+  }
+
+  @override
+  void endOptionalFormalParameters(
+      int count, Token beginToken, Token endToken) {
+    debugEvent("OptionalFormalParameters", beginToken);
+  }
+
+  @override
+  void handleParenthesizedCondition(Token token) {
+    debugEvent("ParenthesizedCondition", token);
+  }
+
+  @override
+  void handleParenthesizedExpression(Token token) {
+    debugEvent("ParenthesizedExpression", token);
+    state.popPushNull("%(expr)%", token);
+  }
+
+  @override
+  void endPart(Token partKeyword, Token semicolon) {
+    debugEvent("Part", partKeyword);
+    state.pop(); // URI.
+    state.checkEmpty(semicolon);
+  }
+
+  @override
+  void endPartOf(
+      Token partKeyword, Token ofKeyword, Token semicolon, bool hasName) {
+    debugEvent("PartOf", partKeyword);
+    state.pop(); // Name or URI.
+    state.checkEmpty(semicolon);
+  }
+
+  @override
+  void handleQualified(Token period) {
+    debugEvent("Qualified", period);
+    state.pop(); // Suffix.
+    state.popPushNull("%Qualified%", period); // Qualifier.
+  }
+
+  @override
+  void handleRecoverClassHeader() {
+    debugEvent("RecoverClassHeader", null);
+    state.checkEmpty(null);
+  }
+
+  @override
+  void handleRecoverImport(Token semicolon) {
+    debugEvent("RecoverImport", semicolon);
+    unhandled("RecoverImport", semicolon);
+  }
+
+  @override
+  void handleRecoverMixinHeader() {
+    debugEvent("RecoverMixinHeader", null);
+    state.checkEmpty(null);
+  }
+
+  @override
+  void handleRecoverableError(
+      Message message, Token startToken, Token endToken) {
+    debugEvent("RecoverableError ${message.message}", startToken);
+  }
+
+  @override
+  void endRedirectingFactoryBody(Token beginToken, Token endToken) {
+    debugEvent("RedirectingFactoryBody", beginToken);
+    state.pop(); // Constructor reference.
+  }
+
+  @override
+  void endRethrowStatement(Token rethrowToken, Token endToken) {
+    debugEvent("RethrowStatement", rethrowToken);
+  }
+
+  @override
+  void endReturnStatement(
+      bool hasExpression, Token beginToken, Token endToken) {
+    debugEvent("ReturnStatement", beginToken);
+    if (hasExpression) {
+      state.pop(); // Expression.
+    }
+  }
+
+  @override
+  void handleScript(Token token) {
+    debugEvent("Script", token);
+    unhandled("Script", token);
+  }
+
+  @override
+  void handleSend(Token beginToken, Token endToken) {
+    debugEvent("Send", beginToken);
+    Declaration arguments = state.pop();
+    if (identical(arguments, noArgumentsSentinel)) {
+      // Leave the receiver on the stack.
+    } else {
+      state.popPushNull("%send%", beginToken);
+    }
+  }
+
+  @override
+  void endShow(Token showKeyword) {
+    debugEvent("Show", showKeyword);
+  }
+
+  @override
+  void handleStringJuxtaposition(int literalCount) {
+    debugEvent("StringJuxtaposition", null);
+    state.discard(literalCount);
+    state.pushNull("%StringJuxtaposition%", null);
+  }
+
+  @override
+  void handleStringPart(Token token) {
+    debugEvent("StringPart", token);
+    state.pushNull(token.lexeme, token);
+  }
+
+  @override
+  void handleSuperExpression(Token token, IdentifierContext context) {
+    debugEvent("SuperExpression", token);
+    state.pushNull(token.lexeme, token);
+  }
+
+  @override
+  void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
+    debugEvent("SwitchBlock", beginToken);
+    state.pop(); // Expression.
+  }
+
+  @override
+  void endSwitchCase(
+      int labelCount,
+      int expressionCount,
+      Token defaultKeyword,
+      Token colonAfterDefault,
+      int statementCount,
+      Token firstToken,
+      Token endToken) {
+    debugEvent("SwitchCase", defaultKeyword);
+  }
+
+  @override
+  void endSwitchStatement(Token switchKeyword, Token endToken) {
+    debugEvent("SwitchStatement", switchKeyword);
+  }
+
+  @override
+  void handleSymbolVoid(Token token) {
+    debugEvent("SymbolVoid", token);
+    unhandled("SymbolVoid", token);
+  }
+
+  @override
+  void endThenStatement(Token token) {
+    debugEvent("ThenStatement", token);
+  }
+
+  @override
+  void handleThisExpression(Token token, IdentifierContext context) {
+    debugEvent("ThisExpression", token);
+    state.pushNull(token.lexeme, token);
+  }
+
+  @override
+  void handleThrowExpression(Token throwToken, Token endToken) {
+    debugEvent("ThrowExpression", throwToken);
+    state.popPushNull(throwToken.lexeme, throwToken);
+  }
+
+  @override
+  void endTopLevelDeclaration(Token token) {
+    debugEvent("TopLevelDeclaration", token);
+    state.checkEmpty(token);
+  }
+
+  @override
+  void endTopLevelFields(Token staticToken, Token covariantToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+    debugEvent("TopLevelFields", staticToken);
+    state.discard(count); // Field names.
+    state.checkEmpty(endToken);
+  }
+
+  @override
+  void beginTopLevelMethod(Token lastConsumed, Token externalToken) {
+    debugEvent("beginTopLevelMethod", lastConsumed.next);
+    state.checkEmpty(lastConsumed.next);
+  }
+
+  @override
+  void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
+    debugEvent("endTopLevelMethod", beginToken);
+    state.pop(); // Method name.
+    state.checkEmpty(endToken);
+  }
+
+  @override
+  void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
+    debugEvent("TryStatement", tryKeyword);
+  }
+
+  @override
+  void handleType(Token beginToken) {
+    debugEvent("Type", beginToken);
+    state.pop();
+  }
+
+  @override
+  void handleNoType(Token lastConsumed) {
+    debugEvent("NoType", lastConsumed);
+  }
+
+  @override
+  void endTypeArguments(int count, Token beginToken, Token endToken) {
+    debugEvent("TypeArguments", beginToken);
+  }
+
+  @override
+  void handleNoTypeArguments(Token token) {
+    debugEvent("NoTypeArguments", token);
+  }
+
+  @override
+  void endTypeList(int count) {
+    debugEvent("TypeList", null);
+  }
+
+  @override
+  void endTypeVariable(Token token, int index, Token extendsOrSuper) {
+    debugEvent("TypeVariable", token);
+    state.pop(); // Name.
+  }
+
+  @override
+  void endTypeVariables(Token beginToken, Token endToken) {
+    debugEvent("TypeVariables", beginToken);
+  }
+
+  @override
+  void handleNoTypeVariables(Token token) {
+    debugEvent("NoTypeVariables", token);
+  }
+
+  @override
+  void handleTypeVariablesDefined(Token token, int count) {
+    debugEvent("TypeVariablesDefined", token);
+  }
+
+  @override
+  void handleUnaryPostfixAssignmentExpression(Token token) {
+    debugEvent("UnaryPostfixAssignmentExpression", token);
+    Declaration expr = state.popPushNull(token.lexeme, token);
+    if (expr is UnspecifiedDeclaration) {
+      state.registerWrite(expr, token);
+    }
+  }
+
+  @override
+  void handleUnaryPrefixAssignmentExpression(Token token) {
+    debugEvent("UnaryPrefixAssignmentExpression", token);
+    Declaration expr = state.popPushNull(token.lexeme, token);
+    if (expr is UnspecifiedDeclaration) {
+      state.registerWrite(expr, token);
+    }
+  }
+
+  @override
+  void handleUnaryPrefixExpression(Token token) {
+    debugEvent("UnaryPrefixExpression", token);
+    state.popPushNull("%UnaryPrefixExpression%", token);
+  }
+
+  @override
+  void handleUnescapeError(
+      Message message, Token location, int stringOffset, int length) {
+    debugEvent("UnescapeError", location);
+    unhandled("UnescapeError", location);
+  }
+
+  @override
+  void handleValuedFormalParameter(Token equals, Token token) {
+    debugEvent("ValuedFormalParameter", equals);
+  }
+
+  @override
+  void endVariableInitializer(Token assignmentOperator) {
+    debugEvent("VariableInitializer", assignmentOperator);
+    state.pop(); // Initializer.
+  }
+
+  @override
+  void handleNoVariableInitializer(Token token) {
+    debugEvent("NoVariableInitializer", token);
+  }
+
+  @override
+  void endVariablesDeclaration(int count, Token endToken) {
+    debugEvent("VariablesDeclaration", endToken);
+    state.discard(count); // Variable names.
+  }
+
+  @override
+  void handleVoidKeyword(Token token) {
+    debugEvent("VoidKeyword", token);
+  }
+
+  @override
+  void endWhileStatement(Token whileKeyword, Token endToken) {
+    debugEvent("WhileStatement", whileKeyword);
+    state.pop(); // Condition.
+  }
+
+  @override
+  void endWhileStatementBody(Token token) {
+    debugEvent("WhileStatementBody", token);
+  }
+
+  @override
+  void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
+    debugEvent("YieldStatement", yieldToken);
+    state.pop(); // Expression.
+  }
+
+  void unhandled(String event, Token token) {
+    problems.unhandled(
+        event, "TypePromotionLookAheadListener", token?.charOffset ?? -1, uri);
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/testing/kernel_chain.dart b/pkg/front_end/lib/src/fasta/testing/kernel_chain.dart
index 608b2bc..5e2944d 100644
--- a/pkg/front_end/lib/src/fasta/testing/kernel_chain.dart
+++ b/pkg/front_end/lib/src/fasta/testing/kernel_chain.dart
@@ -128,9 +128,9 @@
 
   Future<Result<Component>> run(Component component, dynamic context) async {
     StringBuffer messages = context.componentToDiagnostics[component];
+    Uri uri = component.uriToSource.keys.first;
     Library library = component.libraries
         .firstWhere((Library library) => library.importUri.scheme != "dart");
-    Uri uri = library.importUri;
     Uri base = uri.resolve(".");
     Uri dartBase = Uri.base;
     StringBuffer buffer = new StringBuffer();
@@ -164,7 +164,11 @@
       if (expected.trim() != actual.trim()) {
         if (!updateExpectations) {
           String diff = await runDiff(expectedFile.uri, actual);
-          return fail(null, "$uri doesn't match ${expectedFile.uri}\n$diff");
+          return new Result<Component>(
+              component,
+              context.expectationSet["ExpectationFileMismatch"],
+              "$uri doesn't match ${expectedFile.uri}\n$diff",
+              null);
         }
       } else {
         return pass(component);
@@ -176,9 +180,13 @@
       });
       return pass(component);
     } else {
-      return fail(component, """
+      return new Result<Component>(
+          component,
+          context.expectationSet["ExpectationFileMissing"],
+          """
 Please create file ${expectedFile.path} with this content:
-$actual""");
+$actual""",
+          null);
     }
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/testing/scanner_chain.dart b/pkg/front_end/lib/src/fasta/testing/scanner_chain.dart
index 277697e..151291f 100644
--- a/pkg/front_end/lib/src/fasta/testing/scanner_chain.dart
+++ b/pkg/front_end/lib/src/fasta/testing/scanner_chain.dart
@@ -10,24 +10,39 @@
 
 import '../scanner/io.dart';
 
-class Read extends Step<TestDescription, List<int>, ChainContext> {
+class ReadFile {
+  final Uri uri;
+
+  final List<int> bytes;
+
+  const ReadFile(this.uri, this.bytes);
+}
+
+class ScannedFile {
+  final ReadFile file;
+
+  final ScannerResult result;
+
+  const ScannedFile(this.file, this.result);
+}
+
+class Read extends Step<TestDescription, ReadFile, ChainContext> {
   const Read();
 
   String get name => "read";
 
-  Future<Result<List<int>>> run(
+  Future<Result<ReadFile>> run(
       TestDescription input, ChainContext context) async {
-    return pass(await readBytesFromFile(input.uri));
+    return pass(new ReadFile(input.uri, await readBytesFromFile(input.uri)));
   }
 }
 
-class Scan extends Step<List<int>, ScannerResult, ChainContext> {
+class Scan extends Step<ReadFile, ScannedFile, ChainContext> {
   const Scan();
 
   String get name => "scan";
 
-  Future<Result<ScannerResult>> run(
-      List<int> bytes, ChainContext context) async {
-    return pass(scan(bytes));
+  Future<Result<ScannedFile>> run(ReadFile file, ChainContext context) async {
+    return pass(new ScannedFile(file, scan(file.bytes)));
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart b/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
index 879e18f..fba244b 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
@@ -257,7 +257,7 @@
   /// they would not be checked in an inherited implementation, a forwarding
   /// stub is introduced as a place to put the checks.
   Procedure _computeCovarianceFixes(Procedure interfaceMember) {
-    assert(_interfaceResolver.strongMode);
+    assert(!_interfaceResolver.legacyMode);
     var substitution =
         _interfaceResolver._substitutionFor(interfaceMember, enclosingClass);
     // We always create a forwarding stub when we've inherited a member from an
@@ -546,7 +546,7 @@
   /// Creates a forwarding stub for this node if necessary, and propagates
   /// covariance information.
   Procedure _finalize() {
-    return _interfaceResolver.strongMode
+    return !_interfaceResolver.legacyMode
         ? _computeCovarianceFixes(resolve())
         : resolve();
   }
@@ -682,10 +682,10 @@
 
   final Instrumentation _instrumentation;
 
-  final bool strongMode;
+  final bool legacyMode;
 
   InterfaceResolver(this._typeInferenceEngine, this._typeEnvironment,
-      this._instrumentation, this.strongMode);
+      this._instrumentation, this.legacyMode);
 
   /// Indicates whether the "prepare" phase of type inference is complete.
   bool get isTypeInferencePrepared =>
@@ -839,7 +839,7 @@
     // getter and a setter.  We will report both conflicts.
     Map<Name, List<Member>> staticMembers = {};
     for (var procedure in class_.procedures) {
-      if (procedure.isStatic) {
+      if (procedure.isStatic && !procedure.isFactory) {
         staticMembers.putIfAbsent(procedure.name, () => []).add(procedure);
       }
     }
@@ -924,7 +924,7 @@
             return;
           }
         }
-        if (strongMode &&
+        if (!legacyMode &&
             member.enclosingClass == class_ &&
             _requiresTypeInference(member)) {
           inferMethodType(library, class_, member, candidates, start + 1, end);
@@ -1067,7 +1067,7 @@
       if (resolution is Procedure &&
           resolution.isSyntheticForwarder &&
           identical(resolution.enclosingClass, class_)) {
-        if (strongMode) class_.addMember(resolution);
+        if (!legacyMode) class_.addMember(resolution);
         _instrumentation?.record(
             class_.location.file,
             class_.fileOffset,
@@ -1128,10 +1128,10 @@
       Uri fileUri) {
     InferenceNode node;
     if (procedure.isAccessor && _requiresTypeInference(procedure)) {
-      if (strongMode && start < end) {
+      if (!legacyMode && start < end) {
         node = new AccessorInferenceNode(
             this, procedure, candidates, start, end, library, fileUri);
-      } else if (strongMode && crossStart < crossEnd) {
+      } else if (!legacyMode && crossStart < crossEnd) {
         node = new AccessorInferenceNode(this, procedure, candidates,
             crossStart, crossEnd, library, fileUri);
       } else if (procedure is SyntheticAccessor &&
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index c5ebbb1..fda2de0 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -48,7 +48,7 @@
 
   @override
   void resolveInternal() {
-    if (_typeInferenceEngine.strongMode) {
+    if (!_typeInferenceEngine.legacyMode) {
       var typeInferrer = _typeInferenceEngine.getFieldTypeInferrer(field);
       // Note: in the event that there is erroneous code, it's possible for
       // typeInferrer to be null.  If this happens, just skip type inference for
@@ -227,9 +227,9 @@
 
   final Instrumentation instrumentation;
 
-  final bool strongMode;
+  final bool legacyMode;
 
-  TypeInferenceEngine(this.instrumentation, this.strongMode);
+  TypeInferenceEngine(this.instrumentation, this.legacyMode);
 
   /// Creates a disabled type inferrer (intended for debugging and profiling
   /// only).
@@ -300,7 +300,7 @@
     this.coreTypes = coreTypes;
     this.classHierarchy = hierarchy;
     this.typeSchemaEnvironment =
-        new TypeSchemaEnvironment(coreTypes, hierarchy, strongMode);
+        new TypeSchemaEnvironment(coreTypes, hierarchy, legacyMode);
   }
 
   /// Records that the given static [field] will need top level type inference.
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 6c4a2c6..50223d0 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -101,6 +101,8 @@
         ShadowClass,
         ShadowField,
         ShadowMember,
+        ShadowTypeInferenceEngine,
+        ShadowTypeInferrer,
         VariableDeclarationJudgment,
         getExplicitTypeArguments,
         getInferredType;
@@ -122,7 +124,7 @@
 import 'type_inference_engine.dart'
     show IncludesTypeParametersCovariantly, TypeInferenceEngine;
 
-import 'type_promotion.dart' show TypePromoter, TypePromoterDisabled;
+import 'type_promotion.dart' show TypePromoter;
 
 import 'type_schema.dart' show isKnown, UnknownType;
 
@@ -444,7 +446,17 @@
 abstract class TypeInferrer {
   final CoreTypes coreTypes;
 
-  TypeInferrer(this.coreTypes);
+  TypeInferrer.private(this.coreTypes);
+
+  factory TypeInferrer(
+      ShadowTypeInferenceEngine engine,
+      Uri uri,
+      bool topLevel,
+      InterfaceType thisType,
+      KernelLibraryBuilder library) = ShadowTypeInferrer.private;
+
+  factory TypeInferrer.disabled(TypeSchemaEnvironment typeSchemaEnvironment) =
+      TypeInferrerDisabled.private;
 
   KernelLibraryBuilder get library;
 
@@ -490,12 +502,13 @@
 /// promotion do not slow down compilation too much.
 class TypeInferrerDisabled extends TypeInferrer {
   @override
-  final typePromoter = new TypePromoterDisabled();
+  final typePromoter = new TypePromoter.disabled();
 
   @override
   final TypeSchemaEnvironment typeSchemaEnvironment;
 
-  TypeInferrerDisabled(this.typeSchemaEnvironment) : super(null);
+  TypeInferrerDisabled.private(this.typeSchemaEnvironment)
+      : super.private(null);
 
   @override
   KernelLibraryBuilder get library => null;
@@ -548,7 +561,7 @@
   /// should apply.
   final bool isTopLevel;
 
-  final bool strongMode;
+  final bool legacyMode;
 
   final ClassHierarchy classHierarchy;
 
@@ -577,14 +590,14 @@
   /// if the last invocation didn't require any inference.
   FunctionType lastCalleeType;
 
-  TypeInferrerImpl(
+  TypeInferrerImpl.private(
       this.engine, this.uri, bool topLevel, this.thisType, this.library)
-      : strongMode = engine.strongMode,
+      : legacyMode = engine.legacyMode,
         classHierarchy = engine.classHierarchy,
         instrumentation = topLevel ? null : engine.instrumentation,
         typeSchemaEnvironment = engine.typeSchemaEnvironment,
         isTopLevel = topLevel,
-        super(engine.coreTypes);
+        super.private(engine.coreTypes);
 
   DartType storeInferredType(TreeNode node, DartType type) {
     if (node is ExpressionJudgment) {
@@ -667,8 +680,8 @@
     // is inferred (the kernel code is discarded).
     if (isTopLevel) return null;
 
-    // This logic is strong mode only; in legacy mode anything goes.
-    if (!strongMode) return null;
+    // In legacy mode, we don't check assignability.
+    if (legacyMode) return null;
 
     // If an interface type is being assigned to a function type, see if we
     // should tear off `.call`.
@@ -777,10 +790,10 @@
       bool instrumented: true}) {
     assert(receiverType != null && isKnown(receiverType));
 
-    // Our non-strong golden files currently don't include interface
-    // targets, so we can't store the interface target without causing tests
-    // to fail.  TODO(paulberry): fix this.
-    if (!strongMode) return null;
+    // Our legacy golden files currently don't include interface targets, so we
+    // can't store the interface target without causing tests to fail.
+    // TODO(paulberry): fix this.
+    if (legacyMode) return null;
 
     receiverType = resolveTypeParameter(receiverType);
 
@@ -859,7 +872,7 @@
               new InstrumentationValueForMember(interfaceMember));
         }
         methodInvocation.interfaceTarget = interfaceMember;
-      } else if (strongMode && interfaceMember is Member) {
+      } else if (!legacyMode && interfaceMember is Member) {
         methodInvocation.interfaceTarget = interfaceMember;
       }
       return interfaceMember;
@@ -868,7 +881,7 @@
       var interfaceMember = findInterfaceMember(
           receiverType, methodInvocation.name, methodInvocation.fileOffset,
           instrumented: instrumented);
-      if (strongMode && interfaceMember is Member) {
+      if (!legacyMode && interfaceMember is Member) {
         methodInvocation.interfaceTarget = interfaceMember;
       }
       return interfaceMember;
@@ -891,7 +904,7 @@
           expression: propertyGet,
           receiver: propertyGet.receiver,
           instrumented: instrumented);
-      if (strongMode && interfaceMember is Member) {
+      if (!legacyMode && interfaceMember is Member) {
         if (instrumented &&
             instrumentation != null &&
             receiverType == const DynamicType()) {
@@ -906,7 +919,7 @@
       var interfaceMember = findInterfaceMember(
           receiverType, propertyGet.name, propertyGet.fileOffset,
           instrumented: instrumented);
-      if (strongMode && interfaceMember is Member) {
+      if (!legacyMode && interfaceMember is Member) {
         propertyGet.interfaceTarget = interfaceMember;
       }
       return interfaceMember;
@@ -928,7 +941,7 @@
           receiver: propertySet.receiver,
           setter: true,
           instrumented: instrumented);
-      if (strongMode && interfaceMember is Member) {
+      if (!legacyMode && interfaceMember is Member) {
         if (instrumented &&
             instrumentation != null &&
             receiverType == const DynamicType()) {
@@ -943,7 +956,7 @@
       var interfaceMember = findInterfaceMember(
           receiverType, propertySet.name, propertySet.fileOffset,
           setter: true, instrumented: instrumented);
-      if (strongMode && interfaceMember is Member) {
+      if (!legacyMode && interfaceMember is Member) {
         propertySet.interfaceTarget = interfaceMember;
       }
       return interfaceMember;
@@ -1254,7 +1267,7 @@
     List<DartType> explicitTypeArguments = getExplicitTypeArguments(arguments);
     bool inferenceNeeded = !skipTypeArgumentInference &&
         explicitTypeArguments == null &&
-        strongMode &&
+        !legacyMode &&
         calleeTypeParameters.isNotEmpty;
     bool typeChecksNeeded = !isTopLevel;
     List<DartType> inferredTypes;
@@ -1453,7 +1466,7 @@
     Substitution substitution;
     List<DartType> formalTypesFromContext =
         new List<DartType>.filled(formals.length, null);
-    if (strongMode && typeContext is FunctionType) {
+    if (!legacyMode && typeContext is FunctionType) {
       for (int i = 0; i < formals.length; i++) {
         if (i < function.positionalParameters.length) {
           formalTypesFromContext[i] =
@@ -1513,7 +1526,7 @@
 
     // Apply type inference to `B` in return context `N’`, with any references
     // to `xi` in `B` having type `Pi`.  This produces `B’`.
-    bool needToSetReturnType = hasImplicitReturnType && strongMode;
+    bool needToSetReturnType = hasImplicitReturnType && !legacyMode;
     ClosureContext oldClosureContext = this.closureContext;
     ClosureContext closureContext = new ClosureContext(
         this, function.asyncMarker, returnContext, needToSetReturnType);
@@ -1537,7 +1550,7 @@
       instrumentation?.record(uri, fileOffset, 'returnType',
           new InstrumentationValueForType(inferredReturnType));
       function.returnType = inferredReturnType;
-    } else if (!strongMode && hasImplicitReturnType) {
+    } else if (legacyMode && hasImplicitReturnType) {
       function.returnType =
           closureContext._wrapAsyncOrGenerator(this, const DynamicType());
     }
@@ -1589,7 +1602,7 @@
     var receiverType = receiver == null
         ? thisType
         : inferExpression(receiver, const UnknownType(), true);
-    if (strongMode) {
+    if (!legacyMode) {
       receiverVariable?.type = receiverType;
     }
     if (desugaredInvocation != null) {
@@ -1627,7 +1640,7 @@
     handleInvocationContravariance(checkKind, desugaredInvocation, arguments,
         expression, inferredType, functionType, fileOffset);
     if (!identical(interfaceMember, 'call')) {
-      if (strongMode &&
+      if (!legacyMode &&
           isImplicitCall &&
           interfaceMember != null &&
           !(interfaceMember is Procedure &&
@@ -1706,7 +1719,7 @@
       inferExpression(receiver, const UnknownType(), true);
       receiverType = getInferredType(receiver, this);
     }
-    if (strongMode) {
+    if (!legacyMode) {
       receiverVariable?.type = receiverType;
     }
     propertyName ??= desugaredGet.name;
@@ -1716,7 +1729,7 @@
           errorTemplate: templateUndefinedGetter,
           expression: expression,
           receiver: receiver);
-      if (strongMode && interfaceMember is Member) {
+      if (!legacyMode && interfaceMember is Member) {
         if (instrumentation != null && receiverType == const DynamicType()) {
           instrumentation.record(uri, desugaredGet.fileOffset, 'target',
               new InstrumentationValueForMember(interfaceMember));
@@ -1755,7 +1768,7 @@
   /// (if necessary).
   DartType instantiateTearOff(
       DartType tearoffType, DartType context, Expression expression) {
-    if (strongMode &&
+    if (!legacyMode &&
         tearoffType is FunctionType &&
         context is FunctionType &&
         context.typeParameters.isEmpty) {
@@ -2092,7 +2105,7 @@
       Class mixinClass = mixedInType.classNode;
       Supertype mixinSupertype = mixinClass.supertype;
       gatherer = new TypeConstraintGatherer(
-          new TypeSchemaEnvironment(loader.coreTypes, hierarchy, true),
+          new TypeSchemaEnvironment(loader.coreTypes, hierarchy, false),
           mixinClass.typeParameters);
       // Generate constraints based on the mixin's supertype.
       generateConstraints(hierarchy, mixinClass, baseType, mixinSupertype);
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart b/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
index 791a584..80c10e5 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
@@ -9,6 +9,8 @@
 
 import '../problems.dart' show internalProblem;
 
+import '../kernel/kernel_shadow_ast.dart' show ShadowTypePromoter;
+
 import 'type_schema_environment.dart' show TypeSchemaEnvironment;
 
 /// Keeps track of the state necessary to perform type promotion.
@@ -31,6 +33,13 @@
 /// generic parameters.  Derived classes should set E and V to the class they
 /// use to represent expressions and variable declarations, respectively.
 abstract class TypePromoter {
+  TypePromoter.private();
+
+  factory TypePromoter(TypeSchemaEnvironment typeSchemaEnvironment) =
+      ShadowTypePromoter.private;
+
+  factory TypePromoter.disabled() = TypePromoterDisabled.private;
+
   /// Returns the current type promotion scope.
   TypePromotionScope get currentScope;
 
@@ -90,6 +99,8 @@
 /// This is intended for profiling, to ensure that type inference and type
 /// promotion do not slow down compilation too much.
 class TypePromoterDisabled extends TypePromoter {
+  TypePromoterDisabled.private() : super.private();
+
   @override
   TypePromotionScope get currentScope => null;
 
@@ -177,12 +188,13 @@
   /// created.
   int _lastFactSequenceNumber = 0;
 
-  TypePromoterImpl(TypeSchemaEnvironment typeSchemaEnvironment)
+  TypePromoterImpl.private(TypeSchemaEnvironment typeSchemaEnvironment)
       : this._(typeSchemaEnvironment, new _NullFact());
 
   TypePromoterImpl._(this.typeSchemaEnvironment, _NullFact this._nullFacts)
       : _factCacheState = _nullFacts,
-        _currentFacts = _nullFacts {
+        _currentFacts = _nullFacts,
+        super.private() {
     _factCache[null] = _nullFacts;
   }
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart
index 060aad1..e742fd0 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart
@@ -6,6 +6,7 @@
     show
         DartType,
         DartTypeVisitor,
+        DartTypeVisitor1,
         FunctionType,
         InterfaceType,
         TypedefType,
@@ -84,6 +85,9 @@
   }
 
   @override
+  accept1(DartTypeVisitor1 v, arg) => v.defaultDartType(this, arg);
+
+  @override
   visitChildren(Visitor v) {}
 }
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart
index 519c3df..cf4c6bf 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart
@@ -77,9 +77,11 @@
       }
     }
     isLeastClosure = !isLeastClosure;
+    DartType typedefType = node.typedefType?.accept(this);
     if (newReturnType == null &&
         newPositionalParameters == null &&
-        newNamedParameters == null) {
+        newNamedParameters == null &&
+        typedefType == null) {
       // No types had to be substituted.
       return null;
     } else {
@@ -89,7 +91,7 @@
           namedParameters: newNamedParameters ?? node.namedParameters,
           typeParameters: node.typeParameters,
           requiredParameterCount: node.requiredParameterCount,
-          typedefReference: node.typedefReference);
+          typedefType: typedefType);
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
index 8b5aac7..507e085 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
@@ -46,7 +46,9 @@
           .toList(),
       typeParameters: newTypeParameters,
       requiredParameterCount: type.requiredParameterCount,
-      typedefReference: type.typedefReference);
+      typedefType: type.typedefType == null
+          ? null
+          : substitution.substituteType(type.typedefType));
 }
 
 /// Given a [FunctionType], gets the type of the named parameter with the given
@@ -89,8 +91,8 @@
 
 class TypeSchemaEnvironment extends TypeEnvironment {
   TypeSchemaEnvironment(
-      CoreTypes coreTypes, ClassHierarchy hierarchy, bool strongMode)
-      : super(coreTypes, hierarchy, strongMode: strongMode);
+      CoreTypes coreTypes, ClassHierarchy hierarchy, bool legacyMode)
+      : super(coreTypes, hierarchy, strongMode: !legacyMode);
 
   /// Modify the given [constraint]'s lower bound to include [lower].
   void addLowerBound(TypeConstraint constraint, DartType lower) {
diff --git a/pkg/front_end/lib/src/scanner/token.dart b/pkg/front_end/lib/src/scanner/token.dart
index 4d07967..119006f 100644
--- a/pkg/front_end/lib/src/scanner/token.dart
+++ b/pkg/front_end/lib/src/scanner/token.dart
@@ -1275,6 +1275,10 @@
       '>>=', 'GT_GT_EQ', ASSIGNMENT_PRECEDENCE, GT_GT_EQ_TOKEN,
       isOperator: true);
 
+  static const TokenType GT_GT_GT = const TokenType(
+      '>>>', 'GT_GT_GT', SHIFT_PRECEDENCE, GT_GT_GT_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
   static const TokenType HASH =
       const TokenType('#', 'HASH', NO_PRECEDENCE, HASH_TOKEN);
 
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index be04c73..29e52a1 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -62,11 +62,14 @@
 ConstEvalDuplicateKey/example: Fail
 ConstEvalFailedAssertion/example: Fail
 ConstEvalFailedAssertionWithMessage/example: Fail
+ConstEvalFreeTypeParameter/analyzerCode: Fail
+ConstEvalFreeTypeParameter/example: Fail
 ConstEvalInvalidBinaryOperandType/analyzerCode: Fail # CONST_EVAL_TYPE_NUM / CONST_EVAL_TYPE_BOOL
 ConstEvalInvalidBinaryOperandType/example: Fail
 ConstEvalInvalidMethodInvocation/example: Fail
 ConstEvalInvalidStaticInvocation/example: Fail
 ConstEvalInvalidStringInterpolationOperand/example: Fail
+ConstEvalInvalidSymbolName/example: Fail
 ConstEvalInvalidType/analyzerCode: Fail # CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH / CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH / CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH / ...
 ConstEvalInvalidType/example: Fail
 ConstEvalNegativeShift/analyzerCode: Fail # http://dartbug.com/33481
@@ -277,7 +280,6 @@
 PackageNotFound/example: Fail
 PackagesFileFormat/analyzerCode: Fail # Analyzer crashes when .packages file has format error
 PartOfLibraryNameMismatch/example: Fail
-PartOfTwice/script2: Fail # TODO(ahe): Investigate why this fails.
 PartOfUriMismatch/example: Fail
 PartOfUseUri/example: Fail
 PartOrphan/analyzerCode: Fail # Analyzer can't handle this situation
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 60bb455..f80e641 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -64,7 +64,7 @@
 #    do not use them for composing error messages, see [diagnostics.md](
 #    lib/src/fasta/diagnostics.md#avoid-composing-messages-programmatically).
 #
-# `#type`, #type2`: Kernel types.
+# `#type`, #type2`, `#type3`: Kernel types.
 #
 # `#uri`, `#uri2`, `#uri3`: URIs.
 #
@@ -116,6 +116,10 @@
   template: "The invocation of '#name' is not allowed within a const context."
   analyzerCode: CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
 
+ConstEvalInvalidSymbolName:
+  template: "The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '#constant'."
+  analyzerCode: CONST_EVAL_THROWS_EXCEPTION
+
 ConstEvalFailedAssertion:
   template: "This assertion failed."
   analyzerCode: CONST_EVAL_THROWS_EXCEPTION
@@ -137,6 +141,9 @@
     from the import.
   analyzerCode: NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY
 
+ConstEvalFreeTypeParameter:
+  template: "The type '#type' is not a constant because it depends on a type parameter, only instantiated types are allowed."
+
 NotConstantExpression:
   template: "#string is not a constant expression."
   analyzerCode: NOT_CONSTANT_EXPRESSION
@@ -1644,7 +1651,11 @@
   severity: INTERNAL_PROBLEM
 
 InternalProblemStoringMultipleInferredTypes:
-  template: "There's already an inferred type (#type) for '#name'."
+  template: "There's already an inferred type, '#type', for '#name'."
+  severity: INTERNAL_PROBLEM
+
+InternalProblemLabelUsageInVariablesDeclaration:
+  template: "Unexpected usage of label inside declaration of variables."
   severity: INTERNAL_PROBLEM
 
 LocalDefinitionHidesExport:
@@ -1970,13 +1981,13 @@
   analyzerCode: INVALID_OVERRIDE_REQUIRED
 
 OverrideTypeMismatchParameter:
-  template: "The parameter '#name' of the method '#name2' has type #type, which does not match the corresponding type in the overridden method (#type2)."
-  tip: "Change to a supertype of #type2 (or, for a covariant parameter, a subtype)."
+  template: "The parameter '#name' of the method '#name2' has type '#type', which does not match the corresponding type in the overridden method, '#type2'."
+  tip: "Change to a supertype of '#type2', or, for a covariant parameter, a subtype."
   analyzerCode: INVALID_METHOD_OVERRIDE
 
 OverrideTypeMismatchReturnType:
-  template: "The return type of the method '#name' is #type, which does not match the return type of the overridden method (#type2)."
-  tip: "Change to a subtype of #type2."
+  template: "The return type of the method '#name' is '#type', which does not match the return type of the overridden method, '#type2'."
+  tip: "Change to a subtype of '#type2'."
   analyzerCode: INVALID_METHOD_OVERRIDE
 
 PartOfSelf:
@@ -2499,6 +2510,9 @@
 
 FinalInstanceVariableAlreadyInitialized:
   template: "'#name' is a final instance variable that has already been initialized."
+  # TODO(ahe): Strictly speaking, as of
+  # 3b5874a332b24f326775b3520f32b9a818731aca, this is a compile-time error in
+  # legacy mode.
   severity: ERROR_LEGACY_WARNING
   analyzerCode: FINAL_INITIALIZED_MULTIPLE_TIMES
 
@@ -2913,8 +2927,8 @@
   analyzerCode: FOR_IN_OF_INVALID_TYPE
 
 InitializingFormalTypeMismatch:
-  template: "The type of parameter '#name' (#type) is not a subtype of the corresponding field's type (#type2)."
-  tip: "Try changing the type of parameter '#name' to a subtype of #type2."
+  template: "The type of parameter '#name', '#type' is not a subtype of the corresponding field's type, '#type2'."
+  tip: "Try changing the type of parameter '#name' to a subtype of '#type2'."
   severity: ERROR_LEGACY_WARNING
   analyzerCode: INVALID_PARAMETER_DECLARATION
   script: >
@@ -3150,7 +3164,7 @@
       }
 
 RedirectingFactoryInvalidPositionalParameterType:
-  template: "The type of parameter '#name' (#type) is not a subtype of the redirection target's corresponding parameter type (#type2)."
+  template: "The type of parameter '#name', '#type' is not a subtype of the redirection target's corresponding parameter type, '#type2'."
   tip: "Try changing either the type of the parameter or the redirection target."
   analyzerCode: REDIRECT_TO_INVALID_FUNCTION_TYPE
   script:
@@ -3172,7 +3186,7 @@
       }
 
 RedirectingFactoryInvalidNamedParameterType:
-  template: "The type of the named parameter '#name' (#type) is not a subtype of the redirection target's corresponding named parameter type (#type2)."
+  template: "The type of the named parameter '#name', '#type' is not a subtype of the redirection target's corresponding named parameter type, '#type2'."
   tip: "Try changing either the type of the parameter or the redirection target."
   analyzerCode: REDIRECT_TO_INVALID_FUNCTION_TYPE
   script:
@@ -3271,8 +3285,8 @@
     class C = Object with M;
 
 GenericFunctionTypeUsedAsActualTypeArgument:
-  template: Unexpected generic function type found in a type argument.
-  tip: Try using a non-generic function type.
+  template: "Unexpected generic function type found in a type argument."
+  tip: "Try using a non-generic function type."
   analyzerCode: GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT
   script:
     - >-
@@ -3287,8 +3301,8 @@
       }
 
 GenericFunctionTypeInferredAsActualTypeArgument:
-  template: Unexpected generic function type '#type' inferred as a type argument.
-  tip: Try providing a non-generic function type explicitly.
+  template: "Unexpected generic function type '#type' inferred as a type argument."
+  tip: "Try providing a non-generic function type explicitly."
   analyzerCode: GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT
   script:
     foo<X>(X x) => null;
diff --git a/pkg/front_end/test/fasta/compile_test.dart b/pkg/front_end/test/fasta/legacy_test.dart
similarity index 89%
rename from pkg/front_end/test/fasta/compile_test.dart
rename to pkg/front_end/test/fasta/legacy_test.dart
index e56e918..ff28e5b 100644
--- a/pkg/front_end/test/fasta/compile_test.dart
+++ b/pkg/front_end/test/fasta/legacy_test.dart
@@ -2,7 +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.md file.
 
-library fasta.test.compile_test;
+library fasta.test.legacy_test;
 
 import 'dart:async' show Future;
 
@@ -11,6 +11,7 @@
 Future<FastaContext> createContext(
     Chain suite, Map<String, String> environment) {
   environment[ENABLE_FULL_COMPILE] = "";
+  environment[LEGACY_MODE] = "";
   return FastaContext.create(suite, environment);
 }
 
diff --git a/pkg/front_end/test/fasta/outline_test.dart b/pkg/front_end/test/fasta/outline_test.dart
index 43e9cc9..3551732 100644
--- a/pkg/front_end/test/fasta/outline_test.dart
+++ b/pkg/front_end/test/fasta/outline_test.dart
@@ -10,6 +10,7 @@
 
 Future<FastaContext> createContext(
     Chain suite, Map<String, String> environment) {
+  environment[LEGACY_MODE] = "";
   return FastaContext.create(suite, environment);
 }
 
diff --git a/pkg/front_end/test/fasta/parser/parser_suite.dart b/pkg/front_end/test/fasta/parser/parser_suite.dart
index f922086..ad15a8f 100644
--- a/pkg/front_end/test/fasta/parser/parser_suite.dart
+++ b/pkg/front_end/test/fasta/parser/parser_suite.dart
@@ -4,8 +4,6 @@
 
 import 'package:testing/testing.dart';
 
-import 'package:front_end/src/fasta/scanner.dart';
-
 import 'package:front_end/src/fasta/testing/scanner_chain.dart';
 
 import 'package:front_end/src/fasta/parser.dart';
@@ -23,14 +21,14 @@
   ];
 }
 
-class Parse extends Step<ScannerResult, Null, ChainContext> {
+class Parse extends Step<ScannedFile, Null, ChainContext> {
   const Parse();
 
   String get name => "parse";
 
-  Future<Result<Null>> run(ScannerResult result, ChainContext context) async {
+  Future<Result<Null>> run(ScannedFile file, ChainContext context) async {
     try {
-      List<ParserError> errors = parse(result.tokens);
+      List<ParserError> errors = parse(file.result.tokens);
       if (errors.isNotEmpty) {
         return fail(null, errors.join("\n"));
       }
diff --git a/pkg/front_end/test/fasta/parser/type_info_test.dart b/pkg/front_end/test/fasta/parser/type_info_test.dart
index d50b840..f3f7c2c 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -971,6 +971,7 @@
 class NoTypeParamOrArgTest {
   void test_basic() {
     expect(noTypeParamOrArg.isSimpleTypeArgument, isFalse);
+    expect(noTypeParamOrArg.typeArgumentCount, 0);
 
     final Token start = scanString('before after').tokens;
     expect(noTypeParamOrArg.skip(start), start);
@@ -1013,6 +1014,7 @@
 class SimpleTypeParamOrArgTest {
   void test_basic_gt() {
     expect(simpleTypeArgument1.isSimpleTypeArgument, isTrue);
+    expect(simpleTypeArgument1.typeArgumentCount, 1);
     expect(simpleTypeArgument1.typeInfo, simpleTypeWith1Argument);
 
     final Token start = scanString('before <T> after').tokens;
@@ -1026,6 +1028,7 @@
 
   void test_basic_gt_eq() {
     expect(simpleTypeArgument1GtEq.isSimpleTypeArgument, isTrue);
+    expect(simpleTypeArgument1GtEq.typeArgumentCount, 1);
     expect(simpleTypeArgument1GtEq.typeInfo, simpleTypeWith1ArgumentGtEq);
 
     final Token start = scanString('before <T>= after').tokens;
@@ -1041,6 +1044,7 @@
 
   void test_basic_gt_gt() {
     expect(simpleTypeArgument1GtGt.isSimpleTypeArgument, isTrue);
+    expect(simpleTypeArgument1GtGt.typeArgumentCount, 1);
     expect(simpleTypeArgument1GtGt.typeInfo, simpleTypeWith1ArgumentGtGt);
 
     final Token start = scanString('before <S<T>> after').tokens.next.next;
@@ -1159,7 +1163,7 @@
 @reflectiveTest
 class TypeParamOrArgInfoTest {
   void test_computeTypeArg_complex() {
-    expectComplexTypeArg('<S,T>', expectedCalls: [
+    expectComplexTypeArg('<S,T>', typeArgumentCount: 2, expectedCalls: [
       'beginTypeArguments <',
       'handleIdentifier S typeReference',
       'handleNoTypeArguments ,',
@@ -1169,49 +1173,59 @@
       'handleType T',
       'endTypeArguments 2 < >'
     ]);
-    expectComplexTypeArg('<S,T>=', expectedAfter: '=', expectedCalls: [
-      'beginTypeArguments <',
-      'handleIdentifier S typeReference',
-      'handleNoTypeArguments ,',
-      'handleType S',
-      'handleIdentifier T typeReference',
-      'handleNoTypeArguments >=',
-      'handleType T',
-      'endTypeArguments 2 < >'
-    ]);
-    expectComplexTypeArg('<S,T>>=', expectedAfter: '>=', expectedCalls: [
-      'beginTypeArguments <',
-      'handleIdentifier S typeReference',
-      'handleNoTypeArguments ,',
-      'handleType S',
-      'handleIdentifier T typeReference',
-      'handleNoTypeArguments >>=',
-      'handleType T',
-      'endTypeArguments 2 < >'
-    ]);
-    expectComplexTypeArg('<S Function()>', expectedCalls: [
-      'beginTypeArguments <',
-      'handleNoTypeVariables (',
-      'beginFunctionType S',
-      'handleIdentifier S typeReference',
-      'handleNoTypeArguments Function',
-      'handleType S',
-      'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
-      'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
-      'endFunctionType Function',
-      'endTypeArguments 1 < >'
-    ]);
-    expectComplexTypeArg('<void Function()>', expectedCalls: [
-      'beginTypeArguments <',
-      'handleNoTypeVariables (',
-      'beginFunctionType void',
-      'handleVoidKeyword void',
-      'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
-      'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
-      'endFunctionType Function',
-      'endTypeArguments 1 < >'
-    ]);
-    expectComplexTypeArg('<S<T>>', expectedCalls: [
+    expectComplexTypeArg('<S,T>=',
+        typeArgumentCount: 2,
+        expectedAfter: '=',
+        expectedCalls: [
+          'beginTypeArguments <',
+          'handleIdentifier S typeReference',
+          'handleNoTypeArguments ,',
+          'handleType S',
+          'handleIdentifier T typeReference',
+          'handleNoTypeArguments >=',
+          'handleType T',
+          'endTypeArguments 2 < >'
+        ]);
+    expectComplexTypeArg('<S,T>>=',
+        typeArgumentCount: 2,
+        expectedAfter: '>=',
+        expectedCalls: [
+          'beginTypeArguments <',
+          'handleIdentifier S typeReference',
+          'handleNoTypeArguments ,',
+          'handleType S',
+          'handleIdentifier T typeReference',
+          'handleNoTypeArguments >>=',
+          'handleType T',
+          'endTypeArguments 2 < >'
+        ]);
+    expectComplexTypeArg('<S Function()>',
+        typeArgumentCount: 1,
+        expectedCalls: [
+          'beginTypeArguments <',
+          'handleNoTypeVariables (',
+          'beginFunctionType S',
+          'handleIdentifier S typeReference',
+          'handleNoTypeArguments Function',
+          'handleType S',
+          'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
+          'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
+          'endFunctionType Function',
+          'endTypeArguments 1 < >'
+        ]);
+    expectComplexTypeArg('<void Function()>',
+        typeArgumentCount: 1,
+        expectedCalls: [
+          'beginTypeArguments <',
+          'handleNoTypeVariables (',
+          'beginFunctionType void',
+          'handleVoidKeyword void',
+          'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
+          'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
+          'endFunctionType Function',
+          'endTypeArguments 1 < >'
+        ]);
+    expectComplexTypeArg('<S<T>>', typeArgumentCount: 1, expectedCalls: [
       'beginTypeArguments <',
       'handleIdentifier S typeReference',
       'beginTypeArguments <',
@@ -1222,32 +1236,38 @@
       'handleType S',
       'endTypeArguments 1 < >'
     ]);
-    expectComplexTypeArg('<S<T>>=', expectedAfter: '=', expectedCalls: [
-      'beginTypeArguments <',
-      'handleIdentifier S typeReference',
-      'beginTypeArguments <',
-      'handleIdentifier T typeReference',
-      'handleNoTypeArguments >>=',
-      'handleType T',
-      'endTypeArguments 1 < >',
-      'handleType S',
-      'endTypeArguments 1 < >'
-    ]);
-    expectComplexTypeArg('<S<Function()>>', expectedCalls: [
-      'beginTypeArguments <',
-      'handleIdentifier S typeReference',
-      'beginTypeArguments <',
-      'handleNoTypeVariables (',
-      'beginFunctionType Function',
-      'handleNoType <',
-      'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
-      'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
-      'endFunctionType Function',
-      'endTypeArguments 1 < >',
-      'handleType S',
-      'endTypeArguments 1 < >'
-    ]);
+    expectComplexTypeArg('<S<T>>=',
+        typeArgumentCount: 1,
+        expectedAfter: '=',
+        expectedCalls: [
+          'beginTypeArguments <',
+          'handleIdentifier S typeReference',
+          'beginTypeArguments <',
+          'handleIdentifier T typeReference',
+          'handleNoTypeArguments >>=',
+          'handleType T',
+          'endTypeArguments 1 < >',
+          'handleType S',
+          'endTypeArguments 1 < >'
+        ]);
+    expectComplexTypeArg('<S<Function()>>',
+        typeArgumentCount: 1,
+        expectedCalls: [
+          'beginTypeArguments <',
+          'handleIdentifier S typeReference',
+          'beginTypeArguments <',
+          'handleNoTypeVariables (',
+          'beginFunctionType Function',
+          'handleNoType <',
+          'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
+          'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
+          'endFunctionType Function',
+          'endTypeArguments 1 < >',
+          'handleType S',
+          'endTypeArguments 1 < >'
+        ]);
     expectComplexTypeArg('<S<Function()>>=',
+        typeArgumentCount: 1,
         expectedAfter: '=',
         expectedCalls: [
           'beginTypeArguments <',
@@ -1263,42 +1283,50 @@
           'handleType S',
           'endTypeArguments 1 < >'
         ]);
-    expectComplexTypeArg('<S<void Function()>>', expectedCalls: [
-      'beginTypeArguments <',
-      'handleIdentifier S typeReference',
-      'beginTypeArguments <',
-      'handleNoTypeVariables (',
-      'beginFunctionType void', // was 'beginFunctionType Function'
-      'handleVoidKeyword void', // was 'handleNoType <'
-      'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
-      'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
-      'endFunctionType Function',
-      'endTypeArguments 1 < >',
-      'handleType S',
-      'endTypeArguments 1 < >'
-    ]);
+    expectComplexTypeArg('<S<void Function()>>',
+        typeArgumentCount: 1,
+        expectedCalls: [
+          'beginTypeArguments <',
+          'handleIdentifier S typeReference',
+          'beginTypeArguments <',
+          'handleNoTypeVariables (',
+          'beginFunctionType void', // was 'beginFunctionType Function'
+          'handleVoidKeyword void', // was 'handleNoType <'
+          'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
+          'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
+          'endFunctionType Function',
+          'endTypeArguments 1 < >',
+          'handleType S',
+          'endTypeArguments 1 < >'
+        ]);
   }
 
   void test_computeTypeArg_complex_recovery() {
-    expectComplexTypeArg('<S extends T>', expectedErrors: [
-      error(codeExpectedAfterButGot, 1, 1)
-    ], expectedCalls: [
-      'beginTypeArguments <',
-      'handleIdentifier S typeReference',
-      'handleNoTypeArguments extends',
-      'handleType S',
-      'endTypeArguments 1 < >',
-    ]);
-    expectComplexTypeArg('<S extends List<T>>', expectedErrors: [
-      error(codeExpectedAfterButGot, 1, 1)
-    ], expectedCalls: [
-      'beginTypeArguments <',
-      'handleIdentifier S typeReference',
-      'handleNoTypeArguments extends',
-      'handleType S',
-      'endTypeArguments 1 < >',
-    ]);
-    expectComplexTypeArg('<@A S,T>', expectedErrors: [
+    expectComplexTypeArg('<S extends T>',
+        typeArgumentCount: 1,
+        expectedErrors: [
+          error(codeExpectedAfterButGot, 1, 1)
+        ],
+        expectedCalls: [
+          'beginTypeArguments <',
+          'handleIdentifier S typeReference',
+          'handleNoTypeArguments extends',
+          'handleType S',
+          'endTypeArguments 1 < >',
+        ]);
+    expectComplexTypeArg('<S extends List<T>>',
+        typeArgumentCount: 1,
+        expectedErrors: [
+          error(codeExpectedAfterButGot, 1, 1)
+        ],
+        expectedCalls: [
+          'beginTypeArguments <',
+          'handleIdentifier S typeReference',
+          'handleNoTypeArguments extends',
+          'handleType S',
+          'endTypeArguments 1 < >',
+        ]);
+    expectComplexTypeArg('<@A S,T>', typeArgumentCount: 2, expectedErrors: [
       error(codeUnexpectedToken, 1, 1)
     ], expectedCalls: [
       'beginTypeArguments <',
@@ -1310,7 +1338,7 @@
       'handleType T',
       'endTypeArguments 2 < >'
     ]);
-    expectComplexTypeArg('<@A() S,T>', expectedErrors: [
+    expectComplexTypeArg('<@A() S,T>', typeArgumentCount: 2, expectedErrors: [
       error(codeUnexpectedToken, 1, 1)
     ], expectedCalls: [
       'beginTypeArguments <',
@@ -1322,45 +1350,58 @@
       'handleType T',
       'endTypeArguments 2 < >'
     ]);
-    expectComplexTypeArg('<@A() @B S,T>', expectedErrors: [
-      error(codeUnexpectedToken, 1, 1),
-      error(codeUnexpectedToken, 6, 1),
-    ], expectedCalls: [
-      'beginTypeArguments <',
-      'handleIdentifier S typeReference',
-      'handleNoTypeArguments ,',
-      'handleType S',
-      'handleIdentifier T typeReference',
-      'handleNoTypeArguments >',
-      'handleType T',
-      'endTypeArguments 2 < >'
-    ]);
+    expectComplexTypeArg('<@A() @B S,T>',
+        typeArgumentCount: 2,
+        expectedErrors: [
+          error(codeUnexpectedToken, 1, 1),
+          error(codeUnexpectedToken, 6, 1),
+        ],
+        expectedCalls: [
+          'beginTypeArguments <',
+          'handleIdentifier S typeReference',
+          'handleNoTypeArguments ,',
+          'handleType S',
+          'handleIdentifier T typeReference',
+          'handleNoTypeArguments >',
+          'handleType T',
+          'endTypeArguments 2 < >'
+        ]);
     expectComplexTypeArg('<S T>',
-        inDeclaration: true, expectedErrors: [error(codeExpectedButGot, 3, 1)]);
+        inDeclaration: true,
+        typeArgumentCount: 2,
+        expectedErrors: [error(codeExpectedButGot, 3, 1)]);
     expectComplexTypeArg('<S',
         inDeclaration: true,
+        typeArgumentCount: 1,
         expectedErrors: [error(codeExpectedAfterButGot, 1, 1)]);
-    expectComplexTypeArg('<@Foo S', inDeclaration: true, expectedErrors: [
-      error(codeUnexpectedToken, 1, 1),
-      error(codeExpectedAfterButGot, 6, 1)
-    ]);
-    expectComplexTypeArg('<S<T', inDeclaration: true, expectedErrors: [
-      error(codeExpectedAfterButGot, 3, 1)
-    ], expectedCalls: [
-      'beginTypeArguments <',
-      'handleIdentifier S typeReference',
-      'beginTypeArguments <',
-      'handleIdentifier T typeReference',
-      'handleNoTypeArguments ',
-      'handleType T',
-      'endTypeArguments 1 < >',
-      'handleType S',
-      'endTypeArguments 1 < >'
-    ]);
+    expectComplexTypeArg('<@Foo S',
+        inDeclaration: true,
+        typeArgumentCount: 1,
+        expectedErrors: [
+          error(codeUnexpectedToken, 1, 1),
+          error(codeExpectedAfterButGot, 6, 1)
+        ]);
+    expectComplexTypeArg('<S<T',
+        inDeclaration: true,
+        typeArgumentCount: 1,
+        expectedErrors: [
+          error(codeExpectedAfterButGot, 3, 1)
+        ],
+        expectedCalls: [
+          'beginTypeArguments <',
+          'handleIdentifier S typeReference',
+          'beginTypeArguments <',
+          'handleIdentifier T typeReference',
+          'handleNoTypeArguments ',
+          'handleType T',
+          'endTypeArguments 1 < >',
+          'handleType S',
+          'endTypeArguments 1 < >'
+        ]);
   }
 
   void test_computeTypeParam_complex() {
-    expectComplexTypeParam('<S,T>', expectedCalls: [
+    expectComplexTypeParam('<S,T>', typeArgumentCount: 2, expectedCalls: [
       'beginTypeVariables <',
       'beginMetadataStar S',
       'endMetadataStar 0',
@@ -1377,59 +1418,65 @@
       'endTypeVariable , 0 null',
       'endTypeVariables < >',
     ]);
-    expectComplexTypeParam('<S extends T>', expectedCalls: [
-      'beginTypeVariables <',
-      'beginMetadataStar S',
-      'endMetadataStar 0',
-      'handleIdentifier S typeVariableDeclaration',
-      'beginTypeVariable S',
-      'handleTypeVariablesDefined T 1',
-      'handleIdentifier T typeReference',
-      'handleNoTypeArguments >',
-      'handleType T',
-      'endTypeVariable > 0 extends',
-      'endTypeVariables < >',
-    ]);
-    expectComplexTypeParam('<S extends List<T>>', expectedCalls: [
-      'beginTypeVariables <',
-      'beginMetadataStar S',
-      'endMetadataStar 0',
-      'handleIdentifier S typeVariableDeclaration',
-      'beginTypeVariable S',
-      'handleTypeVariablesDefined > 1',
-      'handleIdentifier List typeReference',
-      'beginTypeArguments <',
-      'handleIdentifier T typeReference',
-      'handleNoTypeArguments >',
-      'handleType T',
-      'endTypeArguments 1 < >',
-      'handleType List',
-      'endTypeVariable > 0 extends',
-      'endTypeVariables < >',
-    ]);
-    expectComplexTypeParam('<R, S extends void Function()>', expectedCalls: [
-      'beginTypeVariables <',
-      'beginMetadataStar R',
-      'endMetadataStar 0',
-      'handleIdentifier R typeVariableDeclaration',
-      'beginTypeVariable R',
-      'beginMetadataStar S',
-      'endMetadataStar 0',
-      'handleIdentifier S typeVariableDeclaration',
-      'beginTypeVariable S',
-      'handleTypeVariablesDefined ) 2',
-      'handleNoTypeVariables (',
-      'beginFunctionType void',
-      'handleVoidKeyword void',
-      'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
-      'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
-      'endFunctionType Function',
-      'endTypeVariable > 1 extends',
-      'handleNoType R',
-      'endTypeVariable , 0 null',
-      'endTypeVariables < >',
-    ]);
-    expectComplexTypeParam('<@A S,T>', expectedCalls: [
+    expectComplexTypeParam('<S extends T>',
+        typeArgumentCount: 1,
+        expectedCalls: [
+          'beginTypeVariables <',
+          'beginMetadataStar S',
+          'endMetadataStar 0',
+          'handleIdentifier S typeVariableDeclaration',
+          'beginTypeVariable S',
+          'handleTypeVariablesDefined T 1',
+          'handleIdentifier T typeReference',
+          'handleNoTypeArguments >',
+          'handleType T',
+          'endTypeVariable > 0 extends',
+          'endTypeVariables < >',
+        ]);
+    expectComplexTypeParam('<S extends List<T>>',
+        typeArgumentCount: 1,
+        expectedCalls: [
+          'beginTypeVariables <',
+          'beginMetadataStar S',
+          'endMetadataStar 0',
+          'handleIdentifier S typeVariableDeclaration',
+          'beginTypeVariable S',
+          'handleTypeVariablesDefined > 1',
+          'handleIdentifier List typeReference',
+          'beginTypeArguments <',
+          'handleIdentifier T typeReference',
+          'handleNoTypeArguments >',
+          'handleType T',
+          'endTypeArguments 1 < >',
+          'handleType List',
+          'endTypeVariable > 0 extends',
+          'endTypeVariables < >',
+        ]);
+    expectComplexTypeParam('<R, S extends void Function()>',
+        typeArgumentCount: 2,
+        expectedCalls: [
+          'beginTypeVariables <',
+          'beginMetadataStar R',
+          'endMetadataStar 0',
+          'handleIdentifier R typeVariableDeclaration',
+          'beginTypeVariable R',
+          'beginMetadataStar S',
+          'endMetadataStar 0',
+          'handleIdentifier S typeVariableDeclaration',
+          'beginTypeVariable S',
+          'handleTypeVariablesDefined ) 2',
+          'handleNoTypeVariables (',
+          'beginFunctionType void',
+          'handleVoidKeyword void',
+          'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
+          'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
+          'endFunctionType Function',
+          'endTypeVariable > 1 extends',
+          'handleNoType R',
+          'endTypeVariable , 0 null',
+          'endTypeVariables < >',
+        ]);
+    expectComplexTypeParam('<@A S,T>', typeArgumentCount: 2, expectedCalls: [
       'beginTypeVariables <',
       'beginMetadataStar @',
       'beginMetadata @',
@@ -1451,7 +1498,7 @@
       'endTypeVariable , 0 null',
       'endTypeVariables < >',
     ]);
-    expectComplexTypeParam('<@A() S,T>', expectedCalls: [
+    expectComplexTypeParam('<@A() S,T>', typeArgumentCount: 2, expectedCalls: [
       'beginTypeVariables <',
       'beginMetadataStar @',
       'beginMetadata @',
@@ -1474,82 +1521,93 @@
       'endTypeVariable , 0 null',
       'endTypeVariables < >',
     ]);
-    expectComplexTypeParam('<@A() @B S,T>', expectedCalls: [
-      'beginTypeVariables <',
-      'beginMetadataStar @',
-      'beginMetadata @',
-      'handleIdentifier A metadataReference',
-      'handleNoTypeArguments (',
-      'beginArguments (',
-      'endArguments 0 ( )',
-      'endMetadata @ null @',
-      'beginMetadata @',
-      'handleIdentifier B metadataReference',
-      'handleNoTypeArguments S',
-      'handleNoArguments S',
-      'endMetadata @ null S',
-      'endMetadataStar 2',
-      'handleIdentifier S typeVariableDeclaration',
-      'beginTypeVariable S',
-      'beginMetadataStar T',
-      'endMetadataStar 0',
-      'handleIdentifier T typeVariableDeclaration',
-      'beginTypeVariable T',
-      'handleTypeVariablesDefined T 2',
-      'handleNoType T',
-      'endTypeVariable > 1 null',
-      'handleNoType S',
-      'endTypeVariable , 0 null',
-      'endTypeVariables < >',
-    ]);
+    expectComplexTypeParam('<@A() @B S,T>',
+        typeArgumentCount: 2,
+        expectedCalls: [
+          'beginTypeVariables <',
+          'beginMetadataStar @',
+          'beginMetadata @',
+          'handleIdentifier A metadataReference',
+          'handleNoTypeArguments (',
+          'beginArguments (',
+          'endArguments 0 ( )',
+          'endMetadata @ null @',
+          'beginMetadata @',
+          'handleIdentifier B metadataReference',
+          'handleNoTypeArguments S',
+          'handleNoArguments S',
+          'endMetadata @ null S',
+          'endMetadataStar 2',
+          'handleIdentifier S typeVariableDeclaration',
+          'beginTypeVariable S',
+          'beginMetadataStar T',
+          'endMetadataStar 0',
+          'handleIdentifier T typeVariableDeclaration',
+          'beginTypeVariable T',
+          'handleTypeVariablesDefined T 2',
+          'handleNoType T',
+          'endTypeVariable > 1 null',
+          'handleNoType S',
+          'endTypeVariable , 0 null',
+          'endTypeVariables < >',
+        ]);
   }
 
   void test_computeTypeParam_complex_extends_void() {
-    expectComplexTypeParam('<T extends void>', expectedErrors: [
-      error(codeInvalidVoid, 11, 4),
-    ], expectedCalls: [
-      'beginTypeVariables <',
-      'beginMetadataStar T',
-      'endMetadataStar 0',
-      'handleIdentifier T typeVariableDeclaration',
-      'beginTypeVariable T',
-      'handleTypeVariablesDefined void 1',
-      'handleIdentifier void typeReference',
-      'handleNoTypeArguments >',
-      'handleType void',
-      'endTypeVariable > 0 extends',
-      'endTypeVariables < >'
-    ]);
+    expectComplexTypeParam('<T extends void>',
+        typeArgumentCount: 1,
+        expectedErrors: [
+          error(codeInvalidVoid, 11, 4),
+        ],
+        expectedCalls: [
+          'beginTypeVariables <',
+          'beginMetadataStar T',
+          'endMetadataStar 0',
+          'handleIdentifier T typeVariableDeclaration',
+          'beginTypeVariable T',
+          'handleTypeVariablesDefined void 1',
+          'handleIdentifier void typeReference',
+          'handleNoTypeArguments >',
+          'handleType void',
+          'endTypeVariable > 0 extends',
+          'endTypeVariables < >'
+        ]);
   }
 
   void test_computeTypeParam_complex_recovery() {
-    expectComplexTypeParam('<S Function()>', expectedErrors: [
-      error(codeExpectedAfterButGot, 1, 1),
-    ], expectedCalls: [
-      'beginTypeVariables <',
-      'beginMetadataStar S',
-      'endMetadataStar 0',
-      'handleIdentifier S typeVariableDeclaration',
-      'beginTypeVariable S',
-      'handleTypeVariablesDefined S 1',
-      'handleNoType S',
-      'endTypeVariable Function 0 null',
-      'endTypeVariables < >',
-    ]);
-    expectComplexTypeParam('<void Function()>', expectedErrors: [
-      error(codeExpectedIdentifier, 1, 4),
-    ], expectedCalls: [
-      'beginTypeVariables <',
-      'beginMetadataStar void',
-      'endMetadataStar 0',
-      'handleIdentifier  typeVariableDeclaration',
-      'beginTypeVariable ',
-      'handleTypeVariablesDefined  1',
-      'handleNoType ',
-      'endTypeVariable void 0 null',
-      'endTypeVariables < >',
-    ]);
-    expectComplexTypeParam('<S<T>>', expectedErrors: [
+    expectComplexTypeParam('<S Function()>',
+        typeArgumentCount: 1,
+        expectedErrors: [
+          error(codeExpectedAfterButGot, 1, 1),
+        ],
+        expectedCalls: [
+          'beginTypeVariables <',
+          'beginMetadataStar S',
+          'endMetadataStar 0',
+          'handleIdentifier S typeVariableDeclaration',
+          'beginTypeVariable S',
+          'handleTypeVariablesDefined S 1',
+          'handleNoType S',
+          'endTypeVariable Function 0 null',
+          'endTypeVariables < >',
+        ]);
+    expectComplexTypeParam('<void Function()>',
+        typeArgumentCount: 1,
+        expectedErrors: [
+          error(codeExpectedIdentifier, 1, 4),
+        ],
+        expectedCalls: [
+          'beginTypeVariables <',
+          'beginMetadataStar void',
+          'endMetadataStar 0',
+          'handleIdentifier  typeVariableDeclaration',
+          'beginTypeVariable ',
+          'handleTypeVariablesDefined  1',
+          'handleNoType ',
+          'endTypeVariable void 0 null',
+          'endTypeVariables < >',
+        ]);
+    expectComplexTypeParam('<S<T>>', typeArgumentCount: 1, expectedErrors: [
       error(codeExpectedAfterButGot, 1, 1),
     ], expectedCalls: [
       'beginTypeVariables <',
@@ -1562,21 +1620,30 @@
       'endTypeVariable < 0 null',
       'endTypeVariables < >',
     ]);
-    expectComplexTypeParam('<S T>', inDeclaration: true, expectedErrors: [
-      error(codeExpectedButGot, 3, 1),
-    ]);
-    expectComplexTypeParam('<S', inDeclaration: true, expectedErrors: [
-      error(codeExpectedAfterButGot, 1, 1),
-    ]);
+    expectComplexTypeParam('<S T>',
+        inDeclaration: true,
+        typeArgumentCount: 2,
+        expectedErrors: [
+          error(codeExpectedButGot, 3, 1),
+        ]);
+    expectComplexTypeParam('<S',
+        inDeclaration: true,
+        typeArgumentCount: 1,
+        expectedErrors: [
+          error(codeExpectedAfterButGot, 1, 1),
+        ]);
     expectComplexTypeParam('<@Foo S',
         inDeclaration: true,
+        typeArgumentCount: 1,
         expectedErrors: [error(codeExpectedAfterButGot, 6, 1)]);
     expectComplexTypeParam('<@Foo }',
         inDeclaration: true,
+        typeArgumentCount: 0,
         expectedAfter: '}',
         expectedErrors: [error(codeExpectedIdentifier, 6, 1)]);
     expectComplexTypeParam('<S extends List<T fieldName;',
         inDeclaration: true,
+        typeArgumentCount: 1,
         expectedErrors: [error(codeExpectedAfterButGot, 16, 1)],
         expectedAfter: 'fieldName',
         expectedCalls: [
@@ -1599,110 +1666,123 @@
   }
 
   void test_computeTypeParam_31846() {
-    expectComplexTypeParam('<T extends Comparable<T>>', expectedCalls: [
-      'beginTypeVariables <',
-      'beginMetadataStar T',
-      'endMetadataStar 0',
-      'handleIdentifier T typeVariableDeclaration',
-      'beginTypeVariable T',
-      'handleTypeVariablesDefined > 1',
-      'handleIdentifier Comparable typeReference',
-      'beginTypeArguments <',
-      'handleIdentifier T typeReference',
-      'handleNoTypeArguments >',
-      'handleType T',
-      'endTypeArguments 1 < >',
-      'handleType Comparable',
-      'endTypeVariable > 0 extends',
-      'endTypeVariables < >',
-    ]);
-    expectComplexTypeParam('<T extends Comparable<S>, S>', expectedCalls: [
-      'beginTypeVariables <',
-      'beginMetadataStar T',
-      'endMetadataStar 0',
-      'handleIdentifier T typeVariableDeclaration',
-      'beginTypeVariable T',
-      'beginMetadataStar S',
-      'endMetadataStar 0',
-      'handleIdentifier S typeVariableDeclaration',
-      'beginTypeVariable S',
-      'handleTypeVariablesDefined S 2',
-      'handleNoType S',
-      'endTypeVariable > 1 null',
-      'handleIdentifier Comparable typeReference',
-      'beginTypeArguments <',
-      'handleIdentifier S typeReference',
-      'handleNoTypeArguments >',
-      'handleType S',
-      'endTypeArguments 1 < >',
-      'handleType Comparable',
-      'endTypeVariable , 0 extends',
-      'endTypeVariables < >'
-    ]);
-    expectComplexTypeParam('<T extends Function(T)>', expectedCalls: [
-      'beginTypeVariables <',
-      'beginMetadataStar T',
-      'endMetadataStar 0',
-      'handleIdentifier T typeVariableDeclaration',
-      'beginTypeVariable T',
-      'handleTypeVariablesDefined ) 1',
-      'handleNoTypeVariables (',
-      'beginFunctionType Function',
-      'handleNoType extends',
-      'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
-      'beginMetadataStar T',
-      'endMetadataStar 0',
-      'beginFormalParameter T MemberKind.GeneralizedFunctionType',
-      'handleIdentifier T typeReference',
-      'handleNoTypeArguments )',
-      'handleType T',
-      'handleNoName )',
-      'handleFormalParameterWithoutValue )',
-      'endFormalParameter null null ) FormalParameterKind.mandatory MemberKind.GeneralizedFunctionType',
-      'endFormalParameters 1 ( ) MemberKind.GeneralizedFunctionType',
-      'endFunctionType Function',
-      'endTypeVariable > 0 extends',
-      'endTypeVariables < >'
-    ]);
-    expectComplexTypeParam('<T extends List<List<T>>>', expectedCalls: [
-      'beginTypeVariables <',
-      'beginMetadataStar T',
-      'endMetadataStar 0',
-      'handleIdentifier T typeVariableDeclaration',
-      'beginTypeVariable T',
-      'handleTypeVariablesDefined > 1',
-      'handleIdentifier List typeReference',
-      'beginTypeArguments <',
-      'handleIdentifier List typeReference',
-      'beginTypeArguments <',
-      'handleIdentifier T typeReference',
-      'handleNoTypeArguments >',
-      'handleType T',
-      'endTypeArguments 1 < >',
-      'handleType List',
-      'endTypeArguments 1 < >',
-      'handleType List',
-      'endTypeVariable > 0 extends',
-      'endTypeVariables < >'
-    ]);
+    expectComplexTypeParam('<T extends Comparable<T>>',
+        typeArgumentCount: 1,
+        expectedCalls: [
+          'beginTypeVariables <',
+          'beginMetadataStar T',
+          'endMetadataStar 0',
+          'handleIdentifier T typeVariableDeclaration',
+          'beginTypeVariable T',
+          'handleTypeVariablesDefined > 1',
+          'handleIdentifier Comparable typeReference',
+          'beginTypeArguments <',
+          'handleIdentifier T typeReference',
+          'handleNoTypeArguments >',
+          'handleType T',
+          'endTypeArguments 1 < >',
+          'handleType Comparable',
+          'endTypeVariable > 0 extends',
+          'endTypeVariables < >',
+        ]);
+    expectComplexTypeParam('<T extends Comparable<S>, S>',
+        typeArgumentCount: 2,
+        expectedCalls: [
+          'beginTypeVariables <',
+          'beginMetadataStar T',
+          'endMetadataStar 0',
+          'handleIdentifier T typeVariableDeclaration',
+          'beginTypeVariable T',
+          'beginMetadataStar S',
+          'endMetadataStar 0',
+          'handleIdentifier S typeVariableDeclaration',
+          'beginTypeVariable S',
+          'handleTypeVariablesDefined S 2',
+          'handleNoType S',
+          'endTypeVariable > 1 null',
+          'handleIdentifier Comparable typeReference',
+          'beginTypeArguments <',
+          'handleIdentifier S typeReference',
+          'handleNoTypeArguments >',
+          'handleType S',
+          'endTypeArguments 1 < >',
+          'handleType Comparable',
+          'endTypeVariable , 0 extends',
+          'endTypeVariables < >'
+        ]);
+    expectComplexTypeParam('<T extends Function(T)>',
+        typeArgumentCount: 1,
+        expectedCalls: [
+          'beginTypeVariables <',
+          'beginMetadataStar T',
+          'endMetadataStar 0',
+          'handleIdentifier T typeVariableDeclaration',
+          'beginTypeVariable T',
+          'handleTypeVariablesDefined ) 1',
+          'handleNoTypeVariables (',
+          'beginFunctionType Function',
+          'handleNoType extends',
+          'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
+          'beginMetadataStar T',
+          'endMetadataStar 0',
+          'beginFormalParameter T MemberKind.GeneralizedFunctionType',
+          'handleIdentifier T typeReference',
+          'handleNoTypeArguments )',
+          'handleType T',
+          'handleNoName )',
+          'handleFormalParameterWithoutValue )',
+          'endFormalParameter null null ) FormalParameterKind.mandatory MemberKind.GeneralizedFunctionType',
+          'endFormalParameters 1 ( ) MemberKind.GeneralizedFunctionType',
+          'endFunctionType Function',
+          'endTypeVariable > 0 extends',
+          'endTypeVariables < >'
+        ]);
+    expectComplexTypeParam('<T extends List<List<T>>>',
+        typeArgumentCount: 1,
+        expectedCalls: [
+          'beginTypeVariables <',
+          'beginMetadataStar T',
+          'endMetadataStar 0',
+          'handleIdentifier T typeVariableDeclaration',
+          'beginTypeVariable T',
+          'handleTypeVariablesDefined > 1',
+          'handleIdentifier List typeReference',
+          'beginTypeArguments <',
+          'handleIdentifier List typeReference',
+          'beginTypeArguments <',
+          'handleIdentifier T typeReference',
+          'handleNoTypeArguments >',
+          'handleType T',
+          'endTypeArguments 1 < >',
+          'handleType List',
+          'endTypeArguments 1 < >',
+          'handleType List',
+          'endTypeVariable > 0 extends',
+          'endTypeVariables < >'
+        ]);
   }
 
   void test_computeTypeParam_34850() {
-    expectComplexTypeParam('<S<T>> A', expectedAfter: 'A', expectedErrors: [
-      error(codeExpectedAfterButGot, 1, 1),
-    ], expectedCalls: [
-      'beginTypeVariables <',
-      'beginMetadataStar S',
-      'endMetadataStar 0',
-      'handleIdentifier S typeVariableDeclaration',
-      'beginTypeVariable S',
-      'handleTypeVariablesDefined S 1',
-      'handleNoType S',
-      'endTypeVariable < 0 null',
-      'endTypeVariables < >',
-    ]);
+    expectComplexTypeParam('<S<T>> A',
+        typeArgumentCount: 1,
+        expectedAfter: 'A',
+        expectedErrors: [
+          error(codeExpectedAfterButGot, 1, 1),
+        ],
+        expectedCalls: [
+          'beginTypeVariables <',
+          'beginMetadataStar S',
+          'endMetadataStar 0',
+          'handleIdentifier S typeVariableDeclaration',
+          'beginTypeVariable S',
+          'handleTypeVariablesDefined S 1',
+          'handleNoType S',
+          'endTypeVariable < 0 null',
+          'endTypeVariables < >',
+        ]);
     expectComplexTypeParam('<S();> A',
         inDeclaration: true,
+        typeArgumentCount: 1,
         expectedAfter: 'A',
         expectedErrors: [
           error(codeExpectedAfterButGot, 1, 1),
@@ -1798,6 +1878,7 @@
 
 void expectComplexTypeArg(String source,
     {bool inDeclaration = false,
+    int typeArgumentCount = -1,
     String expectedAfter,
     List<String> expectedCalls,
     List<ExpectedError> expectedErrors}) {
@@ -1815,6 +1896,7 @@
   expect(countGtGtAndNullEnd(start), expectedGtGtAndNullEndCount,
       reason: 'TypeParamOrArgInfo.skipType'
           ' should not modify the token stream');
+  expect(typeVarInfo.typeArgumentCount, typeArgumentCount);
 
   TypeInfoListener listener = new TypeInfoListener();
   Parser parser = new Parser(listener);
@@ -1830,6 +1912,7 @@
 
 void expectComplexTypeParam(String source,
     {bool inDeclaration = false,
+    int typeArgumentCount = -1,
     String expectedAfter,
     List<String> expectedCalls,
     List<ExpectedError> expectedErrors}) {
@@ -1847,6 +1930,7 @@
   expect(countGtGtAndNullEnd(start), expectedGtGtAndNullEndCount,
       reason: 'TypeParamOrArgInfo.skipType'
           ' should not modify the token stream');
+  expect(typeVarInfo.typeArgumentCount, typeArgumentCount);
 
   TypeInfoListener listener =
       new TypeInfoListener(firstToken: start, metadataAllowed: true);
diff --git a/pkg/front_end/test/fasta/sdk_test.dart b/pkg/front_end/test/fasta/sdk_test.dart
index 90c2a5f..515a243 100644
--- a/pkg/front_end/test/fasta/sdk_test.dart
+++ b/pkg/front_end/test/fasta/sdk_test.dart
@@ -2,7 +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.md file.
 
-library fasta.test.compile_test;
+library fasta.test.sdk_test;
 
 import 'dart:async' show Future;
 
@@ -11,6 +11,7 @@
 Future<FastaContext> createContext(
     Chain suite, Map<String, String> environment) async {
   environment[ENABLE_FULL_COMPILE] = "";
+  environment[LEGACY_MODE] = "";
   environment["skipVm"] ??= "true";
   environment["onlyCrashes"] ??= "true";
   environment["ignoreExpectations"] ??= "true";
diff --git a/pkg/front_end/test/fasta/strong_test.dart b/pkg/front_end/test/fasta/strong_test.dart
index 9adc4aa..e8e430d 100644
--- a/pkg/front_end/test/fasta/strong_test.dart
+++ b/pkg/front_end/test/fasta/strong_test.dart
@@ -2,7 +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.md file.
 
-library fasta.test.compile_test;
+library fasta.test.strong_test;
 
 import 'dart:async' show Future;
 
@@ -11,7 +11,6 @@
 Future<FastaContext> createContext(
     Chain suite, Map<String, String> environment) {
   environment[ENABLE_FULL_COMPILE] = "";
-  environment[STRONG_MODE] = "";
   return FastaContext.create(suite, environment);
 }
 
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 659fb1b..da3d94d 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -67,32 +67,44 @@
 
 export 'package:testing/testing.dart' show Chain, runMe;
 
-const String STRONG_MODE = " strong mode ";
+const String LEGACY_MODE = " legacy mode ";
 
 const String ENABLE_FULL_COMPILE = " full compile ";
 
 const String EXPECTATIONS = '''
 [
   {
-    "name": "VerificationError",
+    "name": "ExpectationFileMismatch",
+    "group": "Fail"
+  },
+  {
+    "name": "ExpectationFileMissing",
+    "group": "Fail"
+  },
+  {
+    "name": "InstrumentationMismatch",
     "group": "Fail"
   },
   {
     "name": "TypeCheckError",
     "group": "Fail"
+  },
+  {
+    "name": "VerificationError",
+    "group": "Fail"
   }
 ]
 ''';
 
-String generateExpectationName(bool strongMode) {
-  return strongMode ? "strong" : "direct";
+String generateExpectationName(bool legacyMode) {
+  return legacyMode ? "legacy" : "strong";
 }
 
 class FastaContext extends ChainContext {
   final UriTranslator uriTranslator;
   final List<Step> steps;
   final Uri vm;
-  final bool strongMode;
+  final bool legacyMode;
   final bool onlyCrashes;
   final Map<Component, KernelTarget> componentToTarget =
       <Component, KernelTarget>{};
@@ -108,7 +120,7 @@
 
   FastaContext(
       this.vm,
-      this.strongMode,
+      this.legacyMode,
       this.platformBinaries,
       this.onlyCrashes,
       bool ignoreExpectations,
@@ -118,7 +130,7 @@
       this.uriTranslator,
       bool fullCompile)
       : steps = <Step>[
-          new Outline(fullCompile, strongMode, updateComments: updateComments),
+          new Outline(fullCompile, legacyMode, updateComments: updateComments),
           const Print(),
           new Verify(fullCompile)
         ] {
@@ -126,11 +138,11 @@
     if (!ignoreExpectations) {
       steps.add(new MatchExpectation(
           fullCompile
-              ? ".${generateExpectationName(strongMode)}.expect"
+              ? ".${generateExpectationName(legacyMode)}.expect"
               : ".outline.expect",
           updateExpectations: updateExpectations));
     }
-    if (strongMode) {
+    if (!legacyMode) {
       steps.add(const TypeCheck());
     }
     steps.add(const EnsureNoErrors());
@@ -139,7 +151,7 @@
       if (!ignoreExpectations) {
         steps.add(new MatchExpectation(
             fullCompile
-                ? ".${generateExpectationName(strongMode)}.transformed.expect"
+                ? ".${generateExpectationName(legacyMode)}.transformed.expect"
                 : ".outline.transformed.expect",
             updateExpectations: updateExpectations));
       }
@@ -152,7 +164,7 @@
   Future ensurePlatformUris() async {
     if (platformUri == null) {
       platformUri = platformBinaries
-          .resolve(strongMode ? "vm_platform_strong.dill" : "vm_platform.dill");
+          .resolve(legacyMode ? "vm_platform.dill" : "vm_platform_strong.dill");
     }
   }
 
@@ -191,7 +203,7 @@
           ..sdkRoot = sdk
           ..packagesFileUri = packages);
     UriTranslator uriTranslator = await options.getUriTranslator();
-    bool strongMode = environment.containsKey(STRONG_MODE);
+    bool legacyMode = environment.containsKey(LEGACY_MODE);
     bool onlyCrashes = environment["onlyCrashes"] == "true";
     bool ignoreExpectations = environment["ignoreExpectations"] == "true";
     bool updateExpectations = environment["updateExpectations"] == "true";
@@ -203,7 +215,7 @@
     }
     return new FastaContext(
         vm,
-        strongMode,
+        legacyMode,
         platformBinaries == null
             ? computePlatformBinariesLocation(forceBuildDir: true)
             : Uri.base.resolve(platformBinaries),
@@ -234,7 +246,7 @@
     StdioProcess process;
     try {
       var args = <String>[];
-      if (context.strongMode) {
+      if (!context.legacyMode) {
         // TODO(ahe): This argument is probably ignored by the VM.
         args.add('--strong');
         // TODO(ahe): This argument is probably ignored by the VM.
@@ -253,9 +265,9 @@
 class Outline extends Step<TestDescription, Component, FastaContext> {
   final bool fullCompile;
 
-  final bool strongMode;
+  final bool legacyMode;
 
-  const Outline(this.fullCompile, this.strongMode,
+  const Outline(this.fullCompile, this.legacyMode,
       {this.updateComments: false});
 
   final bool updateComments;
@@ -271,7 +283,7 @@
     StringBuffer errors = new StringBuffer();
     ProcessedOptions options = new ProcessedOptions(
         options: new CompilerOptions()
-          ..legacyMode = !strongMode
+          ..legacyMode = legacyMode
           ..onDiagnostic = (DiagnosticMessage message) {
             if (errors.isNotEmpty) {
               errors.write("\n\n");
@@ -286,7 +298,7 @@
       Component platform = await context.loadPlatform();
       Ticker ticker = new Ticker();
       DillTarget dillTarget = new DillTarget(ticker, context.uriTranslator,
-          new TestVmTarget(new TargetFlags(legacyMode: !strongMode)));
+          new TestVmTarget(new TargetFlags(legacyMode: legacyMode)));
       dillTarget.loader.appendLibraries(platform);
       // We create a new URI translator to avoid reading platform libraries from
       // file system.
@@ -299,12 +311,16 @@
       sourceTarget.setEntryPoints(<Uri>[description.uri]);
       await dillTarget.buildOutlines();
       ValidatingInstrumentation instrumentation;
-      if (strongMode) {
+      if (!legacyMode) {
         instrumentation = new ValidatingInstrumentation();
         await instrumentation.loadExpectations(description.uri);
         sourceTarget.loader.instrumentation = instrumentation;
       }
       Component p = await sourceTarget.buildOutlines();
+      context.componentToTarget.clear();
+      context.componentToTarget[p] = sourceTarget;
+      context.componentToDiagnostics.clear();
+      context.componentToDiagnostics[p] = errors;
       if (fullCompile) {
         p = await sourceTarget.buildComponent();
         instrumentation?.finish();
@@ -312,14 +328,14 @@
           if (updateComments) {
             await instrumentation.fixSource(description.uri, false);
           } else {
-            return fail(null, instrumentation.problemsAsString);
+            return new Result<Component>(
+                p,
+                context.expectationSet["InstrumentationMismatch"],
+                instrumentation.problemsAsString,
+                null);
           }
         }
       }
-      context.componentToTarget.clear();
-      context.componentToTarget[p] = sourceTarget;
-      context.componentToDiagnostics.clear();
-      context.componentToDiagnostics[p] = errors;
       return pass(p);
     });
   }
diff --git a/pkg/front_end/test/fasta/type_inference/interface_resolver_test.dart b/pkg/front_end/test/fasta/type_inference/interface_resolver_test.dart
index 97a1d64..6389bc7 100644
--- a/pkg/front_end/test/fasta/type_inference/interface_resolver_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/interface_resolver_test.dart
@@ -47,12 +47,12 @@
 
   TypeSchemaEnvironment get typeEnvironment {
     return cachedTypeEnvironment ??=
-        new TypeSchemaEnvironment(coreTypes, classHierarchy, true);
+        new TypeSchemaEnvironment(coreTypes, classHierarchy, false);
   }
 
   InterfaceResolver get interfaceResolver {
     return cachedInterfaceResolver ??=
-        new InterfaceResolver(null, typeEnvironment, null, true);
+        new InterfaceResolver(null, typeEnvironment, null, false);
   }
 
   InterfaceType get intType => coreTypes.intClass.rawType;
diff --git a/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart b/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart
index dddce21..3df1a9e 100644
--- a/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart
@@ -210,7 +210,7 @@
   void _checkConstraints(
       DartType a, DartType b, List<String> expectedConstraints) {
     var typeSchemaEnvironment = new TypeSchemaEnvironment(
-        coreTypes, new ClassHierarchy(component), true);
+        coreTypes, new ClassHierarchy(component), false);
     var typeConstraintGatherer = new TypeConstraintGatherer(
         typeSchemaEnvironment, [T1.parameter, T2.parameter]);
     var constraints = typeConstraintGatherer.trySubtypeMatch(a, b)
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
index cddd384..86e1564 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
@@ -715,7 +715,7 @@
 
   TypeSchemaEnvironment _makeEnv() {
     return new TypeSchemaEnvironment(
-        coreTypes, new ClassHierarchy(component), true);
+        coreTypes, new ClassHierarchy(component), false);
   }
 
   DartType _map(DartType key, DartType value) =>
diff --git a/pkg/front_end/test/fasta/type_promotion_look_ahead_test.dart b/pkg/front_end/test/fasta/type_promotion_look_ahead_test.dart
new file mode 100644
index 0000000..9fe6f56
--- /dev/null
+++ b/pkg/front_end/test/fasta/type_promotion_look_ahead_test.dart
@@ -0,0 +1,277 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert' show jsonDecode;
+
+import 'dart:io' show File, IOSink;
+
+import 'package:front_end/src/base/processed_options.dart'
+    show ProcessedOptions;
+
+import 'package:front_end/src/fasta/builder/builder.dart' show Declaration;
+
+import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
+
+import 'package:front_end/src/fasta/messages.dart'
+    show LocatedMessage, templateUnspecified;
+
+import 'package:front_end/src/fasta/parser.dart' show Parser;
+
+import 'package:front_end/src/fasta/scanner.dart' show Token;
+
+import 'package:front_end/src/fasta/severity.dart' show Severity;
+
+import 'package:front_end/src/fasta/source/type_promotion_look_ahead_listener.dart'
+    show
+        TypePromotionLookAheadListener,
+        TypePromotionState,
+        UnspecifiedDeclaration;
+
+import 'package:front_end/src/fasta/testing/kernel_chain.dart'
+    show openWrite, runDiff;
+
+import 'package:front_end/src/fasta/testing/scanner_chain.dart'
+    show Read, Scan, ScannedFile;
+
+import 'package:kernel/ast.dart' show Source;
+
+import 'package:testing/testing.dart';
+
+const String EXPECTATIONS = '''
+[
+  {
+    "name": "ExpectationFileMismatch",
+    "group": "Fail"
+  },
+  {
+    "name": "ExpectationFileMissing",
+    "group": "Fail"
+  }
+]
+''';
+
+Future<ChainContext> createContext(
+    Chain suite, Map<String, String> environment) async {
+  CompilerContext context =
+      await CompilerContext.runWithOptions<CompilerContext>(
+          new ProcessedOptions(),
+          (CompilerContext context) =>
+              new Future<CompilerContext>.value(context),
+          errorOnMissingInput: false);
+  context.disableColors();
+  return new TypePromotionLookAheadContext(
+      context, environment["updateExpectations"] == "true");
+}
+
+class TypePromotionLookAheadContext extends ChainContext {
+  final CompilerContext context;
+
+  final List<Step> steps = const <Step>[
+    const Read(),
+    const Scan(),
+    const TypePromotionLookAheadStep(),
+    const CheckTypePromotionResult(),
+  ];
+
+  final bool updateExpectations;
+
+  final ExpectationSet expectationSet =
+      new ExpectationSet.fromJsonList(jsonDecode(EXPECTATIONS));
+
+  TypePromotionLookAheadContext(this.context, this.updateExpectations);
+
+  Expectation get expectationFileMismatch =>
+      expectationSet["ExpectationFileMismatch"];
+
+  Expectation get expectationFileMissing =>
+      expectationSet["ExpectationFileMissing"];
+}
+
+class TypePromotionLookAheadStep extends Step<ScannedFile, TypePromotionResult,
+    TypePromotionLookAheadContext> {
+  const TypePromotionLookAheadStep();
+
+  String get name => "Type Promotion Look Ahead";
+
+  Future<Result<TypePromotionResult>> run(
+      ScannedFile file, TypePromotionLookAheadContext context) async {
+    return context.context
+        .runInContext<Result<TypePromotionResult>>((CompilerContext c) async {
+      Uri uri = file.file.uri;
+      c.uriToSource[uri] = new Source(file.result.lineStarts, file.file.bytes);
+      StringBuffer buffer = new StringBuffer();
+      Parser parser = new Parser(new TestListener(uri, buffer));
+      try {
+        parser.parseUnit(file.result.tokens);
+      } finally {
+        c.uriToSource.remove(uri);
+      }
+      return pass(new TypePromotionResult(uri, "$buffer"));
+    });
+  }
+}
+
+class TestState extends TypePromotionState {
+  final StringBuffer buffer;
+
+  TestState(Uri uri, this.buffer) : super(uri);
+
+  void note(String message, Token token) {
+    buffer.writeln(CompilerContext.current.format(
+        debugMessage(message, uri, token.charOffset, token.lexeme.length),
+        Severity.context));
+  }
+
+  @override
+  void checkEmpty(Token token) {
+    if (stack.isNotEmpty) {
+      throw CompilerContext.current.format(
+          debugMessage("Stack not empty", uri, token?.charOffset ?? -1,
+              token?.length ?? 1),
+          Severity.internalProblem);
+    }
+  }
+
+  @override
+  void declareIdentifier(Token token) {
+    super.declareIdentifier(token);
+    trace("Declared ${token.lexeme}", token);
+  }
+
+  @override
+  Declaration nullValue(String name, Token token) {
+    return new DebugDeclaration(name, uri, token?.charOffset ?? -1);
+  }
+
+  @override
+  void registerWrite(UnspecifiedDeclaration declaration, Token token) {
+    note("Write to ${declaration.name}@${declaration.charOffset}", token);
+  }
+
+  @override
+  void registerPromotionCandidate(
+      UnspecifiedDeclaration declaration, Token token) {
+    note("Possible promotion of ${declaration.name}@${declaration.charOffset}",
+        token);
+  }
+
+  @override
+  void report(LocatedMessage message, Severity severity,
+      {List<LocatedMessage> context}) {
+    CompilerContext.current.report(message, severity, context: context);
+  }
+
+  @override
+  void trace(String message, Token token) {
+    report(
+        debugMessage(message, uri, token?.charOffset ?? -1, token?.length ?? 1),
+        Severity.warning);
+    for (Object o in stack) {
+      String s = "  $o";
+      int index = s.indexOf("\n");
+      if (index != -1) {
+        s = s.substring(0, index) + "...";
+      }
+      print(s);
+    }
+    print('------------------\n');
+  }
+}
+
+LocatedMessage debugMessage(String text, Uri uri, int offset, int length) {
+  return templateUnspecified
+      .withArguments(text)
+      .withLocation(uri, offset, length);
+}
+
+class TestListener extends TypePromotionLookAheadListener {
+  TestListener(Uri uri, StringBuffer buffer)
+      : super(new TestState(uri, buffer));
+
+  @override
+  void debugEvent(String name, Token token) {
+    state.trace(name, token);
+  }
+}
+
+class DebugDeclaration extends Declaration {
+  final String name;
+
+  @override
+  final Uri fileUri;
+
+  @override
+  int charOffset;
+
+  DebugDeclaration(this.name, this.fileUri, this.charOffset);
+
+  Declaration get parent => null;
+
+  String get fullNameForErrors => name;
+
+  String toString() => "<<$name@$charOffset>>";
+}
+
+class TypePromotionResult {
+  final Uri uri;
+
+  final String trace;
+
+  const TypePromotionResult(this.uri, this.trace);
+}
+
+class CheckTypePromotionResult
+    extends Step<TypePromotionResult, Null, TypePromotionLookAheadContext> {
+  const CheckTypePromotionResult();
+
+  String get name => "Check Type Promotion Result";
+
+  Future<Result<Null>> run(
+      TypePromotionResult result, TypePromotionLookAheadContext context) async {
+    Uri uri = result.uri;
+    String actual = result.trace.trim();
+    if (actual.isNotEmpty) {
+      actual += "\n";
+    }
+    File expectedFile = new File("${uri.toFilePath()}.type_promotion.expect");
+    if (await expectedFile.exists()) {
+      String expected = await expectedFile.readAsString();
+      if (expected != actual) {
+        if (context.updateExpectations) {
+          return updateExpectationFile(expectedFile.uri, actual);
+        }
+        String diff = await runDiff(expectedFile.uri, actual);
+        return new Result<Null>(null, context.expectationFileMismatch,
+            "$uri doesn't match ${expectedFile.uri}\n$diff", null);
+      }
+      return pass(null);
+    } else {
+      if (actual.isEmpty) return pass(null);
+      if (context.updateExpectations) {
+        return updateExpectationFile(expectedFile.uri, actual);
+      }
+      return new Result<Null>(
+          null,
+          context.expectationFileMissing,
+          """
+Please create file ${expectedFile.path} with this content:
+$actual""",
+          null);
+    }
+  }
+
+  Future<Result<Null>> updateExpectationFile(Uri uri, String actual) async {
+    if (actual.isEmpty) {
+      await new File.fromUri(uri).delete();
+    } else {
+      await openWrite(uri, (IOSink sink) {
+        sink.write(actual);
+      });
+    }
+    return pass(null);
+  }
+}
+
+main([List<String> arguments = const []]) =>
+    runMe(arguments, createContext, "../../testing.json");
diff --git a/pkg/front_end/testcases/DeltaBlue.dart.direct.expect b/pkg/front_end/testcases/DeltaBlue.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/DeltaBlue.dart.direct.expect
rename to pkg/front_end/testcases/DeltaBlue.dart.legacy.expect
diff --git a/pkg/front_end/testcases/DeltaBlue.dart.strong.expect b/pkg/front_end/testcases/DeltaBlue.dart.strong.expect
index 2579576..78e2440 100644
--- a/pkg/front_end/testcases/DeltaBlue.dart.strong.expect
+++ b/pkg/front_end/testcases/DeltaBlue.dart.strong.expect
@@ -1,10 +1,9 @@
-// dynamic is not a subtype of dart.core::int (DeltaBlue.dart:139:16)
 library;
 import self as self;
 import "dart:core" as core;
 
 class DeltaBlue extends core::Object {
-  constructor •() → void
+  synthetic constructor •() → self::DeltaBlue
     : super core::Object::•()
     ;
   method run() → void {
@@ -15,7 +14,7 @@
 class Strength extends core::Object {
   final field core::int value;
   final field core::String name;
-  const constructor •(core::int value, core::String name) → void
+  const constructor •(core::int value, core::String name) → self::Strength
     : self::Strength::value = value, self::Strength::name = name, super core::Object::•()
     ;
   method nextWeaker() → self::Strength
@@ -27,12 +26,15 @@
     return s1.{self::Strength::value}.{core::num::>}(s2.{self::Strength::value});
   }
   static method weakest(self::Strength s1, self::Strength s2) → self::Strength {
-    return self::Strength::weaker(s1, s2) ? s1 : s2;
+    return self::Strength::weaker(s1, s2) ?{self::Strength} s1 : s2;
+  }
+  static method strongest(self::Strength s1, self::Strength s2) → self::Strength {
+    return self::Strength::stronger(s1, s2) ?{self::Strength} s1 : s2;
   }
 }
 abstract class Constraint extends core::Object {
   final field self::Strength strength;
-  const constructor •(self::Strength strength) → void
+  const constructor •(self::Strength strength) → self::Constraint
     : self::Constraint::strength = strength, super core::Object::•()
     ;
   abstract method isSatisfied() → core::bool;
@@ -50,22 +52,22 @@
     self::planner.{self::Planner::incrementalAdd}(this);
   }
   method satisfy(dynamic mark) → self::Constraint {
-    this.{self::Constraint::chooseMethod}(mark as core::int);
+    this.{self::Constraint::chooseMethod}(mark as{TypeError} core::int);
     if(!this.{self::Constraint::isSatisfied}()) {
       if(this.{self::Constraint::strength}.{core::Object::==}(self::REQUIRED)) {
         core::print("Could not satisfy a required constraint!");
       }
       return null;
     }
-    this.{self::Constraint::markInputs}(mark as core::int);
+    this.{self::Constraint::markInputs}(mark as{TypeError} core::int);
     self::Variable out = this.{self::Constraint::output}();
     self::Constraint overridden = out.{self::Variable::determinedBy};
     if(!overridden.{core::Object::==}(null))
       overridden.{self::Constraint::markUnsatisfied}();
     out.{self::Variable::determinedBy} = this;
-    if(!self::planner.{self::Planner::addPropagate}(this, mark as core::int))
+    if(!self::planner.{self::Planner::addPropagate}(this, mark as{TypeError} core::int))
       core::print("Cycle encountered");
-    out.{self::Variable::mark} = mark;
+    out.{self::Variable::mark} = mark as{TypeError} core::int;
     return overridden;
   }
   method destroyConstraint() → void {
@@ -79,7 +81,7 @@
 abstract class UnaryConstraint extends self::Constraint {
   final field self::Variable myOutput;
   field core::bool satisfied = false;
-  constructor •(self::Variable myOutput, self::Strength strength) → void
+  constructor •(self::Variable myOutput, self::Strength strength) → self::UnaryConstraint
     : self::UnaryConstraint::myOutput = myOutput, super self::Constraint::•(strength) {
     this.{self::Constraint::addConstraint}();
   }
@@ -113,13 +115,13 @@
   }
 }
 class StayConstraint extends self::UnaryConstraint {
-  constructor •(self::Variable v, self::Strength str) → void
+  constructor •(self::Variable v, self::Strength str) → self::StayConstraint
     : super self::UnaryConstraint::•(v, str)
     ;
   method execute() → void {}
 }
 class EditConstraint extends self::UnaryConstraint {
-  constructor •(self::Variable v, self::Strength str) → void
+  constructor •(self::Variable v, self::Strength str) → self::EditConstraint
     : super self::UnaryConstraint::•(v, str)
     ;
   method isInput() → core::bool
@@ -130,22 +132,22 @@
   field self::Variable v1;
   field self::Variable v2;
   field core::int direction = self::NONE;
-  constructor •(self::Variable v1, self::Variable v2, self::Strength strength) → void
+  constructor •(self::Variable v1, self::Variable v2, self::Strength strength) → self::BinaryConstraint
     : self::BinaryConstraint::v1 = v1, self::BinaryConstraint::v2 = v2, super self::Constraint::•(strength) {
     this.{self::Constraint::addConstraint}();
   }
   method chooseMethod(core::int mark) → void {
     if(this.{self::BinaryConstraint::v1}.{self::Variable::mark}.{core::num::==}(mark)) {
-      this.{self::BinaryConstraint::direction} = !this.{self::BinaryConstraint::v2}.{self::Variable::mark}.{core::num::==}(mark) && self::Strength::stronger(this.{self::Constraint::strength}, this.{self::BinaryConstraint::v2}.{self::Variable::walkStrength}) ? self::FORWARD : self::NONE;
+      this.{self::BinaryConstraint::direction} = !this.{self::BinaryConstraint::v2}.{self::Variable::mark}.{core::num::==}(mark) && self::Strength::stronger(this.{self::Constraint::strength}, this.{self::BinaryConstraint::v2}.{self::Variable::walkStrength}) ?{core::int} self::FORWARD : self::NONE;
     }
     if(this.{self::BinaryConstraint::v2}.{self::Variable::mark}.{core::num::==}(mark)) {
-      this.{self::BinaryConstraint::direction} = !this.{self::BinaryConstraint::v1}.{self::Variable::mark}.{core::num::==}(mark) && self::Strength::stronger(this.{self::Constraint::strength}, this.{self::BinaryConstraint::v1}.{self::Variable::walkStrength}) ? self::BACKWARD : self::NONE;
+      this.{self::BinaryConstraint::direction} = !this.{self::BinaryConstraint::v1}.{self::Variable::mark}.{core::num::==}(mark) && self::Strength::stronger(this.{self::Constraint::strength}, this.{self::BinaryConstraint::v1}.{self::Variable::walkStrength}) ?{core::int} self::BACKWARD : self::NONE;
     }
     if(self::Strength::weaker(this.{self::BinaryConstraint::v1}.{self::Variable::walkStrength}, this.{self::BinaryConstraint::v2}.{self::Variable::walkStrength})) {
-      this.{self::BinaryConstraint::direction} = self::Strength::stronger(this.{self::Constraint::strength}, this.{self::BinaryConstraint::v1}.{self::Variable::walkStrength}) ? self::BACKWARD : self::NONE;
+      this.{self::BinaryConstraint::direction} = self::Strength::stronger(this.{self::Constraint::strength}, this.{self::BinaryConstraint::v1}.{self::Variable::walkStrength}) ?{core::int} self::BACKWARD : self::NONE;
     }
     else {
-      this.{self::BinaryConstraint::direction} = self::Strength::stronger(this.{self::Constraint::strength}, this.{self::BinaryConstraint::v2}.{self::Variable::walkStrength}) ? self::FORWARD : self::BACKWARD;
+      this.{self::BinaryConstraint::direction} = self::Strength::stronger(this.{self::Constraint::strength}, this.{self::BinaryConstraint::v2}.{self::Variable::walkStrength}) ?{core::int} self::FORWARD : self::BACKWARD;
     }
   }
   method addToGraph() → void {
@@ -159,9 +161,9 @@
     this.{self::BinaryConstraint::input}().{self::Variable::mark} = mark;
   }
   method input() → self::Variable
-    return this.{self::BinaryConstraint::direction}.{core::num::==}(self::FORWARD) ? this.{self::BinaryConstraint::v1} : this.{self::BinaryConstraint::v2};
+    return this.{self::BinaryConstraint::direction}.{core::num::==}(self::FORWARD) ?{self::Variable} this.{self::BinaryConstraint::v1} : this.{self::BinaryConstraint::v2};
   method output() → self::Variable
-    return this.{self::BinaryConstraint::direction}.{core::num::==}(self::FORWARD) ? this.{self::BinaryConstraint::v2} : this.{self::BinaryConstraint::v1};
+    return this.{self::BinaryConstraint::direction}.{core::num::==}(self::FORWARD) ?{self::Variable} this.{self::BinaryConstraint::v2} : this.{self::BinaryConstraint::v1};
   method recalculate() → void {
     self::Variable ihn = this.{self::BinaryConstraint::input}();
     self::Variable out = this.{self::BinaryConstraint::output}();
@@ -188,23 +190,23 @@
 class ScaleConstraint extends self::BinaryConstraint {
   final field self::Variable scale;
   final field self::Variable offset;
-  constructor •(self::Variable src, self::Variable scale, self::Variable offset, self::Variable dest, self::Strength strength) → void
+  constructor •(self::Variable src, self::Variable scale, self::Variable offset, self::Variable dest, self::Strength strength) → self::ScaleConstraint
     : self::ScaleConstraint::scale = scale, self::ScaleConstraint::offset = offset, super self::BinaryConstraint::•(src, dest, strength)
     ;
   method addToGraph() → void {
-    this.{=self::BinaryConstraint::addToGraph}();
+    super.{self::BinaryConstraint::addToGraph}();
     this.{self::ScaleConstraint::scale}.{self::Variable::addConstraint}(this);
     this.{self::ScaleConstraint::offset}.{self::Variable::addConstraint}(this);
   }
   method removeFromGraph() → void {
-    this.{=self::BinaryConstraint::removeFromGraph}();
+    super.{self::BinaryConstraint::removeFromGraph}();
     if(!this.{self::ScaleConstraint::scale}.{core::Object::==}(null))
       this.{self::ScaleConstraint::scale}.{self::Variable::removeConstraint}(this);
     if(!this.{self::ScaleConstraint::offset}.{core::Object::==}(null))
       this.{self::ScaleConstraint::offset}.{self::Variable::removeConstraint}(this);
   }
   method markInputs(core::int mark) → void {
-    this.{=self::BinaryConstraint::markInputs}(mark);
+    super.{self::BinaryConstraint::markInputs}(mark);
     this.{self::ScaleConstraint::scale}.{self::Variable::mark} = this.{self::ScaleConstraint::offset}.{self::Variable::mark} = mark;
   }
   method execute() → void {
@@ -225,7 +227,7 @@
   }
 }
 class EqualityConstraint extends self::BinaryConstraint {
-  constructor •(self::Variable v1, self::Variable v2, self::Strength strength) → void
+  constructor •(self::Variable v1, self::Variable v2, self::Strength strength) → self::EqualityConstraint
     : super self::BinaryConstraint::•(v1, v2, strength)
     ;
   method execute() → void {
@@ -240,11 +242,11 @@
   field core::bool stay = true;
   field core::int value;
   final field core::String name;
-  constructor •(core::String name, core::int value) → void
+  constructor •(core::String name, core::int value) → self::Variable
     : self::Variable::name = name, self::Variable::value = value, super core::Object::•()
     ;
   method addConstraint(self::Constraint c) → void {
-    this.{self::Variable::constraints}.{core::List::add$cc}(c);
+    this.{self::Variable::constraints}.{core::List::add}(c);
   }
   method removeConstraint(self::Constraint c) → void {
     this.{self::Variable::constraints}.{core::List::remove}(c);
@@ -254,7 +256,7 @@
 }
 class Planner extends core::Object {
   field core::int currentMark = 0;
-  constructor •() → void
+  synthetic constructor •() → self::Planner
     : super core::Object::•()
     ;
   method incrementalAdd(self::Constraint c) → void {
@@ -299,7 +301,7 @@
     for (core::int i = 0; i.{core::num::<}(constraints.{core::List::length}); i = i.{core::num::+}(1)) {
       self::Constraint c = constraints.{core::List::[]}(i);
       if(c.{self::Constraint::isInput}() && c.{self::Constraint::isSatisfied}())
-        sources.{core::List::add$cc}(c);
+        sources.{core::List::add}(c);
     }
     return this.{self::Planner::makePlan}(sources);
   }
@@ -327,7 +329,7 @@
       for (core::int i = 0; i.{core::num::<}(v.{self::Variable::constraints}.{core::List::length}); i = i.{core::num::+}(1)) {
         self::Constraint c = v.{self::Variable::constraints}.{core::List::[]}(i);
         if(!c.{self::Constraint::isSatisfied}())
-          unsatisfied.{core::List::add$cc}(c);
+          unsatisfied.{core::List::add}(c);
       }
       self::Constraint determining = v.{self::Variable::determinedBy};
       for (core::int i = 0; i.{core::num::<}(v.{self::Variable::constraints}.{core::List::length}); i = i.{core::num::+}(1)) {
@@ -345,18 +347,20 @@
     for (core::int i = 0; i.{core::num::<}(v.{self::Variable::constraints}.{core::List::length}); i = i.{core::num::+}(1)) {
       self::Constraint c = v.{self::Variable::constraints}.{core::List::[]}(i);
       if(!c.{core::Object::==}(determining) && c.{self::Constraint::isSatisfied}())
-        coll.{core::List::add$cc}(c);
+        coll.{core::List::add}(c);
     }
   }
 }
 class Plan extends core::Object {
   field core::List<self::Constraint> list = <self::Constraint>[];
-  constructor •() → void
+  synthetic constructor •() → self::Plan
     : super core::Object::•()
     ;
   method addConstraint(self::Constraint c) → void {
-    this.{self::Plan::list}.{core::List::add$cc}(c);
+    this.{self::Plan::list}.{core::List::add}(c);
   }
+  method size() → core::int
+    return this.{self::Plan::list}.{core::List::length};
   method execute() → void {
     for (core::int i = 0; i.{core::num::<}(this.{self::Plan::list}.{core::List::length}); i = i.{core::num::+}(1)) {
       this.{self::Plan::list}.{core::List::[]}(i).{self::Constraint::execute}();
@@ -373,7 +377,7 @@
 static const field core::int NONE = 1;
 static const field core::int FORWARD = 2;
 static const field core::int BACKWARD = 0;
-static field self::Planner planner = null;
+static field self::Planner planner;
 static method main() → dynamic {
   new self::DeltaBlue::•().{self::DeltaBlue::run}();
 }
diff --git a/pkg/front_end/testcases/DeltaBlue.dart.strong.transformed.expect b/pkg/front_end/testcases/DeltaBlue.dart.strong.transformed.expect
new file mode 100644
index 0000000..78e2440
--- /dev/null
+++ b/pkg/front_end/testcases/DeltaBlue.dart.strong.transformed.expect
@@ -0,0 +1,450 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class DeltaBlue extends core::Object {
+  synthetic constructor •() → self::DeltaBlue
+    : super core::Object::•()
+    ;
+  method run() → void {
+    self::chainTest(100);
+    self::projectionTest(100);
+  }
+}
+class Strength extends core::Object {
+  final field core::int value;
+  final field core::String name;
+  const constructor •(core::int value, core::String name) → self::Strength
+    : self::Strength::value = value, self::Strength::name = name, super core::Object::•()
+    ;
+  method nextWeaker() → self::Strength
+    return const <self::Strength>[self::STRONG_PREFERRED, self::PREFERRED, self::STRONG_DEFAULT, self::NORMAL, self::WEAK_DEFAULT, self::WEAKEST].{core::List::[]}(this.{self::Strength::value});
+  static method stronger(self::Strength s1, self::Strength s2) → core::bool {
+    return s1.{self::Strength::value}.{core::num::<}(s2.{self::Strength::value});
+  }
+  static method weaker(self::Strength s1, self::Strength s2) → core::bool {
+    return s1.{self::Strength::value}.{core::num::>}(s2.{self::Strength::value});
+  }
+  static method weakest(self::Strength s1, self::Strength s2) → self::Strength {
+    return self::Strength::weaker(s1, s2) ?{self::Strength} s1 : s2;
+  }
+  static method strongest(self::Strength s1, self::Strength s2) → self::Strength {
+    return self::Strength::stronger(s1, s2) ?{self::Strength} s1 : s2;
+  }
+}
+abstract class Constraint extends core::Object {
+  final field self::Strength strength;
+  const constructor •(self::Strength strength) → self::Constraint
+    : self::Constraint::strength = strength, super core::Object::•()
+    ;
+  abstract method isSatisfied() → core::bool;
+  abstract method markUnsatisfied() → void;
+  abstract method addToGraph() → void;
+  abstract method removeFromGraph() → void;
+  abstract method chooseMethod(core::int mark) → void;
+  abstract method markInputs(core::int mark) → void;
+  abstract method inputsKnown(core::int mark) → core::bool;
+  abstract method output() → self::Variable;
+  abstract method execute() → void;
+  abstract method recalculate() → void;
+  method addConstraint() → void {
+    this.{self::Constraint::addToGraph}();
+    self::planner.{self::Planner::incrementalAdd}(this);
+  }
+  method satisfy(dynamic mark) → self::Constraint {
+    this.{self::Constraint::chooseMethod}(mark as{TypeError} core::int);
+    if(!this.{self::Constraint::isSatisfied}()) {
+      if(this.{self::Constraint::strength}.{core::Object::==}(self::REQUIRED)) {
+        core::print("Could not satisfy a required constraint!");
+      }
+      return null;
+    }
+    this.{self::Constraint::markInputs}(mark as{TypeError} core::int);
+    self::Variable out = this.{self::Constraint::output}();
+    self::Constraint overridden = out.{self::Variable::determinedBy};
+    if(!overridden.{core::Object::==}(null))
+      overridden.{self::Constraint::markUnsatisfied}();
+    out.{self::Variable::determinedBy} = this;
+    if(!self::planner.{self::Planner::addPropagate}(this, mark as{TypeError} core::int))
+      core::print("Cycle encountered");
+    out.{self::Variable::mark} = mark as{TypeError} core::int;
+    return overridden;
+  }
+  method destroyConstraint() → void {
+    if(this.{self::Constraint::isSatisfied}())
+      self::planner.{self::Planner::incrementalRemove}(this);
+    this.{self::Constraint::removeFromGraph}();
+  }
+  method isInput() → core::bool
+    return false;
+}
+abstract class UnaryConstraint extends self::Constraint {
+  final field self::Variable myOutput;
+  field core::bool satisfied = false;
+  constructor •(self::Variable myOutput, self::Strength strength) → self::UnaryConstraint
+    : self::UnaryConstraint::myOutput = myOutput, super self::Constraint::•(strength) {
+    this.{self::Constraint::addConstraint}();
+  }
+  method addToGraph() → void {
+    this.{self::UnaryConstraint::myOutput}.{self::Variable::addConstraint}(this);
+    this.{self::UnaryConstraint::satisfied} = false;
+  }
+  method chooseMethod(core::int mark) → void {
+    this.{self::UnaryConstraint::satisfied} = !this.{self::UnaryConstraint::myOutput}.{self::Variable::mark}.{core::num::==}(mark) && self::Strength::stronger(this.{self::Constraint::strength}, this.{self::UnaryConstraint::myOutput}.{self::Variable::walkStrength});
+  }
+  method isSatisfied() → core::bool
+    return this.{self::UnaryConstraint::satisfied};
+  method markInputs(core::int mark) → void {}
+  method output() → self::Variable
+    return this.{self::UnaryConstraint::myOutput};
+  method recalculate() → void {
+    this.{self::UnaryConstraint::myOutput}.{self::Variable::walkStrength} = this.{self::Constraint::strength};
+    this.{self::UnaryConstraint::myOutput}.{self::Variable::stay} = !this.{self::Constraint::isInput}();
+    if(this.{self::UnaryConstraint::myOutput}.{self::Variable::stay})
+      this.{self::Constraint::execute}();
+  }
+  method markUnsatisfied() → void {
+    this.{self::UnaryConstraint::satisfied} = false;
+  }
+  method inputsKnown(core::int mark) → core::bool
+    return true;
+  method removeFromGraph() → void {
+    if(!this.{self::UnaryConstraint::myOutput}.{core::Object::==}(null))
+      this.{self::UnaryConstraint::myOutput}.{self::Variable::removeConstraint}(this);
+    this.{self::UnaryConstraint::satisfied} = false;
+  }
+}
+class StayConstraint extends self::UnaryConstraint {
+  constructor •(self::Variable v, self::Strength str) → self::StayConstraint
+    : super self::UnaryConstraint::•(v, str)
+    ;
+  method execute() → void {}
+}
+class EditConstraint extends self::UnaryConstraint {
+  constructor •(self::Variable v, self::Strength str) → self::EditConstraint
+    : super self::UnaryConstraint::•(v, str)
+    ;
+  method isInput() → core::bool
+    return true;
+  method execute() → void {}
+}
+abstract class BinaryConstraint extends self::Constraint {
+  field self::Variable v1;
+  field self::Variable v2;
+  field core::int direction = self::NONE;
+  constructor •(self::Variable v1, self::Variable v2, self::Strength strength) → self::BinaryConstraint
+    : self::BinaryConstraint::v1 = v1, self::BinaryConstraint::v2 = v2, super self::Constraint::•(strength) {
+    this.{self::Constraint::addConstraint}();
+  }
+  method chooseMethod(core::int mark) → void {
+    if(this.{self::BinaryConstraint::v1}.{self::Variable::mark}.{core::num::==}(mark)) {
+      this.{self::BinaryConstraint::direction} = !this.{self::BinaryConstraint::v2}.{self::Variable::mark}.{core::num::==}(mark) && self::Strength::stronger(this.{self::Constraint::strength}, this.{self::BinaryConstraint::v2}.{self::Variable::walkStrength}) ?{core::int} self::FORWARD : self::NONE;
+    }
+    if(this.{self::BinaryConstraint::v2}.{self::Variable::mark}.{core::num::==}(mark)) {
+      this.{self::BinaryConstraint::direction} = !this.{self::BinaryConstraint::v1}.{self::Variable::mark}.{core::num::==}(mark) && self::Strength::stronger(this.{self::Constraint::strength}, this.{self::BinaryConstraint::v1}.{self::Variable::walkStrength}) ?{core::int} self::BACKWARD : self::NONE;
+    }
+    if(self::Strength::weaker(this.{self::BinaryConstraint::v1}.{self::Variable::walkStrength}, this.{self::BinaryConstraint::v2}.{self::Variable::walkStrength})) {
+      this.{self::BinaryConstraint::direction} = self::Strength::stronger(this.{self::Constraint::strength}, this.{self::BinaryConstraint::v1}.{self::Variable::walkStrength}) ?{core::int} self::BACKWARD : self::NONE;
+    }
+    else {
+      this.{self::BinaryConstraint::direction} = self::Strength::stronger(this.{self::Constraint::strength}, this.{self::BinaryConstraint::v2}.{self::Variable::walkStrength}) ?{core::int} self::FORWARD : self::BACKWARD;
+    }
+  }
+  method addToGraph() → void {
+    this.{self::BinaryConstraint::v1}.{self::Variable::addConstraint}(this);
+    this.{self::BinaryConstraint::v2}.{self::Variable::addConstraint}(this);
+    this.{self::BinaryConstraint::direction} = self::NONE;
+  }
+  method isSatisfied() → core::bool
+    return !this.{self::BinaryConstraint::direction}.{core::num::==}(self::NONE);
+  method markInputs(core::int mark) → void {
+    this.{self::BinaryConstraint::input}().{self::Variable::mark} = mark;
+  }
+  method input() → self::Variable
+    return this.{self::BinaryConstraint::direction}.{core::num::==}(self::FORWARD) ?{self::Variable} this.{self::BinaryConstraint::v1} : this.{self::BinaryConstraint::v2};
+  method output() → self::Variable
+    return this.{self::BinaryConstraint::direction}.{core::num::==}(self::FORWARD) ?{self::Variable} this.{self::BinaryConstraint::v2} : this.{self::BinaryConstraint::v1};
+  method recalculate() → void {
+    self::Variable ihn = this.{self::BinaryConstraint::input}();
+    self::Variable out = this.{self::BinaryConstraint::output}();
+    out.{self::Variable::walkStrength} = self::Strength::weakest(this.{self::Constraint::strength}, ihn.{self::Variable::walkStrength});
+    out.{self::Variable::stay} = ihn.{self::Variable::stay};
+    if(out.{self::Variable::stay})
+      this.{self::Constraint::execute}();
+  }
+  method markUnsatisfied() → void {
+    this.{self::BinaryConstraint::direction} = self::NONE;
+  }
+  method inputsKnown(core::int mark) → core::bool {
+    self::Variable i = this.{self::BinaryConstraint::input}();
+    return i.{self::Variable::mark}.{core::num::==}(mark) || i.{self::Variable::stay} || i.{self::Variable::determinedBy}.{core::Object::==}(null);
+  }
+  method removeFromGraph() → void {
+    if(!this.{self::BinaryConstraint::v1}.{core::Object::==}(null))
+      this.{self::BinaryConstraint::v1}.{self::Variable::removeConstraint}(this);
+    if(!this.{self::BinaryConstraint::v2}.{core::Object::==}(null))
+      this.{self::BinaryConstraint::v2}.{self::Variable::removeConstraint}(this);
+    this.{self::BinaryConstraint::direction} = self::NONE;
+  }
+}
+class ScaleConstraint extends self::BinaryConstraint {
+  final field self::Variable scale;
+  final field self::Variable offset;
+  constructor •(self::Variable src, self::Variable scale, self::Variable offset, self::Variable dest, self::Strength strength) → self::ScaleConstraint
+    : self::ScaleConstraint::scale = scale, self::ScaleConstraint::offset = offset, super self::BinaryConstraint::•(src, dest, strength)
+    ;
+  method addToGraph() → void {
+    super.{self::BinaryConstraint::addToGraph}();
+    this.{self::ScaleConstraint::scale}.{self::Variable::addConstraint}(this);
+    this.{self::ScaleConstraint::offset}.{self::Variable::addConstraint}(this);
+  }
+  method removeFromGraph() → void {
+    super.{self::BinaryConstraint::removeFromGraph}();
+    if(!this.{self::ScaleConstraint::scale}.{core::Object::==}(null))
+      this.{self::ScaleConstraint::scale}.{self::Variable::removeConstraint}(this);
+    if(!this.{self::ScaleConstraint::offset}.{core::Object::==}(null))
+      this.{self::ScaleConstraint::offset}.{self::Variable::removeConstraint}(this);
+  }
+  method markInputs(core::int mark) → void {
+    super.{self::BinaryConstraint::markInputs}(mark);
+    this.{self::ScaleConstraint::scale}.{self::Variable::mark} = this.{self::ScaleConstraint::offset}.{self::Variable::mark} = mark;
+  }
+  method execute() → void {
+    if(this.{self::BinaryConstraint::direction}.{core::num::==}(self::FORWARD)) {
+      this.{self::BinaryConstraint::v2}.{self::Variable::value} = this.{self::BinaryConstraint::v1}.{self::Variable::value}.{core::num::*}(this.{self::ScaleConstraint::scale}.{self::Variable::value}).{core::num::+}(this.{self::ScaleConstraint::offset}.{self::Variable::value});
+    }
+    else {
+      this.{self::BinaryConstraint::v1}.{self::Variable::value} = this.{self::BinaryConstraint::v2}.{self::Variable::value}.{core::num::-}(this.{self::ScaleConstraint::offset}.{self::Variable::value}).{core::num::~/}(this.{self::ScaleConstraint::scale}.{self::Variable::value});
+    }
+  }
+  method recalculate() → void {
+    self::Variable ihn = this.{self::BinaryConstraint::input}();
+    self::Variable out = this.{self::BinaryConstraint::output}();
+    out.{self::Variable::walkStrength} = self::Strength::weakest(this.{self::Constraint::strength}, ihn.{self::Variable::walkStrength});
+    out.{self::Variable::stay} = ihn.{self::Variable::stay} && this.{self::ScaleConstraint::scale}.{self::Variable::stay} && this.{self::ScaleConstraint::offset}.{self::Variable::stay};
+    if(out.{self::Variable::stay})
+      this.{self::ScaleConstraint::execute}();
+  }
+}
+class EqualityConstraint extends self::BinaryConstraint {
+  constructor •(self::Variable v1, self::Variable v2, self::Strength strength) → self::EqualityConstraint
+    : super self::BinaryConstraint::•(v1, v2, strength)
+    ;
+  method execute() → void {
+    this.{self::BinaryConstraint::output}().{self::Variable::value} = this.{self::BinaryConstraint::input}().{self::Variable::value};
+  }
+}
+class Variable extends core::Object {
+  field core::List<self::Constraint> constraints = <self::Constraint>[];
+  field self::Constraint determinedBy = null;
+  field core::int mark = 0;
+  field self::Strength walkStrength = self::WEAKEST;
+  field core::bool stay = true;
+  field core::int value;
+  final field core::String name;
+  constructor •(core::String name, core::int value) → self::Variable
+    : self::Variable::name = name, self::Variable::value = value, super core::Object::•()
+    ;
+  method addConstraint(self::Constraint c) → void {
+    this.{self::Variable::constraints}.{core::List::add}(c);
+  }
+  method removeConstraint(self::Constraint c) → void {
+    this.{self::Variable::constraints}.{core::List::remove}(c);
+    if(this.{self::Variable::determinedBy}.{core::Object::==}(c))
+      this.{self::Variable::determinedBy} = null;
+  }
+}
+class Planner extends core::Object {
+  field core::int currentMark = 0;
+  synthetic constructor •() → self::Planner
+    : super core::Object::•()
+    ;
+  method incrementalAdd(self::Constraint c) → void {
+    core::int mark = this.{self::Planner::newMark}();
+    for (self::Constraint overridden = c.{self::Constraint::satisfy}(mark); !overridden.{core::Object::==}(null); overridden = overridden.{self::Constraint::satisfy}(mark))
+      ;
+  }
+  method incrementalRemove(self::Constraint c) → void {
+    self::Variable out = c.{self::Constraint::output}();
+    c.{self::Constraint::markUnsatisfied}();
+    c.{self::Constraint::removeFromGraph}();
+    core::List<self::Constraint> unsatisfied = this.{self::Planner::removePropagateFrom}(out);
+    self::Strength strength = self::REQUIRED;
+    do {
+      for (core::int i = 0; i.{core::num::<}(unsatisfied.{core::List::length}); i = i.{core::num::+}(1)) {
+        self::Constraint u = unsatisfied.{core::List::[]}(i);
+        if(u.{self::Constraint::strength}.{core::Object::==}(strength))
+          this.{self::Planner::incrementalAdd}(u);
+      }
+      strength = strength.{self::Strength::nextWeaker}();
+    }
+    while (!strength.{core::Object::==}(self::WEAKEST))
+  }
+  method newMark() → core::int
+    return this.{self::Planner::currentMark} = this.{self::Planner::currentMark}.{core::num::+}(1);
+  method makePlan(core::List<self::Constraint> sources) → self::Plan {
+    core::int mark = this.{self::Planner::newMark}();
+    self::Plan plan = new self::Plan::•();
+    core::List<self::Constraint> todo = sources;
+    while (todo.{core::List::length}.{core::num::>}(0)) {
+      self::Constraint c = todo.{core::List::removeLast}();
+      if(!c.{self::Constraint::output}().{self::Variable::mark}.{core::num::==}(mark) && c.{self::Constraint::inputsKnown}(mark)) {
+        plan.{self::Plan::addConstraint}(c);
+        c.{self::Constraint::output}().{self::Variable::mark} = mark;
+        this.{self::Planner::addConstraintsConsumingTo}(c.{self::Constraint::output}(), todo);
+      }
+    }
+    return plan;
+  }
+  method extractPlanFromConstraints(core::List<self::Constraint> constraints) → self::Plan {
+    core::List<self::Constraint> sources = <self::Constraint>[];
+    for (core::int i = 0; i.{core::num::<}(constraints.{core::List::length}); i = i.{core::num::+}(1)) {
+      self::Constraint c = constraints.{core::List::[]}(i);
+      if(c.{self::Constraint::isInput}() && c.{self::Constraint::isSatisfied}())
+        sources.{core::List::add}(c);
+    }
+    return this.{self::Planner::makePlan}(sources);
+  }
+  method addPropagate(self::Constraint c, core::int mark) → core::bool {
+    core::List<self::Constraint> todo = <self::Constraint>[c];
+    while (todo.{core::List::length}.{core::num::>}(0)) {
+      self::Constraint d = todo.{core::List::removeLast}();
+      if(d.{self::Constraint::output}().{self::Variable::mark}.{core::num::==}(mark)) {
+        this.{self::Planner::incrementalRemove}(c);
+        return false;
+      }
+      d.{self::Constraint::recalculate}();
+      this.{self::Planner::addConstraintsConsumingTo}(d.{self::Constraint::output}(), todo);
+    }
+    return true;
+  }
+  method removePropagateFrom(self::Variable out) → core::List<self::Constraint> {
+    out.{self::Variable::determinedBy} = null;
+    out.{self::Variable::walkStrength} = self::WEAKEST;
+    out.{self::Variable::stay} = true;
+    core::List<self::Constraint> unsatisfied = <self::Constraint>[];
+    core::List<self::Variable> todo = <self::Variable>[out];
+    while (todo.{core::List::length}.{core::num::>}(0)) {
+      self::Variable v = todo.{core::List::removeLast}();
+      for (core::int i = 0; i.{core::num::<}(v.{self::Variable::constraints}.{core::List::length}); i = i.{core::num::+}(1)) {
+        self::Constraint c = v.{self::Variable::constraints}.{core::List::[]}(i);
+        if(!c.{self::Constraint::isSatisfied}())
+          unsatisfied.{core::List::add}(c);
+      }
+      self::Constraint determining = v.{self::Variable::determinedBy};
+      for (core::int i = 0; i.{core::num::<}(v.{self::Variable::constraints}.{core::List::length}); i = i.{core::num::+}(1)) {
+        self::Constraint next = v.{self::Variable::constraints}.{core::List::[]}(i);
+        if(!next.{core::Object::==}(determining) && next.{self::Constraint::isSatisfied}()) {
+          next.{self::Constraint::recalculate}();
+          todo.{core::List::add}(next.{self::Constraint::output}());
+        }
+      }
+    }
+    return unsatisfied;
+  }
+  method addConstraintsConsumingTo(self::Variable v, core::List<self::Constraint> coll) → void {
+    self::Constraint determining = v.{self::Variable::determinedBy};
+    for (core::int i = 0; i.{core::num::<}(v.{self::Variable::constraints}.{core::List::length}); i = i.{core::num::+}(1)) {
+      self::Constraint c = v.{self::Variable::constraints}.{core::List::[]}(i);
+      if(!c.{core::Object::==}(determining) && c.{self::Constraint::isSatisfied}())
+        coll.{core::List::add}(c);
+    }
+  }
+}
+class Plan extends core::Object {
+  field core::List<self::Constraint> list = <self::Constraint>[];
+  synthetic constructor •() → self::Plan
+    : super core::Object::•()
+    ;
+  method addConstraint(self::Constraint c) → void {
+    this.{self::Plan::list}.{core::List::add}(c);
+  }
+  method size() → core::int
+    return this.{self::Plan::list}.{core::List::length};
+  method execute() → void {
+    for (core::int i = 0; i.{core::num::<}(this.{self::Plan::list}.{core::List::length}); i = i.{core::num::+}(1)) {
+      this.{self::Plan::list}.{core::List::[]}(i).{self::Constraint::execute}();
+    }
+  }
+}
+static const field self::Strength REQUIRED = const self::Strength::•(0, "required");
+static const field self::Strength STRONG_PREFERRED = const self::Strength::•(1, "strongPreferred");
+static const field self::Strength PREFERRED = const self::Strength::•(2, "preferred");
+static const field self::Strength STRONG_DEFAULT = const self::Strength::•(3, "strongDefault");
+static const field self::Strength NORMAL = const self::Strength::•(4, "normal");
+static const field self::Strength WEAK_DEFAULT = const self::Strength::•(5, "weakDefault");
+static const field self::Strength WEAKEST = const self::Strength::•(6, "weakest");
+static const field core::int NONE = 1;
+static const field core::int FORWARD = 2;
+static const field core::int BACKWARD = 0;
+static field self::Planner planner;
+static method main() → dynamic {
+  new self::DeltaBlue::•().{self::DeltaBlue::run}();
+}
+static method chainTest(core::int n) → void {
+  self::planner = new self::Planner::•();
+  self::Variable prev = null;
+  self::Variable first = null;
+  self::Variable last = null;
+  for (core::int i = 0; i.{core::num::<=}(n); i = i.{core::num::+}(1)) {
+    self::Variable v = new self::Variable::•("v${i}", 0);
+    if(!prev.{core::Object::==}(null))
+      new self::EqualityConstraint::•(prev, v, self::REQUIRED);
+    if(i.{core::num::==}(0))
+      first = v;
+    if(i.{core::num::==}(n))
+      last = v;
+    prev = v;
+  }
+  new self::StayConstraint::•(last, self::STRONG_DEFAULT);
+  self::EditConstraint edit = new self::EditConstraint::•(first, self::PREFERRED);
+  self::Plan plan = self::planner.{self::Planner::extractPlanFromConstraints}(<self::Constraint>[edit]);
+  for (core::int i = 0; i.{core::num::<}(100); i = i.{core::num::+}(1)) {
+    first.{self::Variable::value} = i;
+    plan.{self::Plan::execute}();
+    if(!last.{self::Variable::value}.{core::num::==}(i)) {
+      core::print("Chain test failed:");
+      core::print("Expected last value to be ${i} but it was ${last.{self::Variable::value}}.");
+    }
+  }
+}
+static method projectionTest(core::int n) → void {
+  self::planner = new self::Planner::•();
+  self::Variable scale = new self::Variable::•("scale", 10);
+  self::Variable offset = new self::Variable::•("offset", 1000);
+  self::Variable src = null;
+  self::Variable dst = null;
+  core::List<self::Variable> dests = <self::Variable>[];
+  for (core::int i = 0; i.{core::num::<}(n); i = i.{core::num::+}(1)) {
+    src = new self::Variable::•("src", i);
+    dst = new self::Variable::•("dst", i);
+    dests.{core::List::add}(dst);
+    new self::StayConstraint::•(src, self::NORMAL);
+    new self::ScaleConstraint::•(src, scale, offset, dst, self::REQUIRED);
+  }
+  self::change(src, 17);
+  if(!dst.{self::Variable::value}.{core::num::==}(1170))
+    core::print("Projection 1 failed");
+  self::change(dst, 1050);
+  if(!src.{self::Variable::value}.{core::num::==}(5))
+    core::print("Projection 2 failed");
+  self::change(scale, 5);
+  for (core::int i = 0; i.{core::num::<}(n.{core::num::-}(1)); i = i.{core::num::+}(1)) {
+    if(!dests.{core::List::[]}(i).{self::Variable::value}.{core::num::==}(i.{core::num::*}(5).{core::num::+}(1000)))
+      core::print("Projection 3 failed");
+  }
+  self::change(offset, 2000);
+  for (core::int i = 0; i.{core::num::<}(n.{core::num::-}(1)); i = i.{core::num::+}(1)) {
+    if(!dests.{core::List::[]}(i).{self::Variable::value}.{core::num::==}(i.{core::num::*}(5).{core::num::+}(2000)))
+      core::print("Projection 4 failed");
+  }
+}
+static method change(self::Variable v, core::int newValue) → void {
+  self::EditConstraint edit = new self::EditConstraint::•(v, self::PREFERRED);
+  self::Plan plan = self::planner.{self::Planner::extractPlanFromConstraints}(<self::EditConstraint>[edit]);
+  for (core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1)) {
+    v.{self::Variable::value} = newValue;
+    plan.{self::Plan::execute}();
+  }
+  edit.{self::Constraint::destroyConstraint}();
+}
diff --git a/pkg/front_end/testcases/DeltaBlue.dart.type_promotion.expect b/pkg/front_end/testcases/DeltaBlue.dart.type_promotion.expect
new file mode 100644
index 0000000..d99f933
--- /dev/null
+++ b/pkg/front_end/testcases/DeltaBlue.dart.type_promotion.expect
@@ -0,0 +1,57 @@
+pkg/front_end/testcases/DeltaBlue.dart:458:20: Context: Write to overridden@13138
+        overridden = overridden.satisfy(mark));
+                   ^
+pkg/front_end/testcases/DeltaBlue.dart:479:48: Context: Write to i@14064
+      for (int i = 0; i < unsatisfied.length; i++) {
+                                               ^^
+pkg/front_end/testcases/DeltaBlue.dart:483:16: Context: Write to strength@14019
+      strength = strength.nextWeaker();
+               ^
+pkg/front_end/testcases/DeltaBlue.dart:530:46: Context: Write to i@16107
+    for (int i = 0; i < constraints.length; i++) {
+                                             ^^
+pkg/front_end/testcases/DeltaBlue.dart:578:50: Context: Write to i@17907
+      for (int i = 0; i < v.constraints.length; i++) {
+                                                 ^^
+pkg/front_end/testcases/DeltaBlue.dart:583:50: Context: Write to i@17907
+      for (int i = 0; i < v.constraints.length; i++) {
+                                                 ^^
+pkg/front_end/testcases/DeltaBlue.dart:596:48: Context: Write to i@18495
+    for (int i = 0; i < v.constraints.length; i++) {
+                                               ^^
+pkg/front_end/testcases/DeltaBlue.dart:618:39: Context: Write to i@19004
+    for (int i = 0; i < list.length; i++) {
+                                      ^^
+pkg/front_end/testcases/DeltaBlue.dart:641:28: Context: Write to i@19938
+  for (int i = 0; i <= n; i++) {
+                           ^^
+pkg/front_end/testcases/DeltaBlue.dart:644:23: Context: Write to first@19856
+    if (i == 0) first = v;
+                      ^
+pkg/front_end/testcases/DeltaBlue.dart:645:22: Context: Write to last@19870
+    if (i == n) last = v;
+                     ^
+pkg/front_end/testcases/DeltaBlue.dart:646:10: Context: Write to prev@19843
+    prev = v;
+         ^
+pkg/front_end/testcases/DeltaBlue.dart:651:29: Context: Write to i@19938
+  for (int i = 0; i < 100; i++) {
+                            ^^
+pkg/front_end/testcases/DeltaBlue.dart:674:27: Context: Write to i@21029
+  for (int i = 0; i < n; i++) {
+                          ^^
+pkg/front_end/testcases/DeltaBlue.dart:675:9: Context: Write to src@20954
+    src = new Variable("src", i);
+        ^
+pkg/front_end/testcases/DeltaBlue.dart:676:9: Context: Write to dst@20966
+    dst = new Variable("dst", i);
+        ^
+pkg/front_end/testcases/DeltaBlue.dart:686:31: Context: Write to i@21029
+  for (int i = 0; i < n - 1; i++) {
+                              ^^
+pkg/front_end/testcases/DeltaBlue.dart:690:31: Context: Write to i@21029
+  for (int i = 0; i < n - 1; i++) {
+                              ^^
+pkg/front_end/testcases/DeltaBlue.dart:698:28: Context: Write to i@21836
+  for (int i = 0; i < 10; i++) {
+                           ^^
diff --git a/pkg/front_end/testcases/README.md b/pkg/front_end/testcases/README.md
index a7d4fb1..143a0df 100644
--- a/pkg/front_end/testcases/README.md
+++ b/pkg/front_end/testcases/README.md
@@ -13,8 +13,8 @@
 
 ## Dart 1.0 Compilation
 
-* Status file: [compile.status](compile.status)
-* Standalone test: [pkg/front_end/test/fasta/compile_test.dart](../test/fasta/compile_test.dart)
+* Status file: [legacy.status](legacy.status)
+* Standalone test: [pkg/front_end/test/fasta/legacy_test.dart](../test/fasta/legacy_test.dart)
 * Expectation prefix: `.direct.expect`
 * How to update expectations:
 
diff --git a/pkg/front_end/testcases/accessors.dart.direct.expect b/pkg/front_end/testcases/accessors.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/accessors.dart.direct.expect
rename to pkg/front_end/testcases/accessors.dart.legacy.expect
diff --git a/pkg/front_end/testcases/accessors.dart.direct.transformed.expect b/pkg/front_end/testcases/accessors.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/accessors.dart.direct.transformed.expect
rename to pkg/front_end/testcases/accessors.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/accessors.dart.strong.expect b/pkg/front_end/testcases/accessors.dart.strong.expect
new file mode 100644
index 0000000..d4210c6
--- /dev/null
+++ b/pkg/front_end/testcases/accessors.dart.strong.expect
@@ -0,0 +1,93 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/accessors.dart:16:13: Error: Getter not found: 'onlySetter'.
+//       print(onlySetter);
+//             ^^^^^^^^^^
+//
+// pkg/front_end/testcases/accessors.dart:16:13: Error: The getter 'onlySetter' isn't defined for the class '#lib1::C'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'onlySetter'.
+//       print(onlySetter);
+//             ^^^^^^^^^^
+//
+// pkg/front_end/testcases/accessors.dart:25:11: Error: Getter not found: 'onlySetter'.
+//     print(onlySetter);
+//           ^^^^^^^^^^
+//
+// pkg/front_end/testcases/accessors.dart:25:11: Error: The getter 'onlySetter' isn't defined for the class '#lib1::C'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'onlySetter'.
+//     print(onlySetter);
+//           ^^^^^^^^^^
+//
+// pkg/front_end/testcases/accessors.dart:40:11: Error: Getter not found: 'onlySetter'.
+//     print(onlySetter);
+//           ^^^^^^^^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/accessors.dart:16:13: Error: Getter not found: 'onlySetter'.
+//       print(onlySetter);
+//             ^^^^^^^^^^
+//
+// pkg/front_end/testcases/accessors.dart:25:11: Error: Getter not found: 'onlySetter'.
+//     print(onlySetter);
+//           ^^^^^^^^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  set onlySetter(dynamic value) → void {
+    core::print("C.onlySetter called with ${value}.");
+  }
+  method testC() → dynamic {
+    try {
+      core::print(let final dynamic #t1 = this in invalid-expression "pkg/front_end/testcases/accessors.dart:16:13: Error: The getter 'onlySetter' isn't defined for the class '#lib1::C'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'onlySetter'.
+      print(onlySetter);
+            ^^^^^^^^^^");
+      throw "No error thrown";
+    }
+    on core::NoSuchMethodError catch(final core::NoSuchMethodError e) {
+      core::print("Expected error: ${e}");
+    }
+    this.{self::C::onlySetter} = "hest";
+  }
+  method testD() → dynamic {
+    core::print(let final dynamic #t2 = this in invalid-expression "pkg/front_end/testcases/accessors.dart:25:11: Error: The getter 'onlySetter' isn't defined for the class '#lib1::C'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'onlySetter'.
+    print(onlySetter);
+          ^^^^^^^^^^");
+    this.{self::C::onlySetter} = "hest";
+  }
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+  get onlySetter() → core::String
+    return "D.onlySetter called.";
+  set onlySetter(dynamic value) → void {
+    core::print("D.onlySetter called with ${value}.");
+  }
+}
+static set onlySetter(dynamic value) → void {
+  core::print("onlySetter called with ${value}.");
+}
+static method main() → dynamic {
+  try {
+    core::print(invalid-expression "pkg/front_end/testcases/accessors.dart:40:11: Error: Getter not found: 'onlySetter'.
+    print(onlySetter);
+          ^^^^^^^^^^");
+    throw "No error thrown";
+  }
+  on core::NoSuchMethodError catch(final core::NoSuchMethodError e) {
+    core::print("Expected error: ${e}");
+  }
+  self::onlySetter = "fisk";
+  new self::C::•().{self::C::testC}();
+  new self::D::•().{self::C::testD}();
+}
diff --git a/pkg/front_end/testcases/accessors.dart.strong.transformed.expect b/pkg/front_end/testcases/accessors.dart.strong.transformed.expect
new file mode 100644
index 0000000..1eed890
--- /dev/null
+++ b/pkg/front_end/testcases/accessors.dart.strong.transformed.expect
@@ -0,0 +1,69 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/accessors.dart:16:13: Error: Getter not found: 'onlySetter'.
+//       print(onlySetter);
+//             ^^^^^^^^^^
+//
+// pkg/front_end/testcases/accessors.dart:25:11: Error: Getter not found: 'onlySetter'.
+//     print(onlySetter);
+//           ^^^^^^^^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  set onlySetter(dynamic value) → void {
+    core::print("C.onlySetter called with ${value}.");
+  }
+  method testC() → dynamic {
+    try {
+      core::print(let final self::C #t1 = this in invalid-expression "pkg/front_end/testcases/accessors.dart:16:13: Error: The getter 'onlySetter' isn't defined for the class '#lib1::C'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'onlySetter'.
+      print(onlySetter);
+            ^^^^^^^^^^");
+      throw "No error thrown";
+    }
+    on core::NoSuchMethodError catch(final core::NoSuchMethodError e) {
+      core::print("Expected error: ${e}");
+    }
+    this.{self::C::onlySetter} = "hest";
+  }
+  method testD() → dynamic {
+    core::print(let final self::C #t2 = this in invalid-expression "pkg/front_end/testcases/accessors.dart:25:11: Error: The getter 'onlySetter' isn't defined for the class '#lib1::C'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'onlySetter'.
+    print(onlySetter);
+          ^^^^^^^^^^");
+    this.{self::C::onlySetter} = "hest";
+  }
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+  get onlySetter() → core::String
+    return "D.onlySetter called.";
+  set onlySetter(dynamic value) → void {
+    core::print("D.onlySetter called with ${value}.");
+  }
+}
+static set onlySetter(dynamic value) → void {
+  core::print("onlySetter called with ${value}.");
+}
+static method main() → dynamic {
+  try {
+    core::print(invalid-expression "pkg/front_end/testcases/accessors.dart:40:11: Error: Getter not found: 'onlySetter'.
+    print(onlySetter);
+          ^^^^^^^^^^");
+    throw "No error thrown";
+  }
+  on core::NoSuchMethodError catch(final core::NoSuchMethodError e) {
+    core::print("Expected error: ${e}");
+  }
+  self::onlySetter = "fisk";
+  new self::C::•().{self::C::testC}();
+  new self::D::•().{self::C::testD}();
+}
diff --git a/pkg/front_end/testcases/ambiguous_exports.dart.direct.expect b/pkg/front_end/testcases/ambiguous_exports.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/ambiguous_exports.dart.direct.expect
rename to pkg/front_end/testcases/ambiguous_exports.dart.legacy.expect
diff --git a/pkg/front_end/testcases/ambiguous_exports.dart.direct.transformed.expect b/pkg/front_end/testcases/ambiguous_exports.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/ambiguous_exports.dart.direct.transformed.expect
rename to pkg/front_end/testcases/ambiguous_exports.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/annotation_eof.dart.direct.expect b/pkg/front_end/testcases/annotation_eof.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/annotation_eof.dart.direct.expect
rename to pkg/front_end/testcases/annotation_eof.dart.legacy.expect
diff --git a/pkg/front_end/testcases/annotation_eof.dart.direct.transformed.expect b/pkg/front_end/testcases/annotation_eof.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/annotation_eof.dart.direct.transformed.expect
rename to pkg/front_end/testcases/annotation_eof.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/annotation_on_enum_values.dart.direct.expect b/pkg/front_end/testcases/annotation_on_enum_values.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/annotation_on_enum_values.dart.direct.expect
rename to pkg/front_end/testcases/annotation_on_enum_values.dart.legacy.expect
diff --git a/pkg/front_end/testcases/annotation_on_enum_values.dart.direct.transformed.expect b/pkg/front_end/testcases/annotation_on_enum_values.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/annotation_on_enum_values.dart.direct.transformed.expect
rename to pkg/front_end/testcases/annotation_on_enum_values.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/annotation_top.dart.direct.expect b/pkg/front_end/testcases/annotation_top.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/annotation_top.dart.direct.expect
rename to pkg/front_end/testcases/annotation_top.dart.legacy.expect
diff --git a/pkg/front_end/testcases/annotation_top.dart.direct.transformed.expect b/pkg/front_end/testcases/annotation_top.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/annotation_top.dart.direct.transformed.expect
rename to pkg/front_end/testcases/annotation_top.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/annotation_typedef_formals.dart.direct.expect b/pkg/front_end/testcases/annotation_typedef_formals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/annotation_typedef_formals.dart.direct.expect
rename to pkg/front_end/testcases/annotation_typedef_formals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/annotation_typedef_formals.dart.direct.transformed.expect b/pkg/front_end/testcases/annotation_typedef_formals.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/annotation_typedef_formals.dart.direct.transformed.expect
rename to pkg/front_end/testcases/annotation_typedef_formals.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/annotation_typedef_formals_resolution.dart.direct.expect b/pkg/front_end/testcases/annotation_typedef_formals_resolution.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/annotation_typedef_formals_resolution.dart.direct.expect
rename to pkg/front_end/testcases/annotation_typedef_formals_resolution.dart.legacy.expect
diff --git a/pkg/front_end/testcases/annotation_typedef_formals_resolution.dart.direct.transformed.expect b/pkg/front_end/testcases/annotation_typedef_formals_resolution.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/annotation_typedef_formals_resolution.dart.direct.transformed.expect
rename to pkg/front_end/testcases/annotation_typedef_formals_resolution.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/annotation_variable_declaration.dart.direct.expect b/pkg/front_end/testcases/annotation_variable_declaration.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/annotation_variable_declaration.dart.direct.expect
rename to pkg/front_end/testcases/annotation_variable_declaration.dart.legacy.expect
diff --git a/pkg/front_end/testcases/annotation_variable_declaration.dart.direct.transformed.expect b/pkg/front_end/testcases/annotation_variable_declaration.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/annotation_variable_declaration.dart.direct.transformed.expect
rename to pkg/front_end/testcases/annotation_variable_declaration.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/argument.dart.direct.expect b/pkg/front_end/testcases/argument.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/argument.dart.direct.expect
rename to pkg/front_end/testcases/argument.dart.legacy.expect
diff --git a/pkg/front_end/testcases/argument.dart.direct.transformed.expect b/pkg/front_end/testcases/argument.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/argument.dart.direct.transformed.expect
rename to pkg/front_end/testcases/argument.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/argument_mismatch.dart.direct.expect b/pkg/front_end/testcases/argument_mismatch.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/argument_mismatch.dart.direct.expect
rename to pkg/front_end/testcases/argument_mismatch.dart.legacy.expect
diff --git a/pkg/front_end/testcases/argument_mismatch.dart.direct.transformed.expect b/pkg/front_end/testcases/argument_mismatch.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/argument_mismatch.dart.direct.transformed.expect
rename to pkg/front_end/testcases/argument_mismatch.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/arithmetic.dart.direct.expect b/pkg/front_end/testcases/arithmetic.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/arithmetic.dart.direct.expect
rename to pkg/front_end/testcases/arithmetic.dart.legacy.expect
diff --git a/pkg/front_end/testcases/arithmetic.dart.direct.transformed.expect b/pkg/front_end/testcases/arithmetic.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/arithmetic.dart.direct.transformed.expect
rename to pkg/front_end/testcases/arithmetic.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/arithmetic.dart.type_promotion.expect b/pkg/front_end/testcases/arithmetic.dart.type_promotion.expect
new file mode 100644
index 0000000..8a5a7db
--- /dev/null
+++ b/pkg/front_end/testcases/arithmetic.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/arithmetic.dart:11:35: Context: Write to i@330
+  for (int i = 0; i < xs.length; i++) {}
+                                  ^^
diff --git a/pkg/front_end/testcases/arrow_function.dart.direct.expect b/pkg/front_end/testcases/arrow_function.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/arrow_function.dart.direct.expect
rename to pkg/front_end/testcases/arrow_function.dart.legacy.expect
diff --git a/pkg/front_end/testcases/arrow_function.dart.direct.transformed.expect b/pkg/front_end/testcases/arrow_function.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/arrow_function.dart.direct.transformed.expect
rename to pkg/front_end/testcases/arrow_function.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/async_function.dart.direct.expect b/pkg/front_end/testcases/async_function.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/async_function.dart.direct.expect
rename to pkg/front_end/testcases/async_function.dart.legacy.expect
diff --git a/pkg/front_end/testcases/async_function.dart.direct.transformed.expect b/pkg/front_end/testcases/async_function.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/async_function.dart.direct.transformed.expect
rename to pkg/front_end/testcases/async_function.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/async_function.dart.strong.expect b/pkg/front_end/testcases/async_function.dart.strong.expect
index d498bf6..4cbc5e0 100644
--- a/pkg/front_end/testcases/async_function.dart.strong.expect
+++ b/pkg/front_end/testcases/async_function.dart.strong.expect
@@ -3,9 +3,29 @@
 import "dart:async" as asy;
 import "dart:core" as core;
 
+static field core::List<core::String> stringList = <core::String>["bar"];
 static method asyncString() → asy::Future<core::String> async {
   return "foo";
 }
+static method asyncString2() → asy::Future<core::String> async {
+  return self::asyncString();
+}
+static method syncStarString() → core::Iterable<core::String> sync* {
+  yield "foo";
+  yield* self::syncStarString2();
+  yield* self::stringList;
+}
+static method syncStarString2() → core::Iterable<core::String> sync* {
+  yield "foo";
+}
+static method asyncStarString() → asy::Stream<core::String> async* {
+  yield "foo";
+  yield* self::asyncStarString2();
+  yield await self::asyncString();
+}
+static method asyncStarString2() → asy::Stream<core::String> async* {
+  yield "bar";
+}
 static method main() → dynamic async {
   core::String str = await self::asyncString();
 }
diff --git a/pkg/front_end/testcases/async_function.dart.strong.transformed.expect b/pkg/front_end/testcases/async_function.dart.strong.transformed.expect
new file mode 100644
index 0000000..e0c9dae
--- /dev/null
+++ b/pkg/front_end/testcases/async_function.dart.strong.transformed.expect
@@ -0,0 +1,203 @@
+library;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static field core::List<core::String> stringList = <core::String>["bar"];
+static method asyncString() → asy::Future<core::String> /* originally async */ {
+  final asy::Completer<core::String> :async_completer = asy::Completer::sync<core::String>();
+  asy::FutureOr<core::String> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        :return_value = "foo";
+        break #L1;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method asyncString2() → asy::Future<core::String> /* originally async */ {
+  final asy::Completer<core::String> :async_completer = asy::Completer::sync<core::String>();
+  asy::FutureOr<core::String> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        :return_value = self::asyncString();
+        break #L2;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method syncStarString() → core::Iterable<core::String> /* originally sync* */ {
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :sync_op(core::_SyncIterator<core::String> :iterator) → core::bool yielding {
+    {
+      {
+        :iterator.{core::_SyncIterator::_current} = "foo";
+        [yield] true;
+      }
+      {
+        :iterator.{core::_SyncIterator::_yieldEachIterable} = self::syncStarString2();
+        [yield] true;
+      }
+      {
+        :iterator.{core::_SyncIterator::_yieldEachIterable} = self::stringList;
+        [yield] true;
+      }
+    }
+    return false;
+  }
+  return new core::_SyncIterable::•<core::String>(:sync_op);
+}
+static method syncStarString2() → core::Iterable<core::String> /* originally sync* */ {
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :sync_op(core::_SyncIterator<core::String> :iterator) → core::bool yielding {
+    {
+      {
+        :iterator.{core::_SyncIterator::_current} = "foo";
+        [yield] true;
+      }
+    }
+    return false;
+  }
+  return new core::_SyncIterable::•<core::String>(:sync_op);
+}
+static method asyncStarString() → asy::Stream<core::String> /* originally async* */ {
+  asy::_AsyncStarStreamController<core::String> :controller;
+  dynamic :controller_stream;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :saved_try_context_var1;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try
+      try {
+        #L3:
+        {
+          if(:controller.{asy::_AsyncStarStreamController::add}("foo"))
+            return null;
+          else
+            [yield] null;
+          if(:controller.{asy::_AsyncStarStreamController::addStream}(self::asyncStarString2()))
+            return null;
+          else
+            [yield] null;
+          [yield] let dynamic #t1 = asy::_awaitHelper(self::asyncString(), :async_op_then, :async_op_error, :async_op) in null;
+          if(:controller.{asy::_AsyncStarStreamController::add}(:result))
+            return null;
+          else
+            [yield] null;
+        }
+        return;
+      }
+      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
+      }
+    finally {
+      :controller.{asy::_AsyncStarStreamController::close}();
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :controller = new asy::_AsyncStarStreamController::•<core::String>(:async_op);
+  :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
+  return :controller_stream;
+}
+static method asyncStarString2() → asy::Stream<core::String> /* originally async* */ {
+  asy::_AsyncStarStreamController<core::String> :controller;
+  dynamic :controller_stream;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :saved_try_context_var1;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try
+      try {
+        #L4:
+        {
+          if(:controller.{asy::_AsyncStarStreamController::add}("bar"))
+            return null;
+          else
+            [yield] null;
+        }
+        return;
+      }
+      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
+      }
+    finally {
+      :controller.{asy::_AsyncStarStreamController::close}();
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :controller = new asy::_AsyncStarStreamController::•<core::String>(:async_op);
+  :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
+  return :controller_stream;
+}
+static method main() → dynamic /* originally async */ {
+  final asy::Completer<dynamic> :async_completer = asy::Completer::sync<dynamic>();
+  asy::FutureOr<dynamic> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L5:
+      {
+        [yield] let dynamic #t2 = asy::_awaitHelper(self::asyncString(), :async_op_then, :async_op_error, :async_op) in null;
+        core::String str = :result;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
diff --git a/pkg/front_end/testcases/async_nested.dart.direct.expect b/pkg/front_end/testcases/async_nested.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/async_nested.dart.direct.expect
rename to pkg/front_end/testcases/async_nested.dart.legacy.expect
diff --git a/pkg/front_end/testcases/async_nested.dart.direct.transformed.expect b/pkg/front_end/testcases/async_nested.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/async_nested.dart.direct.transformed.expect
rename to pkg/front_end/testcases/async_nested.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/await.dart.direct.expect b/pkg/front_end/testcases/await.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/await.dart.direct.expect
rename to pkg/front_end/testcases/await.dart.legacy.expect
diff --git a/pkg/front_end/testcases/await.dart.direct.transformed.expect b/pkg/front_end/testcases/await.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/await.dart.direct.transformed.expect
rename to pkg/front_end/testcases/await.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/await.dart.direct.expect b/pkg/front_end/testcases/await.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/await.dart.direct.expect
copy to pkg/front_end/testcases/await.dart.strong.expect
diff --git a/pkg/front_end/testcases/await.dart.direct.transformed.expect b/pkg/front_end/testcases/await.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/await.dart.direct.transformed.expect
copy to pkg/front_end/testcases/await.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/bad_setter_abstract.dart.direct.expect b/pkg/front_end/testcases/bad_setter_abstract.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bad_setter_abstract.dart.direct.expect
rename to pkg/front_end/testcases/bad_setter_abstract.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bad_setter_abstract.dart.direct.transformed.expect b/pkg/front_end/testcases/bad_setter_abstract.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bad_setter_abstract.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bad_setter_abstract.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/bad_setter_abstract.dart.type_promotion.expect b/pkg/front_end/testcases/bad_setter_abstract.dart.type_promotion.expect
new file mode 100644
index 0000000..adc877f
--- /dev/null
+++ b/pkg/front_end/testcases/bad_setter_abstract.dart.type_promotion.expect
@@ -0,0 +1,30 @@
+pkg/front_end/testcases/bad_setter_abstract.dart:22:11: Context: Write to threw@344
+    threw = true;
+          ^
+pkg/front_end/testcases/bad_setter_abstract.dart:24:11: Context: Write to threw@344
+    threw = false;
+          ^
+pkg/front_end/testcases/bad_setter_abstract.dart:32:11: Context: Write to threw@344
+    threw = true;
+          ^
+pkg/front_end/testcases/bad_setter_abstract.dart:34:11: Context: Write to threw@344
+    threw = false;
+          ^
+pkg/front_end/testcases/bad_setter_abstract.dart:42:11: Context: Write to threw@344
+    threw = true;
+          ^
+pkg/front_end/testcases/bad_setter_abstract.dart:44:11: Context: Write to threw@344
+    threw = false;
+          ^
+pkg/front_end/testcases/bad_setter_abstract.dart:55:11: Context: Write to threw@344
+    threw = true;
+          ^
+pkg/front_end/testcases/bad_setter_abstract.dart:57:11: Context: Write to threw@344
+    threw = false;
+          ^
+pkg/front_end/testcases/bad_setter_abstract.dart:65:11: Context: Write to threw@344
+    threw = true;
+          ^
+pkg/front_end/testcases/bad_setter_abstract.dart:67:11: Context: Write to threw@344
+    threw = false;
+          ^
diff --git a/pkg/front_end/testcases/bad_store.dart.direct.expect b/pkg/front_end/testcases/bad_store.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bad_store.dart.direct.expect
rename to pkg/front_end/testcases/bad_store.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bad_store.dart.direct.transformed.expect b/pkg/front_end/testcases/bad_store.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bad_store.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bad_store.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/bounds_check_depends_on_inference.dart.direct.expect b/pkg/front_end/testcases/bounds_check_depends_on_inference.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bounds_check_depends_on_inference.dart.direct.expect
rename to pkg/front_end/testcases/bounds_check_depends_on_inference.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bounds_check_depends_on_inference.dart.direct.transformed.expect b/pkg/front_end/testcases/bounds_check_depends_on_inference.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bounds_check_depends_on_inference.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bounds_check_depends_on_inference.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/bug21938.dart.direct.expect b/pkg/front_end/testcases/bug21938.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bug21938.dart.direct.expect
rename to pkg/front_end/testcases/bug21938.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bug21938.dart.direct.transformed.expect b/pkg/front_end/testcases/bug21938.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bug21938.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bug21938.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/bug30695.dart.direct.expect b/pkg/front_end/testcases/bug30695.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bug30695.dart.direct.expect
rename to pkg/front_end/testcases/bug30695.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bug30695.dart.direct.transformed.expect b/pkg/front_end/testcases/bug30695.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bug30695.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bug30695.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/bug31124.dart.direct.expect b/pkg/front_end/testcases/bug31124.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bug31124.dart.direct.expect
rename to pkg/front_end/testcases/bug31124.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bug31124.dart.direct.transformed.expect b/pkg/front_end/testcases/bug31124.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bug31124.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bug31124.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/bug32414a.dart.direct.expect b/pkg/front_end/testcases/bug32414a.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bug32414a.dart.direct.expect
rename to pkg/front_end/testcases/bug32414a.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bug32414a.dart.direct.transformed.expect b/pkg/front_end/testcases/bug32414a.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bug32414a.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bug32414a.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/bug32414a.dart.type_promotion.expect b/pkg/front_end/testcases/bug32414a.dart.type_promotion.expect
new file mode 100644
index 0000000..6f70c2d
--- /dev/null
+++ b/pkg/front_end/testcases/bug32414a.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/bug32414a.dart:10:5: Context: Write to b@302
+  b = 42;
+    ^
diff --git a/pkg/front_end/testcases/bug32414b.dart.direct.expect b/pkg/front_end/testcases/bug32414b.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bug32414b.dart.direct.expect
rename to pkg/front_end/testcases/bug32414b.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bug32414b.dart.direct.transformed.expect b/pkg/front_end/testcases/bug32414b.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bug32414b.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bug32414b.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/bug32426.dart.direct.expect b/pkg/front_end/testcases/bug32426.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bug32426.dart.direct.expect
rename to pkg/front_end/testcases/bug32426.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bug32426.dart.direct.transformed.expect b/pkg/front_end/testcases/bug32426.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bug32426.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bug32426.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/bug32629.dart.direct.expect b/pkg/front_end/testcases/bug32629.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bug32629.dart.direct.expect
rename to pkg/front_end/testcases/bug32629.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bug32629.dart.direct.transformed.expect b/pkg/front_end/testcases/bug32629.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bug32629.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bug32629.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/bug32866.dart.direct.expect b/pkg/front_end/testcases/bug32866.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bug32866.dart.direct.expect
rename to pkg/front_end/testcases/bug32866.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bug32866.dart.direct.transformed.expect b/pkg/front_end/testcases/bug32866.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bug32866.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bug32866.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/bug33099.dart.direct.expect b/pkg/front_end/testcases/bug33099.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bug33099.dart.direct.expect
rename to pkg/front_end/testcases/bug33099.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bug33099.dart.direct.transformed.expect b/pkg/front_end/testcases/bug33099.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bug33099.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bug33099.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/bug33196.dart.direct.expect b/pkg/front_end/testcases/bug33196.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bug33196.dart.direct.expect
rename to pkg/front_end/testcases/bug33196.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bug33196.dart.direct.transformed.expect b/pkg/front_end/testcases/bug33196.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bug33196.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bug33196.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/bug33206.dart.direct.expect b/pkg/front_end/testcases/bug33206.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bug33206.dart.direct.expect
rename to pkg/front_end/testcases/bug33206.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bug33206.dart.direct.transformed.expect b/pkg/front_end/testcases/bug33206.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bug33206.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bug33206.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/bug33298.dart.direct.expect b/pkg/front_end/testcases/bug33298.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/bug33298.dart.direct.expect
rename to pkg/front_end/testcases/bug33298.dart.legacy.expect
diff --git a/pkg/front_end/testcases/bug33298.dart.direct.transformed.expect b/pkg/front_end/testcases/bug33298.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/bug33298.dart.direct.transformed.expect
rename to pkg/front_end/testcases/bug33298.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/call.dart.direct.expect b/pkg/front_end/testcases/call.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/call.dart.direct.expect
rename to pkg/front_end/testcases/call.dart.legacy.expect
diff --git a/pkg/front_end/testcases/call.dart.strong.expect b/pkg/front_end/testcases/call.dart.strong.expect
index 8f91575..1ca029b 100644
--- a/pkg/front_end/testcases/call.dart.strong.expect
+++ b/pkg/front_end/testcases/call.dart.strong.expect
@@ -1,9 +1,87 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/call.dart:29:31: Error: Cannot invoke an instance of '#lib1::CallableGetter' because it declares 'call' to be something other than a method.
+// Try changing 'call' to a method or explicitly invoke 'call'.
+//   var string5 = callableGetter(1);
+//                               ^
+//
+// pkg/front_end/testcases/call.dart:34:25: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing1 = closure();
+//                         ^
+//
+// pkg/front_end/testcases/call.dart:35:30: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing2 = closure.call();
+//                              ^
+//
+// pkg/front_end/testcases/call.dart:36:35: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing3 = closure.call.call();
+//                                   ^
+//
+// pkg/front_end/testcases/call.dart:37:40: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing4 = closure.call.call.call();
+//                                        ^
+//
+// pkg/front_end/testcases/call.dart:39:26: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing5 = callable();
+//                          ^
+//
+// pkg/front_end/testcases/call.dart:40:31: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing6 = callable.call();
+//                               ^
+//
+// pkg/front_end/testcases/call.dart:41:36: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing7 = callable.call.call();
+//                                    ^
+//
+// pkg/front_end/testcases/call.dart:42:41: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing8 = callable.call.call.call();
+//                                         ^
+//
+// pkg/front_end/testcases/call.dart:44:32: Error: Cannot invoke an instance of '#lib1::CallableGetter' because it declares 'call' to be something other than a method.
+// Try changing 'call' to a method or explicitly invoke 'call'.
+//   var nothing9 = callableGetter();
+//                                ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/call.dart:34:25: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing1 = closure();
+//                         ^
+//
+// pkg/front_end/testcases/call.dart:35:30: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing2 = closure.call();
+//                              ^
+//
+// pkg/front_end/testcases/call.dart:36:35: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing3 = closure.call.call();
+//                                   ^
+//
+// pkg/front_end/testcases/call.dart:37:40: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing4 = closure.call.call.call();
+//                                        ^
+//
+// pkg/front_end/testcases/call.dart:39:26: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing5 = callable();
+//                          ^
+//
+// pkg/front_end/testcases/call.dart:40:31: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing6 = callable.call();
+//                               ^
+//
+// pkg/front_end/testcases/call.dart:41:36: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing7 = callable.call.call();
+//                                    ^
+//
+// pkg/front_end/testcases/call.dart:42:41: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing8 = callable.call.call.call();
+//                                         ^
+
 library;
 import self as self;
 import "dart:core" as core;
 
 class Callable extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::Callable
     : super core::Object::•()
     ;
   method call(dynamic x) → dynamic {
@@ -11,7 +89,7 @@
   }
 }
 class CallableGetter extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::CallableGetter
     : super core::Object::•()
     ;
   get call() → dynamic
@@ -29,7 +107,10 @@
   dynamic string3 = callable.{self::Callable::call}.call(1);
   dynamic string4 = callable.{self::Callable::call}.call.call(1);
   self::CallableGetter callableGetter = new self::CallableGetter::•();
-  dynamic string5 = callableGetter.{self::CallableGetter::call}(1);
+  dynamic string5 = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/call.dart:29:31: Error: Cannot invoke an instance of '#lib1::CallableGetter' because it declares 'call' to be something other than a method.
+Try changing 'call' to a method or explicitly invoke 'call'.
+  var string5 = callableGetter(1);
+                              ^" in callableGetter.{self::CallableGetter::call}(1);
   dynamic string6 = callableGetter.{self::CallableGetter::call}(1);
   dynamic string7 = callableGetter.{self::CallableGetter::call}.call(1);
   dynamic string8 = callableGetter.{self::CallableGetter::call}.call.call(1);
@@ -41,7 +122,10 @@
   dynamic nothing6 = callable.{self::Callable::call}();
   dynamic nothing7 = callable.{self::Callable::call}.call();
   dynamic nothing8 = callable.{self::Callable::call}.call.call();
-  dynamic nothing9 = callableGetter.{self::CallableGetter::call}();
+  dynamic nothing9 = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/call.dart:44:32: Error: Cannot invoke an instance of '#lib1::CallableGetter' because it declares 'call' to be something other than a method.
+Try changing 'call' to a method or explicitly invoke 'call'.
+  var nothing9 = callableGetter();
+                               ^" in callableGetter.{self::CallableGetter::call}();
   dynamic nothing10 = callableGetter.{self::CallableGetter::call}();
   dynamic nothing11 = callableGetter.{self::CallableGetter::call}.call();
   dynamic nothing12 = callableGetter.{self::CallableGetter::call}.call.call();
diff --git a/pkg/front_end/testcases/cascade.dart.direct.expect b/pkg/front_end/testcases/cascade.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/cascade.dart.direct.expect
rename to pkg/front_end/testcases/cascade.dart.legacy.expect
diff --git a/pkg/front_end/testcases/cascade.dart.direct.transformed.expect b/pkg/front_end/testcases/cascade.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/cascade.dart.direct.transformed.expect
rename to pkg/front_end/testcases/cascade.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/cascade.dart.strong.expect b/pkg/front_end/testcases/cascade.dart.strong.expect
new file mode 100644
index 0000000..5feb052
--- /dev/null
+++ b/pkg/front_end/testcases/cascade.dart.strong.expect
@@ -0,0 +1,48 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/cascade.dart:26:5: Error: A value of type 'dart.core::List<dart.core::int>' can't be assigned to a variable of type 'dart.core::int'.
+// Try changing the type of the left hand side, or casting the right hand side to 'dart.core::int'.
+//     [1]
+//     ^
+//
+// pkg/front_end/testcases/cascade.dart:28:13: Error: The getter 'last' isn't defined for the class 'dart.core::int'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'last'.
+//     ..first.last.toString()
+//             ^^^^
+//
+// pkg/front_end/testcases/cascade.dart:29:12: Error: The method '[]' isn't defined for the class 'dart.core::int'.
+// Try correcting the name to the name of an existing method, or defining a method named '[]'.
+//     ..first[0].toString()
+//            ^^
+//
+// pkg/front_end/testcases/cascade.dart:30:11: Error: The getter 'last' isn't defined for the class 'dart.core::int'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'last'.
+//     ..[0].last.toString();
+//           ^^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::List<core::int> list = let final core::List<core::int> #t1 = <core::int>[1] in let final dynamic #t2 = #t1.{core::List::add}(2) in let final dynamic #t3 = #t1.{core::List::add}(3) in let final dynamic #t4 = #t1.{core::List::addAll}(<core::int>[4, 5]) in #t1;
+  core::print(list);
+  let final core::List<core::int> #t5 = list in let final dynamic #t6 = #t5.{core::List::add}(2) in let final dynamic #t7 = #t5.{core::List::length} in let final dynamic #t8 = #t5.{core::List::length} = 0 in #t5;
+  core::print(list);
+  let final core::List<core::int> #t9 = list in let final dynamic #t10 = #t9.{core::List::add}(2) in let final dynamic #t11 = #t9.{core::List::[]}(0) in let final dynamic #t12 = #t9.{core::List::[]=}(0, 87) in #t9;
+  core::print(list);
+  list = let final core::List<core::int> #t13 = <core::int>[let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/cascade.dart:26:5: Error: A value of type 'dart.core::List<dart.core::int>' can't be assigned to a variable of type 'dart.core::int'.
+Try changing the type of the left hand side, or casting the right hand side to 'dart.core::int'.
+    [1]
+    ^" in <core::int>[1] as{TypeError} core::int] in let final dynamic #t15 = (let final dynamic #t16 = #t13.{core::Iterable::first} in invalid-expression "pkg/front_end/testcases/cascade.dart:28:13: Error: The getter 'last' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'last'.
+    ..first.last.toString()
+            ^^^^").{core::Object::toString}() in let final dynamic #t17 = (let final dynamic #t18 = #t13.{core::Iterable::first} in invalid-expression "pkg/front_end/testcases/cascade.dart:29:12: Error: The method '[]' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing method, or defining a method named '[]'.
+    ..first[0].toString()
+           ^^").{core::Object::toString}() in let final dynamic #t19 = (let final dynamic #t20 = #t13.{core::List::[]}(0) in invalid-expression "pkg/front_end/testcases/cascade.dart:30:11: Error: The getter 'last' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'last'.
+    ..[0].last.toString();
+          ^^^^").{core::Object::toString}() in #t13;
+  core::print(list);
+}
diff --git a/pkg/front_end/testcases/cascade.dart.strong.transformed.expect b/pkg/front_end/testcases/cascade.dart.strong.transformed.expect
new file mode 100644
index 0000000..83c3d98
--- /dev/null
+++ b/pkg/front_end/testcases/cascade.dart.strong.transformed.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::List<core::int> list = let final core::List<core::int> #t1 = <core::int>[1] in let final void #t2 = #t1.{core::List::add}(2) in let final void #t3 = #t1.{core::List::add}(3) in let final void #t4 = #t1.{core::List::addAll}(<core::int>[4, 5]) in #t1;
+  core::print(list);
+  let final core::List<core::int> #t5 = list in let final void #t6 = #t5.{core::List::add}(2) in let final core::int #t7 = #t5.{core::List::length} in let final core::int #t8 = #t5.{core::List::length} = 0 in #t5;
+  core::print(list);
+  let final core::List<core::int> #t9 = list in let final void #t10 = #t9.{core::List::add}(2) in let final core::int #t11 = #t9.{core::List::[]}(0) in let final void #t12 = #t9.{core::List::[]=}(0, 87) in #t9;
+  core::print(list);
+  list = let final core::List<core::int> #t13 = <core::int>[let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/cascade.dart:26:5: Error: A value of type 'dart.core::List<dart.core::int>' can't be assigned to a variable of type 'dart.core::int'.
+Try changing the type of the left hand side, or casting the right hand side to 'dart.core::int'.
+    [1]
+    ^" in <core::int>[1] as{TypeError} core::int] in let final core::String #t15 = (let final core::int #t16 = #t13.{core::Iterable::first} in invalid-expression "pkg/front_end/testcases/cascade.dart:28:13: Error: The getter 'last' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'last'.
+    ..first.last.toString()
+            ^^^^").{core::Object::toString}() in let final core::String #t17 = (let final core::int #t18 = #t13.{core::Iterable::first} in invalid-expression "pkg/front_end/testcases/cascade.dart:29:12: Error: The method '[]' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing method, or defining a method named '[]'.
+    ..first[0].toString()
+           ^^").{core::Object::toString}() in let final core::String #t19 = (let final core::int #t20 = #t13.{core::List::[]}(0) in invalid-expression "pkg/front_end/testcases/cascade.dart:30:11: Error: The getter 'last' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'last'.
+    ..[0].last.toString();
+          ^^^^").{core::Object::toString}() in #t13;
+  core::print(list);
+}
diff --git a/pkg/front_end/testcases/cascade.dart.type_promotion.expect b/pkg/front_end/testcases/cascade.dart.type_promotion.expect
new file mode 100644
index 0000000..3d3e899
--- /dev/null
+++ b/pkg/front_end/testcases/cascade.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/cascade.dart:25:8: Context: Write to list@232
+  list = [
+       ^
diff --git a/pkg/front_end/testcases/casts.dart.direct.expect b/pkg/front_end/testcases/casts.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/casts.dart.direct.expect
rename to pkg/front_end/testcases/casts.dart.legacy.expect
diff --git a/pkg/front_end/testcases/casts.dart.direct.transformed.expect b/pkg/front_end/testcases/casts.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/casts.dart.direct.transformed.expect
rename to pkg/front_end/testcases/casts.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/casts.dart.direct.expect b/pkg/front_end/testcases/casts.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/casts.dart.direct.expect
copy to pkg/front_end/testcases/casts.dart.strong.expect
diff --git a/pkg/front_end/testcases/casts.dart.direct.transformed.expect b/pkg/front_end/testcases/casts.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/casts.dart.direct.transformed.expect
copy to pkg/front_end/testcases/casts.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/check_deferred_allocation.dart.direct.expect b/pkg/front_end/testcases/check_deferred_allocation.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_allocation.dart.direct.expect
rename to pkg/front_end/testcases/check_deferred_allocation.dart.legacy.expect
diff --git a/pkg/front_end/testcases/check_deferred_allocation.dart.direct.transformed.expect b/pkg/front_end/testcases/check_deferred_allocation.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_allocation.dart.direct.transformed.expect
rename to pkg/front_end/testcases/check_deferred_allocation.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/check_deferred_as_check.dart.direct.expect b/pkg/front_end/testcases/check_deferred_as_check.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_as_check.dart.direct.expect
rename to pkg/front_end/testcases/check_deferred_as_check.dart.legacy.expect
diff --git a/pkg/front_end/testcases/check_deferred_as_check.dart.direct.transformed.expect b/pkg/front_end/testcases/check_deferred_as_check.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_as_check.dart.direct.transformed.expect
rename to pkg/front_end/testcases/check_deferred_as_check.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/check_deferred_before_args.dart.direct.expect b/pkg/front_end/testcases/check_deferred_before_args.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_before_args.dart.direct.expect
rename to pkg/front_end/testcases/check_deferred_before_args.dart.legacy.expect
diff --git a/pkg/front_end/testcases/check_deferred_before_args.dart.direct.transformed.expect b/pkg/front_end/testcases/check_deferred_before_args.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_before_args.dart.direct.transformed.expect
rename to pkg/front_end/testcases/check_deferred_before_args.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/check_deferred_before_args2.dart.direct.expect b/pkg/front_end/testcases/check_deferred_before_args2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_before_args2.dart.direct.expect
rename to pkg/front_end/testcases/check_deferred_before_args2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/check_deferred_before_args2.dart.direct.transformed.expect b/pkg/front_end/testcases/check_deferred_before_args2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_before_args2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/check_deferred_before_args2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/check_deferred_before_call.dart.direct.expect b/pkg/front_end/testcases/check_deferred_before_call.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_before_call.dart.direct.expect
rename to pkg/front_end/testcases/check_deferred_before_call.dart.legacy.expect
diff --git a/pkg/front_end/testcases/check_deferred_before_call.dart.direct.transformed.expect b/pkg/front_end/testcases/check_deferred_before_call.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_before_call.dart.direct.transformed.expect
rename to pkg/front_end/testcases/check_deferred_before_call.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/check_deferred_before_write.dart.direct.expect b/pkg/front_end/testcases/check_deferred_before_write.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_before_write.dart.direct.expect
rename to pkg/front_end/testcases/check_deferred_before_write.dart.legacy.expect
diff --git a/pkg/front_end/testcases/check_deferred_before_write.dart.direct.transformed.expect b/pkg/front_end/testcases/check_deferred_before_write.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_before_write.dart.direct.transformed.expect
rename to pkg/front_end/testcases/check_deferred_before_write.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/check_deferred_is_check.dart.direct.expect b/pkg/front_end/testcases/check_deferred_is_check.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_is_check.dart.direct.expect
rename to pkg/front_end/testcases/check_deferred_is_check.dart.legacy.expect
diff --git a/pkg/front_end/testcases/check_deferred_is_check.dart.direct.transformed.expect b/pkg/front_end/testcases/check_deferred_is_check.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_is_check.dart.direct.transformed.expect
rename to pkg/front_end/testcases/check_deferred_is_check.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/check_deferred_is_check.dart.type_promotion.expect b/pkg/front_end/testcases/check_deferred_is_check.dart.type_promotion.expect
new file mode 100644
index 0000000..fbbe754
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_is_check.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/check_deferred_is_check.dart:9:11: Context: Possible promotion of x@279
+  print(x is lib.C);
+          ^^
diff --git a/pkg/front_end/testcases/check_deferred_read.dart.direct.expect b/pkg/front_end/testcases/check_deferred_read.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_read.dart.direct.expect
rename to pkg/front_end/testcases/check_deferred_read.dart.legacy.expect
diff --git a/pkg/front_end/testcases/check_deferred_read.dart.direct.transformed.expect b/pkg/front_end/testcases/check_deferred_read.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_read.dart.direct.transformed.expect
rename to pkg/front_end/testcases/check_deferred_read.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/check_deferred_read_static_field.dart.direct.expect b/pkg/front_end/testcases/check_deferred_read_static_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_read_static_field.dart.direct.expect
rename to pkg/front_end/testcases/check_deferred_read_static_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/check_deferred_read_static_field.dart.direct.transformed.expect b/pkg/front_end/testcases/check_deferred_read_static_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_read_static_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/check_deferred_read_static_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/check_deferred_read_type.dart.direct.expect b/pkg/front_end/testcases/check_deferred_read_type.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_read_type.dart.direct.expect
rename to pkg/front_end/testcases/check_deferred_read_type.dart.legacy.expect
diff --git a/pkg/front_end/testcases/check_deferred_read_type.dart.direct.transformed.expect b/pkg/front_end/testcases/check_deferred_read_type.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_read_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/check_deferred_read_type.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/check_deferred_static_method_call.dart.direct.expect b/pkg/front_end/testcases/check_deferred_static_method_call.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_static_method_call.dart.direct.expect
rename to pkg/front_end/testcases/check_deferred_static_method_call.dart.legacy.expect
diff --git a/pkg/front_end/testcases/check_deferred_static_method_call.dart.direct.transformed.expect b/pkg/front_end/testcases/check_deferred_static_method_call.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_static_method_call.dart.direct.transformed.expect
rename to pkg/front_end/testcases/check_deferred_static_method_call.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/check_deferred_type_declaration.dart.direct.expect b/pkg/front_end/testcases/check_deferred_type_declaration.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_type_declaration.dart.direct.expect
rename to pkg/front_end/testcases/check_deferred_type_declaration.dart.legacy.expect
diff --git a/pkg/front_end/testcases/check_deferred_type_declaration.dart.direct.transformed.expect b/pkg/front_end/testcases/check_deferred_type_declaration.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/check_deferred_type_declaration.dart.direct.transformed.expect
rename to pkg/front_end/testcases/check_deferred_type_declaration.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/circularity-via-initializing-formal.dart.direct.expect b/pkg/front_end/testcases/circularity-via-initializing-formal.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/circularity-via-initializing-formal.dart.direct.expect
rename to pkg/front_end/testcases/circularity-via-initializing-formal.dart.legacy.expect
diff --git a/pkg/front_end/testcases/circularity-via-initializing-formal.dart.direct.transformed.expect b/pkg/front_end/testcases/circularity-via-initializing-formal.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/circularity-via-initializing-formal.dart.direct.transformed.expect
rename to pkg/front_end/testcases/circularity-via-initializing-formal.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/classes.dart.direct.expect b/pkg/front_end/testcases/classes.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/classes.dart.direct.expect
rename to pkg/front_end/testcases/classes.dart.legacy.expect
diff --git a/pkg/front_end/testcases/classes.dart.direct.transformed.expect b/pkg/front_end/testcases/classes.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/classes.dart.direct.transformed.expect
rename to pkg/front_end/testcases/classes.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/classes.dart.strong.expect b/pkg/front_end/testcases/classes.dart.strong.expect
new file mode 100644
index 0000000..05cade4
--- /dev/null
+++ b/pkg/front_end/testcases/classes.dart.strong.expect
@@ -0,0 +1,31 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  final field core::int x;
+  final field core::int y;
+  constructor •(core::int y) → self::A
+    : self::A::y = y, self::A::x = 42, super core::Object::•()
+    ;
+  method method() → dynamic {
+    core::print("A.method x: ${this.{self::A::x}} y: ${this.{self::A::y}}");
+    core::print(this);
+    core::print(this.{core::Object::runtimeType});
+  }
+}
+class B extends self::A {
+  constructor •(dynamic x) → self::B
+    : super self::A::•(x as{TypeError} core::int)
+    ;
+  method method() → dynamic {
+    core::print("B.method x: ${this.{self::A::x}} y: ${this.{self::A::y}}");
+    super.{self::A::method}();
+  }
+}
+static method main() → dynamic {
+  self::A a = new self::A::•(87);
+  self::B b = new self::B::•(117);
+  a.{self::A::method}();
+  b.{self::B::method}();
+}
diff --git a/pkg/front_end/testcases/classes.dart.strong.transformed.expect b/pkg/front_end/testcases/classes.dart.strong.transformed.expect
new file mode 100644
index 0000000..05cade4
--- /dev/null
+++ b/pkg/front_end/testcases/classes.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  final field core::int x;
+  final field core::int y;
+  constructor •(core::int y) → self::A
+    : self::A::y = y, self::A::x = 42, super core::Object::•()
+    ;
+  method method() → dynamic {
+    core::print("A.method x: ${this.{self::A::x}} y: ${this.{self::A::y}}");
+    core::print(this);
+    core::print(this.{core::Object::runtimeType});
+  }
+}
+class B extends self::A {
+  constructor •(dynamic x) → self::B
+    : super self::A::•(x as{TypeError} core::int)
+    ;
+  method method() → dynamic {
+    core::print("B.method x: ${this.{self::A::x}} y: ${this.{self::A::y}}");
+    super.{self::A::method}();
+  }
+}
+static method main() → dynamic {
+  self::A a = new self::A::•(87);
+  self::B b = new self::B::•(117);
+  a.{self::A::method}();
+  b.{self::B::method}();
+}
diff --git a/pkg/front_end/testcases/closure.dart.direct.expect b/pkg/front_end/testcases/closure.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/closure.dart.direct.expect
rename to pkg/front_end/testcases/closure.dart.legacy.expect
diff --git a/pkg/front_end/testcases/closure.dart.direct.transformed.expect b/pkg/front_end/testcases/closure.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/closure.dart.direct.transformed.expect
rename to pkg/front_end/testcases/closure.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/closure.dart.strong.expect b/pkg/front_end/testcases/closure.dart.strong.expect
index 936ac03..0f3d05d 100644
--- a/pkg/front_end/testcases/closure.dart.strong.expect
+++ b/pkg/front_end/testcases/closure.dart.strong.expect
@@ -4,12 +4,12 @@
 
 class Foo extends core::Object {
   field self::Bar _field = new self::Bar::•();
-  synthetic constructor •() → void
+  synthetic constructor •() → self::Foo
     : super core::Object::•()
     ;
 }
 class Bar extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::Bar
     : super core::Object::•()
     ;
 }
@@ -18,7 +18,7 @@
 }
 static method main() → dynamic {
   dynamic x;
-  function inner() → dynamic {
+  function inner() → self::Foo {
     x = new self::Foo::•();
     return new self::Foo::•();
   }
diff --git a/pkg/front_end/testcases/closure.dart.strong.transformed.expect b/pkg/front_end/testcases/closure.dart.strong.transformed.expect
new file mode 100644
index 0000000..0f3d05d
--- /dev/null
+++ b/pkg/front_end/testcases/closure.dart.strong.transformed.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  field self::Bar _field = new self::Bar::•();
+  synthetic constructor •() → self::Foo
+    : super core::Object::•()
+    ;
+}
+class Bar extends core::Object {
+  synthetic constructor •() → self::Bar
+    : super core::Object::•()
+    ;
+}
+static method useCallback(dynamic callback) → dynamic {
+  dynamic _ = callback.call();
+}
+static method main() → dynamic {
+  dynamic x;
+  function inner() → self::Foo {
+    x = new self::Foo::•();
+    return new self::Foo::•();
+  }
+  self::useCallback(inner);
+  self::Bar _ = inner.call().{self::Foo::_field};
+}
diff --git a/pkg/front_end/testcases/closure.dart.type_promotion.expect b/pkg/front_end/testcases/closure.dart.type_promotion.expect
new file mode 100644
index 0000000..a0203a7
--- /dev/null
+++ b/pkg/front_end/testcases/closure.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/closure.dart:18:7: Context: Write to x@336
+    x = new Foo();
+      ^
diff --git a/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.direct.expect b/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.direct.expect
rename to pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.legacy.expect
diff --git a/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.direct.transformed.expect b/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.direct.transformed.expect
rename to pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/constructor_const_inference.dart.direct.expect b/pkg/front_end/testcases/constructor_const_inference.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/constructor_const_inference.dart.direct.expect
rename to pkg/front_end/testcases/constructor_const_inference.dart.legacy.expect
diff --git a/pkg/front_end/testcases/constructor_const_inference.dart.direct.transformed.expect b/pkg/front_end/testcases/constructor_const_inference.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/constructor_const_inference.dart.direct.transformed.expect
rename to pkg/front_end/testcases/constructor_const_inference.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/constructor_cycle.dart.direct.expect b/pkg/front_end/testcases/constructor_cycle.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/constructor_cycle.dart.direct.expect
rename to pkg/front_end/testcases/constructor_cycle.dart.legacy.expect
diff --git a/pkg/front_end/testcases/constructor_cycle.dart.direct.transformed.expect b/pkg/front_end/testcases/constructor_cycle.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/constructor_cycle.dart.direct.transformed.expect
rename to pkg/front_end/testcases/constructor_cycle.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/constructor_function_types.dart.direct.expect b/pkg/front_end/testcases/constructor_function_types.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/constructor_function_types.dart.direct.expect
rename to pkg/front_end/testcases/constructor_function_types.dart.legacy.expect
diff --git a/pkg/front_end/testcases/constructor_function_types.dart.direct.transformed.expect b/pkg/front_end/testcases/constructor_function_types.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/constructor_function_types.dart.direct.transformed.expect
rename to pkg/front_end/testcases/constructor_function_types.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/constructor_initializer_invalid.dart.direct.expect b/pkg/front_end/testcases/constructor_initializer_invalid.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/constructor_initializer_invalid.dart.direct.expect
rename to pkg/front_end/testcases/constructor_initializer_invalid.dart.legacy.expect
diff --git a/pkg/front_end/testcases/constructor_initializer_invalid.dart.direct.transformed.expect b/pkg/front_end/testcases/constructor_initializer_invalid.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/constructor_initializer_invalid.dart.direct.transformed.expect
rename to pkg/front_end/testcases/constructor_initializer_invalid.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/continue_inference_after_error.dart.direct.expect b/pkg/front_end/testcases/continue_inference_after_error.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/continue_inference_after_error.dart.direct.expect
rename to pkg/front_end/testcases/continue_inference_after_error.dart.legacy.expect
diff --git a/pkg/front_end/testcases/continue_inference_after_error.dart.direct.transformed.expect b/pkg/front_end/testcases/continue_inference_after_error.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/continue_inference_after_error.dart.direct.transformed.expect
rename to pkg/front_end/testcases/continue_inference_after_error.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/covariant_generic.dart.direct.expect b/pkg/front_end/testcases/covariant_generic.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/covariant_generic.dart.direct.expect
rename to pkg/front_end/testcases/covariant_generic.dart.legacy.expect
diff --git a/pkg/front_end/testcases/covariant_generic.dart.direct.transformed.expect b/pkg/front_end/testcases/covariant_generic.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/covariant_generic.dart.direct.transformed.expect
rename to pkg/front_end/testcases/covariant_generic.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/covariant_generic.dart.strong.expect b/pkg/front_end/testcases/covariant_generic.dart.strong.expect
index 1e99fae..fdbee87 100644
--- a/pkg/front_end/testcases/covariant_generic.dart.strong.expect
+++ b/pkg/front_end/testcases/covariant_generic.dart.strong.expect
@@ -2,25 +2,20 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo<T extends core::Object> extends core::Object {
+typedef Callback<T extends core::Object = dynamic> = (T) → void;
+class Foo<T extends core::Object = dynamic> extends core::Object {
   final field self::Foo::T finalField;
   final field (self::Foo::T) → void callbackField;
-  field self::Foo::T mutableField = null;
+  generic-covariant-impl field self::Foo::T mutableField = null;
   field (self::Foo::T) → void mutableCallbackField = null;
-  constructor •(self::Foo::T finalField, (self::Foo::T) → void callbackField) → void
+  constructor •(self::Foo::T finalField, (self::Foo::T) → void callbackField) → self::Foo<self::Foo::T>
     : self::Foo::finalField = finalField, self::Foo::callbackField = callbackField, super core::Object::•()
     ;
-  method method(self::Foo::T x) → void {}
-  set setter(self::Foo::T x) → void {}
+  method method(generic-covariant-impl self::Foo::T x) → void {}
+  set setter(generic-covariant-impl self::Foo::T x) → void {}
   method withCallback((self::Foo::T) → void callback) → void {
     callback.call(this.{self::Foo::finalField});
   }
-  set mutableField$cc(core::Object mutableField_) → dynamic
-    this.{=self::Foo::mutableField} = mutableField_ as self::Foo::T;
-  method method$cc(core::Object x) → void
-    this.{=self::Foo::method}(x as self::Foo::T);
-  set setter$cc(core::Object x) → void
-    this.{=self::Foo::setter} = x as self::Foo::T;
 }
 static method main() → dynamic {
   self::Foo<core::int> fooInt = new self::Foo::•<core::int>(1, (core::int x) → core::Null {});
@@ -31,14 +26,14 @@
   fooInt.{self::Foo::mutableField} = 3;
   fooInt.{self::Foo::mutableCallbackField} = (core::int x) → core::Null {};
   self::Foo<core::num> fooNum = fooInt;
-  fooNum.{self::Foo::method$cc}(3);
-  fooNum.{self::Foo::method$cc}(2.5);
-  fooNum.{self::Foo::setter$cc} = 3;
-  fooNum.{self::Foo::setter$cc} = 2.5;
+  fooNum.{self::Foo::method}(3);
+  fooNum.{self::Foo::method}(2.5);
+  fooNum.{self::Foo::setter} = 3;
+  fooNum.{self::Foo::setter} = 2.5;
   fooNum.{self::Foo::withCallback}((core::num x) → core::Null {});
-  fooNum.{self::Foo::mutableField$cc} = 3;
-  fooNum.{self::Foo::mutableField$cc} = 2.5;
-  fooNum.{self::Foo::mutableCallbackField}.call(3);
-  fooNum.{self::Foo::mutableCallbackField}.call(2.5);
+  fooNum.{self::Foo::mutableField} = 3;
+  fooNum.{self::Foo::mutableField} = 2.5;
+  (fooNum.{self::Foo::mutableCallbackField} as{TypeError} (core::num) → void).call(3);
+  (fooNum.{self::Foo::mutableCallbackField} as{TypeError} (core::num) → void).call(2.5);
   fooNum.{self::Foo::mutableCallbackField} = (core::num x) → core::Null {};
 }
diff --git a/pkg/front_end/testcases/covariant_generic.dart.strong.transformed.expect b/pkg/front_end/testcases/covariant_generic.dart.strong.transformed.expect
new file mode 100644
index 0000000..fdbee87
--- /dev/null
+++ b/pkg/front_end/testcases/covariant_generic.dart.strong.transformed.expect
@@ -0,0 +1,39 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Callback<T extends core::Object = dynamic> = (T) → void;
+class Foo<T extends core::Object = dynamic> extends core::Object {
+  final field self::Foo::T finalField;
+  final field (self::Foo::T) → void callbackField;
+  generic-covariant-impl field self::Foo::T mutableField = null;
+  field (self::Foo::T) → void mutableCallbackField = null;
+  constructor •(self::Foo::T finalField, (self::Foo::T) → void callbackField) → self::Foo<self::Foo::T>
+    : self::Foo::finalField = finalField, self::Foo::callbackField = callbackField, super core::Object::•()
+    ;
+  method method(generic-covariant-impl self::Foo::T x) → void {}
+  set setter(generic-covariant-impl self::Foo::T x) → void {}
+  method withCallback((self::Foo::T) → void callback) → void {
+    callback.call(this.{self::Foo::finalField});
+  }
+}
+static method main() → dynamic {
+  self::Foo<core::int> fooInt = new self::Foo::•<core::int>(1, (core::int x) → core::Null {});
+  fooInt.{self::Foo::method}(3);
+  fooInt.{self::Foo::setter} = 3;
+  fooInt.{self::Foo::withCallback}((core::int x) → core::Null {});
+  fooInt.{self::Foo::withCallback}((core::num x) → core::Null {});
+  fooInt.{self::Foo::mutableField} = 3;
+  fooInt.{self::Foo::mutableCallbackField} = (core::int x) → core::Null {};
+  self::Foo<core::num> fooNum = fooInt;
+  fooNum.{self::Foo::method}(3);
+  fooNum.{self::Foo::method}(2.5);
+  fooNum.{self::Foo::setter} = 3;
+  fooNum.{self::Foo::setter} = 2.5;
+  fooNum.{self::Foo::withCallback}((core::num x) → core::Null {});
+  fooNum.{self::Foo::mutableField} = 3;
+  fooNum.{self::Foo::mutableField} = 2.5;
+  (fooNum.{self::Foo::mutableCallbackField} as{TypeError} (core::num) → void).call(3);
+  (fooNum.{self::Foo::mutableCallbackField} as{TypeError} (core::num) → void).call(2.5);
+  fooNum.{self::Foo::mutableCallbackField} = (core::num x) → core::Null {};
+}
diff --git a/pkg/front_end/testcases/cycles.dart.direct.expect b/pkg/front_end/testcases/cycles.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/cycles.dart.direct.expect
rename to pkg/front_end/testcases/cycles.dart.legacy.expect
diff --git a/pkg/front_end/testcases/cycles.dart.direct.transformed.expect b/pkg/front_end/testcases/cycles.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/cycles.dart.direct.transformed.expect
rename to pkg/front_end/testcases/cycles.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/cycles.dart.direct.expect b/pkg/front_end/testcases/cycles.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/cycles.dart.direct.expect
copy to pkg/front_end/testcases/cycles.dart.strong.expect
diff --git a/pkg/front_end/testcases/cycles.dart.direct.transformed.expect b/pkg/front_end/testcases/cycles.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/cycles.dart.direct.transformed.expect
copy to pkg/front_end/testcases/cycles.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/default_values.dart.direct.expect b/pkg/front_end/testcases/default_values.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/default_values.dart.direct.expect
rename to pkg/front_end/testcases/default_values.dart.legacy.expect
diff --git a/pkg/front_end/testcases/default_values.dart.direct.transformed.expect b/pkg/front_end/testcases/default_values.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/default_values.dart.direct.transformed.expect
rename to pkg/front_end/testcases/default_values.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/default_values.dart.direct.expect b/pkg/front_end/testcases/default_values.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/default_values.dart.direct.expect
copy to pkg/front_end/testcases/default_values.dart.strong.expect
diff --git a/pkg/front_end/testcases/default_values.dart.direct.transformed.expect b/pkg/front_end/testcases/default_values.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/default_values.dart.direct.transformed.expect
copy to pkg/front_end/testcases/default_values.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/deferred_type_annotation.dart.direct.expect b/pkg/front_end/testcases/deferred_type_annotation.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/deferred_type_annotation.dart.direct.expect
rename to pkg/front_end/testcases/deferred_type_annotation.dart.legacy.expect
diff --git a/pkg/front_end/testcases/deferred_type_annotation.dart.direct.transformed.expect b/pkg/front_end/testcases/deferred_type_annotation.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/deferred_type_annotation.dart.direct.transformed.expect
rename to pkg/front_end/testcases/deferred_type_annotation.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/duplicated_bad_prefix.dart.direct.expect b/pkg/front_end/testcases/duplicated_bad_prefix.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/duplicated_bad_prefix.dart.direct.expect
rename to pkg/front_end/testcases/duplicated_bad_prefix.dart.legacy.expect
diff --git a/pkg/front_end/testcases/duplicated_bad_prefix.dart.direct.transformed.expect b/pkg/front_end/testcases/duplicated_bad_prefix.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/duplicated_bad_prefix.dart.direct.transformed.expect
rename to pkg/front_end/testcases/duplicated_bad_prefix.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/duplicated_declarations.dart.direct.expect b/pkg/front_end/testcases/duplicated_declarations.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/duplicated_declarations.dart.direct.expect
rename to pkg/front_end/testcases/duplicated_declarations.dart.legacy.expect
diff --git a/pkg/front_end/testcases/duplicated_declarations.dart.direct.transformed.expect b/pkg/front_end/testcases/duplicated_declarations.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/duplicated_declarations.dart.direct.transformed.expect
rename to pkg/front_end/testcases/duplicated_declarations.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/duplicated_field_initializer.dart b/pkg/front_end/testcases/duplicated_field_initializer.dart
new file mode 100644
index 0000000..fac68e9
--- /dev/null
+++ b/pkg/front_end/testcases/duplicated_field_initializer.dart
@@ -0,0 +1,13 @@
+// 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.
+
+class A {
+  int a;
+  int a;
+  A(this.a);
+}
+
+void main() {
+  A(1);
+}
diff --git a/pkg/front_end/testcases/duplicated_field_initializer.dart.legacy.expect b/pkg/front_end/testcases/duplicated_field_initializer.dart.legacy.expect
new file mode 100644
index 0000000..2c39c5e
--- /dev/null
+++ b/pkg/front_end/testcases/duplicated_field_initializer.dart.legacy.expect
@@ -0,0 +1,34 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/duplicated_field_initializer.dart:7:7: Error: 'a' is already declared in this scope.
+//   int a;
+//       ^
+// pkg/front_end/testcases/duplicated_field_initializer.dart:6:7: Context: Previous declaration of 'a'.
+//   int a;
+//       ^
+//
+// pkg/front_end/testcases/duplicated_field_initializer.dart:8:10: Error: Can't use 'a' because it is declared more than once.
+//   A(this.a);
+//          ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/duplicated_field_initializer.dart:7:7: Error: 'a' is already declared in this scope.
+//   int a;
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int a = null;
+  constructor •(core::int a) → self::A
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/duplicated_field_initializer.dart:8:10: Error: Can't use 'a' because it is declared more than once.
+  A(this.a);
+         ^", super core::Object::•()
+    ;
+}
+static method main() → void {
+  new self::A::•(1);
+}
diff --git a/pkg/front_end/testcases/duplicated_field_initializer.dart.legacy.transformed.expect b/pkg/front_end/testcases/duplicated_field_initializer.dart.legacy.transformed.expect
new file mode 100644
index 0000000..b3fa279
--- /dev/null
+++ b/pkg/front_end/testcases/duplicated_field_initializer.dart.legacy.transformed.expect
@@ -0,0 +1,21 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/duplicated_field_initializer.dart:7:7: Error: 'a' is already declared in this scope.
+//   int a;
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int a = null;
+  constructor •(core::int a) → self::A
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/duplicated_field_initializer.dart:8:10: Error: Can't use 'a' because it is declared more than once.
+  A(this.a);
+         ^", super core::Object::•()
+    ;
+}
+static method main() → void {
+  new self::A::•(1);
+}
diff --git a/pkg/front_end/testcases/duplicated_field_initializer.dart.outline.expect b/pkg/front_end/testcases/duplicated_field_initializer.dart.outline.expect
new file mode 100644
index 0000000..0d027ad
--- /dev/null
+++ b/pkg/front_end/testcases/duplicated_field_initializer.dart.outline.expect
@@ -0,0 +1,20 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/duplicated_field_initializer.dart:7:7: Error: 'a' is already declared in this scope.
+//   int a;
+//       ^
+// pkg/front_end/testcases/duplicated_field_initializer.dart:6:7: Context: Previous declaration of 'a'.
+//   int a;
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int a;
+  constructor •(core::int a) → self::A
+    ;
+}
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/duplicated_field_initializer.dart.strong.expect b/pkg/front_end/testcases/duplicated_field_initializer.dart.strong.expect
new file mode 100644
index 0000000..2c39c5e
--- /dev/null
+++ b/pkg/front_end/testcases/duplicated_field_initializer.dart.strong.expect
@@ -0,0 +1,34 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/duplicated_field_initializer.dart:7:7: Error: 'a' is already declared in this scope.
+//   int a;
+//       ^
+// pkg/front_end/testcases/duplicated_field_initializer.dart:6:7: Context: Previous declaration of 'a'.
+//   int a;
+//       ^
+//
+// pkg/front_end/testcases/duplicated_field_initializer.dart:8:10: Error: Can't use 'a' because it is declared more than once.
+//   A(this.a);
+//          ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/duplicated_field_initializer.dart:7:7: Error: 'a' is already declared in this scope.
+//   int a;
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int a = null;
+  constructor •(core::int a) → self::A
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/duplicated_field_initializer.dart:8:10: Error: Can't use 'a' because it is declared more than once.
+  A(this.a);
+         ^", super core::Object::•()
+    ;
+}
+static method main() → void {
+  new self::A::•(1);
+}
diff --git a/pkg/front_end/testcases/duplicated_field_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/duplicated_field_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..b3fa279
--- /dev/null
+++ b/pkg/front_end/testcases/duplicated_field_initializer.dart.strong.transformed.expect
@@ -0,0 +1,21 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/duplicated_field_initializer.dart:7:7: Error: 'a' is already declared in this scope.
+//   int a;
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int a = null;
+  constructor •(core::int a) → self::A
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/duplicated_field_initializer.dart:8:10: Error: Can't use 'a' because it is declared more than once.
+  A(this.a);
+         ^", super core::Object::•()
+    ;
+}
+static method main() → void {
+  new self::A::•(1);
+}
diff --git a/pkg/front_end/testcases/duplicated_named_args_3.dart.direct.expect b/pkg/front_end/testcases/duplicated_named_args_3.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/duplicated_named_args_3.dart.direct.expect
rename to pkg/front_end/testcases/duplicated_named_args_3.dart.legacy.expect
diff --git a/pkg/front_end/testcases/duplicated_named_args_3.dart.direct.transformed.expect b/pkg/front_end/testcases/duplicated_named_args_3.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/duplicated_named_args_3.dart.direct.transformed.expect
rename to pkg/front_end/testcases/duplicated_named_args_3.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/dynamic_and_void.dart.direct.expect b/pkg/front_end/testcases/dynamic_and_void.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/dynamic_and_void.dart.direct.expect
rename to pkg/front_end/testcases/dynamic_and_void.dart.legacy.expect
diff --git a/pkg/front_end/testcases/dynamic_and_void.dart.direct.transformed.expect b/pkg/front_end/testcases/dynamic_and_void.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/dynamic_and_void.dart.direct.transformed.expect
rename to pkg/front_end/testcases/dynamic_and_void.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/escape.dart.direct.expect b/pkg/front_end/testcases/escape.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/escape.dart.direct.expect
rename to pkg/front_end/testcases/escape.dart.legacy.expect
diff --git a/pkg/front_end/testcases/escape.dart.direct.transformed.expect b/pkg/front_end/testcases/escape.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/escape.dart.direct.transformed.expect
rename to pkg/front_end/testcases/escape.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/escape.dart.strong.expect b/pkg/front_end/testcases/escape.dart.strong.expect
index 4dfacb5..2a1b03e 100644
--- a/pkg/front_end/testcases/escape.dart.strong.expect
+++ b/pkg/front_end/testcases/escape.dart.strong.expect
@@ -4,19 +4,26 @@
 
 class A extends core::Object {
   field dynamic field = null;
-  synthetic constructor •() → void
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 }
 class B extends core::Object {
   field dynamic field = null;
-  synthetic constructor •() → void
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
 }
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  operator ==(dynamic x) → core::bool
+    return false;
+}
 class X extends core::Object implements self::A, self::B {
   field dynamic field = null;
-  synthetic constructor •() → void
+  synthetic constructor •() → self::X
     : super core::Object::•()
     ;
 }
@@ -28,8 +35,8 @@
   self::escape(object);
 }
 static method escape(dynamic x) → void {
-  x.==(null) ? x = "" : null;
-  x.==(null) ? x = 45 : null;
+  x.{core::Object::==}(null) ?{dynamic} x = "" : null;
+  x.{core::Object::==}(null) ?{dynamic} x = 45 : null;
   if(!(x is core::int) && !(x is core::String)) {
     x.field = 45;
   }
diff --git a/pkg/front_end/testcases/escape.dart.strong.transformed.expect b/pkg/front_end/testcases/escape.dart.strong.transformed.expect
new file mode 100644
index 0000000..2a1b03e
--- /dev/null
+++ b/pkg/front_end/testcases/escape.dart.strong.transformed.expect
@@ -0,0 +1,50 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic field = null;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  field dynamic field = null;
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  operator ==(dynamic x) → core::bool
+    return false;
+}
+class X extends core::Object implements self::A, self::B {
+  field dynamic field = null;
+  synthetic constructor •() → self::X
+    : super core::Object::•()
+    ;
+}
+static method useAsA(self::A object) → void {
+  dynamic _ = object.{self::A::field};
+}
+static method useAsB(self::B object) → void {
+  dynamic _ = object.{self::B::field};
+  self::escape(object);
+}
+static method escape(dynamic x) → void {
+  x.{core::Object::==}(null) ?{dynamic} x = "" : null;
+  x.{core::Object::==}(null) ?{dynamic} x = 45 : null;
+  if(!(x is core::int) && !(x is core::String)) {
+    x.field = 45;
+  }
+}
+static method main() → dynamic {
+  self::X object = new self::X::•();
+  self::useAsA(new self::A::•());
+  self::useAsA(object);
+  self::useAsB(new self::B::•());
+  self::useAsB(object);
+}
diff --git a/pkg/front_end/testcases/escape.dart.type_promotion.expect b/pkg/front_end/testcases/escape.dart.type_promotion.expect
new file mode 100644
index 0000000..ff163e6
--- /dev/null
+++ b/pkg/front_end/testcases/escape.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/escape.dart:31:5: Context: Write to x@483
+  x ??= "";
+    ^^^
+pkg/front_end/testcases/escape.dart:32:5: Context: Write to x@483
+  x ??= 45;
+    ^^^
diff --git a/pkg/front_end/testcases/export_main.dart.direct.expect b/pkg/front_end/testcases/export_main.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/export_main.dart.direct.expect
rename to pkg/front_end/testcases/export_main.dart.legacy.expect
diff --git a/pkg/front_end/testcases/export_main.dart.direct.transformed.expect b/pkg/front_end/testcases/export_main.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/export_main.dart.direct.transformed.expect
rename to pkg/front_end/testcases/export_main.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/export_test.dart.direct.expect b/pkg/front_end/testcases/export_test.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/export_test.dart.direct.expect
rename to pkg/front_end/testcases/export_test.dart.legacy.expect
diff --git a/pkg/front_end/testcases/export_test.dart.direct.transformed.expect b/pkg/front_end/testcases/export_test.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/export_test.dart.direct.transformed.expect
rename to pkg/front_end/testcases/export_test.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/expressions.dart.direct.expect b/pkg/front_end/testcases/expressions.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/expressions.dart.direct.expect
rename to pkg/front_end/testcases/expressions.dart.legacy.expect
diff --git a/pkg/front_end/testcases/expressions.dart.direct.transformed.expect b/pkg/front_end/testcases/expressions.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/expressions.dart.direct.transformed.expect
rename to pkg/front_end/testcases/expressions.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/expressions.dart.type_promotion.expect b/pkg/front_end/testcases/expressions.dart.type_promotion.expect
new file mode 100644
index 0000000..3692c63
--- /dev/null
+++ b/pkg/front_end/testcases/expressions.dart.type_promotion.expect
@@ -0,0 +1,15 @@
+pkg/front_end/testcases/expressions.dart:34:5: Context: Write to i@286
+  i = 87;
+    ^
+pkg/front_end/testcases/expressions.dart:38:9: Context: Write to i@286
+  print(--i);
+        ^^
+pkg/front_end/testcases/expressions.dart:39:9: Context: Write to i@286
+  print(++i);
+        ^^
+pkg/front_end/testcases/expressions.dart:40:10: Context: Write to i@286
+  print(i--);
+         ^^
+pkg/front_end/testcases/expressions.dart:41:10: Context: Write to i@286
+  print(i++);
+         ^^
diff --git a/pkg/front_end/testcases/external.dart.direct.expect b/pkg/front_end/testcases/external.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/external.dart.direct.expect
rename to pkg/front_end/testcases/external.dart.legacy.expect
diff --git a/pkg/front_end/testcases/external.dart.direct.transformed.expect b/pkg/front_end/testcases/external.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/external.dart.direct.transformed.expect
rename to pkg/front_end/testcases/external.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/external.dart.strong.expect b/pkg/front_end/testcases/external.dart.strong.expect
index e4d6f84..e4daff6 100644
--- a/pkg/front_end/testcases/external.dart.strong.expect
+++ b/pkg/front_end/testcases/external.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 import "dart:isolate" as iso;
 
-static field dynamic subscription = null;
+static field dynamic subscription;
 static method onData(dynamic x) → void {
   core::print(x);
   self::subscription.cancel();
diff --git a/pkg/front_end/testcases/external.dart.strong.transformed.expect b/pkg/front_end/testcases/external.dart.strong.transformed.expect
new file mode 100644
index 0000000..e4daff6
--- /dev/null
+++ b/pkg/front_end/testcases/external.dart.strong.transformed.expect
@@ -0,0 +1,16 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:isolate" as iso;
+
+static field dynamic subscription;
+static method onData(dynamic x) → void {
+  core::print(x);
+  self::subscription.cancel();
+}
+static method main() → dynamic {
+  core::String string = core::String::fromCharCode(65);
+  iso::ReceivePort port = iso::ReceivePort::•();
+  self::subscription = port.{iso::ReceivePort::listen}(self::onData);
+  port.{iso::ReceivePort::sendPort}.{iso::SendPort::send}(string);
+}
diff --git a/pkg/front_end/testcases/external_import.dart.direct.expect b/pkg/front_end/testcases/external_import.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/external_import.dart.direct.expect
rename to pkg/front_end/testcases/external_import.dart.legacy.expect
diff --git a/pkg/front_end/testcases/external_import.dart.direct.transformed.expect b/pkg/front_end/testcases/external_import.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/external_import.dart.direct.transformed.expect
rename to pkg/front_end/testcases/external_import.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/fallthrough.dart.direct.expect b/pkg/front_end/testcases/fallthrough.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/fallthrough.dart.direct.expect
rename to pkg/front_end/testcases/fallthrough.dart.legacy.expect
diff --git a/pkg/front_end/testcases/fallthrough.dart.strong.expect b/pkg/front_end/testcases/fallthrough.dart.strong.expect
index 8c544b3..b4eb852 100644
--- a/pkg/front_end/testcases/fallthrough.dart.strong.expect
+++ b/pkg/front_end/testcases/fallthrough.dart.strong.expect
@@ -1,3 +1,23 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/fallthrough.dart:8:5: Error: Switch case may fall through to the next case.
+//     case 3:
+//     ^
+//
+// pkg/front_end/testcases/fallthrough.dart:12:5: Error: Switch case may fall through to the next case.
+//     case 6:
+//     ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/fallthrough.dart:8:5: Error: Switch case may fall through to the next case.
+//     case 3:
+//     ^
+//
+// pkg/front_end/testcases/fallthrough.dart:12:5: Error: Switch case may fall through to the next case.
+//     case 6:
+//     ^
+
 library;
 import self as self;
 import "dart:core" as core;
@@ -10,7 +30,7 @@
     case 3:
       {
         x = 4;
-        throw new core::FallThroughError::•();
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///fallthrough.dart", 8);
       }
     #L3:
     case 5:
@@ -27,7 +47,7 @@
         else {
           return;
         }
-        throw new core::FallThroughError::•();
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///fallthrough.dart", 12);
       }
     #L5:
     case 4:
diff --git a/pkg/front_end/testcases/fallthrough.dart.type_promotion.expect b/pkg/front_end/testcases/fallthrough.dart.type_promotion.expect
new file mode 100644
index 0000000..a753f8b
--- /dev/null
+++ b/pkg/front_end/testcases/fallthrough.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/fallthrough.dart:9:9: Context: Write to x@254
+      x = 4;
+        ^
diff --git a/pkg/front_end/testcases/fibonacci.dart.direct.expect b/pkg/front_end/testcases/fibonacci.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/fibonacci.dart.direct.expect
rename to pkg/front_end/testcases/fibonacci.dart.legacy.expect
diff --git a/pkg/front_end/testcases/fibonacci.dart.direct.transformed.expect b/pkg/front_end/testcases/fibonacci.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/fibonacci.dart.direct.transformed.expect
rename to pkg/front_end/testcases/fibonacci.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/fibonacci.dart.strong.expect b/pkg/front_end/testcases/fibonacci.dart.strong.expect
new file mode 100644
index 0000000..6b654e5
--- /dev/null
+++ b/pkg/front_end/testcases/fibonacci.dart.strong.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method fibonacci(core::int n) → core::int {
+  if(n.{core::num::<}(2))
+    return n;
+  return self::fibonacci(n.{core::num::-}(1)).{core::num::+}(self::fibonacci(n.{core::num::-}(2)));
+}
+static method main() → dynamic {
+  for (core::int i = 0; i.{core::num::<}(20); i = i.{core::num::+}(1)) {
+    core::print(self::fibonacci(i));
+  }
+}
diff --git a/pkg/front_end/testcases/fibonacci.dart.strong.transformed.expect b/pkg/front_end/testcases/fibonacci.dart.strong.transformed.expect
new file mode 100644
index 0000000..6b654e5
--- /dev/null
+++ b/pkg/front_end/testcases/fibonacci.dart.strong.transformed.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method fibonacci(core::int n) → core::int {
+  if(n.{core::num::<}(2))
+    return n;
+  return self::fibonacci(n.{core::num::-}(1)).{core::num::+}(self::fibonacci(n.{core::num::-}(2)));
+}
+static method main() → dynamic {
+  for (core::int i = 0; i.{core::num::<}(20); i = i.{core::num::+}(1)) {
+    core::print(self::fibonacci(i));
+  }
+}
diff --git a/pkg/front_end/testcases/fibonacci.dart.type_promotion.expect b/pkg/front_end/testcases/fibonacci.dart.type_promotion.expect
new file mode 100644
index 0000000..42ffb08
--- /dev/null
+++ b/pkg/front_end/testcases/fibonacci.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/fibonacci.dart:11:28: Context: Write to i@332
+  for (int i = 0; i < 20; i++) {
+                           ^^
diff --git a/pkg/front_end/testcases/for_in_scope.dart.direct.expect b/pkg/front_end/testcases/for_in_scope.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/for_in_scope.dart.direct.expect
rename to pkg/front_end/testcases/for_in_scope.dart.legacy.expect
diff --git a/pkg/front_end/testcases/for_in_scope.dart.direct.transformed.expect b/pkg/front_end/testcases/for_in_scope.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/for_in_scope.dart.direct.transformed.expect
rename to pkg/front_end/testcases/for_in_scope.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/for_in_scope.dart.direct.expect b/pkg/front_end/testcases/for_in_scope.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/for_in_scope.dart.direct.expect
copy to pkg/front_end/testcases/for_in_scope.dart.strong.expect
diff --git a/pkg/front_end/testcases/for_in_scope.dart.direct.transformed.expect b/pkg/front_end/testcases/for_in_scope.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/for_in_scope.dart.direct.transformed.expect
copy to pkg/front_end/testcases/for_in_scope.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/function_in_field.dart.direct.expect b/pkg/front_end/testcases/function_in_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/function_in_field.dart.direct.expect
rename to pkg/front_end/testcases/function_in_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/function_in_field.dart.direct.transformed.expect b/pkg/front_end/testcases/function_in_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/function_in_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/function_in_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/function_in_field.dart.strong.expect b/pkg/front_end/testcases/function_in_field.dart.strong.expect
new file mode 100644
index 0000000..4cbb448
--- /dev/null
+++ b/pkg/front_end/testcases/function_in_field.dart.strong.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static field () → core::int x = () → core::int {
+  core::int y = 42;
+  return y;
+};
+static method main() → dynamic {
+  core::print(self::x.call());
+}
diff --git a/pkg/front_end/testcases/function_in_field.dart.strong.transformed.expect b/pkg/front_end/testcases/function_in_field.dart.strong.transformed.expect
new file mode 100644
index 0000000..4cbb448
--- /dev/null
+++ b/pkg/front_end/testcases/function_in_field.dart.strong.transformed.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static field () → core::int x = () → core::int {
+  core::int y = 42;
+  return y;
+};
+static method main() → dynamic {
+  core::print(self::x.call());
+}
diff --git a/pkg/front_end/testcases/function_type_default_value.dart.direct.expect b/pkg/front_end/testcases/function_type_default_value.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/function_type_default_value.dart.direct.expect
rename to pkg/front_end/testcases/function_type_default_value.dart.legacy.expect
diff --git a/pkg/front_end/testcases/function_type_default_value.dart.direct.transformed.expect b/pkg/front_end/testcases/function_type_default_value.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/function_type_default_value.dart.direct.transformed.expect
rename to pkg/front_end/testcases/function_type_default_value.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/function_type_is_check.dart.direct.expect b/pkg/front_end/testcases/function_type_is_check.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/function_type_is_check.dart.direct.expect
rename to pkg/front_end/testcases/function_type_is_check.dart.legacy.expect
diff --git a/pkg/front_end/testcases/function_type_is_check.dart.direct.transformed.expect b/pkg/front_end/testcases/function_type_is_check.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/function_type_is_check.dart.direct.transformed.expect
rename to pkg/front_end/testcases/function_type_is_check.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/function_type_is_check.dart.type_promotion.expect b/pkg/front_end/testcases/function_type_is_check.dart.type_promotion.expect
new file mode 100644
index 0000000..9ad971a
--- /dev/null
+++ b/pkg/front_end/testcases/function_type_is_check.dart.type_promotion.expect
@@ -0,0 +1,9 @@
+pkg/front_end/testcases/function_type_is_check.dart:8:9: Context: Possible promotion of f@272
+  if (f is void Function(Object, StackTrace)) return 1;
+        ^^
+pkg/front_end/testcases/function_type_is_check.dart:9:9: Context: Possible promotion of f@272
+  if (f is void Function(Object)) return 10;
+        ^^
+pkg/front_end/testcases/function_type_is_check.dart:10:9: Context: Possible promotion of f@272
+  if (f is void Function()) return 100;
+        ^^
diff --git a/pkg/front_end/testcases/function_type_recovery.dart.strong.expect b/pkg/front_end/testcases/function_type_recovery.dart.strong.expect
new file mode 100644
index 0000000..ff7a407
--- /dev/null
+++ b/pkg/front_end/testcases/function_type_recovery.dart.strong.expect
@@ -0,0 +1,33 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/function_type_recovery.dart:8:31: Error: Inline function types cannot be used for parameters in a generic function type.
+// Try changing the inline function type (as in 'int f()') to a prefixed function type using the `Function` keyword (as in 'int Function() f').
+// typedef F = int Function(int f(String x));
+//                               ^
+//
+// pkg/front_end/testcases/function_type_recovery.dart:12:27: Error: Inline function types cannot be used for parameters in a generic function type.
+// Try changing the inline function type (as in 'int f()') to a prefixed function type using the `Function` keyword (as in 'int Function() f').
+//   String Function(String g(int y)) g = null;
+//                           ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/function_type_recovery.dart:8:31: Error: Inline function types cannot be used for parameters in a generic function type.
+// Try changing the inline function type (as in 'int f()') to a prefixed function type using the `Function` keyword (as in 'int Function() f').
+// typedef F = int Function(int f(String x));
+//                               ^
+//
+// pkg/front_end/testcases/function_type_recovery.dart:12:27: Error: Inline function types cannot be used for parameters in a generic function type.
+// Try changing the inline function type (as in 'int f()') to a prefixed function type using the `Function` keyword (as in 'int Function() f').
+//   String Function(String g(int y)) g = null;
+//                           ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F = ((core::String) → core::int) → core::int;
+static method main() → dynamic {
+  ((core::String) → core::int) → core::int f = null;
+  ((core::int) → core::String) → core::String g = null;
+}
diff --git a/pkg/front_end/testcases/function_type_recovery.dart.strong.transformed.expect b/pkg/front_end/testcases/function_type_recovery.dart.strong.transformed.expect
new file mode 100644
index 0000000..cc3bac0
--- /dev/null
+++ b/pkg/front_end/testcases/function_type_recovery.dart.strong.transformed.expect
@@ -0,0 +1,21 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/function_type_recovery.dart:8:31: Error: Inline function types cannot be used for parameters in a generic function type.
+// Try changing the inline function type (as in 'int f()') to a prefixed function type using the `Function` keyword (as in 'int Function() f').
+// typedef F = int Function(int f(String x));
+//                               ^
+//
+// pkg/front_end/testcases/function_type_recovery.dart:12:27: Error: Inline function types cannot be used for parameters in a generic function type.
+// Try changing the inline function type (as in 'int f()') to a prefixed function type using the `Function` keyword (as in 'int Function() f').
+//   String Function(String g(int y)) g = null;
+//                           ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F = ((core::String) → core::int) → core::int;
+static method main() → dynamic {
+  ((core::String) → core::int) → core::int f = null;
+  ((core::int) → core::String) → core::String g = null;
+}
diff --git a/pkg/front_end/testcases/functions.dart.direct.expect b/pkg/front_end/testcases/functions.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/functions.dart.direct.expect
rename to pkg/front_end/testcases/functions.dart.legacy.expect
diff --git a/pkg/front_end/testcases/functions.dart.direct.transformed.expect b/pkg/front_end/testcases/functions.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/functions.dart.direct.transformed.expect
rename to pkg/front_end/testcases/functions.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/functions.dart.strong.expect b/pkg/front_end/testcases/functions.dart.strong.expect
new file mode 100644
index 0000000..500ef71
--- /dev/null
+++ b/pkg/front_end/testcases/functions.dart.strong.expect
@@ -0,0 +1,13 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  function local(({a: dynamic}) → void f) → void {
+    f.call(a: "Hello, World");
+    f.call();
+  }
+  local.call(({dynamic a = "Default greeting!"}) → core::Null {
+    core::print(a);
+  });
+}
diff --git a/pkg/front_end/testcases/functions.dart.strong.transformed.expect b/pkg/front_end/testcases/functions.dart.strong.transformed.expect
new file mode 100644
index 0000000..500ef71
--- /dev/null
+++ b/pkg/front_end/testcases/functions.dart.strong.transformed.expect
@@ -0,0 +1,13 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  function local(({a: dynamic}) → void f) → void {
+    f.call(a: "Hello, World");
+    f.call();
+  }
+  local.call(({dynamic a = "Default greeting!"}) → core::Null {
+    core::print(a);
+  });
+}
diff --git a/pkg/front_end/testcases/future_or_test.dart.direct.expect b/pkg/front_end/testcases/future_or_test.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/future_or_test.dart.direct.expect
rename to pkg/front_end/testcases/future_or_test.dart.legacy.expect
diff --git a/pkg/front_end/testcases/future_or_test.dart.direct.transformed.expect b/pkg/front_end/testcases/future_or_test.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/future_or_test.dart.direct.transformed.expect
rename to pkg/front_end/testcases/future_or_test.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/hello.dart.direct.expect b/pkg/front_end/testcases/hello.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/hello.dart.direct.expect
rename to pkg/front_end/testcases/hello.dart.legacy.expect
diff --git a/pkg/front_end/testcases/hello.dart.direct.transformed.expect b/pkg/front_end/testcases/hello.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/hello.dart.direct.transformed.expect
rename to pkg/front_end/testcases/hello.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/hello.dart.direct.expect b/pkg/front_end/testcases/hello.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/hello.dart.direct.expect
copy to pkg/front_end/testcases/hello.dart.strong.expect
diff --git a/pkg/front_end/testcases/hello.dart.direct.transformed.expect b/pkg/front_end/testcases/hello.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/hello.dart.direct.transformed.expect
copy to pkg/front_end/testcases/hello.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/illegal_named_function_expression.dart.direct.expect b/pkg/front_end/testcases/illegal_named_function_expression.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/illegal_named_function_expression.dart.direct.expect
rename to pkg/front_end/testcases/illegal_named_function_expression.dart.legacy.expect
diff --git a/pkg/front_end/testcases/illegal_named_function_expression.dart.direct.transformed.expect b/pkg/front_end/testcases/illegal_named_function_expression.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/illegal_named_function_expression.dart.direct.transformed.expect
rename to pkg/front_end/testcases/illegal_named_function_expression.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/illegal_named_function_expression_scope.dart.direct.expect b/pkg/front_end/testcases/illegal_named_function_expression_scope.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/illegal_named_function_expression_scope.dart.direct.expect
rename to pkg/front_end/testcases/illegal_named_function_expression_scope.dart.legacy.expect
diff --git a/pkg/front_end/testcases/illegal_named_function_expression_scope.dart.direct.transformed.expect b/pkg/front_end/testcases/illegal_named_function_expression_scope.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/illegal_named_function_expression_scope.dart.direct.transformed.expect
rename to pkg/front_end/testcases/illegal_named_function_expression_scope.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/implicit_const_with_static_fields.dart.direct.expect b/pkg/front_end/testcases/implicit_const_with_static_fields.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/implicit_const_with_static_fields.dart.direct.expect
rename to pkg/front_end/testcases/implicit_const_with_static_fields.dart.legacy.expect
diff --git a/pkg/front_end/testcases/implicit_const_with_static_fields.dart.direct.transformed.expect b/pkg/front_end/testcases/implicit_const_with_static_fields.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/implicit_const_with_static_fields.dart.direct.transformed.expect
rename to pkg/front_end/testcases/implicit_const_with_static_fields.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/implicit_new.dart.direct.expect b/pkg/front_end/testcases/implicit_new.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/implicit_new.dart.direct.expect
rename to pkg/front_end/testcases/implicit_new.dart.legacy.expect
diff --git a/pkg/front_end/testcases/implicit_new.dart.direct.transformed.expect b/pkg/front_end/testcases/implicit_new.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/implicit_new.dart.direct.transformed.expect
rename to pkg/front_end/testcases/implicit_new.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/implicit_new.dart.type_promotion.expect b/pkg/front_end/testcases/implicit_new.dart.type_promotion.expect
new file mode 100644
index 0000000..33f7ebc
--- /dev/null
+++ b/pkg/front_end/testcases/implicit_new.dart.type_promotion.expect
@@ -0,0 +1,12 @@
+pkg/front_end/testcases/implicit_new.dart:31:5: Context: Write to x@522
+  x = prefix.Foo();
+    ^
+pkg/front_end/testcases/implicit_new.dart:33:5: Context: Write to z@559
+  z = prefix.Bar.named();
+    ^
+pkg/front_end/testcases/implicit_new.dart:39:5: Context: Write to l@682
+  l = [prefix.Foo(), prefix.Bar.named()];
+    ^
+pkg/front_end/testcases/implicit_new.dart:41:5: Context: Write to m@756
+  m = {"foo": prefix.Foo(), "bar": prefix.Bar.named()};
+    ^
diff --git a/pkg/front_end/testcases/implicit_scope_test.dart.direct.expect b/pkg/front_end/testcases/implicit_scope_test.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/implicit_scope_test.dart.direct.expect
rename to pkg/front_end/testcases/implicit_scope_test.dart.legacy.expect
diff --git a/pkg/front_end/testcases/implicit_scope_test.dart.direct.transformed.expect b/pkg/front_end/testcases/implicit_scope_test.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/implicit_scope_test.dart.direct.transformed.expect
rename to pkg/front_end/testcases/implicit_scope_test.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/implicit_scope_test.dart.type_promotion.expect b/pkg/front_end/testcases/implicit_scope_test.dart.type_promotion.expect
new file mode 100644
index 0000000..cf8d11a
--- /dev/null
+++ b/pkg/front_end/testcases/implicit_scope_test.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/implicit_scope_test.dart:28:30: Context: Write to i@736
+    for (int i = 0; i < 10; i++) var a = "bar", b = "baz";
+                             ^^
diff --git a/pkg/front_end/testcases/implicit_this.dart.direct.expect b/pkg/front_end/testcases/implicit_this.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/implicit_this.dart.direct.expect
rename to pkg/front_end/testcases/implicit_this.dart.legacy.expect
diff --git a/pkg/front_end/testcases/implicit_this.dart.direct.transformed.expect b/pkg/front_end/testcases/implicit_this.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/implicit_this.dart.direct.transformed.expect
rename to pkg/front_end/testcases/implicit_this.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/implicit_this.dart.strong.expect b/pkg/front_end/testcases/implicit_this.dart.strong.expect
new file mode 100644
index 0000000..fca414d
--- /dev/null
+++ b/pkg/front_end/testcases/implicit_this.dart.strong.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  method m() → dynamic {
+    core::print("Called m");
+  }
+  method testC() → dynamic {
+    this.{self::C::m}();
+  }
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+  method testD() → dynamic {
+    this.{self::C::m}();
+  }
+}
+static method main() → dynamic {
+  new self::C::•().{self::C::testC}();
+  new self::D::•().{self::D::testD}();
+}
diff --git a/pkg/front_end/testcases/implicit_this.dart.strong.transformed.expect b/pkg/front_end/testcases/implicit_this.dart.strong.transformed.expect
new file mode 100644
index 0000000..fca414d
--- /dev/null
+++ b/pkg/front_end/testcases/implicit_this.dart.strong.transformed.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  method m() → dynamic {
+    core::print("Called m");
+  }
+  method testC() → dynamic {
+    this.{self::C::m}();
+  }
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+  method testD() → dynamic {
+    this.{self::C::m}();
+  }
+}
+static method main() → dynamic {
+  new self::C::•().{self::C::testC}();
+  new self::D::•().{self::D::testD}();
+}
diff --git a/pkg/front_end/testcases/incomplete_field_formal_parameter.dart.strong.expect b/pkg/front_end/testcases/incomplete_field_formal_parameter.dart.strong.expect
new file mode 100644
index 0000000..9b7ba9d
--- /dev/null
+++ b/pkg/front_end/testcases/incomplete_field_formal_parameter.dart.strong.expect
@@ -0,0 +1,70 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:6:11: Error: Expected '.' before this.
+//   C.a(this);
+//           ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:6:11: Error: Expected an identifier, but got ')'.
+//   C.a(this);
+//           ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:7:12: Error: Expected an identifier, but got ')'.
+//   C.b(this.);
+//            ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:8:11: Error: Expected '.' before this.
+//   C.c(this, p);
+//           ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:8:11: Error: Expected an identifier, but got ','.
+//   C.c(this, p);
+//           ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:9:12: Error: Expected an identifier, but got ','.
+//   C.d(this., p);
+//            ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:6:11: Error: Expected '.' before this.
+//   C.a(this);
+//           ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:6:11: Error: Expected an identifier, but got ')'.
+//   C.a(this);
+//           ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:7:12: Error: Expected an identifier, but got ')'.
+//   C.b(this.);
+//            ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:8:11: Error: Expected '.' before this.
+//   C.c(this, p);
+//           ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:8:11: Error: Expected an identifier, but got ','.
+//   C.c(this, p);
+//           ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:9:12: Error: Expected an identifier, but got ','.
+//   C.d(this., p);
+//            ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor a() → self::C
+    : super core::Object::•()
+    ;
+  constructor b() → self::C
+    : super core::Object::•()
+    ;
+  constructor c() → self::C
+    : super core::Object::•()
+    ;
+  constructor d() → self::C
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/incomplete_field_formal_parameter.dart.strong.transformed.expect b/pkg/front_end/testcases/incomplete_field_formal_parameter.dart.strong.transformed.expect
new file mode 100644
index 0000000..6bcd2e6
--- /dev/null
+++ b/pkg/front_end/testcases/incomplete_field_formal_parameter.dart.strong.transformed.expect
@@ -0,0 +1,44 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:6:11: Error: Expected '.' before this.
+//   C.a(this);
+//           ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:6:11: Error: Expected an identifier, but got ')'.
+//   C.a(this);
+//           ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:7:12: Error: Expected an identifier, but got ')'.
+//   C.b(this.);
+//            ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:8:11: Error: Expected '.' before this.
+//   C.c(this, p);
+//           ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:8:11: Error: Expected an identifier, but got ','.
+//   C.c(this, p);
+//           ^
+//
+// pkg/front_end/testcases/incomplete_field_formal_parameter.dart:9:12: Error: Expected an identifier, but got ','.
+//   C.d(this., p);
+//            ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor a() → self::C
+    : super core::Object::•()
+    ;
+  constructor b() → self::C
+    : super core::Object::•()
+    ;
+  constructor c() → self::C
+    : super core::Object::•()
+    ;
+  constructor d() → self::C
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/incremental_bulk_compiler_full.status b/pkg/front_end/testcases/incremental_bulk_compiler_full.status
index d5e7324..3c112db 100644
--- a/pkg/front_end/testcases/incremental_bulk_compiler_full.status
+++ b/pkg/front_end/testcases/incremental_bulk_compiler_full.status
@@ -2,8 +2,13 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE.md file.
 language_2/deferred_super_dependency_test: Crash # missing "#errors"
+language_2/duplicate_export_collision_test: Crash # missing '#errors'
+language_2/import_nonexisting_dart_uri_test: Crash # missing '#errors'
+language_2/internal_library_test: Crash # non-identical '#errors'
 language_2/missing_part_of_tag_test: Crash # missing empty library that shouldn't have been there in the first place
+language_2/mixin_type_parameter_inference_error_test: Crash # non-identical '#errors'
 language_2/part_of_multiple_libs_test: Crash # missing "#errors"
+language_2/part_refers_to_core_library_test: Crash # non-identical '#errors'
 language_2/regress_27957_test: Crash # isSynthetic becomes false on C1 SuperInitializer.
 language_2/script1_negative_test: Crash # missing "#errors", missing empty library that shouldn't have been there in the first place
 language_2/script2_negative_test: Crash # missing "#errors", missing empty library that shouldn't have been there in the first place
diff --git a/pkg/front_end/testcases/inference/abstract_class_instantiation.dart.direct.expect b/pkg/front_end/testcases/inference/abstract_class_instantiation.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/abstract_class_instantiation.dart.direct.expect
rename to pkg/front_end/testcases/inference/abstract_class_instantiation.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/abstract_class_instantiation.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/abstract_class_instantiation.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/abstract_class_instantiation.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/abstract_class_instantiation.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/assert.dart.direct.expect b/pkg/front_end/testcases/inference/assert.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/assert.dart.direct.expect
rename to pkg/front_end/testcases/inference/assert.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/assert.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/assert.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/assert.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/assert.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/assert_initializer.dart.direct.expect b/pkg/front_end/testcases/inference/assert_initializer.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/assert_initializer.dart.direct.expect
rename to pkg/front_end/testcases/inference/assert_initializer.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/assert_initializer.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/assert_initializer.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/assert_initializer.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/assert_initializer.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/assign_local.dart.direct.expect b/pkg/front_end/testcases/inference/assign_local.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/assign_local.dart.direct.expect
rename to pkg/front_end/testcases/inference/assign_local.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/assign_local.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/assign_local.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/assign_local.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/assign_local.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/assign_local.dart.type_promotion.expect b/pkg/front_end/testcases/inference/assign_local.dart.type_promotion.expect
new file mode 100644
index 0000000..f49cffea
--- /dev/null
+++ b/pkg/front_end/testcases/inference/assign_local.dart.type_promotion.expect
@@ -0,0 +1,12 @@
+pkg/front_end/testcases/inference/assign_local.dart:14:29: Context: Write to x@320
+  var /*@type=int*/ x1 = (x = 1);
+                            ^
+pkg/front_end/testcases/inference/assign_local.dart:15:32: Context: Write to x@320
+  var /*@type=double*/ x2 = (x = 1.0);
+                               ^
+pkg/front_end/testcases/inference/assign_local.dart:18:32: Context: Write to y@406
+  var /*@type=A<int>*/ y1 = (y = new /*@typeArgs=int*/ A());
+                               ^
+pkg/front_end/testcases/inference/assign_local.dart:19:32: Context: Write to y@406
+  var /*@type=B<int>*/ y2 = (y = new /*@typeArgs=int*/ B());
+                               ^
diff --git a/pkg/front_end/testcases/inference/async_await.dart.direct.expect b/pkg/front_end/testcases/inference/async_await.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/async_await.dart.direct.expect
rename to pkg/front_end/testcases/inference/async_await.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/async_await.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/async_await.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/async_await.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/async_await.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.direct.expect b/pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.direct.expect
rename to pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.direct.expect b/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/async_closure_return_type_future.dart.direct.expect
rename to pkg/front_end/testcases/inference/async_closure_return_type_future.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/async_closure_return_type_future.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/async_closure_return_type_future.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.direct.expect b/pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.direct.expect
rename to pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_basic.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_basic.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_basic.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_basic.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_basic.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_basic.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_basic.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_basic.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_basic_void.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_basic_void.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_basic_void.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_basic_void.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_basic_void.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_basic_void.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_basic_void.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_basic_void.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart.type_promotion.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart.type_promotion.expect
new file mode 100644
index 0000000..d05a1c0
--- /dev/null
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference.dart:11:5: Context: Write to g@322
+  g = /*@returnType=String*/ () {
+    ^
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.type_promotion.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.type_promotion.expect
new file mode 100644
index 0000000..2c4de0d
--- /dev/null
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart:17:5: Context: Write to f@369
+  f = /*error:INVALID_CAST_FUNCTION_EXPR*/ /*@returnType=Null*/ (/*@type=Object*/ x) =>
+    ^
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_lub.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_lub.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_lub.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_lub.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_lub.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_lub.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_lub.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_lub.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_nested_lambdas.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_nested_lambdas.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_nested_lambdas.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_nested_lambdas.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_nested_lambdas.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_nested_lambdas.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_nested_lambdas.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_nested_lambdas.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_void_context.dart.direct.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_void_context.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_void_context.dart.direct.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_void_context.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_void_context.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_void_context.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/block_bodied_lambdas_void_context.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/block_bodied_lambdas_void_context.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/bottom.dart.direct.expect b/pkg/front_end/testcases/inference/bottom.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bottom.dart.direct.expect
rename to pkg/front_end/testcases/inference/bottom.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/bottom.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bottom.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bottom.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/bottom.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/bottom_in_closure.dart.direct.expect b/pkg/front_end/testcases/inference/bottom_in_closure.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bottom_in_closure.dart.direct.expect
rename to pkg/front_end/testcases/inference/bottom_in_closure.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/bottom_in_closure.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bottom_in_closure.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bottom_in_closure.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/bottom_in_closure.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/bug30251.dart.direct.expect b/pkg/front_end/testcases/inference/bug30251.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug30251.dart.direct.expect
rename to pkg/front_end/testcases/inference/bug30251.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/bug30251.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bug30251.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug30251.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/bug30251.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/bug30620.dart.direct.expect b/pkg/front_end/testcases/inference/bug30620.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug30620.dart.direct.expect
rename to pkg/front_end/testcases/inference/bug30620.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/bug30620.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bug30620.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug30620.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/bug30620.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/bug30620.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug30620.dart.type_promotion.expect
new file mode 100644
index 0000000..f995931
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug30620.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/bug30620.dart:14:13: Context: Possible promotion of other@335
+      other is A && /*@promotedType=A*/ other
+            ^^
diff --git a/pkg/front_end/testcases/inference/bug30620_b.dart.direct.expect b/pkg/front_end/testcases/inference/bug30620_b.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug30620_b.dart.direct.expect
rename to pkg/front_end/testcases/inference/bug30620_b.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/bug30620_b.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bug30620_b.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug30620_b.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/bug30620_b.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/bug30620_b.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug30620_b.dart.type_promotion.expect
new file mode 100644
index 0000000..85cca67
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug30620_b.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/bug30620_b.dart:14:13: Context: Possible promotion of other@335
+      other is A && /*@promotedType=A*/ other
+            ^^
diff --git a/pkg/front_end/testcases/inference/bug30620_c.dart.direct.expect b/pkg/front_end/testcases/inference/bug30620_c.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug30620_c.dart.direct.expect
rename to pkg/front_end/testcases/inference/bug30620_c.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/bug30620_c.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bug30620_c.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug30620_c.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/bug30620_c.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/bug30620_c.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug30620_c.dart.type_promotion.expect
new file mode 100644
index 0000000..3a22ae1
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug30620_c.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/bug30620_c.dart:14:15: Context: Possible promotion of other@335
+    if (other is A && /*@promotedType=A*/ other
+              ^^
diff --git a/pkg/front_end/testcases/inference/bug30620_d.dart.direct.expect b/pkg/front_end/testcases/inference/bug30620_d.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug30620_d.dart.direct.expect
rename to pkg/front_end/testcases/inference/bug30620_d.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/bug30620_d.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bug30620_d.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug30620_d.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/bug30620_d.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/bug30620_d.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug30620_d.dart.type_promotion.expect
new file mode 100644
index 0000000..bdbeb50
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug30620_d.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/bug30620_d.dart:8:24: Context: Possible promotion of obj@273
+String foo(obj) => obj is String
+                       ^^
diff --git a/pkg/front_end/testcases/inference/bug30624.dart.direct.expect b/pkg/front_end/testcases/inference/bug30624.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug30624.dart.direct.expect
rename to pkg/front_end/testcases/inference/bug30624.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/bug30624.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bug30624.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug30624.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/bug30624.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/bug31132.dart.direct.expect b/pkg/front_end/testcases/inference/bug31132.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug31132.dart.direct.expect
rename to pkg/front_end/testcases/inference/bug31132.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/bug31132.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bug31132.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug31132.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/bug31132.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/bug31132.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug31132.dart.type_promotion.expect
new file mode 100644
index 0000000..101f24d
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug31132.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/bug31132.dart:15:25: Context: Possible promotion of x@339
+  var /*@type=C*/ y = x is C ? /*@promotedType=C*/ x : new C();
+                        ^^
diff --git a/pkg/front_end/testcases/inference/bug31133.dart.direct.expect b/pkg/front_end/testcases/inference/bug31133.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug31133.dart.direct.expect
rename to pkg/front_end/testcases/inference/bug31133.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/bug31133.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bug31133.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug31133.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/bug31133.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/bug31133.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug31133.dart.type_promotion.expect
new file mode 100644
index 0000000..51f05ad
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug31133.dart.type_promotion.expect
@@ -0,0 +1,24 @@
+pkg/front_end/testcases/inference/bug31133.dart:10:9: Context: Write to i@296
+  for (i++; i /*@target=num::<*/ < 10; i++) {}
+        ^^
+pkg/front_end/testcases/inference/bug31133.dart:10:41: Context: Write to i@296
+  for (i++; i /*@target=num::<*/ < 10; i++) {}
+                                        ^^
+pkg/front_end/testcases/inference/bug31133.dart:11:8: Context: Write to i@296
+  for (++i; i /*@target=num::<*/ < 10; i++) {}
+       ^^
+pkg/front_end/testcases/inference/bug31133.dart:11:41: Context: Write to i@296
+  for (++i; i /*@target=num::<*/ < 10; i++) {}
+                                        ^^
+pkg/front_end/testcases/inference/bug31133.dart:12:9: Context: Write to i@296
+  for (i--; i /*@target=num::>=*/ >= 0; i--) {}
+        ^^
+pkg/front_end/testcases/inference/bug31133.dart:12:42: Context: Write to i@296
+  for (i--; i /*@target=num::>=*/ >= 0; i--) {}
+                                         ^^
+pkg/front_end/testcases/inference/bug31133.dart:13:8: Context: Write to i@296
+  for (--i; i /*@target=num::>=*/ >= 0; i--) {}
+       ^^
+pkg/front_end/testcases/inference/bug31133.dart:13:42: Context: Write to i@296
+  for (--i; i /*@target=num::>=*/ >= 0; i--) {}
+                                         ^^
diff --git a/pkg/front_end/testcases/inference/bug31436.dart.direct.expect b/pkg/front_end/testcases/inference/bug31436.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug31436.dart.direct.expect
rename to pkg/front_end/testcases/inference/bug31436.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/bug31436.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bug31436.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug31436.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/bug31436.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/bug31436.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug31436.dart.type_promotion.expect
new file mode 100644
index 0000000..c01ee24
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug31436.dart.type_promotion.expect
@@ -0,0 +1,48 @@
+pkg/front_end/testcases/inference/bug31436.dart:10:5: Context: Write to g@308
+  g = /*@returnType=List<Object>*/ () {
+    ^
+pkg/front_end/testcases/inference/bug31436.dart:13:12: Context: Possible promotion of g@308
+  assert(g is List<Object> Function());
+           ^^
+pkg/front_end/testcases/inference/bug31436.dart:17:5: Context: Write to g@308
+  g = /*@returnType=List<int>*/ () {
+    ^
+pkg/front_end/testcases/inference/bug31436.dart:20:12: Context: Possible promotion of g@308
+  assert(g is List<Object> Function());
+           ^^
+pkg/front_end/testcases/inference/bug31436.dart:21:12: Context: Possible promotion of g@308
+  assert(g is List<int> Function());
+           ^^
+pkg/front_end/testcases/inference/bug31436.dart:27:5: Context: Write to g@308
+  g = /*@returnType=List<Object>*/ () {
+    ^
+pkg/front_end/testcases/inference/bug31436.dart:30:12: Context: Possible promotion of g@308
+  assert(g is List<Object> Function());
+           ^^
+pkg/front_end/testcases/inference/bug31436.dart:34:5: Context: Write to o@843
+  o = 3;
+    ^
+pkg/front_end/testcases/inference/bug31436.dart:43:5: Context: Write to g@1305
+  g = /*@returnType=List<Object>*/ () => /*@typeArgs=Object*/ [3];
+    ^
+pkg/front_end/testcases/inference/bug31436.dart:44:12: Context: Possible promotion of g@1305
+  assert(g is List<Object> Function());
+           ^^
+pkg/front_end/testcases/inference/bug31436.dart:48:5: Context: Write to g@1305
+  g = /*@returnType=List<int>*/ () => l;
+    ^
+pkg/front_end/testcases/inference/bug31436.dart:49:12: Context: Possible promotion of g@1305
+  assert(g is List<Object> Function());
+           ^^
+pkg/front_end/testcases/inference/bug31436.dart:50:12: Context: Possible promotion of g@1305
+  assert(g is List<int> Function());
+           ^^
+pkg/front_end/testcases/inference/bug31436.dart:56:5: Context: Write to g@1305
+  g = /*@returnType=List<Object>*/ () =>
+    ^
+pkg/front_end/testcases/inference/bug31436.dart:58:12: Context: Possible promotion of g@1305
+  assert(g is List<Object> Function());
+           ^^
+pkg/front_end/testcases/inference/bug31436.dart:62:5: Context: Write to o@1810
+  o = 3;
+    ^
diff --git a/pkg/front_end/testcases/inference/bug32291.dart.direct.expect b/pkg/front_end/testcases/inference/bug32291.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug32291.dart.direct.expect
rename to pkg/front_end/testcases/inference/bug32291.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/bug32291.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bug32291.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug32291.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/bug32291.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/bug33324.dart.direct.expect b/pkg/front_end/testcases/inference/bug33324.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug33324.dart.direct.expect
rename to pkg/front_end/testcases/inference/bug33324.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/bug33324.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bug33324.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/bug33324.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/bug33324.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/call_corner_cases.dart.direct.expect b/pkg/front_end/testcases/inference/call_corner_cases.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/call_corner_cases.dart.direct.expect
rename to pkg/front_end/testcases/inference/call_corner_cases.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/call_corner_cases.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/call_corner_cases.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/call_corner_cases.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/call_corner_cases.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/callable_generic_class.dart.direct.expect b/pkg/front_end/testcases/inference/callable_generic_class.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/callable_generic_class.dart.direct.expect
rename to pkg/front_end/testcases/inference/callable_generic_class.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/callable_generic_class.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/callable_generic_class.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/callable_generic_class.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/callable_generic_class.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/circular_method_inference.dart.direct.expect b/pkg/front_end/testcases/inference/circular_method_inference.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/circular_method_inference.dart.direct.expect
rename to pkg/front_end/testcases/inference/circular_method_inference.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/circular_method_inference.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/circular_method_inference.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/circular_method_inference.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/circular_method_inference.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/circular_reference_via_closures.dart.direct.expect b/pkg/front_end/testcases/inference/circular_reference_via_closures.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/circular_reference_via_closures.dart.direct.expect
rename to pkg/front_end/testcases/inference/circular_reference_via_closures.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/circular_reference_via_closures.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/circular_reference_via_closures.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/circular_reference_via_closures.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/circular_reference_via_closures.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.direct.expect b/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.direct.expect
deleted file mode 100644
index fd3ef5e..0000000
--- a/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.direct.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-library test;
-import self as self;
-
-static field dynamic x = () → dynamic => self::y;
-static field dynamic y = () → dynamic => self::x;
-static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.direct.transformed.expect
deleted file mode 100644
index fd3ef5e..0000000
--- a/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.direct.transformed.expect
+++ /dev/null
@@ -1,6 +0,0 @@
-library test;
-import self as self;
-
-static field dynamic x = () → dynamic => self::y;
-static field dynamic y = () → dynamic => self::x;
-static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/circular_reference_via_closures.dart.direct.expect b/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.legacy.expect
similarity index 100%
copy from pkg/front_end/testcases/inference/circular_reference_via_closures.dart.direct.expect
copy to pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/circular_reference_via_closures.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.legacy.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/inference/circular_reference_via_closures.dart.direct.transformed.expect
copy to pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/closure_param_null_to_object.dart.direct.expect b/pkg/front_end/testcases/inference/closure_param_null_to_object.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/closure_param_null_to_object.dart.direct.expect
rename to pkg/front_end/testcases/inference/closure_param_null_to_object.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/closure_param_null_to_object.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/closure_param_null_to_object.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/closure_param_null_to_object.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/closure_param_null_to_object.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.direct.expect b/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.direct.expect
rename to pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/complex_predecrement.dart.direct.expect b/pkg/front_end/testcases/inference/complex_predecrement.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/complex_predecrement.dart.direct.expect
rename to pkg/front_end/testcases/inference/complex_predecrement.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/complex_predecrement.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/complex_predecrement.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/complex_predecrement.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/complex_predecrement.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/conditional_lub.dart.direct.expect b/pkg/front_end/testcases/inference/conditional_lub.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/conditional_lub.dart.direct.expect
rename to pkg/front_end/testcases/inference/conditional_lub.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/conditional_lub.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/conditional_lub.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/conditional_lub.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/conditional_lub.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/conditional_upwards_inference.dart.direct.expect b/pkg/front_end/testcases/inference/conditional_upwards_inference.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/conditional_upwards_inference.dart.direct.expect
rename to pkg/front_end/testcases/inference/conditional_upwards_inference.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/conditional_upwards_inference.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/conditional_upwards_inference.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/conditional_upwards_inference.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/conditional_upwards_inference.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.direct.expect b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/conflicts_can_happen.dart.direct.expect
rename to pkg/front_end/testcases/inference/conflicts_can_happen.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/conflicts_can_happen.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/conflicts_can_happen.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
index 55ed953..6cfda11 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
@@ -10,32 +10,32 @@
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1::a' is dynamic, which does not match the return type of the overridden method (test::I1).
-// Change to a subtype of test::I1.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1::a' is 'dynamic', which does not match the return type of the overridden method, 'test::I1'.
+// Change to a subtype of 'test::I1'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 // pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is the overridden method ('a').
 //   final I1 a = null;
 //            ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1::a' is dynamic, which does not match the return type of the overridden method (test::I2).
-// Change to a subtype of test::I2.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1::a' is 'dynamic', which does not match the return type of the overridden method, 'test::I2'.
+// Change to a subtype of 'test::I2'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 // pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is the overridden method ('a').
 //   final I2 a = null;
 //            ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2::a' is dynamic, which does not match the return type of the overridden method (test::I2).
-// Change to a subtype of test::I2.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2::a' is 'dynamic', which does not match the return type of the overridden method, 'test::I2'.
+// Change to a subtype of 'test::I2'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 // pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is the overridden method ('a').
 //   final I2 a = null;
 //            ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2::a' is dynamic, which does not match the return type of the overridden method (test::I1).
-// Change to a subtype of test::I1.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2::a' is 'dynamic', which does not match the return type of the overridden method, 'test::I1'.
+// Change to a subtype of 'test::I1'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 // pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is the overridden method ('a').
@@ -54,23 +54,23 @@
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1::a' is dynamic, which does not match the return type of the overridden method (test::I1).
-// Change to a subtype of test::I1.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1::a' is 'dynamic', which does not match the return type of the overridden method, 'test::I1'.
+// Change to a subtype of 'test::I1'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1::a' is dynamic, which does not match the return type of the overridden method (test::I2).
-// Change to a subtype of test::I2.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:163: Error: The return type of the method 'C1::a' is 'dynamic', which does not match the return type of the overridden method, 'test::I2'.
+// Change to a subtype of 'test::I2'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2::a' is dynamic, which does not match the return type of the overridden method (test::I2).
-// Change to a subtype of test::I2.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2::a' is 'dynamic', which does not match the return type of the overridden method, 'test::I2'.
+// Change to a subtype of 'test::I2'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2::a' is dynamic, which does not match the return type of the overridden method (test::I1).
-// Change to a subtype of test::I1.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:31:163: Error: The return type of the method 'C2::a' is 'dynamic', which does not match the return type of the overridden method, 'test::I1'.
+// Change to a subtype of 'test::I1'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.direct.expect b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/conflicts_can_happen2.dart.direct.expect
rename to pkg/front_end/testcases/inference/conflicts_can_happen2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/conflicts_can_happen2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/conflicts_can_happen2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
index d347006..48a22c7 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
@@ -5,16 +5,16 @@
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2::a' is dynamic, which does not match the return type of the overridden method (test::I1).
-// Change to a subtype of test::I1.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2::a' is 'dynamic', which does not match the return type of the overridden method, 'test::I1'.
+// Change to a subtype of 'test::I1'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 // pkg/front_end/testcases/inference/conflicts_can_happen2.dart:22:12: Context: This is the overridden method ('a').
 //   final I1 a = null;
 //            ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2::a' is dynamic, which does not match the return type of the overridden method (test::I2).
-// Change to a subtype of test::I2.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2::a' is 'dynamic', which does not match the return type of the overridden method, 'test::I2'.
+// Change to a subtype of 'test::I2'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 // pkg/front_end/testcases/inference/conflicts_can_happen2.dart:26:12: Context: This is the overridden method ('a').
@@ -28,13 +28,13 @@
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2::a' is dynamic, which does not match the return type of the overridden method (test::I1).
-// Change to a subtype of test::I1.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2::a' is 'dynamic', which does not match the return type of the overridden method, 'test::I1'.
+// Change to a subtype of 'test::I1'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2::a' is dynamic, which does not match the return type of the overridden method (test::I2).
-// Change to a subtype of test::I2.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:163: Error: The return type of the method 'C2::a' is 'dynamic', which does not match the return type of the overridden method, 'test::I2'.
+// Change to a subtype of 'test::I2'.
 //   get /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ a =>
 //                                                                                                                                                                   ^
 
diff --git a/pkg/front_end/testcases/inference/constructors_downwards_with_constraint.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_downwards_with_constraint.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_downwards_with_constraint.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_downwards_with_constraint.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_downwards_with_constraint.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_downwards_with_constraint.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_downwards_with_constraint.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_downwards_with_constraint.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_downwards_from_constructor.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_downwards_from_constructor.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_downwards_from_constructor.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_downwards_from_constructor.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_downwards_from_constructor.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_downwards_from_constructor.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_downwards_from_constructor.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_downwards_from_constructor.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory_calls_constructor.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory_calls_constructor.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory_calls_constructor.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory_calls_constructor.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory_calls_constructor.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory_calls_constructor.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory_calls_constructor.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_factory_calls_constructor.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_named.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_named.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_named.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_named.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_named.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_named.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_named.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_named.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_named_factory.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_named_factory.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_named_factory.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_named_factory.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_named_factory.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_named_factory.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_named_factory.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_named_factory.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_inference_f_bounded.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_inference_f_bounded.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_inference_f_bounded.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_inference_f_bounded.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_inference_f_bounded.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_inference_f_bounded.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_inference_f_bounded.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_inference_f_bounded.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_reverse_type_parameters.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_reverse_type_parameters.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_reverse_type_parameters.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_reverse_type_parameters.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/constructors_reverse_type_parameters.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/constructors_reverse_type_parameters.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_reverse_type_parameters.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/constructors_reverse_type_parameters.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/constructors_too_many_positional_arguments.dart.direct.expect b/pkg/front_end/testcases/inference/constructors_too_many_positional_arguments.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/constructors_too_many_positional_arguments.dart.direct.expect
rename to pkg/front_end/testcases/inference/constructors_too_many_positional_arguments.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.direct.expect b/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.direct.expect
rename to pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.strong.expect b/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.strong.expect
index 4e0da98..c074644 100644
--- a/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart.strong.expect
@@ -1,7 +1,7 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart:13:49: Error: The return type of the method 'B::x' is dynamic, which does not match the return type of the overridden method (dart.core::int).
-// Change to a subtype of dart.core::int.
+// pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart:13:49: Error: The return type of the method 'B::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::int'.
+// Change to a subtype of 'dart.core::int'.
 //   /*error:INVALID_METHOD_OVERRIDE*/ dynamic get x => 3;
 //                                                 ^
 // pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart:9:13: Context: This is the overridden method ('x').
@@ -10,8 +10,8 @@
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart:13:49: Error: The return type of the method 'B::x' is dynamic, which does not match the return type of the overridden method (dart.core::int).
-// Change to a subtype of dart.core::int.
+// pkg/front_end/testcases/inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer.dart:13:49: Error: The return type of the method 'B::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::int'.
+// Change to a subtype of 'dart.core::int'.
 //   /*error:INVALID_METHOD_OVERRIDE*/ dynamic get x => 3;
 //                                                 ^
 
diff --git a/pkg/front_end/testcases/inference/dont_infer_field_type_when_initializer_is_null.dart.direct.expect b/pkg/front_end/testcases/inference/dont_infer_field_type_when_initializer_is_null.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/dont_infer_field_type_when_initializer_is_null.dart.direct.expect
rename to pkg/front_end/testcases/inference/dont_infer_field_type_when_initializer_is_null.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/dont_infer_field_type_when_initializer_is_null.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/dont_infer_field_type_when_initializer_is_null.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/dont_infer_field_type_when_initializer_is_null.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/dont_infer_field_type_when_initializer_is_null.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart.direct.expect b/pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart.direct.expect
rename to pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart.type_promotion.expect b/pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart.type_promotion.expect
new file mode 100644
index 0000000..1d0fb56
--- /dev/null
+++ b/pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/dont_infer_type_on_dynamic.dart:10:5: Context: Write to x@281
+  x = "hi";
+    ^
diff --git a/pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart.direct.expect b/pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart.direct.expect
rename to pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart.type_promotion.expect b/pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart.type_promotion.expect
new file mode 100644
index 0000000..e2bfbdc
--- /dev/null
+++ b/pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart:10:5: Context: Write to x@295
+  x = "hi";
+    ^
+pkg/front_end/testcases/inference/dont_infer_type_when_initializer_is_null.dart:11:5: Context: Write to x@295
+  x = 3;
+    ^
diff --git a/pkg/front_end/testcases/inference/downward_inference_fixes_no_upwards_errors.dart.direct.expect b/pkg/front_end/testcases/inference/downward_inference_fixes_no_upwards_errors.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downward_inference_fixes_no_upwards_errors.dart.direct.expect
rename to pkg/front_end/testcases/inference/downward_inference_fixes_no_upwards_errors.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downward_inference_fixes_no_upwards_errors.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downward_inference_fixes_no_upwards_errors.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downward_inference_fixes_no_upwards_errors.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downward_inference_fixes_no_upwards_errors.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.direct.expect b/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.direct.expect
rename to pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_context_from_inferred_field_type.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_context_from_inferred_field_type.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_context_from_inferred_field_type.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_context_from_inferred_field_type.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_context_from_inferred_field_type.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_context_from_inferred_field_type.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_context_from_inferred_field_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_context_from_inferred_field_type.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.type_promotion.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.type_promotion.expect
new file mode 100644
index 0000000..6b72671
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart:14:34: Context: Write to i@367
+       i /*@target=num::<*/< 1; i++) {}
+                                 ^^
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.type_promotion.expect b/pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.type_promotion.expect
new file mode 100644
index 0000000..c96c4a6
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.type_promotion.expect
@@ -0,0 +1,9 @@
+pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart:10:5: Context: Write to l@288
+  l = /*@typeArgs=int*/ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ "hello"];
+    ^
+pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart:11:10: Context: Write to l@288
+  l = (l = /*@typeArgs=int*/ [1]);
+         ^
+pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart:11:5: Context: Write to l@288
+  l = (l = /*@typeArgs=int*/ [1]);
+    ^
diff --git a/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_async_await.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_async_await.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_async_await.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_async_await.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_for_each.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_for_each.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_for_each.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_for_each.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_initializing_formal_default_formal.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_inside_top_level_2.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_inside_top_level_2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_inside_top_level_2.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_inside_top_level_2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_inside_top_level_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_inside_top_level_2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_inside_top_level_2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_inside_top_level_2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.type_promotion.expect b/pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.type_promotion.expect
new file mode 100644
index 0000000..d06c6eb
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart:12:8: Context: Write to v1@368
+    v1 = <S> /*@returnType=main::::S*/ (/*@type=main::::S*/ x) => x;
+       ^
+pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart:17:8: Context: Write to v2@553
+    v2 = <S> /*@returnType=List<main::::S>*/
+       ^
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_empty_list.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_empty_list.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_empty_list.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_empty_list.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_empty_list.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_empty_list.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_empty_list.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_empty_list.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.type_promotion.expect b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.type_promotion.expect
new file mode 100644
index 0000000..419aa7c
--- /dev/null
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.type_promotion.expect
@@ -0,0 +1,60 @@
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:12:7: Context: Write to v@374
+    v = <T> /*@returnType=Null*/ (int x) => null;
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:13:7: Context: Write to v@374
+    v = <T> /*@returnType=String*/ (int x) => "hello";
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:14:7: Context: Write to v@374
+    v = /*error:INVALID_ASSIGNMENT*/ <T> /*@returnType=String*/ (String x) =>
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:16:7: Context: Write to v@374
+    v = /*error:INVALID_ASSIGNMENT*/ <T> /*@returnType=String*/ (int x) => 3;
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:17:7: Context: Write to v@374
+    v = <T> /*@returnType=String*/ (int x) {
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:24:7: Context: Write to v@862
+    v = <T> /*@returnType=Null*/ (/*@type=int*/ x) => null;
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:25:7: Context: Write to v@862
+    v = <T> /*@returnType=String*/ (/*@type=int*/ x) => "hello";
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:26:7: Context: Write to v@862
+    v = /*info:INFERRED_TYPE_CLOSURE, error:INVALID_ASSIGNMENT*/ <
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:29:7: Context: Write to v@862
+    v = <T> /*@returnType=String*/ (/*@type=int*/ x) {
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:32:7: Context: Write to v@862
+    v = <T> /*@returnType=String*/ (/*@type=int*/ x) {
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:39:7: Context: Write to v@1467
+    v = <T> /*@returnType=Null*/ (int x) => null;
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:40:7: Context: Write to v@1467
+    v = <T> /*@returnType=List<String>*/ (int x) => /*@typeArgs=String*/ [
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:43:7: Context: Write to v@1467
+    v = /*error:INVALID_ASSIGNMENT*/ <T> /*@returnType=List<String>*/ (String
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:45:7: Context: Write to v@1467
+    v = <T> /*@returnType=List<String>*/ (int x) => /*@typeArgs=String*/ [
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:48:7: Context: Write to v@1467
+    v = <T> /*@returnType=List<String>*/ (int x) {
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:59:7: Context: Write to x@2239
+    x = <T> /*@returnType=int*/ (/*@type=int*/ x) => x;
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:60:7: Context: Write to x@2239
+    x = <T> /*@returnType=int*/ (/*@type=int*/ x) => x /*@target=num::+*/ + 1;
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:62:7: Context: Write to y@2449
+    y = /*info:INFERRED_TYPE_CLOSURE, error:INVALID_ASSIGNMENT*/ <
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:65:7: Context: Write to y@2449
+    y = <T> /*@returnType=String*/ (/*@type=int*/ x) => /*info:DYNAMIC_INVOKE, info:DYNAMIC_CAST*/ x
+      ^
+pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:69:7: Context: Write to z@2791
+    z = <T> /*@returnType=String*/ (/*@type=String*/ x) =>
+      ^
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_map_literals.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_on_map_literals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_map_literals.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_map_literals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_map_literals.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_map_literals.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_on_map_literals.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_on_map_literals.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.direct.expect b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.direct.expect
rename to pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/dynamic_methods.dart.direct.expect b/pkg/front_end/testcases/inference/dynamic_methods.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/dynamic_methods.dart.direct.expect
rename to pkg/front_end/testcases/inference/dynamic_methods.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/dynamic_methods.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/dynamic_methods.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/dynamic_methods.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/dynamic_methods.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/field_initializer_context_explicit.dart.direct.expect b/pkg/front_end/testcases/inference/field_initializer_context_explicit.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/field_initializer_context_explicit.dart.direct.expect
rename to pkg/front_end/testcases/inference/field_initializer_context_explicit.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/field_initializer_context_explicit.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/field_initializer_context_explicit.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/field_initializer_context_explicit.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/field_initializer_context_explicit.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/field_initializer_context_implicit.dart.direct.expect b/pkg/front_end/testcases/inference/field_initializer_context_implicit.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/field_initializer_context_implicit.dart.direct.expect
rename to pkg/front_end/testcases/inference/field_initializer_context_implicit.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/field_initializer_context_implicit.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/field_initializer_context_implicit.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/field_initializer_context_implicit.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/field_initializer_context_implicit.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/field_initializer_context_this.dart.direct.expect b/pkg/front_end/testcases/inference/field_initializer_context_this.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/field_initializer_context_this.dart.direct.expect
rename to pkg/front_end/testcases/inference/field_initializer_context_this.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/field_initializer_context_this.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/field_initializer_context_this.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/field_initializer_context_this.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/field_initializer_context_this.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/field_initializer_parameter.dart.direct.expect b/pkg/front_end/testcases/inference/field_initializer_parameter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/field_initializer_parameter.dart.direct.expect
rename to pkg/front_end/testcases/inference/field_initializer_parameter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/field_initializer_parameter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/field_initializer_parameter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/field_initializer_parameter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/field_initializer_parameter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/field_refers_to_static_getter.dart.direct.expect b/pkg/front_end/testcases/inference/field_refers_to_static_getter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/field_refers_to_static_getter.dart.direct.expect
rename to pkg/front_end/testcases/inference/field_refers_to_static_getter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/field_refers_to_static_getter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/field_refers_to_static_getter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/field_refers_to_static_getter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/field_refers_to_static_getter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/field_refers_to_top_level_getter.dart.direct.expect b/pkg/front_end/testcases/inference/field_refers_to_top_level_getter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/field_refers_to_top_level_getter.dart.direct.expect
rename to pkg/front_end/testcases/inference/field_refers_to_top_level_getter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/field_refers_to_top_level_getter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/field_refers_to_top_level_getter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/field_refers_to_top_level_getter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/field_refers_to_top_level_getter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.direct.expect b/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.direct.expect
rename to pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/for_in_loop_promotion.dart.direct.expect b/pkg/front_end/testcases/inference/for_in_loop_promotion.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/for_in_loop_promotion.dart.direct.expect
rename to pkg/front_end/testcases/inference/for_in_loop_promotion.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/for_in_loop_promotion.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/for_in_loop_promotion.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/for_in_loop_promotion.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/for_in_loop_promotion.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/for_in_loop_promotion.dart.type_promotion.expect b/pkg/front_end/testcases/inference/for_in_loop_promotion.dart.type_promotion.expect
new file mode 100644
index 0000000..b5fe65a
--- /dev/null
+++ b/pkg/front_end/testcases/inference/for_in_loop_promotion.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/for_in_loop_promotion.dart:10:11: Context: Possible promotion of x@315
+    if (x is int) {
+          ^^
diff --git a/pkg/front_end/testcases/inference/for_loop_empty_condition.dart.direct.expect b/pkg/front_end/testcases/inference/for_loop_empty_condition.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/for_loop_empty_condition.dart.direct.expect
rename to pkg/front_end/testcases/inference/for_loop_empty_condition.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/for_loop_empty_condition.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/for_loop_empty_condition.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/for_loop_empty_condition.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/for_loop_empty_condition.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/for_loop_empty_condition.dart.type_promotion.expect b/pkg/front_end/testcases/inference/for_loop_empty_condition.dart.type_promotion.expect
new file mode 100644
index 0000000..8598d0c
--- /dev/null
+++ b/pkg/front_end/testcases/inference/for_loop_empty_condition.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/for_loop_empty_condition.dart:9:21: Context: Write to x@287
+  for (num x = 0;; x++) {
+                    ^^
+pkg/front_end/testcases/inference/for_loop_empty_condition.dart:11:11: Context: Possible promotion of x@287
+    if (x is int) {
+          ^^
diff --git a/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.direct.expect b/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.direct.expect
rename to pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.type_promotion.expect b/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.type_promotion.expect
new file mode 100644
index 0000000..84d17d3
--- /dev/null
+++ b/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.type_promotion.expect
@@ -0,0 +1,9 @@
+pkg/front_end/testcases/inference/for_loop_initializer_expression.dart:10:10: Context: Write to x@282
+  for (x = 0; x /*@target=num::<*/ < 10; x++) {
+         ^
+pkg/front_end/testcases/inference/for_loop_initializer_expression.dart:10:43: Context: Write to x@282
+  for (x = 0; x /*@target=num::<*/ < 10; x++) {
+                                          ^^
+pkg/front_end/testcases/inference/for_loop_initializer_expression.dart:11:11: Context: Possible promotion of x@282
+    if (x is int) {
+          ^^
diff --git a/pkg/front_end/testcases/inference/for_loop_promotion.dart.direct.expect b/pkg/front_end/testcases/inference/for_loop_promotion.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/for_loop_promotion.dart.direct.expect
rename to pkg/front_end/testcases/inference/for_loop_promotion.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/for_loop_promotion.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/for_loop_promotion.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/for_loop_promotion.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/for_loop_promotion.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/for_loop_promotion.dart.type_promotion.expect b/pkg/front_end/testcases/inference/for_loop_promotion.dart.type_promotion.expect
new file mode 100644
index 0000000..5cf87fe
--- /dev/null
+++ b/pkg/front_end/testcases/inference/for_loop_promotion.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/for_loop_promotion.dart:9:47: Context: Write to x@287
+  for (num x = 0; x /*@target=num::<*/ < 10; x++) {
+                                              ^^
+pkg/front_end/testcases/inference/for_loop_promotion.dart:10:11: Context: Possible promotion of x@287
+    if (x is int) {
+          ^^
diff --git a/pkg/front_end/testcases/inference/future_or_subtyping.dart.direct.expect b/pkg/front_end/testcases/inference/future_or_subtyping.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_or_subtyping.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_or_subtyping.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_or_subtyping.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_or_subtyping.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_or_subtyping.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_or_subtyping.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then.dart.direct.expect b/pkg/front_end/testcases/inference/future_then.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_2.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_3.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_3.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_3.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_3.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_3.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_3.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_4.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_4.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_4.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_4.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_4.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_4.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_5.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_5.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_5.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_5.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_5.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_5.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_6.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_6.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_6.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_6.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_6.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_6.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_conditional.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_conditional.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_conditional.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_conditional.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_conditional_2.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_conditional_2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_conditional_2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_conditional_2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_conditional_3.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_conditional_3.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_conditional_3.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_conditional_3.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_conditional_4.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_conditional_4.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_conditional_4.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_conditional_4.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_conditional_5.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_conditional_5.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_conditional_5.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_conditional_5.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_conditional_6.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_conditional_6.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_conditional_6.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_conditional_6.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.type_promotion.expect b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.type_promotion.expect
new file mode 100644
index 0000000..e254cf4
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/future_then_downwards_method_target.dart:17:5: Context: Write to b@330
+  b = f. /*@typeArgs=List<int>*/ /*@target=Future::then*/ then(
+    ^
diff --git a/pkg/front_end/testcases/inference/future_then_explicit_future.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_explicit_future.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_explicit_future.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_explicit_future.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_ifNull.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_ifNull.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_ifNull.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_ifNull.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_upwards.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_upwards_2.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_upwards_2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_upwards_2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_upwards_2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_upwards_3.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_upwards_3.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_upwards_3.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_upwards_3.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.direct.expect b/pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.type_promotion.expect b/pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.type_promotion.expect
new file mode 100644
index 0000000..b9275fa64
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_then_upwards_from_block.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/future_then_upwards_from_block.dart:21:5: Context: Write to b@695
+  b = g;
+    ^
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_async_conditional.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_union_async_conditional.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_async_conditional.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_union_async_conditional.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_downwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_union_downwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_downwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_union_downwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_downwards_2.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_union_downwards_2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_downwards_2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_union_downwards_2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_downwards_3.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_union_downwards_3.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_downwards_3.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_union_downwards_3.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_downwards_4.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_union_downwards_4.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_downwards_4.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_union_downwards_4.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.direct.expect b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.direct.expect
rename to pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.type_promotion.expect b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.type_promotion.expect
new file mode 100644
index 0000000..8c6d411
--- /dev/null
+++ b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart:18:8: Context: Write to list@682
+  list = result2;
+       ^
diff --git a/pkg/front_end/testcases/inference/generator_closure.dart.direct.expect b/pkg/front_end/testcases/inference/generator_closure.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generator_closure.dart.direct.expect
rename to pkg/front_end/testcases/inference/generator_closure.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generator_closure.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generator_closure.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generator_closure.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generator_closure.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.direct.expect b/pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.type_promotion.expect b/pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.type_promotion.expect
new file mode 100644
index 0000000..b9f3609
--- /dev/null
+++ b/pkg/front_end/testcases/inference/generic_functions_return_typedef.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/generic_functions_return_typedef.dart:15:12: Context: Write to takesInt@458
+  takesInt = y;
+           ^
diff --git a/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_correctly_recognize_generic_upper_bound.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_correctly_recognize_generic_upper_bound.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_correctly_recognize_generic_upper_bound.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_correctly_recognize_generic_upper_bound.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_correctly_recognize_generic_upper_bound.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_correctly_recognize_generic_upper_bound.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_correctly_recognize_generic_upper_bound.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_correctly_recognize_generic_upper_bound.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
index cc08449..50af1be 100644
--- a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
@@ -7,8 +7,8 @@
 //   T m<T>(T x) => x;
 //     ^
 //
-// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:14:64: Error: The return type of the method 'D::m' is dynamic, which does not match the return type of the overridden method (test::C::m::T).
-// Change to a subtype of test::C::m::T.
+// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:14:64: Error: The return type of the method 'D::m' is 'dynamic', which does not match the return type of the overridden method, 'test::C::m::T'.
+// Change to a subtype of 'test::C::m::T'.
 // /*@error=OverrideTypeMismatchReturnType*/ /*@topType=dynamic*/ m(
 //                                                                ^
 // pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:9:5: Context: This is the overridden method ('m').
@@ -25,8 +25,8 @@
 // /*@error=OverrideTypeMismatchReturnType*/ /*@topType=dynamic*/ m(
 //                                                                ^
 //
-// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:14:64: Error: The return type of the method 'D::m' is dynamic, which does not match the return type of the overridden method (test::C::m::T).
-// Change to a subtype of test::C::m::T.
+// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:14:64: Error: The return type of the method 'D::m' is 'dynamic', which does not match the return type of the overridden method, 'test::C::m::T'.
+// Change to a subtype of 'test::C::m::T'.
 // /*@error=OverrideTypeMismatchReturnType*/ /*@topType=dynamic*/ m(
 //                                                                ^
 //
diff --git a/pkg/front_end/testcases/inference/generic_methods_downwards_inference_affects_arguments.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_downwards_inference_affects_arguments.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_downwards_inference_affects_arguments.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_downwards_inference_affects_arguments.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_downwards_inference_affects_arguments.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_downwards_inference_affects_arguments.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_downwards_inference_affects_arguments.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_downwards_inference_affects_arguments.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart.type_promotion.expect b/pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart.type_promotion.expect
new file mode 100644
index 0000000..6793864
--- /dev/null
+++ b/pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart:20:5: Context: Write to y@436
+  y = /*info:DYNAMIC_CAST*/ z;
+    ^
+pkg/front_end/testcases/inference/generic_methods_downwards_inference_fold.dart:35:5: Context: Write to y@941
+  y = /*info:DYNAMIC_CAST*/ z;
+    ^
diff --git a/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.strong.expect
index a010490..417d91a 100644
--- a/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart.strong.expect
@@ -7,8 +7,8 @@
 //   /*@topType=dynamic*/ m(/*@topType=dynamic*/ x) => x;
 //                        ^
 //
-// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:15:54: Error: The parameter 'x' of the method 'D::m' has type test::D::m::T, which does not match the corresponding type in the overridden method (dynamic).
-// Change to a supertype of dynamic (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:15:54: Error: The parameter 'x' of the method 'D::m' has type 'test::D::m::T', which does not match the corresponding type in the overridden method, 'dynamic'.
+// Change to a supertype of 'dynamic', or, for a covariant parameter, a subtype.
 //           T /*@error=OverrideTypeMismatchParameter*/ x) =>
 //                                                      ^
 // pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:9:24: Context: This is the overridden method ('m').
@@ -22,8 +22,8 @@
 //   dynamic g(int x) => x;
 //           ^
 //
-// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:18:54: Error: The parameter 'x' of the method 'D::g' has type test::D::g::T, which does not match the corresponding type in the overridden method (dart.core::int).
-// Change to a supertype of dart.core::int (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:18:54: Error: The parameter 'x' of the method 'D::g' has type 'test::D::g::T', which does not match the corresponding type in the overridden method, 'dart.core::int'.
+// Change to a supertype of 'dart.core::int', or, for a covariant parameter, a subtype.
 //           T /*@error=OverrideTypeMismatchParameter*/ x) =>
 //                                                      ^
 // pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:10:11: Context: This is the overridden method ('g').
@@ -36,8 +36,8 @@
 //   T /*@error=OverrideTypeVariablesMismatch*/ m<T>(
 //                                              ^
 //
-// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:15:54: Error: The parameter 'x' of the method 'D::m' has type test::D::m::T, which does not match the corresponding type in the overridden method (dynamic).
-// Change to a supertype of dynamic (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:15:54: Error: The parameter 'x' of the method 'D::m' has type 'test::D::m::T', which does not match the corresponding type in the overridden method, 'dynamic'.
+// Change to a supertype of 'dynamic', or, for a covariant parameter, a subtype.
 //           T /*@error=OverrideTypeMismatchParameter*/ x) =>
 //                                                      ^
 //
@@ -45,8 +45,8 @@
 //   T /*@error=OverrideTypeVariablesMismatch*/ g<T>(
 //                                              ^
 //
-// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:18:54: Error: The parameter 'x' of the method 'D::g' has type test::D::g::T, which does not match the corresponding type in the overridden method (dart.core::int).
-// Change to a supertype of dart.core::int (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/inference/generic_methods_handle_override_of_non_generic_with_generic.dart:18:54: Error: The parameter 'x' of the method 'D::g' has type 'test::D::g::T', which does not match the corresponding type in the overridden method, 'dart.core::int'.
+// Change to a supertype of 'dart.core::int', or, for a covariant parameter, a subtype.
 //           T /*@error=OverrideTypeMismatchParameter*/ x) =>
 //                                                      ^
 
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_return_type.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_return_type.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_infer_generic_function_return_type.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_infer_generic_function_return_type.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_return_type.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_return_type.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_infer_generic_function_return_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_infer_generic_function_return_type.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_method_type.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_method_type.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_infer_generic_method_type.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_infer_generic_method_type.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_method_type.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_method_type.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_infer_generic_method_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_infer_generic_method_type.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.type_promotion.expect b/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.type_promotion.expect
new file mode 100644
index 0000000..7e3d35f
--- /dev/null
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart:13:5: Context: Write to y@427
+  y = "world";
+    ^
+pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart:14:5: Context: Write to y@427
+  y = /*error:INVALID_ASSIGNMENT*/ 42;
+    ^
diff --git a/pkg/front_end/testcases/inference/generic_methods_inference_error.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_inference_error.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_inference_error.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_inference_error.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_inference_error.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_inference_error.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_inference_error.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_inference_error.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.direct.expect b/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.direct.expect
rename to pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.direct.expect b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.direct.expect
rename to pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/index_assign_operator_return_type.dart.direct.expect b/pkg/front_end/testcases/inference/index_assign_operator_return_type.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/index_assign_operator_return_type.dart.direct.expect
rename to pkg/front_end/testcases/inference/index_assign_operator_return_type.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/index_assign_operator_return_type.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/index_assign_operator_return_type.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/index_assign_operator_return_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/index_assign_operator_return_type.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/index_assign_operator_return_type_2.dart.direct.expect b/pkg/front_end/testcases/inference/index_assign_operator_return_type_2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/index_assign_operator_return_type_2.dart.direct.expect
rename to pkg/front_end/testcases/inference/index_assign_operator_return_type_2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/index_assign_operator_return_type_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/index_assign_operator_return_type_2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/index_assign_operator_return_type_2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/index_assign_operator_return_type_2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.direct.expect b/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_accessor_from_later_inferred_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_implicit_this_upwards.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_implicit_this_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_implicit_this_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_implicit_this_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_implicit_this_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_implicit_this_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_implicit_this_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_implicit_this_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_index_super.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_index_this.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_local.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_local.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_local.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_local.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_local.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_local.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_local.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_local.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_local.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_assign_to_local.dart.type_promotion.expect
new file mode 100644
index 0000000..b6004bf
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_assign_to_local.dart.type_promotion.expect
@@ -0,0 +1,39 @@
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:23:9: Context: Write to local@474
+  local = /*@typeArgs=B*/ f();
+        ^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:24:9: Context: Write to local@474
+  local ??= /*@typeArgs=B*/ f();
+        ^^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:25:9: Context: Write to local@474
+  local += /*@typeArgs=dynamic*/ f();
+        ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:26:9: Context: Write to local@474
+  local *= /*@typeArgs=dynamic*/ f();
+        ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:27:9: Context: Write to local@474
+  local &= /*@typeArgs=dynamic*/ f();
+        ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:28:3: Context: Write to local@474
+  --local;
+  ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:29:8: Context: Write to local@474
+  local--;
+       ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:30:30: Context: Write to local@474
+  var /*@type=B*/ v1 = local = /*@typeArgs=B*/ f();
+                             ^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:31:30: Context: Write to local@474
+  var /*@type=B*/ v2 = local ??= /*@typeArgs=B*/ f();
+                             ^^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:32:30: Context: Write to local@474
+  var /*@type=B*/ v4 = local *= /*@typeArgs=dynamic*/ f();
+                             ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:33:30: Context: Write to local@474
+  var /*@type=C*/ v5 = local &= /*@typeArgs=dynamic*/ f();
+                             ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:34:24: Context: Write to local@474
+  var /*@type=B*/ v6 = --local;
+                       ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:35:29: Context: Write to local@474
+  var /*@type=B*/ v7 = local--;
+                            ^^
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.type_promotion.expect
new file mode 100644
index 0000000..0bddfc5
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.type_promotion.expect
@@ -0,0 +1,69 @@
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:13:28: Context: Write to t@343
+  var /*@type=int*/ v1 = t = getInt();
+                           ^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:14:28: Context: Write to t@343
+  var /*@type=int*/ v4 = t ??= getInt();
+                           ^^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:15:28: Context: Write to t@343
+  var /*@type=int*/ v7 = t += getInt();
+                           ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:16:27: Context: Write to t@343
+  var /*@type=int*/ v10 = ++t;
+                          ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:17:28: Context: Write to t@343
+  var /*@type=int*/ v11 = t++;
+                           ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:21:28: Context: Write to t@343
+  var /*@type=int*/ v1 = t = getInt();
+                           ^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:22:28: Context: Write to t@343
+  var /*@type=num*/ v2 = t = getNum();
+                           ^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:23:31: Context: Write to t@343
+  var /*@type=double*/ v3 = t = getDouble();
+                              ^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:24:28: Context: Write to t@343
+  var /*@type=num*/ v4 = t ??= getInt();
+                           ^^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:25:28: Context: Write to t@343
+  var /*@type=num*/ v5 = t ??= getNum();
+                           ^^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:26:28: Context: Write to t@343
+  var /*@type=num*/ v6 = t ??= getDouble();
+                           ^^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:27:28: Context: Write to t@343
+  var /*@type=num*/ v7 = t += getInt();
+                           ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:28:28: Context: Write to t@343
+  var /*@type=num*/ v8 = t += getNum();
+                           ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:29:28: Context: Write to t@343
+  var /*@type=num*/ v9 = t += getDouble();
+                           ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:30:27: Context: Write to t@343
+  var /*@type=num*/ v10 = ++t;
+                          ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:31:28: Context: Write to t@343
+  var /*@type=num*/ v11 = t++;
+                           ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:35:31: Context: Write to t@343
+  var /*@type=double*/ v3 = t = getDouble();
+                              ^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:36:31: Context: Write to t@343
+  var /*@type=double*/ v6 = t ??= getDouble();
+                              ^^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:37:31: Context: Write to t@343
+  var /*@type=double*/ v7 = t += getInt();
+                              ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:38:31: Context: Write to t@343
+  var /*@type=double*/ v8 = t += getNum();
+                              ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:39:31: Context: Write to t@343
+  var /*@type=double*/ v9 = t += getDouble();
+                              ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:40:30: Context: Write to t@343
+  var /*@type=double*/ v10 = ++t;
+                             ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:41:31: Context: Write to t@343
+  var /*@type=double*/ v11 = t++;
+                              ^^
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_ref.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_ref.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_ref.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_ref.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_ref.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_ref.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_ref.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_ref.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_static.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_static.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_static.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_static.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_static.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_static.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_static.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_static.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_static_upwards.dart.direct.expect b/pkg/front_end/testcases/inference/infer_assign_to_static_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_static_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_static_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_static_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_static_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_assign_to_static_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_assign_to_static_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_binary_custom.dart.direct.expect b/pkg/front_end/testcases/inference/infer_binary_custom.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_binary_custom.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_binary_custom.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_binary_custom.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_binary_custom.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_binary_custom.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_binary_custom.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_binary_double_double.dart.direct.expect b/pkg/front_end/testcases/inference/infer_binary_double_double.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_binary_double_double.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_binary_double_double.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_binary_double_double.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_binary_double_double.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_binary_double_double.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_binary_double_double.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_binary_double_int.dart.direct.expect b/pkg/front_end/testcases/inference/infer_binary_double_int.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_binary_double_int.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_binary_double_int.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_binary_double_int.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_binary_double_int.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_binary_double_int.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_binary_double_int.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_binary_int_double.dart.direct.expect b/pkg/front_end/testcases/inference/infer_binary_int_double.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_binary_int_double.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_binary_int_double.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_binary_int_double.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_binary_int_double.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_binary_int_double.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_binary_int_double.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_binary_int_int.dart.direct.expect b/pkg/front_end/testcases/inference/infer_binary_int_int.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_binary_int_int.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_binary_int_int.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_binary_int_int.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_binary_int_int.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_binary_int_int.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_binary_int_int.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_conditional.dart.direct.expect b/pkg/front_end/testcases/inference/infer_conditional.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_conditional.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_conditional.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_conditional.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_conditional.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_conditional.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_conditional.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.direct.expect b/pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.type_promotion.expect
new file mode 100644
index 0000000..3628855
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/infer_consts_transitively_2.dart:15:5: Context: Write to i@387
+  i = m1;
+    ^
diff --git a/pkg/front_end/testcases/inference/infer_consts_transitively_2_a.dart.direct.expect b/pkg/front_end/testcases/inference/infer_consts_transitively_2_a.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_consts_transitively_2_a.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_consts_transitively_2_a.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_consts_transitively_2_a.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_consts_transitively_2_a.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_consts_transitively_2_a.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_consts_transitively_2_a.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_consts_transitively_2_b.dart.direct.expect b/pkg/front_end/testcases/inference/infer_consts_transitively_2_b.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_consts_transitively_2_b.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_consts_transitively_2_b.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_consts_transitively_2_b.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_consts_transitively_2_b.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_consts_transitively_2_b.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_consts_transitively_2_b.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_consts_transitively_b.dart.direct.expect b/pkg/front_end/testcases/inference/infer_consts_transitively_b.dart.direct.expect
deleted file mode 100644
index 335fe8e..0000000
--- a/pkg/front_end/testcases/inference/infer_consts_transitively_b.dart.direct.expect
+++ /dev/null
@@ -1,7 +0,0 @@
-library;
-import self as self;
-
-static const field dynamic b1 = 2;
-static method main() → dynamic {
-  self::b1;
-}
diff --git a/pkg/front_end/testcases/inference/infer_consts_transitively_2_b.dart.direct.expect b/pkg/front_end/testcases/inference/infer_consts_transitively_b.dart.legacy.expect
similarity index 100%
copy from pkg/front_end/testcases/inference/infer_consts_transitively_2_b.dart.direct.expect
copy to pkg/front_end/testcases/inference/infer_consts_transitively_b.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_consts_transitively_b.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_consts_transitively_b.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_consts_transitively_b.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_consts_transitively_b.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.direct.expect b/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.type_promotion.expect
new file mode 100644
index 0000000..7c9fd70
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart.type_promotion.expect
@@ -0,0 +1,24 @@
+pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:25:5: Context: Write to s@537
+  s = /*info:DYNAMIC_CAST*/ new B(). /*@target=B::x*/ x;
+    ^
+pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:26:5: Context: Write to s@537
+  s = /*error:INVALID_ASSIGNMENT*/ new B(). /*@target=B::y*/ y;
+    ^
+pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:27:5: Context: Write to s@537
+  s = new B(). /*@target=B::z*/ z;
+    ^
+pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:28:5: Context: Write to s@537
+  s = /*error:INVALID_ASSIGNMENT*/ new B(). /*@target=B::w*/ w;
+    ^
+pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:30:5: Context: Write to i@546
+  i = /*info:DYNAMIC_CAST*/ new B(). /*@target=B::x*/ x;
+    ^
+pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:31:5: Context: Write to i@546
+  i = new B(). /*@target=B::y*/ y;
+    ^
+pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:32:5: Context: Write to i@546
+  i = /*error:INVALID_ASSIGNMENT*/ new B(). /*@target=B::z*/ z;
+    ^
+pkg/front_end/testcases/inference/infer_correctly_on_multiple_variables_declared_together.dart:33:5: Context: Write to i@546
+  i = new B(). /*@target=B::w*/ w;
+    ^
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_field_from_later_inferred_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_field_from_later_inferred_getter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_field_from_later_inferred_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_override_multiple.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_field_override_multiple.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_override_multiple.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_field_override_multiple.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
index ea30e70..d6165e5 100644
--- a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
@@ -15,48 +15,48 @@
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F::x' is dynamic, which does not match the return type of the overridden method (dart.core::int).
-// Change to a subtype of dart.core::int.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::int'.
+// Change to a subtype of 'dart.core::int'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 // pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is the overridden method ('x').
 //   int get x;
 //           ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F::x' is dynamic, which does not match the return type of the overridden method (dart.core::num).
-// Change to a subtype of dart.core::num.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::num'.
+// Change to a subtype of 'dart.core::num'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 // pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is the overridden method ('x').
 //   num get x;
 //           ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G::x' is dynamic, which does not match the return type of the overridden method (dart.core::int).
-// Change to a subtype of dart.core::int.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::int'.
+// Change to a subtype of 'dart.core::int'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 // pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is the overridden method ('x').
 //   int get x;
 //           ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G::x' is dynamic, which does not match the return type of the overridden method (dart.core::double).
-// Change to a subtype of dart.core::double.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::double'.
+// Change to a subtype of 'dart.core::double'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 // pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is the overridden method ('x').
 //   double get x;
 //              ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H::x' is dynamic, which does not match the return type of the overridden method (dart.core::num).
-// Change to a subtype of dart.core::num.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::num'.
+// Change to a subtype of 'dart.core::num'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 // pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is the overridden method ('x').
 //   num get x;
 //           ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H::x' is dynamic, which does not match the return type of the overridden method (dart.core::double).
-// Change to a subtype of dart.core::double.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::double'.
+// Change to a subtype of 'dart.core::double'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 // pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is the overridden method ('x').
@@ -80,33 +80,33 @@
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F::x' is dynamic, which does not match the return type of the overridden method (dart.core::int).
-// Change to a subtype of dart.core::int.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::int'.
+// Change to a subtype of 'dart.core::int'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F::x' is dynamic, which does not match the return type of the overridden method (dart.core::num).
-// Change to a subtype of dart.core::num.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:163: Error: The return type of the method 'F::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::num'.
+// Change to a subtype of 'dart.core::num'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G::x' is dynamic, which does not match the return type of the overridden method (dart.core::int).
-// Change to a subtype of dart.core::int.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::int'.
+// Change to a subtype of 'dart.core::int'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G::x' is dynamic, which does not match the return type of the overridden method (dart.core::double).
-// Change to a subtype of dart.core::double.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:163: Error: The return type of the method 'G::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::double'.
+// Change to a subtype of 'dart.core::double'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H::x' is dynamic, which does not match the return type of the overridden method (dart.core::num).
-// Change to a subtype of dart.core::num.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::num'.
+// Change to a subtype of 'dart.core::num'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H::x' is dynamic, which does not match the return type of the overridden method (dart.core::double).
-// Change to a subtype of dart.core::double.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:163: Error: The return type of the method 'H::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::double'.
+// Change to a subtype of 'dart.core::double'.
 //   var /*@topType=dynamic*/ /*@error=CantInferTypeDueToInconsistentOverrides*/ /*@error=OverrideTypeMismatchReturnType*/ /*@error=OverrideTypeMismatchReturnType*/ x;
 //                                                                                                                                                                   ^
 
diff --git a/pkg/front_end/testcases/inference/infer_field_override_of_override.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_override_of_override.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_override_of_override.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_field_override_of_override.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_override_of_override.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_field_override_of_override.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_override_of_override.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_field_override_of_override.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_field_override_with_substitution.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_static.dart.direct.expect b/pkg/front_end/testcases/inference/infer_field_static.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_static.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_field_static.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_field_static.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_field_static.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_field_static.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_field_static.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.direct.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_final_field_getter_only.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.expect b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_final_field_setter_only.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.direct.expect b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart.direct.expect b/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart.direct.expect b/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart.direct.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart.type_promotion.expect
new file mode 100644
index 0000000..f71d77a
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart:14:5: Context: Write to t@389
+  t = x;
+    ^
+pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on.dart:15:5: Context: Write to t@389
+  t = y;
+    ^
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart.direct.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart.type_promotion.expect
new file mode 100644
index 0000000..5b8cb3d
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart:16:5: Context: Write to t@400
+  t = A.x;
+    ^
+pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2.dart:17:5: Context: Write to t@400
+  t = B.y;
+    ^
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a.dart.direct.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on_a.dart.direct.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on_a.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on_a.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on_a.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on_a.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on_a.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on_a.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on_a.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag.dart.direct.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2.dart.direct.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2_a.dart.direct.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2_a.dart.direct.expect
deleted file mode 100644
index b2d87e2..0000000
--- a/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2_a.dart.direct.expect
+++ /dev/null
@@ -1,11 +0,0 @@
-library;
-import self as self;
-import "dart:core" as core;
-
-class A extends core::Object {
-  static field dynamic x = 2;
-  synthetic constructor •() → self::A
-    : super core::Object::•()
-    ;
-}
-static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2_a.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2_a.dart.direct.transformed.expect
deleted file mode 100644
index b2d87e2..0000000
--- a/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2_a.dart.direct.transformed.expect
+++ /dev/null
@@ -1,11 +0,0 @@
-library;
-import self as self;
-import "dart:core" as core;
-
-class A extends core::Object {
-  static field dynamic x = 2;
-  synthetic constructor •() → self::A
-    : super core::Object::•()
-    ;
-}
-static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a.dart.direct.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2_a.dart.legacy.expect
similarity index 100%
copy from pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a.dart.direct.expect
copy to pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2_a.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2_a.dart.legacy.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a.dart.direct.transformed.expect
copy to pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag2_a.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag_a.dart.direct.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag_a.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag_a.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag_a.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag_a.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag_a.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag_a.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_from_variables_in_non_cycle_imports_with_flag_a.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_generic_method_type_named.dart.direct.expect b/pkg/front_end/testcases/inference/infer_generic_method_type_named.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_generic_method_type_named.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_generic_method_type_named.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_generic_method_type_named.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_generic_method_type_named.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_generic_method_type_named.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_generic_method_type_named.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_generic_method_type_positional.dart.direct.expect b/pkg/front_end/testcases/inference/infer_generic_method_type_positional.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_generic_method_type_positional.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_generic_method_type_positional.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_generic_method_type_positional.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_generic_method_type_positional.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_generic_method_type_positional.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_generic_method_type_positional.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_generic_method_type_positional2.dart.direct.expect b/pkg/front_end/testcases/inference/infer_generic_method_type_positional2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_generic_method_type_positional2.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_generic_method_type_positional2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_generic_method_type_positional2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_generic_method_type_positional2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_generic_method_type_positional2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_generic_method_type_positional2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_generic_method_type_required.dart.direct.expect b/pkg/front_end/testcases/inference/infer_generic_method_type_required.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_generic_method_type_required.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_generic_method_type_required.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_generic_method_type_required.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_generic_method_type_required.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_generic_method_type_required.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_generic_method_type_required.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_getter_cross_to_setter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_getter_cross_to_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_getter_cross_to_setter.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_getter_cross_to_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_getter_cross_to_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_getter_cross_to_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_getter_cross_to_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_getter_cross_to_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_getter_from_later_inferred_getter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_list_literal_nested_in_map_literal.dart.direct.expect b/pkg/front_end/testcases/inference/infer_list_literal_nested_in_map_literal.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_list_literal_nested_in_map_literal.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_list_literal_nested_in_map_literal.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_list_literal_nested_in_map_literal.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_list_literal_nested_in_map_literal.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_list_literal_nested_in_map_literal.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_list_literal_nested_in_map_literal.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_local_function_referenced_before_declaration.dart.direct.expect b/pkg/front_end/testcases/inference/infer_local_function_referenced_before_declaration.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_local_function_referenced_before_declaration.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_local_function_referenced_before_declaration.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_local_function_referenced_before_declaration.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_local_function_referenced_before_declaration.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_local_function_referenced_before_declaration.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_local_function_referenced_before_declaration.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.direct.expect b/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_local_function_return_type.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_local_function_return_type.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_local_function_return_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_local_function_return_type.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_method_function_typed.dart.direct.expect b/pkg/front_end/testcases/inference/infer_method_function_typed.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_method_function_typed.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_method_function_typed.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_method_function_typed.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_method_function_typed.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_method_function_typed.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_method_function_typed.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_method_missing_params.dart.direct.expect b/pkg/front_end/testcases/inference/infer_method_missing_params.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_method_missing_params.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_method_missing_params.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_method_missing_params.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_method_missing_params.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_method_missing_params.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_method_missing_params.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart.direct.expect b/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_parameter_type_setter_from_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_parameter_type_setter_from_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_prefix_expression.dart.direct.expect b/pkg/front_end/testcases/inference/infer_prefix_expression.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_prefix_expression.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_prefix_expression.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_prefix_expression.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_prefix_expression.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_prefix_expression.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_prefix_expression.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_prefix_expression_custom.dart.direct.expect b/pkg/front_end/testcases/inference/infer_prefix_expression_custom.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_prefix_expression_custom.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_prefix_expression_custom.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_prefix_expression_custom.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_prefix_expression_custom.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_prefix_expression_custom.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_prefix_expression_custom.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_rethrow.dart.direct.expect b/pkg/front_end/testcases/inference/infer_rethrow.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_rethrow.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_rethrow.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_rethrow.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_rethrow.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_rethrow.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_rethrow.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_return_of_statement_lambda.dart.direct.expect b/pkg/front_end/testcases/inference/infer_return_of_statement_lambda.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_return_of_statement_lambda.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_return_of_statement_lambda.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_return_of_statement_lambda.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_return_of_statement_lambda.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_return_of_statement_lambda.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_return_of_statement_lambda.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_return_type_for_static_setter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_return_type_for_static_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_return_type_for_static_setter.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_return_type_for_static_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_return_type_for_static_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_return_type_for_static_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_return_type_for_static_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_return_type_for_static_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_setter_cross_to_getter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_setter_cross_to_getter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_setter_cross_to_getter.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_setter_cross_to_getter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_setter_cross_to_getter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_setter_cross_to_getter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_setter_cross_to_getter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_setter_cross_to_getter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.direct.expect b/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_setter_from_later_inferred_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_setter_function_typed.dart.direct.expect b/pkg/front_end/testcases/inference/infer_setter_function_typed.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_setter_function_typed.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_setter_function_typed.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_setter_function_typed.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_setter_function_typed.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_setter_function_typed.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_setter_function_typed.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_setter_return_type_only.dart.direct.expect b/pkg/front_end/testcases/inference/infer_setter_return_type_only.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_setter_return_type_only.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_setter_return_type_only.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_setter_return_type_only.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_setter_return_type_only.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_setter_return_type_only.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_setter_return_type_only.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively.dart.direct.expect b/pkg/front_end/testcases/inference/infer_statics_transitively.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_transitively.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_statics_transitively.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_statics_transitively.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_transitively.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_statics_transitively.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_statics_transitively.dart.type_promotion.expect
new file mode 100644
index 0000000..2bf9cee
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_statics_transitively.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/infer_statics_transitively.dart:15:5: Context: Write to i@388
+  i = m1;
+    ^
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively2.dart.direct.expect b/pkg/front_end/testcases/inference/infer_statics_transitively2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_transitively2.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_statics_transitively2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_statics_transitively2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_transitively2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_statics_transitively2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively2.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_statics_transitively2.dart.type_promotion.expect
new file mode 100644
index 0000000..bd3b23fe
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_statics_transitively2.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/infer_statics_transitively2.dart:15:5: Context: Write to i@403
+  i = y1;
+    ^
+pkg/front_end/testcases/inference/infer_statics_transitively2.dart:16:5: Context: Write to i@403
+  i = y2;
+    ^
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively3.dart.direct.expect b/pkg/front_end/testcases/inference/infer_statics_transitively3.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_transitively3.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_statics_transitively3.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively3.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_statics_transitively3.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_transitively3.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_statics_transitively3.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively3.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_statics_transitively3.dart.type_promotion.expect
new file mode 100644
index 0000000..2d28253
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_statics_transitively3.dart.type_promotion.expect
@@ -0,0 +1,12 @@
+pkg/front_end/testcases/inference/infer_statics_transitively3.dart:20:5: Context: Write to i@602
+  i = t1;
+    ^
+pkg/front_end/testcases/inference/infer_statics_transitively3.dart:21:5: Context: Write to i@602
+  i = t2;
+    ^
+pkg/front_end/testcases/inference/infer_statics_transitively3.dart:22:5: Context: Write to i@602
+  i = t3;
+    ^
+pkg/front_end/testcases/inference/infer_statics_transitively3.dart:23:5: Context: Write to i@602
+  i = t4;
+    ^
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively3_a.dart.direct.expect b/pkg/front_end/testcases/inference/infer_statics_transitively3_a.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_transitively3_a.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_statics_transitively3_a.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively3_a.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_statics_transitively3_a.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_transitively3_a.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_statics_transitively3_a.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively_2_a.dart.direct.expect b/pkg/front_end/testcases/inference/infer_statics_transitively_2_a.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_transitively_2_a.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_statics_transitively_2_a.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively_2_a.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_statics_transitively_2_a.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_transitively_2_a.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_statics_transitively_2_a.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively_a.dart.direct.expect b/pkg/front_end/testcases/inference/infer_statics_transitively_a.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_transitively_a.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_statics_transitively_a.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively_a.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_statics_transitively_a.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_transitively_a.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_statics_transitively_a.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively_b.dart.direct.expect b/pkg/front_end/testcases/inference/infer_statics_transitively_b.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_transitively_b.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_statics_transitively_b.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively_b.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_statics_transitively_b.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_transitively_b.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_statics_transitively_b.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_with_method_invocations.dart.direct.expect b/pkg/front_end/testcases/inference/infer_statics_with_method_invocations.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_with_method_invocations.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_statics_with_method_invocations.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_with_method_invocations.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_statics_with_method_invocations.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_with_method_invocations.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_statics_with_method_invocations.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_with_method_invocations_a.dart.direct.expect b/pkg/front_end/testcases/inference/infer_statics_with_method_invocations_a.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_with_method_invocations_a.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_statics_with_method_invocations_a.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_statics_with_method_invocations_a.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_statics_with_method_invocations_a.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_statics_with_method_invocations_a.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_statics_with_method_invocations_a.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_throw.dart.direct.expect b/pkg/front_end/testcases/inference/infer_throw.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_throw.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_throw.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_throw.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_throw.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_throw.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_throw.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_throw_downwards.dart.direct.expect b/pkg/front_end/testcases/inference/infer_throw_downwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_throw_downwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_throw_downwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_throw_downwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_throw_downwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_throw_downwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_throw_downwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart.direct.expect b/pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_type_on_overridden_fields2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart.direct.expect b/pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_type_on_overridden_fields4.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var.dart.direct.expect b/pkg/front_end/testcases/inference/infer_type_on_var.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_on_var.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_type_on_var.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_type_on_var.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_on_var.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_type_on_var.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_type_on_var.dart.type_promotion.expect
new file mode 100644
index 0000000..f8cd812
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_type_on_var.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/infer_type_on_var.dart:10:5: Context: Write to x@278
+  x = /*error:INVALID_ASSIGNMENT*/ "hi";
+    ^
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var2.dart.direct.expect b/pkg/front_end/testcases/inference/infer_type_on_var2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_on_var2.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_type_on_var2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_type_on_var2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_on_var2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_type_on_var2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var2.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_type_on_var2.dart.type_promotion.expect
new file mode 100644
index 0000000..23f8fc0
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_type_on_var2.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/infer_type_on_var2.dart:10:5: Context: Write to x@292
+  x = /*error:INVALID_ASSIGNMENT*/ "hi";
+    ^
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart.direct.expect b/pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart.type_promotion.expect
new file mode 100644
index 0000000..e745ffe
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart.type_promotion.expect
@@ -0,0 +1,18 @@
+pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart:13:7: Context: Write to a@341
+    a = /*error:INVALID_ASSIGNMENT*/ "hi";
+      ^
+pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart:14:7: Context: Write to a@341
+    a = 3;
+      ^
+pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart:16:7: Context: Write to b@441
+    b = /*error:INVALID_ASSIGNMENT*/ "hi";
+      ^
+pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart:17:7: Context: Write to b@441
+    b = 4;
+      ^
+pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart:19:7: Context: Write to c@541
+    c = /*error:INVALID_ASSIGNMENT*/ "hi";
+      ^
+pkg/front_end/testcases/inference/infer_type_on_var_from_field.dart:20:7: Context: Write to c@541
+    c = 4;
+      ^
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart.direct.expect b/pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart.type_promotion.expect
new file mode 100644
index 0000000..771ee3c
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart.type_promotion.expect
@@ -0,0 +1,18 @@
+pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart:12:5: Context: Write to a@304
+  a = /*error:INVALID_ASSIGNMENT*/ "hi";
+    ^
+pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart:13:5: Context: Write to a@304
+  a = 3;
+    ^
+pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart:15:5: Context: Write to b@381
+  b = /*error:INVALID_ASSIGNMENT*/ "hi";
+    ^
+pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart:16:5: Context: Write to b@381
+  b = 4;
+    ^
+pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart:18:5: Context: Write to c@458
+  c = /*error:INVALID_ASSIGNMENT*/ "hi";
+    ^
+pkg/front_end/testcases/inference/infer_type_on_var_from_top_level.dart:19:5: Context: Write to c@458
+  c = 4;
+    ^
diff --git a/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart.direct.expect b/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles_b.dart.direct.expect b/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles_b.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles_b.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles_b.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles_b.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles_b.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles_b.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_type_regardless_of_declaration_order_or_cycles_b.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_typed_map_literal.dart.direct.expect b/pkg/front_end/testcases/inference/infer_typed_map_literal.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_typed_map_literal.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_typed_map_literal.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_typed_map_literal.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_typed_map_literal.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_typed_map_literal.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_typed_map_literal.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart.direct.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_3.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart.direct.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_4.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.direct.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.direct.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.direct.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.direct.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.strong.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.strong.expect
index 8751e0d..469454f 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart.strong.expect
@@ -1,7 +1,7 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart:13:49: Error: The return type of the method 'B::x' is dynamic, which does not match the return type of the overridden method (dart.core::int).
-// Change to a subtype of dart.core::int.
+// pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart:13:49: Error: The return type of the method 'B::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::int'.
+// Change to a subtype of 'dart.core::int'.
 //   /*error:INVALID_METHOD_OVERRIDE*/ dynamic get x => 3;
 //                                                 ^
 // pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart:9:11: Context: This is the overridden method ('x').
@@ -10,8 +10,8 @@
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart:13:49: Error: The return type of the method 'B::x' is dynamic, which does not match the return type of the overridden method (dart.core::int).
-// Change to a subtype of dart.core::int.
+// pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_infer.dart:13:49: Error: The return type of the method 'B::x' is 'dynamic', which does not match the return type of the overridden method, 'dart.core::int'.
+// Change to a subtype of 'dart.core::int'.
 //   /*error:INVALID_METHOD_OVERRIDE*/ dynamic get x => 3;
 //                                                 ^
 
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.direct.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.direct.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.direct.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.type_promotion.expect
new file mode 100644
index 0000000..ab77237
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart:9:61: Context: Write to i@296
+  for (var /*@type=int*/ i = 0; i /*@target=num::<*/ < 10; i++) {
+                                                            ^^
diff --git a/pkg/front_end/testcases/inference/infer_use_of_void_local.dart.direct.expect b/pkg/front_end/testcases/inference/infer_use_of_void_local.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_use_of_void_local.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_use_of_void_local.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_use_of_void_local.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_use_of_void_local.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_use_of_void_local.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_use_of_void_local.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/infer_variable_void.dart.direct.expect b/pkg/front_end/testcases/inference/infer_variable_void.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_variable_void.dart.direct.expect
rename to pkg/front_end/testcases/inference/infer_variable_void.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/infer_variable_void.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/infer_variable_void.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/infer_variable_void.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/infer_variable_void.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_initializing_formal_checks_default_value.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_initializing_formal_checks_default_value.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_initializing_formal_checks_default_value.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_initializing_formal_checks_default_value.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_initializing_formal_checks_default_value.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_initializing_formal_checks_default_value.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_initializing_formal_checks_default_value.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_initializing_formal_checks_default_value.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_static_field_complex.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_static_field_complex.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_static_field_complex.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_static_field_complex.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_static_field_complex.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_static_field_complex.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_static_field_complex.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_static_field_complex.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_top_level_var_simple.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_top_level_var_simple.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_top_level_var_simple.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_top_level_var_simple.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_top_level_var_simple.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_top_level_var_simple.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_top_level_var_simple.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_nonstatic_field_depends_on_top_level_var_simple.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_cascade.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_cascade.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_cascade.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_cascade.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_cascade.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_cascade.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_cascade.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_cascade.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_custom_binary_op.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_custom_binary_op.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_custom_binary_op.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_custom_binary_op.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_custom_binary_op.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_custom_binary_op.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_custom_binary_op.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_custom_binary_op.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_custom_binary_op_via_interface.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_custom_binary_op_via_interface.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_custom_binary_op_via_interface.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_custom_binary_op_via_interface.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_custom_binary_op_via_interface.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_custom_binary_op_via_interface.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_custom_binary_op_via_interface.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_custom_binary_op_via_interface.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_custom_index_op.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_custom_index_op.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_custom_index_op.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_custom_index_op.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_custom_index_op.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_custom_index_op.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_custom_index_op.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_custom_index_op.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_custom_index_op_via_interface.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_custom_index_op_via_interface.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_custom_index_op_via_interface.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_custom_index_op_via_interface.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_custom_index_op_via_interface.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_custom_index_op_via_interface.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_custom_index_op_via_interface.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_custom_index_op_via_interface.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_custom_unary_op.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_custom_unary_op.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_custom_unary_op.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_custom_unary_op.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_custom_unary_op.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_custom_unary_op.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_custom_unary_op.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_custom_unary_op.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_custom_unary_op_via_interface.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_custom_unary_op_via_interface.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_custom_unary_op_via_interface.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_custom_unary_op_via_interface.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_custom_unary_op_via_interface.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_custom_unary_op_via_interface.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_custom_unary_op_via_interface.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_custom_unary_op_via_interface.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off_via_interface.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off_via_interface.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off_via_interface.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off_via_interface.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off_via_interface.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off_via_interface.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off_via_interface.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_extract_method_tear_off_via_interface.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_invoke_method.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_invoke_method.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_invoke_method.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_invoke_method.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_invoke_method.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_invoke_method.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_invoke_method.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_invoke_method.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_invoke_method_via_interface.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_invoke_method_via_interface.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_invoke_method_via_interface.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_invoke_method_via_interface.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_invoke_method_via_interface.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_invoke_method_via_interface.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_invoke_method_via_interface.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_invoke_method_via_interface.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_is_enum.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_is_enum.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_is_enum.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_is_enum.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_typedef.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_is_typedef.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_is_typedef.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_is_typedef.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_typedef.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_is_typedef.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_is_typedef.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_is_typedef.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_typedef_parameterized.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_is_typedef_parameterized.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_is_typedef_parameterized.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_is_typedef_parameterized.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_typedef_parameterized.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_is_typedef_parameterized.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_is_typedef_parameterized.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_is_typedef_parameterized.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_via_closure_multiple_levels_of_nesting.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_via_closure_multiple_levels_of_nesting.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_via_closure_multiple_levels_of_nesting.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_via_closure_multiple_levels_of_nesting.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_via_closure_multiple_levels_of_nesting.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_via_closure_multiple_levels_of_nesting.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_via_closure_multiple_levels_of_nesting.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_via_closure_multiple_levels_of_nesting.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_via_closure_type_depends_on_args.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_via_closure_type_depends_on_args.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_via_closure_type_depends_on_args.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_via_closure_type_depends_on_args.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_via_closure_type_depends_on_args.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_via_closure_type_depends_on_args.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_via_closure_type_depends_on_args.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_via_closure_type_depends_on_args.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_field.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_field.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_field.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_top_level.dart.direct.expect b/pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_top_level.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_top_level.dart.direct.expect
rename to pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_top_level.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_top_level.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_top_level.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_top_level.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inferred_type_via_closure_type_independent_of_args_top_level.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/inheritance_does_not_imply_circularity.dart.direct.expect b/pkg/front_end/testcases/inference/inheritance_does_not_imply_circularity.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inheritance_does_not_imply_circularity.dart.direct.expect
rename to pkg/front_end/testcases/inference/inheritance_does_not_imply_circularity.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/inheritance_does_not_imply_circularity.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/inheritance_does_not_imply_circularity.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/inheritance_does_not_imply_circularity.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/inheritance_does_not_imply_circularity.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/instance_creation_downwards.dart.direct.expect b/pkg/front_end/testcases/inference/instance_creation_downwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instance_creation_downwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/instance_creation_downwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/instance_creation_downwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/instance_creation_downwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instance_creation_downwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/instance_creation_downwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.direct.expect b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_tearoff.dart.direct.expect
rename to pkg/front_end/testcases/inference/instantiate_tearoff.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_tearoff.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/instantiate_tearoff.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.type_promotion.expect b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.type_promotion.expect
new file mode 100644
index 0000000..b81ec02
--- /dev/null
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.type_promotion.expect
@@ -0,0 +1,15 @@
+pkg/front_end/testcases/inference/instantiate_tearoff.dart:18:10: Context: Write to func@399
+    func = super. /*@target=C::f*/ f;
+         ^
+pkg/front_end/testcases/inference/instantiate_tearoff.dart:25:8: Context: Write to func@504
+  func = f;
+       ^
+pkg/front_end/testcases/inference/instantiate_tearoff.dart:26:8: Context: Write to func@504
+  func = new C(). /*@target=C::f*/ f;
+       ^
+pkg/front_end/testcases/inference/instantiate_tearoff.dart:27:8: Context: Write to func@504
+  func = C.g;
+       ^
+pkg/front_end/testcases/inference/instantiate_tearoff.dart:28:8: Context: Write to func@504
+  func = h;
+       ^
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.direct.expect b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.direct.expect
rename to pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.direct.expect b/pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.direct.expect
rename to pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.strong.expect b/pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.strong.expect
index c944bdb..dbc978a 100644
--- a/pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.strong.expect
@@ -1,9 +1,19 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart:10:12: Error: A value of type '<T extends dart.core::Object = dynamic>(T) → T' can't be assigned to a variable of type '(dart.core::int) → dart.core::int'.
+// Try changing the type of the left hand side, or casting the right hand side to '(dart.core::int) → dart.core::int'.
+//   func = f.call;
+//            ^
+
 library test;
 import self as self;
 import "dart:core" as core;
 
-static method test(<T extends core::Object>(T) → T f) → void {
+static method test(<T extends core::Object = dynamic>(T) → T f) → void {
   (core::int) → core::int func;
-  func = f.call<core::int>;
+  func = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart:10:12: Error: A value of type '<T extends dart.core::Object = dynamic>(T) \u8594 T' can't be assigned to a variable of type '(dart.core::int) \u8594 dart.core::int'.
+Try changing the type of the left hand side, or casting the right hand side to '(dart.core::int) \u8594 dart.core::int'.
+  func = f.call;
+           ^" in f.call as{TypeError} (core::int) → core::int;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.type_promotion.expect b/pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.type_promotion.expect
new file mode 100644
index 0000000..b654339
--- /dev/null
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/instantiate_tearoff_of_call.dart:10:8: Context: Write to func@314
+  func = f.call;
+       ^
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_after.dart.direct.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_after.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_after.dart.direct.expect
rename to pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_after.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_after.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_after.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_after.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_after.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_before.dart.direct.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_before.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_before.dart.direct.expect
rename to pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_before.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_before.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_before.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_before.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_has_bound_defined_before.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_no_bound.dart.direct.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_no_bound.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_no_bound.dart.direct.expect
rename to pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_no_bound.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_no_bound.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_no_bound.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_no_bound.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/instantiate_to_bounds_generic2_no_bound.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_after.dart.direct.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_after.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_after.dart.direct.expect
rename to pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_after.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_after.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_after.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_after.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_after.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_before.dart.direct.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_before.dart.direct.expect
deleted file mode 100644
index d772694..0000000
--- a/pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_before.dart.direct.expect
+++ /dev/null
@@ -1,13 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-class A<T extends core::int = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T>
-    : super core::Object::•()
-    ;
-}
-static field self::A<dynamic> v = null;
-static method main() → dynamic {
-  self::v;
-}
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_before.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_before.dart.direct.transformed.expect
deleted file mode 100644
index d772694..0000000
--- a/pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_before.dart.direct.transformed.expect
+++ /dev/null
@@ -1,13 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-class A<T extends core::int = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T>
-    : super core::Object::•()
-    ;
-}
-static field self::A<dynamic> v = null;
-static method main() → dynamic {
-  self::v;
-}
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_after.dart.direct.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_before.dart.legacy.expect
similarity index 100%
copy from pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_after.dart.direct.expect
copy to pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_before.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_after.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_before.dart.legacy.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_after.dart.direct.transformed.expect
copy to pkg/front_end/testcases/inference/instantiate_to_bounds_generic_has_bound_defined_before.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_no_bound.dart.direct.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_no_bound.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_no_bound.dart.direct.expect
rename to pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_no_bound.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_no_bound.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_no_bound.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_no_bound.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_no_bound.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_type_args_exact.dart.direct.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_type_args_exact.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_type_args_exact.dart.direct.expect
rename to pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_type_args_exact.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_type_args_exact.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_type_args_exact.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_type_args_exact.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/instantiate_to_bounds_invoke_constructor_type_args_exact.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_not_generic.dart.direct.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_not_generic.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_to_bounds_not_generic.dart.direct.expect
rename to pkg/front_end/testcases/inference/instantiate_to_bounds_not_generic.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/instantiate_to_bounds_not_generic.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/instantiate_to_bounds_not_generic.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/instantiate_to_bounds_not_generic.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/instantiate_to_bounds_not_generic.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/int_upwards_local.dart.direct.expect b/pkg/front_end/testcases/inference/int_upwards_local.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/int_upwards_local.dart.direct.expect
rename to pkg/front_end/testcases/inference/int_upwards_local.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/int_upwards_local.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/int_upwards_local.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/int_upwards_local.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/int_upwards_local.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.direct.expect b/pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.direct.expect
rename to pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.type_promotion.expect b/pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.type_promotion.expect
new file mode 100644
index 0000000..10fcaec
--- /dev/null
+++ b/pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart:19:10: Context: Write to list@521
+    list = <String>[];
+         ^
diff --git a/pkg/front_end/testcases/inference/lambda_return_type.dart.direct.expect b/pkg/front_end/testcases/inference/lambda_return_type.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/lambda_return_type.dart.direct.expect
rename to pkg/front_end/testcases/inference/lambda_return_type.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/lambda_return_type.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/lambda_return_type.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/lambda_return_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/lambda_return_type.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/lambda_void_context.dart.direct.expect b/pkg/front_end/testcases/inference/lambda_void_context.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/lambda_void_context.dart.direct.expect
rename to pkg/front_end/testcases/inference/lambda_void_context.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/lambda_void_context.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/lambda_void_context.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/lambda_void_context.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/lambda_void_context.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/list_literal_typed.dart.direct.expect b/pkg/front_end/testcases/inference/list_literal_typed.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/list_literal_typed.dart.direct.expect
rename to pkg/front_end/testcases/inference/list_literal_typed.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/list_literal_typed.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/list_literal_typed.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/list_literal_typed.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/list_literal_typed.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/list_literals.dart.direct.expect b/pkg/front_end/testcases/inference/list_literals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/list_literals.dart.direct.expect
rename to pkg/front_end/testcases/inference/list_literals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/list_literals.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/list_literals.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/list_literals.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/list_literals.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.direct.expect b/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.direct.expect
rename to pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/list_literals_top_level.dart.direct.expect b/pkg/front_end/testcases/inference/list_literals_top_level.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/list_literals_top_level.dart.direct.expect
rename to pkg/front_end/testcases/inference/list_literals_top_level.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/list_literals_top_level.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/list_literals_top_level.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/list_literals_top_level.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/list_literals_top_level.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/local_constructor_from_arguments.dart.direct.expect b/pkg/front_end/testcases/inference/local_constructor_from_arguments.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/local_constructor_from_arguments.dart.direct.expect
rename to pkg/front_end/testcases/inference/local_constructor_from_arguments.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/local_constructor_from_arguments.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/local_constructor_from_arguments.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/local_constructor_from_arguments.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/local_constructor_from_arguments.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/local_reference_upwards_local.dart.direct.expect b/pkg/front_end/testcases/inference/local_reference_upwards_local.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/local_reference_upwards_local.dart.direct.expect
rename to pkg/front_end/testcases/inference/local_reference_upwards_local.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/local_reference_upwards_local.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/local_reference_upwards_local.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/local_reference_upwards_local.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/local_reference_upwards_local.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/local_return_and_yield.dart.direct.expect b/pkg/front_end/testcases/inference/local_return_and_yield.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/local_return_and_yield.dart.direct.expect
rename to pkg/front_end/testcases/inference/local_return_and_yield.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/local_return_and_yield.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/local_return_and_yield.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/local_return_and_yield.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/local_return_and_yield.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/logical_or_promotion.dart.direct.expect b/pkg/front_end/testcases/inference/logical_or_promotion.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/logical_or_promotion.dart.direct.expect
rename to pkg/front_end/testcases/inference/logical_or_promotion.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/logical_or_promotion.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/logical_or_promotion.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/logical_or_promotion.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/logical_or_promotion.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/logical_or_promotion.dart.type_promotion.expect b/pkg/front_end/testcases/inference/logical_or_promotion.dart.type_promotion.expect
new file mode 100644
index 0000000..88430c6
--- /dev/null
+++ b/pkg/front_end/testcases/inference/logical_or_promotion.dart.type_promotion.expect
@@ -0,0 +1,9 @@
+pkg/front_end/testcases/inference/logical_or_promotion.dart:16:11: Context: Possible promotion of o@338
+    if (o is A || o is B) {
+          ^^
+pkg/front_end/testcases/inference/logical_or_promotion.dart:16:21: Context: Possible promotion of o@338
+    if (o is A || o is B) {
+                    ^^
+pkg/front_end/testcases/inference/logical_or_promotion.dart:17:13: Context: Possible promotion of o@338
+      if (o is A) {
+            ^^
diff --git a/pkg/front_end/testcases/inference/map_literals.dart.direct.expect b/pkg/front_end/testcases/inference/map_literals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/map_literals.dart.direct.expect
rename to pkg/front_end/testcases/inference/map_literals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/map_literals.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/map_literals.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/map_literals.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/map_literals.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.direct.expect b/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.direct.expect
rename to pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/map_literals_top_level.dart.direct.expect b/pkg/front_end/testcases/inference/map_literals_top_level.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/map_literals_top_level.dart.direct.expect
rename to pkg/front_end/testcases/inference/map_literals_top_level.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/map_literals_top_level.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/map_literals_top_level.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/map_literals_top_level.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/map_literals_top_level.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method.dart.direct.expect b/pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method.dart.direct.expect
rename to pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method_identifier_sequence.dart.direct.expect b/pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method_identifier_sequence.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method_identifier_sequence.dart.direct.expect
rename to pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method_identifier_sequence.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method_identifier_sequence.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method_identifier_sequence.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method_identifier_sequence.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/method_call_with_type_arguments_instance_method_identifier_sequence.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/method_call_with_type_arguments_static_method.dart.direct.expect b/pkg/front_end/testcases/inference/method_call_with_type_arguments_static_method.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/method_call_with_type_arguments_static_method.dart.direct.expect
rename to pkg/front_end/testcases/inference/method_call_with_type_arguments_static_method.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/method_call_with_type_arguments_static_method.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/method_call_with_type_arguments_static_method.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/method_call_with_type_arguments_static_method.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/method_call_with_type_arguments_static_method.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/method_call_with_type_arguments_top_level_function.dart.direct.expect b/pkg/front_end/testcases/inference/method_call_with_type_arguments_top_level_function.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/method_call_with_type_arguments_top_level_function.dart.direct.expect
rename to pkg/front_end/testcases/inference/method_call_with_type_arguments_top_level_function.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/method_call_with_type_arguments_top_level_function.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/method_call_with_type_arguments_top_level_function.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/method_call_with_type_arguments_top_level_function.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/method_call_with_type_arguments_top_level_function.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.direct.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.direct.expect
rename to pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.direct.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.direct.expect
rename to pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.direct.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.direct.expect
rename to pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.direct.expect b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.direct.expect
rename to pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.direct.expect b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.direct.expect
rename to pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.direct.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.direct.expect
rename to pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.direct.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.direct.expect
rename to pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.direct.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.direct.expect
rename to pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.direct.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.direct.expect
rename to pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.direct.expect b/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.direct.expect
rename to pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.direct.expect b/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.direct.expect
rename to pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart.direct.expect b/pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart.direct.expect
rename to pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart.type_promotion.expect b/pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart.type_promotion.expect
new file mode 100644
index 0000000..d405d4e
--- /dev/null
+++ b/pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/no_error_when_declared_type_is_num_and_assigned_null.dart:10:5: Context: Write to x@278
+  x = null;
+    ^
diff --git a/pkg/front_end/testcases/inference/non_const_invocation.dart.direct.expect b/pkg/front_end/testcases/inference/non_const_invocation.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/non_const_invocation.dart.direct.expect
rename to pkg/front_end/testcases/inference/non_const_invocation.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/non_const_invocation.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/non_const_invocation.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/non_const_invocation.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/non_const_invocation.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.direct.expect b/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.direct.expect
rename to pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/non_inferrable_getter_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/null_aware_method_invocation.dart.direct.expect b/pkg/front_end/testcases/inference/null_aware_method_invocation.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/null_aware_method_invocation.dart.direct.expect
rename to pkg/front_end/testcases/inference/null_aware_method_invocation.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/null_aware_method_invocation.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/null_aware_method_invocation.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/null_aware_method_invocation.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/null_aware_method_invocation.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/null_aware_property_get.dart.direct.expect b/pkg/front_end/testcases/inference/null_aware_property_get.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/null_aware_property_get.dart.direct.expect
rename to pkg/front_end/testcases/inference/null_aware_property_get.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/null_aware_property_get.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/null_aware_property_get.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/null_aware_property_get.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/null_aware_property_get.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/null_coalescing_operator.dart.direct.expect b/pkg/front_end/testcases/inference/null_coalescing_operator.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/null_coalescing_operator.dart.direct.expect
rename to pkg/front_end/testcases/inference/null_coalescing_operator.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/null_coalescing_operator.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/null_coalescing_operator.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/null_coalescing_operator.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/null_coalescing_operator.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.direct.expect b/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.direct.expect
rename to pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.direct.expect b/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.direct.expect
rename to pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.type_promotion.expect b/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.type_promotion.expect
new file mode 100644
index 0000000..1eed720
--- /dev/null
+++ b/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart:15:5: Context: Write to f@369
+  f = /*@returnType=Null*/ (/*@type=Object*/ x) => 'hello';
+    ^
+pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart:18:5: Context: Write to g@542
+  g = 'hello';
+    ^
diff --git a/pkg/front_end/testcases/inference/overloaded_int_operators.dart.direct.expect b/pkg/front_end/testcases/inference/overloaded_int_operators.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/overloaded_int_operators.dart.direct.expect
rename to pkg/front_end/testcases/inference/overloaded_int_operators.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/overloaded_int_operators.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/overloaded_int_operators.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/overloaded_int_operators.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/overloaded_int_operators.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/override_equals.dart.direct.expect b/pkg/front_end/testcases/inference/override_equals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/override_equals.dart.direct.expect
rename to pkg/front_end/testcases/inference/override_equals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/override_equals.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/override_equals.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/override_equals.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/override_equals.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.direct.expect b/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.direct.expect b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/promote_bounds.dart.direct.expect b/pkg/front_end/testcases/inference/promote_bounds.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/promote_bounds.dart.direct.expect
rename to pkg/front_end/testcases/inference/promote_bounds.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/promote_bounds.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/promote_bounds.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/promote_bounds.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/promote_bounds.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/promote_bounds.dart.type_promotion.expect b/pkg/front_end/testcases/inference/promote_bounds.dart.type_promotion.expect
new file mode 100644
index 0000000..90d61ac
--- /dev/null
+++ b/pkg/front_end/testcases/inference/promote_bounds.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/promote_bounds.dart:17:9: Context: Possible promotion of a@366
+  if (a is String) {
+        ^^
+pkg/front_end/testcases/inference/promote_bounds.dart:21:9: Context: Possible promotion of a@366
+  if (a is C) {
+        ^^
diff --git a/pkg/front_end/testcases/inference/promote_from_logical_rhs.dart.direct.expect b/pkg/front_end/testcases/inference/promote_from_logical_rhs.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/promote_from_logical_rhs.dart.direct.expect
rename to pkg/front_end/testcases/inference/promote_from_logical_rhs.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/promote_from_logical_rhs.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/promote_from_logical_rhs.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/promote_from_logical_rhs.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/promote_from_logical_rhs.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/promote_from_logical_rhs.dart.type_promotion.expect b/pkg/front_end/testcases/inference/promote_from_logical_rhs.dart.type_promotion.expect
new file mode 100644
index 0000000..dafde1f
--- /dev/null
+++ b/pkg/front_end/testcases/inference/promote_from_logical_rhs.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/promote_from_logical_rhs.dart:9:14: Context: Possible promotion of a@279
+  if (b && a is int) {
+             ^^
diff --git a/pkg/front_end/testcases/inference/promotion_subtype_check.dart.direct.expect b/pkg/front_end/testcases/inference/promotion_subtype_check.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/promotion_subtype_check.dart.direct.expect
rename to pkg/front_end/testcases/inference/promotion_subtype_check.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/promotion_subtype_check.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/promotion_subtype_check.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/promotion_subtype_check.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/promotion_subtype_check.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/promotion_subtype_check.dart.type_promotion.expect b/pkg/front_end/testcases/inference/promotion_subtype_check.dart.type_promotion.expect
new file mode 100644
index 0000000..93c14dd
--- /dev/null
+++ b/pkg/front_end/testcases/inference/promotion_subtype_check.dart.type_promotion.expect
@@ -0,0 +1,9 @@
+pkg/front_end/testcases/inference/promotion_subtype_check.dart:9:9: Context: Possible promotion of x@276
+  if (x is int) {
+        ^^
+pkg/front_end/testcases/inference/promotion_subtype_check.dart:10:33: Context: Possible promotion of x@276
+    if (/*@promotedType=int*/ x is String) {
+                                ^^
+pkg/front_end/testcases/inference/promotion_subtype_check.dart:18:9: Context: Possible promotion of x@276
+  if (x is String) {
+        ^^
diff --git a/pkg/front_end/testcases/inference/propagate_inference_to_field_in_class.dart.direct.expect b/pkg/front_end/testcases/inference/propagate_inference_to_field_in_class.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/propagate_inference_to_field_in_class.dart.direct.expect
rename to pkg/front_end/testcases/inference/propagate_inference_to_field_in_class.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/propagate_inference_to_field_in_class.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/propagate_inference_to_field_in_class.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/propagate_inference_to_field_in_class.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/propagate_inference_to_field_in_class.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/propagate_inference_to_field_in_class_dynamic_warnings.dart.direct.expect b/pkg/front_end/testcases/inference/propagate_inference_to_field_in_class_dynamic_warnings.dart.direct.expect
deleted file mode 100644
index 2b18c7f..0000000
--- a/pkg/front_end/testcases/inference/propagate_inference_to_field_in_class_dynamic_warnings.dart.direct.expect
+++ /dev/null
@@ -1,16 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-class A extends core::Object {
-  field core::int x = 2;
-  synthetic constructor •() → self::A
-    : super core::Object::•()
-    ;
-}
-static method main() → dynamic {
-  dynamic a = new self::A::•();
-  self::A b = a;
-  core::print(a.x);
-  core::print(a.x.+(2));
-}
diff --git a/pkg/front_end/testcases/inference/propagate_inference_to_field_in_class_dynamic_warnings.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/propagate_inference_to_field_in_class_dynamic_warnings.dart.direct.transformed.expect
deleted file mode 100644
index 2b18c7f..0000000
--- a/pkg/front_end/testcases/inference/propagate_inference_to_field_in_class_dynamic_warnings.dart.direct.transformed.expect
+++ /dev/null
@@ -1,16 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-class A extends core::Object {
-  field core::int x = 2;
-  synthetic constructor •() → self::A
-    : super core::Object::•()
-    ;
-}
-static method main() → dynamic {
-  dynamic a = new self::A::•();
-  self::A b = a;
-  core::print(a.x);
-  core::print(a.x.+(2));
-}
diff --git a/pkg/front_end/testcases/inference/propagate_inference_to_field_in_class.dart.direct.expect b/pkg/front_end/testcases/inference/propagate_inference_to_field_in_class_dynamic_warnings.dart.legacy.expect
similarity index 100%
copy from pkg/front_end/testcases/inference/propagate_inference_to_field_in_class.dart.direct.expect
copy to pkg/front_end/testcases/inference/propagate_inference_to_field_in_class_dynamic_warnings.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/propagate_inference_to_field_in_class.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/propagate_inference_to_field_in_class_dynamic_warnings.dart.legacy.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/inference/propagate_inference_to_field_in_class.dart.direct.transformed.expect
copy to pkg/front_end/testcases/inference/propagate_inference_to_field_in_class_dynamic_warnings.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/propagate_inference_transitively.dart.direct.expect b/pkg/front_end/testcases/inference/propagate_inference_transitively.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/propagate_inference_transitively.dart.direct.expect
rename to pkg/front_end/testcases/inference/propagate_inference_transitively.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/propagate_inference_transitively.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/propagate_inference_transitively.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/propagate_inference_transitively.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/propagate_inference_transitively.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/propagate_inference_transitively2.dart.direct.expect b/pkg/front_end/testcases/inference/propagate_inference_transitively2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/propagate_inference_transitively2.dart.direct.expect
rename to pkg/front_end/testcases/inference/propagate_inference_transitively2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/propagate_inference_transitively2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/propagate_inference_transitively2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/propagate_inference_transitively2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/propagate_inference_transitively2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/propagate_variable_get.dart.direct.expect b/pkg/front_end/testcases/inference/propagate_variable_get.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/propagate_variable_get.dart.direct.expect
rename to pkg/front_end/testcases/inference/propagate_variable_get.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/propagate_variable_get.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/propagate_variable_get.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/propagate_variable_get.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/propagate_variable_get.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/property_get_toplevel.dart.direct.expect b/pkg/front_end/testcases/inference/property_get_toplevel.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/property_get_toplevel.dart.direct.expect
rename to pkg/front_end/testcases/inference/property_get_toplevel.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/property_get_toplevel.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/property_get_toplevel.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/property_get_toplevel.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/property_get_toplevel.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/property_set.dart.direct.expect b/pkg/front_end/testcases/inference/property_set.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/property_set.dart.direct.expect
rename to pkg/front_end/testcases/inference/property_set.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/property_set.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/property_set.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/property_set.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/property_set.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/property_set_bad_setter.dart.direct.expect b/pkg/front_end/testcases/inference/property_set_bad_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/property_set_bad_setter.dart.direct.expect
rename to pkg/front_end/testcases/inference/property_set_bad_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/property_set_bad_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/property_set_bad_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/property_set_bad_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/property_set_bad_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/recursive_generic_function.dart.direct.expect b/pkg/front_end/testcases/inference/recursive_generic_function.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/recursive_generic_function.dart.direct.expect
rename to pkg/front_end/testcases/inference/recursive_generic_function.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/recursive_generic_function.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/recursive_generic_function.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/recursive_generic_function.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/recursive_generic_function.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/reference_to_typedef.dart.direct.expect b/pkg/front_end/testcases/inference/reference_to_typedef.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/reference_to_typedef.dart.direct.expect
rename to pkg/front_end/testcases/inference/reference_to_typedef.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/reference_to_typedef.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/reference_to_typedef.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/reference_to_typedef.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/reference_to_typedef.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_double.dart.direct.expect b/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_double.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_double.dart.direct.expect
rename to pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_double.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_double.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_double.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_double.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_double.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_int.dart.direct.expect b/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_int.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_int.dart.direct.expect
rename to pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_int.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_int.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_int.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_int.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_int.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_t.dart.direct.expect b/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_t.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_t.dart.direct.expect
rename to pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_t.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_t.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_t.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_t.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/refine_binary_expression_type_type_parameter_t_t.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/setter_return_type.dart.direct.expect b/pkg/front_end/testcases/inference/setter_return_type.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/setter_return_type.dart.direct.expect
rename to pkg/front_end/testcases/inference/setter_return_type.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/setter_return_type.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/setter_return_type.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/setter_return_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/setter_return_type.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/simple_literal_bool.dart.direct.expect b/pkg/front_end/testcases/inference/simple_literal_bool.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/simple_literal_bool.dart.direct.expect
rename to pkg/front_end/testcases/inference/simple_literal_bool.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/simple_literal_bool.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/simple_literal_bool.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/simple_literal_bool.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/simple_literal_bool.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/simple_literal_double.dart.direct.expect b/pkg/front_end/testcases/inference/simple_literal_double.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/simple_literal_double.dart.direct.expect
rename to pkg/front_end/testcases/inference/simple_literal_double.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/simple_literal_double.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/simple_literal_double.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/simple_literal_double.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/simple_literal_double.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/simple_literal_int.dart.direct.expect b/pkg/front_end/testcases/inference/simple_literal_int.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/simple_literal_int.dart.direct.expect
rename to pkg/front_end/testcases/inference/simple_literal_int.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/simple_literal_int.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/simple_literal_int.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/simple_literal_int.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/simple_literal_int.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/simple_literal_null.dart.direct.expect b/pkg/front_end/testcases/inference/simple_literal_null.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/simple_literal_null.dart.direct.expect
rename to pkg/front_end/testcases/inference/simple_literal_null.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/simple_literal_null.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/simple_literal_null.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/simple_literal_null.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/simple_literal_null.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/static_method_tear_off.dart.direct.expect b/pkg/front_end/testcases/inference/static_method_tear_off.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/static_method_tear_off.dart.direct.expect
rename to pkg/front_end/testcases/inference/static_method_tear_off.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/static_method_tear_off.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/static_method_tear_off.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/static_method_tear_off.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/static_method_tear_off.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/string_literal.dart.direct.expect b/pkg/front_end/testcases/inference/string_literal.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/string_literal.dart.direct.expect
rename to pkg/front_end/testcases/inference/string_literal.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/string_literal.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/string_literal.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/string_literal.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/string_literal.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/subexpressions_of_explicitly_typed_fields.dart.direct.expect b/pkg/front_end/testcases/inference/subexpressions_of_explicitly_typed_fields.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/subexpressions_of_explicitly_typed_fields.dart.direct.expect
rename to pkg/front_end/testcases/inference/subexpressions_of_explicitly_typed_fields.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/subexpressions_of_explicitly_typed_fields.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/subexpressions_of_explicitly_typed_fields.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/subexpressions_of_explicitly_typed_fields.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/subexpressions_of_explicitly_typed_fields.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/super_index_set.dart.direct.expect b/pkg/front_end/testcases/inference/super_index_set.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_index_set.dart.direct.expect
rename to pkg/front_end/testcases/inference/super_index_set.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/super_index_set.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/super_index_set.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_index_set.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/super_index_set.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/super_index_set_substitution.dart.direct.expect b/pkg/front_end/testcases/inference/super_index_set_substitution.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_index_set_substitution.dart.direct.expect
rename to pkg/front_end/testcases/inference/super_index_set_substitution.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/super_index_set_substitution.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/super_index_set_substitution.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_index_set_substitution.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/super_index_set_substitution.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/super_initializer.dart.direct.expect b/pkg/front_end/testcases/inference/super_initializer.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_initializer.dart.direct.expect
rename to pkg/front_end/testcases/inference/super_initializer.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/super_initializer.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/super_initializer.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_initializer.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/super_initializer.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/super_initializer_substitution.dart.direct.expect b/pkg/front_end/testcases/inference/super_initializer_substitution.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_initializer_substitution.dart.direct.expect
rename to pkg/front_end/testcases/inference/super_initializer_substitution.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/super_initializer_substitution.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/super_initializer_substitution.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_initializer_substitution.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/super_initializer_substitution.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/super_method_invocation.dart.direct.expect b/pkg/front_end/testcases/inference/super_method_invocation.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_method_invocation.dart.direct.expect
rename to pkg/front_end/testcases/inference/super_method_invocation.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/super_method_invocation.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/super_method_invocation.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_method_invocation.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/super_method_invocation.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/super_method_invocation_substitution.dart.direct.expect b/pkg/front_end/testcases/inference/super_method_invocation_substitution.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_method_invocation_substitution.dart.direct.expect
rename to pkg/front_end/testcases/inference/super_method_invocation_substitution.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/super_method_invocation_substitution.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/super_method_invocation_substitution.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_method_invocation_substitution.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/super_method_invocation_substitution.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/super_property_get.dart.direct.expect b/pkg/front_end/testcases/inference/super_property_get.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_property_get.dart.direct.expect
rename to pkg/front_end/testcases/inference/super_property_get.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/super_property_get.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/super_property_get.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_property_get.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/super_property_get.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/super_property_get_invoke_function_typed.dart.direct.expect b/pkg/front_end/testcases/inference/super_property_get_invoke_function_typed.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_property_get_invoke_function_typed.dart.direct.expect
rename to pkg/front_end/testcases/inference/super_property_get_invoke_function_typed.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/super_property_get_invoke_function_typed.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/super_property_get_invoke_function_typed.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_property_get_invoke_function_typed.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/super_property_get_invoke_function_typed.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/super_property_get_invoke_implicit_call.dart.direct.expect b/pkg/front_end/testcases/inference/super_property_get_invoke_implicit_call.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_property_get_invoke_implicit_call.dart.direct.expect
rename to pkg/front_end/testcases/inference/super_property_get_invoke_implicit_call.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/super_property_get_invoke_implicit_call.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/super_property_get_invoke_implicit_call.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_property_get_invoke_implicit_call.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/super_property_get_invoke_implicit_call.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/super_property_get_substitution.dart.direct.expect b/pkg/front_end/testcases/inference/super_property_get_substitution.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_property_get_substitution.dart.direct.expect
rename to pkg/front_end/testcases/inference/super_property_get_substitution.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/super_property_get_substitution.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/super_property_get_substitution.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_property_get_substitution.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/super_property_get_substitution.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/super_property_get_tearoff.dart.direct.expect b/pkg/front_end/testcases/inference/super_property_get_tearoff.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_property_get_tearoff.dart.direct.expect
rename to pkg/front_end/testcases/inference/super_property_get_tearoff.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/super_property_get_tearoff.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/super_property_get_tearoff.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_property_get_tearoff.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/super_property_get_tearoff.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/super_property_set_substitution.dart.direct.expect b/pkg/front_end/testcases/inference/super_property_set_substitution.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_property_set_substitution.dart.direct.expect
rename to pkg/front_end/testcases/inference/super_property_set_substitution.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/super_property_set_substitution.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/super_property_set_substitution.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/super_property_set_substitution.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/super_property_set_substitution.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/switch_continue.dart.direct.expect b/pkg/front_end/testcases/inference/switch_continue.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/switch_continue.dart.direct.expect
rename to pkg/front_end/testcases/inference/switch_continue.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/switch_continue.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/switch_continue.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/switch_continue.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/switch_continue.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/symbol_literal.dart.direct.expect b/pkg/front_end/testcases/inference/symbol_literal.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/symbol_literal.dart.direct.expect
rename to pkg/front_end/testcases/inference/symbol_literal.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/symbol_literal.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/symbol_literal.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/symbol_literal.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/symbol_literal.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/this_reference.dart.direct.expect b/pkg/front_end/testcases/inference/this_reference.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/this_reference.dart.direct.expect
rename to pkg/front_end/testcases/inference/this_reference.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/this_reference.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/this_reference.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/this_reference.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/this_reference.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.direct.expect b/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/top_level_return_and_yield.dart.direct.expect
rename to pkg/front_end/testcases/inference/top_level_return_and_yield.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/top_level_return_and_yield.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/top_level_return_and_yield.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.direct.expect b/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.direct.expect
rename to pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/try_catch.dart.direct.expect b/pkg/front_end/testcases/inference/try_catch.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/try_catch.dart.direct.expect
rename to pkg/front_end/testcases/inference/try_catch.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/try_catch.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/try_catch.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/try_catch.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/try_catch.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/try_catch_finally.dart.direct.expect b/pkg/front_end/testcases/inference/try_catch_finally.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/try_catch_finally.dart.direct.expect
rename to pkg/front_end/testcases/inference/try_catch_finally.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/try_catch_finally.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/try_catch_finally.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/try_catch_finally.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/try_catch_finally.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/try_catch_promotion.dart.direct.expect b/pkg/front_end/testcases/inference/try_catch_promotion.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/try_catch_promotion.dart.direct.expect
rename to pkg/front_end/testcases/inference/try_catch_promotion.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/try_catch_promotion.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/try_catch_promotion.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/try_catch_promotion.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/try_catch_promotion.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/try_catch_promotion.dart.type_promotion.expect b/pkg/front_end/testcases/inference/try_catch_promotion.dart.type_promotion.expect
new file mode 100644
index 0000000..d34e2ca
--- /dev/null
+++ b/pkg/front_end/testcases/inference/try_catch_promotion.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/try_catch_promotion.dart:20:11: Context: Possible promotion of x@382
+    if (x is D) {
+          ^^
+pkg/front_end/testcases/inference/try_catch_promotion.dart:23:11: Context: Possible promotion of y@385
+    if (y is E) {
+          ^^
diff --git a/pkg/front_end/testcases/inference/try_finally.dart.direct.expect b/pkg/front_end/testcases/inference/try_finally.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/try_finally.dart.direct.expect
rename to pkg/front_end/testcases/inference/try_finally.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/try_finally.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/try_finally.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/try_finally.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/try_finally.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/type_cast.dart.direct.expect b/pkg/front_end/testcases/inference/type_cast.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/type_cast.dart.direct.expect
rename to pkg/front_end/testcases/inference/type_cast.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/type_cast.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/type_cast.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/type_cast.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/type_cast.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.direct.expect b/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.direct.expect
rename to pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/type_promotion_ignores_local_functions.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/type_promotion_not_and_not.dart.direct.expect b/pkg/front_end/testcases/inference/type_promotion_not_and_not.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/type_promotion_not_and_not.dart.direct.expect
rename to pkg/front_end/testcases/inference/type_promotion_not_and_not.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/type_promotion_not_and_not.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/type_promotion_not_and_not.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/type_promotion_not_and_not.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/type_promotion_not_and_not.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/type_promotion_simple.dart.direct.expect b/pkg/front_end/testcases/inference/type_promotion_simple.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/type_promotion_simple.dart.direct.expect
rename to pkg/front_end/testcases/inference/type_promotion_simple.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/type_promotion_simple.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/type_promotion_simple.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/type_promotion_simple.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/type_promotion_simple.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/type_promotion_simple.dart.type_promotion.expect b/pkg/front_end/testcases/inference/type_promotion_simple.dart.type_promotion.expect
new file mode 100644
index 0000000..364cd86
--- /dev/null
+++ b/pkg/front_end/testcases/inference/type_promotion_simple.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/inference/type_promotion_simple.dart:10:9: Context: Possible promotion of n@279
+  if (n is int) {
+        ^^
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.direct.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.direct.expect
rename to pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.type_promotion.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.type_promotion.expect
new file mode 100644
index 0000000..d1dd6f5
--- /dev/null
+++ b/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart:10:9: Context: Possible promotion of n@279
+  if (n is int) {
+        ^^
+pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart:16:5: Context: Write to n@279
+  n = null;
+    ^
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart.direct.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart.direct.expect
rename to pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart.type_promotion.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart.type_promotion.expect
new file mode 100644
index 0000000..3a7414e
--- /dev/null
+++ b/pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart:10:9: Context: Possible promotion of n@279
+  if (n is int) {
+        ^^
+pkg/front_end/testcases/inference/type_promotion_stopped_by_assignment_in_scope.dart:12:7: Context: Write to n@279
+    n = null;
+      ^
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.direct.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.direct.expect
rename to pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.type_promotion.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.type_promotion.expect
new file mode 100644
index 0000000..c5a50d4
--- /dev/null
+++ b/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart:10:9: Context: Possible promotion of n@279
+  if (n is int) {
+        ^^
+pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart:14:7: Context: Write to n@279
+    n = null;
+      ^
diff --git a/pkg/front_end/testcases/inference/unresolved_super.dart.direct.expect b/pkg/front_end/testcases/inference/unresolved_super.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unresolved_super.dart.direct.expect
rename to pkg/front_end/testcases/inference/unresolved_super.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unresolved_super.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unresolved_super.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unresolved_super.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unresolved_super.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_closure_call.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_closure_call.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_closure_call.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_closure_call.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_closure_call.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_closure_call.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_closure_call.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_closure_call.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_dynamic_param.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_dynamic_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_dynamic_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_dynamic_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_dynamic_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_dynamic_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_dynamic_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_dynamic_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_type_param.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_type_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_type_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_type_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_type_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_type_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_type_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_explicit_type_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_implicit_type_param.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_implicit_type_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_implicit_type_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_implicit_type_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_implicit_type_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_implicit_type_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_implicit_type_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_implicit_type_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_no_type_param.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_no_type_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_no_type_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_no_type_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_no_type_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_no_type_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_no_type_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_constructor_call_no_type_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_untyped.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_untyped.dart.direct.expect
deleted file mode 100644
index 52a9a4a..0000000
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_untyped.dart.direct.expect
+++ /dev/null
@@ -1,8 +0,0 @@
-library test;
-import self as self;
-
-static method main() → dynamic {
-  dynamic v = <dynamic>[() → dynamic {
-    return 1;
-  }];
-}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_untyped.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_untyped.dart.direct.transformed.expect
deleted file mode 100644
index 52a9a4a..0000000
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_untyped.dart.direct.transformed.expect
+++ /dev/null
@@ -1,8 +0,0 @@
-library test;
-import self as self;
-
-static method main() → dynamic {
-  dynamic v = <dynamic>[() → dynamic {
-    return 1;
-  }];
-}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_untyped.dart.legacy.expect
similarity index 100%
copy from pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.direct.expect
copy to pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_untyped.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_untyped.dart.legacy.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.direct.transformed.expect
copy to pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_untyped.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_dynamic.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_dynamic.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_dynamic.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_dynamic.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_dynamic.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_dynamic.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_dynamic.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_dynamic.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_typed.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_typed.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_typed.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_typed.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_typed.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_typed.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_typed.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_typed.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_untyped.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_untyped.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_untyped.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_untyped.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_untyped.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_untyped.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_untyped.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_map_untyped.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_dynamic_param.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_dynamic_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_dynamic_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_dynamic_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_dynamic_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_dynamic_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_dynamic_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_dynamic_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_type_param.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_type_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_type_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_type_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_type_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_type_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_type_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_type_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_implicit_type_param.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_implicit_type_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_implicit_type_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_implicit_type_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_implicit_type_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_implicit_type_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_implicit_type_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_implicit_type_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_no_type_param.dart.direct.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_no_type_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_no_type_param.dart.direct.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_no_type_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_no_type_param.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_no_type_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_no_type_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_no_type_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.direct.expect b/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.direct.expect
rename to pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.type_promotion.expect b/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.type_promotion.expect
new file mode 100644
index 0000000..96232fc
--- /dev/null
+++ b/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.type_promotion.expect
@@ -0,0 +1,12 @@
+pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart:29:5: Context: Write to x@559
+  x = 123;
+    ^
+pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart:30:5: Context: Write to x@559
+  x = 'hi';
+    ^
+pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart:31:5: Context: Write to y@612
+  y = /*error:INVALID_ASSIGNMENT*/ 123;
+    ^
+pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart:32:5: Context: Write to y@612
+  y = /*error:INVALID_ASSIGNMENT*/ 'hi';
+    ^
diff --git a/pkg/front_end/testcases/inference_new/const_invocation.dart.direct.expect b/pkg/front_end/testcases/inference_new/const_invocation.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/const_invocation.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/const_invocation.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/const_invocation.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/const_invocation.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/const_invocation.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/const_invocation.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.direct.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.direct.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/do_loop.dart.direct.expect b/pkg/front_end/testcases/inference_new/do_loop.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/do_loop.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/do_loop.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/do_loop.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/do_loop.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/do_loop.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/do_loop.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level.dart.direct.expect b/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level_2.dart.direct.expect b/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level_2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level_2.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level_2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level_2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level_2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level_2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level_2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.direct.expect b/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/field_inference_circularity.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/field_inference_circularity.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/field_inference_circularity.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/field_inference_circularity.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart.direct.expect b/pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.direct.expect b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.direct.expect b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.direct.expect b/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this_upwards.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index_super.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index_super_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index_this.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index_this_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.type_promotion.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.type_promotion.expect
new file mode 100644
index 0000000..ca45342
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.type_promotion.expect
@@ -0,0 +1,42 @@
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:23:9: Context: Write to local@474
+  local = /*@typeArgs=B*/ f();
+        ^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:24:9: Context: Write to local@474
+  local ??= /*@typeArgs=B*/ f();
+        ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:25:9: Context: Write to local@474
+  local += /*@typeArgs=dynamic*/ f();
+        ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:26:9: Context: Write to local@474
+  local *= /*@typeArgs=dynamic*/ f();
+        ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:27:9: Context: Write to local@474
+  local &= /*@typeArgs=dynamic*/ f();
+        ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:28:3: Context: Write to local@474
+  --local;
+  ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:29:8: Context: Write to local@474
+  local--;
+       ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:30:30: Context: Write to local@474
+  var /*@type=B*/ v1 = local = /*@typeArgs=B*/ f();
+                             ^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:31:30: Context: Write to local@474
+  var /*@type=B*/ v2 = local ??= /*@typeArgs=B*/ f();
+                             ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:32:30: Context: Write to local@474
+  var /*@type=A*/ v3 = local += /*@typeArgs=dynamic*/ f();
+                             ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:33:30: Context: Write to local@474
+  var /*@type=B*/ v4 = local *= /*@typeArgs=dynamic*/ f();
+                             ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:34:30: Context: Write to local@474
+  var /*@type=C*/ v5 = local &= /*@typeArgs=dynamic*/ f();
+                             ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:35:24: Context: Write to local@474
+  var /*@type=B*/ v6 = --local;
+                       ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:36:29: Context: Write to local@474
+  var /*@type=B*/ v7 = local--;
+                            ^^
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.type_promotion.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.type_promotion.expect
new file mode 100644
index 0000000..b6c751d
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.type_promotion.expect
@@ -0,0 +1,84 @@
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:13:28: Context: Write to t@343
+  var /*@type=int*/ v1 = t = getInt();
+                           ^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:14:28: Context: Write to t@343
+  var /*@type=num*/ v2 = t = getNum();
+                           ^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:15:28: Context: Write to t@343
+  var /*@type=int*/ v4 = t ??= getInt();
+                           ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:16:28: Context: Write to t@343
+  var /*@type=num*/ v5 = t ??= getNum();
+                           ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:17:28: Context: Write to t@343
+  var /*@type=int*/ v7 = t += getInt();
+                           ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:18:28: Context: Write to t@343
+  var /*@type=num*/ v8 = t += getNum();
+                           ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:19:27: Context: Write to t@343
+  var /*@type=int*/ v10 = ++t;
+                          ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:20:28: Context: Write to t@343
+  var /*@type=int*/ v11 = t++;
+                           ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:24:28: Context: Write to t@343
+  var /*@type=int*/ v1 = t = getInt();
+                           ^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:25:28: Context: Write to t@343
+  var /*@type=num*/ v2 = t = getNum();
+                           ^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:26:31: Context: Write to t@343
+  var /*@type=double*/ v3 = t = getDouble();
+                              ^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:27:28: Context: Write to t@343
+  var /*@type=num*/ v4 = t ??= getInt();
+                           ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:28:28: Context: Write to t@343
+  var /*@type=num*/ v5 = t ??= getNum();
+                           ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:29:28: Context: Write to t@343
+  var /*@type=num*/ v6 = t ??= getDouble();
+                           ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:30:28: Context: Write to t@343
+  var /*@type=num*/ v7 = t += getInt();
+                           ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:31:28: Context: Write to t@343
+  var /*@type=num*/ v8 = t += getNum();
+                           ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:32:28: Context: Write to t@343
+  var /*@type=num*/ v9 = t += getDouble();
+                           ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:33:27: Context: Write to t@343
+  var /*@type=num*/ v10 = ++t;
+                          ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:34:28: Context: Write to t@343
+  var /*@type=num*/ v11 = t++;
+                           ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:38:28: Context: Write to t@343
+  var /*@type=num*/ v2 = t = getNum();
+                           ^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:39:31: Context: Write to t@343
+  var /*@type=double*/ v3 = t = getDouble();
+                              ^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:40:28: Context: Write to t@343
+  var /*@type=num*/ v5 = t ??= getNum();
+                           ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:41:31: Context: Write to t@343
+  var /*@type=double*/ v6 = t ??= getDouble();
+                              ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:42:31: Context: Write to t@343
+  var /*@type=double*/ v7 = t += getInt();
+                              ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:43:31: Context: Write to t@343
+  var /*@type=double*/ v8 = t += getNum();
+                              ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:44:31: Context: Write to t@343
+  var /*@type=double*/ v9 = t += getDouble();
+                              ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:45:30: Context: Write to t@343
+  var /*@type=double*/ v10 = ++t;
+                             ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:46:31: Context: Write to t@343
+  var /*@type=double*/ v11 = t++;
+                              ^^
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_ref.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_static_upwards.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_static_upwards.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_static_upwards.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_static_upwards.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_static_upwards.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_static_upwards.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_assign_to_static_upwards.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_assign_to_static_upwards.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
index 0643685..37904ca 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
@@ -1,7 +1,7 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:24: Error: The return type of the method 'B::x' is dart.core::int, which does not match the return type of the overridden method (dart.core::double).
-// Change to a subtype of dart.core::double.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:24: Error: The return type of the method 'B::x' is 'dart.core::int', which does not match the return type of the overridden method, 'dart.core::double'.
+// Change to a subtype of 'dart.core::double'.
 //   var /*@topType=int*/ x;
 //                        ^
 // pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:10:12: Context: This is the overridden method ('x').
@@ -10,8 +10,8 @@
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:24: Error: The return type of the method 'B::x' is dart.core::int, which does not match the return type of the overridden method (dart.core::double).
-// Change to a subtype of dart.core::double.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:24: Error: The return type of the method 'B::x' is 'dart.core::int', which does not match the return type of the overridden method, 'dart.core::double'.
+// Change to a subtype of 'dart.core::double'.
 //   var /*@topType=int*/ x;
 //                        ^
 
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
index 14bfe0d..0e2da1c 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
@@ -1,7 +1,7 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:24: Error: The return type of the method 'C::x' is dart.core::int, which does not match the return type of the overridden method (dart.core::num).
-// Change to a subtype of dart.core::num.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:24: Error: The return type of the method 'C::x' is 'dart.core::int', which does not match the return type of the overridden method, 'dart.core::num'.
+// Change to a subtype of 'dart.core::num'.
 //   var /*@topType=int*/ x;
 //                        ^
 // pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:9:12: Context: This is the overridden method ('x').
@@ -10,8 +10,8 @@
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:24: Error: The return type of the method 'C::x' is dart.core::int, which does not match the return type of the overridden method (dart.core::num).
-// Change to a subtype of dart.core::num.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:24: Error: The return type of the method 'C::x' is 'dart.core::int', which does not match the return type of the overridden method, 'dart.core::num'.
+// Change to a subtype of 'dart.core::num'.
 //   var /*@topType=int*/ x;
 //                        ^
 
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_logical.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_logical.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_logical.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_logical.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_logical.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_logical.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_logical.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_logical.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_use_of_void.dart.direct.expect b/pkg/front_end/testcases/inference_new/infer_use_of_void.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_use_of_void.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/infer_use_of_void.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/infer_use_of_void.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/infer_use_of_void.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/infer_use_of_void.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/infer_use_of_void.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.direct.expect b/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.direct.expect b/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.direct.expect b/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/multiple_interface_inheritance.dart.direct.expect b/pkg/front_end/testcases/inference_new/multiple_interface_inheritance.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/multiple_interface_inheritance.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/multiple_interface_inheritance.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/multiple_interface_inheritance.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/multiple_interface_inheritance.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/multiple_interface_inheritance.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/multiple_interface_inheritance.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.direct.expect b/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/property_assign_combiner.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/property_assign_combiner.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/property_assign_combiner.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/property_assign_combiner.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.direct.expect b/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/property_get_toplevel.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/property_get_toplevel.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/property_get_toplevel.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/property_get_toplevel.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.direct.expect b/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/static_assign_combiner.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/static_assign_combiner.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/static_assign_combiner.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/static_assign_combiner.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.direct.expect b/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/strongly_connected_component.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/strongly_connected_component.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/strongly_connected_component.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/strongly_connected_component.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/super_index_get.dart.direct.expect b/pkg/front_end/testcases/inference_new/super_index_get.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/super_index_get.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/super_index_get.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/super_index_get.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/super_index_get.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/super_index_get.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/super_index_get.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/super_index_get_substitution.dart.direct.expect b/pkg/front_end/testcases/inference_new/super_index_get_substitution.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/super_index_get_substitution.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/super_index_get_substitution.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/super_index_get_substitution.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/super_index_get_substitution.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/super_index_get_substitution.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/super_index_get_substitution.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/switch.dart.direct.expect b/pkg/front_end/testcases/inference_new/switch.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/switch.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/switch.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/switch.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/switch.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/switch.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/switch.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/top_level_field_depends_on_multiple_inheritance.dart.direct.expect b/pkg/front_end/testcases/inference_new/top_level_field_depends_on_multiple_inheritance.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/top_level_field_depends_on_multiple_inheritance.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/top_level_field_depends_on_multiple_inheritance.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/top_level_field_depends_on_multiple_inheritance.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/top_level_field_depends_on_multiple_inheritance.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/top_level_field_depends_on_multiple_inheritance.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/top_level_field_depends_on_multiple_inheritance.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.direct.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.direct.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.direct.expect
deleted file mode 100644
index 9c67644..0000000
--- a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.direct.expect
+++ /dev/null
@@ -1,12 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-static field dynamic v = self::f.call(() → dynamic {
-  return 1;
-});
-static method f<T extends core::Object = dynamic>(() → self::f::T g) → core::List<self::f::T>
-  return <self::f::T>[g.call()];
-static method main() → dynamic {
-  self::v;
-}
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.direct.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.legacy.expect
similarity index 100%
copy from pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.direct.expect
copy to pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.direct.expect b/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/inference_new/while_loop.dart.direct.expect b/pkg/front_end/testcases/inference_new/while_loop.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/while_loop.dart.direct.expect
rename to pkg/front_end/testcases/inference_new/while_loop.dart.legacy.expect
diff --git a/pkg/front_end/testcases/inference_new/while_loop.dart.direct.transformed.expect b/pkg/front_end/testcases/inference_new/while_loop.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/inference_new/while_loop.dart.direct.transformed.expect
rename to pkg/front_end/testcases/inference_new/while_loop.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/all_steps.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/all_steps.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/all_steps.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/all_steps.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/all_steps.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/all_steps.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/all_steps.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/all_steps.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_generic_classes_from_dill.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/body_generic_classes_from_dill.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_generic_classes_from_dill.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_generic_classes_from_dill.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_generic_classes_from_dill.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_generic_classes_from_dill.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_generic_classes_from_dill.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_generic_classes_from_dill.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_literal_list.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/body_literal_list.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_literal_list.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_literal_list.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_literal_list.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_literal_list.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_literal_list.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_literal_list.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_literal_list_with_generic_argument.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/body_literal_list_with_generic_argument.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_literal_list_with_generic_argument.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_literal_list_with_generic_argument.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_literal_list_with_generic_argument.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_literal_list_with_generic_argument.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_literal_list_with_generic_argument.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_literal_list_with_generic_argument.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_literal_map.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/body_literal_map.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_literal_map.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_literal_map.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_literal_map.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_literal_map.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_literal_map.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_literal_map.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_omitted_bound.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/body_omitted_bound.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_omitted_bound.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_omitted_bound.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_omitted_bound.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_omitted_bound.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_omitted_bound.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_omitted_bound.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_super_bounded_type.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/body_super_bounded_type.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_super_bounded_type.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_super_bounded_type.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_super_bounded_type.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_super_bounded_type.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_super_bounded_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_super_bounded_type.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_map.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/body_typedef_omitted_bound.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.strong.expect
new file mode 100644
index 0000000..1f8d821
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.strong.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef A<T extends core::Object = dynamic> = (T) → dynamic;
+typedef B<U extends (U) → dynamic = (dynamic) → dynamic> = (U) → dynamic;
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {
+    ((dynamic) → dynamic) → dynamic b;
+  }
+}
+static method main() → dynamic {
+  ((dynamic) → dynamic) → dynamic b;
+}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.strong.transformed.expect
new file mode 100644
index 0000000..1f8d821
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_super_bounded_type.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef A<T extends core::Object = dynamic> = (T) → dynamic;
+typedef B<U extends (U) → dynamic = (dynamic) → dynamic> = (U) → dynamic;
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {
+    ((dynamic) → dynamic) → dynamic b;
+  }
+}
+static method main() → dynamic {
+  ((dynamic) → dynamic) → dynamic b;
+}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence_in_literals.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence_in_literals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence_in_literals.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence_in_literals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence_in_literals.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence_in_literals.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence_in_literals.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence_in_literals.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence_in_literals.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence_in_literals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence_in_literals.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence_in_literals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence_in_literals.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence_in_literals.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence_in_literals.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence_in_literals.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/covariant_dependence.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/covariant_dependence.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/covariant_dependence.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/covariant_dependence.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/covariant_dependence.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/covariant_dependence.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/covariant_dependence.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/covariant_dependence.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/covariant_dependence_in_literals.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/covariant_dependence_in_literals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/covariant_dependence_in_literals.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/covariant_dependence_in_literals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/covariant_dependence_in_literals.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/covariant_dependence_in_literals.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/covariant_dependence_in_literals.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/covariant_dependence_in_literals.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence_in_literals.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence_in_literals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence_in_literals.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence_in_literals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence_in_literals.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence_in_literals.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence_in_literals.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence_in_literals.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/dependence.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/dependence.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/dependence.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/dependence.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/dependence.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/dependence.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/dependence.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/dependence.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/dependence_in_literals.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/dependence_in_literals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/dependence_in_literals.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/dependence_in_literals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/dependence_in_literals.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/dependence_in_literals.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/dependence_in_literals.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/dependence_in_literals.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/generic_classes_from_dill.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/generic_classes_from_dill.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/generic_classes_from_dill.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/generic_classes_from_dill.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/generic_classes_from_dill.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/generic_classes_from_dill.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/generic_classes_from_dill.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/generic_classes_from_dill.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/inference_constrained_by_bound.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/inference_constrained_by_bound.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/inference_constrained_by_bound.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/inference_constrained_by_bound.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/inference_constrained_by_bound.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/inference_constrained_by_bound.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/inference_constrained_by_bound.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/inference_constrained_by_bound.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/inference_defaults_to_bound.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/inference_defaults_to_bound.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/inference_defaults_to_bound.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/inference_defaults_to_bound.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/inference_defaults_to_bound.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/inference_defaults_to_bound.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/inference_defaults_to_bound.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/inference_defaults_to_bound.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/inference_gives_input.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/inference_gives_input.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/inference_gives_input.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/inference_gives_input.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/inference_gives_input.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/inference_gives_input.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/inference_gives_input.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/inference_gives_input.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/inference_super_bounded_rejected.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/inference_super_bounded_rejected.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/inference_super_bounded_rejected.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/inference_super_bounded_rejected.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/inference_super_bounded_rejected.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/inference_super_bounded_rejected.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/inference_super_bounded_rejected.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/inference_super_bounded_rejected.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/instantiated_in_outline.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/instantiated_in_outline.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/instantiated_in_outline.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/instantiated_in_outline.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/instantiated_in_outline.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/instantiated_in_outline.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/instantiated_in_outline.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/instantiated_in_outline.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/literal_list.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/literal_list.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/literal_list.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/literal_list.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/literal_list.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/literal_list.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/literal_list.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/literal_list.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/literal_list_with_generic_argument.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/literal_list_with_generic_argument.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/literal_list_with_generic_argument.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/literal_list_with_generic_argument.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/literal_list_with_generic_argument.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/literal_list_with_generic_argument.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/literal_list_with_generic_argument.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/literal_list_with_generic_argument.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/literal_map.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/literal_map.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/literal_map.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/literal_map.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/literal_map.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/literal_map.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/literal_map.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/literal_map.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/multiple_strongly_connected.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/multiple_strongly_connected.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/multiple_strongly_connected.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/multiple_strongly_connected.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/multiple_strongly_connected.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/multiple_strongly_connected.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/multiple_strongly_connected.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/multiple_strongly_connected.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/mutual_dependence.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/mutual_dependence.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/mutual_dependence.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/mutual_dependence.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/mutual_dependence.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/mutual_dependence.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/mutual_dependence.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/mutual_dependence.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/mutual_dependence_in_literals.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/mutual_dependence_in_literals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/mutual_dependence_in_literals.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/mutual_dependence_in_literals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/mutual_dependence_in_literals.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/mutual_dependence_in_literals.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/mutual_dependence_in_literals.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/mutual_dependence_in_literals.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_non_simple.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_non_simple.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_non_simple.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_non_simple.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_non_simple.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_non_simple.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_non_simple.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_non_simple.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_variables.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_variables.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_variables.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_variables.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_variables.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_variables.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_variables.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_variables.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_parametrized_typedef_cycle.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_parametrized_typedef_cycle.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_class_parametrized_typedef_cycle.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_class_parametrized_typedef_cycle.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_parametrized_typedef_cycle.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_parametrized_typedef_cycle.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_class_parametrized_typedef_cycle.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_class_parametrized_typedef_cycle.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_for_each.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_for_each.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_for_each.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_for_each.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_for_each.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_for_each.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_for_each.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_for_each.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_no_dup.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_no_dup.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_no_dup.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_no_dup.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_no_dup.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_no_dup.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_no_dup.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_no_dup.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_folded_regress.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_folded_regress.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_folded_regress.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_folded_regress.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_folded_regress.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_folded_regress.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_folded_regress.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_folded_regress.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_for_each.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_for_each.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_for_each.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_for_each.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_for_each.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_for_each.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_for_each.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_for_each.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_generic_function_in_bound_regress.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_generic_function_in_bound_regress.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_generic_function_in_bound_regress.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_generic_function_in_bound_regress.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_generic_function_in_bound_regress.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_generic_function_in_bound_regress.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_generic_function_in_bound_regress.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_generic_function_in_bound_regress.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_many.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_many.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_many.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_many.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_many.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_many.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_many.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_many.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_many_libs_same_name_cycle.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_many_libs_same_name_cycle.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_many_libs_same_name_cycle.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_many_libs_same_name_cycle.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_many_libs_same_name_cycle.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_many_libs_same_name_cycle.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_many_libs_same_name_cycle.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_many_libs_same_name_cycle.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_no_dup.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_no_dup.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_no_dup.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_no_dup.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_no_dup.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_no_dup.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_no_dup.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_no_dup.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_suppress_consequence.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_suppress_consequence.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_suppress_consequence.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_suppress_consequence.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_suppress_consequence.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_suppress_consequence.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_suppress_consequence.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_suppress_consequence.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_variables_from_same.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_variables_from_same.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_variables_from_same.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_variables_from_same.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_variables_from_same.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_variables_from_same.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/non_simple_variables_from_same.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/non_simple_variables_from_same.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/omitted_bound.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/omitted_bound.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/omitted_bound.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/omitted_bound.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/omitted_bound.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/omitted_bound.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/omitted_bound.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/omitted_bound.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/raw_in_bound.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/raw_in_bound.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/raw_in_bound.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/raw_in_bound.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/raw_in_bound.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/raw_in_bound.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/raw_in_bound.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/raw_in_bound.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_type.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_type.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/super_bounded_type.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/super_bounded_type.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_type.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_type.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/super_bounded_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/super_bounded_type.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/supertypes.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/supertypes.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/supertypes.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/supertypes.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/supertypes.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/supertypes.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/supertypes.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/supertypes.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/typedef_instantiated_in_outline.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/typedef_literal_map.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/typedef_omitted_bound.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.direct.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.direct.expect
rename to pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.legacy.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.direct.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.direct.transformed.expect
rename to pkg/front_end/testcases/instantiate_to_bound/typedef_raw_in_bound.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.strong.expect
new file mode 100644
index 0000000..cead8f1
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.strong.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef A<T extends core::Object = dynamic> = (T) → dynamic;
+typedef B<S extends (S) → dynamic = (dynamic) → dynamic> = (S) → dynamic;
+static field ((dynamic) → dynamic) → dynamic b;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.strong.transformed.expect
new file mode 100644
index 0000000..cead8f1
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_super_bounded_type.dart.strong.transformed.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef A<T extends core::Object = dynamic> = (T) → dynamic;
+typedef B<S extends (S) → dynamic = (dynamic) → dynamic> = (S) → dynamic;
+static field ((dynamic) → dynamic) → dynamic b;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/invalid_assignment.dart.direct.expect b/pkg/front_end/testcases/invalid_assignment.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/invalid_assignment.dart.direct.expect
rename to pkg/front_end/testcases/invalid_assignment.dart.legacy.expect
diff --git a/pkg/front_end/testcases/invalid_assignment.dart.direct.transformed.expect b/pkg/front_end/testcases/invalid_assignment.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/invalid_assignment.dart.direct.transformed.expect
rename to pkg/front_end/testcases/invalid_assignment.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/invalid_assignment.dart.type_promotion.expect b/pkg/front_end/testcases/invalid_assignment.dart.type_promotion.expect
new file mode 100644
index 0000000..abff5c0e
--- /dev/null
+++ b/pkg/front_end/testcases/invalid_assignment.dart.type_promotion.expect
@@ -0,0 +1,18 @@
+pkg/front_end/testcases/invalid_assignment.dart:12:5: Context: Write to i@300
+  i = 1;
+    ^
+pkg/front_end/testcases/invalid_assignment.dart:13:5: Context: Write to i@300
+  i = /*@error=InvalidAssignment*/ s;
+    ^
+pkg/front_end/testcases/invalid_assignment.dart:14:5: Context: Write to i@300
+  i ??= 1;
+    ^^^
+pkg/front_end/testcases/invalid_assignment.dart:15:5: Context: Write to i@300
+  i ??= /*@error=InvalidAssignment*/ s;
+    ^^^
+pkg/front_end/testcases/invalid_assignment.dart:16:5: Context: Write to a@315
+  a = new A();
+    ^
+pkg/front_end/testcases/invalid_assignment.dart:17:34: Context: Write to a@315
+  a /*@error=InvalidAssignment*/ += 1;
+                                 ^^
diff --git a/pkg/front_end/testcases/invalid_cast.dart.direct.expect b/pkg/front_end/testcases/invalid_cast.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/invalid_cast.dart.direct.expect
rename to pkg/front_end/testcases/invalid_cast.dart.legacy.expect
diff --git a/pkg/front_end/testcases/invalid_cast.dart.direct.transformed.expect b/pkg/front_end/testcases/invalid_cast.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/invalid_cast.dart.direct.transformed.expect
rename to pkg/front_end/testcases/invalid_cast.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/invalid_type.dart.direct.expect b/pkg/front_end/testcases/invalid_type.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/invalid_type.dart.direct.expect
rename to pkg/front_end/testcases/invalid_type.dart.legacy.expect
diff --git a/pkg/front_end/testcases/invalid_type.dart.direct.transformed.expect b/pkg/front_end/testcases/invalid_type.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/invalid_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/invalid_type.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/invocations.dart.direct.expect b/pkg/front_end/testcases/invocations.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/invocations.dart.direct.expect
rename to pkg/front_end/testcases/invocations.dart.legacy.expect
diff --git a/pkg/front_end/testcases/invocations.dart.strong.expect b/pkg/front_end/testcases/invocations.dart.strong.expect
new file mode 100644
index 0000000..9bfb838
--- /dev/null
+++ b/pkg/front_end/testcases/invocations.dart.strong.expect
@@ -0,0 +1,68 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/invocations.dart:7:3: Error: Method not found: 'z'.
+//   z("Hello, World!");
+//   ^
+//
+// pkg/front_end/testcases/invocations.dart:8:3: Error: Getter not found: 'z'.
+//   z.print("Hello, World!");
+//   ^
+//
+// pkg/front_end/testcases/invocations.dart:9:3: Error: Getter not found: 'y'.
+//   y.z.print("Hello, World!");
+//   ^
+//
+// pkg/front_end/testcases/invocations.dart:10:3: Error: Getter not found: 'x'.
+//   x.y.z.print("Hello, World!");
+//   ^
+//
+// pkg/front_end/testcases/invocations.dart:14:7: Error: Method not found: 'z'.
+//       z("Hello, World!") +
+//       ^
+//
+// pkg/front_end/testcases/invocations.dart:15:7: Error: Getter not found: 'z'.
+//       z.print("Hello, World!") +
+//       ^
+//
+// pkg/front_end/testcases/invocations.dart:16:7: Error: Getter not found: 'y'.
+//       y.z.print("Hello, World!") +
+//       ^
+//
+// pkg/front_end/testcases/invocations.dart:17:7: Error: Getter not found: 'x'.
+//       x.y.z.print("Hello, World!");
+//       ^
+//
+// pkg/front_end/testcases/invocations.dart:13:7: Error: This expression has type 'void' and can't be used.
+//       print("Hello, World!") +
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print("Hello, World!");
+  invalid-expression "pkg/front_end/testcases/invocations.dart:7:3: Error: Method not found: 'z'.
+  z(\"Hello, World!\");
+  ^";
+  invalid-expression "pkg/front_end/testcases/invocations.dart:8:3: Error: Getter not found: 'z'.
+  z.print(\"Hello, World!\");
+  ^".print("Hello, World!");
+  invalid-expression "pkg/front_end/testcases/invocations.dart:9:3: Error: Getter not found: 'y'.
+  y.z.print(\"Hello, World!\");
+  ^".z.print("Hello, World!");
+  invalid-expression "pkg/front_end/testcases/invocations.dart:10:3: Error: Getter not found: 'x'.
+  x.y.z.print(\"Hello, World!\");
+  ^".y.z.print("Hello, World!");
+  1.{core::num::+}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/invocations.dart:13:7: Error: This expression has type 'void' and can't be used.
+      print(\"Hello, World!\") +
+      ^" in core::print("Hello, World!")).{core::num::+}(invalid-expression "pkg/front_end/testcases/invocations.dart:14:7: Error: Method not found: 'z'.
+      z(\"Hello, World!\") +
+      ^" as{TypeError} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/invocations.dart:15:7: Error: Getter not found: 'z'.
+      z.print(\"Hello, World!\") +
+      ^".print("Hello, World!") as{TypeError} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/invocations.dart:16:7: Error: Getter not found: 'y'.
+      y.z.print(\"Hello, World!\") +
+      ^".z.print("Hello, World!") as{TypeError} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/invocations.dart:17:7: Error: Getter not found: 'x'.
+      x.y.z.print(\"Hello, World!\");
+      ^".y.z.print("Hello, World!") as{TypeError} core::num);
+}
diff --git a/pkg/front_end/testcases/invocations.dart.strong.transformed.expect b/pkg/front_end/testcases/invocations.dart.strong.transformed.expect
new file mode 100644
index 0000000..773afe1
--- /dev/null
+++ b/pkg/front_end/testcases/invocations.dart.strong.transformed.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print("Hello, World!");
+  invalid-expression "pkg/front_end/testcases/invocations.dart:7:3: Error: Method not found: 'z'.
+  z(\"Hello, World!\");
+  ^";
+  invalid-expression "pkg/front_end/testcases/invocations.dart:8:3: Error: Getter not found: 'z'.
+  z.print(\"Hello, World!\");
+  ^".print("Hello, World!");
+  invalid-expression "pkg/front_end/testcases/invocations.dart:9:3: Error: Getter not found: 'y'.
+  y.z.print(\"Hello, World!\");
+  ^".z.print("Hello, World!");
+  invalid-expression "pkg/front_end/testcases/invocations.dart:10:3: Error: Getter not found: 'x'.
+  x.y.z.print(\"Hello, World!\");
+  ^".y.z.print("Hello, World!");
+  1.{core::num::+}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/invocations.dart:13:7: Error: This expression has type 'void' and can't be used.
+      print(\"Hello, World!\") +
+      ^" in core::print("Hello, World!")).{core::num::+}(invalid-expression "pkg/front_end/testcases/invocations.dart:14:7: Error: Method not found: 'z'.
+      z(\"Hello, World!\") +
+      ^" as{TypeError} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/invocations.dart:15:7: Error: Getter not found: 'z'.
+      z.print(\"Hello, World!\") +
+      ^".print("Hello, World!") as{TypeError} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/invocations.dart:16:7: Error: Getter not found: 'y'.
+      y.z.print(\"Hello, World!\") +
+      ^".z.print("Hello, World!") as{TypeError} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/invocations.dart:17:7: Error: Getter not found: 'x'.
+      x.y.z.print(\"Hello, World!\");
+      ^".y.z.print("Hello, World!") as{TypeError} core::num);
+}
diff --git a/pkg/front_end/testcases/issue34899.dart.direct.expect b/pkg/front_end/testcases/issue34899.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/issue34899.dart.direct.expect
rename to pkg/front_end/testcases/issue34899.dart.legacy.expect
diff --git a/pkg/front_end/testcases/issue34899.dart.direct.transformed.expect b/pkg/front_end/testcases/issue34899.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/issue34899.dart.direct.transformed.expect
rename to pkg/front_end/testcases/issue34899.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/compile.status b/pkg/front_end/testcases/legacy.status
similarity index 95%
rename from pkg/front_end/testcases/compile.status
rename to pkg/front_end/testcases/legacy.status
index 5fef26a..6fec1c8 100644
--- a/pkg/front_end/testcases/compile.status
+++ b/pkg/front_end/testcases/legacy.status
@@ -2,9 +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.md file.
 
-# Status file for the compile_test.dart (notice c, not k) test suite. This is
-# testing generating Kernel ASTs directly, that is, code in
-# pkg/fasta/lib/src/kernel/.
+# Status file for the legacy_test.dart test suite. This is testing generating
+# Kernel ASTs in legacy mode (Dart 1.0).
 
 DeltaBlue: Fail # Fasta and dartk disagree on static initializers
 ambiguous_exports: RuntimeError # Expected, this file exports two main methods.
@@ -12,6 +11,7 @@
 call: Fail # Test can't run.
 constructor_const_inference: RuntimeError # Test exercises strong mode semantics.  See also Issue #33813.
 constructor_initializer_invalid: RuntimeError # Fails execution after recovery
+duplicated_field_initializer: RuntimeError
 external_import: RuntimeError # Expected -- test uses import which doesn't exist.
 fallthrough: Fail # Missing FallThroughError.
 function_type_recovery: Fail
@@ -40,10 +40,10 @@
 rasta/bad_continue: Fail
 rasta/bad_default_constructor: Fail # Compile-time error destroys program.
 rasta/bad_explicit_super_constructor: RuntimeError
-rasta/bad_implicit_super_constructor: Fail
+rasta/bad_implicit_super_constructor: RuntimeError
 rasta/bad_interpolation: Fail
 rasta/bad_redirection: Fail
-rasta/bad_setter_initializer: Fail
+rasta/bad_setter_initializer: RuntimeError
 rasta/bad_unicode: Fail
 rasta/breaking_bad: Fail
 rasta/class_hierarchy: Fail
@@ -106,6 +106,7 @@
 regress/issue_33452: RuntimeError # Test has an intentional error
 regress/issue_34225: RuntimeError
 regress/issue_34563: RuntimeError # Test execution after recovery
+regress/issue_35177: RuntimeError
 runtime_checks/implicit_downcast_constructor_initializer: RuntimeError # Test exercises strong mode semantics
 runtime_checks/implicit_downcast_do: RuntimeError # Test exercises strong mode semantics
 runtime_checks/implicit_downcast_for_condition: RuntimeError # Test exercises strong mode semantics
diff --git a/pkg/front_end/testcases/literals.dart.direct.expect b/pkg/front_end/testcases/literals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/literals.dart.direct.expect
rename to pkg/front_end/testcases/literals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/literals.dart.direct.transformed.expect b/pkg/front_end/testcases/literals.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/literals.dart.direct.transformed.expect
rename to pkg/front_end/testcases/literals.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/literals.dart.strong.expect b/pkg/front_end/testcases/literals.dart.strong.expect
new file mode 100644
index 0000000..8fa18be
--- /dev/null
+++ b/pkg/front_end/testcases/literals.dart.strong.expect
@@ -0,0 +1,43 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method testString() → dynamic {
+  core::print("a");
+}
+static method testInt() → dynamic {
+  core::print(1);
+}
+static method testBool() → dynamic {
+  core::print(true);
+  core::print(false);
+}
+static method testDouble() → dynamic {
+  core::print(1.0);
+}
+static method testNull() → dynamic {
+  core::print(null);
+}
+static method testList() → dynamic {
+  core::print(<dynamic>[]);
+  core::print(<core::String>["a", "b"]);
+}
+static method testMap() → dynamic {
+  core::print(<dynamic, dynamic>{});
+  core::print(<core::String, core::String>{"a": "b"});
+}
+static method testSymbol() → dynamic {
+  core::print(#fisk);
+  core::print(#_fisk);
+  core::print(#fisk.hest.ko);
+}
+static method main() → dynamic {
+  self::testString();
+  self::testInt();
+  self::testBool();
+  self::testDouble();
+  self::testNull();
+  self::testList();
+  self::testMap();
+  self::testSymbol();
+}
diff --git a/pkg/front_end/testcases/literals.dart.strong.transformed.expect b/pkg/front_end/testcases/literals.dart.strong.transformed.expect
new file mode 100644
index 0000000..8fa18be
--- /dev/null
+++ b/pkg/front_end/testcases/literals.dart.strong.transformed.expect
@@ -0,0 +1,43 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method testString() → dynamic {
+  core::print("a");
+}
+static method testInt() → dynamic {
+  core::print(1);
+}
+static method testBool() → dynamic {
+  core::print(true);
+  core::print(false);
+}
+static method testDouble() → dynamic {
+  core::print(1.0);
+}
+static method testNull() → dynamic {
+  core::print(null);
+}
+static method testList() → dynamic {
+  core::print(<dynamic>[]);
+  core::print(<core::String>["a", "b"]);
+}
+static method testMap() → dynamic {
+  core::print(<dynamic, dynamic>{});
+  core::print(<core::String, core::String>{"a": "b"});
+}
+static method testSymbol() → dynamic {
+  core::print(#fisk);
+  core::print(#_fisk);
+  core::print(#fisk.hest.ko);
+}
+static method main() → dynamic {
+  self::testString();
+  self::testInt();
+  self::testBool();
+  self::testDouble();
+  self::testNull();
+  self::testList();
+  self::testMap();
+  self::testSymbol();
+}
diff --git a/pkg/front_end/testcases/local_generic_function.dart.direct.expect b/pkg/front_end/testcases/local_generic_function.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/local_generic_function.dart.direct.expect
rename to pkg/front_end/testcases/local_generic_function.dart.legacy.expect
diff --git a/pkg/front_end/testcases/local_generic_function.dart.direct.transformed.expect b/pkg/front_end/testcases/local_generic_function.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/local_generic_function.dart.direct.transformed.expect
rename to pkg/front_end/testcases/local_generic_function.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/magic_const.dart.direct.expect b/pkg/front_end/testcases/magic_const.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/magic_const.dart.direct.expect
rename to pkg/front_end/testcases/magic_const.dart.legacy.expect
diff --git a/pkg/front_end/testcases/magic_const.dart.direct.transformed.expect b/pkg/front_end/testcases/magic_const.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/magic_const.dart.direct.transformed.expect
rename to pkg/front_end/testcases/magic_const.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/map.dart.direct.expect b/pkg/front_end/testcases/map.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/map.dart.direct.expect
rename to pkg/front_end/testcases/map.dart.legacy.expect
diff --git a/pkg/front_end/testcases/map.dart.direct.transformed.expect b/pkg/front_end/testcases/map.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/map.dart.direct.transformed.expect
rename to pkg/front_end/testcases/map.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/map.dart.direct.expect b/pkg/front_end/testcases/map.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/map.dart.direct.expect
copy to pkg/front_end/testcases/map.dart.strong.expect
diff --git a/pkg/front_end/testcases/map.dart.direct.transformed.expect b/pkg/front_end/testcases/map.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/map.dart.direct.transformed.expect
copy to pkg/front_end/testcases/map.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/metadata_enum.dart.direct.expect b/pkg/front_end/testcases/metadata_enum.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/metadata_enum.dart.direct.expect
rename to pkg/front_end/testcases/metadata_enum.dart.legacy.expect
diff --git a/pkg/front_end/testcases/metadata_enum.dart.direct.transformed.expect b/pkg/front_end/testcases/metadata_enum.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/metadata_enum.dart.direct.transformed.expect
rename to pkg/front_end/testcases/metadata_enum.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/metadata_named_mixin_application.dart.direct.expect b/pkg/front_end/testcases/metadata_named_mixin_application.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/metadata_named_mixin_application.dart.direct.expect
rename to pkg/front_end/testcases/metadata_named_mixin_application.dart.legacy.expect
diff --git a/pkg/front_end/testcases/metadata_named_mixin_application.dart.direct.transformed.expect b/pkg/front_end/testcases/metadata_named_mixin_application.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/metadata_named_mixin_application.dart.direct.transformed.expect
rename to pkg/front_end/testcases/metadata_named_mixin_application.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/micro.dart.direct.expect b/pkg/front_end/testcases/micro.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/micro.dart.direct.expect
rename to pkg/front_end/testcases/micro.dart.legacy.expect
diff --git a/pkg/front_end/testcases/micro.dart.strong.expect b/pkg/front_end/testcases/micro.dart.strong.expect
index c7b1e6d..1acd17c 100644
--- a/pkg/front_end/testcases/micro.dart.strong.expect
+++ b/pkg/front_end/testcases/micro.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class Foo extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::Foo
     : super core::Object::•()
     ;
   method instanceMethod() → dynamic {
@@ -11,41 +11,41 @@
   }
 }
 abstract class ExternalValue extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::ExternalValue
     : super core::Object::•()
     ;
 }
 abstract class Bar extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::Bar
     : super core::Object::•()
     ;
   abstract method externalInstanceMethod() → self::ExternalValue;
 }
 class Box extends core::Object {
   field dynamic field = null;
-  synthetic constructor •() → void
+  synthetic constructor •() → self::Box
     : super core::Object::•()
     ;
 }
 class FinalBox extends core::Object {
   final field dynamic finalField;
-  constructor •(dynamic finalField) → void
+  constructor •(dynamic finalField) → self::FinalBox
     : self::FinalBox::finalField = finalField, super core::Object::•()
     ;
 }
 class SubFinalBox extends self::FinalBox {
-  constructor •(dynamic value) → void
+  constructor •(dynamic value) → self::SubFinalBox
     : super self::FinalBox::•(value)
     ;
 }
 class DynamicReceiver1 extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::DynamicReceiver1
     : super core::Object::•()
     ;
   method dynamicallyCalled(dynamic x) → dynamic {}
 }
 class DynamicReceiver2 extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::DynamicReceiver2
     : super core::Object::•()
     ;
   method dynamicallyCalled(dynamic x) → dynamic {}
diff --git a/pkg/front_end/testcases/micro.dart.strong.transformed.expect b/pkg/front_end/testcases/micro.dart.strong.transformed.expect
new file mode 100644
index 0000000..1acd17c
--- /dev/null
+++ b/pkg/front_end/testcases/micro.dart.strong.transformed.expect
@@ -0,0 +1,81 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  synthetic constructor •() → self::Foo
+    : super core::Object::•()
+    ;
+  method instanceMethod() → dynamic {
+    return 123;
+  }
+}
+abstract class ExternalValue extends core::Object {
+  synthetic constructor •() → self::ExternalValue
+    : super core::Object::•()
+    ;
+}
+abstract class Bar extends core::Object {
+  synthetic constructor •() → self::Bar
+    : super core::Object::•()
+    ;
+  abstract method externalInstanceMethod() → self::ExternalValue;
+}
+class Box extends core::Object {
+  field dynamic field = null;
+  synthetic constructor •() → self::Box
+    : super core::Object::•()
+    ;
+}
+class FinalBox extends core::Object {
+  final field dynamic finalField;
+  constructor •(dynamic finalField) → self::FinalBox
+    : self::FinalBox::finalField = finalField, super core::Object::•()
+    ;
+}
+class SubFinalBox extends self::FinalBox {
+  constructor •(dynamic value) → self::SubFinalBox
+    : super self::FinalBox::•(value)
+    ;
+}
+class DynamicReceiver1 extends core::Object {
+  synthetic constructor •() → self::DynamicReceiver1
+    : super core::Object::•()
+    ;
+  method dynamicallyCalled(dynamic x) → dynamic {}
+}
+class DynamicReceiver2 extends core::Object {
+  synthetic constructor •() → self::DynamicReceiver2
+    : super core::Object::•()
+    ;
+  method dynamicallyCalled(dynamic x) → dynamic {}
+}
+static method staticMethod() → dynamic {
+  return "sdfg";
+}
+external static abstract method externalStatic() → core::bool;
+external static abstract method createBar() → self::Bar;
+static method stringArgument(dynamic x) → dynamic {}
+static method intArgument(dynamic x) → dynamic {}
+static method makeDynamicCall(dynamic receiver) → void {
+  receiver.dynamicallyCalled("sdfg");
+}
+static method main() → dynamic {
+  dynamic x = self::staticMethod();
+  dynamic y = new self::Foo::•().{self::Foo::instanceMethod}();
+  core::bool z = self::externalStatic();
+  self::ExternalValue w = self::createBar().{self::Bar::externalInstanceMethod}();
+  self::stringArgument("sdfg");
+  self::intArgument(42);
+  self::Box box = new self::Box::•();
+  box.{self::Box::field} = "sdfg";
+  dynamic a = box.{self::Box::field};
+  self::FinalBox finalBox = new self::FinalBox::•("dfg");
+  dynamic b = finalBox.{self::FinalBox::finalField};
+  self::SubFinalBox subBox = new self::SubFinalBox::•("dfg");
+  dynamic c = subBox.{self::FinalBox::finalField};
+  self::makeDynamicCall(new self::DynamicReceiver1::•());
+  self::makeDynamicCall(new self::DynamicReceiver2::•());
+  core::List<core::String> list = <core::String>["string"];
+  core::String d = list.{core::List::[]}(0);
+}
diff --git a/pkg/front_end/testcases/minimum_int.dart.direct.expect b/pkg/front_end/testcases/minimum_int.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/minimum_int.dart.direct.expect
rename to pkg/front_end/testcases/minimum_int.dart.legacy.expect
diff --git a/pkg/front_end/testcases/minimum_int.dart.direct.transformed.expect b/pkg/front_end/testcases/minimum_int.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/minimum_int.dart.direct.transformed.expect
rename to pkg/front_end/testcases/minimum_int.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/missing_constructor.dart.direct.expect b/pkg/front_end/testcases/missing_constructor.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/missing_constructor.dart.direct.expect
rename to pkg/front_end/testcases/missing_constructor.dart.legacy.expect
diff --git a/pkg/front_end/testcases/missing_constructor.dart.direct.transformed.expect b/pkg/front_end/testcases/missing_constructor.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/missing_constructor.dart.direct.transformed.expect
rename to pkg/front_end/testcases/missing_constructor.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/mixin.dart.direct.expect b/pkg/front_end/testcases/mixin.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/mixin.dart.direct.expect
rename to pkg/front_end/testcases/mixin.dart.legacy.expect
diff --git a/pkg/front_end/testcases/mixin.dart.direct.transformed.expect b/pkg/front_end/testcases/mixin.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/mixin.dart.direct.transformed.expect
rename to pkg/front_end/testcases/mixin.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/mixin_application_override.dart.direct.expect b/pkg/front_end/testcases/mixin_application_override.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/mixin_application_override.dart.direct.expect
rename to pkg/front_end/testcases/mixin_application_override.dart.legacy.expect
diff --git a/pkg/front_end/testcases/mixin_application_override.dart.direct.transformed.expect b/pkg/front_end/testcases/mixin_application_override.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/mixin_application_override.dart.direct.transformed.expect
rename to pkg/front_end/testcases/mixin_application_override.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/mixin_constructors_with_default_values.dart.direct.expect b/pkg/front_end/testcases/mixin_constructors_with_default_values.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/mixin_constructors_with_default_values.dart.direct.expect
rename to pkg/front_end/testcases/mixin_constructors_with_default_values.dart.legacy.expect
diff --git a/pkg/front_end/testcases/mixin_constructors_with_default_values.dart.direct.transformed.expect b/pkg/front_end/testcases/mixin_constructors_with_default_values.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/mixin_constructors_with_default_values.dart.direct.transformed.expect
rename to pkg/front_end/testcases/mixin_constructors_with_default_values.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.direct.expect b/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.direct.expect
rename to pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.direct.transformed.expect b/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/mixin_super_repeated.dart.direct.expect b/pkg/front_end/testcases/mixin_super_repeated.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/mixin_super_repeated.dart.direct.expect
rename to pkg/front_end/testcases/mixin_super_repeated.dart.legacy.expect
diff --git a/pkg/front_end/testcases/mixin_super_repeated.dart.direct.transformed.expect b/pkg/front_end/testcases/mixin_super_repeated.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/mixin_super_repeated.dart.direct.transformed.expect
rename to pkg/front_end/testcases/mixin_super_repeated.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/named_function_scope.dart.direct.expect b/pkg/front_end/testcases/named_function_scope.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/named_function_scope.dart.direct.expect
rename to pkg/front_end/testcases/named_function_scope.dart.legacy.expect
diff --git a/pkg/front_end/testcases/named_function_scope.dart.direct.transformed.expect b/pkg/front_end/testcases/named_function_scope.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/named_function_scope.dart.direct.transformed.expect
rename to pkg/front_end/testcases/named_function_scope.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/named_parameters.dart.direct.expect b/pkg/front_end/testcases/named_parameters.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/named_parameters.dart.direct.expect
rename to pkg/front_end/testcases/named_parameters.dart.legacy.expect
diff --git a/pkg/front_end/testcases/named_parameters.dart.strong.expect b/pkg/front_end/testcases/named_parameters.dart.strong.expect
index ad415f8..2a59b49 100644
--- a/pkg/front_end/testcases/named_parameters.dart.strong.expect
+++ b/pkg/front_end/testcases/named_parameters.dart.strong.expect
@@ -2,19 +2,27 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class Superclass extends core::Object {
-  constructor •() → void
+class Superclass extends core::Object {
+  synthetic constructor •() → self::Superclass
     : super core::Object::•()
     ;
-  abstract method foo({dynamic alpha, dynamic beta}) → dynamic;
+  method foo({dynamic alpha = null, dynamic beta = null}) → dynamic {}
+  method bar({dynamic beta = null, dynamic alpha = null}) → dynamic {}
+  method namedCallback(({alpha: core::String, beta: core::int}) → dynamic callback) → dynamic {
+    callback.call(alpha: "one", beta: 2);
+    callback.call(beta: 1, alpha: "two");
+  }
 }
 class Subclass extends self::Superclass {
-  constructor •() → void
+  synthetic constructor •() → self::Subclass
     : super self::Superclass::•()
     ;
-  method foo({dynamic beta, dynamic alpha}) → dynamic {}
+  method foo({dynamic beta = null, dynamic alpha = null}) → dynamic {}
+  method bar({dynamic alpha = null, dynamic beta = null}) → dynamic {}
+  method namedCallback(({alpha: core::String, beta: core::int}) → dynamic callback) → dynamic {}
 }
-static method topLevelNamed(dynamic beta, dynamic alpha, {dynamic gamma, dynamic delta}) → dynamic {}
+static method topLevelNamed(dynamic beta, dynamic alpha, {dynamic gamma = null, dynamic delta = null}) → dynamic {}
+static method topLevelOptional(dynamic beta, dynamic alpha, [dynamic gamma = null, dynamic delta = null]) → dynamic {}
 static method main() → dynamic {
   new self::Subclass::•().{self::Subclass::foo}(beta: 1, alpha: 2);
   new self::Subclass::•().{self::Subclass::foo}(alpha: 1, beta: 2);
diff --git a/pkg/front_end/testcases/named_parameters.dart.strong.transformed.expect b/pkg/front_end/testcases/named_parameters.dart.strong.transformed.expect
new file mode 100644
index 0000000..2a59b49
--- /dev/null
+++ b/pkg/front_end/testcases/named_parameters.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Superclass extends core::Object {
+  synthetic constructor •() → self::Superclass
+    : super core::Object::•()
+    ;
+  method foo({dynamic alpha = null, dynamic beta = null}) → dynamic {}
+  method bar({dynamic beta = null, dynamic alpha = null}) → dynamic {}
+  method namedCallback(({alpha: core::String, beta: core::int}) → dynamic callback) → dynamic {
+    callback.call(alpha: "one", beta: 2);
+    callback.call(beta: 1, alpha: "two");
+  }
+}
+class Subclass extends self::Superclass {
+  synthetic constructor •() → self::Subclass
+    : super self::Superclass::•()
+    ;
+  method foo({dynamic beta = null, dynamic alpha = null}) → dynamic {}
+  method bar({dynamic alpha = null, dynamic beta = null}) → dynamic {}
+  method namedCallback(({alpha: core::String, beta: core::int}) → dynamic callback) → dynamic {}
+}
+static method topLevelNamed(dynamic beta, dynamic alpha, {dynamic gamma = null, dynamic delta = null}) → dynamic {}
+static method topLevelOptional(dynamic beta, dynamic alpha, [dynamic gamma = null, dynamic delta = null]) → dynamic {}
+static method main() → dynamic {
+  new self::Subclass::•().{self::Subclass::foo}(beta: 1, alpha: 2);
+  new self::Subclass::•().{self::Subclass::foo}(alpha: 1, beta: 2);
+  self::topLevelNamed(1, 2, gamma: 3, delta: 4);
+  self::topLevelNamed(1, 2, delta: 3, gamma: 4);
+}
diff --git a/pkg/front_end/testcases/native_as_name.dart.direct.expect b/pkg/front_end/testcases/native_as_name.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/native_as_name.dart.direct.expect
rename to pkg/front_end/testcases/native_as_name.dart.legacy.expect
diff --git a/pkg/front_end/testcases/native_as_name.dart.direct.transformed.expect b/pkg/front_end/testcases/native_as_name.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/native_as_name.dart.direct.transformed.expect
rename to pkg/front_end/testcases/native_as_name.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.direct.expect b/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.direct.expect
rename to pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.legacy.expect
diff --git a/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.direct.transformed.expect b/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.direct.transformed.expect
rename to pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/new_const_insertion/simple.dart.direct.expect b/pkg/front_end/testcases/new_const_insertion/simple.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/new_const_insertion/simple.dart.direct.expect
rename to pkg/front_end/testcases/new_const_insertion/simple.dart.legacy.expect
diff --git a/pkg/front_end/testcases/new_const_insertion/simple.dart.direct.transformed.expect b/pkg/front_end/testcases/new_const_insertion/simple.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/new_const_insertion/simple.dart.direct.transformed.expect
rename to pkg/front_end/testcases/new_const_insertion/simple.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.type_promotion.expect b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.type_promotion.expect
new file mode 100644
index 0000000..8dc5a4c
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart:34:14: Context: Write to value@1053
+  if ((value = b.foo()) != "baz") {
+             ^
+pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart:37:14: Context: Write to value@1053
+  if ((value = b.hest()) != 42) {
+             ^
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/duplicated_abstract_method.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/duplicated_abstract_method.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/duplicated_abstract_method.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/duplicated_abstract_method.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/duplicated_abstract_method.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/duplicated_abstract_method.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/duplicated_abstract_method.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/duplicated_abstract_method.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes_chain.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes_chain.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes_chain.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes_chain.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes_chain.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes_chain.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes_chain.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes_chain.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/private.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/private.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/private.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/private.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/private.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/private.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/private.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/private.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/private_module.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/private_module.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/private_module.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/private_module.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/private_module.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/private_module.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/private_module.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/private_module.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/private_same.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/private_same.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/private_same.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/private_same.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/private_same.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/private_same.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/private_same.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/private_same.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/same.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/same.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/no_such_method_private_setter.dart.direct.expect b/pkg/front_end/testcases/no_such_method_private_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_private_setter.dart.direct.expect
rename to pkg/front_end/testcases/no_such_method_private_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/no_such_method_private_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_private_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/no_such_method_private_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/no_such_method_private_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/null_aware.dart.direct.expect b/pkg/front_end/testcases/null_aware.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/null_aware.dart.direct.expect
rename to pkg/front_end/testcases/null_aware.dart.legacy.expect
diff --git a/pkg/front_end/testcases/null_aware.dart.direct.transformed.expect b/pkg/front_end/testcases/null_aware.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/null_aware.dart.direct.transformed.expect
rename to pkg/front_end/testcases/null_aware.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/null_aware.dart.strong.expect b/pkg/front_end/testcases/null_aware.dart.strong.expect
index 0c3d292..3f3d5e0 100644
--- a/pkg/front_end/testcases/null_aware.dart.strong.expect
+++ b/pkg/front_end/testcases/null_aware.dart.strong.expect
@@ -5,18 +5,18 @@
 class Foo extends core::Object {
   field core::int field = null;
   static field core::int staticField = null;
-  synthetic constructor •() → void
+  synthetic constructor •() → self::Foo
     : super core::Object::•()
     ;
 }
 static method main() → dynamic {
   self::Foo foo = new self::Foo::•();
-  let final self::Foo #t1 = foo in #t1.==(null) ? null : #t1.{self::Foo::field} = 5;
+  let final self::Foo #t1 = foo in #t1.==(null) ?{core::int} null : #t1.{self::Foo::field} = 5;
   self::Foo::staticField = 5;
-  let final self::Foo #t2 = foo in #t2.{self::Foo::field}.==(null) ? #t2.{self::Foo::field} = 5 : null;
-  self::Foo::staticField.==(null) ? self::Foo::staticField = 5 : null;
-  let final self::Foo #t3 = foo in #t3.==(null) ? null : #t3.{self::Foo::field}.==(null) ? #t3.{self::Foo::field} = 5 : null;
-  self::Foo::staticField.==(null) ? self::Foo::staticField = 5 : null;
-  core::int intValue = let final core::int #t4 = foo.{self::Foo::field} in #t4.==(null) ? 6 : #t4;
-  core::num numValue = let final core::int #t5 = foo.{self::Foo::field} in #t5.==(null) ? 4.5 : #t5;
+  let final self::Foo #t2 = foo in #t2.{self::Foo::field}.{core::num::==}(null) ?{core::int} #t2.{self::Foo::field} = 5 : null;
+  self::Foo::staticField.{core::num::==}(null) ?{core::int} self::Foo::staticField = 5 : null;
+  let final self::Foo #t3 = foo in #t3.==(null) ?{core::int} null : #t3.{self::Foo::field}.{core::num::==}(null) ?{core::int} #t3.{self::Foo::field} = 5 : null;
+  self::Foo::staticField.{core::num::==}(null) ?{core::int} self::Foo::staticField = 5 : null;
+  core::int intValue = let final core::int #t4 = foo.{self::Foo::field} in #t4.==(null) ?{core::int} 6 : #t4;
+  core::num numValue = let final core::int #t5 = foo.{self::Foo::field} in #t5.==(null) ?{core::num} 4.5 : #t5;
 }
diff --git a/pkg/front_end/testcases/null_aware.dart.strong.transformed.expect b/pkg/front_end/testcases/null_aware.dart.strong.transformed.expect
new file mode 100644
index 0000000..3f3d5e0
--- /dev/null
+++ b/pkg/front_end/testcases/null_aware.dart.strong.transformed.expect
@@ -0,0 +1,22 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  field core::int field = null;
+  static field core::int staticField = null;
+  synthetic constructor •() → self::Foo
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  self::Foo foo = new self::Foo::•();
+  let final self::Foo #t1 = foo in #t1.==(null) ?{core::int} null : #t1.{self::Foo::field} = 5;
+  self::Foo::staticField = 5;
+  let final self::Foo #t2 = foo in #t2.{self::Foo::field}.{core::num::==}(null) ?{core::int} #t2.{self::Foo::field} = 5 : null;
+  self::Foo::staticField.{core::num::==}(null) ?{core::int} self::Foo::staticField = 5 : null;
+  let final self::Foo #t3 = foo in #t3.==(null) ?{core::int} null : #t3.{self::Foo::field}.{core::num::==}(null) ?{core::int} #t3.{self::Foo::field} = 5 : null;
+  self::Foo::staticField.{core::num::==}(null) ?{core::int} self::Foo::staticField = 5 : null;
+  core::int intValue = let final core::int #t4 = foo.{self::Foo::field} in #t4.==(null) ?{core::int} 6 : #t4;
+  core::num numValue = let final core::int #t5 = foo.{self::Foo::field} in #t5.==(null) ?{core::num} 4.5 : #t5;
+}
diff --git a/pkg/front_end/testcases/operators.dart.direct.expect b/pkg/front_end/testcases/operators.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/operators.dart.direct.expect
rename to pkg/front_end/testcases/operators.dart.legacy.expect
diff --git a/pkg/front_end/testcases/operators.dart.direct.transformed.expect b/pkg/front_end/testcases/operators.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/operators.dart.direct.transformed.expect
rename to pkg/front_end/testcases/operators.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/operators.dart.strong.expect b/pkg/front_end/testcases/operators.dart.strong.expect
new file mode 100644
index 0000000..2c8078c
--- /dev/null
+++ b/pkg/front_end/testcases/operators.dart.strong.expect
@@ -0,0 +1,72 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Operators extends core::Object {
+  synthetic constructor •() → self::Operators
+    : super core::Object::•()
+    ;
+  operator +(dynamic other) → dynamic
+    return null;
+  operator &(dynamic other) → dynamic
+    return null;
+  operator ~() → dynamic
+    return null;
+  operator |(dynamic other) → dynamic
+    return null;
+  operator ^(dynamic other) → dynamic
+    return null;
+  operator /(dynamic other) → dynamic
+    return null;
+  operator ==(dynamic other) → core::bool
+    return null;
+  operator >(dynamic other) → dynamic
+    return null;
+  operator >=(dynamic other) → dynamic
+    return null;
+  operator [](dynamic index) → dynamic
+    return null;
+  operator []=(dynamic index, dynamic value) → void {}
+  operator <<(dynamic other) → dynamic
+    return null;
+  operator <(dynamic other) → dynamic
+    return null;
+  operator <=(dynamic other) → dynamic
+    return null;
+  operator *(dynamic other) → dynamic
+    return null;
+  operator %(dynamic other) → dynamic
+    return null;
+  operator >>(dynamic other) → dynamic
+    return null;
+  operator -(dynamic other) → dynamic
+    return null;
+  operator ~/(dynamic other) → dynamic
+    return null;
+  operator unary-() → dynamic
+    return null;
+}
+static method main(dynamic arguments) → dynamic {
+  self::Operators a = new self::Operators::•();
+  self::Operators b = new self::Operators::•();
+  a.{self::Operators::+}(b);
+  a.{self::Operators::&}(b);
+  a.{self::Operators::~}();
+  a.{self::Operators::|}(b);
+  a.{self::Operators::^}(b);
+  a.{self::Operators::/}(b);
+  a.{self::Operators::==}(b);
+  a.{self::Operators::>}(b);
+  a.{self::Operators::>=}(b);
+  a.{self::Operators::[]}(0);
+  a.{self::Operators::[]=}(0, b);
+  a.{self::Operators::<<}(b);
+  a.{self::Operators::<}(b);
+  a.{self::Operators::<=}(b);
+  a.{self::Operators::*}(b);
+  a.{self::Operators::%}(b);
+  a.{self::Operators::>>}(b);
+  a.{self::Operators::-}(b);
+  a.{self::Operators::~/}(b);
+  a.{self::Operators::unary-}();
+}
diff --git a/pkg/front_end/testcases/operators.dart.strong.transformed.expect b/pkg/front_end/testcases/operators.dart.strong.transformed.expect
new file mode 100644
index 0000000..2c8078c
--- /dev/null
+++ b/pkg/front_end/testcases/operators.dart.strong.transformed.expect
@@ -0,0 +1,72 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Operators extends core::Object {
+  synthetic constructor •() → self::Operators
+    : super core::Object::•()
+    ;
+  operator +(dynamic other) → dynamic
+    return null;
+  operator &(dynamic other) → dynamic
+    return null;
+  operator ~() → dynamic
+    return null;
+  operator |(dynamic other) → dynamic
+    return null;
+  operator ^(dynamic other) → dynamic
+    return null;
+  operator /(dynamic other) → dynamic
+    return null;
+  operator ==(dynamic other) → core::bool
+    return null;
+  operator >(dynamic other) → dynamic
+    return null;
+  operator >=(dynamic other) → dynamic
+    return null;
+  operator [](dynamic index) → dynamic
+    return null;
+  operator []=(dynamic index, dynamic value) → void {}
+  operator <<(dynamic other) → dynamic
+    return null;
+  operator <(dynamic other) → dynamic
+    return null;
+  operator <=(dynamic other) → dynamic
+    return null;
+  operator *(dynamic other) → dynamic
+    return null;
+  operator %(dynamic other) → dynamic
+    return null;
+  operator >>(dynamic other) → dynamic
+    return null;
+  operator -(dynamic other) → dynamic
+    return null;
+  operator ~/(dynamic other) → dynamic
+    return null;
+  operator unary-() → dynamic
+    return null;
+}
+static method main(dynamic arguments) → dynamic {
+  self::Operators a = new self::Operators::•();
+  self::Operators b = new self::Operators::•();
+  a.{self::Operators::+}(b);
+  a.{self::Operators::&}(b);
+  a.{self::Operators::~}();
+  a.{self::Operators::|}(b);
+  a.{self::Operators::^}(b);
+  a.{self::Operators::/}(b);
+  a.{self::Operators::==}(b);
+  a.{self::Operators::>}(b);
+  a.{self::Operators::>=}(b);
+  a.{self::Operators::[]}(0);
+  a.{self::Operators::[]=}(0, b);
+  a.{self::Operators::<<}(b);
+  a.{self::Operators::<}(b);
+  a.{self::Operators::<=}(b);
+  a.{self::Operators::*}(b);
+  a.{self::Operators::%}(b);
+  a.{self::Operators::>>}(b);
+  a.{self::Operators::-}(b);
+  a.{self::Operators::~/}(b);
+  a.{self::Operators::unary-}();
+}
diff --git a/pkg/front_end/testcases/optional.dart.direct.expect b/pkg/front_end/testcases/optional.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/optional.dart.direct.expect
rename to pkg/front_end/testcases/optional.dart.legacy.expect
diff --git a/pkg/front_end/testcases/optional.dart.strong.expect b/pkg/front_end/testcases/optional.dart.strong.expect
index a741c32..513178e 100644
--- a/pkg/front_end/testcases/optional.dart.strong.expect
+++ b/pkg/front_end/testcases/optional.dart.strong.expect
@@ -1,9 +1,54 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/optional.dart:47:21: Error: The argument type '#lib1::InvalidListener' can't be assigned to the parameter type '#lib1::Listener'.
+// Try changing the type of the parameter, or casting the argument to '#lib1::Listener'.
+//   extern.listen(new InvalidListener());
+//                     ^
+//
+// pkg/front_end/testcases/optional.dart:49:28: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing1 = foo.method();
+//                            ^
+//
+// pkg/front_end/testcases/optional.dart:50:28: Error: Too many positional arguments: 3 allowed, but 4 found.
+// Try removing the extra positional arguments.
+//   var nothing2 = foo.method(1, 2, 3, 4);
+//                            ^
+//
+// pkg/front_end/testcases/optional.dart:51:39: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing3 = extern.externalMethod();
+//                                       ^
+//
+// pkg/front_end/testcases/optional.dart:52:39: Error: Too many positional arguments: 3 allowed, but 4 found.
+// Try removing the extra positional arguments.
+//   var nothing4 = extern.externalMethod(1, 2, 3, 4);
+//                                       ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/optional.dart:49:28: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing1 = foo.method();
+//                            ^
+//
+// pkg/front_end/testcases/optional.dart:50:28: Error: Too many positional arguments: 3 allowed, but 4 found.
+// Try removing the extra positional arguments.
+//   var nothing2 = foo.method(1, 2, 3, 4);
+//                            ^
+//
+// pkg/front_end/testcases/optional.dart:51:39: Error: Too few positional arguments: 1 required, 0 given.
+//   var nothing3 = extern.externalMethod();
+//                                       ^
+//
+// pkg/front_end/testcases/optional.dart:52:39: Error: Too many positional arguments: 3 allowed, but 4 found.
+// Try removing the extra positional arguments.
+//   var nothing4 = extern.externalMethod(1, 2, 3, 4);
+//                                       ^
+
 library;
 import self as self;
 import "dart:core" as core;
 
 class Foo extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::Foo
     : super core::Object::•()
     ;
   method method(dynamic x, [dynamic y = null, dynamic z = null]) → dynamic {
@@ -11,32 +56,32 @@
   }
 }
 abstract class External extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::External
     : super core::Object::•()
     ;
   abstract method externalMethod(core::int x, [core::int y = null, core::int z = null]) → core::String;
   abstract method listen(self::Listener listener) → void;
 }
 abstract class Listener extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::Listener
     : super core::Object::•()
     ;
   abstract method event(core::String input, [core::int x = null, core::int y = null]) → void;
 }
 class TestListener extends self::Listener {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::TestListener
     : super self::Listener::•()
     ;
-  method event(core::String input, [core::int x, core::int y]) → void {}
+  method event(core::String input, [core::int x = null, core::int y = null]) → void {}
 }
 class ExtendedListener extends self::Listener {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::ExtendedListener
     : super self::Listener::•()
     ;
-  method event(core::String input, [core::int x, core::int y, dynamic z]) → void {}
+  method event(core::String input, [core::int x = null, core::int y = null, dynamic z = null]) → void {}
 }
 class InvalidListener extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::InvalidListener
     : super core::Object::•()
     ;
   method event(dynamic input, [dynamic x = null]) → void {}
@@ -53,7 +98,10 @@
   core::String string6 = extern.{self::External::externalMethod}(1, 2, 3);
   extern.{self::External::listen}(new self::TestListener::•());
   extern.{self::External::listen}(new self::ExtendedListener::•());
-  extern.{self::External::listen}(new self::InvalidListener::•());
+  extern.{self::External::listen}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/optional.dart:47:21: Error: The argument type '#lib1::InvalidListener' can't be assigned to the parameter type '#lib1::Listener'.
+Try changing the type of the parameter, or casting the argument to '#lib1::Listener'.
+  extern.listen(new InvalidListener());
+                    ^" in new self::InvalidListener::•() as{TypeError} self::Listener);
   dynamic nothing1 = foo.{self::Foo::method}();
   dynamic nothing2 = foo.{self::Foo::method}(1, 2, 3, 4);
   core::String nothing3 = extern.{self::External::externalMethod}();
diff --git a/pkg/front_end/testcases/override.dart.direct.expect b/pkg/front_end/testcases/override.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/override.dart.direct.expect
rename to pkg/front_end/testcases/override.dart.legacy.expect
diff --git a/pkg/front_end/testcases/override.dart.direct.transformed.expect b/pkg/front_end/testcases/override.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/override.dart.direct.transformed.expect
rename to pkg/front_end/testcases/override.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/override_check_accessor_after_inference.dart.direct.expect b/pkg/front_end/testcases/override_check_accessor_after_inference.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_accessor_after_inference.dart.direct.expect
rename to pkg/front_end/testcases/override_check_accessor_after_inference.dart.legacy.expect
diff --git a/pkg/front_end/testcases/override_check_accessor_after_inference.dart.direct.transformed.expect b/pkg/front_end/testcases/override_check_accessor_after_inference.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_accessor_after_inference.dart.direct.transformed.expect
rename to pkg/front_end/testcases/override_check_accessor_after_inference.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/override_check_accessor_after_inference.dart.strong.expect b/pkg/front_end/testcases/override_check_accessor_after_inference.dart.strong.expect
index d6ad025..0a47546 100644
--- a/pkg/front_end/testcases/override_check_accessor_after_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_accessor_after_inference.dart.strong.expect
@@ -1,15 +1,15 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/override_check_accessor_after_inference.dart:28:51: Error: The return type of the method 'F::y' is #lib1::A, which does not match the return type of the overridden method (#lib1::B).
-// Change to a subtype of #lib1::B.
+// pkg/front_end/testcases/override_check_accessor_after_inference.dart:28:51: Error: The return type of the method 'F::y' is '#lib1::A', which does not match the return type of the overridden method, '#lib1::B'.
+// Change to a subtype of '#lib1::B'.
 //   A get /*@error=OverrideTypeMismatchReturnType*/ y => null;
 //                                                   ^
 // pkg/front_end/testcases/override_check_accessor_after_inference.dart:18:7: Context: This is the overridden method ('y').
 //   get y => null; // Inferred type: B
 //       ^
 //
-// pkg/front_end/testcases/override_check_accessor_after_inference.dart:27:57: Error: The parameter 'value' of the method 'F::x' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_accessor_after_inference.dart:27:57: Error: The parameter 'value' of the method 'F::x' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void set x(B /*@error=OverrideTypeMismatchParameter*/ value) {}
 //                                                         ^
 // pkg/front_end/testcases/override_check_accessor_after_inference.dart:17:12: Context: This is the overridden method ('x').
@@ -18,13 +18,13 @@
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/override_check_accessor_after_inference.dart:28:51: Error: The return type of the method 'F::y' is #lib1::A, which does not match the return type of the overridden method (#lib1::B).
-// Change to a subtype of #lib1::B.
+// pkg/front_end/testcases/override_check_accessor_after_inference.dart:28:51: Error: The return type of the method 'F::y' is '#lib1::A', which does not match the return type of the overridden method, '#lib1::B'.
+// Change to a subtype of '#lib1::B'.
 //   A get /*@error=OverrideTypeMismatchReturnType*/ y => null;
 //                                                   ^
 //
-// pkg/front_end/testcases/override_check_accessor_after_inference.dart:27:57: Error: The parameter 'value' of the method 'F::x' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_accessor_after_inference.dart:27:57: Error: The parameter 'value' of the method 'F::x' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void set x(B /*@error=OverrideTypeMismatchParameter*/ value) {}
 //                                                         ^
 
diff --git a/pkg/front_end/testcases/override_check_accessor_basic.dart.direct.expect b/pkg/front_end/testcases/override_check_accessor_basic.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_accessor_basic.dart.direct.expect
rename to pkg/front_end/testcases/override_check_accessor_basic.dart.legacy.expect
diff --git a/pkg/front_end/testcases/override_check_accessor_basic.dart.direct.transformed.expect b/pkg/front_end/testcases/override_check_accessor_basic.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_accessor_basic.dart.direct.transformed.expect
rename to pkg/front_end/testcases/override_check_accessor_basic.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/override_check_accessor_basic.dart.strong.expect b/pkg/front_end/testcases/override_check_accessor_basic.dart.strong.expect
index dc4010c..6372350 100644
--- a/pkg/front_end/testcases/override_check_accessor_basic.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_accessor_basic.dart.strong.expect
@@ -1,15 +1,15 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/override_check_accessor_basic.dart:23:56: Error: The return type of the method 'E::y' is dart.core::Object, which does not match the return type of the overridden method (#lib1::A).
-// Change to a subtype of #lib1::A.
+// pkg/front_end/testcases/override_check_accessor_basic.dart:23:56: Error: The return type of the method 'E::y' is 'dart.core::Object', which does not match the return type of the overridden method, '#lib1::A'.
+// Change to a subtype of '#lib1::A'.
 //   Object get /*@error=OverrideTypeMismatchReturnType*/ y => null;
 //                                                        ^
 // pkg/front_end/testcases/override_check_accessor_basic.dart:13:9: Context: This is the overridden method ('y').
 //   A get y => null;
 //         ^
 //
-// pkg/front_end/testcases/override_check_accessor_basic.dart:22:57: Error: The parameter 'value' of the method 'E::x' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_accessor_basic.dart:22:57: Error: The parameter 'value' of the method 'E::x' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void set x(B /*@error=OverrideTypeMismatchParameter*/ value) {}
 //                                                         ^
 // pkg/front_end/testcases/override_check_accessor_basic.dart:12:12: Context: This is the overridden method ('x').
@@ -18,13 +18,13 @@
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/override_check_accessor_basic.dart:23:56: Error: The return type of the method 'E::y' is dart.core::Object, which does not match the return type of the overridden method (#lib1::A).
-// Change to a subtype of #lib1::A.
+// pkg/front_end/testcases/override_check_accessor_basic.dart:23:56: Error: The return type of the method 'E::y' is 'dart.core::Object', which does not match the return type of the overridden method, '#lib1::A'.
+// Change to a subtype of '#lib1::A'.
 //   Object get /*@error=OverrideTypeMismatchReturnType*/ y => null;
 //                                                        ^
 //
-// pkg/front_end/testcases/override_check_accessor_basic.dart:22:57: Error: The parameter 'value' of the method 'E::x' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_accessor_basic.dart:22:57: Error: The parameter 'value' of the method 'E::x' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void set x(B /*@error=OverrideTypeMismatchParameter*/ value) {}
 //                                                         ^
 
diff --git a/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.direct.expect b/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.direct.expect
rename to pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.legacy.expect
diff --git a/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.direct.transformed.expect b/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.direct.transformed.expect
rename to pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.strong.expect b/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.strong.expect
index 8fc4f70..ff331c6 100644
--- a/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart.strong.expect
@@ -1,15 +1,15 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:25:50: Error: The parameter 'value' of the method 'D::x4' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:25:50: Error: The parameter 'value' of the method 'D::x4' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //       B /*@error=OverrideTypeMismatchParameter*/ value) {} // Not covariant
 //                                                  ^
 // pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:15:12: Context: This is the overridden method ('x4').
 //   void set x4(A value) {}
 //            ^
 //
-// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:27:65: Error: The parameter 'value' of the method 'D::x5' has type dart.core::String, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:27:65: Error: The parameter 'value' of the method 'D::x5' has type 'dart.core::String', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //       covariant String /*@error=OverrideTypeMismatchParameter*/ value) {}
 //                                                                 ^
 // pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:16:12: Context: This is the overridden method ('x5').
@@ -18,13 +18,13 @@
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:25:50: Error: The parameter 'value' of the method 'D::x4' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:25:50: Error: The parameter 'value' of the method 'D::x4' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //       B /*@error=OverrideTypeMismatchParameter*/ value) {} // Not covariant
 //                                                  ^
 //
-// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:27:65: Error: The parameter 'value' of the method 'D::x5' has type dart.core::String, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_accessor_with_covariant_modifier.dart:27:65: Error: The parameter 'value' of the method 'D::x5' has type 'dart.core::String', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //       covariant String /*@error=OverrideTypeMismatchParameter*/ value) {}
 //                                                                 ^
 
diff --git a/pkg/front_end/testcases/override_check_after_inference.dart.direct.expect b/pkg/front_end/testcases/override_check_after_inference.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_after_inference.dart.direct.expect
rename to pkg/front_end/testcases/override_check_after_inference.dart.legacy.expect
diff --git a/pkg/front_end/testcases/override_check_after_inference.dart.direct.transformed.expect b/pkg/front_end/testcases/override_check_after_inference.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_after_inference.dart.direct.transformed.expect
rename to pkg/front_end/testcases/override_check_after_inference.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/override_check_after_inference.dart.strong.expect b/pkg/front_end/testcases/override_check_after_inference.dart.strong.expect
index 8b8b1b8..279771a 100644
--- a/pkg/front_end/testcases/override_check_after_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_after_inference.dart.strong.expect
@@ -1,7 +1,7 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/override_check_after_inference.dart:24:53: Error: The parameter 'x' of the method 'F::f' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_after_inference.dart:24:53: Error: The parameter 'x' of the method 'F::f' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void f(B /*@error=OverrideTypeMismatchParameter*/ x) {}
 //                                                     ^
 // pkg/front_end/testcases/override_check_after_inference.dart:16:8: Context: This is the overridden method ('f').
@@ -10,8 +10,8 @@
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/override_check_after_inference.dart:24:53: Error: The parameter 'x' of the method 'F::f' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_after_inference.dart:24:53: Error: The parameter 'x' of the method 'F::f' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void f(B /*@error=OverrideTypeMismatchParameter*/ x) {}
 //                                                     ^
 
diff --git a/pkg/front_end/testcases/override_check_basic.dart.direct.expect b/pkg/front_end/testcases/override_check_basic.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_basic.dart.direct.expect
rename to pkg/front_end/testcases/override_check_basic.dart.legacy.expect
diff --git a/pkg/front_end/testcases/override_check_basic.dart.direct.transformed.expect b/pkg/front_end/testcases/override_check_basic.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_basic.dart.direct.transformed.expect
rename to pkg/front_end/testcases/override_check_basic.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/override_check_basic.dart.strong.expect b/pkg/front_end/testcases/override_check_basic.dart.strong.expect
index 72ccf4c..6455aa7 100644
--- a/pkg/front_end/testcases/override_check_basic.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_basic.dart.strong.expect
@@ -1,31 +1,31 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/override_check_basic.dart:29:52: Error: The return type of the method 'E::f4' is dart.core::Object, which does not match the return type of the overridden method (#lib1::A).
-// Change to a subtype of #lib1::A.
+// pkg/front_end/testcases/override_check_basic.dart:29:52: Error: The return type of the method 'E::f4' is 'dart.core::Object', which does not match the return type of the overridden method, '#lib1::A'.
+// Change to a subtype of '#lib1::A'.
 //   Object /*@error=OverrideTypeMismatchReturnType*/ f4() {}
 //                                                    ^
 // pkg/front_end/testcases/override_check_basic.dart:15:5: Context: This is the overridden method ('f4').
 //   A f4() {}
 //     ^
 //
-// pkg/front_end/testcases/override_check_basic.dart:28:55: Error: The parameter 'x' of the method 'E::f3' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_basic.dart:28:55: Error: The parameter 'x' of the method 'E::f3' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void f3({B /*@error=OverrideTypeMismatchParameter*/ x}) {}
 //                                                       ^
 // pkg/front_end/testcases/override_check_basic.dart:14:8: Context: This is the overridden method ('f3').
 //   void f3({A x}) {}
 //        ^
 //
-// pkg/front_end/testcases/override_check_basic.dart:26:54: Error: The parameter 'x' of the method 'E::f1' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_basic.dart:26:54: Error: The parameter 'x' of the method 'E::f1' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void f1(B /*@error=OverrideTypeMismatchParameter*/ x) {}
 //                                                      ^
 // pkg/front_end/testcases/override_check_basic.dart:12:8: Context: This is the overridden method ('f1').
 //   void f1(A x) {}
 //        ^
 //
-// pkg/front_end/testcases/override_check_basic.dart:27:55: Error: The parameter 'x' of the method 'E::f2' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_basic.dart:27:55: Error: The parameter 'x' of the method 'E::f2' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void f2([B /*@error=OverrideTypeMismatchParameter*/ x]) {}
 //                                                       ^
 // pkg/front_end/testcases/override_check_basic.dart:13:8: Context: This is the overridden method ('f2').
@@ -34,23 +34,23 @@
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/override_check_basic.dart:29:52: Error: The return type of the method 'E::f4' is dart.core::Object, which does not match the return type of the overridden method (#lib1::A).
-// Change to a subtype of #lib1::A.
+// pkg/front_end/testcases/override_check_basic.dart:29:52: Error: The return type of the method 'E::f4' is 'dart.core::Object', which does not match the return type of the overridden method, '#lib1::A'.
+// Change to a subtype of '#lib1::A'.
 //   Object /*@error=OverrideTypeMismatchReturnType*/ f4() {}
 //                                                    ^
 //
-// pkg/front_end/testcases/override_check_basic.dart:28:55: Error: The parameter 'x' of the method 'E::f3' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_basic.dart:28:55: Error: The parameter 'x' of the method 'E::f3' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void f3({B /*@error=OverrideTypeMismatchParameter*/ x}) {}
 //                                                       ^
 //
-// pkg/front_end/testcases/override_check_basic.dart:26:54: Error: The parameter 'x' of the method 'E::f1' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_basic.dart:26:54: Error: The parameter 'x' of the method 'E::f1' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void f1(B /*@error=OverrideTypeMismatchParameter*/ x) {}
 //                                                      ^
 //
-// pkg/front_end/testcases/override_check_basic.dart:27:55: Error: The parameter 'x' of the method 'E::f2' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_basic.dart:27:55: Error: The parameter 'x' of the method 'E::f2' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void f2([B /*@error=OverrideTypeMismatchParameter*/ x]) {}
 //                                                       ^
 
diff --git a/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.direct.expect b/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.direct.expect
rename to pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.legacy.expect
diff --git a/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.direct.transformed.expect b/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.direct.transformed.expect
rename to pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/override_check_two_substitutions.dart.direct.expect b/pkg/front_end/testcases/override_check_two_substitutions.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_two_substitutions.dart.direct.expect
rename to pkg/front_end/testcases/override_check_two_substitutions.dart.legacy.expect
diff --git a/pkg/front_end/testcases/override_check_two_substitutions.dart.direct.transformed.expect b/pkg/front_end/testcases/override_check_two_substitutions.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_two_substitutions.dart.direct.transformed.expect
rename to pkg/front_end/testcases/override_check_two_substitutions.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.direct.expect b/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_with_covariant_modifier.dart.direct.expect
rename to pkg/front_end/testcases/override_check_with_covariant_modifier.dart.legacy.expect
diff --git a/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.direct.transformed.expect b/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/override_check_with_covariant_modifier.dart.direct.transformed.expect
rename to pkg/front_end/testcases/override_check_with_covariant_modifier.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.strong.expect b/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.strong.expect
index 955df32..290169e 100644
--- a/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.strong.expect
+++ b/pkg/front_end/testcases/override_check_with_covariant_modifier.dart.strong.expect
@@ -1,15 +1,15 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:25:69: Error: The parameter 'x' of the method 'D::f5' has type dart.core::String, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:25:69: Error: The parameter 'x' of the method 'D::f5' has type 'dart.core::String', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void f5(covariant String /*@error=OverrideTypeMismatchParameter*/ x) {}
 //                                                                     ^
 // pkg/front_end/testcases/override_check_with_covariant_modifier.dart:16:8: Context: This is the overridden method ('f5').
 //   void f5(covariant A x) {}
 //        ^
 //
-// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:24:54: Error: The parameter 'x' of the method 'D::f4' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:24:54: Error: The parameter 'x' of the method 'D::f4' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void f4(B /*@error=OverrideTypeMismatchParameter*/ x) {} // Not covariant
 //                                                      ^
 // pkg/front_end/testcases/override_check_with_covariant_modifier.dart:15:8: Context: This is the overridden method ('f4').
@@ -18,13 +18,13 @@
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:25:69: Error: The parameter 'x' of the method 'D::f5' has type dart.core::String, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:25:69: Error: The parameter 'x' of the method 'D::f5' has type 'dart.core::String', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void f5(covariant String /*@error=OverrideTypeMismatchParameter*/ x) {}
 //                                                                     ^
 //
-// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:24:54: Error: The parameter 'x' of the method 'D::f4' has type #lib1::B, which does not match the corresponding type in the overridden method (#lib1::A).
-// Change to a supertype of #lib1::A (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/override_check_with_covariant_modifier.dart:24:54: Error: The parameter 'x' of the method 'D::f4' has type '#lib1::B', which does not match the corresponding type in the overridden method, '#lib1::A'.
+// Change to a supertype of '#lib1::A', or, for a covariant parameter, a subtype.
 //   void f4(B /*@error=OverrideTypeMismatchParameter*/ x) {} // Not covariant
 //                                                      ^
 
diff --git a/pkg/front_end/testcases/part_as_entry_point.dart b/pkg/front_end/testcases/part_as_entry_point.dart
new file mode 100644
index 0000000..0b9dc66
--- /dev/null
+++ b/pkg/front_end/testcases/part_as_entry_point.dart
@@ -0,0 +1,5 @@
+// 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.
+
+part of "part_as_entry_point_lib.dart";
diff --git a/pkg/front_end/testcases/hello.dart.direct.expect b/pkg/front_end/testcases/part_as_entry_point.dart.legacy.expect
similarity index 100%
copy from pkg/front_end/testcases/hello.dart.direct.expect
copy to pkg/front_end/testcases/part_as_entry_point.dart.legacy.expect
diff --git a/pkg/front_end/testcases/hello.dart.direct.transformed.expect b/pkg/front_end/testcases/part_as_entry_point.dart.legacy.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/hello.dart.direct.transformed.expect
copy to pkg/front_end/testcases/part_as_entry_point.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000045.dart.direct.expect b/pkg/front_end/testcases/part_as_entry_point.dart.outline.expect
similarity index 74%
rename from pkg/front_end/testcases/rasta/issue_000045.dart.direct.expect
rename to pkg/front_end/testcases/part_as_entry_point.dart.outline.expect
index 1cafd63..6a28c0d 100644
--- a/pkg/front_end/testcases/rasta/issue_000045.dart.direct.expect
+++ b/pkg/front_end/testcases/part_as_entry_point.dart.outline.expect
@@ -2,4 +2,4 @@
 import self as self;
 
 static method main() → dynamic
-  invalid-statement;
+  ;
diff --git a/pkg/front_end/testcases/hello.dart.direct.expect b/pkg/front_end/testcases/part_as_entry_point.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/hello.dart.direct.expect
copy to pkg/front_end/testcases/part_as_entry_point.dart.strong.expect
diff --git a/pkg/front_end/testcases/hello.dart.direct.transformed.expect b/pkg/front_end/testcases/part_as_entry_point.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/hello.dart.direct.transformed.expect
copy to pkg/front_end/testcases/part_as_entry_point.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/part_as_entry_point_lib.dart b/pkg/front_end/testcases/part_as_entry_point_lib.dart
new file mode 100644
index 0000000..a2f5430
--- /dev/null
+++ b/pkg/front_end/testcases/part_as_entry_point_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part "part_as_entry_point.dart";
+
+main() {
+  print("Hello, World!");
+}
diff --git a/pkg/front_end/testcases/platform.dart.direct.expect b/pkg/front_end/testcases/platform.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/platform.dart.direct.expect
rename to pkg/front_end/testcases/platform.dart.legacy.expect
diff --git a/pkg/front_end/testcases/platform.dart.direct.transformed.expect b/pkg/front_end/testcases/platform.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/platform.dart.direct.transformed.expect
rename to pkg/front_end/testcases/platform.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/platform.dart.direct.expect b/pkg/front_end/testcases/platform.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/platform.dart.direct.expect
copy to pkg/front_end/testcases/platform.dart.strong.expect
diff --git a/pkg/front_end/testcases/platform.dart.direct.transformed.expect b/pkg/front_end/testcases/platform.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/platform.dart.direct.transformed.expect
copy to pkg/front_end/testcases/platform.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/prefer_baseclass.dart.direct.expect b/pkg/front_end/testcases/prefer_baseclass.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/prefer_baseclass.dart.direct.expect
rename to pkg/front_end/testcases/prefer_baseclass.dart.legacy.expect
diff --git a/pkg/front_end/testcases/prefer_baseclass.dart.direct.transformed.expect b/pkg/front_end/testcases/prefer_baseclass.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/prefer_baseclass.dart.direct.transformed.expect
rename to pkg/front_end/testcases/prefer_baseclass.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/prefer_baseclass.dart.strong.expect b/pkg/front_end/testcases/prefer_baseclass.dart.strong.expect
index 56e4f44..18f3480 100644
--- a/pkg/front_end/testcases/prefer_baseclass.dart.strong.expect
+++ b/pkg/front_end/testcases/prefer_baseclass.dart.strong.expect
@@ -2,33 +2,33 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class A extends core::Object {
-  synthetic constructor •() → void
+class A extends core::Object {
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 }
-abstract class B extends core::Object {
-  synthetic constructor •() → void
+class B extends core::Object {
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
 }
 class AB1 extends self::A implements self::B {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::AB1
     : super self::A::•()
     ;
 }
 class AB2 extends self::A implements self::B {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::AB2
     : super self::A::•()
     ;
 }
 class BA1 extends self::B implements self::A {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::BA1
     : super self::B::•()
     ;
 }
 class BA2 extends self::B implements self::A {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::BA2
     : super self::B::•()
     ;
 }
diff --git a/pkg/front_end/testcases/prefer_baseclass.dart.direct.transformed.expect b/pkg/front_end/testcases/prefer_baseclass.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/prefer_baseclass.dart.direct.transformed.expect
copy to pkg/front_end/testcases/prefer_baseclass.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/private_method_tearoff.dart.direct.expect b/pkg/front_end/testcases/private_method_tearoff.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/private_method_tearoff.dart.direct.expect
rename to pkg/front_end/testcases/private_method_tearoff.dart.legacy.expect
diff --git a/pkg/front_end/testcases/private_method_tearoff.dart.direct.transformed.expect b/pkg/front_end/testcases/private_method_tearoff.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/private_method_tearoff.dart.direct.transformed.expect
rename to pkg/front_end/testcases/private_method_tearoff.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/public_method_tearoff.dart.direct.expect b/pkg/front_end/testcases/public_method_tearoff.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/public_method_tearoff.dart.direct.expect
rename to pkg/front_end/testcases/public_method_tearoff.dart.legacy.expect
diff --git a/pkg/front_end/testcases/public_method_tearoff.dart.direct.transformed.expect b/pkg/front_end/testcases/public_method_tearoff.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/public_method_tearoff.dart.direct.transformed.expect
rename to pkg/front_end/testcases/public_method_tearoff.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/qualified.dart.direct.expect b/pkg/front_end/testcases/qualified.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/qualified.dart.direct.expect
rename to pkg/front_end/testcases/qualified.dart.legacy.expect
diff --git a/pkg/front_end/testcases/qualified.dart.direct.transformed.expect b/pkg/front_end/testcases/qualified.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/qualified.dart.direct.transformed.expect
rename to pkg/front_end/testcases/qualified.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/abstract_constructor.dart.direct.expect b/pkg/front_end/testcases/rasta/abstract_constructor.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/abstract_constructor.dart.direct.expect
rename to pkg/front_end/testcases/rasta/abstract_constructor.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/abstract_constructor.dart.strong.expect b/pkg/front_end/testcases/rasta/abstract_constructor.dart.strong.expect
new file mode 100644
index 0000000..f288f84
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/abstract_constructor.dart.strong.expect
@@ -0,0 +1,24 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/abstract_constructor.dart:8:7: Error: The class 'C' is abstract and can't be instantiated.
+//   new C();
+//       ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/abstract_constructor.dart:8:7: Error: The class 'C' is abstract and can't be instantiated.
+//   new C();
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  throw new core::AbstractClassInstantiationError::•("C");
+}
diff --git a/pkg/front_end/testcases/rasta/abstract_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/abstract_constructor.dart.strong.transformed.expect
new file mode 100644
index 0000000..e2f40b5
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/abstract_constructor.dart.strong.transformed.expect
@@ -0,0 +1,18 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/abstract_constructor.dart:8:7: Error: The class 'C' is abstract and can't be instantiated.
+//   new C();
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  throw new core::AbstractClassInstantiationError::•("C");
+}
diff --git a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.direct.expect b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.direct.expect
rename to pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect
new file mode 100644
index 0000000..dca2096
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect
@@ -0,0 +1,26 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/bad_constructor_redirection.dart:6:21: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//   const C() : this.x(1);
+//                     ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  const constructor •() → self::C
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_constructor_redirection.dart:6:21: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+  const C() : this.x(1);
+                    ^"
+    ;
+  const constructor x() → self::C
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  new self::C::•();
+  const self::C::•();
+}
diff --git a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect
new file mode 100644
index 0000000..34a5b09
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  const constructor •() → self::C
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_constructor_redirection.dart:6:21: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+  const C() : this.x(1);
+                    ^"
+    ;
+  const constructor x() → self::C
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  new self::C::•();
+  const self::C::•();
+}
diff --git a/pkg/front_end/testcases/rasta/bad_continue.dart.direct.expect b/pkg/front_end/testcases/rasta/bad_continue.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/bad_continue.dart.direct.expect
rename to pkg/front_end/testcases/rasta/bad_continue.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/bad_continue.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_continue.dart.strong.expect
new file mode 100644
index 0000000..5ceeb3a
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_continue.dart.strong.expect
@@ -0,0 +1,40 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/bad_continue.dart:6:3: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//   continue here;
+//   ^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/bad_continue.dart:6:12: Error: Can't find label 'here'.
+// Try defining the label, or correcting the name to match an existing label.
+//   continue here;
+//            ^
+//
+// pkg/front_end/testcases/rasta/bad_continue.dart:7:10: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//   label: continue label;
+//          ^^^^^^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/bad_continue.dart:6:3: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//   continue here;
+//   ^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/bad_continue.dart:7:10: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//   label: continue label;
+//          ^^^^^^^^
+
+library;
+import self as self;
+
+static method main() → dynamic {
+  invalid-expression "pkg/front_end/testcases/rasta/bad_continue.dart:6:12: Error: Can't find label 'here'.
+Try defining the label, or correcting the name to match an existing label.
+  continue here;
+           ^";
+  #L1:
+  break #L1;
+}
diff --git a/pkg/front_end/testcases/rasta/bad_continue.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_continue.dart.strong.transformed.expect
new file mode 100644
index 0000000..4d870d0
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_continue.dart.strong.transformed.expect
@@ -0,0 +1,23 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/bad_continue.dart:6:3: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//   continue here;
+//   ^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/bad_continue.dart:7:10: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//   label: continue label;
+//          ^^^^^^^^
+
+library;
+import self as self;
+
+static method main() → dynamic {
+  invalid-expression "pkg/front_end/testcases/rasta/bad_continue.dart:6:12: Error: Can't find label 'here'.
+Try defining the label, or correcting the name to match an existing label.
+  continue here;
+           ^";
+  #L1:
+  break #L1;
+}
diff --git a/pkg/front_end/testcases/rasta/bad_default_constructor.dart.direct.expect b/pkg/front_end/testcases/rasta/bad_default_constructor.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/bad_default_constructor.dart.direct.expect
rename to pkg/front_end/testcases/rasta/bad_default_constructor.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.direct.expect b/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.direct.expect
rename to pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.direct.expect b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.direct.expect
deleted file mode 100644
index dcdb2f0..0000000
--- a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.direct.expect
+++ /dev/null
@@ -1,18 +0,0 @@
-library;
-import self as self;
-import "dart:core" as core;
-
-class A extends core::Object {
-  constructor •(dynamic x) → void
-    : final dynamic #t1 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:6:10: Error: 'x' isn't an instance field of this class.\n  A(this.x);\n         ^"
-    ;
-}
-class B extends self::A {
-  const constructor •() → void
-    : final dynamic #t2 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:10:9: Error: The unnamed constructor in 'A' requires arguments.\n  const B();\n        ^"
-    ;
-}
-static method main() → dynamic {
-  new self::B::•();
-  const self::B::•();
-}
diff --git a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.legacy.expect b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.legacy.expect
new file mode 100644
index 0000000..815d322
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.legacy.expect
@@ -0,0 +1,32 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:6:10: Error: 'x' isn't an instance field of this class.
+//   A(this.x);
+//          ^
+//
+// pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:10:9: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
+//   const B();
+//         ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •(dynamic x) → self::A
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:6:10: Error: 'x' isn't an instance field of this class.
+  A(this.x);
+         ^"
+    ;
+}
+class B extends self::A {
+  const constructor •() → self::B
+    : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:10:9: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
+  const B();
+        ^"
+    ;
+}
+static method main() → dynamic {
+  new self::B::•();
+  const self::B::•();
+}
diff --git a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.legacy.transformed.expect b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.legacy.transformed.expect
new file mode 100644
index 0000000..e218a4f
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.legacy.transformed.expect
@@ -0,0 +1,22 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •(dynamic x) → self::A
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:6:10: Error: 'x' isn't an instance field of this class.
+  A(this.x);
+         ^"
+    ;
+}
+class B extends self::A {
+  const constructor •() → self::B
+    : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:10:9: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
+  const B();
+        ^"
+    ;
+}
+static method main() → dynamic {
+  new self::B::•();
+  const self::B::•();
+}
diff --git a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.expect
new file mode 100644
index 0000000..815d322
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.expect
@@ -0,0 +1,32 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:6:10: Error: 'x' isn't an instance field of this class.
+//   A(this.x);
+//          ^
+//
+// pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:10:9: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
+//   const B();
+//         ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •(dynamic x) → self::A
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:6:10: Error: 'x' isn't an instance field of this class.
+  A(this.x);
+         ^"
+    ;
+}
+class B extends self::A {
+  const constructor •() → self::B
+    : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:10:9: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
+  const B();
+        ^"
+    ;
+}
+static method main() → dynamic {
+  new self::B::•();
+  const self::B::•();
+}
diff --git a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.transformed.expect
new file mode 100644
index 0000000..e218a4f
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.transformed.expect
@@ -0,0 +1,22 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •(dynamic x) → self::A
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:6:10: Error: 'x' isn't an instance field of this class.
+  A(this.x);
+         ^"
+    ;
+}
+class B extends self::A {
+  const constructor •() → self::B
+    : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:10:9: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
+  const B();
+        ^"
+    ;
+}
+static method main() → dynamic {
+  new self::B::•();
+  const self::B::•();
+}
diff --git a/pkg/front_end/testcases/rasta/bad_interpolation.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_interpolation.dart.strong.expect
new file mode 100644
index 0000000..6d6a791
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_interpolation.dart.strong.expect
@@ -0,0 +1,41 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/bad_interpolation.dart:6:13: Error: String starting with " must end with ".
+//   print(" $x.);
+//             ^^^
+//
+// pkg/front_end/testcases/rasta/bad_interpolation.dart:6:8: Error: Can't find ')' to match '('.
+//   print(" $x.);
+//        ^
+//
+// pkg/front_end/testcases/rasta/bad_interpolation.dart:6:12: Error: Getter not found: 'x'.
+//   print(" $x.);
+//            ^
+//
+// pkg/front_end/testcases/rasta/bad_interpolation.dart:6:13: Error: Expected ';' after this.
+//   print(" $x.);
+//             ^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/bad_interpolation.dart:6:13: Error: String starting with " must end with ".
+//   print(" $x.);
+//             ^^^
+//
+// pkg/front_end/testcases/rasta/bad_interpolation.dart:6:8: Error: Can't find ')' to match '('.
+//   print(" $x.);
+//        ^
+//
+// pkg/front_end/testcases/rasta/bad_interpolation.dart:6:13: Error: Expected ';' after this.
+//   print(" $x.);
+//             ^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print(" ${invalid-expression "pkg/front_end/testcases/rasta/bad_interpolation.dart:6:12: Error: Getter not found: 'x'.
+  print(\" \$x.);
+           ^"}.);");
+}
diff --git a/pkg/front_end/testcases/rasta/bad_interpolation.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_interpolation.dart.strong.transformed.expect
new file mode 100644
index 0000000..7e1cc73
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_interpolation.dart.strong.transformed.expect
@@ -0,0 +1,23 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/bad_interpolation.dart:6:13: Error: String starting with " must end with ".
+//   print(" $x.);
+//             ^^^
+//
+// pkg/front_end/testcases/rasta/bad_interpolation.dart:6:8: Error: Can't find ')' to match '('.
+//   print(" $x.);
+//        ^
+//
+// pkg/front_end/testcases/rasta/bad_interpolation.dart:6:13: Error: Expected ';' after this.
+//   print(" $x.);
+//             ^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print(" ${invalid-expression "pkg/front_end/testcases/rasta/bad_interpolation.dart:6:12: Error: Getter not found: 'x'.
+  print(\" \$x.);
+           ^"}.);");
+}
diff --git a/pkg/front_end/testcases/rasta/bad_redirection.dart.direct.expect b/pkg/front_end/testcases/rasta/bad_redirection.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/bad_redirection.dart.direct.expect
rename to pkg/front_end/testcases/rasta/bad_redirection.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/bad_redirection.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_redirection.dart.strong.expect
new file mode 100644
index 0000000..b9c7876
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_redirection.dart.strong.expect
@@ -0,0 +1,48 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/bad_redirection.dart:6:9: Error: Only factory constructor can specify '=' redirection.
+// Try making this a factory constructor, or remove the redirection.
+//   Foo() = Bar;
+//         ^
+//
+// pkg/front_end/testcases/rasta/bad_redirection.dart:6:9: Error: Expected a function body or '=>'.
+// Try adding {}.
+//   Foo() = Bar;
+//         ^
+//
+// pkg/front_end/testcases/rasta/bad_redirection.dart:6:11: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   Foo() = Bar;
+//           ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/bad_redirection.dart:6:9: Error: Only factory constructor can specify '=' redirection.
+// Try making this a factory constructor, or remove the redirection.
+//   Foo() = Bar;
+//         ^
+//
+// pkg/front_end/testcases/rasta/bad_redirection.dart:6:9: Error: Expected a function body or '=>'.
+// Try adding {}.
+//   Foo() = Bar;
+//         ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo
+    : super core::Object::•()
+    invalid-expression "pkg/front_end/testcases/rasta/bad_redirection.dart:6:11: Error: Constructors can't have a return type.
+Try removing the return type.
+  Foo() = Bar;
+          ^";
+}
+class Bar extends self::Foo {
+  static factory •() → self::Bar
+    return null;
+}
+static method main() → dynamic {
+  new self::Foo::•();
+}
diff --git a/pkg/front_end/testcases/rasta/bad_redirection.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_redirection.dart.strong.transformed.expect
new file mode 100644
index 0000000..016f9e1
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_redirection.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/bad_redirection.dart:6:9: Error: Only factory constructor can specify '=' redirection.
+// Try making this a factory constructor, or remove the redirection.
+//   Foo() = Bar;
+//         ^
+//
+// pkg/front_end/testcases/rasta/bad_redirection.dart:6:9: Error: Expected a function body or '=>'.
+// Try adding {}.
+//   Foo() = Bar;
+//         ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo
+    : super core::Object::•()
+    invalid-expression "pkg/front_end/testcases/rasta/bad_redirection.dart:6:11: Error: Constructors can't have a return type.
+Try removing the return type.
+  Foo() = Bar;
+          ^";
+}
+class Bar extends self::Foo {
+  static factory •() → self::Bar
+    return null;
+}
+static method main() → dynamic {
+  new self::Foo::•();
+}
diff --git a/pkg/front_end/testcases/rasta/bad_setter_initializer.dart.legacy.expect b/pkg/front_end/testcases/rasta/bad_setter_initializer.dart.legacy.expect
new file mode 100644
index 0000000..9cf944e
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_setter_initializer.dart.legacy.expect
@@ -0,0 +1,21 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/bad_setter_initializer.dart:6:9: Error: 'field' isn't an instance field of this class.
+//   C() : field = null;
+//         ^^^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor •() → self::C
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_setter_initializer.dart:6:9: Error: 'field' isn't an instance field of this class.
+  C() : field = null;
+        ^^^^^"
+    ;
+  set field(dynamic value) → dynamic {}
+}
+static method main() → dynamic {
+  new self::C::•();
+}
diff --git a/pkg/front_end/testcases/rasta/bad_setter_initializer.dart.direct.expect b/pkg/front_end/testcases/rasta/bad_setter_initializer.dart.legacy.transformed.expect
similarity index 60%
rename from pkg/front_end/testcases/rasta/bad_setter_initializer.dart.direct.expect
rename to pkg/front_end/testcases/rasta/bad_setter_initializer.dart.legacy.transformed.expect
index 957daf2..ee2c69c 100644
--- a/pkg/front_end/testcases/rasta/bad_setter_initializer.dart.direct.expect
+++ b/pkg/front_end/testcases/rasta/bad_setter_initializer.dart.legacy.transformed.expect
@@ -3,8 +3,10 @@
 import "dart:core" as core;
 
 class C extends core::Object {
-  constructor •() → void
-    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_setter_initializer.dart:6:15: Error: 'field' isn't an instance field of this class.\n  C() : field = null;\n              ^"
+  constructor •() → self::C
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_setter_initializer.dart:6:9: Error: 'field' isn't an instance field of this class.
+  C() : field = null;
+        ^^^^^"
     ;
   set field(dynamic value) → dynamic {}
 }
diff --git a/pkg/front_end/testcases/rasta/bad_setter_initializer.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_setter_initializer.dart.strong.expect
new file mode 100644
index 0000000..e77acb3
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_setter_initializer.dart.strong.expect
@@ -0,0 +1,21 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/bad_setter_initializer.dart:6:9: Error: 'field' isn't an instance field of this class.
+//   C() : field = null;
+//         ^^^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor •() → self::C
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_setter_initializer.dart:6:9: Error: 'field' isn't an instance field of this class.
+  C() : field = null;
+        ^^^^^"
+    ;
+  set field(dynamic value) → void {}
+}
+static method main() → dynamic {
+  new self::C::•();
+}
diff --git a/pkg/front_end/testcases/rasta/bad_setter_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_setter_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..692c97d
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_setter_initializer.dart.strong.transformed.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor •() → self::C
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_setter_initializer.dart:6:9: Error: 'field' isn't an instance field of this class.
+  C() : field = null;
+        ^^^^^"
+    ;
+  set field(dynamic value) → void {}
+}
+static method main() → dynamic {
+  new self::C::•();
+}
diff --git a/pkg/front_end/testcases/rasta/bad_unicode.dart.direct.expect b/pkg/front_end/testcases/rasta/bad_unicode.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/bad_unicode.dart.direct.expect
rename to pkg/front_end/testcases/rasta/bad_unicode.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/bad_unicode.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_unicode.dart.strong.expect
new file mode 100644
index 0000000..c35015a
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_unicode.dart.strong.expect
@@ -0,0 +1,19 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/bad_unicode.dart:6:10: Error: An escape sequence starting with '\u' must be followed by 4 hexadecimal digits or from 1 to 6 digits between '{' and '}'.
+//   print("\u00"); // Bad Unicode escape, must have 4 hex digits.
+//          ^^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/bad_unicode.dart:6:10: Error: An escape sequence starting with '\u' must be followed by 4 hexadecimal digits or from 1 to 6 digits between '{' and '}'.
+//   print("\u00"); // Bad Unicode escape, must have 4 hex digits.
+//          ^^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print("\\u00");
+}
diff --git a/pkg/front_end/testcases/rasta/bad_unicode.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_unicode.dart.strong.transformed.expect
new file mode 100644
index 0000000..5a2277d
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/bad_unicode.dart.strong.transformed.expect
@@ -0,0 +1,13 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/bad_unicode.dart:6:10: Error: An escape sequence starting with '\u' must be followed by 4 hexadecimal digits or from 1 to 6 digits between '{' and '}'.
+//   print("\u00"); // Bad Unicode escape, must have 4 hex digits.
+//          ^^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print("\\u00");
+}
diff --git a/pkg/front_end/testcases/rasta/breaking_bad.dart.direct.expect b/pkg/front_end/testcases/rasta/breaking_bad.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/breaking_bad.dart.direct.expect
rename to pkg/front_end/testcases/rasta/breaking_bad.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/breaking_bad.dart.strong.expect b/pkg/front_end/testcases/rasta/breaking_bad.dart.strong.expect
new file mode 100644
index 0000000..583a90e
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/breaking_bad.dart.strong.expect
@@ -0,0 +1,25 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/breaking_bad.dart:6:3: Error: A break statement can't be used outside of a loop or switch statement.
+// Try removing the break statement.
+//   break;
+//   ^^^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/breaking_bad.dart:6:3: Error: A break statement can't be used outside of a loop or switch statement.
+// Try removing the break statement.
+//   break;
+//   ^^^^^
+
+library;
+import self as self;
+
+static method main() → dynamic {
+  invalid-expression "pkg/front_end/testcases/rasta/breaking_bad.dart:6:3: Error: A break statement can't be used outside of a loop or switch statement.
+Try removing the break statement.
+  break;
+  ^";
+  #L1:
+  break #L1;
+}
diff --git a/pkg/front_end/testcases/rasta/breaking_bad.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/breaking_bad.dart.strong.transformed.expect
new file mode 100644
index 0000000..5401bce
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/breaking_bad.dart.strong.transformed.expect
@@ -0,0 +1,18 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/breaking_bad.dart:6:3: Error: A break statement can't be used outside of a loop or switch statement.
+// Try removing the break statement.
+//   break;
+//   ^^^^^
+
+library;
+import self as self;
+
+static method main() → dynamic {
+  invalid-expression "pkg/front_end/testcases/rasta/breaking_bad.dart:6:3: Error: A break statement can't be used outside of a loop or switch statement.
+Try removing the break statement.
+  break;
+  ^";
+  #L1:
+  break #L1;
+}
diff --git a/pkg/front_end/testcases/rasta/cascades.dart.direct.expect b/pkg/front_end/testcases/rasta/cascades.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/cascades.dart.direct.expect
rename to pkg/front_end/testcases/rasta/cascades.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/cascades.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/cascades.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/cascades.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/cascades.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/cascades.dart.strong.expect b/pkg/front_end/testcases/rasta/cascades.dart.strong.expect
new file mode 100644
index 0000000..4cbe618
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/cascades.dart.strong.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method add(dynamic x) → dynamic
+    return x;
+}
+static method main() → dynamic {
+  self::A a = new self::A::•();
+  function f(dynamic x) → dynamic
+    return x;
+  let final self::A #t1 = a in let final dynamic #t2 = #t1.{self::A::add}(f).call("WHAT") in #t1;
+}
diff --git a/pkg/front_end/testcases/rasta/cascades.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/cascades.dart.strong.transformed.expect
new file mode 100644
index 0000000..4cbe618
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/cascades.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method add(dynamic x) → dynamic
+    return x;
+}
+static method main() → dynamic {
+  self::A a = new self::A::•();
+  function f(dynamic x) → dynamic
+    return x;
+  let final self::A #t1 = a in let final dynamic #t2 = #t1.{self::A::add}(f).call("WHAT") in #t1;
+}
diff --git a/pkg/front_end/testcases/rasta/class_hierarchy.dart.direct.expect b/pkg/front_end/testcases/rasta/class_hierarchy.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/class_hierarchy.dart.direct.expect
rename to pkg/front_end/testcases/rasta/class_hierarchy.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect
new file mode 100644
index 0000000..9580383
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect
@@ -0,0 +1,88 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:9:7: Error: The type 'Missing' can't be mixed in.
+// class C = Object with Missing;
+//       ^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:5:17: Error: Type 'Missing' not found.
+// class A extends Missing {}
+//                 ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:7:20: Error: Type 'Missing' not found.
+// class B implements Missing {}
+//                    ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:9:23: Error: Type 'Missing' not found.
+// class C = Object with Missing;
+//                       ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:12:17: Error: Couldn't find constructor 'Missing'.
+//   factory D() = Missing;
+//                 ^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:12:11: Error: Redirection constructor target not found: 'Missing'
+//   factory D() = Missing;
+//           ^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:12:11: Error: Method not found: 'Missing'.
+//   factory D() = Missing;
+//           ^^^^^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:9:7: Error: The type 'Missing' can't be mixed in.
+// class C = Object with Missing;
+//       ^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:5:17: Error: Type 'Missing' not found.
+// class A extends Missing {}
+//                 ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:7:20: Error: Type 'Missing' not found.
+// class B implements Missing {}
+//                    ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:9:23: Error: Type 'Missing' not found.
+// class C = Object with Missing;
+//                       ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:12:17: Error: Couldn't find constructor 'Missing'.
+//   factory D() = Missing;
+//                 ^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:12:11: Error: Redirection constructor target not found: 'Missing'
+//   factory D() = Missing;
+//           ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::D::•];
+  static factory •() → self::D
+    let dynamic #redirecting_factory = "Missing" in invalid-expression;
+}
+static method main() → void {
+  new self::A::•();
+  new self::B::•();
+  new self::C::•();
+  let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/class_hierarchy.dart:12:11: Error: Method not found: 'Missing'.
+  factory D() = Missing;
+          ^^^^^^^";
+}
diff --git a/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect
new file mode 100644
index 0000000..b0ed08e
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect
@@ -0,0 +1,58 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:9:7: Error: The type 'Missing' can't be mixed in.
+// class C = Object with Missing;
+//       ^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:5:17: Error: Type 'Missing' not found.
+// class A extends Missing {}
+//                 ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:7:20: Error: Type 'Missing' not found.
+// class B implements Missing {}
+//                    ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:9:23: Error: Type 'Missing' not found.
+// class C = Object with Missing;
+//                       ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:12:17: Error: Couldn't find constructor 'Missing'.
+//   factory D() = Missing;
+//                 ^
+//
+// pkg/front_end/testcases/rasta/class_hierarchy.dart:12:11: Error: Redirection constructor target not found: 'Missing'
+//   factory D() = Missing;
+//           ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::D::•];
+  static factory •() → self::D
+    let core::String #redirecting_factory = "Missing" in invalid-expression;
+}
+static method main() → void {
+  new self::A::•();
+  new self::B::•();
+  new self::C::•();
+  let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/class_hierarchy.dart:12:11: Error: Method not found: 'Missing'.
+  factory D() = Missing;
+          ^^^^^^^";
+}
diff --git a/pkg/front_end/testcases/rasta/class_member.dart.direct.expect b/pkg/front_end/testcases/rasta/class_member.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/class_member.dart.direct.expect
rename to pkg/front_end/testcases/rasta/class_member.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/class_member.dart.strong.expect b/pkg/front_end/testcases/rasta/class_member.dart.strong.expect
new file mode 100644
index 0000000..5e57d9d
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/class_member.dart.strong.expect
@@ -0,0 +1,21 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  field dynamic field1 = null;
+  field dynamic field2 = null;
+  field dynamic field3 = null;
+  constructor constructor1() → self::Foo
+    : super core::Object::•()
+    ;
+  constructor constructor2() → self::Foo
+    : super core::Object::•()
+    ;
+  constructor constructor3() → self::Foo
+    : super core::Object::•()
+    ;
+  method a() → dynamic {}
+  method b() → dynamic {}
+  method c() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/rasta/class_member.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/class_member.dart.strong.transformed.expect
new file mode 100644
index 0000000..5e57d9d
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/class_member.dart.strong.transformed.expect
@@ -0,0 +1,21 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  field dynamic field1 = null;
+  field dynamic field2 = null;
+  field dynamic field3 = null;
+  constructor constructor1() → self::Foo
+    : super core::Object::•()
+    ;
+  constructor constructor2() → self::Foo
+    : super core::Object::•()
+    ;
+  constructor constructor3() → self::Foo
+    : super core::Object::•()
+    ;
+  method a() → dynamic {}
+  method b() → dynamic {}
+  method c() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/rasta/constant_get_and_invoke.dart.direct.expect b/pkg/front_end/testcases/rasta/constant_get_and_invoke.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/constant_get_and_invoke.dart.direct.expect
rename to pkg/front_end/testcases/rasta/constant_get_and_invoke.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/constant_get_and_invoke.dart.strong.expect b/pkg/front_end/testcases/rasta/constant_get_and_invoke.dart.strong.expect
new file mode 100644
index 0000000..b652238
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/constant_get_and_invoke.dart.strong.expect
@@ -0,0 +1,19 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/constant_get_and_invoke.dart:8:4: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+// Try correcting the name to the name of an existing method, or defining a method named 'call'.
+//   c();
+//    ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static const field core::int c = 1;
+static method main() → dynamic {
+  self::c;
+  let final dynamic #t1 = self::c in invalid-expression "pkg/front_end/testcases/rasta/constant_get_and_invoke.dart:8:4: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing method, or defining a method named 'call'.
+  c();
+   ^";
+}
diff --git a/pkg/front_end/testcases/rasta/constant_get_and_invoke.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/constant_get_and_invoke.dart.strong.transformed.expect
new file mode 100644
index 0000000..147a34d
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/constant_get_and_invoke.dart.strong.transformed.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static const field core::int c = 1;
+static method main() → dynamic {
+  self::c;
+  let final core::int #t1 = self::c in invalid-expression "pkg/front_end/testcases/rasta/constant_get_and_invoke.dart:8:4: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing method, or defining a method named 'call'.
+  c();
+   ^";
+}
diff --git a/pkg/front_end/testcases/rasta/deferred_lib.dart.direct.expect b/pkg/front_end/testcases/rasta/deferred_lib.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/deferred_lib.dart.direct.expect
rename to pkg/front_end/testcases/rasta/deferred_lib.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/deferred_load.dart.direct.expect b/pkg/front_end/testcases/rasta/deferred_load.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/deferred_load.dart.direct.expect
rename to pkg/front_end/testcases/rasta/deferred_load.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/deferred_load.dart.strong.expect b/pkg/front_end/testcases/rasta/deferred_load.dart.strong.expect
new file mode 100644
index 0000000..f076a51
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/deferred_load.dart.strong.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:async" as asy;
+
+static method main() → dynamic {
+  self::__loadLibrary_lib;
+  LoadLibrary(lib);
+}
+static method __loadLibrary_lib() → asy::Future<dynamic>
+  return LoadLibrary(lib);
diff --git a/pkg/front_end/testcases/rasta/deferred_load.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/deferred_load.dart.strong.transformed.expect
new file mode 100644
index 0000000..f076a51
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/deferred_load.dart.strong.transformed.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:async" as asy;
+
+static method main() → dynamic {
+  self::__loadLibrary_lib;
+  LoadLibrary(lib);
+}
+static method __loadLibrary_lib() → asy::Future<dynamic>
+  return LoadLibrary(lib);
diff --git a/pkg/front_end/testcases/rasta/duplicated_mixin.dart.direct.expect b/pkg/front_end/testcases/rasta/duplicated_mixin.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/duplicated_mixin.dart.direct.expect
rename to pkg/front_end/testcases/rasta/duplicated_mixin.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/duplicated_mixin.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/duplicated_mixin.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/duplicated_mixin.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/duplicated_mixin.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/enum.dart.direct.expect b/pkg/front_end/testcases/rasta/enum.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/enum.dart.direct.expect
rename to pkg/front_end/testcases/rasta/enum.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/enum.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/enum.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/enum.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/enum.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/enum.dart.direct.expect b/pkg/front_end/testcases/rasta/enum.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/rasta/enum.dart.direct.expect
copy to pkg/front_end/testcases/rasta/enum.dart.strong.expect
diff --git a/pkg/front_end/testcases/rasta/enum.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/enum.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/rasta/enum.dart.direct.transformed.expect
copy to pkg/front_end/testcases/rasta/enum.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/export.dart.direct.expect b/pkg/front_end/testcases/rasta/export.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/export.dart.direct.expect
rename to pkg/front_end/testcases/rasta/export.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/export.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/export.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/export.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/export.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/external_factory_redirection.dart.direct.expect b/pkg/front_end/testcases/rasta/external_factory_redirection.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/external_factory_redirection.dart.direct.expect
rename to pkg/front_end/testcases/rasta/external_factory_redirection.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/external_factory_redirection.dart.strong.expect b/pkg/front_end/testcases/rasta/external_factory_redirection.dart.strong.expect
new file mode 100644
index 0000000..acf6687
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/external_factory_redirection.dart.strong.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  "Should redirect to LinkedHashMap constructor.";
+  core::Map::•<core::Symbol, dynamic>();
+}
diff --git a/pkg/front_end/testcases/rasta/external_factory_redirection.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/external_factory_redirection.dart.strong.transformed.expect
new file mode 100644
index 0000000..acf6687
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/external_factory_redirection.dart.strong.transformed.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  "Should redirect to LinkedHashMap constructor.";
+  core::Map::•<core::Symbol, dynamic>();
+}
diff --git a/pkg/front_end/testcases/rasta/foo.dart.direct.expect b/pkg/front_end/testcases/rasta/foo.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/foo.dart.direct.expect
rename to pkg/front_end/testcases/rasta/foo.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/foo.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/foo.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/foo.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/foo.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/for_loop.dart.direct.expect b/pkg/front_end/testcases/rasta/for_loop.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/for_loop.dart.direct.expect
rename to pkg/front_end/testcases/rasta/for_loop.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/for_loop.dart.strong.expect b/pkg/front_end/testcases/rasta/for_loop.dart.strong.expect
new file mode 100644
index 0000000..babb8d3
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/for_loop.dart.strong.expect
@@ -0,0 +1,13 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::int c = new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch};
+  for (core::int i = 0; i.{core::num::<}(100); i = i.{core::num::+}(1)) {
+    core::print(let final core::int #t1 = i in let final core::int #t2 = i = #t1.{core::num::+}(1) in #t1);
+  }
+  for (core::int i = 0; i.{core::num::<}(100); c.{core::num::<}(42) ?{core::int} throw "fisk" : let final core::int #t3 = i in let final core::int #t4 = i = #t3.{core::num::+}(1) in #t3) {
+    core::print(let final core::int #t5 = i in let final core::int #t6 = i = #t5.{core::num::+}(1) in #t5);
+  }
+}
diff --git a/pkg/front_end/testcases/rasta/for_loop.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/for_loop.dart.strong.transformed.expect
new file mode 100644
index 0000000..babb8d3
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/for_loop.dart.strong.transformed.expect
@@ -0,0 +1,13 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::int c = new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch};
+  for (core::int i = 0; i.{core::num::<}(100); i = i.{core::num::+}(1)) {
+    core::print(let final core::int #t1 = i in let final core::int #t2 = i = #t1.{core::num::+}(1) in #t1);
+  }
+  for (core::int i = 0; i.{core::num::<}(100); c.{core::num::<}(42) ?{core::int} throw "fisk" : let final core::int #t3 = i in let final core::int #t4 = i = #t3.{core::num::+}(1) in #t3) {
+    core::print(let final core::int #t5 = i in let final core::int #t6 = i = #t5.{core::num::+}(1) in #t5);
+  }
+}
diff --git a/pkg/front_end/testcases/rasta/for_loop.dart.type_promotion.expect b/pkg/front_end/testcases/rasta/for_loop.dart.type_promotion.expect
new file mode 100644
index 0000000..2beae6f
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/for_loop.dart.type_promotion.expect
@@ -0,0 +1,12 @@
+pkg/front_end/testcases/rasta/for_loop.dart:7:29: Context: Write to i@292
+  for (int i = 0; i < 100; i++) {
+                            ^^
+pkg/front_end/testcases/rasta/for_loop.dart:8:12: Context: Write to i@292
+    print(i++);
+           ^^
+pkg/front_end/testcases/rasta/for_loop.dart:10:53: Context: Write to i@292
+  for (int i = 0; i < 100; c < 42 ? throw "fisk" : i++) {
+                                                    ^^
+pkg/front_end/testcases/rasta/for_loop.dart:11:12: Context: Write to i@292
+    print(i++);
+           ^^
diff --git a/pkg/front_end/testcases/rasta/generic_factory.dart.direct.expect b/pkg/front_end/testcases/rasta/generic_factory.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/generic_factory.dart.direct.expect
rename to pkg/front_end/testcases/rasta/generic_factory.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/generic_factory.dart.strong.expect b/pkg/front_end/testcases/rasta/generic_factory.dart.strong.expect
new file mode 100644
index 0000000..e191b84
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/generic_factory.dart.strong.expect
@@ -0,0 +1,99 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/generic_factory.dart:16:19: Error: Couldn't find constructor 'Missing'.
+//   factory A.c() = Missing;
+//                   ^
+//
+// pkg/front_end/testcases/rasta/generic_factory.dart:16:11: Error: Redirection constructor target not found: 'Missing'
+//   factory A.c() = Missing;
+//           ^
+//
+// pkg/front_end/testcases/rasta/generic_factory.dart:15:19: Error: The return type '#lib1::B<#lib1::C1>' of the constructor 'B.a' isn't a subtype of '#lib1::A<#lib1::A::b::T>'.
+// Try redirecting to a different constructor.
+//   factory A.b() = B<C1>.a;
+//                   ^
+//
+// pkg/front_end/testcases/rasta/generic_factory.dart:23:19: Error: The return type '#lib1::C<#lib1::C2>' of the constructor 'C' isn't a subtype of '#lib1::B<#lib1::B::b::S>'.
+// Try redirecting to a different constructor.
+//   factory B.b() = C<C2>;
+//                   ^
+//
+// pkg/front_end/testcases/rasta/generic_factory.dart:16:11: Error: Method not found: 'Missing'.
+//   factory A.c() = Missing;
+//           ^^^^^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/generic_factory.dart:16:19: Error: Couldn't find constructor 'Missing'.
+//   factory A.c() = Missing;
+//                   ^
+//
+// pkg/front_end/testcases/rasta/generic_factory.dart:16:11: Error: Redirection constructor target not found: 'Missing'
+//   factory A.c() = Missing;
+//           ^
+//
+// pkg/front_end/testcases/rasta/generic_factory.dart:15:19: Error: The return type '#lib1::B<#lib1::C1>' of the constructor 'B.a' isn't a subtype of '#lib1::A<#lib1::A::b::T>'.
+// Try redirecting to a different constructor.
+//   factory A.b() = B<C1>.a;
+//                   ^
+//
+// pkg/front_end/testcases/rasta/generic_factory.dart:23:19: Error: The return type '#lib1::C<#lib1::C2>' of the constructor 'C' isn't a subtype of '#lib1::B<#lib1::B::b::S>'.
+// Try redirecting to a different constructor.
+//   factory B.b() = C<C2>;
+//                   ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C1 extends core::Object {
+  synthetic constructor •() → self::C1
+    : super core::Object::•()
+    ;
+}
+class C2 extends core::Object {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+}
+class C3 extends core::Object {
+  synthetic constructor •() → self::C3
+    : super core::Object::•()
+    ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::A::a, self::A::b, self::A::c];
+  constructor internal() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+  static factory a<T extends core::Object = dynamic>() → self::A<self::A::a::T>
+    let dynamic #redirecting_factory = self::B::a in let self::A::a::T #typeArg0 = null in invalid-expression;
+  static factory b<T extends core::Object = dynamic>() → self::A<self::A::b::T>
+    let dynamic #redirecting_factory = self::B::a in let self::C1 #typeArg0 = null in invalid-expression;
+  static factory c<T extends core::Object = dynamic>() → self::A<self::A::c::T>
+    let dynamic #redirecting_factory = "Missing" in invalid-expression;
+}
+class B<S extends core::Object = dynamic> extends self::A<self::B::S> {
+  static field dynamic _redirecting# = <dynamic>[self::B::a, self::B::b];
+  constructor internal() → self::B<self::B::S>
+    : super self::A::internal()
+    ;
+  static factory a<S extends core::Object = dynamic>() → self::B<self::B::a::S>
+    let dynamic #redirecting_factory = self::C::• in let self::B::a::S #typeArg0 = null in invalid-expression;
+  static factory b<S extends core::Object = dynamic>() → self::B<self::B::b::S>
+    let dynamic #redirecting_factory = self::C::• in let self::C2 #typeArg0 = null in invalid-expression;
+}
+class C<U extends core::Object = dynamic> extends self::B<self::C::U> {
+  constructor •() → self::C<self::C::U>
+    : super self::B::internal()
+    ;
+}
+static method main() → dynamic {
+  new self::C::•<self::C3>();
+  new self::C::•<self::C1>();
+  new self::C::•<self::C3>();
+  new self::C::•<self::C2>();
+  let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/generic_factory.dart:16:11: Error: Method not found: 'Missing'.
+  factory A.c() = Missing;
+          ^^^^^^^";
+}
diff --git a/pkg/front_end/testcases/rasta/generic_factory.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/generic_factory.dart.strong.transformed.expect
new file mode 100644
index 0000000..c80527b
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/generic_factory.dart.strong.transformed.expect
@@ -0,0 +1,75 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/generic_factory.dart:16:19: Error: Couldn't find constructor 'Missing'.
+//   factory A.c() = Missing;
+//                   ^
+//
+// pkg/front_end/testcases/rasta/generic_factory.dart:16:11: Error: Redirection constructor target not found: 'Missing'
+//   factory A.c() = Missing;
+//           ^
+//
+// pkg/front_end/testcases/rasta/generic_factory.dart:15:19: Error: The return type '#lib1::B<#lib1::C1>' of the constructor 'B.a' isn't a subtype of '#lib1::A<#lib1::A::b::T>'.
+// Try redirecting to a different constructor.
+//   factory A.b() = B<C1>.a;
+//                   ^
+//
+// pkg/front_end/testcases/rasta/generic_factory.dart:23:19: Error: The return type '#lib1::C<#lib1::C2>' of the constructor 'C' isn't a subtype of '#lib1::B<#lib1::B::b::S>'.
+// Try redirecting to a different constructor.
+//   factory B.b() = C<C2>;
+//                   ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C1 extends core::Object {
+  synthetic constructor •() → self::C1
+    : super core::Object::•()
+    ;
+}
+class C2 extends core::Object {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+}
+class C3 extends core::Object {
+  synthetic constructor •() → self::C3
+    : super core::Object::•()
+    ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::A::a, self::A::b, self::A::c];
+  constructor internal() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+  static factory a<T extends core::Object = dynamic>() → self::A<self::A::a::T>
+    let <S extends core::Object = dynamic>() → self::B<self::B::a::S> #redirecting_factory = self::B::a in let self::A::a::T #typeArg0 = null in invalid-expression;
+  static factory b<T extends core::Object = dynamic>() → self::A<self::A::b::T>
+    let <S extends core::Object = dynamic>() → self::B<self::B::a::S> #redirecting_factory = self::B::a in let self::C1 #typeArg0 = null in invalid-expression;
+  static factory c<T extends core::Object = dynamic>() → self::A<self::A::c::T>
+    let core::String #redirecting_factory = "Missing" in invalid-expression;
+}
+class B<S extends core::Object = dynamic> extends self::A<self::B::S> {
+  static field dynamic _redirecting# = <dynamic>[self::B::a, self::B::b];
+  constructor internal() → self::B<self::B::S>
+    : super self::A::internal()
+    ;
+  static factory a<S extends core::Object = dynamic>() → self::B<self::B::a::S>
+    let<BottomType> #redirecting_factory = self::C::• in let self::B::a::S #typeArg0 = null in invalid-expression;
+  static factory b<S extends core::Object = dynamic>() → self::B<self::B::b::S>
+    let<BottomType> #redirecting_factory = self::C::• in let self::C2 #typeArg0 = null in invalid-expression;
+}
+class C<U extends core::Object = dynamic> extends self::B<self::C::U> {
+  constructor •() → self::C<self::C::U>
+    : super self::B::internal()
+    ;
+}
+static method main() → dynamic {
+  new self::C::•<self::C3>();
+  new self::C::•<self::C1>();
+  new self::C::•<self::C3>();
+  new self::C::•<self::C2>();
+  let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/generic_factory.dart:16:11: Error: Method not found: 'Missing'.
+  factory A.c() = Missing;
+          ^^^^^^^";
+}
diff --git a/pkg/front_end/testcases/rasta/hello.dart.direct.expect b/pkg/front_end/testcases/rasta/hello.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/hello.dart.direct.expect
rename to pkg/front_end/testcases/rasta/hello.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/hello.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/hello.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/hello.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/hello.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/hello.dart.direct.expect b/pkg/front_end/testcases/rasta/hello.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/rasta/hello.dart.direct.expect
copy to pkg/front_end/testcases/rasta/hello.dart.strong.expect
diff --git a/pkg/front_end/testcases/rasta/hello.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/hello.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/rasta/hello.dart.direct.transformed.expect
copy to pkg/front_end/testcases/rasta/hello.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/import_export.dart.direct.expect b/pkg/front_end/testcases/rasta/import_export.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/import_export.dart.direct.expect
rename to pkg/front_end/testcases/rasta/import_export.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/import_export.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/import_export.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/import_export.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/import_export.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000001.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000001.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000001.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000001.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000001.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000001.dart.strong.expect
new file mode 100644
index 0000000..d435a39
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000001.dart.strong.expect
@@ -0,0 +1,23 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/issue_000001.dart:11:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//   test0(0, 1);
+//        ^
+// pkg/front_end/testcases/rasta/issue_000001.dart:5:1: Context: Found this candidate, but the arguments don't match.
+// test0(x) {
+// ^^^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method test0(dynamic x) → dynamic {
+  core::print("test0");
+}
+static method main() → dynamic {
+  invalid-expression "pkg/front_end/testcases/rasta/issue_000001.dart:11:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+  test0(0, 1);
+       ^";
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000001.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000001.dart.strong.transformed.expect
new file mode 100644
index 0000000..0f8dca8
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000001.dart.strong.transformed.expect
@@ -0,0 +1,13 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method test0(dynamic x) → dynamic {
+  core::print("test0");
+}
+static method main() → dynamic {
+  invalid-expression "pkg/front_end/testcases/rasta/issue_000001.dart:11:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+  test0(0, 1);
+       ^";
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000002.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000002.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000002.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000002.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000002.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000002.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000002.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000002.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000002.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000002.dart.strong.expect
new file mode 100644
index 0000000..cb9d36e
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000002.dart.strong.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+import "dart:typed_data" as typ;
+
+class Foo extends core::Object {
+  final field dynamic value;
+  constructor •(dynamic value) → self::Foo
+    : self::Foo::value = value, super core::Object::•() {}
+  static factory fac(dynamic value) → self::Foo {
+    return new self::Foo::•(value);
+  }
+}
+static field core::List<core::int> list = <core::int>[1, 2, 3];
+static method main() → dynamic {
+  exp::Expect::isTrue(typ::Uint8List::fromList(self::list).{core::List::[]}(1).{core::num::==}(2));
+  exp::Expect::isTrue(self::Foo::fac(10).{self::Foo::value}.{core::Object::==}(10));
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000002.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000002.dart.strong.transformed.expect
new file mode 100644
index 0000000..cb9d36e
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000002.dart.strong.transformed.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+import "dart:typed_data" as typ;
+
+class Foo extends core::Object {
+  final field dynamic value;
+  constructor •(dynamic value) → self::Foo
+    : self::Foo::value = value, super core::Object::•() {}
+  static factory fac(dynamic value) → self::Foo {
+    return new self::Foo::•(value);
+  }
+}
+static field core::List<core::int> list = <core::int>[1, 2, 3];
+static method main() → dynamic {
+  exp::Expect::isTrue(typ::Uint8List::fromList(self::list).{core::List::[]}(1).{core::num::==}(2));
+  exp::Expect::isTrue(self::Foo::fac(10).{self::Foo::value}.{core::Object::==}(10));
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000004.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000004.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000004.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000004.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000004.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000004.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000004.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000004.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000004.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000004.dart.strong.expect
new file mode 100644
index 0000000..faa041e
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000004.dart.strong.expect
@@ -0,0 +1,35 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+static field dynamic global;
+static method fact4() → dynamic {
+  core::int f = 1;
+  for (core::int n in <core::int>[1, 2, 3, 4]) {
+    f = f.{core::num::*}(n);
+  }
+  return f;
+}
+static method fact5() → dynamic {
+  core::int f = 1;
+  dynamic n;
+  for (final dynamic #t1 in <dynamic>[1, 2, 3, 4, 5]) {
+    n = #t1;
+    f = f.{core::num::*}(n as{TypeError} core::num) as{TypeError} core::int;
+  }
+  return f;
+}
+static method fact6() → dynamic {
+  core::int f = 1;
+  for (final dynamic #t2 in <dynamic>[1, 2, 3, 4, 5, 6]) {
+    self::global = #t2;
+    f = f.{core::num::*}(self::global as{TypeError} core::num) as{TypeError} core::int;
+  }
+  return f;
+}
+static method main() → dynamic {
+  exp::Expect::isTrue(self::fact4().{core::Object::==}(24));
+  exp::Expect::isTrue(self::fact5().{core::Object::==}(120));
+  exp::Expect::isTrue(self::fact6().{core::Object::==}(720));
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000004.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000004.dart.strong.transformed.expect
new file mode 100644
index 0000000..faa041e
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000004.dart.strong.transformed.expect
@@ -0,0 +1,35 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+static field dynamic global;
+static method fact4() → dynamic {
+  core::int f = 1;
+  for (core::int n in <core::int>[1, 2, 3, 4]) {
+    f = f.{core::num::*}(n);
+  }
+  return f;
+}
+static method fact5() → dynamic {
+  core::int f = 1;
+  dynamic n;
+  for (final dynamic #t1 in <dynamic>[1, 2, 3, 4, 5]) {
+    n = #t1;
+    f = f.{core::num::*}(n as{TypeError} core::num) as{TypeError} core::int;
+  }
+  return f;
+}
+static method fact6() → dynamic {
+  core::int f = 1;
+  for (final dynamic #t2 in <dynamic>[1, 2, 3, 4, 5, 6]) {
+    self::global = #t2;
+    f = f.{core::num::*}(self::global as{TypeError} core::num) as{TypeError} core::int;
+  }
+  return f;
+}
+static method main() → dynamic {
+  exp::Expect::isTrue(self::fact4().{core::Object::==}(24));
+  exp::Expect::isTrue(self::fact5().{core::Object::==}(120));
+  exp::Expect::isTrue(self::fact6().{core::Object::==}(720));
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000004.dart.type_promotion.expect b/pkg/front_end/testcases/rasta/issue_000004.dart.type_promotion.expect
new file mode 100644
index 0000000..4904aab
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000004.dart.type_promotion.expect
@@ -0,0 +1,9 @@
+pkg/front_end/testcases/rasta/issue_000004.dart:10:7: Context: Write to f@273
+    f *= n;
+      ^^
+pkg/front_end/testcases/rasta/issue_000004.dart:18:7: Context: Write to f@359
+    f *= n;
+      ^^
+pkg/front_end/testcases/rasta/issue_000004.dart:27:7: Context: Write to f@459
+    f *= global;
+      ^^
diff --git a/pkg/front_end/testcases/rasta/issue_000006.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000006.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000006.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000006.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000006.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000006.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000006.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000006.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000006.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000006.dart.strong.expect
new file mode 100644
index 0000000..56bb4a2
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000006.dart.strong.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static field core::List<core::int> list = <core::int>[1, 2, 3];
+static method main() → dynamic {
+  self::list.{core::List::add}(1);
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000006.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000006.dart.strong.transformed.expect
new file mode 100644
index 0000000..56bb4a2
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000006.dart.strong.transformed.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static field core::List<core::int> list = <core::int>[1, 2, 3];
+static method main() → dynamic {
+  self::list.{core::List::add}(1);
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000007.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000007.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000007.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000007.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000007.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000007.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000007.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000007.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000008.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000008.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000008.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000008.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000008.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000008.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000008.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000008.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000008.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000008.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/rasta/issue_000008.dart.direct.expect
copy to pkg/front_end/testcases/rasta/issue_000008.dart.strong.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000008.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000008.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/rasta/issue_000008.dart.direct.transformed.expect
copy to pkg/front_end/testcases/rasta/issue_000008.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000011.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000011.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000011.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000011.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000011.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000011.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000011.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000011.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000011.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000011.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/rasta/issue_000011.dart.direct.expect
copy to pkg/front_end/testcases/rasta/issue_000011.dart.strong.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000011.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000011.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/rasta/issue_000011.dart.direct.transformed.expect
copy to pkg/front_end/testcases/rasta/issue_000011.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000012.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000012.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000012.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000012.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000012.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000012.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000012.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000012.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000012.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000012.dart.strong.expect
new file mode 100644
index 0000000..58026e4
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000012.dart.strong.expect
@@ -0,0 +1,21 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic field = null;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  method m() → dynamic {
+    super.{self::A::field} = 42;
+  }
+}
+static method main() → dynamic {
+  new self::B::•().{self::B::m}();
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000012.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000012.dart.strong.transformed.expect
new file mode 100644
index 0000000..58026e4
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000012.dart.strong.transformed.expect
@@ -0,0 +1,21 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic field = null;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  method m() → dynamic {
+    super.{self::A::field} = 42;
+  }
+}
+static method main() → dynamic {
+  new self::B::•().{self::B::m}();
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000025.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000025.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000025.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000025.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000025.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000025.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000025.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000025.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000025.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000025.dart.strong.expect
new file mode 100644
index 0000000..3be7ccc
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000025.dart.strong.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static get x() → dynamic
+  return 42;
+static set x(dynamic val) → void {}
+static method main() → dynamic {
+  core::print(self::x);
+  core::print(self::x = 87);
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000025.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000025.dart.strong.transformed.expect
new file mode 100644
index 0000000..3be7ccc
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000025.dart.strong.transformed.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static get x() → dynamic
+  return 42;
+static set x(dynamic val) → void {}
+static method main() → dynamic {
+  core::print(self::x);
+  core::print(self::x = 87);
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000026.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000026.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000026.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000026.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000026.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000026.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000026.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000026.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000026.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000026.dart.strong.expect
new file mode 100644
index 0000000..01488e9
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000026.dart.strong.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field dynamic a = null;
+  field core::int b = 0;
+  field core::int c = 1.{core::num::+}(2);
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object {
+  field dynamic a = null;
+  field core::int b = 1;
+  field core::int c = 2.{core::num::-}(3);
+  constructor •() → self::D
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  new self::C::•();
+  new self::D::•();
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000026.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000026.dart.strong.transformed.expect
new file mode 100644
index 0000000..01488e9
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000026.dart.strong.transformed.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field dynamic a = null;
+  field core::int b = 0;
+  field core::int c = 1.{core::num::+}(2);
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object {
+  field dynamic a = null;
+  field core::int b = 1;
+  field core::int c = 2.{core::num::-}(3);
+  constructor •() → self::D
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  new self::C::•();
+  new self::D::•();
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000031.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000031.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000031.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000031.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000031.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000031.dart.strong.expect
new file mode 100644
index 0000000..8894cf7
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000031.dart.strong.expect
@@ -0,0 +1,14 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/issue_000031.dart:8:3: Error: A prefix can't be used as an expression.
+//   math..toString();
+//   ^^^^
+
+library;
+import self as self;
+
+static method main() → dynamic {
+  let final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/issue_000031.dart:8:3: Error: A prefix can't be used as an expression.
+  math..toString();
+  ^^^^" in let final dynamic #t2 = #t1.{dart.core::Object::toString}() in #t1;
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000031.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000031.dart.strong.transformed.expect
new file mode 100644
index 0000000..3042bd3
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000031.dart.strong.transformed.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  let final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/issue_000031.dart:8:3: Error: A prefix can't be used as an expression.
+  math..toString();
+  ^^^^" in let final core::String #t2 = #t1.{core::Object::toString}() in #t1;
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000032.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000032.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000032.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000032.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000032.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000032.dart.strong.expect
new file mode 100644
index 0000000..b296e5b
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000032.dart.strong.expect
@@ -0,0 +1,73 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:7:1: Error: Expected an identifier, but got '}'.
+// }
+// ^
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:6:4: Error: Constructors can't have type parameters.
+//   C<
+//    ^^...
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:6:3: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   C<
+//   ^
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:7:1: Error: Expected '{' before this.
+// }
+// ^
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:11:1: Error: Expected an identifier, but got '}'.
+// }
+// ^
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:11:1: Error: Expected ';' after this.
+// }
+// ^
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:10:4: Error: The method '<' isn't defined for the class 'dart.core::Type'.
+// Try correcting the name to the name of an existing method, or defining a method named '<'.
+//   C<
+//    ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:7:1: Error: Expected an identifier, but got '}'.
+// }
+// ^
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:6:4: Error: Constructors can't have type parameters.
+//   C<
+//    ^^...
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:6:3: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   C<
+//   ^
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:7:1: Error: Expected '{' before this.
+// }
+// ^
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:11:1: Error: Expected an identifier, but got '}'.
+// }
+// ^
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:11:1: Error: Expected ';' after this.
+// }
+// ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor •() → self::C
+    : super core::Object::•() {}
+}
+static method main() → dynamic {
+  let final dynamic #t1 = self::C in invalid-expression "pkg/front_end/testcases/rasta/issue_000032.dart:10:4: Error: The method '<' isn't defined for the class 'dart.core::Type'.
+Try correcting the name to the name of an existing method, or defining a method named '<'.
+  C<
+   ^";
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000032.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000032.dart.strong.transformed.expect
new file mode 100644
index 0000000..8f5a746
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000032.dart.strong.transformed.expect
@@ -0,0 +1,41 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:7:1: Error: Expected an identifier, but got '}'.
+// }
+// ^
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:6:4: Error: Constructors can't have type parameters.
+//   C<
+//    ^^...
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:6:3: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   C<
+//   ^
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:7:1: Error: Expected '{' before this.
+// }
+// ^
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:11:1: Error: Expected an identifier, but got '}'.
+// }
+// ^
+//
+// pkg/front_end/testcases/rasta/issue_000032.dart:11:1: Error: Expected ';' after this.
+// }
+// ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor •() → self::C
+    : super core::Object::•() {}
+}
+static method main() → dynamic {
+  let final core::Type #t1 = self::C in invalid-expression "pkg/front_end/testcases/rasta/issue_000032.dart:10:4: Error: The method '<' isn't defined for the class 'dart.core::Type'.
+Try correcting the name to the name of an existing method, or defining a method named '<'.
+  C<
+   ^";
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000033.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000033.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000033.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000033.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000033.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000033.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000033.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000033.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000033.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000033.dart.strong.expect
new file mode 100644
index 0000000..894663d
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000033.dart.strong.expect
@@ -0,0 +1,13 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/issue_000033.dart:5:2: Error: Method not found: 'JS'.
+// @JS()
+//  ^^
+
+library;
+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/rasta/issue_000033.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000033.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/rasta/issue_000033.dart.direct.transformed.expect
copy to pkg/front_end/testcases/rasta/issue_000033.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000034.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000034.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000034.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000034.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000034.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000034.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000034.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000034.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000035.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000035.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000035.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000035.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000035.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000035.dart.strong.expect
new file mode 100644
index 0000000..6634367
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000035.dart.strong.expect
@@ -0,0 +1,59 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/issue_000035.dart:5:10: Error: The non-ASCII character 'æ' (U+00E6) can't be used in identifiers, only in strings and comments.
+// Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign).
+// class C {æøC();}
+//          ^
+//
+// pkg/front_end/testcases/rasta/issue_000035.dart:5:11: Error: The non-ASCII character 'ø' (U+00F8) can't be used in identifiers, only in strings and comments.
+// Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign).
+// class C {æøC();}
+//           ^
+//
+// pkg/front_end/testcases/rasta/issue_000035.dart:5:7: Error: The non-abstract class 'C' is missing implementations for these members:
+//   'æøC'.
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class C {æøC();}
+//       ^
+// pkg/front_end/testcases/rasta/issue_000035.dart:5:10: Context: 'æøC' is defined here.
+// class C {æøC();}
+//          ^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000035.dart:5:10: Error: The non-ASCII character 'æ' (U+00E6) can't be used in identifiers, only in strings and comments.
+// Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign).
+// class C {æøC();}
+//          ^
+//
+// pkg/front_end/testcases/rasta/issue_000035.dart:5:11: Error: The non-ASCII character 'ø' (U+00F8) can't be used in identifiers, only in strings and comments.
+// Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign).
+// class C {æøC();}
+//           ^
+//
+// pkg/front_end/testcases/rasta/issue_000035.dart:5:7: Error: The non-abstract class 'C' is missing implementations for these members:
+//   'æøC'.
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+// 
+// class C {æøC();}
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  abstract method æøC() → dynamic;
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000035.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000035.dart.strong.transformed.expect
new file mode 100644
index 0000000..685c552
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000035.dart.strong.transformed.expect
@@ -0,0 +1,33 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000035.dart:5:10: Error: The non-ASCII character 'æ' (U+00E6) can't be used in identifiers, only in strings and comments.
+// Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign).
+// class C {æøC();}
+//          ^
+//
+// pkg/front_end/testcases/rasta/issue_000035.dart:5:11: Error: The non-ASCII character 'ø' (U+00F8) can't be used in identifiers, only in strings and comments.
+// Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign).
+// class C {æøC();}
+//           ^
+//
+// pkg/front_end/testcases/rasta/issue_000035.dart:5:7: Error: The non-abstract class 'C' is missing implementations for these members:
+//   'æøC'.
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+// 
+// class C {æøC();}
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  abstract method æøC() → dynamic;
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000035a.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000035a.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000035a.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000035a.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000035a.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000035a.dart.strong.expect
new file mode 100644
index 0000000..4956732
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000035a.dart.strong.expect
@@ -0,0 +1,29 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/issue_000035a.dart:5:9: Error: The non-ASCII space character U+2028 can only be used in strings and comments.
+// class C{

C();}
+//         ^
+//
+// pkg/front_end/testcases/rasta/issue_000035a.dart:5:10: Error: The non-ASCII space character U+2028 can only be used in strings and comments.
+// class C{

C();}
+//          ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000035a.dart:5:9: Error: The non-ASCII space character U+2028 can only be used in strings and comments.
+// class C{

C();}
+//         ^
+//
+// pkg/front_end/testcases/rasta/issue_000035a.dart:5:10: Error: The non-ASCII space character U+2028 can only be used in strings and comments.
+// class C{

C();}
+//          ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000035a.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000035a.dart.strong.transformed.expect
new file mode 100644
index 0000000..f94b743
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000035a.dart.strong.transformed.expect
@@ -0,0 +1,19 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000035a.dart:5:9: Error: The non-ASCII space character U+2028 can only be used in strings and comments.
+// class C{

C();}
+//         ^
+//
+// pkg/front_end/testcases/rasta/issue_000035a.dart:5:10: Error: The non-ASCII space character U+2028 can only be used in strings and comments.
+// class C{

C();}
+//          ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000036.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000036.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000036.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000036.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000036.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000036.dart.strong.expect
new file mode 100644
index 0000000..52166ab
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000036.dart.strong.expect
@@ -0,0 +1,23 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/issue_000036.dart:5:14: Error: Expected an identifier, but got '-'.
+// main() => a. - 5;
+//              ^
+//
+// pkg/front_end/testcases/rasta/issue_000036.dart:5:14: Error: Expected an identifier, but got ''.
+// main() => a. - 5;
+//              ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000036.dart:5:14: Error: Expected an identifier, but got '-'.
+// main() => a. - 5;
+//              ^
+
+library;
+import self as self;
+
+static method main() → dynamic
+  return invalid-expression "pkg/front_end/testcases/rasta/issue_000036.dart:5:14: Error: Expected an identifier, but got ''.
+main() => a. - 5;
+             ^".-(5);
diff --git a/pkg/front_end/testcases/rasta/issue_000036.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000036.dart.strong.transformed.expect
new file mode 100644
index 0000000..a3dffd2
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000036.dart.strong.transformed.expect
@@ -0,0 +1,13 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000036.dart:5:14: Error: Expected an identifier, but got '-'.
+// main() => a. - 5;
+//              ^
+
+library;
+import self as self;
+
+static method main() → dynamic
+  return invalid-expression "pkg/front_end/testcases/rasta/issue_000036.dart:5:14: Error: Expected an identifier, but got ''.
+main() => a. - 5;
+             ^".-(5);
diff --git a/pkg/front_end/testcases/rasta/issue_000039.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000039.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000039.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000039.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000041.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000041.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000041.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000041.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000041.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000041.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000041.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000041.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000042.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000042.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000042.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000042.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000042.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000042.dart.strong.expect
new file mode 100644
index 0000000..a54413f
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000042.dart.strong.expect
@@ -0,0 +1,71 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/issue_000042.dart:6:13: Error: Unexpected token ','.
+//   for (var x, y in []) {}
+//             ^
+//
+// pkg/front_end/testcases/rasta/issue_000042.dart:6:8: Error: A for-in loop can't have more than one loop variable.
+//   for (var x, y in []) {}
+//        ^^^
+//
+// pkg/front_end/testcases/rasta/issue_000042.dart:7:8: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//   L: { continue L; }
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/issue_000042.dart:8:18: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//   L: if (true) { continue L; }
+//                  ^^^^^^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000042.dart:6:13: Error: Unexpected token ','.
+//   for (var x, y in []) {}
+//             ^
+//
+// pkg/front_end/testcases/rasta/issue_000042.dart:7:8: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//   L: { continue L; }
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/issue_000042.dart:8:18: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//   L: if (true) { continue L; }
+//                  ^^^^^^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  for (final dynamic #t1 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/issue_000042.dart:6:8: Error: A for-in loop can't have more than one loop variable.
+  for (var x, y in []) {}
+       ^^^" in <dynamic>[]) {
+  }
+  #L1:
+  {
+    break #L1;
+  }
+  #L2:
+  if(true) {
+    break #L2;
+  }
+  #L3:
+  switch(1) {
+    #L4:
+    case 1:
+      {
+        break #L3;
+      }
+    #L5:
+    case 2:
+      {
+        break #L3;
+      }
+  }
+  try {
+  }
+  on core::NoSuchMethodError catch(no-exception-var) {
+  }
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect
new file mode 100644
index 0000000..709363f
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect
@@ -0,0 +1,51 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000042.dart:6:13: Error: Unexpected token ','.
+//   for (var x, y in []) {}
+//             ^
+//
+// pkg/front_end/testcases/rasta/issue_000042.dart:7:8: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//   L: { continue L; }
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/issue_000042.dart:8:18: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//   L: if (true) { continue L; }
+//                  ^^^^^^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  for (final dynamic #t1 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/issue_000042.dart:6:8: Error: A for-in loop can't have more than one loop variable.
+  for (var x, y in []) {}
+       ^^^" in <dynamic>[]) {
+  }
+  #L1:
+  {
+    break #L1;
+  }
+  #L2:
+  if(true) {
+    break #L2;
+  }
+  #L3:
+  switch(1) {
+    #L4:
+    case 1:
+      {
+        break #L3;
+      }
+    #L5:
+    case 2:
+      {
+        break #L3;
+      }
+  }
+  try {
+  }
+  on core::NoSuchMethodError catch(no-exception-var) {
+  }
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000043.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000043.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000043.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000043.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000043.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000043.dart.strong.expect
new file mode 100644
index 0000000..84c90c8
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000043.dart.strong.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  get x() → dynamic
+    return "${self::C}".{core::String::hashCode};
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000043.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000043.dart.strong.transformed.expect
new file mode 100644
index 0000000..84c90c8
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000043.dart.strong.transformed.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  get x() → dynamic
+    return "${self::C}".{core::String::hashCode};
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000044.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000044.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000044.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000044.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect
new file mode 100644
index 0000000..1596abd
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect
@@ -0,0 +1,138 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:7:8: Error: Expected a function body or '=>'.
+// Try adding {}.
+// a b(c) = d;
+//        ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:14:29: Error: Only factory constructor can specify '=' redirection.
+// Try making this a factory constructor, or remove the redirection.
+//   C.missingFactoryKeyword() = C.constant;
+//                             ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:21:28: Error: Only factory constructor can specify '=' redirection.
+// Try making this a factory constructor, or remove the redirection.
+//   C notEvenAConstructor(a) = h;
+//                            ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:7:1: Error: Type 'a' not found.
+// a b(c) = d;
+// ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: Couldn't find constructor 'h'.
+//   C notEvenAConstructor(a) = h;
+//                              ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:7:10: Error: Getter not found: 'd'.
+// a b(c) = d;
+//          ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:14:29: Error: Expected a function body or '=>'.
+// Try adding {}.
+//   C.missingFactoryKeyword() = C.constant;
+//                             ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:14:33: Error: Getter not found: 'constant'.
+//   C.missingFactoryKeyword() = C.constant;
+//                                 ^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:14:31: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   C.missingFactoryKeyword() = C.constant;
+//                               ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:21:28: Error: Expected a function body or '=>'.
+// Try adding {}.
+//   C notEvenAConstructor(a) = h;
+//                            ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: Getter not found: 'h'.
+//   C notEvenAConstructor(a) = h;
+//                              ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: The getter 'h' isn't defined for the class '#lib1::C'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'h'.
+//   C notEvenAConstructor(a) = h;
+//                              ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:27:15: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   print(const C.missingFactoryKeyword());
+//               ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:7:8: Error: Expected a function body or '=>'.
+// Try adding {}.
+// a b(c) = d;
+//        ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:14:29: Error: Only factory constructor can specify '=' redirection.
+// Try making this a factory constructor, or remove the redirection.
+//   C.missingFactoryKeyword() = C.constant;
+//                             ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:21:28: Error: Only factory constructor can specify '=' redirection.
+// Try making this a factory constructor, or remove the redirection.
+//   C notEvenAConstructor(a) = h;
+//                            ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:7:1: Error: Type 'a' not found.
+// a b(c) = d;
+// ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: Couldn't find constructor 'h'.
+//   C notEvenAConstructor(a) = h;
+//                              ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:14:29: Error: Expected a function body or '=>'.
+// Try adding {}.
+//   C.missingFactoryKeyword() = C.constant;
+//                             ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:21:28: Error: Expected a function body or '=>'.
+// Try adding {}.
+//   C notEvenAConstructor(a) = h;
+//                            ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: Getter not found: 'h'.
+//   C notEvenAConstructor(a) = h;
+//                              ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::C::good];
+  const constructor constant() → self::C
+    : super core::Object::•()
+    ;
+  constructor missingFactoryKeyword() → self::C
+    : super core::Object::•()
+    invalid-expression "pkg/front_end/testcases/rasta/issue_000044.dart:14:31: Error: Constructors can't have a return type.
+Try removing the return type.
+  C.missingFactoryKeyword() = C.constant;
+                              ^";
+  static factory good() → self::C
+    let dynamic #redirecting_factory = self::C::constant in invalid-expression;
+  method notEvenAConstructor(dynamic a) → self::C
+    return (let final dynamic #t1 = this in invalid-expression "pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: The getter 'h' isn't defined for the class '#lib1::C'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'h'.
+  C notEvenAConstructor(a) = h;
+                             ^") as{TypeError} self::C;
+}
+static method b(dynamic c) → invalid-type
+  return invalid-expression "pkg/front_end/testcases/rasta/issue_000044.dart:7:10: Error: Getter not found: 'd'.
+a b(c) = d;
+         ^" as{TypeError} invalid-type;
+static method main() → dynamic {
+  self::C c = null;
+  core::print(const self::C::constant());
+  core::print(invalid-expression "pkg/front_end/testcases/rasta/issue_000044.dart:27:15: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  print(const C.missingFactoryKeyword());
+              ^");
+  core::print(const self::C::constant());
+  core::print(new self::C::constant().{self::C::notEvenAConstructor}(null));
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect
new file mode 100644
index 0000000..c958e86
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect
@@ -0,0 +1,76 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:7:8: Error: Expected a function body or '=>'.
+// Try adding {}.
+// a b(c) = d;
+//        ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:14:29: Error: Only factory constructor can specify '=' redirection.
+// Try making this a factory constructor, or remove the redirection.
+//   C.missingFactoryKeyword() = C.constant;
+//                             ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:21:28: Error: Only factory constructor can specify '=' redirection.
+// Try making this a factory constructor, or remove the redirection.
+//   C notEvenAConstructor(a) = h;
+//                            ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:7:1: Error: Type 'a' not found.
+// a b(c) = d;
+// ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: Couldn't find constructor 'h'.
+//   C notEvenAConstructor(a) = h;
+//                              ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:14:29: Error: Expected a function body or '=>'.
+// Try adding {}.
+//   C.missingFactoryKeyword() = C.constant;
+//                             ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:21:28: Error: Expected a function body or '=>'.
+// Try adding {}.
+//   C notEvenAConstructor(a) = h;
+//                            ^
+//
+// pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: Getter not found: 'h'.
+//   C notEvenAConstructor(a) = h;
+//                              ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::C::good];
+  const constructor constant() → self::C
+    : super core::Object::•()
+    ;
+  constructor missingFactoryKeyword() → self::C
+    : super core::Object::•()
+    invalid-expression "pkg/front_end/testcases/rasta/issue_000044.dart:14:31: Error: Constructors can't have a return type.
+Try removing the return type.
+  C.missingFactoryKeyword() = C.constant;
+                              ^";
+  static factory good() → self::C
+    let<BottomType> #redirecting_factory = self::C::constant in invalid-expression;
+  method notEvenAConstructor(dynamic a) → self::C
+    return (let final self::C #t1 = this in invalid-expression "pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: The getter 'h' isn't defined for the class '#lib1::C'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'h'.
+  C notEvenAConstructor(a) = h;
+                             ^") as{TypeError} self::C;
+}
+static method b(dynamic c) → invalid-type
+  return invalid-expression "pkg/front_end/testcases/rasta/issue_000044.dart:7:10: Error: Getter not found: 'd'.
+a b(c) = d;
+         ^" as{TypeError} invalid-type;
+static method main() → dynamic {
+  self::C c = null;
+  core::print(const self::C::constant());
+  core::print(invalid-expression "pkg/front_end/testcases/rasta/issue_000044.dart:27:15: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  print(const C.missingFactoryKeyword());
+              ^");
+  core::print(const self::C::constant());
+  core::print(new self::C::constant().{self::C::notEvenAConstructor}(null));
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000036.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000045.dart.legacy.expect
similarity index 100%
copy from pkg/front_end/testcases/rasta/issue_000036.dart.direct.expect
copy to pkg/front_end/testcases/rasta/issue_000045.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000045.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000045.dart.strong.expect
new file mode 100644
index 0000000..8540011
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000045.dart.strong.expect
@@ -0,0 +1,30 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/issue_000045.dart:5:18: Error: String starting with """ must end with """.
+// main() => """${1}
+//                  ^...
+//
+// pkg/front_end/testcases/rasta/issue_000045.dart:5:18: Error: Expected ';' after this.
+// main() => """${1}
+//                  ^...
+//
+// pkg/front_end/testcases/rasta/issue_000045.dart:6:1: Error: Unexpected token ''.
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000045.dart:5:18: Error: String starting with """ must end with """.
+// main() => """${1}
+//                  ^...
+//
+// pkg/front_end/testcases/rasta/issue_000045.dart:5:18: Error: Expected ';' after this.
+// main() => """${1}
+//                  ^...
+//
+// pkg/front_end/testcases/rasta/issue_000045.dart:6:1: Error: Unexpected token ''.
+
+library;
+import self as self;
+
+static method main() → dynamic
+  return "${1}
+";
diff --git a/pkg/front_end/testcases/rasta/issue_000045.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000045.dart.strong.transformed.expect
new file mode 100644
index 0000000..cfd867a
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000045.dart.strong.transformed.expect
@@ -0,0 +1,18 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000045.dart:5:18: Error: String starting with """ must end with """.
+// main() => """${1}
+//                  ^...
+//
+// pkg/front_end/testcases/rasta/issue_000045.dart:5:18: Error: Expected ';' after this.
+// main() => """${1}
+//                  ^...
+//
+// pkg/front_end/testcases/rasta/issue_000045.dart:6:1: Error: Unexpected token ''.
+
+library;
+import self as self;
+
+static method main() → dynamic
+  return "${1}
+";
diff --git a/pkg/front_end/testcases/rasta/issue_000046.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000046.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000046.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000046.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000046.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000046.dart.strong.expect
new file mode 100644
index 0000000..e707fd6
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000046.dart.strong.expect
@@ -0,0 +1,54 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/issue_000046.dart:6:13: Error: Expected '(' before this.
+//   C c = new Object)();
+//             ^^^^^^
+//
+// pkg/front_end/testcases/rasta/issue_000046.dart:6:19: Error: Expected ';' after this.
+//   C c = new Object)();
+//                   ^
+//
+// pkg/front_end/testcases/rasta/issue_000046.dart:6:19: Error: Expected a class member, but got ')'.
+//   C c = new Object)();
+//                   ^
+//
+// pkg/front_end/testcases/rasta/issue_000046.dart:6:20: Error: Expected an identifier, but got '('.
+//   C c = new Object)();
+//                    ^
+//
+// pkg/front_end/testcases/rasta/issue_000046.dart:6:13: Error: The constructor returns type 'dart.core::Object' that isn't of expected type '#lib1::C'.
+// Change the type of the object being constructed or the context in which it is used.
+//   C c = new Object)();
+//             ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000046.dart:6:13: Error: Expected '(' before this.
+//   C c = new Object)();
+//             ^^^^^^
+//
+// pkg/front_end/testcases/rasta/issue_000046.dart:6:19: Error: Expected ';' after this.
+//   C c = new Object)();
+//                   ^
+//
+// pkg/front_end/testcases/rasta/issue_000046.dart:6:19: Error: Expected a class member, but got ')'.
+//   C c = new Object)();
+//                   ^
+//
+// pkg/front_end/testcases/rasta/issue_000046.dart:6:20: Error: Expected an identifier, but got '('.
+//   C c = new Object)();
+//                    ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field self::C c = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/rasta/issue_000046.dart:6:13: Error: The constructor returns type 'dart.core::Object' that isn't of expected type '#lib1::C'.
+Change the type of the object being constructed or the context in which it is used.
+  C c = new Object)();
+            ^" in new core::Object::•();
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000046.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000046.dart.strong.transformed.expect
new file mode 100644
index 0000000..258d9de
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000046.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000046.dart:6:13: Error: Expected '(' before this.
+//   C c = new Object)();
+//             ^^^^^^
+//
+// pkg/front_end/testcases/rasta/issue_000046.dart:6:19: Error: Expected ';' after this.
+//   C c = new Object)();
+//                   ^
+//
+// pkg/front_end/testcases/rasta/issue_000046.dart:6:19: Error: Expected a class member, but got ')'.
+//   C c = new Object)();
+//                   ^
+//
+// pkg/front_end/testcases/rasta/issue_000046.dart:6:20: Error: Expected an identifier, but got '('.
+//   C c = new Object)();
+//                    ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field self::C c = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/rasta/issue_000046.dart:6:13: Error: The constructor returns type 'dart.core::Object' that isn't of expected type '#lib1::C'.
+Change the type of the object being constructed or the context in which it is used.
+  C c = new Object)();
+            ^" in new core::Object::•();
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000047.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000047.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000047.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000047.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000047.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000047.dart.strong.expect
new file mode 100644
index 0000000..0805396
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000047.dart.strong.expect
@@ -0,0 +1,18 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/issue_000047.dart:5:17: Error: Expected ')' before this.
+// typedef void T(C<C>);
+//                 ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000047.dart:5:17: Error: Expected ')' before this.
+// typedef void T(C<C>);
+//                 ^
+
+library;
+import self as self;
+
+typedef T = (dynamic) → void;
+static method main() → (dynamic) → void
+  return null;
diff --git a/pkg/front_end/testcases/rasta/issue_000047.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000047.dart.strong.transformed.expect
new file mode 100644
index 0000000..1209acc
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000047.dart.strong.transformed.expect
@@ -0,0 +1,12 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/issue_000047.dart:5:17: Error: Expected ')' before this.
+// typedef void T(C<C>);
+//                 ^
+
+library;
+import self as self;
+
+typedef T = (dynamic) → void;
+static method main() → (dynamic) → void
+  return null;
diff --git a/pkg/front_end/testcases/rasta/issue_000048.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000048.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000048.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000048.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000048.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000048.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000048.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000048.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000048.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000048.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/rasta/issue_000048.dart.direct.expect
copy to pkg/front_end/testcases/rasta/issue_000048.dart.strong.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000048.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000048.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/rasta/issue_000048.dart.direct.transformed.expect
copy to pkg/front_end/testcases/rasta/issue_000048.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000052.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000052.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000052.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000052.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000052.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000052.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000052.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000052.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000052.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000052.dart.strong.expect
new file mode 100644
index 0000000..8b500e6
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000052.dart.strong.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  function f() → core::Null {
+    core::print("hello");
+  }
+  f.call();
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000052.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000052.dart.strong.transformed.expect
new file mode 100644
index 0000000..8b500e6
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000052.dart.strong.transformed.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  function f() → core::Null {
+    core::print("hello");
+  }
+  f.call();
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000053.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000053.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000053.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000053.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000053.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000053.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000053.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000053.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000053.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000053.dart.strong.expect
new file mode 100644
index 0000000..c3a0237
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000053.dart.strong.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  operator ==(dynamic other) → core::bool
+    return throw "x";
+  method test() → dynamic {
+    super.{core::Object::==}(null);
+  }
+}
+static method main() → dynamic {
+  new self::C::•().{self::C::test}();
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000053.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000053.dart.strong.transformed.expect
new file mode 100644
index 0000000..c3a0237
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000053.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  operator ==(dynamic other) → core::bool
+    return throw "x";
+  method test() → dynamic {
+    super.{core::Object::==}(null);
+  }
+}
+static method main() → dynamic {
+  new self::C::•().{self::C::test}();
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000067.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000067.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000067.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000067.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000067.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000067.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000067.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000067.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000067.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000067.dart.strong.expect
new file mode 100644
index 0000000..b685cab
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000067.dart.strong.expect
@@ -0,0 +1,35 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+class A extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::A::foo];
+  constructor •() → self::A
+    : super core::Object::•() {}
+  static factory foo() → self::A
+    let dynamic #redirecting_factory = self::C::bar in invalid-expression;
+  method m() → core::int {}
+}
+class C extends self::A {
+  static field dynamic _redirecting# = <dynamic>[self::C::bar];
+  constructor •() → self::C
+    : super self::A::•() {}
+  static factory bar() → self::C
+    let dynamic #redirecting_factory = self::D::• in invalid-expression;
+  method m() → core::int {
+    return 1;
+  }
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+  method m() → core::int {
+    return 2;
+  }
+}
+static method main() → dynamic {
+  self::A a = new self::D::•();
+  exp::Expect::equals(2, a.{self::A::m}());
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000067.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000067.dart.strong.transformed.expect
new file mode 100644
index 0000000..5d95998
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000067.dart.strong.transformed.expect
@@ -0,0 +1,35 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+class A extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::A::foo];
+  constructor •() → self::A
+    : super core::Object::•() {}
+  static factory foo() → self::A
+    let () → self::C #redirecting_factory = self::C::bar in invalid-expression;
+  method m() → core::int {}
+}
+class C extends self::A {
+  static field dynamic _redirecting# = <dynamic>[self::C::bar];
+  constructor •() → self::C
+    : super self::A::•() {}
+  static factory bar() → self::C
+    let<BottomType> #redirecting_factory = self::D::• in invalid-expression;
+  method m() → core::int {
+    return 1;
+  }
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+  method m() → core::int {
+    return 2;
+  }
+}
+static method main() → dynamic {
+  self::A a = new self::D::•();
+  exp::Expect::equals(2, a.{self::A::m}());
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000068.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000068.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000068.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000068.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000068.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000068.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000068.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000068.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000068.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000068.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/rasta/issue_000068.dart.direct.expect
copy to pkg/front_end/testcases/rasta/issue_000068.dart.strong.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000068.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000068.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/rasta/issue_000068.dart.direct.transformed.expect
copy to pkg/front_end/testcases/rasta/issue_000068.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000069.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000069.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000069.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000069.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000069.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000069.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000069.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000069.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000069.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000069.dart.strong.expect
new file mode 100644
index 0000000..ec1feb2
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000069.dart.strong.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  dynamic x;
+  core::int i = 0;
+  while ((let final core::int #t1 = i in let final core::int #t2 = i = #t1.{core::num::+}(1) in #t1).{core::num::<}(5)) {
+    core::int x = i;
+  }
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000069.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000069.dart.strong.transformed.expect
new file mode 100644
index 0000000..ec1feb2
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000069.dart.strong.transformed.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  dynamic x;
+  core::int i = 0;
+  while ((let final core::int #t1 = i in let final core::int #t2 = i = #t1.{core::num::+}(1) in #t1).{core::num::<}(5)) {
+    core::int x = i;
+  }
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000069.dart.type_promotion.expect b/pkg/front_end/testcases/rasta/issue_000069.dart.type_promotion.expect
new file mode 100644
index 0000000..f2b5d7c
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000069.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/rasta/issue_000069.dart:7:11: Context: Write to i@237
+  while (i++ < 5) var x = i;
+          ^^
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000070.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000070.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000070.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000070.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect
new file mode 100644
index 0000000..0f3241e
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect
@@ -0,0 +1,43 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+class A<N extends core::Object = dynamic, S extends core::Object = dynamic, U extends core::Object = dynamic> extends core::Object {
+  final field core::List<self::A::U> field;
+  constructor •(self::A::N n, self::A::S s) → self::A<self::A::N, self::A::S, self::A::U>
+    : self::A::field = core::List::•<self::A::U>(), super core::Object::•() {
+    exp::Expect::isTrue(n is self::A::N);
+    exp::Expect::isTrue(s is self::A::S);
+  }
+  constructor empty() → self::A<self::A::N, self::A::S, self::A::U>
+    : self::A::field = null, super core::Object::•() {}
+  const constructor c(self::A::U u, self::A::S s) → self::A<self::A::N, self::A::S, self::A::U>
+    : self::A::field = const <core::Null>[null], super core::Object::•()
+    ;
+  static factory f<N extends core::Object = dynamic, S extends core::Object = dynamic, U extends core::Object = dynamic>(self::A::f::S s) → self::A<self::A::f::N, self::A::f::S, self::A::f::U> {
+    exp::Expect::isTrue(s is self::A::f::S);
+    return new self::A::empty<self::A::f::N, self::A::f::S, self::A::f::U>();
+  }
+  get getter() → core::List<self::A::U> {
+    return this.{self::A::field};
+  }
+  set setter(generic-covariant-impl self::A::S s) → void {}
+}
+abstract class J<Aa extends core::Object = dynamic, B extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::J<self::J::Aa, self::J::B>
+    : super core::Object::•()
+    ;
+}
+abstract class I<H extends core::Object = dynamic, C extends core::Object = dynamic, K extends core::Object = dynamic> extends self::J<self::I::C, self::I::K> {
+  synthetic constructor •() → self::I<self::I::H, self::I::C, self::I::K>
+    : super self::J::•()
+    ;
+}
+static method main() → dynamic {
+  new self::A::•<core::num, core::double, core::List<dynamic>>(1, 2.0);
+  self::A<dynamic, dynamic, dynamic> a = self::A::f<core::int, core::int, core::int>(1);
+  const self::A::c<core::int, core::int, core::List<dynamic>>(const <dynamic>[], 1);
+  core::List<dynamic> z = a.{self::A::getter};
+  a.{self::A::setter} = 1;
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect
new file mode 100644
index 0000000..1fd973c
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect
@@ -0,0 +1,43 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+class A<N extends core::Object = dynamic, S extends core::Object = dynamic, U extends core::Object = dynamic> extends core::Object {
+  final field core::List<self::A::U> field;
+  constructor •(self::A::N n, self::A::S s) → self::A<self::A::N, self::A::S, self::A::U>
+    : self::A::field = core::_GrowableList::•<self::A::U>(0), super core::Object::•() {
+    exp::Expect::isTrue(n is self::A::N);
+    exp::Expect::isTrue(s is self::A::S);
+  }
+  constructor empty() → self::A<self::A::N, self::A::S, self::A::U>
+    : self::A::field = null, super core::Object::•() {}
+  const constructor c(self::A::U u, self::A::S s) → self::A<self::A::N, self::A::S, self::A::U>
+    : self::A::field = const <core::Null>[null], super core::Object::•()
+    ;
+  static factory f<N extends core::Object = dynamic, S extends core::Object = dynamic, U extends core::Object = dynamic>(self::A::f::S s) → self::A<self::A::f::N, self::A::f::S, self::A::f::U> {
+    exp::Expect::isTrue(s is self::A::f::S);
+    return new self::A::empty<self::A::f::N, self::A::f::S, self::A::f::U>();
+  }
+  get getter() → core::List<self::A::U> {
+    return this.{self::A::field};
+  }
+  set setter(generic-covariant-impl self::A::S s) → void {}
+}
+abstract class J<Aa extends core::Object = dynamic, B extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::J<self::J::Aa, self::J::B>
+    : super core::Object::•()
+    ;
+}
+abstract class I<H extends core::Object = dynamic, C extends core::Object = dynamic, K extends core::Object = dynamic> extends self::J<self::I::C, self::I::K> {
+  synthetic constructor •() → self::I<self::I::H, self::I::C, self::I::K>
+    : super self::J::•()
+    ;
+}
+static method main() → dynamic {
+  new self::A::•<core::num, core::double, core::List<dynamic>>(1, 2.0);
+  self::A<dynamic, dynamic, dynamic> a = self::A::f<core::int, core::int, core::int>(1);
+  const self::A::c<core::int, core::int, core::List<dynamic>>(const <dynamic>[], 1);
+  core::List<dynamic> z = a.{self::A::getter};
+  a.{self::A::setter} = 1;
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.type_promotion.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.type_promotion.expect
new file mode 100644
index 0000000..27f599e
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000070.dart.type_promotion.expect
@@ -0,0 +1,9 @@
+pkg/front_end/testcases/rasta/issue_000070.dart:11:21: Context: Possible promotion of n@306
+    Expect.isTrue(n is N);
+                    ^^
+pkg/front_end/testcases/rasta/issue_000070.dart:12:21: Context: Possible promotion of s@311
+    Expect.isTrue(s is S);
+                    ^^
+pkg/front_end/testcases/rasta/issue_000070.dart:18:21: Context: Possible promotion of s@311
+    Expect.isTrue(s is S);
+                    ^^
diff --git a/pkg/front_end/testcases/rasta/issue_000080.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000080.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000080.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000080.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000080.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/issue_000080.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000080.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/issue_000080.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000081.dart.direct.expect b/pkg/front_end/testcases/rasta/issue_000081.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/issue_000081.dart.direct.expect
rename to pkg/front_end/testcases/rasta/issue_000081.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/issue_000081.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000081.dart.strong.expect
new file mode 100644
index 0000000..eb53a96
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000081.dart.strong.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Base extends core::Object {
+  field core::int hashCode = 42;
+  synthetic constructor •() → self::Base
+    : super core::Object::•()
+    ;
+}
+class Sub extends self::Base {
+  field core::int _hashCode = null;
+  synthetic constructor •() → self::Sub
+    : super self::Base::•()
+    ;
+  get hashCode() → core::int
+    return let final core::int #t1 = this.{self::Sub::_hashCode} in #t1.{core::num::==}(null) ?{core::int} this.{self::Sub::_hashCode} = super.{self::Base::hashCode} : #t1;
+  method foo() → dynamic {
+    this.{self::Sub::_hashCode}.{core::num::==}(null) ?{core::int} this.{self::Sub::_hashCode} = super.{self::Base::hashCode} : null;
+  }
+}
+static method main() → dynamic {
+  core::print(new self::Sub::•().{self::Sub::hashCode});
+  core::List<core::Null> l = <core::Null>[null];
+  let final core::List<core::Null> #t2 = l in let final core::int #t3 = 0 in #t2.{core::List::[]}(#t3).{core::Object::==}(null) ?{core::String} let final core::String #t4 = "fisk" as{TypeError} core::Null in let final void #t5 = #t2.{core::List::[]=}(#t3, #t4) in #t4 : null;
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect
new file mode 100644
index 0000000..eb53a96
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Base extends core::Object {
+  field core::int hashCode = 42;
+  synthetic constructor •() → self::Base
+    : super core::Object::•()
+    ;
+}
+class Sub extends self::Base {
+  field core::int _hashCode = null;
+  synthetic constructor •() → self::Sub
+    : super self::Base::•()
+    ;
+  get hashCode() → core::int
+    return let final core::int #t1 = this.{self::Sub::_hashCode} in #t1.{core::num::==}(null) ?{core::int} this.{self::Sub::_hashCode} = super.{self::Base::hashCode} : #t1;
+  method foo() → dynamic {
+    this.{self::Sub::_hashCode}.{core::num::==}(null) ?{core::int} this.{self::Sub::_hashCode} = super.{self::Base::hashCode} : null;
+  }
+}
+static method main() → dynamic {
+  core::print(new self::Sub::•().{self::Sub::hashCode});
+  core::List<core::Null> l = <core::Null>[null];
+  let final core::List<core::Null> #t2 = l in let final core::int #t3 = 0 in #t2.{core::List::[]}(#t3).{core::Object::==}(null) ?{core::String} let final core::String #t4 = "fisk" as{TypeError} core::Null in let final void #t5 = #t2.{core::List::[]=}(#t3, #t4) in #t4 : null;
+}
diff --git a/pkg/front_end/testcases/rasta/malformed_const_constructor.dart.direct.expect b/pkg/front_end/testcases/rasta/malformed_const_constructor.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/malformed_const_constructor.dart.direct.expect
rename to pkg/front_end/testcases/rasta/malformed_const_constructor.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/malformed_const_constructor.dart.strong.expect b/pkg/front_end/testcases/rasta/malformed_const_constructor.dart.strong.expect
new file mode 100644
index 0000000..28a0ed7
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/malformed_const_constructor.dart.strong.expect
@@ -0,0 +1,61 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/malformed_const_constructor.dart:8:5: Error: Expected '{' before this.
+//     : x = 'foo'
+//     ^
+//
+// pkg/front_end/testcases/rasta/malformed_const_constructor.dart:6:3: Error: A const constructor can't have a body.
+// Try removing either the 'const' keyword or the body.
+//   const A()
+//   ^^^^^
+//
+// pkg/front_end/testcases/rasta/malformed_const_constructor.dart:8:5: Error: Expected a class member, but got ':'.
+//     : x = 'foo'
+//     ^
+//
+// pkg/front_end/testcases/rasta/malformed_const_constructor.dart:8:7: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+//     : x = 'foo'
+//       ^
+//
+// pkg/front_end/testcases/rasta/malformed_const_constructor.dart:13:9: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const A();
+//         ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/malformed_const_constructor.dart:8:5: Error: Expected '{' before this.
+//     : x = 'foo'
+//     ^
+//
+// pkg/front_end/testcases/rasta/malformed_const_constructor.dart:6:3: Error: A const constructor can't have a body.
+// Try removing either the 'const' keyword or the body.
+//   const A()
+//   ^^^^^
+//
+// pkg/front_end/testcases/rasta/malformed_const_constructor.dart:8:5: Error: Expected a class member, but got ':'.
+//     : x = 'foo'
+//     ^
+//
+// pkg/front_end/testcases/rasta/malformed_const_constructor.dart:8:7: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+//     : x = 'foo'
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::String x = "foo";
+  constructor •() → self::A
+    : self::A::x = "foo", super core::Object::•() {}
+}
+static method main() → dynamic {
+  invalid-expression "pkg/front_end/testcases/rasta/malformed_const_constructor.dart:13:9: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const A();
+        ^";
+  new self::A::•();
+}
diff --git a/pkg/front_end/testcases/rasta/malformed_const_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/malformed_const_constructor.dart.strong.transformed.expect
new file mode 100644
index 0000000..58f81f6
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/malformed_const_constructor.dart.strong.transformed.expect
@@ -0,0 +1,36 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/malformed_const_constructor.dart:8:5: Error: Expected '{' before this.
+//     : x = 'foo'
+//     ^
+//
+// pkg/front_end/testcases/rasta/malformed_const_constructor.dart:6:3: Error: A const constructor can't have a body.
+// Try removing either the 'const' keyword or the body.
+//   const A()
+//   ^^^^^
+//
+// pkg/front_end/testcases/rasta/malformed_const_constructor.dart:8:5: Error: Expected a class member, but got ':'.
+//     : x = 'foo'
+//     ^
+//
+// pkg/front_end/testcases/rasta/malformed_const_constructor.dart:8:7: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+//     : x = 'foo'
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::String x = "foo";
+  constructor •() → self::A
+    : self::A::x = "foo", super core::Object::•() {}
+}
+static method main() → dynamic {
+  invalid-expression "pkg/front_end/testcases/rasta/malformed_const_constructor.dart:13:9: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const A();
+        ^";
+  new self::A::•();
+}
diff --git a/pkg/front_end/testcases/rasta/malformed_function.dart.direct.expect b/pkg/front_end/testcases/rasta/malformed_function.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/malformed_function.dart.direct.expect
rename to pkg/front_end/testcases/rasta/malformed_function.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/malformed_function.dart.strong.expect b/pkg/front_end/testcases/rasta/malformed_function.dart.strong.expect
new file mode 100644
index 0000000..f964b8b
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/malformed_function.dart.strong.expect
@@ -0,0 +1,14 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/malformed_function.dart:7:8: Error: Can't assign to a parenthesized expression.
+//   (null) = null;
+//        ^
+
+library;
+import self as self;
+
+static method main() → dynamic {
+  invalid-expression "pkg/front_end/testcases/rasta/malformed_function.dart:7:8: Error: Can't assign to a parenthesized expression.
+  (null) = null;
+       ^";
+}
diff --git a/pkg/front_end/testcases/rasta/malformed_function.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/malformed_function.dart.strong.transformed.expect
new file mode 100644
index 0000000..caf6bf2
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/malformed_function.dart.strong.transformed.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+
+static method main() → dynamic {
+  invalid-expression "pkg/front_end/testcases/rasta/malformed_function.dart:7:8: Error: Can't assign to a parenthesized expression.
+  (null) = null;
+       ^";
+}
diff --git a/pkg/front_end/testcases/rasta/malformed_function_type.dart.direct.expect b/pkg/front_end/testcases/rasta/malformed_function_type.dart.legacy.expect
similarity index 85%
rename from pkg/front_end/testcases/rasta/malformed_function_type.dart.direct.expect
rename to pkg/front_end/testcases/rasta/malformed_function_type.dart.legacy.expect
index fe2d820..ffb842a 100644
--- a/pkg/front_end/testcases/rasta/malformed_function_type.dart.direct.expect
+++ b/pkg/front_end/testcases/rasta/malformed_function_type.dart.legacy.expect
@@ -14,7 +14,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Handle = (core::String) → dynamic;
+typedef Handle = (core::String) → invalid-type;
 static method main() → dynamic {
-  (core::String) → dynamic h;
+  (core::String) → invalid-type h;
 }
diff --git a/pkg/front_end/testcases/rasta/malformed_function_type.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/malformed_function_type.dart.legacy.transformed.expect
similarity index 77%
rename from pkg/front_end/testcases/rasta/malformed_function_type.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/malformed_function_type.dart.legacy.transformed.expect
index 88fea44..a51b1d7 100644
--- a/pkg/front_end/testcases/rasta/malformed_function_type.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/rasta/malformed_function_type.dart.legacy.transformed.expect
@@ -8,7 +8,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Handle = (core::String) → dynamic;
+typedef Handle = (core::String) → invalid-type;
 static method main() → dynamic {
-  (core::String) → dynamic h;
+  (core::String) → invalid-type h;
 }
diff --git a/pkg/front_end/testcases/rasta/malformed_function_type.dart.outline.expect b/pkg/front_end/testcases/rasta/malformed_function_type.dart.outline.expect
index 2cff7f8..6591886 100644
--- a/pkg/front_end/testcases/rasta/malformed_function_type.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/malformed_function_type.dart.outline.expect
@@ -8,6 +8,6 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Handle = (core::String) → dynamic;
+typedef Handle = (core::String) → invalid-type;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/rasta/malformed_function_type.dart.direct.expect b/pkg/front_end/testcases/rasta/malformed_function_type.dart.strong.expect
similarity index 85%
copy from pkg/front_end/testcases/rasta/malformed_function_type.dart.direct.expect
copy to pkg/front_end/testcases/rasta/malformed_function_type.dart.strong.expect
index fe2d820..ffb842a 100644
--- a/pkg/front_end/testcases/rasta/malformed_function_type.dart.direct.expect
+++ b/pkg/front_end/testcases/rasta/malformed_function_type.dart.strong.expect
@@ -14,7 +14,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Handle = (core::String) → dynamic;
+typedef Handle = (core::String) → invalid-type;
 static method main() → dynamic {
-  (core::String) → dynamic h;
+  (core::String) → invalid-type h;
 }
diff --git a/pkg/front_end/testcases/rasta/malformed_function_type.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/malformed_function_type.dart.strong.transformed.expect
similarity index 77%
copy from pkg/front_end/testcases/rasta/malformed_function_type.dart.direct.transformed.expect
copy to pkg/front_end/testcases/rasta/malformed_function_type.dart.strong.transformed.expect
index 88fea44..a51b1d7 100644
--- a/pkg/front_end/testcases/rasta/malformed_function_type.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/rasta/malformed_function_type.dart.strong.transformed.expect
@@ -8,7 +8,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Handle = (core::String) → dynamic;
+typedef Handle = (core::String) → invalid-type;
 static method main() → dynamic {
-  (core::String) → dynamic h;
+  (core::String) → invalid-type h;
 }
diff --git a/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.direct.expect b/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.direct.expect
rename to pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.expect b/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.expect
new file mode 100644
index 0000000..bc30315
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.expect
@@ -0,0 +1,24 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:16: Error: Non-optional parameters can't have a default value.
+// Try removing the default value or making the parameter optional.
+// main(arguments = [x]) {
+//                ^
+//
+// pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:19: Error: Getter not found: 'x'.
+// main(arguments = [x]) {
+//                   ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:16: Error: Non-optional parameters can't have a default value.
+// Try removing the default value or making the parameter optional.
+// main(arguments = [x]) {
+//                ^
+
+library;
+import self as self;
+
+static method main(dynamic arguments = <dynamic>[let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:19: Error: Getter not found: 'x'.
+main(arguments = [x]) {
+                  ^"]) → dynamic {}
diff --git a/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..e6dd04e
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.transformed.expect
@@ -0,0 +1,13 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:16: Error: Non-optional parameters can't have a default value.
+// Try removing the default value or making the parameter optional.
+// main(arguments = [x]) {
+//                ^
+
+library;
+import self as self;
+
+static method main(dynamic arguments = <dynamic>[let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:19: Error: Getter not found: 'x'.
+main(arguments = [x]) {
+                  ^"]) → dynamic {}
diff --git a/pkg/front_end/testcases/rasta/mixin_library.dart.direct.expect b/pkg/front_end/testcases/rasta/mixin_library.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/mixin_library.dart.direct.expect
rename to pkg/front_end/testcases/rasta/mixin_library.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.direct.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/native_is_illegal.dart.direct.expect
rename to pkg/front_end/testcases/rasta/native_is_illegal.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.strong.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.strong.expect
new file mode 100644
index 0000000..12904aa
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.strong.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Bar extends core::Object {
+  @_in::ExternalName::•("Bar_get_x")
+  external get x() → self::Bar;
+  @_in::ExternalName::•("Bar_set_x")
+  external set x(self::Bar value) → void;
+  @_in::ExternalName::•("Bar_f")
+  external method f() → dynamic;
+  @_in::ExternalName::•("Bar_constructor")
+  external static factory •() → self::Bar;
+}
+@_in::ExternalName::•("foo")
+external static method foo() → dynamic;
diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.strong.transformed.expect
new file mode 100644
index 0000000..12904aa
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Bar extends core::Object {
+  @_in::ExternalName::•("Bar_get_x")
+  external get x() → self::Bar;
+  @_in::ExternalName::•("Bar_set_x")
+  external set x(self::Bar value) → void;
+  @_in::ExternalName::•("Bar_f")
+  external method f() → dynamic;
+  @_in::ExternalName::•("Bar_constructor")
+  external static factory •() → self::Bar;
+}
+@_in::ExternalName::•("foo")
+external static method foo() → dynamic;
diff --git a/pkg/front_end/testcases/rasta/parser_error.dart.direct.expect b/pkg/front_end/testcases/rasta/parser_error.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/parser_error.dart.direct.expect
rename to pkg/front_end/testcases/rasta/parser_error.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/parser_error.dart.strong.expect b/pkg/front_end/testcases/rasta/parser_error.dart.strong.expect
new file mode 100644
index 0000000..9b575d7
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/parser_error.dart.strong.expect
@@ -0,0 +1,45 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/parser_error.dart:10:7: Error: Expected an identifier, but got '?'.
+//   if (?b) return b;  /// 01: compile-time error
+//       ^
+//
+// pkg/front_end/testcases/rasta/parser_error.dart:10:9: Error: Expected ':' before this.
+//   if (?b) return b;  /// 01: compile-time error
+//         ^
+//
+// pkg/front_end/testcases/rasta/parser_error.dart:10:9: Error: Expected an identifier, but got ')'.
+//   if (?b) return b;  /// 01: compile-time error
+//         ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/parser_error.dart:10:7: Error: Expected an identifier, but got '?'.
+//   if (?b) return b;  /// 01: compile-time error
+//       ^
+//
+// pkg/front_end/testcases/rasta/parser_error.dart:10:9: Error: Expected ':' before this.
+//   if (?b) return b;  /// 01: compile-time error
+//         ^
+//
+// pkg/front_end/testcases/rasta/parser_error.dart:10:9: Error: Expected an identifier, but got ')'.
+//   if (?b) return b;  /// 01: compile-time error
+//         ^
+
+library;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+static method test(dynamic a, {dynamic b = null, dynamic c = null}) → core::int {
+  if((invalid-expression "pkg/front_end/testcases/rasta/parser_error.dart:10:7: Error: This couldn't be parsed.
+  if (?b) return b;  /// 01: compile-time error
+      ^" as{TypeError} core::bool ?{dynamic} b : invalid-expression "pkg/front_end/testcases/rasta/parser_error.dart:10:9: Error: This couldn't be parsed.
+  if (?b) return b;  /// 01: compile-time error
+        ^") as{TypeError} core::bool)
+    return b as{TypeError} core::int;
+  return a.+(b).+(c) as{TypeError} core::int;
+}
+static method main() → dynamic {
+  exp::Expect::equals(6, self::test(1, b: 2, c: 3));
+}
diff --git a/pkg/front_end/testcases/rasta/parser_error.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/parser_error.dart.strong.transformed.expect
new file mode 100644
index 0000000..1e72f8b
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/parser_error.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/parser_error.dart:10:7: Error: Expected an identifier, but got '?'.
+//   if (?b) return b;  /// 01: compile-time error
+//       ^
+//
+// pkg/front_end/testcases/rasta/parser_error.dart:10:9: Error: Expected ':' before this.
+//   if (?b) return b;  /// 01: compile-time error
+//         ^
+//
+// pkg/front_end/testcases/rasta/parser_error.dart:10:9: Error: Expected an identifier, but got ')'.
+//   if (?b) return b;  /// 01: compile-time error
+//         ^
+
+library;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+static method test(dynamic a, {dynamic b = null, dynamic c = null}) → core::int {
+  if((invalid-expression "pkg/front_end/testcases/rasta/parser_error.dart:10:7: Error: This couldn't be parsed.
+  if (?b) return b;  /// 01: compile-time error
+      ^" as{TypeError} core::bool ?{dynamic} b : invalid-expression "pkg/front_end/testcases/rasta/parser_error.dart:10:9: Error: This couldn't be parsed.
+  if (?b) return b;  /// 01: compile-time error
+        ^") as{TypeError} core::bool)
+    return b as{TypeError} core::int;
+  return a.+(b).+(c) as{TypeError} core::int;
+}
+static method main() → dynamic {
+  exp::Expect::equals(6, self::test(1, b: 2, c: 3));
+}
diff --git a/pkg/front_end/testcases/rasta/previsit_deferred.dart.direct.expect b/pkg/front_end/testcases/rasta/previsit_deferred.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/previsit_deferred.dart.direct.expect
rename to pkg/front_end/testcases/rasta/previsit_deferred.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/previsit_deferred.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/previsit_deferred.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/previsit_deferred.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/previsit_deferred.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/static.dart.direct.expect b/pkg/front_end/testcases/rasta/static.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/static.dart.direct.expect
rename to pkg/front_end/testcases/rasta/static.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/static.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/static.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/static.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/static.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/static.dart.strong.expect b/pkg/front_end/testcases/rasta/static.dart.strong.expect
new file mode 100644
index 0000000..994cfbb
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/static.dart.strong.expect
@@ -0,0 +1,343 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/static.dart:28:9: Error: Getter not found: 'staticSetter'.
+//     Foo.staticSetter;
+//         ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:29:13: Error: Getter not found: 'staticSetter'.
+//     use(Foo.staticSetter);
+//             ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:31:9: Error: Setter not found: 'staticConstant'.
+//     Foo.staticConstant++;
+//         ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:32:13: Error: Setter not found: 'staticConstant'.
+//     use(Foo.staticConstant++);
+//             ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:35:9: Error: Setter not found: 'staticFunction'.
+//     Foo.staticFunction++;
+//         ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:36:13: Error: Setter not found: 'staticFunction'.
+//     use(Foo.staticFunction++);
+//             ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:37:9: Error: Setter not found: 'staticGetter'.
+//     Foo.staticGetter++;
+//         ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:38:13: Error: Setter not found: 'staticGetter'.
+//     use(Foo.staticGetter++);
+//             ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:39:9: Error: Getter not found: 'staticSetter'.
+//     Foo.staticSetter++;
+//         ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:40:13: Error: Getter not found: 'staticSetter'.
+//     use(Foo.staticSetter++);
+//             ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:42:11: Error: Setter not found: 'staticConstant'.
+//     ++Foo.staticConstant;
+//           ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:43:15: Error: Setter not found: 'staticConstant'.
+//     use(++Foo.staticConstant);
+//               ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:46:11: Error: Setter not found: 'staticFunction'.
+//     ++Foo.staticFunction;
+//           ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:47:15: Error: Setter not found: 'staticFunction'.
+//     use(++Foo.staticFunction);
+//               ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:48:11: Error: Setter not found: 'staticGetter'.
+//     ++Foo.staticGetter;
+//           ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:49:15: Error: Setter not found: 'staticGetter'.
+//     use(++Foo.staticGetter);
+//               ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:50:11: Error: Getter not found: 'staticSetter'.
+//     ++Foo.staticSetter;
+//           ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:51:15: Error: Getter not found: 'staticSetter'.
+//     use(++Foo.staticSetter);
+//               ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:61:9: Error: Getter not found: 'staticSetter'.
+//     Foo.staticSetter();
+//         ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:62:13: Error: Getter not found: 'staticSetter'.
+//     use(Foo.staticSetter());
+//             ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:64:9: Error: Setter not found: 'staticConstant'.
+//     Foo.staticConstant = 87;
+//         ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:65:13: Error: Setter not found: 'staticConstant'.
+//     use(Foo.staticConstant = 87);
+//             ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:68:9: Error: Setter not found: 'staticFunction'.
+//     Foo.staticFunction = 87;
+//         ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:69:13: Error: Setter not found: 'staticFunction'.
+//     use(Foo.staticFunction = 87);
+//             ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:70:9: Error: Setter not found: 'staticGetter'.
+//     Foo.staticGetter = 87;
+//         ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:71:13: Error: Setter not found: 'staticGetter'.
+//     use(Foo.staticGetter = 87);
+//             ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:75:9: Error: Setter not found: 'staticConstant'.
+//     Foo.staticConstant ??= 87;
+//         ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:76:13: Error: Setter not found: 'staticConstant'.
+//     use(Foo.staticConstant ??= 87);
+//             ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:79:9: Error: Setter not found: 'staticFunction'.
+//     Foo.staticFunction ??= 87;
+//         ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:80:13: Error: Setter not found: 'staticFunction'.
+//     use(Foo.staticFunction ??= 87);
+//             ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:81:9: Error: Setter not found: 'staticGetter'.
+//     Foo.staticGetter ??= 87;
+//         ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:82:13: Error: Setter not found: 'staticGetter'.
+//     use(Foo.staticGetter ??= 87);
+//             ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:83:9: Error: Getter not found: 'staticSetter'.
+//     Foo.staticSetter ??= 87;
+//         ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:84:13: Error: Getter not found: 'staticSetter'.
+//     use(Foo.staticSetter ??= 87);
+//             ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/static.dart:35:23: Error: The method '+' isn't defined for the class '() → dynamic'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     Foo.staticFunction++;
+//                       ^
+//
+// pkg/front_end/testcases/rasta/static.dart:36:27: Error: The method '+' isn't defined for the class '() → dynamic'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     use(Foo.staticFunction++);
+//                           ^
+//
+// pkg/front_end/testcases/rasta/static.dart:46:5: Error: The method '+' isn't defined for the class '() → dynamic'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     ++Foo.staticFunction;
+//     ^
+//
+// pkg/front_end/testcases/rasta/static.dart:47:9: Error: The method '+' isn't defined for the class '() → dynamic'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     use(++Foo.staticFunction);
+//         ^
+//
+// pkg/front_end/testcases/rasta/static.dart:53:23: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+// Try correcting the name to the name of an existing method, or defining a method named 'call'.
+//     Foo.staticConstant();
+//                       ^
+//
+// pkg/front_end/testcases/rasta/static.dart:54:27: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+// Try correcting the name to the name of an existing method, or defining a method named 'call'.
+//     use(Foo.staticConstant());
+//                           ^
+//
+// pkg/front_end/testcases/rasta/static.dart:55:20: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+// Try correcting the name to the name of an existing method, or defining a method named 'call'.
+//     Foo.staticField();
+//                    ^
+//
+// pkg/front_end/testcases/rasta/static.dart:56:24: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+// Try correcting the name to the name of an existing method, or defining a method named 'call'.
+//     use(Foo.staticField());
+//                        ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  static const field core::int staticConstant = 42;
+  static field core::int staticField = 42;
+  synthetic constructor •() → self::Foo
+    : super core::Object::•()
+    ;
+  static method staticFunction() → dynamic {}
+  static get staticGetter() → dynamic
+    return null;
+  static set staticSetter(dynamic _) → void {}
+}
+static method use(dynamic x) → dynamic {
+  if(x.{core::Object::==}(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}))
+    throw "Shouldn't happen";
+}
+static method main() → dynamic {
+  try {
+    self::Foo::staticConstant;
+    self::use(self::Foo::staticConstant);
+    self::Foo::staticField;
+    self::use(self::Foo::staticField);
+    self::Foo::staticFunction;
+    self::use(self::Foo::staticFunction);
+    self::Foo::staticGetter;
+    self::use(self::Foo::staticGetter);
+    invalid-expression "pkg/front_end/testcases/rasta/static.dart:28:9: Error: Getter not found: 'staticSetter'.
+    Foo.staticSetter;
+        ^^^^^^^^^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/static.dart:29:13: Error: Getter not found: 'staticSetter'.
+    use(Foo.staticSetter);
+            ^^^^^^^^^^^^");
+    let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:31:9: Error: Setter not found: 'staticConstant'.
+    Foo.staticConstant++;
+        ^^^^^^^^^^^^^^";
+    self::use(let final core::int #t1 = self::Foo::staticConstant in let final core::int #t2 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:32:13: Error: Setter not found: 'staticConstant'.
+    use(Foo.staticConstant++);
+            ^^^^^^^^^^^^^^" in #t1);
+    self::Foo::staticField = self::Foo::staticField.{core::num::+}(1);
+    self::use(let final core::int #t3 = self::Foo::staticField in let final core::int #t4 = self::Foo::staticField = #t3.{core::num::+}(1) in #t3);
+    let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:35:9: Error: Setter not found: 'staticFunction'.
+    Foo.staticFunction++;
+        ^^^^^^^^^^^^^^";
+    self::use(let final () → dynamic #t5 = self::Foo::staticFunction in let final dynamic #t6 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:36:13: Error: Setter not found: 'staticFunction'.
+    use(Foo.staticFunction++);
+            ^^^^^^^^^^^^^^" in #t5);
+    let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:37:9: Error: Setter not found: 'staticGetter'.
+    Foo.staticGetter++;
+        ^^^^^^^^^^^^";
+    self::use(let final dynamic #t7 = self::Foo::staticGetter in let final dynamic #t8 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:38:13: Error: Setter not found: 'staticGetter'.
+    use(Foo.staticGetter++);
+            ^^^^^^^^^^^^" in #t7);
+    self::Foo::staticSetter = (let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:39:9: Error: Getter not found: 'staticSetter'.
+    Foo.staticSetter++;
+        ^^^^^^^^^^^^").+(1);
+    self::use(let final dynamic #t9 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:40:13: Error: Getter not found: 'staticSetter'.
+    use(Foo.staticSetter++);
+            ^^^^^^^^^^^^" in let final dynamic #t10 = self::Foo::staticSetter = #t9.+(1) in #t9);
+    let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:42:11: Error: Setter not found: 'staticConstant'.
+    ++Foo.staticConstant;
+          ^^^^^^^^^^^^^^";
+    self::use(let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:43:15: Error: Setter not found: 'staticConstant'.
+    use(++Foo.staticConstant);
+              ^^^^^^^^^^^^^^");
+    self::Foo::staticField = self::Foo::staticField.{core::num::+}(1);
+    self::use(self::Foo::staticField = self::Foo::staticField.{core::num::+}(1));
+    let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:46:11: Error: Setter not found: 'staticFunction'.
+    ++Foo.staticFunction;
+          ^^^^^^^^^^^^^^";
+    self::use(let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:47:15: Error: Setter not found: 'staticFunction'.
+    use(++Foo.staticFunction);
+              ^^^^^^^^^^^^^^");
+    let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:48:11: Error: Setter not found: 'staticGetter'.
+    ++Foo.staticGetter;
+          ^^^^^^^^^^^^";
+    self::use(let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:49:15: Error: Setter not found: 'staticGetter'.
+    use(++Foo.staticGetter);
+              ^^^^^^^^^^^^");
+    self::Foo::staticSetter = (let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:50:11: Error: Getter not found: 'staticSetter'.
+    ++Foo.staticSetter;
+          ^^^^^^^^^^^^").+(1);
+    self::use(self::Foo::staticSetter = (let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:51:15: Error: Getter not found: 'staticSetter'.
+    use(++Foo.staticSetter);
+              ^^^^^^^^^^^^").+(1));
+    let final dynamic #t11 = self::Foo::staticConstant in invalid-expression "pkg/front_end/testcases/rasta/static.dart:53:23: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing method, or defining a method named 'call'.
+    Foo.staticConstant();
+                      ^";
+    self::use(let final dynamic #t12 = self::Foo::staticConstant in invalid-expression "pkg/front_end/testcases/rasta/static.dart:54:27: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing method, or defining a method named 'call'.
+    use(Foo.staticConstant());
+                          ^");
+    let final dynamic #t13 = self::Foo::staticField in invalid-expression "pkg/front_end/testcases/rasta/static.dart:55:20: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing method, or defining a method named 'call'.
+    Foo.staticField();
+                   ^";
+    self::use(let final dynamic #t14 = self::Foo::staticField in invalid-expression "pkg/front_end/testcases/rasta/static.dart:56:24: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing method, or defining a method named 'call'.
+    use(Foo.staticField());
+                       ^");
+    self::Foo::staticFunction();
+    self::use(self::Foo::staticFunction());
+    self::Foo::staticGetter.call();
+    self::use(self::Foo::staticGetter.call());
+    invalid-expression "pkg/front_end/testcases/rasta/static.dart:61:9: Error: Getter not found: 'staticSetter'.
+    Foo.staticSetter();
+        ^^^^^^^^^^^^".call();
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/static.dart:62:13: Error: Getter not found: 'staticSetter'.
+    use(Foo.staticSetter());
+            ^^^^^^^^^^^^".call());
+    let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:64:9: Error: Setter not found: 'staticConstant'.
+    Foo.staticConstant = 87;
+        ^^^^^^^^^^^^^^";
+    self::use(let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:65:13: Error: Setter not found: 'staticConstant'.
+    use(Foo.staticConstant = 87);
+            ^^^^^^^^^^^^^^");
+    self::Foo::staticField = 87;
+    self::use(self::Foo::staticField = 87);
+    let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:68:9: Error: Setter not found: 'staticFunction'.
+    Foo.staticFunction = 87;
+        ^^^^^^^^^^^^^^";
+    self::use(let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:69:13: Error: Setter not found: 'staticFunction'.
+    use(Foo.staticFunction = 87);
+            ^^^^^^^^^^^^^^");
+    let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:70:9: Error: Setter not found: 'staticGetter'.
+    Foo.staticGetter = 87;
+        ^^^^^^^^^^^^";
+    self::use(let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:71:13: Error: Setter not found: 'staticGetter'.
+    use(Foo.staticGetter = 87);
+            ^^^^^^^^^^^^");
+    self::Foo::staticSetter = 87;
+    self::use(self::Foo::staticSetter = 87);
+    self::Foo::staticConstant.{core::Object::==}(null) ?{core::int} let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:75:9: Error: Setter not found: 'staticConstant'.
+    Foo.staticConstant ??= 87;
+        ^^^^^^^^^^^^^^" : null;
+    self::use(let final core::int #t15 = self::Foo::staticConstant in #t15.{core::Object::==}(null) ?{core::int} let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:76:13: Error: Setter not found: 'staticConstant'.
+    use(Foo.staticConstant ??= 87);
+            ^^^^^^^^^^^^^^" : #t15);
+    self::Foo::staticField.{core::num::==}(null) ?{core::int} self::Foo::staticField = 87 : null;
+    self::use(let final core::int #t16 = self::Foo::staticField in #t16.{core::num::==}(null) ?{core::int} self::Foo::staticField = 87 : #t16);
+    self::Foo::staticFunction.{core::Object::==}(null) ?{core::Object} let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:79:9: Error: Setter not found: 'staticFunction'.
+    Foo.staticFunction ??= 87;
+        ^^^^^^^^^^^^^^" : null;
+    self::use(let final () → dynamic #t17 = self::Foo::staticFunction in #t17.{core::Object::==}(null) ?{core::Object} let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:80:13: Error: Setter not found: 'staticFunction'.
+    use(Foo.staticFunction ??= 87);
+            ^^^^^^^^^^^^^^" : #t17);
+    self::Foo::staticGetter.{core::Object::==}(null) ?{dynamic} let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:81:9: Error: Setter not found: 'staticGetter'.
+    Foo.staticGetter ??= 87;
+        ^^^^^^^^^^^^" : null;
+    self::use(let final dynamic #t18 = self::Foo::staticGetter in #t18.{core::Object::==}(null) ?{dynamic} let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:82:13: Error: Setter not found: 'staticGetter'.
+    use(Foo.staticGetter ??= 87);
+            ^^^^^^^^^^^^" : #t18);
+    (let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:83:9: Error: Getter not found: 'staticSetter'.
+    Foo.staticSetter ??= 87;
+        ^^^^^^^^^^^^").{core::Object::==}(null) ?{dynamic} self::Foo::staticSetter = 87 : null;
+    self::use(let final dynamic #t19 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:84:13: Error: Getter not found: 'staticSetter'.
+    use(Foo.staticSetter ??= 87);
+            ^^^^^^^^^^^^" in #t19.{core::Object::==}(null) ?{dynamic} self::Foo::staticSetter = 87 : #t19);
+  }
+  on core::NoSuchMethodError catch(no-exception-var) {
+  }
+}
diff --git a/pkg/front_end/testcases/rasta/static.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/static.dart.strong.transformed.expect
new file mode 100644
index 0000000..25384d5
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/static.dart.strong.transformed.expect
@@ -0,0 +1,165 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  static const field core::int staticConstant = 42;
+  static field core::int staticField = 42;
+  synthetic constructor •() → self::Foo
+    : super core::Object::•()
+    ;
+  static method staticFunction() → dynamic {}
+  static get staticGetter() → dynamic
+    return null;
+  static set staticSetter(dynamic _) → void {}
+}
+static method use(dynamic x) → dynamic {
+  if(x.{core::Object::==}(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}))
+    throw "Shouldn't happen";
+}
+static method main() → dynamic {
+  try {
+    self::Foo::staticConstant;
+    self::use(self::Foo::staticConstant);
+    self::Foo::staticField;
+    self::use(self::Foo::staticField);
+    self::Foo::staticFunction;
+    self::use(self::Foo::staticFunction);
+    self::Foo::staticGetter;
+    self::use(self::Foo::staticGetter);
+    invalid-expression "pkg/front_end/testcases/rasta/static.dart:28:9: Error: Getter not found: 'staticSetter'.
+    Foo.staticSetter;
+        ^^^^^^^^^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/static.dart:29:13: Error: Getter not found: 'staticSetter'.
+    use(Foo.staticSetter);
+            ^^^^^^^^^^^^");
+    let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:31:9: Error: Setter not found: 'staticConstant'.
+    Foo.staticConstant++;
+        ^^^^^^^^^^^^^^";
+    self::use(let final core::int #t1 = self::Foo::staticConstant in let final core::int #t2 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:32:13: Error: Setter not found: 'staticConstant'.
+    use(Foo.staticConstant++);
+            ^^^^^^^^^^^^^^" in #t1);
+    self::Foo::staticField = self::Foo::staticField.{core::num::+}(1);
+    self::use(let final core::int #t3 = self::Foo::staticField in let final core::int #t4 = self::Foo::staticField = #t3.{core::num::+}(1) in #t3);
+    let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:35:9: Error: Setter not found: 'staticFunction'.
+    Foo.staticFunction++;
+        ^^^^^^^^^^^^^^";
+    self::use(let final () → dynamic #t5 = self::Foo::staticFunction in let final dynamic #t6 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:36:13: Error: Setter not found: 'staticFunction'.
+    use(Foo.staticFunction++);
+            ^^^^^^^^^^^^^^" in #t5);
+    let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:37:9: Error: Setter not found: 'staticGetter'.
+    Foo.staticGetter++;
+        ^^^^^^^^^^^^";
+    self::use(let final dynamic #t7 = self::Foo::staticGetter in let final dynamic #t8 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:38:13: Error: Setter not found: 'staticGetter'.
+    use(Foo.staticGetter++);
+            ^^^^^^^^^^^^" in #t7);
+    self::Foo::staticSetter = (let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:39:9: Error: Getter not found: 'staticSetter'.
+    Foo.staticSetter++;
+        ^^^^^^^^^^^^").+(1);
+    self::use(let final dynamic #t9 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:40:13: Error: Getter not found: 'staticSetter'.
+    use(Foo.staticSetter++);
+            ^^^^^^^^^^^^" in let final dynamic #t10 = self::Foo::staticSetter = #t9.+(1) in #t9);
+    let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:42:11: Error: Setter not found: 'staticConstant'.
+    ++Foo.staticConstant;
+          ^^^^^^^^^^^^^^";
+    self::use(let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:43:15: Error: Setter not found: 'staticConstant'.
+    use(++Foo.staticConstant);
+              ^^^^^^^^^^^^^^");
+    self::Foo::staticField = self::Foo::staticField.{core::num::+}(1);
+    self::use(self::Foo::staticField = self::Foo::staticField.{core::num::+}(1));
+    let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:46:11: Error: Setter not found: 'staticFunction'.
+    ++Foo.staticFunction;
+          ^^^^^^^^^^^^^^";
+    self::use(let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:47:15: Error: Setter not found: 'staticFunction'.
+    use(++Foo.staticFunction);
+              ^^^^^^^^^^^^^^");
+    let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:48:11: Error: Setter not found: 'staticGetter'.
+    ++Foo.staticGetter;
+          ^^^^^^^^^^^^";
+    self::use(let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:49:15: Error: Setter not found: 'staticGetter'.
+    use(++Foo.staticGetter);
+              ^^^^^^^^^^^^");
+    self::Foo::staticSetter = (let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:50:11: Error: Getter not found: 'staticSetter'.
+    ++Foo.staticSetter;
+          ^^^^^^^^^^^^").+(1);
+    self::use(self::Foo::staticSetter = (let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:51:15: Error: Getter not found: 'staticSetter'.
+    use(++Foo.staticSetter);
+              ^^^^^^^^^^^^").+(1));
+    let final core::int #t11 = self::Foo::staticConstant in invalid-expression "pkg/front_end/testcases/rasta/static.dart:53:23: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing method, or defining a method named 'call'.
+    Foo.staticConstant();
+                      ^";
+    self::use(let final core::int #t12 = self::Foo::staticConstant in invalid-expression "pkg/front_end/testcases/rasta/static.dart:54:27: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing method, or defining a method named 'call'.
+    use(Foo.staticConstant());
+                          ^");
+    let final core::int #t13 = self::Foo::staticField in invalid-expression "pkg/front_end/testcases/rasta/static.dart:55:20: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing method, or defining a method named 'call'.
+    Foo.staticField();
+                   ^";
+    self::use(let final core::int #t14 = self::Foo::staticField in invalid-expression "pkg/front_end/testcases/rasta/static.dart:56:24: Error: The method 'call' isn't defined for the class 'dart.core::int'.
+Try correcting the name to the name of an existing method, or defining a method named 'call'.
+    use(Foo.staticField());
+                       ^");
+    self::Foo::staticFunction();
+    self::use(self::Foo::staticFunction());
+    self::Foo::staticGetter.call();
+    self::use(self::Foo::staticGetter.call());
+    invalid-expression "pkg/front_end/testcases/rasta/static.dart:61:9: Error: Getter not found: 'staticSetter'.
+    Foo.staticSetter();
+        ^^^^^^^^^^^^".call();
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/static.dart:62:13: Error: Getter not found: 'staticSetter'.
+    use(Foo.staticSetter());
+            ^^^^^^^^^^^^".call());
+    let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:64:9: Error: Setter not found: 'staticConstant'.
+    Foo.staticConstant = 87;
+        ^^^^^^^^^^^^^^";
+    self::use(let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:65:13: Error: Setter not found: 'staticConstant'.
+    use(Foo.staticConstant = 87);
+            ^^^^^^^^^^^^^^");
+    self::Foo::staticField = 87;
+    self::use(self::Foo::staticField = 87);
+    let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:68:9: Error: Setter not found: 'staticFunction'.
+    Foo.staticFunction = 87;
+        ^^^^^^^^^^^^^^";
+    self::use(let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:69:13: Error: Setter not found: 'staticFunction'.
+    use(Foo.staticFunction = 87);
+            ^^^^^^^^^^^^^^");
+    let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:70:9: Error: Setter not found: 'staticGetter'.
+    Foo.staticGetter = 87;
+        ^^^^^^^^^^^^";
+    self::use(let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:71:13: Error: Setter not found: 'staticGetter'.
+    use(Foo.staticGetter = 87);
+            ^^^^^^^^^^^^");
+    self::Foo::staticSetter = 87;
+    self::use(self::Foo::staticSetter = 87);
+    self::Foo::staticConstant.{core::Object::==}(null) ?{core::int} let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:75:9: Error: Setter not found: 'staticConstant'.
+    Foo.staticConstant ??= 87;
+        ^^^^^^^^^^^^^^" : null;
+    self::use(let final core::int #t15 = self::Foo::staticConstant in #t15.{core::Object::==}(null) ?{core::int} let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:76:13: Error: Setter not found: 'staticConstant'.
+    use(Foo.staticConstant ??= 87);
+            ^^^^^^^^^^^^^^" : #t15);
+    self::Foo::staticField.{core::num::==}(null) ?{core::int} self::Foo::staticField = 87 : null;
+    self::use(let final core::int #t16 = self::Foo::staticField in #t16.{core::num::==}(null) ?{core::int} self::Foo::staticField = 87 : #t16);
+    self::Foo::staticFunction.{core::Object::==}(null) ?{core::Object} let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:79:9: Error: Setter not found: 'staticFunction'.
+    Foo.staticFunction ??= 87;
+        ^^^^^^^^^^^^^^" : null;
+    self::use(let final () → dynamic #t17 = self::Foo::staticFunction in #t17.{core::Object::==}(null) ?{core::Object} let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:80:13: Error: Setter not found: 'staticFunction'.
+    use(Foo.staticFunction ??= 87);
+            ^^^^^^^^^^^^^^" : #t17);
+    self::Foo::staticGetter.{core::Object::==}(null) ?{dynamic} let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:81:9: Error: Setter not found: 'staticGetter'.
+    Foo.staticGetter ??= 87;
+        ^^^^^^^^^^^^" : null;
+    self::use(let final dynamic #t18 = self::Foo::staticGetter in #t18.{core::Object::==}(null) ?{dynamic} let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:82:13: Error: Setter not found: 'staticGetter'.
+    use(Foo.staticGetter ??= 87);
+            ^^^^^^^^^^^^" : #t18);
+    (let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:83:9: Error: Getter not found: 'staticSetter'.
+    Foo.staticSetter ??= 87;
+        ^^^^^^^^^^^^").{core::Object::==}(null) ?{dynamic} self::Foo::staticSetter = 87 : null;
+    self::use(let final dynamic #t19 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/rasta/static.dart:84:13: Error: Getter not found: 'staticSetter'.
+    use(Foo.staticSetter ??= 87);
+            ^^^^^^^^^^^^" in #t19.{core::Object::==}(null) ?{dynamic} self::Foo::staticSetter = 87 : #t19);
+  }
+  on core::NoSuchMethodError catch(no-exception-var) {
+  }
+}
diff --git a/pkg/front_end/testcases/rasta/super.dart.direct.expect b/pkg/front_end/testcases/rasta/super.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/super.dart.direct.expect
rename to pkg/front_end/testcases/rasta/super.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/super.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/super.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/super.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/super.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/super.dart.strong.expect b/pkg/front_end/testcases/rasta/super.dart.strong.expect
index db43639..036d699 100644
--- a/pkg/front_end/testcases/rasta/super.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/super.dart.strong.expect
@@ -1,3 +1,354 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/super.dart:26:8: Error: Can't declare a member that conflicts with an inherited one.
+//   void n() {}
+//        ^
+// pkg/front_end/testcases/rasta/super.dart:27:7: Context: This is the inherited member.
+//   set n(_) {}
+//       ^
+//
+// pkg/front_end/testcases/rasta/super.dart:43:5: Error: '+' is not a prefix operator.
+// Try removing '+'.
+//     +super;
+//     ^
+//
+// pkg/front_end/testcases/rasta/super.dart:43:6: Error: Can't use 'super' as an expression.
+// To delegate a constructor to a super constructor, put the super call as an initializer.
+//     +super;
+//      ^^^^^
+//
+// pkg/front_end/testcases/rasta/super.dart:44:9: Error: '+' is not a prefix operator.
+// Try removing '+'.
+//     use(+super);
+//         ^
+//
+// pkg/front_end/testcases/rasta/super.dart:44:10: Error: Can't use 'super' as an expression.
+// To delegate a constructor to a super constructor, put the super call as an initializer.
+//     use(+super);
+//          ^^^^^
+//
+// pkg/front_end/testcases/rasta/super.dart:62:11: Error: Superclass has no getter named 'g'.
+//     super.g;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:63:15: Error: Superclass has no getter named 'g'.
+//     use(super.g);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:83:11: Error: Superclass has no setter named 'e'.
+//     super.e++;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:84:15: Error: Superclass has no setter named 'e'.
+//     use(super.e++);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:85:11: Error: Superclass has no setter named 'f'.
+//     super.f++;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:86:15: Error: Superclass has no setter named 'f'.
+//     use(super.f++);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:87:11: Error: Superclass has no getter named 'g'.
+//     super.g++;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:88:15: Error: Superclass has no getter named 'g'.
+//     use(super.g++);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:95:11: Error: Superclass has no setter named 'm'.
+//     super.m++;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:96:15: Error: Superclass has no setter named 'm'.
+//     use(super.m++);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:108:13: Error: Superclass has no setter named 'e'.
+//     ++super.e;
+//             ^
+//
+// pkg/front_end/testcases/rasta/super.dart:109:17: Error: Superclass has no setter named 'e'.
+//     use(++super.e);
+//                 ^
+//
+// pkg/front_end/testcases/rasta/super.dart:110:13: Error: Superclass has no setter named 'f'.
+//     ++super.f;
+//             ^
+//
+// pkg/front_end/testcases/rasta/super.dart:111:17: Error: Superclass has no setter named 'f'.
+//     use(++super.f);
+//                 ^
+//
+// pkg/front_end/testcases/rasta/super.dart:112:13: Error: Superclass has no getter named 'g'.
+//     ++super.g;
+//             ^
+//
+// pkg/front_end/testcases/rasta/super.dart:113:17: Error: Superclass has no getter named 'g'.
+//     use(++super.g);
+//                 ^
+//
+// pkg/front_end/testcases/rasta/super.dart:120:13: Error: Superclass has no setter named 'm'.
+//     ++super.m;
+//             ^
+//
+// pkg/front_end/testcases/rasta/super.dart:121:17: Error: Superclass has no setter named 'm'.
+//     use(++super.m);
+//                 ^
+//
+// pkg/front_end/testcases/rasta/super.dart:137:11: Error: Superclass has no method named 'g'.
+//     super.g();
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:138:15: Error: Superclass has no method named 'g'.
+//     use(super.g());
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:160:11: Error: Superclass has no setter named 'e'.
+//     super.e = 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:161:15: Error: Superclass has no setter named 'e'.
+//     use(super.e = 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:162:11: Error: Superclass has no setter named 'f'.
+//     super.f = 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:163:15: Error: Superclass has no setter named 'f'.
+//     use(super.f = 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:172:11: Error: Superclass has no setter named 'm'.
+//     super.m = 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:173:15: Error: Superclass has no setter named 'm'.
+//     use(super.m = 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:185:11: Error: Superclass has no setter named 'e'.
+//     super.e ??= 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:186:15: Error: Superclass has no setter named 'e'.
+//     use(super.e ??= 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:187:11: Error: Superclass has no setter named 'f'.
+//     super.f ??= 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:188:15: Error: Superclass has no setter named 'f'.
+//     use(super.f ??= 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:189:11: Error: Superclass has no getter named 'g'.
+//     super.g ??= 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:190:15: Error: Superclass has no getter named 'g'.
+//     use(super.g ??= 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:197:11: Error: Superclass has no setter named 'm'.
+//     super.m ??= 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:198:15: Error: Superclass has no setter named 'm'.
+//     use(super.m ??= 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:210:11: Error: Superclass has no setter named 'e'.
+//     super.e += 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:211:15: Error: Superclass has no setter named 'e'.
+//     use(super.e += 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:212:11: Error: Superclass has no setter named 'f'.
+//     super.f += 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:213:15: Error: Superclass has no setter named 'f'.
+//     use(super.f += 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:214:11: Error: Superclass has no getter named 'g'.
+//     super.g += 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:215:15: Error: Superclass has no getter named 'g'.
+//     use(super.g += 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:222:11: Error: Superclass has no setter named 'm'.
+//     super.m += 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:223:15: Error: Superclass has no setter named 'm'.
+//     use(super.m += 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:235:11: Error: Superclass has no setter named 'e'.
+//     super.e -= 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:236:15: Error: Superclass has no setter named 'e'.
+//     use(super.e -= 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:237:11: Error: Superclass has no setter named 'f'.
+//     super.f -= 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:238:15: Error: Superclass has no setter named 'f'.
+//     use(super.f -= 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:239:11: Error: Superclass has no getter named 'g'.
+//     super.g -= 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:240:15: Error: Superclass has no getter named 'g'.
+//     use(super.g -= 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:247:11: Error: Superclass has no setter named 'm'.
+//     super.m -= 42;
+//           ^
+//
+// pkg/front_end/testcases/rasta/super.dart:248:15: Error: Superclass has no setter named 'm'.
+//     use(super.m -= 42);
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:95:12: Error: The method '+' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     super.m++;
+//            ^
+//
+// pkg/front_end/testcases/rasta/super.dart:96:16: Error: The method '+' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     use(super.m++);
+//                ^
+//
+// pkg/front_end/testcases/rasta/super.dart:97:12: Error: The method '+' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     super.n++;
+//            ^
+//
+// pkg/front_end/testcases/rasta/super.dart:98:16: Error: The method '+' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     use(super.n++);
+//                ^
+//
+// pkg/front_end/testcases/rasta/super.dart:120:5: Error: The method '+' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     ++super.m;
+//     ^
+//
+// pkg/front_end/testcases/rasta/super.dart:121:9: Error: The method '+' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     use(++super.m);
+//         ^
+//
+// pkg/front_end/testcases/rasta/super.dart:122:5: Error: The method '+' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     ++super.n;
+//     ^
+//
+// pkg/front_end/testcases/rasta/super.dart:123:9: Error: The method '+' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     use(++super.n);
+//         ^
+//
+// pkg/front_end/testcases/rasta/super.dart:146:15: Error: This expression has type 'void' and can't be used.
+//     use(super.m());
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:147:12: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     super.m(87);
+//            ^
+//
+// pkg/front_end/testcases/rasta/super.dart:148:16: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     use(super.m(87));
+//                ^
+//
+// pkg/front_end/testcases/rasta/super.dart:148:15: Error: This expression has type 'void' and can't be used.
+//     use(super.m(87));
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:149:12: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     super.n(87);
+//            ^
+//
+// pkg/front_end/testcases/rasta/super.dart:150:16: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     use(super.n(87));
+//                ^
+//
+// pkg/front_end/testcases/rasta/super.dart:150:15: Error: This expression has type 'void' and can't be used.
+//     use(super.n(87));
+//               ^
+//
+// pkg/front_end/testcases/rasta/super.dart:222:13: Error: The method '+' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     super.m += 42;
+//             ^
+//
+// pkg/front_end/testcases/rasta/super.dart:223:17: Error: The method '+' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     use(super.m += 42);
+//                 ^
+//
+// pkg/front_end/testcases/rasta/super.dart:224:13: Error: The method '+' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     super.n += 42;
+//             ^
+//
+// pkg/front_end/testcases/rasta/super.dart:225:17: Error: The method '+' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+//     use(super.n += 42);
+//                 ^
+//
+// pkg/front_end/testcases/rasta/super.dart:247:13: Error: The method '-' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '-'.
+//     super.m -= 42;
+//             ^
+//
+// pkg/front_end/testcases/rasta/super.dart:248:17: Error: The method '-' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '-'.
+//     use(super.m -= 42);
+//                 ^
+//
+// pkg/front_end/testcases/rasta/super.dart:249:13: Error: The method '-' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '-'.
+//     super.n -= 42;
+//             ^
+//
+// pkg/front_end/testcases/rasta/super.dart:250:17: Error: The method '-' isn't defined for the class '() → void'.
+// Try correcting the name to the name of an existing method, or defining a method named '-'.
+//     use(super.n -= 42);
+//                 ^
+//
+// pkg/front_end/testcases/rasta/super.dart:11:9: Error: Final field 'f' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final f;
+//         ^
+//
+// pkg/front_end/testcases/rasta/super.dart:33:9: Error: Final field 'd' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final d;
+//         ^
+
 // Unhandled errors:
 //
 // pkg/front_end/testcases/rasta/super.dart:26:8: Error: Can't declare a member that conflicts with an inherited one.
@@ -9,19 +360,11 @@
 //     +super;
 //     ^
 //
-// pkg/front_end/testcases/rasta/super.dart:43:5: Error: Getter not found: ''.
-//     +super;
-//     ^
-//
 // pkg/front_end/testcases/rasta/super.dart:44:9: Error: '+' is not a prefix operator.
 // Try removing '+'.
 //     use(+super);
 //         ^
 //
-// pkg/front_end/testcases/rasta/super.dart:44:9: Error: Getter not found: ''.
-//     use(+super);
-//         ^
-//
 // pkg/front_end/testcases/rasta/super.dart:62:11: Error: Superclass has no getter named 'g'.
 //     super.g;
 //           ^
@@ -262,7 +605,7 @@
   field dynamic c = null;
   field dynamic d = null;
   final field dynamic f = null;
-  synthetic constructor •() → void
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
   get e() → dynamic
@@ -288,7 +631,7 @@
 }
 class B extends self::A {
   final field dynamic d = null;
-  synthetic constructor •() → void
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
   get b() → dynamic
@@ -297,7 +640,7 @@
   set i(dynamic x) → void {}
 }
 class C extends self::B {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::C
     : super self::B::•()
     ;
   method test() → dynamic {
@@ -305,17 +648,15 @@
     self::use(super.{self::A::~}());
     super.{self::A::unary-}();
     self::use(super.{self::A::unary-}());
-    (let final dynamic #t1 = this in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:43:5: Error: The getter '' isn't defined for the class '#lib1::C'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named ''.
+    invalid-expression "pkg/front_end/testcases/rasta/super.dart:43:5: Error: This couldn't be parsed.
     +super;
-    ^").+(invalid-expression "pkg/front_end/testcases/rasta/super.dart:43:6: Error: Can't use 'super' as an expression.
+    ^".+(invalid-expression "pkg/front_end/testcases/rasta/super.dart:43:6: Error: Can't use 'super' as an expression.
 To delegate a constructor to a super constructor, put the super call as an initializer.
     +super;
      ^^^^^");
-    self::use((let final dynamic #t2 = this in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:44:9: Error: The getter '' isn't defined for the class '#lib1::C'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named ''.
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/super.dart:44:9: Error: This couldn't be parsed.
     use(+super);
-        ^").+(invalid-expression "pkg/front_end/testcases/rasta/super.dart:44:10: Error: Can't use 'super' as an expression.
+        ^".+(invalid-expression "pkg/front_end/testcases/rasta/super.dart:44:10: Error: Can't use 'super' as an expression.
 To delegate a constructor to a super constructor, put the super call as an initializer.
     use(+super);
          ^^^^^"));
@@ -348,41 +689,41 @@
     super.{self::A::n};
     self::use(super.{self::A::n});
     super.{self::A::a} = super.{self::A::a}.+(1);
-    self::use(let final dynamic #t3 = super.{self::A::a} in let final dynamic #t4 = super.{self::A::a} = #t3.+(1) in #t3);
+    self::use(let final dynamic #t1 = super.{self::A::a} in let final dynamic #t2 = super.{self::A::a} = #t1.+(1) in #t1);
     super.{self::A::b} = super.{self::B::b}.+(1);
-    self::use(let final dynamic #t5 = super.{self::B::b} in let final dynamic #t6 = super.{self::A::b} = #t5.+(1) in #t5);
+    self::use(let final dynamic #t3 = super.{self::B::b} in let final dynamic #t4 = super.{self::A::b} = #t3.+(1) in #t3);
     super.{self::B::c} = super.{self::A::c}.+(1);
-    self::use(let final dynamic #t7 = super.{self::A::c} in let final dynamic #t8 = super.{self::B::c} = #t7.+(1) in #t7);
+    self::use(let final dynamic #t5 = super.{self::A::c} in let final dynamic #t6 = super.{self::B::c} = #t5.+(1) in #t5);
     super.{self::A::d} = super.{self::B::d}.+(1);
-    self::use(let final dynamic #t9 = super.{self::B::d} in let final dynamic #t10 = super.{self::A::d} = #t9.+(1) in #t9);
+    self::use(let final dynamic #t7 = super.{self::B::d} in let final dynamic #t8 = super.{self::A::d} = #t7.+(1) in #t7);
     super.e = super.{self::A::e}.+(1);
-    self::use(let final dynamic #t11 = super.{self::A::e} in let final dynamic #t12 = super.e = #t11.+(1) in #t11);
+    self::use(let final dynamic #t9 = super.{self::A::e} in let final dynamic #t10 = super.e = #t9.+(1) in #t9);
     super.f = super.{self::A::f}.+(1);
-    self::use(let final dynamic #t13 = super.{self::A::f} in let final dynamic #t14 = super.f = #t13.+(1) in #t13);
+    self::use(let final dynamic #t11 = super.{self::A::f} in let final dynamic #t12 = super.f = #t11.+(1) in #t11);
     super.{self::A::g} = super.g.+(1);
-    self::use(let final dynamic #t15 = super.g in let final dynamic #t16 = super.{self::A::g} = #t15.+(1) in #t15);
+    self::use(let final dynamic #t13 = super.g in let final dynamic #t14 = super.{self::A::g} = #t13.+(1) in #t13);
     super.{self::A::h} = super.{self::A::h}.+(1);
-    self::use(let final dynamic #t17 = super.{self::A::h} in let final dynamic #t18 = super.{self::A::h} = #t17.+(1) in #t17);
+    self::use(let final dynamic #t15 = super.{self::A::h} in let final dynamic #t16 = super.{self::A::h} = #t15.+(1) in #t15);
     super.{self::B::i} = super.{self::A::i}.+(1);
-    self::use(let final dynamic #t19 = super.{self::A::i} in let final dynamic #t20 = super.{self::B::i} = #t19.+(1) in #t19);
-    let final core::int #t21 = 87 in super.{self::A::[]=}(#t21, super.{self::A::[]}(#t21).+(1));
-    self::use(let final core::int #t22 = 87 in let final dynamic #t23 = super.{self::A::[]}(#t22) in let final void #t24 = super.{self::A::[]=}(#t22, #t23.+(1)) in #t23);
-    super.m = let final dynamic #t25 = super.{self::A::m} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:95:12: Error: The method '+' isn't defined for the class '() \u8594 void'.
+    self::use(let final dynamic #t17 = super.{self::A::i} in let final dynamic #t18 = super.{self::B::i} = #t17.+(1) in #t17);
+    let final core::int #t19 = 87 in super.{self::A::[]=}(#t19, super.{self::A::[]}(#t19).+(1));
+    self::use(let final core::int #t20 = 87 in let final dynamic #t21 = super.{self::A::[]}(#t20) in let final void #t22 = super.{self::A::[]=}(#t20, #t21.+(1)) in #t21);
+    super.m = let final dynamic #t23 = super.{self::A::m} in invalid-expression "pkg/front_end/testcases/rasta/super.dart:95:12: Error: The method '+' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '+'.
     super.m++;
            ^";
-    self::use(let final () → void #t26 = super.{self::A::m} in let final dynamic #t27 = super.m = let final dynamic #t28 = #t26 in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:96:16: Error: The method '+' isn't defined for the class '() \u8594 void'.
+    self::use(let final () → void #t24 = super.{self::A::m} in let final dynamic #t25 = super.m = let final dynamic #t26 = #t24 in invalid-expression "pkg/front_end/testcases/rasta/super.dart:96:16: Error: The method '+' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '+'.
     use(super.m++);
-               ^" in #t26);
-    super.{self::A::n} = let final dynamic #t29 = super.{self::A::n} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:97:12: Error: The method '+' isn't defined for the class '() \u8594 void'.
+               ^" in #t24);
+    super.{self::A::n} = let final dynamic #t27 = super.{self::A::n} in invalid-expression "pkg/front_end/testcases/rasta/super.dart:97:12: Error: The method '+' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '+'.
     super.n++;
            ^";
-    self::use(let final () → void #t30 = super.{self::A::n} in let final dynamic #t31 = super.{self::A::n} = let final dynamic #t32 = #t30 in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:98:16: Error: The method '+' isn't defined for the class '() \u8594 void'.
+    self::use(let final () → void #t28 = super.{self::A::n} in let final dynamic #t29 = super.{self::A::n} = let final dynamic #t30 = #t28 in invalid-expression "pkg/front_end/testcases/rasta/super.dart:98:16: Error: The method '+' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '+'.
     use(super.n++);
-               ^" in #t30);
+               ^" in #t28);
     super.{self::A::a} = super.{self::A::a}.+(1);
     self::use(super.{self::A::a} = super.{self::A::a}.+(1));
     super.{self::A::b} = super.{self::B::b}.+(1);
@@ -401,21 +742,21 @@
     self::use(super.{self::A::h} = super.{self::A::h}.+(1));
     super.{self::B::i} = super.{self::A::i}.+(1);
     self::use(super.{self::B::i} = super.{self::A::i}.+(1));
-    let final core::int #t33 = 87 in let final dynamic #t34 = super.{self::A::[]}(#t33).+(1) in let final void #t35 = super.{self::A::[]=}(#t33, #t34) in #t34;
-    self::use(let final core::int #t36 = 87 in let final dynamic #t37 = super.{self::A::[]}(#t36).+(1) in let final void #t38 = super.{self::A::[]=}(#t36, #t37) in #t37);
-    super.m = let final dynamic #t39 = super.{self::A::m} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:120:5: Error: The method '+' isn't defined for the class '() \u8594 void'.
+    let final core::int #t31 = 87 in let final dynamic #t32 = super.{self::A::[]}(#t31).+(1) in let final void #t33 = super.{self::A::[]=}(#t31, #t32) in #t32;
+    self::use(let final core::int #t34 = 87 in let final dynamic #t35 = super.{self::A::[]}(#t34).+(1) in let final void #t36 = super.{self::A::[]=}(#t34, #t35) in #t35);
+    super.m = let final dynamic #t37 = super.{self::A::m} in invalid-expression "pkg/front_end/testcases/rasta/super.dart:120:5: Error: The method '+' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '+'.
     ++super.m;
     ^";
-    self::use(super.m = let final dynamic #t40 = super.{self::A::m} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:121:9: Error: The method '+' isn't defined for the class '() \u8594 void'.
+    self::use(super.m = let final dynamic #t38 = super.{self::A::m} in invalid-expression "pkg/front_end/testcases/rasta/super.dart:121:9: Error: The method '+' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '+'.
     use(++super.m);
         ^");
-    super.{self::A::n} = let final dynamic #t41 = super.{self::A::n} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:122:5: Error: The method '+' isn't defined for the class '() \u8594 void'.
+    super.{self::A::n} = let final dynamic #t39 = super.{self::A::n} in invalid-expression "pkg/front_end/testcases/rasta/super.dart:122:5: Error: The method '+' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '+'.
     ++super.n;
     ^";
-    self::use(super.{self::A::n} = let final dynamic #t42 = super.{self::A::n} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:123:9: Error: The method '+' isn't defined for the class '() \u8594 void'.
+    self::use(super.{self::A::n} = let final dynamic #t40 = super.{self::A::n} in invalid-expression "pkg/front_end/testcases/rasta/super.dart:123:9: Error: The method '+' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '+'.
     use(++super.n);
         ^");
@@ -440,11 +781,17 @@
     super.{self::A::[]}(87).call();
     self::use(super.{self::A::[]}(87).call());
     super.{self::A::m}();
-    self::use(super.{self::A::m}());
+    self::use(let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/rasta/super.dart:146:15: Error: This expression has type 'void' and can't be used.
+    use(super.m());
+              ^" in super.{self::A::m}());
     super.{self::A::m}(87);
-    self::use(super.{self::A::m}(87));
+    self::use(let final<BottomType> #t42 = invalid-expression "pkg/front_end/testcases/rasta/super.dart:148:15: Error: This expression has type 'void' and can't be used.
+    use(super.m(87));
+              ^" in super.{self::A::m}(87));
     super.{self::A::n}(87);
-    self::use(super.{self::A::n}(87));
+    self::use(let final<BottomType> #t43 = invalid-expression "pkg/front_end/testcases/rasta/super.dart:150:15: Error: This expression has type 'void' and can't be used.
+    use(super.n(87));
+              ^" in super.{self::A::n}(87));
     super.{self::A::a} = 42;
     self::use(super.{self::A::a} = 42);
     super.{self::A::b} = 42;
@@ -464,35 +811,35 @@
     super.{self::B::i} = 42;
     self::use(super.{self::B::i} = 42);
     super.{self::A::[]=}(87, 42);
-    self::use(let final core::int #t43 = 87 in let final core::int #t44 = 42 in let final void #t45 = super.{self::A::[]=}(#t43, #t44) in #t44);
+    self::use(let final core::int #t44 = 87 in let final core::int #t45 = 42 in let final void #t46 = super.{self::A::[]=}(#t44, #t45) in #t45);
     super.m = 42;
     self::use(super.m = 42);
     super.{self::A::n} = 42;
     self::use(super.{self::A::n} = 42);
     super.{self::A::a}.{core::Object::==}(null) ?{dynamic} super.{self::A::a} = 42 : null;
-    self::use(let final dynamic #t46 = super.{self::A::a} in #t46.{core::Object::==}(null) ?{dynamic} super.{self::A::a} = 42 : #t46);
+    self::use(let final dynamic #t47 = super.{self::A::a} in #t47.{core::Object::==}(null) ?{dynamic} super.{self::A::a} = 42 : #t47);
     super.{self::B::b}.{core::Object::==}(null) ?{dynamic} super.{self::A::b} = 42 : null;
-    self::use(let final dynamic #t47 = super.{self::B::b} in #t47.{core::Object::==}(null) ?{dynamic} super.{self::A::b} = 42 : #t47);
+    self::use(let final dynamic #t48 = super.{self::B::b} in #t48.{core::Object::==}(null) ?{dynamic} super.{self::A::b} = 42 : #t48);
     super.{self::A::c}.{core::Object::==}(null) ?{dynamic} super.{self::B::c} = 42 : null;
-    self::use(let final dynamic #t48 = super.{self::A::c} in #t48.{core::Object::==}(null) ?{dynamic} super.{self::B::c} = 42 : #t48);
+    self::use(let final dynamic #t49 = super.{self::A::c} in #t49.{core::Object::==}(null) ?{dynamic} super.{self::B::c} = 42 : #t49);
     super.{self::B::d}.{core::Object::==}(null) ?{dynamic} super.{self::A::d} = 42 : null;
-    self::use(let final dynamic #t49 = super.{self::B::d} in #t49.{core::Object::==}(null) ?{dynamic} super.{self::A::d} = 42 : #t49);
+    self::use(let final dynamic #t50 = super.{self::B::d} in #t50.{core::Object::==}(null) ?{dynamic} super.{self::A::d} = 42 : #t50);
     super.{self::A::e}.{core::Object::==}(null) ?{dynamic} super.e = 42 : null;
-    self::use(let final dynamic #t50 = super.{self::A::e} in #t50.{core::Object::==}(null) ?{dynamic} super.e = 42 : #t50);
+    self::use(let final dynamic #t51 = super.{self::A::e} in #t51.{core::Object::==}(null) ?{dynamic} super.e = 42 : #t51);
     super.{self::A::f}.{core::Object::==}(null) ?{dynamic} super.f = 42 : null;
-    self::use(let final dynamic #t51 = super.{self::A::f} in #t51.{core::Object::==}(null) ?{dynamic} super.f = 42 : #t51);
+    self::use(let final dynamic #t52 = super.{self::A::f} in #t52.{core::Object::==}(null) ?{dynamic} super.f = 42 : #t52);
     super.g.{core::Object::==}(null) ?{dynamic} super.{self::A::g} = 42 : null;
-    self::use(let final dynamic #t52 = super.g in #t52.{core::Object::==}(null) ?{dynamic} super.{self::A::g} = 42 : #t52);
+    self::use(let final dynamic #t53 = super.g in #t53.{core::Object::==}(null) ?{dynamic} super.{self::A::g} = 42 : #t53);
     super.{self::A::h}.{core::Object::==}(null) ?{dynamic} super.{self::A::h} = 42 : null;
-    self::use(let final dynamic #t53 = super.{self::A::h} in #t53.{core::Object::==}(null) ?{dynamic} super.{self::A::h} = 42 : #t53);
+    self::use(let final dynamic #t54 = super.{self::A::h} in #t54.{core::Object::==}(null) ?{dynamic} super.{self::A::h} = 42 : #t54);
     super.{self::A::i}.{core::Object::==}(null) ?{dynamic} super.{self::B::i} = 42 : null;
-    self::use(let final dynamic #t54 = super.{self::A::i} in #t54.{core::Object::==}(null) ?{dynamic} super.{self::B::i} = 42 : #t54);
-    let final core::int #t55 = 87 in super.{self::A::[]}(#t55).{core::Object::==}(null) ?{dynamic} let final core::int #t56 = 42 in let final void #t57 = super.{self::A::[]=}(#t55, #t56) in #t56 : null;
-    self::use(let final core::int #t58 = 87 in let final dynamic #t59 = super.{self::A::[]}(#t58) in #t59.{core::Object::==}(null) ?{dynamic} let final core::int #t60 = 42 in let final void #t61 = super.{self::A::[]=}(#t58, #t60) in #t60 : #t59);
+    self::use(let final dynamic #t55 = super.{self::A::i} in #t55.{core::Object::==}(null) ?{dynamic} super.{self::B::i} = 42 : #t55);
+    let final core::int #t56 = 87 in super.{self::A::[]}(#t56).{core::Object::==}(null) ?{dynamic} let final core::int #t57 = 42 in let final void #t58 = super.{self::A::[]=}(#t56, #t57) in #t57 : null;
+    self::use(let final core::int #t59 = 87 in let final dynamic #t60 = super.{self::A::[]}(#t59) in #t60.{core::Object::==}(null) ?{dynamic} let final core::int #t61 = 42 in let final void #t62 = super.{self::A::[]=}(#t59, #t61) in #t61 : #t60);
     super.{self::A::m}.{core::Object::==}(null) ?{core::Object} super.m = 42 : null;
-    self::use(let final () → void #t62 = super.{self::A::m} in #t62.{core::Object::==}(null) ?{core::Object} super.m = 42 : #t62);
+    self::use(let final () → void #t63 = super.{self::A::m} in #t63.{core::Object::==}(null) ?{core::Object} super.m = 42 : #t63);
     super.{self::A::n}.{core::Object::==}(null) ?{core::Object} super.{self::A::n} = 42 : null;
-    self::use(let final () → void #t63 = super.{self::A::n} in #t63.{core::Object::==}(null) ?{core::Object} super.{self::A::n} = 42 : #t63);
+    self::use(let final () → void #t64 = super.{self::A::n} in #t64.{core::Object::==}(null) ?{core::Object} super.{self::A::n} = 42 : #t64);
     super.{self::A::a} = super.{self::A::a}.+(42);
     self::use(super.{self::A::a} = super.{self::A::a}.+(42));
     super.{self::A::b} = super.{self::B::b}.+(42);
@@ -511,21 +858,21 @@
     self::use(super.{self::A::h} = super.{self::A::h}.+(42));
     super.{self::B::i} = super.{self::A::i}.+(42);
     self::use(super.{self::B::i} = super.{self::A::i}.+(42));
-    let final core::int #t64 = 87 in super.{self::A::[]=}(#t64, super.{self::A::[]}(#t64).+(42));
-    self::use(let final core::int #t65 = 87 in let final dynamic #t66 = super.{self::A::[]}(#t65).+(42) in let final void #t67 = super.{self::A::[]=}(#t65, #t66) in #t66);
-    super.m = let final dynamic #t68 = super.{self::A::m} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:222:13: Error: The method '+' isn't defined for the class '() \u8594 void'.
+    let final core::int #t65 = 87 in super.{self::A::[]=}(#t65, super.{self::A::[]}(#t65).+(42));
+    self::use(let final core::int #t66 = 87 in let final dynamic #t67 = super.{self::A::[]}(#t66).+(42) in let final void #t68 = super.{self::A::[]=}(#t66, #t67) in #t67);
+    super.m = let final dynamic #t69 = super.{self::A::m} in invalid-expression "pkg/front_end/testcases/rasta/super.dart:222:13: Error: The method '+' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '+'.
     super.m += 42;
             ^";
-    self::use(super.m = let final dynamic #t69 = super.{self::A::m} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:223:17: Error: The method '+' isn't defined for the class '() \u8594 void'.
+    self::use(super.m = let final dynamic #t70 = super.{self::A::m} in invalid-expression "pkg/front_end/testcases/rasta/super.dart:223:17: Error: The method '+' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '+'.
     use(super.m += 42);
                 ^");
-    super.{self::A::n} = let final dynamic #t70 = super.{self::A::n} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:224:13: Error: The method '+' isn't defined for the class '() \u8594 void'.
+    super.{self::A::n} = let final dynamic #t71 = super.{self::A::n} in invalid-expression "pkg/front_end/testcases/rasta/super.dart:224:13: Error: The method '+' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '+'.
     super.n += 42;
             ^";
-    self::use(super.{self::A::n} = let final dynamic #t71 = super.{self::A::n} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:225:17: Error: The method '+' isn't defined for the class '() \u8594 void'.
+    self::use(super.{self::A::n} = let final dynamic #t72 = super.{self::A::n} in invalid-expression "pkg/front_end/testcases/rasta/super.dart:225:17: Error: The method '+' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '+'.
     use(super.n += 42);
                 ^");
@@ -547,21 +894,21 @@
     self::use(super.{self::A::h} = super.{self::A::h}.-(42));
     super.{self::B::i} = super.{self::A::i}.-(42);
     self::use(super.{self::B::i} = super.{self::A::i}.-(42));
-    let final core::int #t72 = 87 in super.{self::A::[]=}(#t72, super.{self::A::[]}(#t72).-(42));
-    self::use(let final core::int #t73 = 87 in let final dynamic #t74 = super.{self::A::[]}(#t73).-(42) in let final void #t75 = super.{self::A::[]=}(#t73, #t74) in #t74);
-    super.m = let final dynamic #t76 = super.{self::A::m} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:247:13: Error: The method '-' isn't defined for the class '() \u8594 void'.
+    let final core::int #t73 = 87 in super.{self::A::[]=}(#t73, super.{self::A::[]}(#t73).-(42));
+    self::use(let final core::int #t74 = 87 in let final dynamic #t75 = super.{self::A::[]}(#t74).-(42) in let final void #t76 = super.{self::A::[]=}(#t74, #t75) in #t75);
+    super.m = let final dynamic #t77 = super.{self::A::m} in invalid-expression "pkg/front_end/testcases/rasta/super.dart:247:13: Error: The method '-' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '-'.
     super.m -= 42;
             ^";
-    self::use(super.m = let final dynamic #t77 = super.{self::A::m} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:248:17: Error: The method '-' isn't defined for the class '() \u8594 void'.
+    self::use(super.m = let final dynamic #t78 = super.{self::A::m} in invalid-expression "pkg/front_end/testcases/rasta/super.dart:248:17: Error: The method '-' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '-'.
     use(super.m -= 42);
                 ^");
-    super.{self::A::n} = let final dynamic #t78 = super.{self::A::n} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:249:13: Error: The method '-' isn't defined for the class '() \u8594 void'.
+    super.{self::A::n} = let final dynamic #t79 = super.{self::A::n} in invalid-expression "pkg/front_end/testcases/rasta/super.dart:249:13: Error: The method '-' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '-'.
     super.n -= 42;
             ^";
-    self::use(super.{self::A::n} = let final dynamic #t79 = super.{self::A::n} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/super.dart:250:17: Error: The method '-' isn't defined for the class '() \u8594 void'.
+    self::use(super.{self::A::n} = let final dynamic #t80 = super.{self::A::n} in invalid-expression "pkg/front_end/testcases/rasta/super.dart:250:17: Error: The method '-' isn't defined for the class '() \u8594 void'.
 Try correcting the name to the name of an existing method, or defining a method named '-'.
     use(super.n -= 42);
                 ^");
diff --git a/pkg/front_end/testcases/rasta/super_initializer.dart.direct.expect b/pkg/front_end/testcases/rasta/super_initializer.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/super_initializer.dart.direct.expect
rename to pkg/front_end/testcases/rasta/super_initializer.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/super_initializer.dart.strong.expect b/pkg/front_end/testcases/rasta/super_initializer.dart.strong.expect
new file mode 100644
index 0000000..04047ee
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/super_initializer.dart.strong.expect
@@ -0,0 +1,47 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/super_initializer.dart:14:15: Error: Can't have initializers after 'super'.
+//       : super.arg0(),
+//               ^
+//
+// pkg/front_end/testcases/rasta/super_initializer.dart:17:15: Error: Can't have initializers after 'super'.
+//       : super.arg1(a),
+//               ^
+//
+// pkg/front_end/testcases/rasta/super_initializer.dart:20:15: Error: Can't have initializers after 'super'.
+//       : super.arg2(a, b),
+//               ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  constructor arg0() → self::Super
+    : super core::Object::•()
+    ;
+  constructor arg1(dynamic a) → self::Super
+    : super core::Object::•()
+    ;
+  constructor arg2(dynamic a, dynamic b) → self::Super
+    : super core::Object::•()
+    ;
+}
+class Sub extends self::Super {
+  field dynamic field = null;
+  constructor arg0() → self::Sub
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/super_initializer.dart:14:15: Error: Can't have initializers after 'super'.
+      : super.arg0(),
+              ^", super self::Super::arg0()
+    ;
+  constructor arg1(dynamic a) → self::Sub
+    : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/rasta/super_initializer.dart:17:15: Error: Can't have initializers after 'super'.
+      : super.arg1(a),
+              ^", super self::Super::arg1(a)
+    ;
+  constructor arg2(dynamic a, dynamic b) → self::Sub
+    : final dynamic #t3 = invalid-expression "pkg/front_end/testcases/rasta/super_initializer.dart:20:15: Error: Can't have initializers after 'super'.
+      : super.arg2(a, b),
+              ^", super self::Super::arg2(a, b)
+    ;
+}
diff --git a/pkg/front_end/testcases/rasta/super_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/super_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..ab3a0b9
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/super_initializer.dart.strong.transformed.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  constructor arg0() → self::Super
+    : super core::Object::•()
+    ;
+  constructor arg1(dynamic a) → self::Super
+    : super core::Object::•()
+    ;
+  constructor arg2(dynamic a, dynamic b) → self::Super
+    : super core::Object::•()
+    ;
+}
+class Sub extends self::Super {
+  field dynamic field = null;
+  constructor arg0() → self::Sub
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/super_initializer.dart:14:15: Error: Can't have initializers after 'super'.
+      : super.arg0(),
+              ^", super self::Super::arg0()
+    ;
+  constructor arg1(dynamic a) → self::Sub
+    : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/rasta/super_initializer.dart:17:15: Error: Can't have initializers after 'super'.
+      : super.arg1(a),
+              ^", super self::Super::arg1(a)
+    ;
+  constructor arg2(dynamic a, dynamic b) → self::Sub
+    : final dynamic #t3 = invalid-expression "pkg/front_end/testcases/rasta/super_initializer.dart:20:15: Error: Can't have initializers after 'super'.
+      : super.arg2(a, b),
+              ^", super self::Super::arg2(a, b)
+    ;
+}
diff --git a/pkg/front_end/testcases/rasta/super_mixin.dart.direct.expect b/pkg/front_end/testcases/rasta/super_mixin.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/super_mixin.dart.direct.expect
rename to pkg/front_end/testcases/rasta/super_mixin.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/super_mixin.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/super_mixin.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/super_mixin.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/super_mixin.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/super_operator.dart.direct.expect b/pkg/front_end/testcases/rasta/super_operator.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/super_operator.dart.direct.expect
rename to pkg/front_end/testcases/rasta/super_operator.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/super_operator.dart.strong.expect b/pkg/front_end/testcases/rasta/super_operator.dart.strong.expect
new file mode 100644
index 0000000..152b391
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/super_operator.dart.strong.expect
@@ -0,0 +1,44 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/super_operator.dart:22:15: Error: Superclass has no method named '[]'.
+//   g() => super[0];
+//               ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/super_operator.dart:22:15: Error: Superclass has no method named '[]'.
+//   g() => super[0];
+//               ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator +(core::String s) → dynamic
+    return null;
+  operator [](dynamic i) → dynamic
+    return null;
+  operator []=(dynamic i, dynamic val) → void {}
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  operator +(core::String s) → dynamic
+    return super.{self::A::+}("${s}${s}");
+  operator [](dynamic i) → dynamic
+    return super.{self::A::[]}(i);
+  operator []=(dynamic i, dynamic val) → void
+    return let final dynamic #t1 = let final dynamic #t2 = i in let final dynamic #t3 = i = #t2.+(1) in #t2 in let final dynamic #t4 = super.{self::A::[]}(#t1).+(val) in let final void #t5 = super.{self::A::[]=}(#t1, #t4) in #t4;
+}
+class Autobianchi extends core::Object {
+  synthetic constructor •() → self::Autobianchi
+    : super core::Object::•()
+    ;
+  method g() → dynamic
+    return super.[](0);
+}
diff --git a/pkg/front_end/testcases/rasta/super_operator.dart.type_promotion.expect b/pkg/front_end/testcases/rasta/super_operator.dart.type_promotion.expect
new file mode 100644
index 0000000..a1bf30c
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/super_operator.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/rasta/super_operator.dart:18:34: Context: Write to i@401
+  operator []=(i, val) => super[i++] += val;
+                                 ^^
diff --git a/pkg/front_end/testcases/rasta/supports_reflection.dart.direct.expect b/pkg/front_end/testcases/rasta/supports_reflection.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/supports_reflection.dart.direct.expect
rename to pkg/front_end/testcases/rasta/supports_reflection.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/supports_reflection.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/supports_reflection.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/supports_reflection.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/supports_reflection.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.direct.expect b/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.direct.expect
rename to pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.strong.expect b/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.strong.expect
new file mode 100644
index 0000000..dd4fb5e
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.strong.expect
@@ -0,0 +1,89 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:35:5: Error: Switch case may fall through to the next case.
+//     case 2:  result = 2; /// static warning - case fall-through, see "Switch"
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:36:5: Error: Switch case may fall through to the next case.
+//     case 3:  result = 3; /// static warning - case fall-through, see "Switch"
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:46:5: Error: Switch case may fall through to the next case.
+//     case 1:
+//     ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:35:5: Error: Switch case may fall through to the next case.
+//     case 2:  result = 2; /// static warning - case fall-through, see "Switch"
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:36:5: Error: Switch case may fall through to the next case.
+//     case 3:  result = 3; /// static warning - case fall-through, see "Switch"
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:46:5: Error: Switch case may fall through to the next case.
+//     case 1:
+//     ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method test(dynamic value) → dynamic {
+  dynamic result;
+  #L1:
+  switch(value) {
+    #L2:
+    case 1:
+      {
+        result = 1;
+        break #L1;
+      }
+    #L3:
+    case 2:
+      {
+        result = 2;
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_execution_case_t02.dart", 35);
+      }
+    #L4:
+    case 3:
+      {
+        result = 3;
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_execution_case_t02.dart", 36);
+      }
+    #L5:
+    default:
+      {
+        result = 4;
+      }
+  }
+  return result;
+}
+static method testEmptyCases(dynamic value) → dynamic {
+  dynamic result;
+  #L6:
+  switch(value) {
+    #L7:
+    case 1:
+    case 2:
+      {
+        result = 1;
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_execution_case_t02.dart", 46);
+      }
+    #L8:
+    case 3:
+    case 4:
+      {
+        result = 2;
+        break #L6;
+      }
+    #L9:
+    case 5:
+    case 6:
+    default:
+      {}
+  }
+  return result;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.strong.transformed.expect
new file mode 100644
index 0000000..a0e9c4f
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.strong.transformed.expect
@@ -0,0 +1,75 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:35:5: Error: Switch case may fall through to the next case.
+//     case 2:  result = 2; /// static warning - case fall-through, see "Switch"
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:36:5: Error: Switch case may fall through to the next case.
+//     case 3:  result = 3; /// static warning - case fall-through, see "Switch"
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:46:5: Error: Switch case may fall through to the next case.
+//     case 1:
+//     ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method test(dynamic value) → dynamic {
+  dynamic result;
+  #L1:
+  switch(value) {
+    #L2:
+    case 1:
+      {
+        result = 1;
+        break #L1;
+      }
+    #L3:
+    case 2:
+      {
+        result = 2;
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_execution_case_t02.dart", 35);
+      }
+    #L4:
+    case 3:
+      {
+        result = 3;
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_execution_case_t02.dart", 36);
+      }
+    #L5:
+    default:
+      {
+        result = 4;
+      }
+  }
+  return result;
+}
+static method testEmptyCases(dynamic value) → dynamic {
+  dynamic result;
+  #L6:
+  switch(value) {
+    #L7:
+    case 1:
+    case 2:
+      {
+        result = 1;
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_execution_case_t02.dart", 46);
+      }
+    #L8:
+    case 3:
+    case 4:
+      {
+        result = 2;
+        break #L6;
+      }
+    #L9:
+    case 5:
+    case 6:
+    default:
+      {}
+  }
+  return result;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.type_promotion.expect b/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.type_promotion.expect
new file mode 100644
index 0000000..4aebb51
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/switch_execution_case_t02.dart.type_promotion.expect
@@ -0,0 +1,18 @@
+pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:33:21: Context: Write to result@1329
+    case 1:  result = 1;
+                    ^
+pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:35:21: Context: Write to result@1329
+    case 2:  result = 2; /// static warning - case fall-through, see "Switch"
+                    ^
+pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:36:21: Context: Write to result@1329
+    case 3:  result = 3; /// static warning - case fall-through, see "Switch"
+                    ^
+pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:37:21: Context: Write to result@1329
+    default: result = 4;
+                    ^
+pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:47:20: Context: Write to result@1636
+    case 2: result = 1; /// static warning - case fall-through, see "Switch"
+                   ^
+pkg/front_end/testcases/rasta/switch_execution_case_t02.dart:49:20: Context: Write to result@1636
+    case 4: result = 2;
+                   ^
diff --git a/pkg/front_end/testcases/rasta/switch_fall_through.dart.direct.expect b/pkg/front_end/testcases/rasta/switch_fall_through.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/switch_fall_through.dart.direct.expect
rename to pkg/front_end/testcases/rasta/switch_fall_through.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/switch_fall_through.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/switch_fall_through.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/switch_fall_through.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/switch_fall_through.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/switch_fall_through.dart.strong.expect b/pkg/front_end/testcases/rasta/switch_fall_through.dart.strong.expect
new file mode 100644
index 0000000..04d25f9
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/switch_fall_through.dart.strong.expect
@@ -0,0 +1,111 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:7:5: Error: Switch case may fall through to the next case.
+//     case 1:
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:13:5: Error: Switch case may fall through to the next case.
+//     case 2:
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:20:5: Error: Switch case may fall through to the next case.
+//     case 3:
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:26:5: Error: Switch case may fall through to the next case.
+//     case 4:
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:31:5: Error: Switch case may fall through to the next case.
+//     case 5:
+//     ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:7:5: Error: Switch case may fall through to the next case.
+//     case 1:
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:13:5: Error: Switch case may fall through to the next case.
+//     case 2:
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:20:5: Error: Switch case may fall through to the next case.
+//     case 3:
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:26:5: Error: Switch case may fall through to the next case.
+//     case 4:
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:31:5: Error: Switch case may fall through to the next case.
+//     case 5:
+//     ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  #L1:
+  switch(1) {
+    #L2:
+    case 1:
+      {
+        {
+          "No fall-through error needed.";
+          break #L1;
+          ;
+        }
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_fall_through.dart", 7);
+      }
+    #L3:
+    case 2:
+      {
+        {
+          "Fall-through error needed.";
+          if(true) {
+            break #L1;
+          }
+        }
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_fall_through.dart", 13);
+      }
+    #L4:
+    case 3:
+      {
+        try {
+          "No fall-through error needed.";
+        }
+        finally {
+          break #L1;
+        }
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_fall_through.dart", 20);
+      }
+    #L5:
+    case 4:
+      {
+        try {
+          "No fall-through error needed.";
+          break #L1;
+        }
+        finally {
+        }
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_fall_through.dart", 26);
+      }
+    #L6:
+    case 5:
+      {
+        try {
+          "Fall-through error needed.";
+        }
+        finally {
+        }
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_fall_through.dart", 31);
+      }
+    #L7:
+    case 10000:
+      {
+        "Should be last. No fall-through error, falling through allowed here.";
+      }
+  }
+}
diff --git a/pkg/front_end/testcases/rasta/switch_fall_through.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/switch_fall_through.dart.strong.transformed.expect
new file mode 100644
index 0000000..242d0e4
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/switch_fall_through.dart.strong.transformed.expect
@@ -0,0 +1,89 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:7:5: Error: Switch case may fall through to the next case.
+//     case 1:
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:13:5: Error: Switch case may fall through to the next case.
+//     case 2:
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:20:5: Error: Switch case may fall through to the next case.
+//     case 3:
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:26:5: Error: Switch case may fall through to the next case.
+//     case 4:
+//     ^
+//
+// pkg/front_end/testcases/rasta/switch_fall_through.dart:31:5: Error: Switch case may fall through to the next case.
+//     case 5:
+//     ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  #L1:
+  switch(1) {
+    #L2:
+    case 1:
+      {
+        {
+          "No fall-through error needed.";
+          break #L1;
+          ;
+        }
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_fall_through.dart", 7);
+      }
+    #L3:
+    case 2:
+      {
+        {
+          "Fall-through error needed.";
+          if(true) {
+            break #L1;
+          }
+        }
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_fall_through.dart", 13);
+      }
+    #L4:
+    case 3:
+      {
+        try {
+          "No fall-through error needed.";
+        }
+        finally {
+          break #L1;
+        }
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_fall_through.dart", 20);
+      }
+    #L5:
+    case 4:
+      {
+        try {
+          "No fall-through error needed.";
+          break #L1;
+        }
+        finally {
+        }
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_fall_through.dart", 26);
+      }
+    #L6:
+    case 5:
+      {
+        try {
+          "Fall-through error needed.";
+        }
+        finally {
+        }
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///switch_fall_through.dart", 31);
+      }
+    #L7:
+    case 10000:
+      {
+        "Should be last. No fall-through error, falling through allowed here.";
+      }
+  }
+}
diff --git a/pkg/front_end/testcases/rasta/this_invoke.dart.direct.expect b/pkg/front_end/testcases/rasta/this_invoke.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/this_invoke.dart.direct.expect
rename to pkg/front_end/testcases/rasta/this_invoke.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/this_invoke.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/this_invoke.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/this_invoke.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/this_invoke.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/this_invoke.dart.strong.expect b/pkg/front_end/testcases/rasta/this_invoke.dart.strong.expect
new file mode 100644
index 0000000..e025609
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/this_invoke.dart.strong.expect
@@ -0,0 +1,16 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  method m(dynamic x) → dynamic
+    return this.{self::C::call}(x);
+  method call(dynamic x) → dynamic
+    return 42;
+}
+static method main() → dynamic {
+  core::print(new self::C::•().{self::C::m}(42));
+}
diff --git a/pkg/front_end/testcases/rasta/this_invoke.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/this_invoke.dart.strong.transformed.expect
new file mode 100644
index 0000000..e025609
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/this_invoke.dart.strong.transformed.expect
@@ -0,0 +1,16 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  method m(dynamic x) → dynamic
+    return this.{self::C::call}(x);
+  method call(dynamic x) → dynamic
+    return 42;
+}
+static method main() → dynamic {
+  core::print(new self::C::•().{self::C::m}(42));
+}
diff --git a/pkg/front_end/testcases/rasta/try_label.dart.direct.expect b/pkg/front_end/testcases/rasta/try_label.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/try_label.dart.direct.expect
rename to pkg/front_end/testcases/rasta/try_label.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/try_label.dart.strong.expect b/pkg/front_end/testcases/rasta/try_label.dart.strong.expect
new file mode 100644
index 0000000..0f4e271
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/try_label.dart.strong.expect
@@ -0,0 +1,26 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/try_label.dart:9:5: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//     continue L;
+//     ^^^^^^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/try_label.dart:9:5: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//     continue L;
+//     ^^^^^^^^
+
+library;
+import self as self;
+
+static method main() → dynamic {
+  #L1:
+  try {
+    break #L1;
+  }
+  finally {
+    break #L1;
+  }
+}
diff --git a/pkg/front_end/testcases/rasta/try_label.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/try_label.dart.strong.transformed.expect
new file mode 100644
index 0000000..8de56dd
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/try_label.dart.strong.transformed.expect
@@ -0,0 +1,19 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/try_label.dart:9:5: Error: A continue statement can't be used outside of a loop or switch statement.
+// Try removing the continue statement.
+//     continue L;
+//     ^^^^^^^^
+
+library;
+import self as self;
+
+static method main() → dynamic {
+  #L1:
+  try {
+    break #L1;
+  }
+  finally {
+    break #L1;
+  }
+}
diff --git a/pkg/front_end/testcases/rasta/type_literals.dart.direct.expect b/pkg/front_end/testcases/rasta/type_literals.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/type_literals.dart.direct.expect
rename to pkg/front_end/testcases/rasta/type_literals.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/type_literals.dart.strong.expect b/pkg/front_end/testcases/rasta/type_literals.dart.strong.expect
new file mode 100644
index 0000000..a0834cd24
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/type_literals.dart.strong.expect
@@ -0,0 +1,521 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:22:5: Error: Method not found: 'dynamic'.
+//     dynamic();
+//     ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:23:9: Error: Method not found: 'dynamic'.
+//     use(dynamic());
+//         ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:24:5: Error: Method not found: 'T'.
+//     T();
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:25:9: Error: Method not found: 'T'.
+//     use(T());
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:26:5: Error: Method not found: 'Func'.
+//     Func();
+//     ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:27:9: Error: Method not found: 'Func'.
+//     use(Func());
+//         ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:29:5: Error: Setter not found: 'C'.
+//     C = 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:30:9: Error: Setter not found: 'C'.
+//     use(C = 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:31:5: Error: Setter not found: 'dynamic'.
+//     dynamic = 42;
+//     ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:32:9: Error: Setter not found: 'dynamic'.
+//     use(dynamic = 42);
+//         ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:33:5: Error: Setter not found: 'T'.
+//     T = 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:34:9: Error: Setter not found: 'T'.
+//     use(T = 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:35:5: Error: Setter not found: 'Func'.
+//     Func = 42;
+//     ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:36:9: Error: Setter not found: 'Func'.
+//     use(Func = 42);
+//         ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:38:5: Error: Setter not found: 'C'.
+//     C++;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:39:9: Error: Setter not found: 'C'.
+//     use(C++);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:40:5: Error: Setter not found: 'dynamic'.
+//     dynamic++;
+//     ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:41:9: Error: Setter not found: 'dynamic'.
+//     use(dynamic++);
+//         ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:42:5: Error: Setter not found: 'T'.
+//     T++;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:43:9: Error: Setter not found: 'T'.
+//     use(T++);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:44:5: Error: Setter not found: 'Func'.
+//     Func++;
+//     ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:45:9: Error: Setter not found: 'Func'.
+//     use(Func++);
+//         ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:47:7: Error: Setter not found: 'C'.
+//     ++C;
+//       ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:48:11: Error: Setter not found: 'C'.
+//     use(++C);
+//           ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:49:7: Error: Setter not found: 'dynamic'.
+//     ++dynamic;
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:50:11: Error: Setter not found: 'dynamic'.
+//     use(++dynamic);
+//           ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:51:7: Error: Setter not found: 'T'.
+//     ++T;
+//       ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:52:11: Error: Setter not found: 'T'.
+//     use(++T);
+//           ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:53:7: Error: Setter not found: 'Func'.
+//     ++Func;
+//       ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:54:11: Error: Setter not found: 'Func'.
+//     use(++Func);
+//           ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:56:5: Error: Setter not found: 'C'.
+//     C--;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:57:9: Error: Setter not found: 'C'.
+//     use(C--);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:58:5: Error: Setter not found: 'dynamic'.
+//     dynamic--;
+//     ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:59:9: Error: Setter not found: 'dynamic'.
+//     use(dynamic--);
+//         ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:60:5: Error: Setter not found: 'T'.
+//     T--;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:61:9: Error: Setter not found: 'T'.
+//     use(T--);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:62:5: Error: Setter not found: 'Func'.
+//     Func--;
+//     ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:63:9: Error: Setter not found: 'Func'.
+//     use(Func--);
+//         ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:65:7: Error: Setter not found: 'C'.
+//     --C;
+//       ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:66:11: Error: Setter not found: 'C'.
+//     use(--C);
+//           ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:67:7: Error: Setter not found: 'dynamic'.
+//     --dynamic;
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:68:11: Error: Setter not found: 'dynamic'.
+//     use(--dynamic);
+//           ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:69:7: Error: Setter not found: 'T'.
+//     --T;
+//       ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:70:11: Error: Setter not found: 'T'.
+//     use(--T);
+//           ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:71:7: Error: Setter not found: 'Func'.
+//     --Func;
+//       ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:72:11: Error: Setter not found: 'Func'.
+//     use(--Func);
+//           ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:74:5: Error: Setter not found: 'C'.
+//     C ??= 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:75:9: Error: Setter not found: 'C'.
+//     use(C ??= 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:76:5: Error: Setter not found: 'dynamic'.
+//     dynamic ??= 42;
+//     ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:77:9: Error: Setter not found: 'dynamic'.
+//     use(dynamic ??= 42);
+//         ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:78:5: Error: Setter not found: 'T'.
+//     T ??= 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:79:9: Error: Setter not found: 'T'.
+//     use(T ??= 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:80:5: Error: Setter not found: 'Func'.
+//     Func ??= 42;
+//     ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:81:9: Error: Setter not found: 'Func'.
+//     use(Func ??= 42);
+//         ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:83:5: Error: Setter not found: 'C'.
+//     C += 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:84:9: Error: Setter not found: 'C'.
+//     use(C += 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:85:5: Error: Setter not found: 'dynamic'.
+//     dynamic += 42;
+//     ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:86:9: Error: Setter not found: 'dynamic'.
+//     use(dynamic += 42);
+//         ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:87:5: Error: Setter not found: 'T'.
+//     T += 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:88:9: Error: Setter not found: 'T'.
+//     use(T += 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:89:5: Error: Setter not found: 'Func'.
+//     Func += 42;
+//     ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:90:9: Error: Setter not found: 'Func'.
+//     use(Func += 42);
+//         ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:92:5: Error: Setter not found: 'C'.
+//     C -= 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:93:9: Error: Setter not found: 'C'.
+//     use(C -= 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:94:5: Error: Setter not found: 'dynamic'.
+//     dynamic -= 42;
+//     ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:95:9: Error: Setter not found: 'dynamic'.
+//     use(dynamic -= 42);
+//         ^^^^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:96:5: Error: Setter not found: 'T'.
+//     T -= 42;
+//     ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:97:9: Error: Setter not found: 'T'.
+//     use(T -= 42);
+//         ^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:98:5: Error: Setter not found: 'Func'.
+//     Func -= 42;
+//     ^^^^
+//
+// pkg/front_end/testcases/rasta/type_literals.dart:99:9: Error: Setter not found: 'Func'.
+//     use(Func -= 42);
+//         ^^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Func = () → void;
+class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+  method test() → dynamic {
+    self::C<dynamic>;
+    self::use(self::C<dynamic>);
+    dynamic;
+    self::use(dynamic);
+    self::C::T;
+    self::use(self::C::T);
+    () → void;
+    self::use(() → void);
+    new self::C::•<dynamic>();
+    self::use(new self::C::•<dynamic>());
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:22:5: Error: Method not found: 'dynamic'.
+    dynamic();
+    ^^^^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:23:9: Error: Method not found: 'dynamic'.
+    use(dynamic());
+        ^^^^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:24:5: Error: Method not found: 'T'.
+    T();
+    ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:25:9: Error: Method not found: 'T'.
+    use(T());
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:26:5: Error: Method not found: 'Func'.
+    Func();
+    ^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:27:9: Error: Method not found: 'Func'.
+    use(Func());
+        ^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:29:5: Error: Setter not found: 'C'.
+    C = 42;
+    ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:30:9: Error: Setter not found: 'C'.
+    use(C = 42);
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:31:5: Error: Setter not found: 'dynamic'.
+    dynamic = 42;
+    ^^^^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:32:9: Error: Setter not found: 'dynamic'.
+    use(dynamic = 42);
+        ^^^^^^^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:33:5: Error: Setter not found: 'T'.
+    T = 42;
+    ^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:34:9: Error: Setter not found: 'T'.
+    use(T = 42);
+        ^");
+    invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:35:5: Error: Setter not found: 'Func'.
+    Func = 42;
+    ^^^^";
+    self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:36:9: Error: Setter not found: 'Func'.
+    use(Func = 42);
+        ^^^^");
+    let final dynamic #t1 = self::C<dynamic> in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:38:5: Error: Setter not found: 'C'.
+    C++;
+    ^";
+    self::use(let final dynamic #t2 = self::C<dynamic> in let final dynamic #t3 = #t2 in let final dynamic #t4 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:39:9: Error: Setter not found: 'C'.
+    use(C++);
+        ^" in #t3);
+    let final dynamic #t5 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:40:5: Error: Setter not found: 'dynamic'.
+    dynamic++;
+    ^^^^^^^";
+    self::use(let final dynamic #t6 = dynamic in let final dynamic #t7 = #t6 in let final dynamic #t8 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:41:9: Error: Setter not found: 'dynamic'.
+    use(dynamic++);
+        ^^^^^^^" in #t7);
+    let final dynamic #t9 = self::C::T in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:42:5: Error: Setter not found: 'T'.
+    T++;
+    ^";
+    self::use(let final dynamic #t10 = self::C::T in let final dynamic #t11 = #t10 in let final dynamic #t12 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:43:9: Error: Setter not found: 'T'.
+    use(T++);
+        ^" in #t11);
+    let final dynamic #t13 = () → void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:44:5: Error: Setter not found: 'Func'.
+    Func++;
+    ^^^^";
+    self::use(let final dynamic #t14 = () → void in let final dynamic #t15 = #t14 in let final dynamic #t16 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:45:9: Error: Setter not found: 'Func'.
+    use(Func++);
+        ^^^^" in #t15);
+    let final dynamic #t17 = self::C<dynamic> in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:47:7: Error: Setter not found: 'C'.
+    ++C;
+      ^";
+    self::use(let final dynamic #t18 = self::C<dynamic> in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:48:11: Error: Setter not found: 'C'.
+    use(++C);
+          ^");
+    let final dynamic #t19 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:49:7: Error: Setter not found: 'dynamic'.
+    ++dynamic;
+      ^^^^^^^";
+    self::use(let final dynamic #t20 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:50:11: Error: Setter not found: 'dynamic'.
+    use(++dynamic);
+          ^^^^^^^");
+    let final dynamic #t21 = self::C::T in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:51:7: Error: Setter not found: 'T'.
+    ++T;
+      ^";
+    self::use(let final dynamic #t22 = self::C::T in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:52:11: Error: Setter not found: 'T'.
+    use(++T);
+          ^");
+    let final dynamic #t23 = () → void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:53:7: Error: Setter not found: 'Func'.
+    ++Func;
+      ^^^^";
+    self::use(let final dynamic #t24 = () → void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:54:11: Error: Setter not found: 'Func'.
+    use(++Func);
+          ^^^^");
+    let final dynamic #t25 = self::C<dynamic> in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:56:5: Error: Setter not found: 'C'.
+    C--;
+    ^";
+    self::use(let final dynamic #t26 = self::C<dynamic> in let final dynamic #t27 = #t26 in let final dynamic #t28 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:57:9: Error: Setter not found: 'C'.
+    use(C--);
+        ^" in #t27);
+    let final dynamic #t29 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:58:5: Error: Setter not found: 'dynamic'.
+    dynamic--;
+    ^^^^^^^";
+    self::use(let final dynamic #t30 = dynamic in let final dynamic #t31 = #t30 in let final dynamic #t32 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:59:9: Error: Setter not found: 'dynamic'.
+    use(dynamic--);
+        ^^^^^^^" in #t31);
+    let final dynamic #t33 = self::C::T in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:60:5: Error: Setter not found: 'T'.
+    T--;
+    ^";
+    self::use(let final dynamic #t34 = self::C::T in let final dynamic #t35 = #t34 in let final dynamic #t36 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:61:9: Error: Setter not found: 'T'.
+    use(T--);
+        ^" in #t35);
+    let final dynamic #t37 = () → void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:62:5: Error: Setter not found: 'Func'.
+    Func--;
+    ^^^^";
+    self::use(let final dynamic #t38 = () → void in let final dynamic #t39 = #t38 in let final dynamic #t40 = invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:63:9: Error: Setter not found: 'Func'.
+    use(Func--);
+        ^^^^" in #t39);
+    let final dynamic #t41 = self::C<dynamic> in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:65:7: Error: Setter not found: 'C'.
+    --C;
+      ^";
+    self::use(let final dynamic #t42 = self::C<dynamic> in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:66:11: Error: Setter not found: 'C'.
+    use(--C);
+          ^");
+    let final dynamic #t43 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:67:7: Error: Setter not found: 'dynamic'.
+    --dynamic;
+      ^^^^^^^";
+    self::use(let final dynamic #t44 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:68:11: Error: Setter not found: 'dynamic'.
+    use(--dynamic);
+          ^^^^^^^");
+    let final dynamic #t45 = self::C::T in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:69:7: Error: Setter not found: 'T'.
+    --T;
+      ^";
+    self::use(let final dynamic #t46 = self::C::T in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:70:11: Error: Setter not found: 'T'.
+    use(--T);
+          ^");
+    let final dynamic #t47 = () → void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:71:7: Error: Setter not found: 'Func'.
+    --Func;
+      ^^^^";
+    self::use(let final dynamic #t48 = () → void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:72:11: Error: Setter not found: 'Func'.
+    use(--Func);
+          ^^^^");
+    let final dynamic #t49 = self::C<dynamic> in #t49.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:74:5: Error: Setter not found: 'C'.
+    C ??= 42;
+    ^" : null;
+    self::use(let final dynamic #t50 = self::C<dynamic> in let final dynamic #t51 = #t50 in #t51.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:75:9: Error: Setter not found: 'C'.
+    use(C ??= 42);
+        ^" : #t51);
+    let final dynamic #t52 = dynamic in #t52.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:76:5: Error: Setter not found: 'dynamic'.
+    dynamic ??= 42;
+    ^^^^^^^" : null;
+    self::use(let final dynamic #t53 = dynamic in let final dynamic #t54 = #t53 in #t54.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:77:9: Error: Setter not found: 'dynamic'.
+    use(dynamic ??= 42);
+        ^^^^^^^" : #t54);
+    let final dynamic #t55 = self::C::T in #t55.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:78:5: Error: Setter not found: 'T'.
+    T ??= 42;
+    ^" : null;
+    self::use(let final dynamic #t56 = self::C::T in let final dynamic #t57 = #t56 in #t57.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:79:9: Error: Setter not found: 'T'.
+    use(T ??= 42);
+        ^" : #t57);
+    let final dynamic #t58 = () → void in #t58.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:80:5: Error: Setter not found: 'Func'.
+    Func ??= 42;
+    ^^^^" : null;
+    self::use(let final dynamic #t59 = () → void in let final dynamic #t60 = #t59 in #t60.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:81:9: Error: Setter not found: 'Func'.
+    use(Func ??= 42);
+        ^^^^" : #t60);
+    let final dynamic #t61 = self::C<dynamic> in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:83:5: Error: Setter not found: 'C'.
+    C += 42;
+    ^";
+    self::use(let final dynamic #t62 = self::C<dynamic> in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:84:9: Error: Setter not found: 'C'.
+    use(C += 42);
+        ^");
+    let final dynamic #t63 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:85:5: Error: Setter not found: 'dynamic'.
+    dynamic += 42;
+    ^^^^^^^";
+    self::use(let final dynamic #t64 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:86:9: Error: Setter not found: 'dynamic'.
+    use(dynamic += 42);
+        ^^^^^^^");
+    let final dynamic #t65 = self::C::T in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:87:5: Error: Setter not found: 'T'.
+    T += 42;
+    ^";
+    self::use(let final dynamic #t66 = self::C::T in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:88:9: Error: Setter not found: 'T'.
+    use(T += 42);
+        ^");
+    let final dynamic #t67 = () → void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:89:5: Error: Setter not found: 'Func'.
+    Func += 42;
+    ^^^^";
+    self::use(let final dynamic #t68 = () → void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:90:9: Error: Setter not found: 'Func'.
+    use(Func += 42);
+        ^^^^");
+    let final dynamic #t69 = self::C<dynamic> in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:92:5: Error: Setter not found: 'C'.
+    C -= 42;
+    ^";
+    self::use(let final dynamic #t70 = self::C<dynamic> in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:93:9: Error: Setter not found: 'C'.
+    use(C -= 42);
+        ^");
+    let final dynamic #t71 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:94:5: Error: Setter not found: 'dynamic'.
+    dynamic -= 42;
+    ^^^^^^^";
+    self::use(let final dynamic #t72 = dynamic in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:95:9: Error: Setter not found: 'dynamic'.
+    use(dynamic -= 42);
+        ^^^^^^^");
+    let final dynamic #t73 = self::C::T in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:96:5: Error: Setter not found: 'T'.
+    T -= 42;
+    ^";
+    self::use(let final dynamic #t74 = self::C::T in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:97:9: Error: Setter not found: 'T'.
+    use(T -= 42);
+        ^");
+    let final dynamic #t75 = () → void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:98:5: Error: Setter not found: 'Func'.
+    Func -= 42;
+    ^^^^";
+    self::use(let final dynamic #t76 = () → void in invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:99:9: Error: Setter not found: 'Func'.
+    use(Func -= 42);
+        ^^^^");
+  }
+}
+static method use(dynamic x) → dynamic {
+  if(x.{core::Object::==}(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}))
+    throw "Shouldn't happen";
+}
+static method main() → dynamic {
+  new self::C::•<dynamic>().{self::C::test}();
+}
diff --git a/pkg/front_end/testcases/rasta/type_with_parse_error.dart.direct.expect b/pkg/front_end/testcases/rasta/type_with_parse_error.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/type_with_parse_error.dart.direct.expect
rename to pkg/front_end/testcases/rasta/type_with_parse_error.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/type_with_parse_error.dart.strong.expect b/pkg/front_end/testcases/rasta/type_with_parse_error.dart.strong.expect
new file mode 100644
index 0000000..fac7d19
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/type_with_parse_error.dart.strong.expect
@@ -0,0 +1,33 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/type_with_parse_error.dart:21:7: Error: Expected ';' after this.
+//   int i
+//       ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/type_with_parse_error.dart:21:7: Error: Expected ';' after this.
+//   int i
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {
+    new self::B::•<self::A>();
+  }
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  field core::int i = null;
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  new self::B::•<self::A>();
+}
diff --git a/pkg/front_end/testcases/rasta/type_with_parse_error.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/type_with_parse_error.dart.strong.transformed.expect
new file mode 100644
index 0000000..b8b11cc
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/type_with_parse_error.dart.strong.transformed.expect
@@ -0,0 +1,27 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/type_with_parse_error.dart:21:7: Error: Expected ';' after this.
+//   int i
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {
+    new self::B::•<self::A>();
+  }
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+  field core::int i = null;
+  synthetic constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  new self::B::•<self::A>();
+}
diff --git a/pkg/front_end/testcases/rasta/typedef.dart.direct.expect b/pkg/front_end/testcases/rasta/typedef.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/typedef.dart.direct.expect
rename to pkg/front_end/testcases/rasta/typedef.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/typedef.dart.strong.expect b/pkg/front_end/testcases/rasta/typedef.dart.strong.expect
new file mode 100644
index 0000000..6a68f69
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/typedef.dart.strong.expect
@@ -0,0 +1,31 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/typedef.dart:9:3: Error: Setter not found: 'Foo'.
+//   Foo = null;
+//   ^^^
+//
+// pkg/front_end/testcases/rasta/typedef.dart:10:3: Error: Setter not found: 'Foo'.
+//   Foo ??= null;
+//   ^^^
+//
+// pkg/front_end/testcases/rasta/typedef.dart:11:3: Error: Method not found: 'Foo'.
+//   Foo();
+//   ^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Foo = () → void;
+static method main() → dynamic {
+  core::print(() → void);
+  invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:9:3: Error: Setter not found: 'Foo'.
+  Foo = null;
+  ^^^";
+  let final dynamic #t1 = () → void in #t1.==(null) ? invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:10:3: Error: Setter not found: 'Foo'.
+  Foo ??= null;
+  ^^^" : null;
+  invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:11:3: Error: Method not found: 'Foo'.
+  Foo();
+  ^^^";
+}
diff --git a/pkg/front_end/testcases/rasta/unresolved.dart.direct.expect b/pkg/front_end/testcases/rasta/unresolved.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/unresolved.dart.direct.expect
rename to pkg/front_end/testcases/rasta/unresolved.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/unresolved.dart.strong.expect b/pkg/front_end/testcases/rasta/unresolved.dart.strong.expect
new file mode 100644
index 0000000..d596412
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/unresolved.dart.strong.expect
@@ -0,0 +1,14 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/unresolved.dart:6:7: Error: Method not found: 'Missing'.
+//   new Missing();
+//       ^^^^^^^
+
+library;
+import self as self;
+
+static method main() → dynamic {
+  invalid-expression "pkg/front_end/testcases/rasta/unresolved.dart:6:7: Error: Method not found: 'Missing'.
+  new Missing();
+      ^^^^^^^";
+}
diff --git a/pkg/front_end/testcases/rasta/unresolved.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/unresolved.dart.strong.transformed.expect
new file mode 100644
index 0000000..ffc54e6
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/unresolved.dart.strong.transformed.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+
+static method main() → dynamic {
+  invalid-expression "pkg/front_end/testcases/rasta/unresolved.dart:6:7: Error: Method not found: 'Missing'.
+  new Missing();
+      ^^^^^^^";
+}
diff --git a/pkg/front_end/testcases/rasta/unresolved_constructor.dart.direct.expect b/pkg/front_end/testcases/rasta/unresolved_constructor.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/unresolved_constructor.dart.direct.expect
rename to pkg/front_end/testcases/rasta/unresolved_constructor.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/unresolved_constructor.dart.strong.expect b/pkg/front_end/testcases/rasta/unresolved_constructor.dart.strong.expect
new file mode 100644
index 0000000..f97fa23
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/unresolved_constructor.dart.strong.expect
@@ -0,0 +1,30 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/unresolved_constructor.dart:10:10: Error: Too few positional arguments: 2 required, 0 given.
+//   new Foo();
+//          ^
+// pkg/front_end/testcases/rasta/unresolved_constructor.dart:6:3: Context: Found this candidate, but the arguments don't match.
+//   Foo(x, y);
+//   ^
+//
+// pkg/front_end/testcases/rasta/unresolved_constructor.dart:11:11: Error: Method not found: 'Foo.notHere'.
+//   new Foo.notHere();
+//           ^^^^^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •(dynamic x, dynamic y) → self::Foo
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  invalid-expression "pkg/front_end/testcases/rasta/unresolved_constructor.dart:10:10: Error: Too few positional arguments: 2 required, 0 given.
+  new Foo();
+         ^";
+  invalid-expression "pkg/front_end/testcases/rasta/unresolved_constructor.dart:11:11: Error: Method not found: 'Foo.notHere'.
+  new Foo.notHere();
+          ^^^^^^^";
+}
diff --git a/pkg/front_end/testcases/rasta/unresolved_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/unresolved_constructor.dart.strong.transformed.expect
new file mode 100644
index 0000000..80c63ba
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/unresolved_constructor.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •(dynamic x, dynamic y) → self::Foo
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  invalid-expression "pkg/front_end/testcases/rasta/unresolved_constructor.dart:10:10: Error: Too few positional arguments: 2 required, 0 given.
+  new Foo();
+         ^";
+  invalid-expression "pkg/front_end/testcases/rasta/unresolved_constructor.dart:11:11: Error: Method not found: 'Foo.notHere'.
+  new Foo.notHere();
+          ^^^^^^^";
+}
diff --git a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.direct.expect b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/unresolved_for_in.dart.direct.expect
rename to pkg/front_end/testcases/rasta/unresolved_for_in.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/unresolved_for_in.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/unresolved_for_in.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/rasta/unresolved_recovery.dart.direct.expect b/pkg/front_end/testcases/rasta/unresolved_recovery.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/unresolved_recovery.dart.direct.expect
rename to pkg/front_end/testcases/rasta/unresolved_recovery.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect b/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect
new file mode 100644
index 0000000..77aeb40
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect
@@ -0,0 +1,101 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:7:10: Error: Superclass has no method named '[]='.
+//     super[4] = 42;
+//          ^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:8:10: Error: Superclass has no method named '[]'.
+//     super[4] += 5;
+//          ^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:8:10: Error: Superclass has no method named '[]='.
+//     super[4] += 5;
+//          ^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:9:17: Error: Superclass has no method named '[]'.
+//     return super[2];
+//                 ^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:3: Error: 'on' isn't a type.
+//   on Exception catch (e) { }
+//   ^^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:6: Error: Expected ';' after this.
+//   on Exception catch (e) { }
+//      ^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:16: Error: Expected an identifier, but got 'catch'.
+//   on Exception catch (e) { }
+//                ^^^^^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:23: Error: Getter not found: 'e'.
+//   on Exception catch (e) { }
+//                       ^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:16: Error: Method not found: 'catch'.
+//   on Exception catch (e) { }
+//                ^^^^^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:24: Error: Expected ';' after this.
+//   on Exception catch (e) { }
+//                        ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:7:10: Error: Superclass has no method named '[]='.
+//     super[4] = 42;
+//          ^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:8:10: Error: Superclass has no method named '[]'.
+//     super[4] += 5;
+//          ^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:8:10: Error: Superclass has no method named '[]='.
+//     super[4] += 5;
+//          ^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:9:17: Error: Superclass has no method named '[]'.
+//     return super[2];
+//                 ^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:3: Error: 'on' isn't a type.
+//   on Exception catch (e) { }
+//   ^^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:6: Error: Expected ';' after this.
+//   on Exception catch (e) { }
+//      ^^^^^^^^^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:16: Error: Expected an identifier, but got 'catch'.
+//   on Exception catch (e) { }
+//                ^^^^^
+//
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:24: Error: Expected ';' after this.
+//   on Exception catch (e) { }
+//                        ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class E extends core::Object {
+  synthetic constructor •() → self::E
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {
+    super.[]=(4, 42);
+    let final core::int #t1 = 4 in super.[]=(#t1, super.[](#t1).+(5));
+    return super.[](2);
+  }
+}
+static method beforeTestMissingTry() → dynamic {
+  self::testMissingTry();
+}
+static method testMissingTry() → dynamic {
+  invalid-type Exception;
+  invalid-expression "pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:16: Error: Method not found: 'catch'.
+  on Exception catch (e) { }
+               ^^^^^";
+  {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/rasta/unsupported_platform_library.dart.direct.expect b/pkg/front_end/testcases/rasta/unsupported_platform_library.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/unsupported_platform_library.dart.direct.expect
rename to pkg/front_end/testcases/rasta/unsupported_platform_library.dart.legacy.expect
diff --git a/pkg/front_end/testcases/rasta/unsupported_platform_library.dart.direct.transformed.expect b/pkg/front_end/testcases/rasta/unsupported_platform_library.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/rasta/unsupported_platform_library.dart.direct.transformed.expect
rename to pkg/front_end/testcases/rasta/unsupported_platform_library.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/redirecting_constructor.dart.direct.expect b/pkg/front_end/testcases/redirecting_constructor.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_constructor.dart.direct.expect
rename to pkg/front_end/testcases/redirecting_constructor.dart.legacy.expect
diff --git a/pkg/front_end/testcases/redirecting_constructor.dart.direct.transformed.expect b/pkg/front_end/testcases/redirecting_constructor.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_constructor.dart.direct.transformed.expect
rename to pkg/front_end/testcases/redirecting_constructor.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/redirecting_constructor.dart.direct.expect b/pkg/front_end/testcases/redirecting_constructor.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/redirecting_constructor.dart.direct.expect
copy to pkg/front_end/testcases/redirecting_constructor.dart.strong.expect
diff --git a/pkg/front_end/testcases/redirecting_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/redirecting_constructor.dart.strong.transformed.expect
new file mode 100644
index 0000000..5376db1
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_constructor.dart.strong.transformed.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::A::fisk];
+  constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static factory fisk() → self::A
+    let<BottomType> #redirecting_factory = self::B::• in invalid-expression;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {
+  new self::B::•();
+}
diff --git a/pkg/front_end/testcases/redirecting_factory.dart.direct.expect b/pkg/front_end/testcases/redirecting_factory.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_factory.dart.direct.expect
rename to pkg/front_end/testcases/redirecting_factory.dart.legacy.expect
diff --git a/pkg/front_end/testcases/redirecting_factory.dart.strong.expect b/pkg/front_end/testcases/redirecting_factory.dart.strong.expect
index 5471c7c..84eb179 100644
--- a/pkg/front_end/testcases/redirecting_factory.dart.strong.expect
+++ b/pkg/front_end/testcases/redirecting_factory.dart.strong.expect
@@ -1,37 +1,74 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/redirecting_factory.dart:7:28: Error: The return type '#lib1::Foo<#lib1::FooBase::•::Tf>' of the constructor 'Foo' isn't a subtype of '#lib1::FooBase<#lib1::FooBase::•::Tf>'.
+// Try redirecting to a different constructor.
+//   factory FooBase(int x) = Foo<Tf>;
+//                            ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/redirecting_factory.dart:7:28: Error: The return type '#lib1::Foo<#lib1::FooBase::•::Tf>' of the constructor 'Foo' isn't a subtype of '#lib1::FooBase<#lib1::FooBase::•::Tf>'.
+// Try redirecting to a different constructor.
+//   factory FooBase(int x) = Foo<Tf>;
+//                            ^
+
 library;
 import self as self;
 import "dart:core" as core;
 
-abstract class FooBase<Tf extends core::Object> extends core::Object {
+abstract class FooBase<Tf extends core::Object = dynamic> extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::FooBase::•];
   abstract get x() → core::int;
+  static factory •<Tf extends core::Object = dynamic>(core::int x) → self::FooBase<self::FooBase::•::Tf>
+    let dynamic #redirecting_factory = self::Foo::• in let self::FooBase::•::Tf #typeArg0 = null in invalid-expression;
 }
-abstract class Foo<T extends core::Object> extends core::Object implements self::FooBase<dynamic> {
+abstract class Foo<T extends core::Object = dynamic> extends core::Object implements self::FooBase<dynamic> {
+  static field dynamic _redirecting# = <dynamic>[self::Foo::•];
+  static factory •<T extends core::Object = dynamic>(core::int x) → self::Foo<self::Foo::•::T>
+    let dynamic #redirecting_factory = self::Bar::• in let core::String #typeArg0 = null in let self::Foo::•::T #typeArg1 = null in invalid-expression;
 }
-class Bar<Sb extends core::Object, Tb extends core::Object> extends core::Object implements self::Foo<self::Bar::Tb> {
+class Bar<Sb extends core::Object = dynamic, Tb extends core::Object = dynamic> extends core::Object implements self::Foo<self::Bar::Tb> {
   field core::int x;
-  constructor •(core::int x) → void
+  constructor •(core::int x) → self::Bar<self::Bar::Sb, self::Bar::Tb>
     : self::Bar::x = x, super core::Object::•() {
     core::print("Bar<${self::Bar::Sb},${self::Bar::Tb}>");
   }
 }
-abstract class SimpleCase<A extends core::Object, B extends core::Object> extends core::Object {
+class Builder<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Builder<self::Builder::X>
+    : super core::Object::•()
+    ;
+  method method() → dynamic {
+    return new self::Bar::•<core::String, self::Builder::X>(4);
+  }
 }
-abstract class SimpleCaseImpl<Ai extends core::Object, Bi extends core::Object> extends core::Object implements self::SimpleCase<self::SimpleCaseImpl::Ai, self::SimpleCaseImpl::Bi> {
+class SimpleCase<A extends core::Object = dynamic, B extends core::Object = dynamic> extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::SimpleCase::•];
+  static factory •<A extends core::Object = dynamic, B extends core::Object = dynamic>() → self::SimpleCase<self::SimpleCase::•::A, self::SimpleCase::•::B>
+    let dynamic #redirecting_factory = self::SimpleCaseImpl::• in let self::SimpleCase::•::A #typeArg0 = null in let self::SimpleCase::•::B #typeArg1 = null in invalid-expression;
 }
-class SimpleCaseImpl2<Ai2 extends core::Object, Bi2 extends core::Object> extends core::Object implements self::SimpleCaseImpl<self::SimpleCaseImpl2::Ai2, self::SimpleCaseImpl2::Bi2> {
-  constructor •() → void
+class SimpleCaseImpl<Ai extends core::Object = dynamic, Bi extends core::Object = dynamic> extends core::Object implements self::SimpleCase<self::SimpleCaseImpl::Ai, self::SimpleCaseImpl::Bi> {
+  static field dynamic _redirecting# = <dynamic>[self::SimpleCaseImpl::•];
+  static factory •<Ai extends core::Object = dynamic, Bi extends core::Object = dynamic>() → self::SimpleCaseImpl<self::SimpleCaseImpl::•::Ai, self::SimpleCaseImpl::•::Bi>
+    let dynamic #redirecting_factory = self::SimpleCaseImpl2::• in let self::SimpleCaseImpl::•::Ai #typeArg0 = null in let self::SimpleCaseImpl::•::Bi #typeArg1 = null in invalid-expression;
+}
+class SimpleCaseImpl2<Ai2 extends core::Object = dynamic, Bi2 extends core::Object = dynamic> extends core::Object implements self::SimpleCaseImpl<self::SimpleCaseImpl2::Ai2, self::SimpleCaseImpl2::Bi2> {
+  synthetic constructor •() → self::SimpleCaseImpl2<self::SimpleCaseImpl2::Ai2, self::SimpleCaseImpl2::Bi2>
     : super core::Object::•()
     ;
 }
-abstract class Base<M extends core::Object> extends core::Object {
-  constructor •() → void
+class Base<M extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Base<self::Base::M>
     : super core::Object::•()
     ;
 }
-abstract class Mixin<M extends core::Object> extends core::Object {
+class Mixin<M extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Mixin<self::Mixin::M>
+    : super core::Object::•()
+    ;
 }
-class Mix<M extends core::Object> extends self::Base<self::Mix::M> implements self::Mixin<self::Mix::M> {
-  constructor •() → void
+class Mix<M extends core::Object = dynamic> = self::Base<self::Mix::M> with self::Mixin<self::Mix::M> {
+  synthetic constructor •() → self::Mix<self::Mix::M>
     : super self::Base::•()
     ;
 }
diff --git a/pkg/front_end/testcases/redirecting_factory.dart.strong.transformed.expect b/pkg/front_end/testcases/redirecting_factory.dart.strong.transformed.expect
new file mode 100644
index 0000000..c34ca34
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory.dart.strong.transformed.expect
@@ -0,0 +1,72 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/redirecting_factory.dart:7:28: Error: The return type '#lib1::Foo<#lib1::FooBase::•::Tf>' of the constructor 'Foo' isn't a subtype of '#lib1::FooBase<#lib1::FooBase::•::Tf>'.
+// Try redirecting to a different constructor.
+//   factory FooBase(int x) = Foo<Tf>;
+//                            ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class FooBase<Tf extends core::Object = dynamic> extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::FooBase::•];
+  abstract get x() → core::int;
+  static factory •<Tf extends core::Object = dynamic>(core::int x) → self::FooBase<self::FooBase::•::Tf>
+    let <T extends core::Object = dynamic>(core::int) → self::Foo<self::Foo::•::T> #redirecting_factory = self::Foo::• in let self::FooBase::•::Tf #typeArg0 = null in invalid-expression;
+}
+abstract class Foo<T extends core::Object = dynamic> extends core::Object implements self::FooBase<dynamic> {
+  static field dynamic _redirecting# = <dynamic>[self::Foo::•];
+  static factory •<T extends core::Object = dynamic>(core::int x) → self::Foo<self::Foo::•::T>
+    let<BottomType> #redirecting_factory = self::Bar::• in let core::String #typeArg0 = null in let self::Foo::•::T #typeArg1 = null in invalid-expression;
+}
+class Bar<Sb extends core::Object = dynamic, Tb extends core::Object = dynamic> extends core::Object implements self::Foo<self::Bar::Tb> {
+  field core::int x;
+  constructor •(core::int x) → self::Bar<self::Bar::Sb, self::Bar::Tb>
+    : self::Bar::x = x, super core::Object::•() {
+    core::print("Bar<${self::Bar::Sb},${self::Bar::Tb}>");
+  }
+}
+class Builder<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Builder<self::Builder::X>
+    : super core::Object::•()
+    ;
+  method method() → dynamic {
+    return new self::Bar::•<core::String, self::Builder::X>(4);
+  }
+}
+class SimpleCase<A extends core::Object = dynamic, B extends core::Object = dynamic> extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::SimpleCase::•];
+  static factory •<A extends core::Object = dynamic, B extends core::Object = dynamic>() → self::SimpleCase<self::SimpleCase::•::A, self::SimpleCase::•::B>
+    let <Ai extends core::Object = dynamic, Bi extends core::Object = dynamic>() → self::SimpleCaseImpl<self::SimpleCaseImpl::•::Ai, self::SimpleCaseImpl::•::Bi> #redirecting_factory = self::SimpleCaseImpl::• in let self::SimpleCase::•::A #typeArg0 = null in let self::SimpleCase::•::B #typeArg1 = null in invalid-expression;
+}
+class SimpleCaseImpl<Ai extends core::Object = dynamic, Bi extends core::Object = dynamic> extends core::Object implements self::SimpleCase<self::SimpleCaseImpl::Ai, self::SimpleCaseImpl::Bi> {
+  static field dynamic _redirecting# = <dynamic>[self::SimpleCaseImpl::•];
+  static factory •<Ai extends core::Object = dynamic, Bi extends core::Object = dynamic>() → self::SimpleCaseImpl<self::SimpleCaseImpl::•::Ai, self::SimpleCaseImpl::•::Bi>
+    let<BottomType> #redirecting_factory = self::SimpleCaseImpl2::• in let self::SimpleCaseImpl::•::Ai #typeArg0 = null in let self::SimpleCaseImpl::•::Bi #typeArg1 = null in invalid-expression;
+}
+class SimpleCaseImpl2<Ai2 extends core::Object = dynamic, Bi2 extends core::Object = dynamic> extends core::Object implements self::SimpleCaseImpl<self::SimpleCaseImpl2::Ai2, self::SimpleCaseImpl2::Bi2> {
+  synthetic constructor •() → self::SimpleCaseImpl2<self::SimpleCaseImpl2::Ai2, self::SimpleCaseImpl2::Bi2>
+    : super core::Object::•()
+    ;
+}
+class Base<M extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Base<self::Base::M>
+    : super core::Object::•()
+    ;
+}
+class Mixin<M extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::Mixin<self::Mixin::M>
+    : super core::Object::•()
+    ;
+}
+class Mix<M extends core::Object = dynamic> extends self::Base<self::Mix::M> implements self::Mixin<self::Mix::M> {
+  synthetic constructor •() → self::Mix<self::Mix::M>
+    : super self::Base::•()
+    ;
+}
+static method main() → dynamic {
+  core::print(new self::Bar::•<core::String, core::double>(4).{self::FooBase::x});
+  new self::SimpleCaseImpl2::•<core::int, core::double>();
+  new self::Mix::•<core::double>();
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_chain_test.dart.direct.expect b/pkg/front_end/testcases/redirecting_factory_chain_test.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_factory_chain_test.dart.direct.expect
rename to pkg/front_end/testcases/redirecting_factory_chain_test.dart.legacy.expect
diff --git a/pkg/front_end/testcases/redirecting_factory_chain_test.dart.strong.expect b/pkg/front_end/testcases/redirecting_factory_chain_test.dart.strong.expect
index fb200fc..1e1549a 100644
--- a/pkg/front_end/testcases/redirecting_factory_chain_test.dart.strong.expect
+++ b/pkg/front_end/testcases/redirecting_factory_chain_test.dart.strong.expect
@@ -3,11 +3,14 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  constructor •() → void
+  static field dynamic _redirecting# = <dynamic>[self::A::first, self::A::second];
+  constructor •() → self::A
     : super core::Object::•()
     ;
-  redirecting_factory first() = self::A::•;
-  redirecting_factory second() = self::A::first;
+  static factory first() → self::A
+    let dynamic #redirecting_factory = self::A::• in invalid-expression;
+  static factory second() → self::A
+    let dynamic #redirecting_factory = self::A::first in invalid-expression;
 }
 static method main() → dynamic {
   new self::A::•();
diff --git a/pkg/front_end/testcases/redirecting_factory_chain_test.dart.strong.transformed.expect b/pkg/front_end/testcases/redirecting_factory_chain_test.dart.strong.transformed.expect
new file mode 100644
index 0000000..eba9d32
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_chain_test.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library redirecting_factory_constructors.chain_test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::A::first, self::A::second];
+  constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static factory first() → self::A
+    let<BottomType> #redirecting_factory = self::A::• in invalid-expression;
+  static factory second() → self::A
+    let () → self::A #redirecting_factory = self::A::first in invalid-expression;
+}
+static method main() → dynamic {
+  new self::A::•();
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_const_inference.dart.direct.expect b/pkg/front_end/testcases/redirecting_factory_const_inference.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_factory_const_inference.dart.direct.expect
rename to pkg/front_end/testcases/redirecting_factory_const_inference.dart.legacy.expect
diff --git a/pkg/front_end/testcases/redirecting_factory_const_inference.dart.direct.transformed.expect b/pkg/front_end/testcases/redirecting_factory_const_inference.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_factory_const_inference.dart.direct.transformed.expect
rename to pkg/front_end/testcases/redirecting_factory_const_inference.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/redirecting_factory_metadata.dart.direct.expect b/pkg/front_end/testcases/redirecting_factory_metadata.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_factory_metadata.dart.direct.expect
rename to pkg/front_end/testcases/redirecting_factory_metadata.dart.legacy.expect
diff --git a/pkg/front_end/testcases/redirecting_factory_metadata.dart.direct.transformed.expect b/pkg/front_end/testcases/redirecting_factory_metadata.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_factory_metadata.dart.direct.transformed.expect
rename to pkg/front_end/testcases/redirecting_factory_metadata.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/redirecting_factory_simple_test.dart.direct.expect b/pkg/front_end/testcases/redirecting_factory_simple_test.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_factory_simple_test.dart.direct.expect
rename to pkg/front_end/testcases/redirecting_factory_simple_test.dart.legacy.expect
diff --git a/pkg/front_end/testcases/redirecting_factory_simple_test.dart.strong.expect b/pkg/front_end/testcases/redirecting_factory_simple_test.dart.strong.expect
index 2ea9699..45ed39e 100644
--- a/pkg/front_end/testcases/redirecting_factory_simple_test.dart.strong.expect
+++ b/pkg/front_end/testcases/redirecting_factory_simple_test.dart.strong.expect
@@ -3,10 +3,12 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  constructor •() → void
+  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  constructor •() → self::A
     : super core::Object::•()
     ;
-  redirecting_factory redir() = self::A::•;
+  static factory redir() → self::A
+    let dynamic #redirecting_factory = self::A::• in invalid-expression;
 }
 static method main() → dynamic {
   new self::A::•();
diff --git a/pkg/front_end/testcases/redirecting_factory_simple_test.dart.strong.transformed.expect b/pkg/front_end/testcases/redirecting_factory_simple_test.dart.strong.transformed.expect
new file mode 100644
index 0000000..f34fced
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_simple_test.dart.strong.transformed.expect
@@ -0,0 +1,15 @@
+library redirecting_factory_constructors.simple_test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static factory redir() → self::A
+    let<BottomType> #redirecting_factory = self::A::• in invalid-expression;
+}
+static method main() → dynamic {
+  new self::A::•();
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.direct.expect b/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.direct.expect
rename to pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.legacy.expect
diff --git a/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.strong.expect b/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.strong.expect
index 9c67c20..3c6fa9b 100644
--- a/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.strong.expect
+++ b/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.strong.expect
@@ -3,23 +3,25 @@
 import "dart:core" as core;
 
 class X extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::X
     : super core::Object::•()
     ;
 }
 class Y extends self::X {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::Y
     : super self::X::•()
     ;
 }
 class A extends core::Object {
-  constructor •() → void
+  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  constructor •() → self::A
     : super core::Object::•()
     ;
-  redirecting_factory redir() = self::B::•<self::Y>;
+  static factory redir() → self::A
+    let dynamic #redirecting_factory = self::B::• in let self::Y #typeArg0 = null in invalid-expression;
 }
-class B<T extends self::X> extends self::A {
-  constructor •() → void
+class B<T extends self::X = self::X> extends self::A {
+  constructor •() → self::B<self::B::T>
     : super self::A::•()
     ;
 }
diff --git a/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.strong.transformed.expect b/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.strong.transformed.expect
new file mode 100644
index 0000000..75b7a4f
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.strong.transformed.expect
@@ -0,0 +1,30 @@
+library redirecting_factory_constructors.typeargs_test;
+import self as self;
+import "dart:core" as core;
+
+class X extends core::Object {
+  synthetic constructor •() → self::X
+    : super core::Object::•()
+    ;
+}
+class Y extends self::X {
+  synthetic constructor •() → self::Y
+    : super self::X::•()
+    ;
+}
+class A extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static factory redir() → self::A
+    let<BottomType> #redirecting_factory = self::B::• in let self::Y #typeArg0 = null in invalid-expression;
+}
+class B<T extends self::X = self::X> extends self::A {
+  constructor •() → self::B<self::B::T>
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {
+  new self::B::•<self::Y>();
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.direct.expect b/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.direct.expect
rename to pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.legacy.expect
diff --git a/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.strong.expect b/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.strong.expect
index 8e10422..e36afbb 100644
--- a/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.strong.expect
+++ b/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.strong.expect
@@ -2,11 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class A<T extends core::Object, S extends core::Object> extends core::Object {
-  constructor •(self::A::T t, self::A::S s) → void
+class A<T extends core::Object = dynamic, S extends core::Object = dynamic> extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  constructor •(self::A::T t, self::A::S s) → self::A<self::A::T, self::A::S>
     : super core::Object::•()
     ;
-  redirecting_factory redir<T extends core::Object, S extends core::Object>(T t, S s) = self::A::•<T, S>;
+  static factory redir<T extends core::Object = dynamic, S extends core::Object = dynamic>(self::A::redir::T t, self::A::redir::S s) → self::A<self::A::redir::T, self::A::redir::S>
+    let dynamic #redirecting_factory = self::A::• in let self::A::redir::T #typeArg0 = null in let self::A::redir::S #typeArg1 = null in invalid-expression;
 }
 static method main() → dynamic {
   new self::A::•<core::int, core::String>(42, "foobar");
diff --git a/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.strong.transformed.expect b/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.strong.transformed.expect
new file mode 100644
index 0000000..d9346de
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.strong.transformed.expect
@@ -0,0 +1,15 @@
+library redirecting_factory_constructors.typeparam_test;
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object = dynamic, S extends core::Object = dynamic> extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  constructor •(self::A::T t, self::A::S s) → self::A<self::A::T, self::A::S>
+    : super core::Object::•()
+    ;
+  static factory redir<T extends core::Object = dynamic, S extends core::Object = dynamic>(self::A::redir::T t, self::A::redir::S s) → self::A<self::A::redir::T, self::A::redir::S>
+    let<BottomType> #redirecting_factory = self::A::• in let self::A::redir::T #typeArg0 = null in let self::A::redir::S #typeArg1 = null in invalid-expression;
+}
+static method main() → dynamic {
+  new self::A::•<core::int, core::String>(42, "foobar");
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.direct.expect b/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.direct.expect
rename to pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.legacy.expect
diff --git a/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.strong.expect b/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.strong.expect
index 278afdd..780300b 100644
--- a/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.strong.expect
+++ b/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.strong.expect
@@ -3,20 +3,22 @@
 import "dart:core" as core;
 
 class X extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::X
     : super core::Object::•()
     ;
 }
 class Y extends self::X {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::Y
     : super self::X::•()
     ;
 }
-class A<T extends core::Object, S extends self::A::T> extends core::Object {
-  constructor •(self::A::T t, self::A::S s) → void
+class A<T extends core::Object = dynamic, S extends self::A::T = dynamic> extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  constructor •(self::A::T t, self::A::S s) → self::A<self::A::T, self::A::S>
     : super core::Object::•()
     ;
-  redirecting_factory redir<T extends core::Object, S extends T>(T t, S s) = self::A::•<T, S>;
+  static factory redir<T extends core::Object = dynamic, S extends self::A::redir::T = dynamic>(self::A::redir::T t, self::A::redir::S s) → self::A<self::A::redir::T, self::A::redir::S>
+    let dynamic #redirecting_factory = self::A::• in let self::A::redir::T #typeArg0 = null in let self::A::redir::S #typeArg1 = null in invalid-expression;
 }
 static method main() → dynamic {
   new self::A::•<self::X, self::Y>(new self::X::•(), new self::Y::•());
diff --git a/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.strong.transformed.expect b/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.strong.transformed.expect
new file mode 100644
index 0000000..7d68623
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.strong.transformed.expect
@@ -0,0 +1,25 @@
+library redirecting_factory_constructors.typeparambounds_test;
+import self as self;
+import "dart:core" as core;
+
+class X extends core::Object {
+  synthetic constructor •() → self::X
+    : super core::Object::•()
+    ;
+}
+class Y extends self::X {
+  synthetic constructor •() → self::Y
+    : super self::X::•()
+    ;
+}
+class A<T extends core::Object = dynamic, S extends self::A::T = dynamic> extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  constructor •(self::A::T t, self::A::S s) → self::A<self::A::T, self::A::S>
+    : super core::Object::•()
+    ;
+  static factory redir<T extends core::Object = dynamic, S extends self::A::redir::T = dynamic>(self::A::redir::T t, self::A::redir::S s) → self::A<self::A::redir::T, self::A::redir::S>
+    let<BottomType> #redirecting_factory = self::A::• in let self::A::redir::T #typeArg0 = null in let self::A::redir::S #typeArg1 = null in invalid-expression;
+}
+static method main() → dynamic {
+  new self::A::•<self::X, self::Y>(new self::X::•(), new self::Y::•());
+}
diff --git a/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.direct.expect b/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.direct.expect
rename to pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.legacy.expect
diff --git a/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.direct.transformed.expect b/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.direct.transformed.expect
rename to pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.direct.expect b/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.direct.expect
rename to pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.legacy.expect
diff --git a/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.direct.transformed.expect b/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.direct.transformed.expect
rename to pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/redirection_chain_type_arguments.dart.direct.expect b/pkg/front_end/testcases/redirection_chain_type_arguments.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/redirection_chain_type_arguments.dart.direct.expect
rename to pkg/front_end/testcases/redirection_chain_type_arguments.dart.legacy.expect
diff --git a/pkg/front_end/testcases/redirection_chain_type_arguments.dart.direct.transformed.expect b/pkg/front_end/testcases/redirection_chain_type_arguments.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/redirection_chain_type_arguments.dart.direct.transformed.expect
rename to pkg/front_end/testcases/redirection_chain_type_arguments.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/redirection_chain_type_arguments_subst.dart.direct.expect b/pkg/front_end/testcases/redirection_chain_type_arguments_subst.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/redirection_chain_type_arguments_subst.dart.direct.expect
rename to pkg/front_end/testcases/redirection_chain_type_arguments_subst.dart.legacy.expect
diff --git a/pkg/front_end/testcases/redirection_chain_type_arguments_subst.dart.direct.transformed.expect b/pkg/front_end/testcases/redirection_chain_type_arguments_subst.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/redirection_chain_type_arguments_subst.dart.direct.transformed.expect
rename to pkg/front_end/testcases/redirection_chain_type_arguments_subst.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/redirection_type_arguments.dart.direct.expect b/pkg/front_end/testcases/redirection_type_arguments.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/redirection_type_arguments.dart.direct.expect
rename to pkg/front_end/testcases/redirection_type_arguments.dart.legacy.expect
diff --git a/pkg/front_end/testcases/redirection_type_arguments.dart.direct.transformed.expect b/pkg/front_end/testcases/redirection_type_arguments.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/redirection_type_arguments.dart.direct.transformed.expect
rename to pkg/front_end/testcases/redirection_type_arguments.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29937.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29937.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29937.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29937.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29937.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29937.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29937.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29937.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29940.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29940.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29940.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29940.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29940.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29940.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29940.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29940.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29941.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29941.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29941.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29941.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29941.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29941.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29941.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29941.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29942.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29942.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29942.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29942.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29942.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29942.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29942.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29942.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29943.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29943.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29943.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29943.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29943.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29943.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29943.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29943.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29944.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29944.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29944.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29944.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29944.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29944.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29944.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29944.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29945.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29945.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29945.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29945.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29945.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29945.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29945.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29945.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29975.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29975.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29975.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29975.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29975.dart.strong.expect b/pkg/front_end/testcases/regress/issue_29975.dart.strong.expect
index 2d292e2..93d444f 100644
--- a/pkg/front_end/testcases/regress/issue_29975.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_29975.dart.strong.expect
@@ -1,6 +1,15 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/regress/issue_29975.dart:6:14: Error: 'F' is already declared in this scope.
+// typedef void F();
+//              ^
+// pkg/front_end/testcases/regress/issue_29975.dart:5:14: Context: Previous declaration of 'F'.
+// typedef void F();
+//              ^
+
 // Unhandled errors:
 //
-// pkg/front_end/testcases/regress/issue_29975.dart:6:14: Error: Duplicated definition of 'F'.
+// pkg/front_end/testcases/regress/issue_29975.dart:6:14: Error: 'F' is already declared in this scope.
 // typedef void F();
 //              ^
 
@@ -8,5 +17,4 @@
 import self as self;
 
 typedef F = () → void;
-typedef F = () → void;
 static method main() → void {}
diff --git a/pkg/front_end/testcases/regress/issue_29975.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_29975.dart.strong.transformed.expect
new file mode 100644
index 0000000..6dc716b
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_29975.dart.strong.transformed.expect
@@ -0,0 +1,11 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/regress/issue_29975.dart:6:14: Error: 'F' is already declared in this scope.
+// typedef void F();
+//              ^
+
+library;
+import self as self;
+
+typedef F = () → void;
+static method main() → void {}
diff --git a/pkg/front_end/testcases/regress/issue_29976.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29976.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29976.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29976.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29976.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29976.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29976.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29976.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29977.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29977.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29977.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29977.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29977.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29977.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29977.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29977.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29978.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29978.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29978.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29978.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29978.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29978.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29978.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29978.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29979.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29979.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29979.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29979.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29979.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29979.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29979.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29979.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29980.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29980.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29980.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29980.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29980.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29980.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29980.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29980.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29981.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29981.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29981.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29981.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29981.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29981.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29981.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29981.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29982.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29982.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29982.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29982.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29982.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29982.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29982.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29982.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29983.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29983.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29983.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29983.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29983.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29983.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29983.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29983.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29984.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29984.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29984.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29984.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29984.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29984.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29984.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29984.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29985.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29985.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29985.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29985.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29985.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29985.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29985.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29985.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29986.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29986.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29986.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29986.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29986.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29986.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29986.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29986.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_29987.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29987.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29987.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_29987.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_29987.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29987.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_29987.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_29987.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_30834.dart.direct.expect b/pkg/front_end/testcases/regress/issue_30834.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_30834.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_30834.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_30834.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_30834.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_30834.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_30834.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_30836.dart.direct.expect b/pkg/front_end/testcases/regress/issue_30836.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_30836.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_30836.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_30836.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_30836.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_30836.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_30836.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.direct.expect b/pkg/front_end/testcases/regress/issue_30838.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_30838.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_30838.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_30838.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_30838.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_30838.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_30981.dart.direct.expect b/pkg/front_end/testcases/regress/issue_30981.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_30981.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_30981.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_30981.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_30981.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_30981.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_30981.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_30994.dart.direct.expect b/pkg/front_end/testcases/regress/issue_30994.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_30994.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_30994.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_30994.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_30994.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_30994.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_30994.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31155.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31155.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31155.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31155.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31155.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31155.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31155.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31155.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31157.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31157.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31157.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31157.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31157.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31157.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31157.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31157.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31171.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31171.dart.legacy.expect
similarity index 97%
rename from pkg/front_end/testcases/regress/issue_31171.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31171.dart.legacy.expect
index f3cb890..54e067f 100644
--- a/pkg/front_end/testcases/regress/issue_31171.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_31171.dart.legacy.expect
@@ -30,6 +30,6 @@
 import self as self;
 import "dart:core" as core;
 
-typedef T = dynamic;
+typedef T = invalid-type;
 typedef F = () → core::Map<core::String, dynamic>;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_31171.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31171.dart.legacy.transformed.expect
similarity index 95%
rename from pkg/front_end/testcases/regress/issue_31171.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31171.dart.legacy.transformed.expect
index f86e25c4..ad9b787 100644
--- a/pkg/front_end/testcases/regress/issue_31171.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31171.dart.legacy.transformed.expect
@@ -16,6 +16,6 @@
 import self as self;
 import "dart:core" as core;
 
-typedef T = dynamic;
+typedef T = invalid-type;
 typedef F = () → core::Map<core::String, dynamic>;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_31171.dart.outline.expect b/pkg/front_end/testcases/regress/issue_31171.dart.outline.expect
index b3c6998..772c92d 100644
--- a/pkg/front_end/testcases/regress/issue_31171.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_31171.dart.outline.expect
@@ -16,7 +16,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef T = dynamic;
+typedef T = invalid-type;
 typedef F = () → core::Map<core::String, dynamic>;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/regress/issue_31171.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31171.dart.strong.expect
index f3cb890..54e067f 100644
--- a/pkg/front_end/testcases/regress/issue_31171.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31171.dart.strong.expect
@@ -30,6 +30,6 @@
 import self as self;
 import "dart:core" as core;
 
-typedef T = dynamic;
+typedef T = invalid-type;
 typedef F = () → core::Map<core::String, dynamic>;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_31171.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31171.dart.strong.transformed.expect
index f86e25c4..ad9b787 100644
--- a/pkg/front_end/testcases/regress/issue_31171.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31171.dart.strong.transformed.expect
@@ -16,6 +16,6 @@
 import self as self;
 import "dart:core" as core;
 
-typedef T = dynamic;
+typedef T = invalid-type;
 typedef F = () → core::Map<core::String, dynamic>;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_31180.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31180.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31180.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31180.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31180.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31180.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31180.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31180.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31181.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31181.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31181.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31181.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31181.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31181.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31181.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31181.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31183.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31183.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31183.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31183.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31183.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31183.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31183.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31183.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31184.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31184.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31184.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31184.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31184.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31184.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31184.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31184.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31184.dart.type_promotion.expect b/pkg/front_end/testcases/regress/issue_31184.dart.type_promotion.expect
new file mode 100644
index 0000000..9514d8e
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_31184.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/regress/issue_31184.dart:6:28: Context: Write to i@243
+  for (int i = 0, i > 10; i++) {}
+                           ^^
diff --git a/pkg/front_end/testcases/regress/issue_31185.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31185.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31185.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31185.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31185.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31185.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31185.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31185.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31186.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31186.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31186.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31186.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31186.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31186.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31186.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31186.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31187.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31187.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31187.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31187.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31187.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31187.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31187.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31187.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31188.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31188.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31188.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31188.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31188.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31188.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31188.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31188.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31190.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31190.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31190.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31190.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31190.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31190.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31190.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31190.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31192.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31192.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31192.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31192.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31192.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31192.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31192.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31192.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31198.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31198.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31198.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31198.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31198.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31198.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31198.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31198.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31213.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31213.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31213.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31213.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31213.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31213.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31299.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31299.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31299.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31299.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31299.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31299.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31299.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31299.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31766.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31766.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31766.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31766.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31766.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31766.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31766.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31766.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31846.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31846.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31846.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31846.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31846.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31846.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31846.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31846.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_31996.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31996.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31996.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_31996.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_31996.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31996.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_31996.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_31996.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_32182.dart.direct.expect b/pkg/front_end/testcases/regress/issue_32182.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_32182.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_32182.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_32182.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_32182.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_32182.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_32182.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_32196.dart.direct.expect b/pkg/front_end/testcases/regress/issue_32196.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_32196.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_32196.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_32196.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_32196.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_32196.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_32196.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_32200.dart.direct.expect b/pkg/front_end/testcases/regress/issue_32200.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_32200.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_32200.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_32200.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_32200.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_32200.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_32200.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_32660.dart.direct.expect b/pkg/front_end/testcases/regress/issue_32660.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_32660.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_32660.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_32660.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_32660.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_32660.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_32660.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_32972.dart.direct.expect b/pkg/front_end/testcases/regress/issue_32972.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_32972.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_32972.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_32972.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_32972.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_32972.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_32972.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_33452.dart.direct.expect b/pkg/front_end/testcases/regress/issue_33452.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_33452.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_33452.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_33452.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_33452.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_33452.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_33452.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_33452.dart.type_promotion.expect b/pkg/front_end/testcases/regress/issue_33452.dart.type_promotion.expect
new file mode 100644
index 0000000..64406e2
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_33452.dart.type_promotion.expect
@@ -0,0 +1,15 @@
+pkg/front_end/testcases/regress/issue_33452.dart:11:5: Context: Write to x@296
+  x = new ExistingClass();
+    ^
+pkg/front_end/testcases/regress/issue_33452.dart:12:5: Context: Write to x@296
+  x = new ExistingClass<String>();
+    ^
+pkg/front_end/testcases/regress/issue_33452.dart:13:5: Context: Write to x@296
+  x = new ExistingClass<String>.nonExistingConstructor();
+    ^
+pkg/front_end/testcases/regress/issue_33452.dart:14:5: Context: Write to x@296
+  x = new ExistingClass<String, String>.nonExistingConstructor();
+    ^
+pkg/front_end/testcases/regress/issue_33452.dart:15:5: Context: Write to x@296
+  x = new NonExistingClass();
+    ^
diff --git a/pkg/front_end/testcases/regress/issue_33672.dart b/pkg/front_end/testcases/regress/issue_33672.dart
new file mode 100644
index 0000000..f302c8a
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_33672.dart
@@ -0,0 +1,15 @@
+// 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.
+
+main() {
+  int count = 0;
+  yield: for (int a = 0; a < 10; ++a) {
+    for (int b = 0; b < 10; ++b) {
+      ++count;
+      if (count == 27) break yield;
+    }
+    ++count;
+  }
+  if (count != 27) throw 'failed: $count';
+}
diff --git a/pkg/front_end/testcases/regress/issue_33672.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_33672.dart.legacy.expect
new file mode 100644
index 0000000..4f58db1
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_33672.dart.legacy.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::int count = 0;
+  #L1:
+  for (core::int a = 0; a.<(10); a = a.+(1)) {
+    for (core::int b = 0; b.<(10); b = b.+(1)) {
+      count = count.+(1);
+      if(count.==(27))
+        break #L1;
+    }
+    count = count.+(1);
+  }
+  if(!count.==(27))
+    throw "failed: ${count}";
+}
diff --git a/pkg/front_end/testcases/regress/issue_33672.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_33672.dart.legacy.transformed.expect
new file mode 100644
index 0000000..4f58db1
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_33672.dart.legacy.transformed.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::int count = 0;
+  #L1:
+  for (core::int a = 0; a.<(10); a = a.+(1)) {
+    for (core::int b = 0; b.<(10); b = b.+(1)) {
+      count = count.+(1);
+      if(count.==(27))
+        break #L1;
+    }
+    count = count.+(1);
+  }
+  if(!count.==(27))
+    throw "failed: ${count}";
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000045.dart.direct.expect b/pkg/front_end/testcases/regress/issue_33672.dart.outline.expect
similarity index 74%
copy from pkg/front_end/testcases/rasta/issue_000045.dart.direct.expect
copy to pkg/front_end/testcases/regress/issue_33672.dart.outline.expect
index 1cafd63..6a28c0d 100644
--- a/pkg/front_end/testcases/rasta/issue_000045.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_33672.dart.outline.expect
@@ -2,4 +2,4 @@
 import self as self;
 
 static method main() → dynamic
-  invalid-statement;
+  ;
diff --git a/pkg/front_end/testcases/regress/issue_33672.dart.strong.expect b/pkg/front_end/testcases/regress/issue_33672.dart.strong.expect
new file mode 100644
index 0000000..2a2bd06
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_33672.dart.strong.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::int count = 0;
+  #L1:
+  for (core::int a = 0; a.{core::num::<}(10); a = a.{core::num::+}(1)) {
+    for (core::int b = 0; b.{core::num::<}(10); b = b.{core::num::+}(1)) {
+      count = count.{core::num::+}(1);
+      if(count.{core::num::==}(27))
+        break #L1;
+    }
+    count = count.{core::num::+}(1);
+  }
+  if(!count.{core::num::==}(27))
+    throw "failed: ${count}";
+}
diff --git a/pkg/front_end/testcases/regress/issue_33672.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_33672.dart.strong.transformed.expect
new file mode 100644
index 0000000..2a2bd06
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_33672.dart.strong.transformed.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::int count = 0;
+  #L1:
+  for (core::int a = 0; a.{core::num::<}(10); a = a.{core::num::+}(1)) {
+    for (core::int b = 0; b.{core::num::<}(10); b = b.{core::num::+}(1)) {
+      count = count.{core::num::+}(1);
+      if(count.{core::num::==}(27))
+        break #L1;
+    }
+    count = count.{core::num::+}(1);
+  }
+  if(!count.{core::num::==}(27))
+    throw "failed: ${count}";
+}
diff --git a/pkg/front_end/testcases/regress/issue_33672.dart.type_promotion.expect b/pkg/front_end/testcases/regress/issue_33672.dart.type_promotion.expect
new file mode 100644
index 0000000..929bc26
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_33672.dart.type_promotion.expect
@@ -0,0 +1,12 @@
+pkg/front_end/testcases/regress/issue_33672.dart:7:34: Context: Write to a@260
+  yield: for (int a = 0; a < 10; ++a) {
+                                 ^^
+pkg/front_end/testcases/regress/issue_33672.dart:8:29: Context: Write to b@295
+    for (int b = 0; b < 10; ++b) {
+                            ^^
+pkg/front_end/testcases/regress/issue_33672.dart:9:7: Context: Write to count@231
+      ++count;
+      ^^
+pkg/front_end/testcases/regress/issue_33672.dart:12:5: Context: Write to count@231
+    ++count;
+    ^^
diff --git a/pkg/front_end/testcases/regress/issue_34225.dart.direct.expect b/pkg/front_end/testcases/regress/issue_34225.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_34225.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_34225.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_34225.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_34225.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_34225.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_34225.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_34291.dart.direct.expect b/pkg/front_end/testcases/regress/issue_34291.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_34291.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_34291.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_34291.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_34291.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_34291.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_34291.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_34403.dart.direct.expect b/pkg/front_end/testcases/regress/issue_34403.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_34403.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_34403.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_34403.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_34403.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_34403.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_34403.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_34498.dart.direct.expect b/pkg/front_end/testcases/regress/issue_34498.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_34498.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_34498.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_34498.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_34498.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_34498.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_34498.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_34563.dart.direct.expect b/pkg/front_end/testcases/regress/issue_34563.dart.legacy.expect
similarity index 88%
rename from pkg/front_end/testcases/regress/issue_34563.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_34563.dart.legacy.expect
index e878e85..5ff2161 100644
--- a/pkg/front_end/testcases/regress/issue_34563.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_34563.dart.legacy.expect
@@ -39,21 +39,12 @@
 import "dart:core" as core;
 
 abstract class M1 extends core::Object {
-  synthetic constructor •() → self::M1
-    : super core::Object::•()
-    ;
   get m() → core::int
     return 1;
 }
 abstract class M2 extends core::Object {
-  synthetic constructor •() → self::M2
-    : super core::Object::•()
-    ;
 }
 abstract class M3 extends core::Object {
-  synthetic constructor •() → self::M3
-    : super core::Object::•()
-    ;
 }
 class C1 extends core::Object {
   synthetic constructor •() → self::C1
diff --git a/pkg/front_end/testcases/regress/issue_34563.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_34563.dart.legacy.transformed.expect
similarity index 84%
rename from pkg/front_end/testcases/regress/issue_34563.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_34563.dart.legacy.transformed.expect
index 5e662e3..3e681c4 100644
--- a/pkg/front_end/testcases/regress/issue_34563.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_34563.dart.legacy.transformed.expect
@@ -21,21 +21,12 @@
 import "dart:core" as core;
 
 abstract class M1 extends core::Object {
-  synthetic constructor •() → self::M1
-    : super core::Object::•()
-    ;
   get m() → core::int
     return 1;
 }
 abstract class M2 extends core::Object {
-  synthetic constructor •() → self::M2
-    : super core::Object::•()
-    ;
 }
 abstract class M3 extends core::Object {
-  synthetic constructor •() → self::M3
-    : super core::Object::•()
-    ;
 }
 class C1 extends core::Object {
   synthetic constructor •() → self::C1
diff --git a/pkg/front_end/testcases/regress/issue_34563.dart.outline.expect b/pkg/front_end/testcases/regress/issue_34563.dart.outline.expect
index 8a53597..0b65eb9 100644
--- a/pkg/front_end/testcases/regress/issue_34563.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_34563.dart.outline.expect
@@ -21,18 +21,12 @@
 import "dart:core" as core;
 
 abstract class M1 extends core::Object {
-  synthetic constructor •() → self::M1
-    ;
   get m() → core::int
     ;
 }
 abstract class M2 extends core::Object {
-  synthetic constructor •() → self::M2
-    ;
 }
 abstract class M3 extends core::Object {
-  synthetic constructor •() → self::M3
-    ;
 }
 class C1 extends core::Object {
   synthetic constructor •() → self::C1
diff --git a/pkg/front_end/testcases/regress/issue_34563.dart.strong.expect b/pkg/front_end/testcases/regress/issue_34563.dart.strong.expect
index 03ab446..1f95d42 100644
--- a/pkg/front_end/testcases/regress/issue_34563.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_34563.dart.strong.expect
@@ -59,21 +59,12 @@
 import "dart:core" as core;
 
 abstract class M1 extends core::Object {
-  synthetic constructor •() → self::M1
-    : super core::Object::•()
-    ;
   get m() → core::int
     return 1;
 }
 abstract class M2 extends core::Object {
-  synthetic constructor •() → self::M2
-    : super core::Object::•()
-    ;
 }
 abstract class M3 extends core::Object {
-  synthetic constructor •() → self::M3
-    : super core::Object::•()
-    ;
 }
 class C1 extends core::Object {
   synthetic constructor •() → self::C1
diff --git a/pkg/front_end/testcases/regress/issue_34563.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_34563.dart.strong.transformed.expect
index 697afbc..0bc2713 100644
--- a/pkg/front_end/testcases/regress/issue_34563.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_34563.dart.strong.transformed.expect
@@ -21,21 +21,12 @@
 import "dart:core" as core;
 
 abstract class M1 extends core::Object {
-  synthetic constructor •() → self::M1
-    : super core::Object::•()
-    ;
   get m() → core::int
     return 1;
 }
 abstract class M2 extends core::Object {
-  synthetic constructor •() → self::M2
-    : super core::Object::•()
-    ;
 }
 abstract class M3 extends core::Object {
-  synthetic constructor •() → self::M3
-    : super core::Object::•()
-    ;
 }
 class C1 extends core::Object {
   synthetic constructor •() → self::C1
diff --git a/pkg/front_end/testcases/regress/issue_34610.dart b/pkg/front_end/testcases/regress/issue_34610.dart
new file mode 100644
index 0000000..09f61fa
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_34610.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A { get A.named => null; get bar => 1; }
+
+class B { B.named : super(); get bar => 1; }
+
+class C { C.named => null; get bar => 1; }
+
+main() {
+  print(new A().bar);
+  print(new B.named().bar);
+  try {
+    print(new C.named().bar);
+    throw 'expected exception';
+  } catch (e) {
+    // Expected Error: Constructors can't have a return type.
+  }
+}
diff --git a/pkg/front_end/testcases/regress/issue_34610.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_34610.dart.legacy.expect
new file mode 100644
index 0000000..ceb8d46
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_34610.dart.legacy.expect
@@ -0,0 +1,104 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:16: Error: Expected '{' before this.
+// class A { get A.named => null; get bar => 1; }
+//                ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:15: Error: A class member can't have the same name as the enclosing class.
+// class A { get A.named => null; get bar => 1; }
+//               ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:16: Error: Expected a class member, but got '.'.
+// class A { get A.named => null; get bar => 1; }
+//                ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:17: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class A { get A.named => null; get bar => 1; }
+//                 ^^^^^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:7:11: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class B { B.named : super(); get bar => 1; }
+//           ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:9:11: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class C { C.named => null; get bar => 1; }
+//           ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:9:22: Error: Constructors can't have a return type.
+// Try removing the return type.
+// class C { C.named => null; get bar => 1; }
+//                      ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:16: Error: Expected '{' before this.
+// class A { get A.named => null; get bar => 1; }
+//                ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:15: Error: A class member can't have the same name as the enclosing class.
+// class A { get A.named => null; get bar => 1; }
+//               ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:16: Error: Expected a class member, but got '.'.
+// class A { get A.named => null; get bar => 1; }
+//                ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:17: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class A { get A.named => null; get bar => 1; }
+//                 ^^^^^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:7:11: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class B { B.named : super(); get bar => 1; }
+//           ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:9:11: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class C { C.named => null; get bar => 1; }
+//           ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  get A() → dynamic {}
+  method named() → dynamic
+    return null;
+  get bar() → dynamic
+    return 1;
+}
+class B extends core::Object {
+  constructor named() → self::B
+    : super core::Object::•()
+    ;
+  get bar() → dynamic
+    return 1;
+}
+class C extends core::Object {
+  constructor named() → self::C
+    : super core::Object::•()
+    invalid-expression "pkg/front_end/testcases/regress/issue_34610.dart:9:22: Error: Constructors can't have a return type.
+Try removing the return type.
+class C { C.named => null; get bar => 1; }
+                     ^";
+  get bar() → dynamic
+    return 1;
+}
+static method main() → dynamic {
+  core::print(new self::A::•().bar);
+  core::print(new self::B::named().bar);
+  try {
+    core::print(new self::C::named().bar);
+    throw "expected exception";
+  }
+  on dynamic catch(final dynamic e) {
+  }
+}
diff --git a/pkg/front_end/testcases/regress/issue_34610.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_34610.dart.legacy.transformed.expect
new file mode 100644
index 0000000..fb45946
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_34610.dart.legacy.transformed.expect
@@ -0,0 +1,70 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:16: Error: Expected '{' before this.
+// class A { get A.named => null; get bar => 1; }
+//                ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:15: Error: A class member can't have the same name as the enclosing class.
+// class A { get A.named => null; get bar => 1; }
+//               ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:16: Error: Expected a class member, but got '.'.
+// class A { get A.named => null; get bar => 1; }
+//                ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:17: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class A { get A.named => null; get bar => 1; }
+//                 ^^^^^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:7:11: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class B { B.named : super(); get bar => 1; }
+//           ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:9:11: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class C { C.named => null; get bar => 1; }
+//           ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  get A() → dynamic {}
+  method named() → dynamic
+    return null;
+  get bar() → dynamic
+    return 1;
+}
+class B extends core::Object {
+  constructor named() → self::B
+    : super core::Object::•()
+    ;
+  get bar() → dynamic
+    return 1;
+}
+class C extends core::Object {
+  constructor named() → self::C
+    : super core::Object::•()
+    invalid-expression "pkg/front_end/testcases/regress/issue_34610.dart:9:22: Error: Constructors can't have a return type.
+Try removing the return type.
+class C { C.named => null; get bar => 1; }
+                     ^";
+  get bar() → dynamic
+    return 1;
+}
+static method main() → dynamic {
+  core::print(new self::A::•().bar);
+  core::print(new self::B::named().bar);
+  try {
+    core::print(new self::C::named().bar);
+    throw "expected exception";
+  }
+  on dynamic catch(final dynamic e) {
+  }
+}
diff --git a/pkg/front_end/testcases/regress/issue_34610.dart.outline.expect b/pkg/front_end/testcases/regress/issue_34610.dart.outline.expect
new file mode 100644
index 0000000..7e39069
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_34610.dart.outline.expect
@@ -0,0 +1,57 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:16: Error: Expected '{' before this.
+// class A { get A.named => null; get bar => 1; }
+//                ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:15: Error: A class member can't have the same name as the enclosing class.
+// class A { get A.named => null; get bar => 1; }
+//               ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:16: Error: Expected a class member, but got '.'.
+// class A { get A.named => null; get bar => 1; }
+//                ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:17: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class A { get A.named => null; get bar => 1; }
+//                 ^^^^^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:7:11: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class B { B.named : super(); get bar => 1; }
+//           ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:9:11: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class C { C.named => null; get bar => 1; }
+//           ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+  get A() → dynamic
+    ;
+  method named() → dynamic
+    ;
+  get bar() → dynamic
+    ;
+}
+class B extends core::Object {
+  constructor named() → self::B
+    ;
+  get bar() → dynamic
+    ;
+}
+class C extends core::Object {
+  constructor named() → self::C
+    ;
+  get bar() → dynamic
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/regress/issue_34610.dart.strong.expect b/pkg/front_end/testcases/regress/issue_34610.dart.strong.expect
new file mode 100644
index 0000000..568654c
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_34610.dart.strong.expect
@@ -0,0 +1,104 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:16: Error: Expected '{' before this.
+// class A { get A.named => null; get bar => 1; }
+//                ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:15: Error: A class member can't have the same name as the enclosing class.
+// class A { get A.named => null; get bar => 1; }
+//               ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:16: Error: Expected a class member, but got '.'.
+// class A { get A.named => null; get bar => 1; }
+//                ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:17: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class A { get A.named => null; get bar => 1; }
+//                 ^^^^^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:7:11: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class B { B.named : super(); get bar => 1; }
+//           ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:9:11: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class C { C.named => null; get bar => 1; }
+//           ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:9:22: Error: Constructors can't have a return type.
+// Try removing the return type.
+// class C { C.named => null; get bar => 1; }
+//                      ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:16: Error: Expected '{' before this.
+// class A { get A.named => null; get bar => 1; }
+//                ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:15: Error: A class member can't have the same name as the enclosing class.
+// class A { get A.named => null; get bar => 1; }
+//               ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:16: Error: Expected a class member, but got '.'.
+// class A { get A.named => null; get bar => 1; }
+//                ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:17: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class A { get A.named => null; get bar => 1; }
+//                 ^^^^^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:7:11: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class B { B.named : super(); get bar => 1; }
+//           ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:9:11: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class C { C.named => null; get bar => 1; }
+//           ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  get A() → dynamic {}
+  method named() → dynamic
+    return null;
+  get bar() → dynamic
+    return 1;
+}
+class B extends core::Object {
+  constructor named() → self::B
+    : super core::Object::•()
+    ;
+  get bar() → dynamic
+    return 1;
+}
+class C extends core::Object {
+  constructor named() → self::C
+    : super core::Object::•()
+    invalid-expression "pkg/front_end/testcases/regress/issue_34610.dart:9:22: Error: Constructors can't have a return type.
+Try removing the return type.
+class C { C.named => null; get bar => 1; }
+                     ^";
+  get bar() → dynamic
+    return 1;
+}
+static method main() → dynamic {
+  core::print(new self::A::•().{self::A::bar});
+  core::print(new self::B::named().{self::B::bar});
+  try {
+    core::print(new self::C::named().{self::C::bar});
+    throw "expected exception";
+  }
+  on dynamic catch(final dynamic e) {
+  }
+}
diff --git a/pkg/front_end/testcases/regress/issue_34610.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_34610.dart.strong.transformed.expect
new file mode 100644
index 0000000..ca2cebe
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_34610.dart.strong.transformed.expect
@@ -0,0 +1,70 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:16: Error: Expected '{' before this.
+// class A { get A.named => null; get bar => 1; }
+//                ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:15: Error: A class member can't have the same name as the enclosing class.
+// class A { get A.named => null; get bar => 1; }
+//               ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:16: Error: Expected a class member, but got '.'.
+// class A { get A.named => null; get bar => 1; }
+//                ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:5:17: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class A { get A.named => null; get bar => 1; }
+//                 ^^^^^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:7:11: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class B { B.named : super(); get bar => 1; }
+//           ^
+//
+// pkg/front_end/testcases/regress/issue_34610.dart:9:11: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+// class C { C.named => null; get bar => 1; }
+//           ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  get A() → dynamic {}
+  method named() → dynamic
+    return null;
+  get bar() → dynamic
+    return 1;
+}
+class B extends core::Object {
+  constructor named() → self::B
+    : super core::Object::•()
+    ;
+  get bar() → dynamic
+    return 1;
+}
+class C extends core::Object {
+  constructor named() → self::C
+    : super core::Object::•()
+    invalid-expression "pkg/front_end/testcases/regress/issue_34610.dart:9:22: Error: Constructors can't have a return type.
+Try removing the return type.
+class C { C.named => null; get bar => 1; }
+                     ^";
+  get bar() → dynamic
+    return 1;
+}
+static method main() → dynamic {
+  core::print(new self::A::•().{self::A::bar});
+  core::print(new self::B::named().{self::B::bar});
+  try {
+    core::print(new self::C::named().{self::C::bar});
+    throw "expected exception";
+  }
+  on dynamic catch(final dynamic e) {
+  }
+}
diff --git a/pkg/front_end/testcases/regress/issue_34614.dart.direct.expect b/pkg/front_end/testcases/regress/issue_34614.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_34614.dart.direct.expect
rename to pkg/front_end/testcases/regress/issue_34614.dart.legacy.expect
diff --git a/pkg/front_end/testcases/regress/issue_34614.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_34614.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/regress/issue_34614.dart.direct.transformed.expect
rename to pkg/front_end/testcases/regress/issue_34614.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/regress/issue_34850.dart b/pkg/front_end/testcases/regress/issue_34850.dart
new file mode 100644
index 0000000..052530e
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_34850.dart
@@ -0,0 +1,23 @@
+// 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.
+
+<foo<
+
+int f1() {
+  return null;
+}
+
+foo
+Future<List<int>> f2() async => null;
+
+Future<List<>> f3() async {
+  return null;
+}
+
+main() async {
+  print(f1());
+  print(await f2());
+  print(await f3());
+}
+
diff --git a/pkg/front_end/testcases/regress/issue_34850.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_34850.dart.legacy.expect
new file mode 100644
index 0000000..a866654
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_34850.dart.legacy.expect
@@ -0,0 +1,87 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:5:1: Error: Expected a declaration, but got '<'.
+// <foo<
+// ^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:7:1: Error: Expected '>' after this.
+// int f1() {
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:8: Error: Expected '>' after this.
+// Future<List<int>> f2() async => null;
+//        ^^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:1: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// Future<List<int>> f2() async => null;
+// ^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:19: Error: Expected '{' before this.
+// Future<List<int>> f2() async => null;
+//                   ^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:13: Error: Expected a type, but got '>>'.
+// Future<List<>> f3() async {
+//             ^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:5:2: Warning: Type 'foo' not found.
+// <foo<
+//  ^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:11:1: Warning: Type 'foo' not found.
+// foo
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:1: Warning: 'Future' isn't a type.
+// Future<List<>> f3() async {
+// ^^^^^^
+// pkg/front_end/testcases/regress/issue_34850.dart:12:1: Context: This isn't a type.
+// Future<List<int>> f2() async => null;
+// ^^^^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:5:1: Error: Expected a declaration, but got '<'.
+// <foo<
+// ^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:7:1: Error: Expected '>' after this.
+// int f1() {
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:8: Error: Expected '>' after this.
+// Future<List<int>> f2() async => null;
+//        ^^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:1: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// Future<List<int>> f2() async => null;
+// ^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:19: Error: Expected '{' before this.
+// Future<List<int>> f2() async => null;
+//                   ^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:13: Error: Expected a type, but got '>>'.
+// Future<List<>> f3() async {
+//             ^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method f1() → invalid-type {
+  return null;
+}
+static method Future<List extends core::Object = dynamic>() → invalid-type {}
+static method f2() → dynamic async 
+  return null;
+static method f3() → invalid-type async {
+  return null;
+}
+static method main() → dynamic async {
+  core::print(self::f1());
+  core::print(await self::f2());
+  core::print(await self::f3());
+}
diff --git a/pkg/front_end/testcases/regress/issue_34850.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_34850.dart.legacy.transformed.expect
new file mode 100644
index 0000000..2ae0673
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_34850.dart.legacy.transformed.expect
@@ -0,0 +1,121 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:5:1: Error: Expected a declaration, but got '<'.
+// <foo<
+// ^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:7:1: Error: Expected '>' after this.
+// int f1() {
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:8: Error: Expected '>' after this.
+// Future<List<int>> f2() async => null;
+//        ^^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:1: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// Future<List<int>> f2() async => null;
+// ^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:19: Error: Expected '{' before this.
+// Future<List<int>> f2() async => null;
+//                   ^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:13: Error: Expected a type, but got '>>'.
+// Future<List<>> f3() async {
+//             ^^
+
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+static method f1() → invalid-type {
+  return null;
+}
+static method Future<List extends core::Object = dynamic>() → invalid-type {}
+static method f2() → dynamic /* originally async */ {
+  final asy::Completer<dynamic> :async_completer = asy::Completer::sync<dynamic>();
+  asy::FutureOr<dynamic> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        :return_value = null;
+        break #L1;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method f3() → invalid-type /* originally async */ {
+  final asy::Completer<dynamic> :async_completer = asy::Completer::sync<dynamic>();
+  asy::FutureOr<dynamic> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        :return_value = null;
+        break #L2;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method main() → dynamic /* originally async */ {
+  final asy::Completer<dynamic> :async_completer = asy::Completer::sync<dynamic>();
+  asy::FutureOr<dynamic> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        core::print(self::f1());
+        [yield] let dynamic #t1 = asy::_awaitHelper(self::f2(), :async_op_then, :async_op_error, :async_op) in null;
+        core::print(:result);
+        [yield] let dynamic #t2 = asy::_awaitHelper(self::f3(), :async_op_then, :async_op_error, :async_op) in null;
+        core::print(:result);
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
diff --git a/pkg/front_end/testcases/regress/issue_34850.dart.outline.expect b/pkg/front_end/testcases/regress/issue_34850.dart.outline.expect
new file mode 100644
index 0000000..1bd0032
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_34850.dart.outline.expect
@@ -0,0 +1,56 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:5:1: Error: Expected a declaration, but got '<'.
+// <foo<
+// ^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:7:1: Error: Expected '>' after this.
+// int f1() {
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:8: Error: Expected '>' after this.
+// Future<List<int>> f2() async => null;
+//        ^^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:1: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// Future<List<int>> f2() async => null;
+// ^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:19: Error: Expected '{' before this.
+// Future<List<int>> f2() async => null;
+//                   ^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:13: Error: Expected a type, but got '>>'.
+// Future<List<>> f3() async {
+//             ^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:5:2: Warning: Type 'foo' not found.
+// <foo<
+//  ^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:11:1: Warning: Type 'foo' not found.
+// foo
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:1: Warning: 'Future' isn't a type.
+// Future<List<>> f3() async {
+// ^^^^^^
+// pkg/front_end/testcases/regress/issue_34850.dart:12:1: Context: This isn't a type.
+// Future<List<int>> f2() async => null;
+// ^^^^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method f1() → invalid-type
+  ;
+static method Future<List extends core::Object = dynamic>() → invalid-type
+  ;
+static method f2() → dynamic
+  ;
+static method f3() → invalid-type
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/regress/issue_34850.dart.strong.expect b/pkg/front_end/testcases/regress/issue_34850.dart.strong.expect
new file mode 100644
index 0000000..1f1bd88
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_34850.dart.strong.expect
@@ -0,0 +1,104 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:5:1: Error: Expected a declaration, but got '<'.
+// <foo<
+// ^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:7:1: Error: Expected '>' after this.
+// int f1() {
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:8: Error: Expected '>' after this.
+// Future<List<int>> f2() async => null;
+//        ^^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:1: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// Future<List<int>> f2() async => null;
+// ^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:19: Error: Expected '{' before this.
+// Future<List<int>> f2() async => null;
+//                   ^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:13: Error: Expected a type, but got '>>'.
+// Future<List<>> f3() async {
+//             ^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:5:2: Error: Expected 0 type arguments.
+// <foo<
+//  ^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:11:1: Error: Type 'foo' not found.
+// foo
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:1: Error: Expected 0 type arguments.
+// Future<List<>> f3() async {
+// ^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:16: Error: Functions marked 'async' must have a return type assignable to 'Future'.
+// Future<List<>> f3() async {
+//                ^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:5:1: Error: Expected a declaration, but got '<'.
+// <foo<
+// ^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:7:1: Error: Expected '>' after this.
+// int f1() {
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:8: Error: Expected '>' after this.
+// Future<List<int>> f2() async => null;
+//        ^^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:1: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// Future<List<int>> f2() async => null;
+// ^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:19: Error: Expected '{' before this.
+// Future<List<int>> f2() async => null;
+//                   ^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:13: Error: Expected a type, but got '>>'.
+// Future<List<>> f3() async {
+//             ^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:5:2: Error: Expected 0 type arguments.
+// <foo<
+//  ^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:11:1: Error: Type 'foo' not found.
+// foo
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:1: Error: Expected 0 type arguments.
+// Future<List<>> f3() async {
+// ^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:16: Error: Functions marked 'async' must have a return type assignable to 'Future'.
+// Future<List<>> f3() async {
+//                ^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+static method f1() → invalid-type {
+  return null;
+}
+static method Future<List extends core::Object = dynamic>() → invalid-type {}
+static method f2() → dynamic async 
+  return null;
+static method f3() → invalid-type async {
+  return null;
+}
+static method main() → dynamic async {
+  core::print(self::f1());
+  core::print(await self::f2());
+  core::print(await self::f3());
+}
diff --git a/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect
new file mode 100644
index 0000000..64ced99
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect
@@ -0,0 +1,137 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:5:1: Error: Expected a declaration, but got '<'.
+// <foo<
+// ^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:7:1: Error: Expected '>' after this.
+// int f1() {
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:8: Error: Expected '>' after this.
+// Future<List<int>> f2() async => null;
+//        ^^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:1: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// Future<List<int>> f2() async => null;
+// ^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:12:19: Error: Expected '{' before this.
+// Future<List<int>> f2() async => null;
+//                   ^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:13: Error: Expected a type, but got '>>'.
+// Future<List<>> f3() async {
+//             ^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:5:2: Error: Expected 0 type arguments.
+// <foo<
+//  ^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:11:1: Error: Type 'foo' not found.
+// foo
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:1: Error: Expected 0 type arguments.
+// Future<List<>> f3() async {
+// ^
+//
+// pkg/front_end/testcases/regress/issue_34850.dart:14:16: Error: Functions marked 'async' must have a return type assignable to 'Future'.
+// Future<List<>> f3() async {
+//                ^^
+
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+static method f1() → invalid-type {
+  return null;
+}
+static method Future<List extends core::Object = dynamic>() → invalid-type {}
+static method f2() → dynamic /* originally async */ {
+  final asy::Completer<dynamic> :async_completer = asy::Completer::sync<dynamic>();
+  asy::FutureOr<dynamic> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        :return_value = null;
+        break #L1;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method f3() → invalid-type /* originally async */ {
+  final asy::Completer<dynamic> :async_completer = asy::Completer::sync<dynamic>();
+  asy::FutureOr<dynamic> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        :return_value = null;
+        break #L2;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method main() → dynamic /* originally async */ {
+  final asy::Completer<dynamic> :async_completer = asy::Completer::sync<dynamic>();
+  asy::FutureOr<dynamic> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        core::print(self::f1());
+        [yield] let dynamic #t1 = asy::_awaitHelper(self::f2(), :async_op_then, :async_op_error, :async_op) in null;
+        core::print(:result);
+        [yield] let dynamic #t2 = asy::_awaitHelper(self::f3(), :async_op_then, :async_op_error, :async_op) in null;
+        core::print(:result);
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
diff --git a/pkg/front_end/testcases/regress/issue_35177.dart b/pkg/front_end/testcases/regress/issue_35177.dart
new file mode 100644
index 0000000..70ea0be
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_35177.dart
@@ -0,0 +1,8 @@
+// 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.
+
+main() {
+  dynamic Function() f;
+  (f)()<int>();
+}
diff --git a/pkg/front_end/testcases/regress/issue_35177.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_35177.dart.legacy.expect
new file mode 100644
index 0000000..67a4d3d
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_35177.dart.legacy.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  () → dynamic f;
+  f.call().call<core::int>();
+}
+
diff --git a/pkg/front_end/testcases/regress/issue_35177.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_35177.dart.legacy.transformed.expect
new file mode 100644
index 0000000..67a4d3d
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_35177.dart.legacy.transformed.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  () → dynamic f;
+  f.call().call<core::int>();
+}
+
diff --git a/pkg/front_end/testcases/rasta/issue_000045.dart.direct.expect b/pkg/front_end/testcases/regress/issue_35177.dart.outline.expect
similarity index 74%
copy from pkg/front_end/testcases/rasta/issue_000045.dart.direct.expect
copy to pkg/front_end/testcases/regress/issue_35177.dart.outline.expect
index 1cafd63..6a28c0d 100644
--- a/pkg/front_end/testcases/rasta/issue_000045.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_35177.dart.outline.expect
@@ -2,4 +2,4 @@
 import self as self;
 
 static method main() → dynamic
-  invalid-statement;
+  ;
diff --git a/pkg/front_end/testcases/regress/issue_35177.dart.strong.expect b/pkg/front_end/testcases/regress/issue_35177.dart.strong.expect
new file mode 100644
index 0000000..7e392f3
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_35177.dart.strong.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  () → dynamic f;
+  f.call().call<core::int>();
+}
diff --git a/pkg/front_end/testcases/regress/issue_35177.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_35177.dart.strong.transformed.expect
new file mode 100644
index 0000000..7e392f3
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_35177.dart.strong.transformed.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  () → dynamic f;
+  f.call().call<core::int>();
+}
diff --git a/pkg/front_end/testcases/reject_generic_function_types_in_bounds.dart.direct.expect b/pkg/front_end/testcases/reject_generic_function_types_in_bounds.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/reject_generic_function_types_in_bounds.dart.direct.expect
rename to pkg/front_end/testcases/reject_generic_function_types_in_bounds.dart.legacy.expect
diff --git a/pkg/front_end/testcases/reject_generic_function_types_in_bounds.dart.direct.transformed.expect b/pkg/front_end/testcases/reject_generic_function_types_in_bounds.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/reject_generic_function_types_in_bounds.dart.direct.transformed.expect
rename to pkg/front_end/testcases/reject_generic_function_types_in_bounds.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/return_with_unknown_type_in_context.dart.direct.expect b/pkg/front_end/testcases/return_with_unknown_type_in_context.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/return_with_unknown_type_in_context.dart.direct.expect
rename to pkg/front_end/testcases/return_with_unknown_type_in_context.dart.legacy.expect
diff --git a/pkg/front_end/testcases/return_with_unknown_type_in_context.dart.direct.transformed.expect b/pkg/front_end/testcases/return_with_unknown_type_in_context.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/return_with_unknown_type_in_context.dart.direct.transformed.expect
rename to pkg/front_end/testcases/return_with_unknown_type_in_context.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/call_kinds.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/call_kinds.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/call_kinds.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/call_kinds.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/call_kinds.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/call_kinds.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/call_kinds.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/call_kinds.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/call_kinds_get.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/call_kinds_get.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/call_kinds_get.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/call_kinds_get.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/call_kinds_get.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/call_kinds_get.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/call_kinds_get.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/call_kinds_get.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/call_kinds_set.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/call_kinds_set.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/call_kinds_set.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/call_kinds_set.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/call_kinds_set.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/call_kinds_set.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/call_kinds_set.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/call_kinds_set.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off_future_or.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off_future_or.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off_future_or.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off_future_or.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off_future_or.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off_future_or.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off_future_or.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/call_method_implicit_tear_off_future_or.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_field.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_method_type_parameter.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_method_type_parameter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_method_type_parameter.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_method_type_parameter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_method_type_parameter.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_method_type_parameter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_method_type_parameter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_method_type_parameter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_parameter.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_parameter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_parameter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_parameter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_complex.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_complex.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_complex.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_complex.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_complex.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_complex.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_complex.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_complex.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super_mixin.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super_mixin.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super_mixin.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super_mixin.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super_mixin.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super_mixin.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super_mixin.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super_mixin.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_keyword.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_keyword_field.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/covariant_keyword_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_keyword_field.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_keyword_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_keyword_field.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_keyword_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_keyword_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_keyword_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_keyword_field_inherited_by_setter.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/covariant_keyword_field_inherited_by_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_keyword_field_inherited_by_setter.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_keyword_field_inherited_by_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_keyword_field_inherited_by_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_keyword_field_inherited_by_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_keyword_field_inherited_by_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_keyword_field_inherited_by_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_keyword_setter.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/covariant_keyword_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_keyword_setter.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_keyword_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_keyword_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_keyword_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_keyword_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_keyword_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_keyword_setter_inherited_by_field.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/covariant_keyword_setter_inherited_by_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_keyword_setter_inherited_by_field.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_keyword_setter_inherited_by_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_keyword_setter_inherited_by_field.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_keyword_setter_inherited_by_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_keyword_setter_inherited_by_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_keyword_setter_inherited_by_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_setter.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/covariant_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/covariant_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/dynamic_invocation.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/dynamic_invocation.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/dynamic_invocation.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/dynamic_invocation.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/dynamic_invocation.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/dynamic_invocation.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/dynamic_invocation.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/dynamic_invocation.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/dynamic_invocation_generic.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/dynamic_invocation_generic.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/dynamic_invocation_generic.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/dynamic_invocation_generic.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/dynamic_invocation_generic.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/dynamic_invocation_generic.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/dynamic_invocation_generic.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/dynamic_invocation_generic.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/field_forwarding_stub_generic_covariant.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/field_forwarding_stub_generic_covariant.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/field_forwarding_stub_generic_covariant.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/field_forwarding_stub_generic_covariant.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/field_forwarding_stub_generic_covariant.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/field_forwarding_stub_generic_covariant.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/field_forwarding_stub_generic_covariant.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/field_forwarding_stub_generic_covariant.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/forwarding_stub_with_default_values.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/forwarding_stub_with_default_values.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/forwarding_stub_with_default_values.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/forwarding_stub_with_default_values.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/forwarding_stub_with_default_values.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/forwarding_stub_with_default_values.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/forwarding_stub_with_default_values.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/forwarding_stub_with_default_values.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/forwarding_stub_with_non_covariant_param.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/forwarding_stub_with_non_covariant_param.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/forwarding_stub_with_non_covariant_param.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/forwarding_stub_with_non_covariant_param.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/forwarding_stub_with_non_covariant_param.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/forwarding_stub_with_non_covariant_param.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/forwarding_stub_with_non_covariant_param.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/forwarding_stub_with_non_covariant_param.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/generic_covariance_inheritance_setter_field.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/generic_covariance_inheritance_setter_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/generic_covariance_inheritance_setter_field.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/generic_covariance_inheritance_setter_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/generic_covariance_inheritance_setter_field.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/generic_covariance_inheritance_setter_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/generic_covariance_inheritance_setter_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/generic_covariance_inheritance_setter_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/generic_vs_explicit_covariance.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/generic_vs_explicit_covariance.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/generic_vs_explicit_covariance.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/generic_vs_explicit_covariance.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/generic_vs_explicit_covariance.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/generic_vs_explicit_covariance.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/generic_vs_explicit_covariance.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/generic_vs_explicit_covariance.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_initializer.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_initializer.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_initializer.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_initializer.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_initializer.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_initializer.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_initializer.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_initializer.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_statement.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_statement.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_statement.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_statement.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_statement.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_statement.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_statement.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_assert_statement.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_constructor_initializer.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_constructor_initializer.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_constructor_initializer.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_constructor_initializer.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_constructor_initializer.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_constructor_initializer.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_constructor_initializer.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_constructor_initializer.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_do.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_do.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_do.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_do.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_do.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_do.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_do.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_do.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart.type_promotion.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart.type_promotion.expect
new file mode 100644
index 0000000..77d54c8
--- /dev/null
+++ b/pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/runtime_checks/implicit_downcast_for_condition.dart:11:25: Context: Write to i@310
+    for (int i = 0; o; i++) {}
+                        ^^
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_if.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_if.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_if.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_if.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_if.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_if.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_if.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_if.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_not.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_not.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_not.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_not.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_not.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_not.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_not.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_not.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_while.dart.direct.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_while.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_while.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_while.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks/implicit_downcast_while.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks/implicit_downcast_while.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks/implicit_downcast_while.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks/implicit_downcast_while.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/call_through_this.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.type_promotion.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.type_promotion.expect
new file mode 100644
index 0000000..d9c1892
--- /dev/null
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart:22:44: Context: Write to b@535
+  b /*@checkReturn=B<num, (num) -> void>*/ += 1;
+                                           ^^
+pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart:23:52: Context: Write to b@535
+  var x = b /*@checkReturn=B<num, (num) -> void>*/ += 2;
+                                                   ^^
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.type_promotion.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.type_promotion.expect
new file mode 100644
index 0000000..52a0161
--- /dev/null
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart:51:5: Context: Write to d@1119
+  d = new D(new C(numToNum));
+    ^
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/contravariant_index_get.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/derived_class_typed.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/derived_class_typed.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/derived_class_typed.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/derived_class_typed.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/derived_class_typed.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/derived_class_typed.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/derived_class_typed.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/derived_class_typed.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_abstract_generic_covariant.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_abstract_generic_covariant.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_abstract_generic_covariant.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_abstract_generic_covariant.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_abstract_generic_covariant.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_abstract_generic_covariant.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_abstract_generic_covariant.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_abstract_generic_covariant.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/generic_covariance_based_on_inference.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/implicit_downcast_field.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/implicit_downcast_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/implicit_downcast_field.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/implicit_downcast_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/implicit_downcast_field.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/implicit_downcast_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/implicit_downcast_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/implicit_downcast_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
index 4932edda..d31ff90 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
@@ -1,7 +1,7 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:48:7: Error: The return type of the method 'M::y' is dart.core::int, which does not match the return type of the overridden method (dart.core::Object).
-// Change to a subtype of dart.core::Object.
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:48:7: Error: The return type of the method 'M::y' is 'dart.core::int', which does not match the return type of the overridden method, 'dart.core::Object'.
+// Change to a subtype of 'dart.core::Object'.
 //   int y;
 //       ^
 // pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:43:12: Context: This is the overridden method ('y').
@@ -13,8 +13,8 @@
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:48:7: Error: The return type of the method 'M::y' is dart.core::int, which does not match the return type of the overridden method (dart.core::Object).
-// Change to a subtype of dart.core::Object.
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:48:7: Error: The return type of the method 'M::y' is 'dart.core::int', which does not match the return type of the overridden method, 'dart.core::Object'.
+// Change to a subtype of 'dart.core::Object'.
 //   int y;
 //       ^
 
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.transformed.expect
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
index e47b16c..9cc1b92 100644
--- 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
@@ -1,7 +1,7 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:39:9: Error: The return type of the method 'M::x' is (test::C::T) → void, which does not match the return type of the overridden method ((dart.core::int) → void).
-// Change to a subtype of (dart.core::int) → void.
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:39:9: Error: The return type of the method 'M::x' is '(test::C::T) → void', which does not match the return type of the overridden method, '(dart.core::int) → void'.
+// Change to a subtype of '(dart.core::int) → void'.
 //   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').
@@ -13,8 +13,8 @@
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:39:9: Error: The return type of the method 'M::x' is (test::C::T) → void, which does not match the return type of the overridden method ((dart.core::int) → void).
-// Change to a subtype of (dart.core::int) → void.
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:39:9: Error: The return type of the method 'M::x' is '(test::C::T) → void', which does not match the return type of the overridden method, '(dart.core::int) → void'.
+// Change to a subtype of '(dart.core::int) → void'.
 //   T get x => f();
 //         ^
 
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
index 923fd4c..9e06293 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
@@ -1,7 +1,7 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:53:18: Error: The parameter 'value' of the method 'M::y' has type dart.core::int, which does not match the corresponding type in the overridden method (dart.core::Object).
-// Change to a supertype of dart.core::Object (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:53:18: Error: The parameter 'value' of the method 'M::y' has type 'dart.core::int', which does not match the corresponding type in the overridden method, 'dart.core::Object'.
+// Change to a supertype of 'dart.core::Object', or, for a covariant parameter, a subtype.
 //   void set y(int value) {
 //                  ^
 // pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:43:12: Context: This is the overridden method ('y').
@@ -13,8 +13,8 @@
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:53:18: Error: The parameter 'value' of the method 'M::y' has type dart.core::int, which does not match the corresponding type in the overridden method (dart.core::Object).
-// Change to a supertype of dart.core::Object (or, for a covariant parameter, a subtype).
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:53:18: Error: The parameter 'value' of the method 'M::y' has type 'dart.core::int', which does not match the corresponding type in the overridden method, 'dart.core::Object'.
+// Change to a supertype of 'dart.core::Object', or, for a covariant parameter, a subtype.
 //   void set y(int value) {
 //                  ^
 
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_interface.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_interface.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_interface.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_interface.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_interface.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_interface.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_interface.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_interface.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_super.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_super.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_super.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_super.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_super.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_super.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_super.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_super.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_interface.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_interface.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_interface.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_interface.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_interface.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_interface.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_interface.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_interface.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_super.dart.direct.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_super.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_super.dart.direct.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_super.dart.legacy.expect
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_super.dart.direct.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_super.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_super.dart.direct.transformed.expect
rename to pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariant_from_super.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/statements.dart.direct.expect b/pkg/front_end/testcases/statements.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/statements.dart.direct.expect
rename to pkg/front_end/testcases/statements.dart.legacy.expect
diff --git a/pkg/front_end/testcases/statements.dart.strong.expect b/pkg/front_end/testcases/statements.dart.strong.expect
new file mode 100644
index 0000000..308cb85
--- /dev/null
+++ b/pkg/front_end/testcases/statements.dart.strong.expect
@@ -0,0 +1,178 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/statements.dart:15:5: Error: 'yield' can only be used in 'sync*' or 'async*' methods.
+//     yield x;
+//     ^^^^^
+//
+// pkg/front_end/testcases/statements.dart:16:5: Error: 'yield' can only be used in 'sync*' or 'async*' methods.
+//     yield* x;
+//     ^^^^^
+//
+// pkg/front_end/testcases/statements.dart:14:23: Error: The type 'dart.core::List<dynamic>' used in the 'for' loop must implement 'dart.async::Stream<dynamic>'.
+//   await for (var x in []) {
+//                       ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/statements.dart:15:5: Error: 'yield' can only be used in 'sync*' or 'async*' methods.
+//     yield x;
+//     ^^^^^
+//
+// pkg/front_end/testcases/statements.dart:16:5: Error: 'yield' can only be used in 'sync*' or 'async*' methods.
+//     yield* x;
+//     ^^^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+static method foo() → dynamic {
+  try {
+    return;
+  }
+  finally {
+    core::print("Hello from finally block!");
+  }
+}
+static method bar() → dynamic async {
+  await for (dynamic x in let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/statements.dart:14:23: Error: The type 'dart.core::List<dynamic>' used in the 'for' loop must implement 'dart.async::Stream<dynamic>'.
+  await for (var x in []) {
+                      ^" in <dynamic>[] as{TypeError} asy::Stream<dynamic>) {
+    yield x;
+    yield* x;
+  }
+}
+static method main() → dynamic {
+  do {
+    core::print("Hello from do-while!");
+  }
+  while (false)
+  do {
+    void x = core::print("Hello from do-while!");
+  }
+  while (false)
+  for (core::String s in <core::String>["Hello from for-in!"]) {
+    core::print(s);
+  }
+  for (core::String s in <core::String>["Hello from for-in without block!"])
+    core::print(s);
+  dynamic s;
+  for (final dynamic #t2 in <dynamic>["Hello from for-in without decl!"]) {
+    s = #t2;
+    core::print(s);
+  }
+  for (final dynamic #t3 in <dynamic>["Hello from for-in without decl and block!"]) {
+    s = #t3;
+    core::print(s);
+  }
+  core::print("Hello from labeled statement!");
+  try {
+    try {
+      throw "Hello from rethrow!";
+    }
+    on dynamic catch(final dynamic e) {
+      rethrow;
+    }
+  }
+  on dynamic catch(final dynamic e) {
+    core::print(e);
+  }
+  self::foo();
+  core::bool done = false;
+  while (!done) {
+    done = true;
+    core::print("Hello from while!");
+  }
+  ;
+  assert(true);
+  assert(true, "Hello from assert!");
+  try {
+    assert(false, "Hello from assert!");
+  }
+  on dynamic catch(final dynamic e) {
+    core::print(e);
+  }
+  #L1:
+  switch(1) {
+    #L2:
+    case 1:
+    case 2:
+      {
+        core::print("Hello from switch case!");
+        break #L1;
+      }
+    #L3:
+    default:
+      {
+        break #L1;
+      }
+  }
+  #L4:
+  switch(4) {
+    #L5:
+    case 2:
+      {
+        core::print("Hello from case 2!");
+        break #L4;
+      }
+    #L6:
+    case 1:
+      {
+        core::print("Hello from case 1!");
+        continue #L5;
+      }
+    #L7:
+    case 0:
+      {
+        core::print("Hello from case 0!");
+        continue #L6;
+      }
+    #L8:
+    case 4:
+      {
+        core::print("Hello from case 4!");
+        continue #L9;
+      }
+    #L9:
+    default:
+      {
+        continue #L7;
+      }
+  }
+  #L10:
+  switch(4) {
+    #L11:
+    case 1:
+      {
+        core::print("Hello from next case 1");
+        break #L10;
+      }
+    #L12:
+    default:
+      {
+        continue #L11;
+      }
+  }
+  core::int i = 0;
+  #L13:
+  do
+    #L14:
+    {
+      core::print("Hello from do-while!");
+      if((i = i.{core::num::+}(1)).{core::num::<}(3))
+        break #L14;
+      break #L13;
+    }
+  while (true)
+  i = 0;
+  #L15:
+  while (true)
+    #L16:
+    {
+      core::print("Hello from while!");
+      if((i = i.{core::num::+}(1)).{core::num::<}(3))
+        break #L16;
+      break #L15;
+    }
+}
diff --git a/pkg/front_end/testcases/statements.dart.type_promotion.expect b/pkg/front_end/testcases/statements.dart.type_promotion.expect
new file mode 100644
index 0000000..f1b6150
--- /dev/null
+++ b/pkg/front_end/testcases/statements.dart.type_promotion.expect
@@ -0,0 +1,12 @@
+pkg/front_end/testcases/statements.dart:50:10: Context: Write to done@988
+    done = true;
+         ^
+pkg/front_end/testcases/statements.dart:95:9: Context: Write to i@1814
+    if (++i < 3) continue;
+        ^^
+pkg/front_end/testcases/statements.dart:98:5: Context: Write to i@1814
+  i = 0;
+    ^
+pkg/front_end/testcases/statements.dart:101:9: Context: Write to i@1814
+    if (++i < 3) continue OUTER;
+        ^^
diff --git a/pkg/front_end/testcases/static_setter.dart.direct.expect b/pkg/front_end/testcases/static_setter.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/static_setter.dart.direct.expect
rename to pkg/front_end/testcases/static_setter.dart.legacy.expect
diff --git a/pkg/front_end/testcases/static_setter.dart.direct.transformed.expect b/pkg/front_end/testcases/static_setter.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/static_setter.dart.direct.transformed.expect
rename to pkg/front_end/testcases/static_setter.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/store_load.dart.direct.expect b/pkg/front_end/testcases/store_load.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/store_load.dart.direct.expect
rename to pkg/front_end/testcases/store_load.dart.legacy.expect
diff --git a/pkg/front_end/testcases/store_load.dart.direct.transformed.expect b/pkg/front_end/testcases/store_load.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/store_load.dart.direct.transformed.expect
rename to pkg/front_end/testcases/store_load.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/stringliteral.dart.direct.expect b/pkg/front_end/testcases/stringliteral.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/stringliteral.dart.direct.expect
rename to pkg/front_end/testcases/stringliteral.dart.legacy.expect
diff --git a/pkg/front_end/testcases/stringliteral.dart.direct.transformed.expect b/pkg/front_end/testcases/stringliteral.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/stringliteral.dart.direct.transformed.expect
rename to pkg/front_end/testcases/stringliteral.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/stringliteral.dart.strong.expect b/pkg/front_end/testcases/stringliteral.dart.strong.expect
index bef6d48..fd90ff9 100644
--- a/pkg/front_end/testcases/stringliteral.dart.strong.expect
+++ b/pkg/front_end/testcases/stringliteral.dart.strong.expect
@@ -1,4 +1,17 @@
 library;
 import self as self;
+import "dart:core" as core;
 
+static field core::String color = "brown";
+static field core::String thing = "lazy dog";
+static field core::String phrase = "The quick ${self::color} fox
+jumped over the ${self::thing}.
+";
+static field core::String adjacent = "${self::color}${self::color}${self::color}";
+static field core::String linebreaks = "${self::color}
+${self::color}
+${self::color}";
+static field core::String other = "${self::color}
+ is 
+${self::color}";
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/stringliteral.dart.strong.transformed.expect b/pkg/front_end/testcases/stringliteral.dart.strong.transformed.expect
new file mode 100644
index 0000000..fd90ff9
--- /dev/null
+++ b/pkg/front_end/testcases/stringliteral.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static field core::String color = "brown";
+static field core::String thing = "lazy dog";
+static field core::String phrase = "The quick ${self::color} fox
+jumped over the ${self::thing}.
+";
+static field core::String adjacent = "${self::color}${self::color}${self::color}";
+static field core::String linebreaks = "${self::color}
+${self::color}
+${self::color}";
+static field core::String other = "${self::color}
+ is 
+${self::color}";
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index f42496b..6a2266f 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -6,63 +6,47 @@
 # Kernel ASTs directly, that is, code in pkg/fasta/lib/src/kernel/ with
 # strong-mode enabled.
 
-DeltaBlue: Fail
-accessors: Fail
+accessors: RuntimeError
 ambiguous_exports: RuntimeError # Expected, this file exports two main methods.
-argument_mismatch: Fail # Test assumes Dart 1.0 semantics
-async_function: Fail
-await: Fail
+argument_mismatch: InstrumentationMismatch # Test assumes Dart 1.0 semantics
 bug21938: TypeCheckError
 bug30695: TypeCheckError
 bug31124: RuntimeError # Test has no main method (and we shouldn't add one).
-bug32629: Fail # Test has an intentional error
-call: Fail
-cascade: Fail
-casts: Fail
-classes: Fail
-closure: Fail
+bug32629: InstrumentationMismatch # Test has an intentional error
+call: TypeCheckError
+cascade: RuntimeError
 constructor_initializer_invalid: RuntimeError # Fails execution after recovery
-covariant_generic: Fail
-cycles: Fail
-default_values: Fail
+covariant_generic: RuntimeError
 duplicated_declarations: TypeCheckError
-dynamic_and_void: Fail # Test assumes Dart 1.0 semantics
-escape: Fail
+duplicated_field_initializer: RuntimeError
+dynamic_and_void: InstrumentationMismatch # Test assumes Dart 1.0 semantics
 expressions: RuntimeError
-external: Fail
 external_import: RuntimeError # The native extension to import doesn't exist. This is ok.
-fallthrough: Fail
-fibonacci: Fail
-for_in_scope: Fail
-function_in_field: Fail
-function_type_recovery: Fail
-functions: Fail
-hello: Fail
-implicit_this: Fail
-incomplete_field_formal_parameter: Fail # Fasta doesn't recover well
-inference/abstract_class_instantiation: Fail # Issue #30040
+fallthrough: ExpectationFileMismatch
+incomplete_field_formal_parameter: RuntimeError
+inference/abstract_class_instantiation: InstrumentationMismatch # Issue #30040
 inference/conflicts_can_happen: TypeCheckError
 inference/conflicts_can_happen2: TypeCheckError
 inference/constructors_infer_from_arguments_argument_not_assignable: TypeCheckError
-inference/constructors_too_many_positional_arguments: Fail # Issue #30040
+inference/constructors_too_many_positional_arguments: InstrumentationMismatch # Issue #30040
 inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer: TypeCheckError
-inference/downwards_inference_annotations_type_variable: Fail # Issue 28981
-inference/downwards_inference_on_function_of_t_using_the_t: Fail # Issue #29798
+inference/downwards_inference_annotations_type_variable: InstrumentationMismatch # Issue 28981
+inference/downwards_inference_on_function_of_t_using_the_t: InstrumentationMismatch # Issue #29798
 inference/downwards_inference_on_list_literals_infer_downwards: RuntimeError
-inference/future_then_explicit_future: Fail # Issue #30040
+inference/future_then_explicit_future: InstrumentationMismatch # Issue #30040
 inference/future_then_upwards: RuntimeError
 inference/future_then_upwards_2: RuntimeError
-inference/generic_functions_return_typedef: Fail # Issue #29798
+inference/generic_functions_return_typedef: InstrumentationMismatch # Issue #29798
 inference/generic_methods_correctly_recognize_generic_upper_bound: TypeCheckError
 inference/generic_methods_do_not_infer_invalid_override_of_generic_method: TypeCheckError
 inference/generic_methods_handle_override_of_non_generic_with_generic: TypeCheckError
-inference/generic_methods_infer_js_builtin: Fail # Issue #30029
+inference/generic_methods_infer_js_builtin: InstrumentationMismatch # Issue #30029
 inference/infer_field_override_multiple: TypeCheckError
 inference/infer_method_missing_params: TypeCheckError
 inference/infer_type_regardless_of_declaration_order_or_cycles: RuntimeError
 inference/infer_types_on_generic_instantiations_4: RuntimeError
 inference/infer_types_on_generic_instantiations_infer: TypeCheckError
-inference/instantiate_tearoff_of_call: Fail # Issue #31746
+inference/instantiate_tearoff_of_call: TypeCheckError # Issue #31746
 inference/instantiate_to_bounds_generic_has_bound_defined_after transform: RuntimeError
 inference/mixin_inference_outwards_3: TypeCheckError
 inference/mixin_inference_outwards_4: TypeCheckError
@@ -70,10 +54,10 @@
 inference/mixin_inference_unification_2: TypeCheckError
 inference/override_equals: RuntimeError
 inference/unresolved_super: TypeCheckError
-inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1: Fail # Issue #25824
-inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2: Fail # Issue #25824
-inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1: Fail # Issue #25824
-inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2: Fail # Issue #25824
+inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1: InstrumentationMismatch # Issue #25824
+inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2: InstrumentationMismatch # Issue #25824
+inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1: InstrumentationMismatch # Issue #25824
+inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2: InstrumentationMismatch # Issue #25824
 inference_new/infer_assign_to_index_super_upwards: TypeCheckError
 inference_new/infer_assign_to_index_this_upwards: TypeCheckError
 inference_new/infer_assign_to_index_upwards: TypeCheckError
@@ -81,115 +65,64 @@
 inference_new/infer_field_getter_setter_mismatch: TypeCheckError
 inference_new/infer_field_override_getter_overrides_setter: TypeCheckError
 inference_new/invalid_assignment_during_toplevel_inference: TypeCheckError
-instantiate_to_bound/body_typedef_super_bounded_type: Fail # Issue 33444
-instantiate_to_bound/typedef_super_bounded_type: Fail # Issue 33444
 invalid_type: TypeCheckError
-invocations: Fail
+invocations: RuntimeError
 issue34899: TypeCheckError
-literals: Fail
-map: Fail
-micro: Fail
+micro: RuntimeError
 mixin_application_override: TypeCheckError
-named_parameters: Fail
-null_aware: Fail
-operators: Fail
-optional: Fail
+optional: TypeCheckError
 override_check_accessor_after_inference: TypeCheckError # Issue #31620
 override_check_accessor_basic: TypeCheckError # Issue #31620
 override_check_accessor_with_covariant_modifier: TypeCheckError # Issue #31620
 override_check_after_inference: TypeCheckError # Issue #31620
 override_check_basic: TypeCheckError # Issue #31620
 override_check_with_covariant_modifier: TypeCheckError # Issue #31620
-platform: Fail
-prefer_baseclass: Fail
-rasta/abstract_constructor: Fail
-rasta/bad_constructor_redirection: Fail
-rasta/bad_continue: Fail
-rasta/bad_default_constructor: Fail
+rasta/abstract_constructor: RuntimeError
+rasta/bad_constructor_redirection: RuntimeError
+rasta/bad_continue: RuntimeError
+rasta/bad_default_constructor: VerificationError
 rasta/bad_explicit_super_constructor: RuntimeError
-rasta/bad_implicit_super_constructor: Fail
-rasta/bad_interpolation: Fail
-rasta/bad_redirection: Fail
-rasta/bad_setter_initializer: Fail
-rasta/bad_unicode: Fail
-rasta/breaking_bad: Fail
-rasta/cascades: Fail
-rasta/class_hierarchy: Fail
-rasta/class_member: Fail
-rasta/constant_get_and_invoke: Fail
-rasta/deferred_lib: Fail
-rasta/deferred_load: Fail
+rasta/bad_implicit_super_constructor: RuntimeError
+rasta/bad_interpolation: RuntimeError
+rasta/bad_redirection: RuntimeError
+rasta/bad_setter_initializer: RuntimeError
+rasta/breaking_bad: RuntimeError
+rasta/class_hierarchy: RuntimeError
+rasta/class_member: RuntimeError
+rasta/constant_get_and_invoke: RuntimeError
 rasta/duplicated_mixin: RuntimeError # Expected, this file has no main method.
-rasta/enum: Fail
 rasta/export: RuntimeError # Expected, this file has no main method.
-rasta/external_factory_redirection: Fail
 rasta/foo: RuntimeError # Expected, this file has no main method.
-rasta/for_loop: Fail
-rasta/generic_factory: Fail
-rasta/hello: Fail
-rasta/issue_000001: Fail
-rasta/issue_000002: Fail
-rasta/issue_000004: Fail
-rasta/issue_000006: Fail
-rasta/issue_000008: Fail
-rasta/issue_000011: Fail
-rasta/issue_000012: Fail
-rasta/issue_000025: Fail
-rasta/issue_000026: Fail
-rasta/issue_000031: Fail
-rasta/issue_000032: Fail
-rasta/issue_000033: Fail
+rasta/generic_factory: RuntimeError
+rasta/issue_000001: RuntimeError
+rasta/issue_000031: RuntimeError
+rasta/issue_000032: RuntimeError
 rasta/issue_000034: RuntimeError
-rasta/issue_000035: Fail
-rasta/issue_000035a: Fail
-rasta/issue_000036: Fail
-rasta/issue_000039: Fail
+rasta/issue_000035: RuntimeError
+rasta/issue_000035a: RuntimeError
+rasta/issue_000036: RuntimeError
+rasta/issue_000039: VerificationError
 rasta/issue_000041: RuntimeError
-rasta/issue_000042: Fail
-rasta/issue_000043: Fail
-rasta/issue_000044: Fail
-rasta/issue_000045: Fail
-rasta/issue_000046: Fail
-rasta/issue_000047: Fail
-rasta/issue_000048: Fail
-rasta/issue_000052: Fail
-rasta/issue_000053: Fail
-rasta/issue_000067: Fail
-rasta/issue_000068: Fail
-rasta/issue_000069: Fail
-rasta/issue_000070: Fail
-rasta/issue_000081: Fail
-rasta/malformed_const_constructor: Fail
-rasta/malformed_function: Fail
-rasta/malformed_function_type: Fail
-rasta/mandatory_parameter_initializer: Fail
+rasta/issue_000043: RuntimeError
+rasta/issue_000044: RuntimeError
+rasta/issue_000046: RuntimeError
+rasta/issue_000081: RuntimeError
+rasta/malformed_const_constructor: RuntimeError
+rasta/malformed_function: RuntimeError
 rasta/mixin_library: TypeCheckError
-rasta/native_is_illegal: Fail
-rasta/parser_error: Fail
-rasta/static: Fail
-rasta/super: Fail
-rasta/super_initializer: Fail
+rasta/native_is_illegal: RuntimeError
+rasta/parser_error: RuntimeError
+rasta/static: RuntimeError
+rasta/super: TypeCheckError
+rasta/super_initializer: RuntimeError
 rasta/super_mixin: TypeCheckError
-rasta/super_operator: Fail
-rasta/switch_execution_case_t02: Fail
-rasta/switch_fall_through: Fail
-rasta/this_invoke: Fail
-rasta/try_label: Fail
-rasta/type_literals: Fail
-rasta/type_with_parse_error: Fail
-rasta/typedef: Fail
-rasta/unresolved: Fail
-rasta/unresolved_constructor: Fail
-rasta/unresolved_for_in: Fail
-rasta/unresolved_recovery: Fail
-redirecting_constructor: Fail
-redirecting_factory: Fail
-redirecting_factory_chain_test: Fail # Missing support for RedirectingFactoryConstructor.
-redirecting_factory_simple_test: Fail # Missing support for RedirectingFactoryConstructor.
-redirecting_factory_typeargs_test: Fail # Missing support for RedirectingFactoryConstructor.
-redirecting_factory_typeparam_test: Fail # Missing support for RedirectingFactoryConstructor.
-redirecting_factory_typeparambounds_test: Fail # Missing support for RedirectingFactoryConstructor.
-regress/issue_29975: Fail # Issue 29975.
+rasta/super_operator: TypeCheckError
+rasta/type_literals: Crash
+rasta/typedef: Crash
+rasta/unresolved: RuntimeError
+rasta/unresolved_constructor: RuntimeError
+rasta/unresolved_for_in: VerificationError
+rasta/unresolved_recovery: TypeCheckError
 regress/issue_29976: RuntimeError # Tests runtime behavior of error recovery.
 regress/issue_29982: RuntimeError # Tests runtime behavior of error recovery.
 regress/issue_30836: RuntimeError # Issue 30836.
@@ -199,18 +132,13 @@
 regress/issue_33452: RuntimeError # Test has an intentional error
 regress/issue_34225: RuntimeError
 regress/issue_34563: RuntimeError # Test execution after recovery
+regress/issue_35177: RuntimeError
 runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast: RuntimeError
 runtime_checks_new/mixin_forwarding_stub_field: TypeCheckError
 runtime_checks_new/mixin_forwarding_stub_getter: TypeCheckError
 runtime_checks_new/mixin_forwarding_stub_setter: TypeCheckError
-statements: Fail
-stringliteral: Fail
-super_rasta_copy: Fail
-top_level_accessors: Fail
-type_variable_as_super: Fail
+statements: Crash
+type_variable_as_super: RuntimeError
 type_variable_prefix: RuntimeError
-typedef: Fail
-uninitialized_fields: Fail
-unused_methods: Fail
-void_methods: Fail
-warn_unresolved_sends: Fail # Test assumes Dart 1.0 semantics
+void_methods: ExpectationFileMismatch
+warn_unresolved_sends: InstrumentationMismatch # Test assumes Dart 1.0 semantics
diff --git a/pkg/front_end/testcases/super_call.dart.direct.expect b/pkg/front_end/testcases/super_call.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/super_call.dart.direct.expect
rename to pkg/front_end/testcases/super_call.dart.legacy.expect
diff --git a/pkg/front_end/testcases/super_call.dart.direct.transformed.expect b/pkg/front_end/testcases/super_call.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/super_call.dart.direct.transformed.expect
rename to pkg/front_end/testcases/super_call.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/super_nsm.dart.direct.expect b/pkg/front_end/testcases/super_nsm.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/super_nsm.dart.direct.expect
rename to pkg/front_end/testcases/super_nsm.dart.legacy.expect
diff --git a/pkg/front_end/testcases/super_nsm.dart.direct.transformed.expect b/pkg/front_end/testcases/super_nsm.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/super_nsm.dart.direct.transformed.expect
rename to pkg/front_end/testcases/super_nsm.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/super_rasta_copy.dart b/pkg/front_end/testcases/super_rasta_copy.dart
deleted file mode 100644
index cbec94c..0000000
--- a/pkg/front_end/testcases/super_rasta_copy.dart
+++ /dev/null
@@ -1,247 +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.md file.
-
-// TODO(ahe): This is a copy of [rasta/super.dart] without the `n`
-// property. Remove this once fasta can handle all of the original file.
-
-class A {
-  var a;
-  var b;
-  var c;
-  var d;
-  get e => null;
-  final f;
-  set g(_) {}
-  get h => null;
-  set h(_) {}
-  get i => null;
-
-  operator [](_) => null;
-  operator []=(a, b) {}
-  operator ~() => 117;
-  operator -() => 117;
-
-  operator ==(other) => true;
-
-  void m() {}
-}
-
-class B extends A {
-  get b => null;
-  set c(x) {}
-  final d;
-  set i(x) {}
-}
-
-class C extends B {
-  test() {
-    ~super;
-    use(~super);
-    -super;
-    use(-super);
-    super == 87;
-    use(super == 87);
-    super != 87;
-    use(super != 87);
-
-    super.a;
-    use(super.a);
-    super.b;
-    use(super.b);
-    super.c;
-    use(super.c);
-    super.d;
-    use(super.d);
-    super.e;
-    use(super.e);
-    super.f;
-    use(super.f);
-    super.g;
-    use(super.g);
-    super.h;
-    use(super.h);
-    super.i;
-    use(super.i);
-    super[87];
-    use(super[87]);
-    super.m;
-    use(super.m);
-
-    super.a++;
-    use(super.a++);
-    super.b++;
-    use(super.b++);
-    super.c++;
-    use(super.c++);
-    super.d++;
-    use(super.d++);
-    super.e++;
-    use(super.e++);
-    super.f++;
-    use(super.f++);
-    super.g++;
-    use(super.g++);
-    super.h++;
-    use(super.h++);
-    super.i++;
-    use(super.i++);
-    super[87]++;
-    use(super[87]++);
-    super.m++;
-    use(super.m++);
-
-    ++super.a;
-    use(++super.a);
-    ++super.b;
-    use(++super.b);
-    ++super.c;
-    use(++super.c);
-    ++super.d;
-    use(++super.d);
-    ++super.e;
-    use(++super.e);
-    ++super.f;
-    use(++super.f);
-    ++super.g;
-    use(++super.g);
-    ++super.h;
-    use(++super.h);
-    ++super.i;
-    use(++super.i);
-    ++super[87];
-    use(++super[87]);
-    ++super.m;
-    use(++super.m);
-
-    super.a();
-    use(super.a());
-    super.b();
-    use(super.b());
-    super.c();
-    use(super.c());
-    super.d();
-    use(super.d());
-    super.e();
-    use(super.e());
-    super.f();
-    use(super.f());
-    super.g();
-    use(super.g());
-    super.h();
-    use(super.h());
-    super.i();
-    use(super.i());
-    super[87]();
-    use(super[87]());
-    super.m();
-    use(super.m());
-    super.m(87);
-    use(super.m(87));
-
-    super.a = 42;
-    use(super.a = 42);
-    super.b = 42;
-    use(super.b = 42);
-    super.c = 42;
-    use(super.c = 42);
-    super.d = 42;
-    use(super.d = 42);
-    super.e = 42;
-    use(super.e = 42);
-    super.f = 42;
-    use(super.f = 42);
-    super.g = 42;
-    use(super.g = 42);
-    super.h = 42;
-    use(super.h = 42);
-    super.i = 42;
-    use(super.i = 42);
-    super[87] = 42;
-    use(super[87] = 42);
-    super.m = 42;
-    use(super.m = 42);
-
-    super.a ??= 42;
-    use(super.a ??= 42);
-    super.b ??= 42;
-    use(super.b ??= 42);
-    super.c ??= 42;
-    use(super.c ??= 42);
-    super.d ??= 42;
-    use(super.d ??= 42);
-    super.e ??= 42;
-    use(super.e ??= 42);
-    super.f ??= 42;
-    use(super.f ??= 42);
-    super.g ??= 42;
-    use(super.g ??= 42);
-    super.h ??= 42;
-    use(super.h ??= 42);
-    super.i ??= 42;
-    use(super.i ??= 42);
-    super[87] ??= 42;
-    use(super[87] ??= 42);
-    super.m ??= 42;
-    use(super.m ??= 42);
-
-    super.a += 42;
-    use(super.a += 42);
-    super.b += 42;
-    use(super.b += 42);
-    super.c += 42;
-    use(super.c += 42);
-    super.d += 42;
-    use(super.d += 42);
-    super.e += 42;
-    use(super.e += 42);
-    super.f += 42;
-    use(super.f += 42);
-    super.g += 42;
-    use(super.g += 42);
-    super.h += 42;
-    use(super.h += 42);
-    super.i += 42;
-    use(super.i += 42);
-    super[87] += 42;
-    use(super[87] += 42);
-    super.m += 42;
-    use(super.m += 42);
-
-    super.a -= 42;
-    use(super.a -= 42);
-    super.b -= 42;
-    use(super.b -= 42);
-    super.c -= 42;
-    use(super.c -= 42);
-    super.d -= 42;
-    use(super.d -= 42);
-    super.e -= 42;
-    use(super.e -= 42);
-    super.f -= 42;
-    use(super.f -= 42);
-    super.g -= 42;
-    use(super.g -= 42);
-    super.h -= 42;
-    use(super.h -= 42);
-    super.i -= 42;
-    use(super.i -= 42);
-    super[87] -= 42;
-    use(super[87] -= 42);
-    super.m -= 42;
-    use(super.m -= 42);
-  }
-}
-
-use(x) {
-  if (x == new DateTime.now().millisecondsSinceEpoch) throw "Shouldn't happen";
-}
-
-main() {
-  try {
-    new C().test();
-  } on NoSuchMethodError {
-    return; // Test passed.
-  }
-  throw "Test failed";
-}
diff --git a/pkg/front_end/testcases/super_rasta_copy.dart.direct.expect b/pkg/front_end/testcases/super_rasta_copy.dart.direct.expect
deleted file mode 100644
index c262ce9..0000000
--- a/pkg/front_end/testcases/super_rasta_copy.dart.direct.expect
+++ /dev/null
@@ -1,482 +0,0 @@
-// Formatted problems:
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:60:11: Warning: Superclass has no getter named 'g'.
-//     super.g;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:61:15: Warning: Superclass has no getter named 'g'.
-//     use(super.g);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:79:11: Warning: Superclass has no setter named 'e'.
-//     super.e++;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:80:15: Warning: Superclass has no setter named 'e'.
-//     use(super.e++);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:81:11: Warning: Superclass has no setter named 'f'.
-//     super.f++;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:82:15: Warning: Superclass has no setter named 'f'.
-//     use(super.f++);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:83:11: Warning: Superclass has no getter named 'g'.
-//     super.g++;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:84:15: Warning: Superclass has no getter named 'g'.
-//     use(super.g++);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:91:11: Warning: Superclass has no setter named 'm'.
-//     super.m++;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:92:15: Warning: Superclass has no setter named 'm'.
-//     use(super.m++);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:102:13: Warning: Superclass has no setter named 'e'.
-//     ++super.e;
-//             ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:103:17: Warning: Superclass has no setter named 'e'.
-//     use(++super.e);
-//                 ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:104:13: Warning: Superclass has no setter named 'f'.
-//     ++super.f;
-//             ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:105:17: Warning: Superclass has no setter named 'f'.
-//     use(++super.f);
-//                 ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:106:13: Warning: Superclass has no getter named 'g'.
-//     ++super.g;
-//             ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:107:17: Warning: Superclass has no getter named 'g'.
-//     use(++super.g);
-//                 ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:114:13: Warning: Superclass has no setter named 'm'.
-//     ++super.m;
-//             ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:115:17: Warning: Superclass has no setter named 'm'.
-//     use(++super.m);
-//                 ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:129:11: Warning: Superclass has no method named 'g'.
-//     super.g();
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:130:15: Warning: Superclass has no method named 'g'.
-//     use(super.g());
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:150:11: Warning: Superclass has no setter named 'e'.
-//     super.e = 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:151:15: Warning: Superclass has no setter named 'e'.
-//     use(super.e = 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:152:11: Warning: Superclass has no setter named 'f'.
-//     super.f = 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:153:15: Warning: Superclass has no setter named 'f'.
-//     use(super.f = 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:162:11: Warning: Superclass has no setter named 'm'.
-//     super.m = 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:163:15: Warning: Superclass has no setter named 'm'.
-//     use(super.m = 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:173:11: Warning: Superclass has no setter named 'e'.
-//     super.e ??= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:174:15: Warning: Superclass has no setter named 'e'.
-//     use(super.e ??= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:175:11: Warning: Superclass has no setter named 'f'.
-//     super.f ??= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:176:15: Warning: Superclass has no setter named 'f'.
-//     use(super.f ??= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:177:11: Warning: Superclass has no getter named 'g'.
-//     super.g ??= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:178:15: Warning: Superclass has no getter named 'g'.
-//     use(super.g ??= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:185:11: Warning: Superclass has no setter named 'm'.
-//     super.m ??= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:186:15: Warning: Superclass has no setter named 'm'.
-//     use(super.m ??= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:196:11: Warning: Superclass has no setter named 'e'.
-//     super.e += 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:197:15: Warning: Superclass has no setter named 'e'.
-//     use(super.e += 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:198:11: Warning: Superclass has no setter named 'f'.
-//     super.f += 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:199:15: Warning: Superclass has no setter named 'f'.
-//     use(super.f += 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:200:11: Warning: Superclass has no getter named 'g'.
-//     super.g += 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:201:15: Warning: Superclass has no getter named 'g'.
-//     use(super.g += 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:208:11: Warning: Superclass has no setter named 'm'.
-//     super.m += 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:209:15: Warning: Superclass has no setter named 'm'.
-//     use(super.m += 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:219:11: Warning: Superclass has no setter named 'e'.
-//     super.e -= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:220:15: Warning: Superclass has no setter named 'e'.
-//     use(super.e -= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:221:11: Warning: Superclass has no setter named 'f'.
-//     super.f -= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:222:15: Warning: Superclass has no setter named 'f'.
-//     use(super.f -= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:223:11: Warning: Superclass has no getter named 'g'.
-//     super.g -= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:224:15: Warning: Superclass has no getter named 'g'.
-//     use(super.g -= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:231:11: Warning: Superclass has no setter named 'm'.
-//     super.m -= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:232:15: Warning: Superclass has no setter named 'm'.
-//     use(super.m -= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:139:12: Warning: Too many positional arguments: 0 allowed, but 1 found.
-// Try removing the extra positional arguments.
-//     super.m(87);
-//            ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:140:16: Warning: Too many positional arguments: 0 allowed, but 1 found.
-// Try removing the extra positional arguments.
-//     use(super.m(87));
-//                ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:14:9: Error: Final field 'f' is not initialized.
-// Try to initialize the field in the declaration or in every constructor.
-//   final f;
-//         ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:33:9: Error: Final field 'd' is not initialized.
-// Try to initialize the field in the declaration or in every constructor.
-//   final d;
-//         ^
-
-// Unhandled errors:
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:14:9: Error: Final field 'f' is not initialized.
-// Try to initialize the field in the declaration or in every constructor.
-//   final f;
-//         ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:33:9: Error: Final field 'd' is not initialized.
-// Try to initialize the field in the declaration or in every constructor.
-//   final d;
-//         ^
-
-library;
-import self as self;
-import "dart:core" as core;
-
-class A extends core::Object {
-  field dynamic a = null;
-  field dynamic b = null;
-  field dynamic c = null;
-  field dynamic d = null;
-  final field dynamic f = null;
-  synthetic constructor •() → self::A
-    : super core::Object::•()
-    ;
-  get e() → dynamic
-    return null;
-  set g(dynamic _) → dynamic {}
-  get h() → dynamic
-    return null;
-  set h(dynamic _) → dynamic {}
-  get i() → dynamic
-    return null;
-  operator [](dynamic _) → dynamic
-    return null;
-  operator []=(dynamic a, dynamic b) → dynamic {}
-  operator ~() → dynamic
-    return 117;
-  operator unary-() → dynamic
-    return 117;
-  operator ==(dynamic other) → dynamic
-    return true;
-  method m() → void {}
-}
-class B extends self::A {
-  final field dynamic d = null;
-  synthetic constructor •() → self::B
-    : super self::A::•()
-    ;
-  get b() → dynamic
-    return null;
-  set c(dynamic x) → dynamic {}
-  set i(dynamic x) → dynamic {}
-}
-class C extends self::B {
-  synthetic constructor •() → self::C
-    : super self::B::•()
-    ;
-  method test() → dynamic {
-    super.{self::A::~}();
-    self::use(super.{self::A::~}());
-    super.{self::A::unary-}();
-    self::use(super.{self::A::unary-}());
-    super.{self::A::==}(87);
-    self::use(super.{self::A::==}(87));
-    !super.{self::A::==}(87);
-    self::use(!super.{self::A::==}(87));
-    super.{self::A::a};
-    self::use(super.{self::A::a});
-    super.{self::B::b};
-    self::use(super.{self::B::b});
-    super.{self::A::c};
-    self::use(super.{self::A::c});
-    super.{self::B::d};
-    self::use(super.{self::B::d});
-    super.{self::A::e};
-    self::use(super.{self::A::e});
-    super.{self::A::f};
-    self::use(super.{self::A::f});
-    super.g;
-    self::use(super.g);
-    super.{self::A::h};
-    self::use(super.{self::A::h});
-    super.{self::A::i};
-    self::use(super.{self::A::i});
-    super.{self::A::[]}(87);
-    self::use(super.{self::A::[]}(87));
-    super.{self::A::m};
-    self::use(super.{self::A::m});
-    super.{self::A::a} = super.{self::A::a}.+(1);
-    self::use(let final dynamic #t1 = super.{self::A::a} in let final dynamic #t2 = super.{self::A::a} = #t1.+(1) in #t1);
-    super.{self::A::b} = super.{self::B::b}.+(1);
-    self::use(let final dynamic #t3 = super.{self::B::b} in let final dynamic #t4 = super.{self::A::b} = #t3.+(1) in #t3);
-    super.{self::B::c} = super.{self::A::c}.+(1);
-    self::use(let final dynamic #t5 = super.{self::A::c} in let final dynamic #t6 = super.{self::B::c} = #t5.+(1) in #t5);
-    super.{self::A::d} = super.{self::B::d}.+(1);
-    self::use(let final dynamic #t7 = super.{self::B::d} in let final dynamic #t8 = super.{self::A::d} = #t7.+(1) in #t7);
-    super.e = super.{self::A::e}.+(1);
-    self::use(let final dynamic #t9 = super.{self::A::e} in let final dynamic #t10 = super.e = #t9.+(1) in #t9);
-    super.f = super.{self::A::f}.+(1);
-    self::use(let final dynamic #t11 = super.{self::A::f} in let final dynamic #t12 = super.f = #t11.+(1) in #t11);
-    super.{self::A::g} = super.g.+(1);
-    self::use(let final dynamic #t13 = super.g in let final dynamic #t14 = super.{self::A::g} = #t13.+(1) in #t13);
-    super.{self::A::h} = super.{self::A::h}.+(1);
-    self::use(let final dynamic #t15 = super.{self::A::h} in let final dynamic #t16 = super.{self::A::h} = #t15.+(1) in #t15);
-    super.{self::B::i} = super.{self::A::i}.+(1);
-    self::use(let final dynamic #t17 = super.{self::A::i} in let final dynamic #t18 = super.{self::B::i} = #t17.+(1) in #t17);
-    let final dynamic #t19 = 87 in super.{self::A::[]=}(#t19, super.{self::A::[]}(#t19).+(1));
-    self::use(let final dynamic #t20 = 87 in let final dynamic #t21 = super.{self::A::[]}(#t20) in let final dynamic #t22 = super.{self::A::[]=}(#t20, #t21.+(1)) in #t21);
-    super.m = super.{self::A::m}.+(1);
-    self::use(let final dynamic #t23 = super.{self::A::m} in let final dynamic #t24 = super.m = #t23.+(1) in #t23);
-    super.{self::A::a} = super.{self::A::a}.+(1);
-    self::use(super.{self::A::a} = super.{self::A::a}.+(1));
-    super.{self::A::b} = super.{self::B::b}.+(1);
-    self::use(super.{self::A::b} = super.{self::B::b}.+(1));
-    super.{self::B::c} = super.{self::A::c}.+(1);
-    self::use(super.{self::B::c} = super.{self::A::c}.+(1));
-    super.{self::A::d} = super.{self::B::d}.+(1);
-    self::use(super.{self::A::d} = super.{self::B::d}.+(1));
-    super.e = super.{self::A::e}.+(1);
-    self::use(super.e = super.{self::A::e}.+(1));
-    super.f = super.{self::A::f}.+(1);
-    self::use(super.f = super.{self::A::f}.+(1));
-    super.{self::A::g} = super.g.+(1);
-    self::use(super.{self::A::g} = super.g.+(1));
-    super.{self::A::h} = super.{self::A::h}.+(1);
-    self::use(super.{self::A::h} = super.{self::A::h}.+(1));
-    super.{self::B::i} = super.{self::A::i}.+(1);
-    self::use(super.{self::B::i} = super.{self::A::i}.+(1));
-    let final dynamic #t25 = 87 in let final dynamic #t26 = super.{self::A::[]}(#t25).+(1) in let final dynamic #t27 = super.{self::A::[]=}(#t25, #t26) in #t26;
-    self::use(let final dynamic #t28 = 87 in let final dynamic #t29 = super.{self::A::[]}(#t28).+(1) in let final dynamic #t30 = super.{self::A::[]=}(#t28, #t29) in #t29);
-    super.m = super.{self::A::m}.+(1);
-    self::use(super.m = super.{self::A::m}.+(1));
-    super.{self::A::a}.call();
-    self::use(super.{self::A::a}.call());
-    super.{self::B::b}.call();
-    self::use(super.{self::B::b}.call());
-    super.{self::A::c}.call();
-    self::use(super.{self::A::c}.call());
-    super.{self::B::d}.call();
-    self::use(super.{self::B::d}.call());
-    super.{self::A::e}.call();
-    self::use(super.{self::A::e}.call());
-    super.{self::A::f}.call();
-    self::use(super.{self::A::f}.call());
-    super.g();
-    self::use(super.g());
-    super.{self::A::h}.call();
-    self::use(super.{self::A::h}.call());
-    super.{self::A::i}.call();
-    self::use(super.{self::A::i}.call());
-    super.{self::A::[]}(87).call();
-    self::use(super.{self::A::[]}(87).call());
-    super.{self::A::m}();
-    self::use(super.{self::A::m}());
-    super.{self::A::m}(87);
-    self::use(super.{self::A::m}(87));
-    super.{self::A::a} = 42;
-    self::use(super.{self::A::a} = 42);
-    super.{self::A::b} = 42;
-    self::use(super.{self::A::b} = 42);
-    super.{self::B::c} = 42;
-    self::use(super.{self::B::c} = 42);
-    super.{self::A::d} = 42;
-    self::use(super.{self::A::d} = 42);
-    super.e = 42;
-    self::use(super.e = 42);
-    super.f = 42;
-    self::use(super.f = 42);
-    super.{self::A::g} = 42;
-    self::use(super.{self::A::g} = 42);
-    super.{self::A::h} = 42;
-    self::use(super.{self::A::h} = 42);
-    super.{self::B::i} = 42;
-    self::use(super.{self::B::i} = 42);
-    super.{self::A::[]=}(87, 42);
-    self::use(let final dynamic #t31 = 87 in let final dynamic #t32 = 42 in let final dynamic #t33 = super.{self::A::[]=}(#t31, #t32) in #t32);
-    super.m = 42;
-    self::use(super.m = 42);
-    super.{self::A::a}.==(null) ? super.{self::A::a} = 42 : null;
-    self::use(let final dynamic #t34 = super.{self::A::a} in #t34.==(null) ? super.{self::A::a} = 42 : #t34);
-    super.{self::B::b}.==(null) ? super.{self::A::b} = 42 : null;
-    self::use(let final dynamic #t35 = super.{self::B::b} in #t35.==(null) ? super.{self::A::b} = 42 : #t35);
-    super.{self::A::c}.==(null) ? super.{self::B::c} = 42 : null;
-    self::use(let final dynamic #t36 = super.{self::A::c} in #t36.==(null) ? super.{self::B::c} = 42 : #t36);
-    super.{self::B::d}.==(null) ? super.{self::A::d} = 42 : null;
-    self::use(let final dynamic #t37 = super.{self::B::d} in #t37.==(null) ? super.{self::A::d} = 42 : #t37);
-    super.{self::A::e}.==(null) ? super.e = 42 : null;
-    self::use(let final dynamic #t38 = super.{self::A::e} in #t38.==(null) ? super.e = 42 : #t38);
-    super.{self::A::f}.==(null) ? super.f = 42 : null;
-    self::use(let final dynamic #t39 = super.{self::A::f} in #t39.==(null) ? super.f = 42 : #t39);
-    super.g.==(null) ? super.{self::A::g} = 42 : null;
-    self::use(let final dynamic #t40 = super.g in #t40.==(null) ? super.{self::A::g} = 42 : #t40);
-    super.{self::A::h}.==(null) ? super.{self::A::h} = 42 : null;
-    self::use(let final dynamic #t41 = super.{self::A::h} in #t41.==(null) ? super.{self::A::h} = 42 : #t41);
-    super.{self::A::i}.==(null) ? super.{self::B::i} = 42 : null;
-    self::use(let final dynamic #t42 = super.{self::A::i} in #t42.==(null) ? super.{self::B::i} = 42 : #t42);
-    let final dynamic #t43 = 87 in super.{self::A::[]}(#t43).==(null) ? let final dynamic #t44 = 42 in let final dynamic #t45 = super.{self::A::[]=}(#t43, #t44) in #t44 : null;
-    self::use(let final dynamic #t46 = 87 in let final dynamic #t47 = super.{self::A::[]}(#t46) in #t47.==(null) ? let final dynamic #t48 = 42 in let final dynamic #t49 = super.{self::A::[]=}(#t46, #t48) in #t48 : #t47);
-    super.{self::A::m}.==(null) ? super.m = 42 : null;
-    self::use(let final dynamic #t50 = super.{self::A::m} in #t50.==(null) ? super.m = 42 : #t50);
-    super.{self::A::a} = super.{self::A::a}.+(42);
-    self::use(super.{self::A::a} = super.{self::A::a}.+(42));
-    super.{self::A::b} = super.{self::B::b}.+(42);
-    self::use(super.{self::A::b} = super.{self::B::b}.+(42));
-    super.{self::B::c} = super.{self::A::c}.+(42);
-    self::use(super.{self::B::c} = super.{self::A::c}.+(42));
-    super.{self::A::d} = super.{self::B::d}.+(42);
-    self::use(super.{self::A::d} = super.{self::B::d}.+(42));
-    super.e = super.{self::A::e}.+(42);
-    self::use(super.e = super.{self::A::e}.+(42));
-    super.f = super.{self::A::f}.+(42);
-    self::use(super.f = super.{self::A::f}.+(42));
-    super.{self::A::g} = super.g.+(42);
-    self::use(super.{self::A::g} = super.g.+(42));
-    super.{self::A::h} = super.{self::A::h}.+(42);
-    self::use(super.{self::A::h} = super.{self::A::h}.+(42));
-    super.{self::B::i} = super.{self::A::i}.+(42);
-    self::use(super.{self::B::i} = super.{self::A::i}.+(42));
-    let final dynamic #t51 = 87 in super.{self::A::[]=}(#t51, super.{self::A::[]}(#t51).+(42));
-    self::use(let final dynamic #t52 = 87 in let final dynamic #t53 = super.{self::A::[]}(#t52).+(42) in let final dynamic #t54 = super.{self::A::[]=}(#t52, #t53) in #t53);
-    super.m = super.{self::A::m}.+(42);
-    self::use(super.m = super.{self::A::m}.+(42));
-    super.{self::A::a} = super.{self::A::a}.-(42);
-    self::use(super.{self::A::a} = super.{self::A::a}.-(42));
-    super.{self::A::b} = super.{self::B::b}.-(42);
-    self::use(super.{self::A::b} = super.{self::B::b}.-(42));
-    super.{self::B::c} = super.{self::A::c}.-(42);
-    self::use(super.{self::B::c} = super.{self::A::c}.-(42));
-    super.{self::A::d} = super.{self::B::d}.-(42);
-    self::use(super.{self::A::d} = super.{self::B::d}.-(42));
-    super.e = super.{self::A::e}.-(42);
-    self::use(super.e = super.{self::A::e}.-(42));
-    super.f = super.{self::A::f}.-(42);
-    self::use(super.f = super.{self::A::f}.-(42));
-    super.{self::A::g} = super.g.-(42);
-    self::use(super.{self::A::g} = super.g.-(42));
-    super.{self::A::h} = super.{self::A::h}.-(42);
-    self::use(super.{self::A::h} = super.{self::A::h}.-(42));
-    super.{self::B::i} = super.{self::A::i}.-(42);
-    self::use(super.{self::B::i} = super.{self::A::i}.-(42));
-    let final dynamic #t55 = 87 in super.{self::A::[]=}(#t55, super.{self::A::[]}(#t55).-(42));
-    self::use(let final dynamic #t56 = 87 in let final dynamic #t57 = super.{self::A::[]}(#t56).-(42) in let final dynamic #t58 = super.{self::A::[]=}(#t56, #t57) in #t57);
-    super.m = super.{self::A::m}.-(42);
-    self::use(super.m = super.{self::A::m}.-(42));
-  }
-}
-static method use(dynamic x) → dynamic {
-  if(x.==(new core::DateTime::now().millisecondsSinceEpoch))
-    throw "Shouldn't happen";
-}
-static method main() → dynamic {
-  try {
-    new self::C::•().test();
-  }
-  on core::NoSuchMethodError catch(no-exception-var) {
-    return;
-  }
-  throw "Test failed";
-}
diff --git a/pkg/front_end/testcases/super_rasta_copy.dart.direct.transformed.expect b/pkg/front_end/testcases/super_rasta_copy.dart.direct.transformed.expect
deleted file mode 100644
index e99eae0..0000000
--- a/pkg/front_end/testcases/super_rasta_copy.dart.direct.transformed.expect
+++ /dev/null
@@ -1,260 +0,0 @@
-// Unhandled errors:
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:14:9: Error: Final field 'f' is not initialized.
-// Try to initialize the field in the declaration or in every constructor.
-//   final f;
-//         ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:33:9: Error: Final field 'd' is not initialized.
-// Try to initialize the field in the declaration or in every constructor.
-//   final d;
-//         ^
-
-library;
-import self as self;
-import "dart:core" as core;
-
-class A extends core::Object {
-  field dynamic a = null;
-  field dynamic b = null;
-  field dynamic c = null;
-  field dynamic d = null;
-  final field dynamic f = null;
-  synthetic constructor •() → self::A
-    : super core::Object::•()
-    ;
-  get e() → dynamic
-    return null;
-  set g(dynamic _) → dynamic {}
-  get h() → dynamic
-    return null;
-  set h(dynamic _) → dynamic {}
-  get i() → dynamic
-    return null;
-  operator [](dynamic _) → dynamic
-    return null;
-  operator []=(dynamic a, dynamic b) → dynamic {}
-  operator ~() → dynamic
-    return 117;
-  operator unary-() → dynamic
-    return 117;
-  operator ==(dynamic other) → dynamic
-    return true;
-  method m() → void {}
-}
-class B extends self::A {
-  final field dynamic d = null;
-  synthetic constructor •() → self::B
-    : super self::A::•()
-    ;
-  get b() → dynamic
-    return null;
-  set c(dynamic x) → dynamic {}
-  set i(dynamic x) → dynamic {}
-}
-class C extends self::B {
-  synthetic constructor •() → self::C
-    : super self::B::•()
-    ;
-  method test() → dynamic {
-    super.{self::A::~}();
-    self::use(super.{self::A::~}());
-    super.{self::A::unary-}();
-    self::use(super.{self::A::unary-}());
-    super.{self::A::==}(87);
-    self::use(super.{self::A::==}(87));
-    !super.{self::A::==}(87);
-    self::use(!super.{self::A::==}(87));
-    super.{self::A::a};
-    self::use(super.{self::A::a});
-    super.{self::B::b};
-    self::use(super.{self::B::b});
-    super.{self::A::c};
-    self::use(super.{self::A::c});
-    super.{self::B::d};
-    self::use(super.{self::B::d});
-    super.{self::A::e};
-    self::use(super.{self::A::e});
-    super.{self::A::f};
-    self::use(super.{self::A::f});
-    super.g;
-    self::use(super.g);
-    super.{self::A::h};
-    self::use(super.{self::A::h});
-    super.{self::A::i};
-    self::use(super.{self::A::i});
-    super.{self::A::[]}(87);
-    self::use(super.{self::A::[]}(87));
-    super.{self::A::m};
-    self::use(super.{self::A::m});
-    super.{self::A::a} = super.{self::A::a}.+(1);
-    self::use(let final dynamic #t1 = super.{self::A::a} in let final dynamic #t2 = super.{self::A::a} = #t1.+(1) in #t1);
-    super.{self::A::b} = super.{self::B::b}.+(1);
-    self::use(let final dynamic #t3 = super.{self::B::b} in let final dynamic #t4 = super.{self::A::b} = #t3.+(1) in #t3);
-    super.{self::B::c} = super.{self::A::c}.+(1);
-    self::use(let final dynamic #t5 = super.{self::A::c} in let final dynamic #t6 = super.{self::B::c} = #t5.+(1) in #t5);
-    super.{self::A::d} = super.{self::B::d}.+(1);
-    self::use(let final dynamic #t7 = super.{self::B::d} in let final dynamic #t8 = super.{self::A::d} = #t7.+(1) in #t7);
-    super.e = super.{self::A::e}.+(1);
-    self::use(let final dynamic #t9 = super.{self::A::e} in let final dynamic #t10 = super.e = #t9.+(1) in #t9);
-    super.f = super.{self::A::f}.+(1);
-    self::use(let final dynamic #t11 = super.{self::A::f} in let final dynamic #t12 = super.f = #t11.+(1) in #t11);
-    super.{self::A::g} = super.g.+(1);
-    self::use(let final dynamic #t13 = super.g in let final dynamic #t14 = super.{self::A::g} = #t13.+(1) in #t13);
-    super.{self::A::h} = super.{self::A::h}.+(1);
-    self::use(let final dynamic #t15 = super.{self::A::h} in let final dynamic #t16 = super.{self::A::h} = #t15.+(1) in #t15);
-    super.{self::B::i} = super.{self::A::i}.+(1);
-    self::use(let final dynamic #t17 = super.{self::A::i} in let final dynamic #t18 = super.{self::B::i} = #t17.+(1) in #t17);
-    let final dynamic #t19 = 87 in super.{self::A::[]=}(#t19, super.{self::A::[]}(#t19).+(1));
-    self::use(let final dynamic #t20 = 87 in let final dynamic #t21 = super.{self::A::[]}(#t20) in let final dynamic #t22 = super.{self::A::[]=}(#t20, #t21.+(1)) in #t21);
-    super.m = super.{self::A::m}.+(1);
-    self::use(let final dynamic #t23 = super.{self::A::m} in let final dynamic #t24 = super.m = #t23.+(1) in #t23);
-    super.{self::A::a} = super.{self::A::a}.+(1);
-    self::use(super.{self::A::a} = super.{self::A::a}.+(1));
-    super.{self::A::b} = super.{self::B::b}.+(1);
-    self::use(super.{self::A::b} = super.{self::B::b}.+(1));
-    super.{self::B::c} = super.{self::A::c}.+(1);
-    self::use(super.{self::B::c} = super.{self::A::c}.+(1));
-    super.{self::A::d} = super.{self::B::d}.+(1);
-    self::use(super.{self::A::d} = super.{self::B::d}.+(1));
-    super.e = super.{self::A::e}.+(1);
-    self::use(super.e = super.{self::A::e}.+(1));
-    super.f = super.{self::A::f}.+(1);
-    self::use(super.f = super.{self::A::f}.+(1));
-    super.{self::A::g} = super.g.+(1);
-    self::use(super.{self::A::g} = super.g.+(1));
-    super.{self::A::h} = super.{self::A::h}.+(1);
-    self::use(super.{self::A::h} = super.{self::A::h}.+(1));
-    super.{self::B::i} = super.{self::A::i}.+(1);
-    self::use(super.{self::B::i} = super.{self::A::i}.+(1));
-    let final dynamic #t25 = 87 in let final dynamic #t26 = super.{self::A::[]}(#t25).+(1) in let final dynamic #t27 = super.{self::A::[]=}(#t25, #t26) in #t26;
-    self::use(let final dynamic #t28 = 87 in let final dynamic #t29 = super.{self::A::[]}(#t28).+(1) in let final dynamic #t30 = super.{self::A::[]=}(#t28, #t29) in #t29);
-    super.m = super.{self::A::m}.+(1);
-    self::use(super.m = super.{self::A::m}.+(1));
-    super.{self::A::a}.call();
-    self::use(super.{self::A::a}.call());
-    super.{self::B::b}.call();
-    self::use(super.{self::B::b}.call());
-    super.{self::A::c}.call();
-    self::use(super.{self::A::c}.call());
-    super.{self::B::d}.call();
-    self::use(super.{self::B::d}.call());
-    super.{self::A::e}.call();
-    self::use(super.{self::A::e}.call());
-    super.{self::A::f}.call();
-    self::use(super.{self::A::f}.call());
-    super.g();
-    self::use(super.g());
-    super.{self::A::h}.call();
-    self::use(super.{self::A::h}.call());
-    super.{self::A::i}.call();
-    self::use(super.{self::A::i}.call());
-    super.{self::A::[]}(87).call();
-    self::use(super.{self::A::[]}(87).call());
-    super.{self::A::m}();
-    self::use(super.{self::A::m}());
-    super.{self::A::m}(87);
-    self::use(super.{self::A::m}(87));
-    super.{self::A::a} = 42;
-    self::use(super.{self::A::a} = 42);
-    super.{self::A::b} = 42;
-    self::use(super.{self::A::b} = 42);
-    super.{self::B::c} = 42;
-    self::use(super.{self::B::c} = 42);
-    super.{self::A::d} = 42;
-    self::use(super.{self::A::d} = 42);
-    super.e = 42;
-    self::use(super.e = 42);
-    super.f = 42;
-    self::use(super.f = 42);
-    super.{self::A::g} = 42;
-    self::use(super.{self::A::g} = 42);
-    super.{self::A::h} = 42;
-    self::use(super.{self::A::h} = 42);
-    super.{self::B::i} = 42;
-    self::use(super.{self::B::i} = 42);
-    super.{self::A::[]=}(87, 42);
-    self::use(let final dynamic #t31 = 87 in let final dynamic #t32 = 42 in let final dynamic #t33 = super.{self::A::[]=}(#t31, #t32) in #t32);
-    super.m = 42;
-    self::use(super.m = 42);
-    super.{self::A::a}.==(null) ? super.{self::A::a} = 42 : null;
-    self::use(let final dynamic #t34 = super.{self::A::a} in #t34.==(null) ? super.{self::A::a} = 42 : #t34);
-    super.{self::B::b}.==(null) ? super.{self::A::b} = 42 : null;
-    self::use(let final dynamic #t35 = super.{self::B::b} in #t35.==(null) ? super.{self::A::b} = 42 : #t35);
-    super.{self::A::c}.==(null) ? super.{self::B::c} = 42 : null;
-    self::use(let final dynamic #t36 = super.{self::A::c} in #t36.==(null) ? super.{self::B::c} = 42 : #t36);
-    super.{self::B::d}.==(null) ? super.{self::A::d} = 42 : null;
-    self::use(let final dynamic #t37 = super.{self::B::d} in #t37.==(null) ? super.{self::A::d} = 42 : #t37);
-    super.{self::A::e}.==(null) ? super.e = 42 : null;
-    self::use(let final dynamic #t38 = super.{self::A::e} in #t38.==(null) ? super.e = 42 : #t38);
-    super.{self::A::f}.==(null) ? super.f = 42 : null;
-    self::use(let final dynamic #t39 = super.{self::A::f} in #t39.==(null) ? super.f = 42 : #t39);
-    super.g.==(null) ? super.{self::A::g} = 42 : null;
-    self::use(let final dynamic #t40 = super.g in #t40.==(null) ? super.{self::A::g} = 42 : #t40);
-    super.{self::A::h}.==(null) ? super.{self::A::h} = 42 : null;
-    self::use(let final dynamic #t41 = super.{self::A::h} in #t41.==(null) ? super.{self::A::h} = 42 : #t41);
-    super.{self::A::i}.==(null) ? super.{self::B::i} = 42 : null;
-    self::use(let final dynamic #t42 = super.{self::A::i} in #t42.==(null) ? super.{self::B::i} = 42 : #t42);
-    let final dynamic #t43 = 87 in super.{self::A::[]}(#t43).==(null) ? let final dynamic #t44 = 42 in let final dynamic #t45 = super.{self::A::[]=}(#t43, #t44) in #t44 : null;
-    self::use(let final dynamic #t46 = 87 in let final dynamic #t47 = super.{self::A::[]}(#t46) in #t47.==(null) ? let final dynamic #t48 = 42 in let final dynamic #t49 = super.{self::A::[]=}(#t46, #t48) in #t48 : #t47);
-    super.{self::A::m}.==(null) ? super.m = 42 : null;
-    self::use(let final dynamic #t50 = super.{self::A::m} in #t50.==(null) ? super.m = 42 : #t50);
-    super.{self::A::a} = super.{self::A::a}.+(42);
-    self::use(super.{self::A::a} = super.{self::A::a}.+(42));
-    super.{self::A::b} = super.{self::B::b}.+(42);
-    self::use(super.{self::A::b} = super.{self::B::b}.+(42));
-    super.{self::B::c} = super.{self::A::c}.+(42);
-    self::use(super.{self::B::c} = super.{self::A::c}.+(42));
-    super.{self::A::d} = super.{self::B::d}.+(42);
-    self::use(super.{self::A::d} = super.{self::B::d}.+(42));
-    super.e = super.{self::A::e}.+(42);
-    self::use(super.e = super.{self::A::e}.+(42));
-    super.f = super.{self::A::f}.+(42);
-    self::use(super.f = super.{self::A::f}.+(42));
-    super.{self::A::g} = super.g.+(42);
-    self::use(super.{self::A::g} = super.g.+(42));
-    super.{self::A::h} = super.{self::A::h}.+(42);
-    self::use(super.{self::A::h} = super.{self::A::h}.+(42));
-    super.{self::B::i} = super.{self::A::i}.+(42);
-    self::use(super.{self::B::i} = super.{self::A::i}.+(42));
-    let final dynamic #t51 = 87 in super.{self::A::[]=}(#t51, super.{self::A::[]}(#t51).+(42));
-    self::use(let final dynamic #t52 = 87 in let final dynamic #t53 = super.{self::A::[]}(#t52).+(42) in let final dynamic #t54 = super.{self::A::[]=}(#t52, #t53) in #t53);
-    super.m = super.{self::A::m}.+(42);
-    self::use(super.m = super.{self::A::m}.+(42));
-    super.{self::A::a} = super.{self::A::a}.-(42);
-    self::use(super.{self::A::a} = super.{self::A::a}.-(42));
-    super.{self::A::b} = super.{self::B::b}.-(42);
-    self::use(super.{self::A::b} = super.{self::B::b}.-(42));
-    super.{self::B::c} = super.{self::A::c}.-(42);
-    self::use(super.{self::B::c} = super.{self::A::c}.-(42));
-    super.{self::A::d} = super.{self::B::d}.-(42);
-    self::use(super.{self::A::d} = super.{self::B::d}.-(42));
-    super.e = super.{self::A::e}.-(42);
-    self::use(super.e = super.{self::A::e}.-(42));
-    super.f = super.{self::A::f}.-(42);
-    self::use(super.f = super.{self::A::f}.-(42));
-    super.{self::A::g} = super.g.-(42);
-    self::use(super.{self::A::g} = super.g.-(42));
-    super.{self::A::h} = super.{self::A::h}.-(42);
-    self::use(super.{self::A::h} = super.{self::A::h}.-(42));
-    super.{self::B::i} = super.{self::A::i}.-(42);
-    self::use(super.{self::B::i} = super.{self::A::i}.-(42));
-    let final dynamic #t55 = 87 in super.{self::A::[]=}(#t55, super.{self::A::[]}(#t55).-(42));
-    self::use(let final dynamic #t56 = 87 in let final dynamic #t57 = super.{self::A::[]}(#t56).-(42) in let final dynamic #t58 = super.{self::A::[]=}(#t56, #t57) in #t57);
-    super.m = super.{self::A::m}.-(42);
-    self::use(super.m = super.{self::A::m}.-(42));
-  }
-}
-static method use(dynamic x) → dynamic {
-  if(x.==(new core::DateTime::now().millisecondsSinceEpoch))
-    throw "Shouldn't happen";
-}
-static method main() → dynamic {
-  try {
-    new self::C::•().test();
-  }
-  on core::NoSuchMethodError catch(no-exception-var) {
-    return;
-  }
-  throw "Test failed";
-}
diff --git a/pkg/front_end/testcases/super_rasta_copy.dart.outline.expect b/pkg/front_end/testcases/super_rasta_copy.dart.outline.expect
deleted file mode 100644
index b65a6c3..0000000
--- a/pkg/front_end/testcases/super_rasta_copy.dart.outline.expect
+++ /dev/null
@@ -1,56 +0,0 @@
-library;
-import self as self;
-import "dart:core" as core;
-
-class A extends core::Object {
-  field dynamic a;
-  field dynamic b;
-  field dynamic c;
-  field dynamic d;
-  final field dynamic f;
-  synthetic constructor •() → self::A
-    ;
-  get e() → dynamic
-    ;
-  set g(dynamic _) → dynamic
-    ;
-  get h() → dynamic
-    ;
-  set h(dynamic _) → dynamic
-    ;
-  get i() → dynamic
-    ;
-  operator [](dynamic _) → dynamic
-    ;
-  operator []=(dynamic a, dynamic b) → dynamic
-    ;
-  operator ~() → dynamic
-    ;
-  operator unary-() → dynamic
-    ;
-  operator ==(dynamic other) → dynamic
-    ;
-  method m() → void
-    ;
-}
-class B extends self::A {
-  final field dynamic d;
-  synthetic constructor •() → self::B
-    ;
-  get b() → dynamic
-    ;
-  set c(dynamic x) → dynamic
-    ;
-  set i(dynamic x) → dynamic
-    ;
-}
-class C extends self::B {
-  synthetic constructor •() → self::C
-    ;
-  method test() → dynamic
-    ;
-}
-static method use(dynamic x) → dynamic
-  ;
-static method main() → dynamic
-  ;
diff --git a/pkg/front_end/testcases/super_rasta_copy.dart.strong.expect b/pkg/front_end/testcases/super_rasta_copy.dart.strong.expect
deleted file mode 100644
index f818b59..0000000
--- a/pkg/front_end/testcases/super_rasta_copy.dart.strong.expect
+++ /dev/null
@@ -1,494 +0,0 @@
-// Unhandled errors:
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:60:11: Error: Superclass has no getter named 'g'.
-//     super.g;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:61:15: Error: Superclass has no getter named 'g'.
-//     use(super.g);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:79:11: Error: Superclass has no setter named 'e'.
-//     super.e++;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:80:15: Error: Superclass has no setter named 'e'.
-//     use(super.e++);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:81:11: Error: Superclass has no setter named 'f'.
-//     super.f++;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:82:15: Error: Superclass has no setter named 'f'.
-//     use(super.f++);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:83:11: Error: Superclass has no getter named 'g'.
-//     super.g++;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:84:15: Error: Superclass has no getter named 'g'.
-//     use(super.g++);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:91:11: Error: Superclass has no setter named 'm'.
-//     super.m++;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:92:15: Error: Superclass has no setter named 'm'.
-//     use(super.m++);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:102:13: Error: Superclass has no setter named 'e'.
-//     ++super.e;
-//             ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:103:17: Error: Superclass has no setter named 'e'.
-//     use(++super.e);
-//                 ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:104:13: Error: Superclass has no setter named 'f'.
-//     ++super.f;
-//             ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:105:17: Error: Superclass has no setter named 'f'.
-//     use(++super.f);
-//                 ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:106:13: Error: Superclass has no getter named 'g'.
-//     ++super.g;
-//             ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:107:17: Error: Superclass has no getter named 'g'.
-//     use(++super.g);
-//                 ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:114:13: Error: Superclass has no setter named 'm'.
-//     ++super.m;
-//             ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:115:17: Error: Superclass has no setter named 'm'.
-//     use(++super.m);
-//                 ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:129:11: Error: Superclass has no method named 'g'.
-//     super.g();
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:130:15: Error: Superclass has no method named 'g'.
-//     use(super.g());
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:150:11: Error: Superclass has no setter named 'e'.
-//     super.e = 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:151:15: Error: Superclass has no setter named 'e'.
-//     use(super.e = 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:152:11: Error: Superclass has no setter named 'f'.
-//     super.f = 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:153:15: Error: Superclass has no setter named 'f'.
-//     use(super.f = 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:162:11: Error: Superclass has no setter named 'm'.
-//     super.m = 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:163:15: Error: Superclass has no setter named 'm'.
-//     use(super.m = 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:173:11: Error: Superclass has no setter named 'e'.
-//     super.e ??= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:174:15: Error: Superclass has no setter named 'e'.
-//     use(super.e ??= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:175:11: Error: Superclass has no setter named 'f'.
-//     super.f ??= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:176:15: Error: Superclass has no setter named 'f'.
-//     use(super.f ??= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:177:11: Error: Superclass has no getter named 'g'.
-//     super.g ??= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:178:15: Error: Superclass has no getter named 'g'.
-//     use(super.g ??= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:185:11: Error: Superclass has no setter named 'm'.
-//     super.m ??= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:186:15: Error: Superclass has no setter named 'm'.
-//     use(super.m ??= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:196:11: Error: Superclass has no setter named 'e'.
-//     super.e += 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:197:15: Error: Superclass has no setter named 'e'.
-//     use(super.e += 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:198:11: Error: Superclass has no setter named 'f'.
-//     super.f += 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:199:15: Error: Superclass has no setter named 'f'.
-//     use(super.f += 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:200:11: Error: Superclass has no getter named 'g'.
-//     super.g += 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:201:15: Error: Superclass has no getter named 'g'.
-//     use(super.g += 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:208:11: Error: Superclass has no setter named 'm'.
-//     super.m += 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:209:15: Error: Superclass has no setter named 'm'.
-//     use(super.m += 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:219:11: Error: Superclass has no setter named 'e'.
-//     super.e -= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:220:15: Error: Superclass has no setter named 'e'.
-//     use(super.e -= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:221:11: Error: Superclass has no setter named 'f'.
-//     super.f -= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:222:15: Error: Superclass has no setter named 'f'.
-//     use(super.f -= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:223:11: Error: Superclass has no getter named 'g'.
-//     super.g -= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:224:15: Error: Superclass has no getter named 'g'.
-//     use(super.g -= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:231:11: Error: Superclass has no setter named 'm'.
-//     super.m -= 42;
-//           ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:232:15: Error: Superclass has no setter named 'm'.
-//     use(super.m -= 42);
-//               ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:139:12: Error: Too many positional arguments: 0 allowed, but 1 found.
-// Try removing the extra positional arguments.
-//     super.m(87);
-//            ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:140:16: Error: Too many positional arguments: 0 allowed, but 1 found.
-// Try removing the extra positional arguments.
-//     use(super.m(87));
-//                ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:14:9: Error: Final field 'f' is not initialized.
-// Try to initialize the field in the declaration or in every constructor.
-//   final f;
-//         ^
-//
-// pkg/front_end/testcases/super_rasta_copy.dart:33:9: Error: Final field 'd' is not initialized.
-// Try to initialize the field in the declaration or in every constructor.
-//   final d;
-//         ^
-
-library;
-import self as self;
-import "dart:core" as core;
-
-class A extends core::Object {
-  field dynamic a = null;
-  field dynamic b = null;
-  field dynamic c = null;
-  field dynamic d = null;
-  final field dynamic f = null;
-  synthetic constructor •() → void
-    : super core::Object::•()
-    ;
-  get e() → dynamic
-    return null;
-  set g(dynamic _) → void {}
-  get h() → dynamic
-    return null;
-  set h(dynamic _) → void {}
-  get i() → dynamic
-    return null;
-  operator [](dynamic _) → dynamic
-    return null;
-  operator []=(dynamic a, dynamic b) → void {}
-  operator ~() → dynamic
-    return 117;
-  operator unary-() → dynamic
-    return 117;
-  operator ==(dynamic other) → core::bool
-    return true;
-  method m() → void {}
-}
-class B extends self::A {
-  final field dynamic d = null;
-  synthetic constructor •() → void
-    : super self::A::•()
-    ;
-  get b() → dynamic
-    return null;
-  set c(dynamic x) → void {}
-  set i(dynamic x) → void {}
-}
-class C extends self::B {
-  synthetic constructor •() → void
-    : super self::B::•()
-    ;
-  method test() → dynamic {
-    super.{self::A::~}();
-    self::use(super.{self::A::~}());
-    super.{self::A::unary-}();
-    self::use(super.{self::A::unary-}());
-    super.{self::A::==}(87);
-    self::use(super.{self::A::==}(87));
-    !super.{self::A::==}(87);
-    self::use(!super.{self::A::==}(87));
-    super.{self::A::a};
-    self::use(super.{self::A::a});
-    super.{self::B::b};
-    self::use(super.{self::B::b});
-    super.{self::A::c};
-    self::use(super.{self::A::c});
-    super.{self::B::d};
-    self::use(super.{self::B::d});
-    super.{self::A::e};
-    self::use(super.{self::A::e});
-    super.{self::A::f};
-    self::use(super.{self::A::f});
-    super.g;
-    self::use(super.g);
-    super.{self::A::h};
-    self::use(super.{self::A::h});
-    super.{self::A::i};
-    self::use(super.{self::A::i});
-    super.{self::A::[]}(87);
-    self::use(super.{self::A::[]}(87));
-    super.{self::A::m};
-    self::use(super.{self::A::m});
-    super.{self::A::a} = super.{self::A::a}.+(1);
-    self::use(let final dynamic #t1 = super.{self::A::a} in let final dynamic #t2 = super.{self::A::a} = #t1.+(1) in #t1);
-    super.{self::A::b} = super.{self::B::b}.+(1);
-    self::use(let final dynamic #t3 = super.{self::B::b} in let final dynamic #t4 = super.{self::A::b} = #t3.+(1) in #t3);
-    super.{self::B::c} = super.{self::A::c}.+(1);
-    self::use(let final dynamic #t5 = super.{self::A::c} in let final dynamic #t6 = super.{self::B::c} = #t5.+(1) in #t5);
-    super.{self::A::d} = super.{self::B::d}.+(1);
-    self::use(let final dynamic #t7 = super.{self::B::d} in let final dynamic #t8 = super.{self::A::d} = #t7.+(1) in #t7);
-    super.e = super.{self::A::e}.+(1);
-    self::use(let final dynamic #t9 = super.{self::A::e} in let final dynamic #t10 = super.e = #t9.+(1) in #t9);
-    super.f = super.{self::A::f}.+(1);
-    self::use(let final dynamic #t11 = super.{self::A::f} in let final dynamic #t12 = super.f = #t11.+(1) in #t11);
-    super.{self::A::g} = super.g.+(1);
-    self::use(let final dynamic #t13 = super.g in let final dynamic #t14 = super.{self::A::g} = #t13.+(1) in #t13);
-    super.{self::A::h} = super.{self::A::h}.+(1);
-    self::use(let final dynamic #t15 = super.{self::A::h} in let final dynamic #t16 = super.{self::A::h} = #t15.+(1) in #t15);
-    super.{self::B::i} = super.{self::A::i}.+(1);
-    self::use(let final dynamic #t17 = super.{self::A::i} in let final dynamic #t18 = super.{self::B::i} = #t17.+(1) in #t17);
-    let final core::int #t19 = 87 in super.{self::A::[]=}(#t19, super.{self::A::[]}(#t19).+(1));
-    self::use(let final core::int #t20 = 87 in let final dynamic #t21 = super.{self::A::[]}(#t20) in let final void #t22 = super.{self::A::[]=}(#t20, #t21.+(1)) in #t21);
-    super.m = let final dynamic #t23 = super.{self::A::m} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/super_rasta_copy.dart:91:12: Error: The method '+' isn't defined for the class '() \u8594 void'.
-Try correcting the name to the name of an existing method, or defining a method named '+'.
-    super.m++;
-           ^";
-    self::use(let final () → void #t24 = super.{self::A::m} in let final dynamic #t25 = super.m = let final dynamic #t26 = #t24 in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/super_rasta_copy.dart:92:16: Error: The method '+' isn't defined for the class '() \u8594 void'.
-Try correcting the name to the name of an existing method, or defining a method named '+'.
-    use(super.m++);
-               ^" in #t24);
-    super.{self::A::a} = super.{self::A::a}.+(1);
-    self::use(super.{self::A::a} = super.{self::A::a}.+(1));
-    super.{self::A::b} = super.{self::B::b}.+(1);
-    self::use(super.{self::A::b} = super.{self::B::b}.+(1));
-    super.{self::B::c} = super.{self::A::c}.+(1);
-    self::use(super.{self::B::c} = super.{self::A::c}.+(1));
-    super.{self::A::d} = super.{self::B::d}.+(1);
-    self::use(super.{self::A::d} = super.{self::B::d}.+(1));
-    super.e = super.{self::A::e}.+(1);
-    self::use(super.e = super.{self::A::e}.+(1));
-    super.f = super.{self::A::f}.+(1);
-    self::use(super.f = super.{self::A::f}.+(1));
-    super.{self::A::g} = super.g.+(1);
-    self::use(super.{self::A::g} = super.g.+(1));
-    super.{self::A::h} = super.{self::A::h}.+(1);
-    self::use(super.{self::A::h} = super.{self::A::h}.+(1));
-    super.{self::B::i} = super.{self::A::i}.+(1);
-    self::use(super.{self::B::i} = super.{self::A::i}.+(1));
-    let final core::int #t27 = 87 in let final dynamic #t28 = super.{self::A::[]}(#t27).+(1) in let final void #t29 = super.{self::A::[]=}(#t27, #t28) in #t28;
-    self::use(let final core::int #t30 = 87 in let final dynamic #t31 = super.{self::A::[]}(#t30).+(1) in let final void #t32 = super.{self::A::[]=}(#t30, #t31) in #t31);
-    super.m = let final dynamic #t33 = super.{self::A::m} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/super_rasta_copy.dart:114:5: Error: The method '+' isn't defined for the class '() \u8594 void'.
-Try correcting the name to the name of an existing method, or defining a method named '+'.
-    ++super.m;
-    ^";
-    self::use(super.m = let final dynamic #t34 = super.{self::A::m} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/super_rasta_copy.dart:115:9: Error: The method '+' isn't defined for the class '() \u8594 void'.
-Try correcting the name to the name of an existing method, or defining a method named '+'.
-    use(++super.m);
-        ^");
-    super.{self::A::a}.call();
-    self::use(super.{self::A::a}.call());
-    super.{self::B::b}.call();
-    self::use(super.{self::B::b}.call());
-    super.{self::A::c}.call();
-    self::use(super.{self::A::c}.call());
-    super.{self::B::d}.call();
-    self::use(super.{self::B::d}.call());
-    super.{self::A::e}.call();
-    self::use(super.{self::A::e}.call());
-    super.{self::A::f}.call();
-    self::use(super.{self::A::f}.call());
-    super.g();
-    self::use(super.g());
-    super.{self::A::h}.call();
-    self::use(super.{self::A::h}.call());
-    super.{self::A::i}.call();
-    self::use(super.{self::A::i}.call());
-    super.{self::A::[]}(87).call();
-    self::use(super.{self::A::[]}(87).call());
-    super.{self::A::m}();
-    self::use(super.{self::A::m}());
-    super.{self::A::m}(87);
-    self::use(super.{self::A::m}(87));
-    super.{self::A::a} = 42;
-    self::use(super.{self::A::a} = 42);
-    super.{self::A::b} = 42;
-    self::use(super.{self::A::b} = 42);
-    super.{self::B::c} = 42;
-    self::use(super.{self::B::c} = 42);
-    super.{self::A::d} = 42;
-    self::use(super.{self::A::d} = 42);
-    super.e = 42;
-    self::use(super.e = 42);
-    super.f = 42;
-    self::use(super.f = 42);
-    super.{self::A::g} = 42;
-    self::use(super.{self::A::g} = 42);
-    super.{self::A::h} = 42;
-    self::use(super.{self::A::h} = 42);
-    super.{self::B::i} = 42;
-    self::use(super.{self::B::i} = 42);
-    super.{self::A::[]=}(87, 42);
-    self::use(let final core::int #t35 = 87 in let final core::int #t36 = 42 in let final void #t37 = super.{self::A::[]=}(#t35, #t36) in #t36);
-    super.m = 42;
-    self::use(super.m = 42);
-    super.{self::A::a}.{core::Object::==}(null) ?{dynamic} super.{self::A::a} = 42 : null;
-    self::use(let final dynamic #t38 = super.{self::A::a} in #t38.{core::Object::==}(null) ?{dynamic} super.{self::A::a} = 42 : #t38);
-    super.{self::B::b}.{core::Object::==}(null) ?{dynamic} super.{self::A::b} = 42 : null;
-    self::use(let final dynamic #t39 = super.{self::B::b} in #t39.{core::Object::==}(null) ?{dynamic} super.{self::A::b} = 42 : #t39);
-    super.{self::A::c}.{core::Object::==}(null) ?{dynamic} super.{self::B::c} = 42 : null;
-    self::use(let final dynamic #t40 = super.{self::A::c} in #t40.{core::Object::==}(null) ?{dynamic} super.{self::B::c} = 42 : #t40);
-    super.{self::B::d}.{core::Object::==}(null) ?{dynamic} super.{self::A::d} = 42 : null;
-    self::use(let final dynamic #t41 = super.{self::B::d} in #t41.{core::Object::==}(null) ?{dynamic} super.{self::A::d} = 42 : #t41);
-    super.{self::A::e}.{core::Object::==}(null) ?{dynamic} super.e = 42 : null;
-    self::use(let final dynamic #t42 = super.{self::A::e} in #t42.{core::Object::==}(null) ?{dynamic} super.e = 42 : #t42);
-    super.{self::A::f}.{core::Object::==}(null) ?{dynamic} super.f = 42 : null;
-    self::use(let final dynamic #t43 = super.{self::A::f} in #t43.{core::Object::==}(null) ?{dynamic} super.f = 42 : #t43);
-    super.g.{core::Object::==}(null) ?{dynamic} super.{self::A::g} = 42 : null;
-    self::use(let final dynamic #t44 = super.g in #t44.{core::Object::==}(null) ?{dynamic} super.{self::A::g} = 42 : #t44);
-    super.{self::A::h}.{core::Object::==}(null) ?{dynamic} super.{self::A::h} = 42 : null;
-    self::use(let final dynamic #t45 = super.{self::A::h} in #t45.{core::Object::==}(null) ?{dynamic} super.{self::A::h} = 42 : #t45);
-    super.{self::A::i}.{core::Object::==}(null) ?{dynamic} super.{self::B::i} = 42 : null;
-    self::use(let final dynamic #t46 = super.{self::A::i} in #t46.{core::Object::==}(null) ?{dynamic} super.{self::B::i} = 42 : #t46);
-    let final core::int #t47 = 87 in super.{self::A::[]}(#t47).{core::Object::==}(null) ?{dynamic} let final core::int #t48 = 42 in let final void #t49 = super.{self::A::[]=}(#t47, #t48) in #t48 : null;
-    self::use(let final core::int #t50 = 87 in let final dynamic #t51 = super.{self::A::[]}(#t50) in #t51.{core::Object::==}(null) ?{dynamic} let final core::int #t52 = 42 in let final void #t53 = super.{self::A::[]=}(#t50, #t52) in #t52 : #t51);
-    super.{self::A::m}.{core::Object::==}(null) ?{core::Object} super.m = 42 : null;
-    self::use(let final () → void #t54 = super.{self::A::m} in #t54.{core::Object::==}(null) ?{core::Object} super.m = 42 : #t54);
-    super.{self::A::a} = super.{self::A::a}.+(42);
-    self::use(super.{self::A::a} = super.{self::A::a}.+(42));
-    super.{self::A::b} = super.{self::B::b}.+(42);
-    self::use(super.{self::A::b} = super.{self::B::b}.+(42));
-    super.{self::B::c} = super.{self::A::c}.+(42);
-    self::use(super.{self::B::c} = super.{self::A::c}.+(42));
-    super.{self::A::d} = super.{self::B::d}.+(42);
-    self::use(super.{self::A::d} = super.{self::B::d}.+(42));
-    super.e = super.{self::A::e}.+(42);
-    self::use(super.e = super.{self::A::e}.+(42));
-    super.f = super.{self::A::f}.+(42);
-    self::use(super.f = super.{self::A::f}.+(42));
-    super.{self::A::g} = super.g.+(42);
-    self::use(super.{self::A::g} = super.g.+(42));
-    super.{self::A::h} = super.{self::A::h}.+(42);
-    self::use(super.{self::A::h} = super.{self::A::h}.+(42));
-    super.{self::B::i} = super.{self::A::i}.+(42);
-    self::use(super.{self::B::i} = super.{self::A::i}.+(42));
-    let final core::int #t55 = 87 in super.{self::A::[]=}(#t55, super.{self::A::[]}(#t55).+(42));
-    self::use(let final core::int #t56 = 87 in let final dynamic #t57 = super.{self::A::[]}(#t56).+(42) in let final void #t58 = super.{self::A::[]=}(#t56, #t57) in #t57);
-    super.m = let final dynamic #t59 = super.{self::A::m} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/super_rasta_copy.dart:208:13: Error: The method '+' isn't defined for the class '() \u8594 void'.
-Try correcting the name to the name of an existing method, or defining a method named '+'.
-    super.m += 42;
-            ^";
-    self::use(super.m = let final dynamic #t60 = super.{self::A::m} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/super_rasta_copy.dart:209:17: Error: The method '+' isn't defined for the class '() \u8594 void'.
-Try correcting the name to the name of an existing method, or defining a method named '+'.
-    use(super.m += 42);
-                ^");
-    super.{self::A::a} = super.{self::A::a}.-(42);
-    self::use(super.{self::A::a} = super.{self::A::a}.-(42));
-    super.{self::A::b} = super.{self::B::b}.-(42);
-    self::use(super.{self::A::b} = super.{self::B::b}.-(42));
-    super.{self::B::c} = super.{self::A::c}.-(42);
-    self::use(super.{self::B::c} = super.{self::A::c}.-(42));
-    super.{self::A::d} = super.{self::B::d}.-(42);
-    self::use(super.{self::A::d} = super.{self::B::d}.-(42));
-    super.e = super.{self::A::e}.-(42);
-    self::use(super.e = super.{self::A::e}.-(42));
-    super.f = super.{self::A::f}.-(42);
-    self::use(super.f = super.{self::A::f}.-(42));
-    super.{self::A::g} = super.g.-(42);
-    self::use(super.{self::A::g} = super.g.-(42));
-    super.{self::A::h} = super.{self::A::h}.-(42);
-    self::use(super.{self::A::h} = super.{self::A::h}.-(42));
-    super.{self::B::i} = super.{self::A::i}.-(42);
-    self::use(super.{self::B::i} = super.{self::A::i}.-(42));
-    let final core::int #t61 = 87 in super.{self::A::[]=}(#t61, super.{self::A::[]}(#t61).-(42));
-    self::use(let final core::int #t62 = 87 in let final dynamic #t63 = super.{self::A::[]}(#t62).-(42) in let final void #t64 = super.{self::A::[]=}(#t62, #t63) in #t63);
-    super.m = let final dynamic #t65 = super.{self::A::m} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/super_rasta_copy.dart:231:13: Error: The method '-' isn't defined for the class '() \u8594 void'.
-Try correcting the name to the name of an existing method, or defining a method named '-'.
-    super.m -= 42;
-            ^";
-    self::use(super.m = let final dynamic #t66 = super.{self::A::m} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/super_rasta_copy.dart:232:17: Error: The method '-' isn't defined for the class '() \u8594 void'.
-Try correcting the name to the name of an existing method, or defining a method named '-'.
-    use(super.m -= 42);
-                ^");
-  }
-}
-static method use(dynamic x) → dynamic {
-  if(x.{core::Object::==}(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}))
-    throw "Shouldn't happen";
-}
-static method main() → dynamic {
-  try {
-    new self::C::•().{self::C::test}();
-  }
-  on core::NoSuchMethodError catch(no-exception-var) {
-    return;
-  }
-  throw "Test failed";
-}
diff --git a/pkg/front_end/testcases/tabs.dart.direct.expect b/pkg/front_end/testcases/tabs.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/tabs.dart.direct.expect
rename to pkg/front_end/testcases/tabs.dart.legacy.expect
diff --git a/pkg/front_end/testcases/tabs.dart.direct.transformed.expect b/pkg/front_end/testcases/tabs.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/tabs.dart.direct.transformed.expect
rename to pkg/front_end/testcases/tabs.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/top_level_accessors.dart.direct.expect b/pkg/front_end/testcases/top_level_accessors.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/top_level_accessors.dart.direct.expect
rename to pkg/front_end/testcases/top_level_accessors.dart.legacy.expect
diff --git a/pkg/front_end/testcases/top_level_accessors.dart.direct.transformed.expect b/pkg/front_end/testcases/top_level_accessors.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/top_level_accessors.dart.direct.transformed.expect
rename to pkg/front_end/testcases/top_level_accessors.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/top_level_accessors.dart.direct.expect b/pkg/front_end/testcases/top_level_accessors.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/top_level_accessors.dart.direct.expect
copy to pkg/front_end/testcases/top_level_accessors.dart.strong.expect
diff --git a/pkg/front_end/testcases/top_level_accessors.dart.direct.transformed.expect b/pkg/front_end/testcases/top_level_accessors.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/top_level_accessors.dart.direct.transformed.expect
copy to pkg/front_end/testcases/top_level_accessors.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/top_level_library_method.dart.direct.expect b/pkg/front_end/testcases/top_level_library_method.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/top_level_library_method.dart.direct.expect
rename to pkg/front_end/testcases/top_level_library_method.dart.legacy.expect
diff --git a/pkg/front_end/testcases/top_level_library_method.dart.direct.transformed.expect b/pkg/front_end/testcases/top_level_library_method.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/top_level_library_method.dart.direct.transformed.expect
rename to pkg/front_end/testcases/top_level_library_method.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/type_promotion_look_ahead.status b/pkg/front_end/testcases/type_promotion_look_ahead.status
new file mode 100644
index 0000000..bee4fdc
--- /dev/null
+++ b/pkg/front_end/testcases/type_promotion_look_ahead.status
@@ -0,0 +1,5 @@
+# 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.md file.
+
+# Status file for the ../test/fasta/type_promotion_look_ahead_test.dart test suite.
diff --git a/pkg/front_end/testcases/type_variable_as_super.dart.direct.expect b/pkg/front_end/testcases/type_variable_as_super.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/type_variable_as_super.dart.direct.expect
rename to pkg/front_end/testcases/type_variable_as_super.dart.legacy.expect
diff --git a/pkg/front_end/testcases/type_variable_as_super.dart.strong.expect b/pkg/front_end/testcases/type_variable_as_super.dart.strong.expect
new file mode 100644
index 0000000..965f277
--- /dev/null
+++ b/pkg/front_end/testcases/type_variable_as_super.dart.strong.expect
@@ -0,0 +1,68 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:5:16: Error: The type variable 'T' can't be used as supertype.
+// abstract class A<T> extends T {}
+//                ^
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:7:16: Error: The type variable 'T' can't be used as supertype.
+// abstract class B<T> extends T {
+//                ^
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:11:7: Error: The type variable 'T' can't be used as supertype.
+// class C<T> extends T {}
+//       ^
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:14:7: Error: The class 'A' is abstract and can't be instantiated.
+//   new A();
+//       ^
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:15:7: Error: The class 'B' is abstract and can't be instantiated.
+//   new B();
+//       ^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:5:16: Error: The type variable 'T' can't be used as supertype.
+// abstract class A<T> extends T {}
+//                ^
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:7:16: Error: The type variable 'T' can't be used as supertype.
+// abstract class B<T> extends T {
+//                ^
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:11:7: Error: The type variable 'T' can't be used as supertype.
+// class C<T> extends T {}
+//       ^
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:14:7: Error: The class 'A' is abstract and can't be instantiated.
+//   new A();
+//       ^
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:15:7: Error: The class 'B' is abstract and can't be instantiated.
+//   new B();
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+}
+abstract class B<T extends core::Object = dynamic> extends core::Object {
+  constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  throw new core::AbstractClassInstantiationError::•("A");
+  throw new core::AbstractClassInstantiationError::•("B");
+  new self::C::•<dynamic>();
+}
diff --git a/pkg/front_end/testcases/type_variable_as_super.dart.strong.transformed.expect b/pkg/front_end/testcases/type_variable_as_super.dart.strong.transformed.expect
new file mode 100644
index 0000000..d58011a
--- /dev/null
+++ b/pkg/front_end/testcases/type_variable_as_super.dart.strong.transformed.expect
@@ -0,0 +1,46 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:5:16: Error: The type variable 'T' can't be used as supertype.
+// abstract class A<T> extends T {}
+//                ^
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:7:16: Error: The type variable 'T' can't be used as supertype.
+// abstract class B<T> extends T {
+//                ^
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:11:7: Error: The type variable 'T' can't be used as supertype.
+// class C<T> extends T {}
+//       ^
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:14:7: Error: The class 'A' is abstract and can't be instantiated.
+//   new A();
+//       ^
+//
+// pkg/front_end/testcases/type_variable_as_super.dart:15:7: Error: The class 'B' is abstract and can't be instantiated.
+//   new B();
+//       ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+}
+abstract class B<T extends core::Object = dynamic> extends core::Object {
+  constructor •() → self::B<self::B::T>
+    : super core::Object::•()
+    ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  throw new core::AbstractClassInstantiationError::•("A");
+  throw new core::AbstractClassInstantiationError::•("B");
+  new self::C::•<dynamic>();
+}
diff --git a/pkg/front_end/testcases/type_variable_prefix.dart.direct.expect b/pkg/front_end/testcases/type_variable_prefix.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/type_variable_prefix.dart.direct.expect
rename to pkg/front_end/testcases/type_variable_prefix.dart.legacy.expect
diff --git a/pkg/front_end/testcases/type_variable_prefix.dart.direct.transformed.expect b/pkg/front_end/testcases/type_variable_prefix.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/type_variable_prefix.dart.direct.transformed.expect
rename to pkg/front_end/testcases/type_variable_prefix.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/type_variable_uses.dart.direct.expect b/pkg/front_end/testcases/type_variable_uses.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/type_variable_uses.dart.direct.expect
rename to pkg/front_end/testcases/type_variable_uses.dart.legacy.expect
diff --git a/pkg/front_end/testcases/type_variable_uses.dart.direct.transformed.expect b/pkg/front_end/testcases/type_variable_uses.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/type_variable_uses.dart.direct.transformed.expect
rename to pkg/front_end/testcases/type_variable_uses.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/typedef.dart.direct.expect b/pkg/front_end/testcases/typedef.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/typedef.dart.direct.expect
rename to pkg/front_end/testcases/typedef.dart.legacy.expect
diff --git a/pkg/front_end/testcases/typedef.dart.direct.transformed.expect b/pkg/front_end/testcases/typedef.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/typedef.dart.direct.transformed.expect
rename to pkg/front_end/testcases/typedef.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/typedef.dart.direct.expect b/pkg/front_end/testcases/typedef.dart.strong.expect
similarity index 100%
copy from pkg/front_end/testcases/typedef.dart.direct.expect
copy to pkg/front_end/testcases/typedef.dart.strong.expect
diff --git a/pkg/front_end/testcases/typedef.dart.direct.transformed.expect b/pkg/front_end/testcases/typedef.dart.strong.transformed.expect
similarity index 100%
copy from pkg/front_end/testcases/typedef.dart.direct.transformed.expect
copy to pkg/front_end/testcases/typedef.dart.strong.transformed.expect
diff --git a/pkg/front_end/testcases/undefined.dart.direct.expect b/pkg/front_end/testcases/undefined.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/undefined.dart.direct.expect
rename to pkg/front_end/testcases/undefined.dart.legacy.expect
diff --git a/pkg/front_end/testcases/undefined.dart.direct.transformed.expect b/pkg/front_end/testcases/undefined.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/undefined.dart.direct.transformed.expect
rename to pkg/front_end/testcases/undefined.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.direct.expect b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.direct.expect
rename to pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.legacy.expect
diff --git a/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.direct.transformed.expect b/pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.direct.transformed.expect
rename to pkg/front_end/testcases/undefined_getter_in_compound_assignment.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/uninitialized_fields.dart.direct.expect b/pkg/front_end/testcases/uninitialized_fields.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/uninitialized_fields.dart.direct.expect
rename to pkg/front_end/testcases/uninitialized_fields.dart.legacy.expect
diff --git a/pkg/front_end/testcases/uninitialized_fields.dart.strong.expect b/pkg/front_end/testcases/uninitialized_fields.dart.strong.expect
index bef6d48..843de869 100644
--- a/pkg/front_end/testcases/uninitialized_fields.dart.strong.expect
+++ b/pkg/front_end/testcases/uninitialized_fields.dart.strong.expect
@@ -1,4 +1,37 @@
 library;
 import self as self;
+import "dart:core" as core;
 
+class Uninitialized extends core::Object {
+  field core::int x = null;
+  synthetic constructor •() → self::Uninitialized
+    : super core::Object::•()
+    ;
+}
+class PartiallyInitialized extends core::Object {
+  field core::int x;
+  constructor •(core::int x) → self::PartiallyInitialized
+    : self::PartiallyInitialized::x = x, super core::Object::•()
+    ;
+  constructor noInitializer() → self::PartiallyInitialized
+    : self::PartiallyInitialized::x = null, super core::Object::•()
+    ;
+}
+class Initialized extends core::Object {
+  field core::int x;
+  constructor •(core::int x) → self::Initialized
+    : self::Initialized::x = x, super core::Object::•()
+    ;
+}
+class Forwarding extends core::Object {
+  field core::int x;
+  constructor initialize(core::int x) → self::Forwarding
+    : self::Forwarding::x = x, super core::Object::•()
+    ;
+  constructor •(core::int arg) → self::Forwarding
+    : this self::Forwarding::initialize(arg)
+    ;
+}
+static field core::int uninitializedTopLevel;
+static field core::int initializedTopLevel = 4;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/uninitialized_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/uninitialized_fields.dart.strong.transformed.expect
new file mode 100644
index 0000000..843de869
--- /dev/null
+++ b/pkg/front_end/testcases/uninitialized_fields.dart.strong.transformed.expect
@@ -0,0 +1,37 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Uninitialized extends core::Object {
+  field core::int x = null;
+  synthetic constructor •() → self::Uninitialized
+    : super core::Object::•()
+    ;
+}
+class PartiallyInitialized extends core::Object {
+  field core::int x;
+  constructor •(core::int x) → self::PartiallyInitialized
+    : self::PartiallyInitialized::x = x, super core::Object::•()
+    ;
+  constructor noInitializer() → self::PartiallyInitialized
+    : self::PartiallyInitialized::x = null, super core::Object::•()
+    ;
+}
+class Initialized extends core::Object {
+  field core::int x;
+  constructor •(core::int x) → self::Initialized
+    : self::Initialized::x = x, super core::Object::•()
+    ;
+}
+class Forwarding extends core::Object {
+  field core::int x;
+  constructor initialize(core::int x) → self::Forwarding
+    : self::Forwarding::x = x, super core::Object::•()
+    ;
+  constructor •(core::int arg) → self::Forwarding
+    : this self::Forwarding::initialize(arg)
+    ;
+}
+static field core::int uninitializedTopLevel;
+static field core::int initializedTopLevel = 4;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/unused_methods.dart.direct.expect b/pkg/front_end/testcases/unused_methods.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/unused_methods.dart.direct.expect
rename to pkg/front_end/testcases/unused_methods.dart.legacy.expect
diff --git a/pkg/front_end/testcases/unused_methods.dart.direct.transformed.expect b/pkg/front_end/testcases/unused_methods.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/unused_methods.dart.direct.transformed.expect
rename to pkg/front_end/testcases/unused_methods.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/unused_methods.dart.strong.expect b/pkg/front_end/testcases/unused_methods.dart.strong.expect
index cb22b9b..d57f97d 100644
--- a/pkg/front_end/testcases/unused_methods.dart.strong.expect
+++ b/pkg/front_end/testcases/unused_methods.dart.strong.expect
@@ -2,28 +2,44 @@
 import self as self;
 import "dart:core" as core;
 
+class UnusedClass extends core::Object {
+  constructor •() → self::UnusedClass
+    : super core::Object::•() {
+    core::print("Unused");
+  }
+}
 abstract class UsedAsBaseClass extends core::Object {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::UsedAsBaseClass
     : super core::Object::•()
     ;
-  abstract method usedInSubclass() → void;
+  method usedInSubclass() → void {
+    core::print("Unused");
+  }
   method calledFromB() → void {
     this.{self::UsedAsBaseClass::calledFromSubclass}();
   }
-  abstract method calledFromSubclass() → void;
+  method calledFromSubclass() → void {
+    core::print("Unused");
+  }
 }
-abstract class UsedAsInterface extends core::Object {
-  abstract method usedInSubclass() → void;
-}
-class InstantiatedButMethodsUnused extends core::Object {
-  synthetic constructor •() → void
+class UsedAsInterface extends core::Object {
+  synthetic constructor •() → self::UsedAsInterface
     : super core::Object::•()
     ;
-  method usedInSubclass() → void
-    throw "Method removed by tree-shaking";
+  method usedInSubclass() → void {
+    core::print("Unused");
+  }
+}
+class InstantiatedButMethodsUnused extends core::Object {
+  synthetic constructor •() → self::InstantiatedButMethodsUnused
+    : super core::Object::•()
+    ;
+  method usedInSubclass() → void {
+    core::print("Unused");
+  }
 }
 class ClassA extends self::UsedAsBaseClass implements self::UsedAsInterface, self::InstantiatedButMethodsUnused {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::ClassA
     : super self::UsedAsBaseClass::•()
     ;
   method usedInSubclass() → void {
@@ -31,7 +47,7 @@
   }
 }
 class ClassB extends self::UsedAsBaseClass implements self::UsedAsInterface, self::InstantiatedButMethodsUnused {
-  synthetic constructor •() → void
+  synthetic constructor •() → self::ClassB
     : super self::UsedAsBaseClass::•()
     ;
   method usedInSubclass() → void {
@@ -52,6 +68,9 @@
 static method exactCallB(self::ClassB object) → void {
   object.{self::ClassB::usedInSubclass}();
 }
+static method unusedTopLevel() → dynamic {
+  core::print("Unused");
+}
 static method usedTopLevel() → dynamic {}
 static method main() → dynamic {
   self::usedTopLevel();
diff --git a/pkg/front_end/testcases/unused_methods.dart.strong.transformed.expect b/pkg/front_end/testcases/unused_methods.dart.strong.transformed.expect
new file mode 100644
index 0000000..d57f97d
--- /dev/null
+++ b/pkg/front_end/testcases/unused_methods.dart.strong.transformed.expect
@@ -0,0 +1,86 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class UnusedClass extends core::Object {
+  constructor •() → self::UnusedClass
+    : super core::Object::•() {
+    core::print("Unused");
+  }
+}
+abstract class UsedAsBaseClass extends core::Object {
+  synthetic constructor •() → self::UsedAsBaseClass
+    : super core::Object::•()
+    ;
+  method usedInSubclass() → void {
+    core::print("Unused");
+  }
+  method calledFromB() → void {
+    this.{self::UsedAsBaseClass::calledFromSubclass}();
+  }
+  method calledFromSubclass() → void {
+    core::print("Unused");
+  }
+}
+class UsedAsInterface extends core::Object {
+  synthetic constructor •() → self::UsedAsInterface
+    : super core::Object::•()
+    ;
+  method usedInSubclass() → void {
+    core::print("Unused");
+  }
+}
+class InstantiatedButMethodsUnused extends core::Object {
+  synthetic constructor •() → self::InstantiatedButMethodsUnused
+    : super core::Object::•()
+    ;
+  method usedInSubclass() → void {
+    core::print("Unused");
+  }
+}
+class ClassA extends self::UsedAsBaseClass implements self::UsedAsInterface, self::InstantiatedButMethodsUnused {
+  synthetic constructor •() → self::ClassA
+    : super self::UsedAsBaseClass::•()
+    ;
+  method usedInSubclass() → void {
+    core::print("A");
+  }
+}
+class ClassB extends self::UsedAsBaseClass implements self::UsedAsInterface, self::InstantiatedButMethodsUnused {
+  synthetic constructor •() → self::ClassB
+    : super self::UsedAsBaseClass::•()
+    ;
+  method usedInSubclass() → void {
+    core::print("B");
+    this.{self::UsedAsBaseClass::calledFromB}();
+  }
+  method calledFromSubclass() → void {}
+}
+static method baseClassCall(self::UsedAsBaseClass object) → void {
+  object.{self::UsedAsBaseClass::usedInSubclass}();
+}
+static method interfaceCall(self::UsedAsInterface object) → void {
+  object.{self::UsedAsInterface::usedInSubclass}();
+}
+static method exactCallA(self::ClassA object) → void {
+  object.{self::ClassA::usedInSubclass}();
+}
+static method exactCallB(self::ClassB object) → void {
+  object.{self::ClassB::usedInSubclass}();
+}
+static method unusedTopLevel() → dynamic {
+  core::print("Unused");
+}
+static method usedTopLevel() → dynamic {}
+static method main() → dynamic {
+  self::usedTopLevel();
+  self::ClassA a = new self::ClassA::•();
+  self::exactCallA(a);
+  self::baseClassCall(a);
+  self::interfaceCall(a);
+  self::ClassB b = new self::ClassB::•();
+  self::exactCallB(b);
+  self::baseClassCall(b);
+  self::interfaceCall(b);
+  new self::InstantiatedButMethodsUnused::•();
+}
diff --git a/pkg/front_end/testcases/var_as_type_name.dart.direct.expect b/pkg/front_end/testcases/var_as_type_name.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/var_as_type_name.dart.direct.expect
rename to pkg/front_end/testcases/var_as_type_name.dart.legacy.expect
diff --git a/pkg/front_end/testcases/var_as_type_name.dart.direct.transformed.expect b/pkg/front_end/testcases/var_as_type_name.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/var_as_type_name.dart.direct.transformed.expect
rename to pkg/front_end/testcases/var_as_type_name.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testcases/void_methods.dart.direct.expect b/pkg/front_end/testcases/void_methods.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/void_methods.dart.direct.expect
rename to pkg/front_end/testcases/void_methods.dart.legacy.expect
diff --git a/pkg/front_end/testcases/void_methods.dart.strong.expect b/pkg/front_end/testcases/void_methods.dart.strong.expect
index ca84f50..2dd976f 100644
--- a/pkg/front_end/testcases/void_methods.dart.strong.expect
+++ b/pkg/front_end/testcases/void_methods.dart.strong.expect
@@ -4,7 +4,7 @@
 
 class Foo extends core::Object {
   field core::List<dynamic> list = <dynamic>[1, 2, 3];
-  synthetic constructor •() → void
+  synthetic constructor •() → self::Foo
     : super core::Object::•()
     ;
   set first(dynamic x) → void
diff --git a/pkg/front_end/testcases/warn_unresolved_sends.dart.direct.expect b/pkg/front_end/testcases/warn_unresolved_sends.dart.legacy.expect
similarity index 100%
rename from pkg/front_end/testcases/warn_unresolved_sends.dart.direct.expect
rename to pkg/front_end/testcases/warn_unresolved_sends.dart.legacy.expect
diff --git a/pkg/front_end/testcases/warn_unresolved_sends.dart.direct.transformed.expect b/pkg/front_end/testcases/warn_unresolved_sends.dart.legacy.transformed.expect
similarity index 100%
rename from pkg/front_end/testcases/warn_unresolved_sends.dart.direct.transformed.expect
rename to pkg/front_end/testcases/warn_unresolved_sends.dart.legacy.transformed.expect
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index 10adcb4..a63d66f 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -69,11 +69,11 @@
     },
 
     {
-      "name": "compile",
+      "name": "legacy",
       "kind": "Chain",
-      "source": "test/fasta/compile_test.dart",
+      "source": "test/fasta/legacy_test.dart",
       "path": "testcases/",
-      "status": "testcases/compile.status",
+      "status": "testcases/legacy.status",
       "pattern": [
         "\\.dart$"
       ],
@@ -280,9 +280,28 @@
       "command-lines": [
         "-cdart2js -rd8 --use-sdk --minified --dart2js-with-kernel language language_2 dart2js_extra dart2js_native corelib corelib_2"
       ]
+    },
+
+    {
+      "name": "type_promotion_look_ahead",
+      "kind": "Chain",
+      "source": "test/fasta/type_promotion_look_ahead_test.dart",
+      "path": "testcases/",
+      "status": "testcases/type_promotion_look_ahead.status",
+      "pattern": [
+        "\\.dart$"
+      ],
+      "exclude": [
+        "/testcases/.*_part[0-9]*\\.dart$",
+        "/testcases/.*_lib[0-9]*\\.dart$",
+        "/testcases/dartino/",
+        "/testcases/shaker/",
+        "/testcases/expression/"
+      ]
     }
   ],
 
+
   "analyze": {
 
     "options": "analysis_options.yaml",
diff --git a/pkg/front_end/tool/fasta_perf.dart b/pkg/front_end/tool/fasta_perf.dart
index 56095b6..bd1ed2c 100644
--- a/pkg/front_end/tool/fasta_perf.dart
+++ b/pkg/front_end/tool/fasta_perf.dart
@@ -35,11 +35,11 @@
     print(argParser.usage);
     exit(1);
   }
-  bool strongMode = !options['legacy'];
+  bool legacyMode = options['legacy'];
   var bench = options.rest[0];
   var entryUri = Uri.base.resolve(options.rest[1]);
 
-  await setup(entryUri, strongMode: strongMode);
+  await setup(entryUri, legacyMode: legacyMode);
 
   Map<Uri, List<int>> files = await scanReachableFiles(entryUri);
   var handlers = {
@@ -47,10 +47,10 @@
     // TODO(sigmund): enable when we can run the ast-builder standalone.
     // 'parse': () async => parseFiles(files),
     'kernel_gen_e2e': () async {
-      await generateKernel(entryUri, strongMode: strongMode);
+      await generateKernel(entryUri, legacyMode: legacyMode);
     },
     'kernel_gen_e2e_sum': () async {
-      await generateKernel(entryUri, compileSdk: false, strongMode: strongMode);
+      await generateKernel(entryUri, compileSdk: false, legacyMode: legacyMode);
     },
   };
 
@@ -89,15 +89,15 @@
 
 /// Preliminary set up to be able to correctly resolve URIs on the given
 /// program.
-Future setup(Uri entryUri, {bool strongMode: false}) async {
+Future setup(Uri entryUri, {bool legacyMode: false}) async {
   var options = new CompilerOptions()
     ..sdkRoot = sdkRoot
     // Because this is only used to create a uriResolver, we don't allow any
     // whitelisting of error messages in the error handler.
-    ..onDiagnostic = onDiagnosticMessageHandler(false)
+    ..onDiagnostic = onDiagnosticMessageHandler(legacyMode: true)
     ..compileSdk = true
     ..packagesFileUri = Uri.base.resolve('.packages')
-    ..target = createTarget(isFlutter: false, strongMode: strongMode);
+    ..target = createTarget(isFlutter: false, legacyMode: legacyMode);
   uriResolver = await new ProcessedOptions(options: options).getUriTranslator();
 }
 
@@ -222,7 +222,7 @@
 
 // Invoke the fasta kernel generator for the program starting in [entryUri]
 generateKernel(Uri entryUri,
-    {bool compileSdk: true, bool strongMode: false}) async {
+    {bool compileSdk: true, bool legacyMode: false}) async {
   // TODO(sigmund): this is here only to compute the input size,
   // we should extract the input size from the frontend instead.
   scanReachableFiles(entryUri);
@@ -230,9 +230,9 @@
   var timer = new Stopwatch()..start();
   var options = new CompilerOptions()
     ..sdkRoot = sdkRoot
-    ..onDiagnostic = onDiagnosticMessageHandler(strongMode)
-    ..legacyMode = !strongMode
-    ..target = createTarget(isFlutter: false, strongMode: strongMode)
+    ..onDiagnostic = onDiagnosticMessageHandler(legacyMode: legacyMode)
+    ..legacyMode = legacyMode
+    ..target = createTarget(isFlutter: false, legacyMode: legacyMode)
     ..packagesFileUri = Uri.base.resolve('.packages')
     ..compileSdk = compileSdk;
   if (!compileSdk) {
diff --git a/pkg/front_end/tool/fasta_perf_test.dart b/pkg/front_end/tool/fasta_perf_test.dart
index 6c174c0..f366e73 100644
--- a/pkg/front_end/tool/fasta_perf_test.dart
+++ b/pkg/front_end/tool/fasta_perf_test.dart
@@ -7,7 +7,7 @@
 library front_end.tool.perf_test;
 
 import 'dart:io' show Platform;
-import 'fasta_perf.dart' as m;
+import 'fasta_perf.dart' as m show main;
 
 main() async {
   var benchIds = [
diff --git a/pkg/front_end/tool/incremental_perf.dart b/pkg/front_end/tool/incremental_perf.dart
index caec1bd..5851526 100644
--- a/pkg/front_end/tool/incremental_perf.dart
+++ b/pkg/front_end/tool/incremental_perf.dart
@@ -72,7 +72,7 @@
       parse(jsonDecode(new File.fromUri(editsUri).readAsStringSync()));
   bool verbose = options["verbose"];
   bool verboseCompilation = options["verbose-compilation"];
-  bool strongMode = options["mode"] == "strong";
+  bool legacyMode = options["mode"] == "legacy";
   bool isFlutter = options["target"] == "flutter";
   bool useMinimalGenerator = options["implementation"] == "minimal";
   TimingsCollector collector = new TimingsCollector(verbose);
@@ -81,7 +81,7 @@
     await benchmark(
         collector,
         entryUri,
-        strongMode,
+        legacyMode,
         isFlutter,
         useMinimalGenerator,
         verbose,
@@ -98,7 +98,7 @@
 Future benchmark(
     TimingsCollector collector,
     Uri entryUri,
-    bool strongMode,
+    bool legacyMode,
     bool isFlutter,
     bool useMinimalGenerator,
     bool verbose,
@@ -111,9 +111,9 @@
   var compilerOptions = new CompilerOptions()
     ..verbose = verboseCompilation
     ..fileSystem = overlayFs
-    ..legacyMode = !strongMode
-    ..onDiagnostic = onDiagnosticMessageHandler(strongMode)
-    ..target = createTarget(isFlutter: isFlutter, strongMode: strongMode);
+    ..legacyMode = legacyMode
+    ..onDiagnostic = onDiagnosticMessageHandler(legacyMode: legacyMode)
+    ..target = createTarget(isFlutter: isFlutter, legacyMode: legacyMode);
   if (sdkSummary != null) {
     compilerOptions.sdkSummary = _resolveOverlayUri(sdkSummary);
   }
diff --git a/pkg/front_end/tool/incremental_perf_test.dart b/pkg/front_end/tool/incremental_perf_test.dart
index f14b847..5a97ad8 100644
--- a/pkg/front_end/tool/incremental_perf_test.dart
+++ b/pkg/front_end/tool/incremental_perf_test.dart
@@ -7,7 +7,7 @@
 import 'dart:io';
 import 'package:front_end/src/compute_platform_binaries_location.dart'
     show computePlatformBinariesLocation;
-import 'incremental_perf.dart' as m;
+import 'incremental_perf.dart' as m show main;
 
 main() async {
   var sdkOutline = computePlatformBinariesLocation(forceBuildDir: true).resolve(
diff --git a/pkg/front_end/tool/perf.dart b/pkg/front_end/tool/perf.dart
index 335dcd4..582d65a 100644
--- a/pkg/front_end/tool/perf.dart
+++ b/pkg/front_end/tool/perf.dart
@@ -228,8 +228,7 @@
     path.dirname(executableDir),
     path.join(executableDir, 'dart-sdk')
   ]) {
-    if (new File(path.join(candidate, 'lib', 'dart_server.platform'))
-        .existsSync()) {
+    if (new File(path.join(candidate, 'lib', 'libraries.json')).existsSync()) {
       return candidate;
     }
   }
diff --git a/pkg/front_end/tool/perf_common.dart b/pkg/front_end/tool/perf_common.dart
index 24a4525..a6054cc 100644
--- a/pkg/front_end/tool/perf_common.dart
+++ b/pkg/front_end/tool/perf_common.dart
@@ -48,12 +48,12 @@
   fastaCodes.codeUndefinedMethod,
 ]);
 
-DiagnosticMessageHandler onDiagnosticMessageHandler(bool isStrong) {
+DiagnosticMessageHandler onDiagnosticMessageHandler({bool legacyMode: false}) {
   bool messageReported = false;
   return (DiagnosticMessage m) {
     if (m.severity == Severity.internalProblem ||
         m.severity == Severity.error) {
-      if (!isStrong ||
+      if (legacyMode ||
           !whitelistMessageCode.contains(getMessageCodeObject(m))) {
         printDiagnosticMessage(m, stderr.writeln);
         exitCode = 1;
@@ -65,19 +65,19 @@
   };
 }
 
-/// Creates a [VmTarget] or [FlutterTarget] with strong-mode enabled or
+/// Creates a [VmTarget] or [FlutterTarget] with legacy mode enabled or
 /// disabled.
 // TODO(sigmund): delete as soon as the disableTypeInference flag and the
-// strongMode flag get merged, and we have a single way of specifying the
-// strong-mode flag to the FE.
-Target createTarget({bool isFlutter: false, bool strongMode: true}) {
-  var flags = new TargetFlags(legacyMode: !strongMode);
+// legacyMode flag get merged, and we have a single way of specifying the
+// legacy-mode flag to the FE.
+Target createTarget({bool isFlutter: false, bool legacyMode: false}) {
+  var flags = new TargetFlags(legacyMode: legacyMode);
   if (isFlutter) {
-    return strongMode
-        ? new FlutterTarget(flags)
-        : new LegacyFlutterTarget(flags);
+    return legacyMode
+        ? new LegacyFlutterTarget(flags)
+        : new FlutterTarget(flags);
   } else {
-    return strongMode ? new VmTarget(flags) : new LegacyVmTarget(flags);
+    return legacyMode ? new LegacyVmTarget(flags) : new VmTarget(flags);
   }
 }
 
diff --git a/pkg/js_ast/lib/src/nodes.dart b/pkg/js_ast/lib/src/nodes.dart
index 2c44a3c..aaa601b 100644
--- a/pkg/js_ast/lib/src/nodes.dart
+++ b/pkg/js_ast/lib/src/nodes.dart
@@ -1645,7 +1645,7 @@
 class ArrayInitializer extends Expression {
   final List<Expression> elements;
 
-  ArrayInitializer(this.elements);
+  ArrayInitializer(this.elements) : assert(!elements.contains(null));
 
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitArrayInitializer(this);
 
diff --git a/pkg/kernel/analysis_options.yaml b/pkg/kernel/analysis_options.yaml
index 79a0819..af1bb97 100644
--- a/pkg/kernel/analysis_options.yaml
+++ b/pkg/kernel/analysis_options.yaml
@@ -1,5 +1,3 @@
 analyzer:
-  language:
-    enableSuperMixins: false
   exclude:
     - testcases/**
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 97faf8b..15c2aa4 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -131,7 +131,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 12;
+  UInt32 formatVersion = 13;
   Library[] libraries;
   UriSource sourceMap;
   List<CanonicalName> canonicalNames;
@@ -201,6 +201,11 @@
   CanonicalNameReference canonicalName;
 }
 
+type TypedefReference {
+  // Must be populated by a typedef (possibly later in the file).
+  CanonicalNameReference canonicalName;
+}
+
 type Name {
   StringReference name;
   if name begins with '_' {
@@ -1141,7 +1146,7 @@
   UInt totalParameterCount;
   List<DartType> positionalParameters;
   List<NamedDartType> namedParameters;
-  CanonicalNameReference typedefReference;
+  Option<TypedefType> typedef;
   DartType returnType;
 }
 
@@ -1183,6 +1188,12 @@
   Option<DartType> bound;
 }
 
+type TypedefType {
+  Byte tag = 87;
+  TypedefReference typedefReference;
+  List<DartType> typeArguments;
+}
+
 type TypeParameter {
   // Note: there is no tag on TypeParameter
   Byte flags (isGenericCovariantImpl);
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 43e3535..7555396 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -606,6 +606,10 @@
 
   Library get enclosingLibrary => parent;
 
+  TypedefType get thisType {
+    return new TypedefType(this, _getAsTypeArguments(typeParameters));
+  }
+
   accept(TreeVisitor v) {
     return v.visitTypedef(this);
   }
@@ -4538,6 +4542,7 @@
   const DartType();
 
   accept(DartTypeVisitor v);
+  accept1(DartTypeVisitor1 v, arg);
 
   bool operator ==(Object other);
 
@@ -4562,6 +4567,7 @@
   const InvalidType();
 
   accept(DartTypeVisitor v) => v.visitInvalidType(this);
+  accept1(DartTypeVisitor1 v, arg) => v.visitInvalidType(this, arg);
   visitChildren(Visitor v) {}
 
   bool operator ==(Object other) => other is InvalidType;
@@ -4573,6 +4579,7 @@
   const DynamicType();
 
   accept(DartTypeVisitor v) => v.visitDynamicType(this);
+  accept1(DartTypeVisitor1 v, arg) => v.visitDynamicType(this, arg);
   visitChildren(Visitor v) {}
 
   bool operator ==(Object other) => other is DynamicType;
@@ -4584,6 +4591,7 @@
   const VoidType();
 
   accept(DartTypeVisitor v) => v.visitVoidType(this);
+  accept1(DartTypeVisitor1 v, arg) => v.visitVoidType(this, arg);
   visitChildren(Visitor v) {}
 
   bool operator ==(Object other) => other is VoidType;
@@ -4595,6 +4603,7 @@
   const BottomType();
 
   accept(DartTypeVisitor v) => v.visitBottomType(this);
+  accept1(DartTypeVisitor1 v, arg) => v.visitBottomType(this, arg);
   visitChildren(Visitor v) {}
 
   bool operator ==(Object other) => other is BottomType;
@@ -4627,6 +4636,7 @@
   }
 
   accept(DartTypeVisitor v) => v.visitInterfaceType(this);
+  accept1(DartTypeVisitor1 v, arg) => v.visitInterfaceType(this, arg);
 
   visitChildren(Visitor v) {
     classNode.acceptReference(v);
@@ -4666,8 +4676,7 @@
   final List<NamedType> namedParameters; // Must be sorted.
 
   /// The [Typedef] this function type is created for.
-  @nocoq
-  Reference typedefReference;
+  final TypedefType typedefType;
 
   final DartType returnType;
   int _hashCode;
@@ -4676,20 +4685,24 @@
       {this.namedParameters: const <NamedType>[],
       this.typeParameters: const <TypeParameter>[],
       int requiredParameterCount,
-      this.typedefReference})
+      this.typedefType})
       : this.positionalParameters = positionalParameters,
         this.requiredParameterCount =
             requiredParameterCount ?? positionalParameters.length;
 
-  /// The [Typedef] this function type is created for.
+  @nocoq
+  Reference get typedefReference => typedefType?.typedefReference;
+
   Typedef get typedef => typedefReference?.asTypedef;
 
   accept(DartTypeVisitor v) => v.visitFunctionType(this);
+  accept1(DartTypeVisitor1 v, arg) => v.visitFunctionType(this, arg);
 
   visitChildren(Visitor v) {
     visitList(typeParameters, v);
     visitList(positionalParameters, v);
     visitList(namedParameters, v);
+    typedefType?.accept(v);
     returnType.accept(v);
   }
 
@@ -4735,7 +4748,7 @@
     return new FunctionType(positionalParameters, returnType,
         requiredParameterCount: requiredParameterCount,
         namedParameters: namedParameters,
-        typedefReference: typedefReference);
+        typedefType: typedefType);
   }
 
   /// Looks up the type of the named parameter with the given name.
@@ -4800,6 +4813,7 @@
   Typedef get typedefNode => typedefReference.asTypedef;
 
   accept(DartTypeVisitor v) => v.visitTypedefType(this);
+  accept1(DartTypeVisitor1 v, arg) => v.visitTypedefType(this, arg);
 
   visitChildren(Visitor v) {
     visitList(typeArguments, v);
@@ -4888,6 +4902,7 @@
   TypeParameterType(this.parameter, [this.promotedBound]);
 
   accept(DartTypeVisitor v) => v.visitTypeParameterType(this);
+  accept1(DartTypeVisitor1 v, arg) => v.visitTypeParameterType(this, arg);
 
   visitChildren(Visitor v) {}
 
@@ -5531,6 +5546,8 @@
 }
 
 abstract class BinarySink {
+  int getBufferOffset();
+
   void writeByte(int byte);
   void writeBytes(List<int> bytes);
   void writeUInt32(int value);
@@ -5560,6 +5577,7 @@
   List<int> get bytes;
 
   int readByte();
+  List<int> readBytes(int length);
   int readUInt();
   int readUint32();
 
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 860489e..8b591ac 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -134,13 +134,17 @@
     return _doubleBuffer[0];
   }
 
-  List<int> readByteList() {
-    List<int> bytes = new Uint8List(readUInt());
+  List<int> readBytes(int length) {
+    List<int> bytes = new Uint8List(length);
     bytes.setRange(0, bytes.length, _bytes, _byteOffset);
     _byteOffset += bytes.length;
     return bytes;
   }
 
+  List<int> readByteList() {
+    return readBytes(readUInt());
+  }
+
   String readStringEntry(int numBytes) {
     // Utf8Decoder will skip leading BOM characters, but we must preserve them.
     // Collect leading BOMs before passing the bytes onto Utf8Decoder.
@@ -681,8 +685,11 @@
     return _linkTable[index - 1];
   }
 
-  Reference readLibraryReference() {
-    return readCanonicalNameReference().getReference();
+  Reference readLibraryReference({bool allowNull: false}) {
+    CanonicalName canonicalName = readCanonicalNameReference();
+    if (canonicalName != null) return canonicalName.getReference();
+    if (allowNull) return null;
+    throw 'Expected a library reference to be valid but was `null`.';
   }
 
   LibraryDependency readLibraryDependencyReference() {
@@ -823,7 +830,7 @@
     var fileOffset = readOffset();
     var flags = readByte();
     var annotations = readExpressionList();
-    var targetLibrary = readLibraryReference();
+    var targetLibrary = readLibraryReference(allowNull: true);
     var prefixName = readStringOrNullIfEmpty();
     var names = readCombinatorList();
     return new LibraryDependency.byReference(
@@ -1828,7 +1835,7 @@
         var totalParameterCount = readUInt();
         var positional = readDartTypeList();
         var named = readNamedTypeList();
-        var typedefReference = readTypedefReference();
+        var typedefType = readDartTypeOption();
         assert(positional.length + named.length == totalParameterCount);
         var returnType = readDartType();
         typeParameterStack.length = typeParameterStackHeight;
@@ -1836,7 +1843,7 @@
             typeParameters: typeParameters,
             requiredParameterCount: requiredParameterCount,
             namedParameters: named,
-            typedefReference: typedefReference);
+            typedefType: typedefType);
       case Tag.SimpleFunctionType:
         var positional = readDartTypeList();
         var returnType = readDartType();
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 7c0795a..b46a768 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -411,6 +411,16 @@
   }
 
   void _writeMetadataSection(Component component) {
+    // Make sure metadata payloads section is 8-byte aligned,
+    // so certain kinds of metadata can contain aligned data.
+    const int metadataPayloadsAlignment = 8;
+    int padding = ((getBufferOffset() + metadataPayloadsAlignment - 1) &
+            -metadataPayloadsAlignment) -
+        getBufferOffset();
+    for (int i = 0; i < padding; ++i) {
+      writeByte(0);
+    }
+
     _binaryOffsetForMetadataPayloads = getBufferOffset();
 
     if (_metadataSubsections == null) {
@@ -1647,7 +1657,7 @@
     if (node.requiredParameterCount == node.positionalParameters.length &&
         node.typeParameters.isEmpty &&
         node.namedParameters.isEmpty &&
-        node.typedefReference == null) {
+        node.typedefType == null) {
       writeByte(Tag.SimpleFunctionType);
       writeNodeList(node.positionalParameters);
       writeNode(node.returnType);
@@ -1660,7 +1670,7 @@
           node.positionalParameters.length + node.namedParameters.length);
       writeNodeList(node.positionalParameters);
       writeNodeList(node.namedParameters);
-      writeReference(node.typedefReference);
+      writeOptionalNode(node.typedefType);
       writeNode(node.returnType);
       leaveScope(typeParameters: node.typeParameters);
     }
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index aea6b2a..5ef6760 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -127,7 +127,7 @@
   /// Internal version of kernel binary format.
   /// Bump it when making incompatible changes in kernel binaries.
   /// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
-  static const int BinaryFormatVersion = 12;
+  static const int BinaryFormatVersion = 13;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/kernel/lib/src/bounds_checks.dart b/pkg/kernel/lib/src/bounds_checks.dart
new file mode 100644
index 0000000..b453f06
--- /dev/null
+++ b/pkg/kernel/lib/src/bounds_checks.dart
@@ -0,0 +1,282 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../ast.dart'
+    show
+        BottomType,
+        DartType,
+        DynamicType,
+        FunctionType,
+        InterfaceType,
+        NamedType,
+        TypeParameter,
+        TypedefType,
+        VoidType;
+
+import '../type_algebra.dart' show substitute;
+
+import '../type_environment.dart' show TypeEnvironment;
+
+class TypeArgumentIssue {
+  // The type argument that violated the bound.
+  final DartType argument;
+
+  // The type parameter with the bound that was violated.
+  final TypeParameter typeParameter;
+
+  // The enclosing type of the issue, that is, the one with [typeParameter].
+  final DartType enclosingType;
+
+  TypeArgumentIssue(this.argument, this.typeParameter, this.enclosingType);
+}
+
+// TODO(dmitryas):  Remove [typedefInstantiations] when type arguments passed to
+// typedefs are preserved in the Kernel output.
+List<TypeArgumentIssue> findTypeArgumentIssues(
+    DartType type, TypeEnvironment typeEnvironment,
+    {bool allowSuperBounded = false}) {
+  List<TypeParameter> variables;
+  List<DartType> arguments;
+  List<TypeArgumentIssue> typedefRhsResult;
+
+  if (type is FunctionType && type.typedefType != null) {
+    // [type] is a function type that is an application of a parametrized
+    // typedef.  We need to check both the l.h.s. and the r.h.s. of the
+    // definition in that case.  For details, see [link]
+    // (https://github.com/dart-lang/sdk/blob/master/docs/language/informal/super-bounded-types.md).
+    FunctionType functionType = type;
+    FunctionType cloned = new FunctionType(
+        functionType.positionalParameters, functionType.returnType,
+        namedParameters: functionType.namedParameters,
+        typeParameters: functionType.typeParameters,
+        requiredParameterCount: functionType.requiredParameterCount,
+        typedefType: null);
+    typedefRhsResult = findTypeArgumentIssues(cloned, typeEnvironment,
+        allowSuperBounded: true);
+    type = functionType.typedefType;
+  }
+
+  if (type is InterfaceType) {
+    variables = type.classNode.typeParameters;
+    arguments = type.typeArguments;
+  } else if (type is TypedefType) {
+    variables = type.typedefNode.typeParameters;
+    arguments = type.typeArguments;
+  } else if (type is FunctionType) {
+    List<TypeArgumentIssue> result = <TypeArgumentIssue>[];
+    for (TypeParameter parameter in type.typeParameters) {
+      result.addAll(findTypeArgumentIssues(parameter.bound, typeEnvironment,
+              allowSuperBounded: true) ??
+          const <TypeArgumentIssue>[]);
+    }
+    for (DartType formal in type.positionalParameters) {
+      result.addAll(findTypeArgumentIssues(formal, typeEnvironment,
+              allowSuperBounded: true) ??
+          const <TypeArgumentIssue>[]);
+    }
+    for (NamedType named in type.namedParameters) {
+      result.addAll(findTypeArgumentIssues(named.type, typeEnvironment,
+              allowSuperBounded: true) ??
+          const <TypeArgumentIssue>[]);
+    }
+    result.addAll(findTypeArgumentIssues(type.returnType, typeEnvironment,
+            allowSuperBounded: true) ??
+        const <TypeArgumentIssue>[]);
+    return result.isEmpty ? null : result;
+  } else {
+    return null;
+  }
+
+  if (variables == null) return null;
+
+  List<TypeArgumentIssue> result;
+  List<TypeArgumentIssue> argumentsResult;
+
+  Map<TypeParameter, DartType> substitutionMap =
+      new Map<TypeParameter, DartType>.fromIterables(variables, arguments);
+  for (int i = 0; i < arguments.length; ++i) {
+    DartType argument = arguments[i];
+    if (argument is FunctionType && argument.typeParameters.length > 0) {
+      // Generic function types aren't allowed as type arguments either.
+      result ??= <TypeArgumentIssue>[];
+      result.add(new TypeArgumentIssue(argument, variables[i], type));
+    } else if (!typeEnvironment.isSubtypeOf(
+        argument, substitute(variables[i].bound, substitutionMap))) {
+      result ??= <TypeArgumentIssue>[];
+      result.add(new TypeArgumentIssue(argument, variables[i], type));
+    }
+
+    List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+        argument, typeEnvironment,
+        allowSuperBounded: true);
+    if (issues != null) {
+      argumentsResult ??= <TypeArgumentIssue>[];
+      argumentsResult.addAll(issues);
+    }
+  }
+  if (argumentsResult != null) {
+    result ??= <TypeArgumentIssue>[];
+    result.addAll(argumentsResult);
+  }
+  if (typedefRhsResult != null) {
+    result ??= <TypeArgumentIssue>[];
+    result.addAll(typedefRhsResult);
+  }
+
+  // [type] is regular-bounded.
+  if (result == null) return null;
+  if (!allowSuperBounded) return result;
+
+  result = null;
+  type = convertSuperBoundedToRegularBounded(typeEnvironment, type);
+  List<DartType> argumentsToReport = arguments.toList();
+  if (type is InterfaceType) {
+    variables = type.classNode.typeParameters;
+    arguments = type.typeArguments;
+  } else if (type is TypedefType) {
+    variables = type.typedefNode.typeParameters;
+    arguments = type.typeArguments;
+  }
+  substitutionMap =
+      new Map<TypeParameter, DartType>.fromIterables(variables, arguments);
+  for (int i = 0; i < arguments.length; ++i) {
+    DartType argument = arguments[i];
+    if (argument is FunctionType && argument.typeParameters.length > 0) {
+      // Generic function types aren't allowed as type arguments either.
+      result ??= <TypeArgumentIssue>[];
+      result
+          .add(new TypeArgumentIssue(argumentsToReport[i], variables[i], type));
+    } else if (!typeEnvironment.isSubtypeOf(
+        argument, substitute(variables[i].bound, substitutionMap))) {
+      result ??= <TypeArgumentIssue>[];
+      result
+          .add(new TypeArgumentIssue(argumentsToReport[i], variables[i], type));
+    }
+  }
+  if (argumentsResult != null) {
+    result ??= <TypeArgumentIssue>[];
+    result.addAll(argumentsResult);
+  }
+  if (typedefRhsResult != null) {
+    result ??= <TypeArgumentIssue>[];
+    result.addAll(typedefRhsResult);
+  }
+  return result;
+}
+
+// TODO(dmitryas):  Remove [typedefInstantiations] when type arguments passed to
+// typedefs are preserved in the Kernel output.
+List<TypeArgumentIssue> findTypeArgumentIssuesForInvocation(
+    List<TypeParameter> parameters,
+    List<DartType> arguments,
+    TypeEnvironment typeEnvironment,
+    {Map<FunctionType, List<DartType>> typedefInstantiations}) {
+  assert(arguments.length == parameters.length);
+  List<TypeArgumentIssue> result;
+  var substitutionMap = <TypeParameter, DartType>{};
+  for (int i = 0; i < arguments.length; ++i) {
+    substitutionMap[parameters[i]] = arguments[i];
+  }
+  for (int i = 0; i < arguments.length; ++i) {
+    DartType argument = arguments[i];
+    if (argument is FunctionType && argument.typeParameters.length > 0) {
+      // Generic function types aren't allowed as type arguments either.
+      result ??= <TypeArgumentIssue>[];
+      result.add(new TypeArgumentIssue(argument, parameters[i], null));
+    } else if (!typeEnvironment.isSubtypeOf(
+        argument, substitute(parameters[i].bound, substitutionMap))) {
+      result ??= <TypeArgumentIssue>[];
+      result.add(new TypeArgumentIssue(argument, parameters[i], null));
+    }
+
+    List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+        argument, typeEnvironment,
+        allowSuperBounded: true);
+    if (issues != null) {
+      result ??= <TypeArgumentIssue>[];
+      result.addAll(issues);
+    }
+  }
+  return result;
+}
+
+String getGenericTypeName(DartType type) {
+  if (type is InterfaceType) {
+    return type.classNode.name;
+  } else if (type is TypedefType) {
+    return type.typedefNode.name;
+  }
+  return type.toString();
+}
+
+/// Replaces all covariant occurrences of `dynamic`, `Object`, and `void` with
+/// [BottomType] and all contravariant occurrences of `Null` and [BottomType]
+/// with `Object`.
+DartType convertSuperBoundedToRegularBounded(
+    TypeEnvironment typeEnvironment, DartType type,
+    {bool isCovariant = true}) {
+  if ((type is DynamicType ||
+          type is VoidType ||
+          isObject(typeEnvironment, type)) &&
+      isCovariant) {
+    return const BottomType();
+  } else if ((type is BottomType || isNull(typeEnvironment, type)) &&
+      !isCovariant) {
+    return typeEnvironment.objectType;
+  } else if (type is InterfaceType && type.classNode.typeParameters != null) {
+    List<DartType> replacedTypeArguments =
+        new List<DartType>(type.typeArguments.length);
+    for (int i = 0; i < replacedTypeArguments.length; i++) {
+      replacedTypeArguments[i] = convertSuperBoundedToRegularBounded(
+          typeEnvironment, type.typeArguments[i],
+          isCovariant: isCovariant);
+    }
+    return new InterfaceType(type.classNode, replacedTypeArguments);
+  } else if (type is TypedefType && type.typedefNode.typeParameters != null) {
+    List<DartType> replacedTypeArguments =
+        new List<DartType>(type.typeArguments.length);
+    for (int i = 0; i < replacedTypeArguments.length; i++) {
+      replacedTypeArguments[i] = convertSuperBoundedToRegularBounded(
+          typeEnvironment, type.typeArguments[i],
+          isCovariant: isCovariant);
+    }
+    return new TypedefType(type.typedefNode, replacedTypeArguments);
+  } else if (type is FunctionType) {
+    var replacedReturnType = convertSuperBoundedToRegularBounded(
+        typeEnvironment, type.returnType,
+        isCovariant: isCovariant);
+    var replacedPositionalParameters =
+        new List<DartType>(type.positionalParameters.length);
+    for (int i = 0; i < replacedPositionalParameters.length; i++) {
+      replacedPositionalParameters[i] = convertSuperBoundedToRegularBounded(
+          typeEnvironment, type.positionalParameters[i],
+          isCovariant: !isCovariant);
+    }
+    var replacedNamedParameters =
+        new List<NamedType>(type.namedParameters.length);
+    for (int i = 0; i < replacedNamedParameters.length; i++) {
+      replacedNamedParameters[i] = new NamedType(
+          type.namedParameters[i].name,
+          convertSuperBoundedToRegularBounded(
+              typeEnvironment, type.namedParameters[i].type,
+              isCovariant: !isCovariant));
+    }
+    return new FunctionType(replacedPositionalParameters, replacedReturnType,
+        namedParameters: replacedNamedParameters,
+        typeParameters: type.typeParameters,
+        requiredParameterCount: type.requiredParameterCount,
+        typedefType: type.typedefType);
+  }
+  return type;
+}
+
+bool isObject(TypeEnvironment typeEnvironment, DartType type) {
+  return type is InterfaceType &&
+      type.classNode == typeEnvironment.objectType.classNode;
+}
+
+bool isNull(TypeEnvironment typeEnvironment, DartType type) {
+  return type is InterfaceType &&
+      type.classNode == typeEnvironment.nullType.classNode;
+}
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index a756595..6c8a75a 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1345,10 +1345,10 @@
     writeIndentation();
     writeWord(node.isImport ? 'import' : 'export');
     var uriString;
-    if (node.importedLibraryReference.node != null) {
+    if (node.importedLibraryReference?.node != null) {
       uriString = '${node.targetLibrary.importUri}';
     } else {
-      uriString = '${node.importedLibraryReference.canonicalName.name}';
+      uriString = '${node.importedLibraryReference?.canonicalName?.name}';
     }
     writeWord('"$uriString"');
     if (node.isDeferred) {
diff --git a/pkg/kernel/lib/transformations/constants.dart b/pkg/kernel/lib/transformations/constants.dart
index 49f6eba..2db13a1 100644
--- a/pkg/kernel/lib/transformations/constants.dart
+++ b/pkg/kernel/lib/transformations/constants.dart
@@ -374,6 +374,8 @@
   final bool enableAsserts;
   final ErrorReporter errorReporter;
 
+  final isInstantiated = new IsInstantiatedVisitor().isInstantiated;
+
   final Map<Constant, Constant> canonicalizationCache;
   final Map<Node, Object> nodeCache;
 
@@ -475,7 +477,7 @@
   }
 
   visitTypeLiteral(TypeLiteral node) {
-    final DartType type = evaluateDartType(node.type);
+    final DartType type = evaluateDartType(node, node.type);
     return canonicalize(new TypeLiteralConstant(type));
   }
 
@@ -496,7 +498,7 @@
     for (int i = 0; i < node.expressions.length; ++i) {
       entries[i] = node.expressions[i].accept(this);
     }
-    final DartType typeArgument = evaluateDartType(node.typeArgument);
+    final DartType typeArgument = evaluateDartType(node, node.typeArgument);
     final ListConstant listConstant = new ListConstant(typeArgument, entries);
     return canonicalize(backend.lowerListConstant(listConstant));
   }
@@ -521,8 +523,8 @@
       }
       entries[i] = new ConstantMapEntry(key, value);
     }
-    final DartType keyType = evaluateDartType(node.keyType);
-    final DartType valueType = evaluateDartType(node.valueType);
+    final DartType keyType = evaluateDartType(node, node.keyType);
+    final DartType valueType = evaluateDartType(node, node.valueType);
     final MapConstant mapConstant =
         new MapConstant(keyType, valueType, entries);
     return canonicalize(backend.lowerMapConstant(mapConstant));
@@ -548,7 +550,7 @@
       throw 'Constructor "$node" belongs to abstract class "${klass}".';
     }
 
-    final typeArguments = evaluateTypeArguments(node.arguments);
+    final typeArguments = evaluateTypeArguments(node, node.arguments);
     final positionals = evaluatePositionalArguments(node.arguments);
     final named = evaluateNamedArguments(node.arguments);
 
@@ -564,11 +566,156 @@
         // initialize the fields of the new instance.
         handleConstructorInvocation(
             constructor, typeArguments, positionals, named);
-        return canonicalize(instanceBuilder.buildInstance());
+        final InstanceConstant result = instanceBuilder.buildInstance();
+
+        // Special case the dart:core's Symbol class here and convert it to a
+        // [SymbolConstant].  For invalid values we report a compile-time error.
+        if (result.klass == coreTypes.internalSymbolClass) {
+          // The dart:_internal's Symbol class has only the name field.
+          assert(coreTypes.internalSymbolClass.fields
+                  .where((f) => !f.isStatic)
+                  .length ==
+              1);
+          final nameValue = result.fieldValues.values.single;
+
+          if (nameValue is StringConstant &&
+              isValidSymbolName(nameValue.value)) {
+            return canonicalize(new SymbolConstant(nameValue.value, null));
+          }
+          errorReporter.invalidSymbolName(
+              contextChain, node.arguments.positional.first, nameValue);
+          throw const _AbortCurrentEvaluation();
+        }
+
+        return canonicalize(result);
       });
     });
   }
 
+  bool isValidSymbolName(String name) {
+    // See https://api.dartlang.org/stable/2.0.0/dart-core/Symbol/Symbol.html:
+    //
+    //  A qualified name is a valid name preceded by a public identifier name and
+    //  a '.', e.g., foo.bar.baz= is a qualified version of baz=.
+    //
+    //  That means that the content of the name String must be either
+    //     - a valid public Dart identifier (that is, an identifier not
+    //       starting with "_"),
+    //     - such an identifier followed by "=" (a setter name),
+    //     - the name of a declarable operator,
+    //     - any of the above preceded by any number of qualifiers, where a
+    //       qualifier is a non-private identifier followed by '.',
+    //     - or the empty string (the default name of a library with no library
+    //       name declaration).
+
+    const operatorNames = const <String>[
+      '+',
+      '-',
+      '*',
+      '/',
+      '%',
+      '~/',
+      '&',
+      '|',
+      '^',
+      '~',
+      '<<',
+      '>>',
+      '<',
+      '<=',
+      '>',
+      '>=',
+      '==',
+      '[]',
+      '[]=',
+      'unary-'
+    ];
+
+    if (name == null) return false;
+    if (name == '') return true;
+
+    final parts = name.split('.');
+
+    // Each qualifier must be a public identifier.
+    for (int i = 0; i < parts.length - 1; ++i) {
+      if (!isValidPublicIdentifier(parts[i])) return false;
+    }
+
+    String last = parts.last;
+    if (operatorNames.contains(last)) {
+      return true;
+    }
+    if (last.endsWith('=')) {
+      last = last.substring(0, last.length - 1);
+    }
+    if (!isValidPublicIdentifier(last)) return false;
+
+    return true;
+  }
+
+  /// From the Dart Language specification:
+  ///
+  ///   IDENTIFIER:
+  ///     IDENTIFIER_START IDENTIFIER_PART*
+  ///
+  ///   IDENTIFIER_START:
+  ///       IDENTIFIER_START_NO_DOLLAR | ‘$’
+  ///
+  ///   IDENTIFIER_PART:
+  ///       IDENTIFIER_START | DIGIT
+  ///
+  ///   IDENTIFIER_NO_DOLLAR:
+  ///     IDENTIFIER_START_NO_DOLLAR IDENTIFIER_PART_NO_DOLLAR*
+  ///
+  ///   IDENTIFIER_START_NO_DOLLAR:
+  ///       LETTER | '_'
+  ///
+  ///   IDENTIFIER_PART_NO_DOLLAR:
+  ///       IDENTIFIER_START_NO_DOLLAR | DIGIT
+  ///
+  static final publicIdentifierRegExp =
+      new RegExp(r'^[a-zA-Z$][a-zA-Z0-9_$]*$');
+
+  static const nonUsableKeywords = const <String>[
+    'assert',
+    'break',
+    'case',
+    'catch',
+    'class',
+    'const',
+    'continue',
+    'default',
+    'do',
+    'else',
+    'enum',
+    'extends',
+    'false',
+    'final',
+    'finally',
+    'for',
+    'if',
+    'in',
+    'is',
+    'new',
+    'null',
+    'rethrow',
+    'return',
+    'super',
+    'switch',
+    'this',
+    'throw',
+    'true',
+    'try',
+    'var',
+    'while',
+    'with',
+  ];
+
+  bool isValidPublicIdentifier(String name) {
+    return publicIdentifierRegExp.hasMatch(name) &&
+        !nonUsableKeywords.contains(name);
+  }
+
   handleConstructorInvocation(
       Constructor constructor,
       List<DartType> typeArguments,
@@ -618,7 +765,7 @@
             handleConstructorInvocation(
                 init.target,
                 evaluateSuperTypeArguments(
-                    constructor.enclosingClass.supertype),
+                    init, constructor.enclosingClass.supertype),
                 evaluatePositionalArguments(init.arguments),
                 evaluateNamedArguments(init.arguments));
           } else if (init is RedirectingInitializer) {
@@ -1000,7 +1147,7 @@
       if (nativeName != null) {
         final Constant constant = backend.buildConstantForNative(
             nativeName,
-            evaluateTypeArguments(node.arguments),
+            evaluateTypeArguments(node, node.arguments),
             evaluatePositionalArguments(node.arguments),
             evaluateNamedArguments(node.arguments),
             contextChain,
@@ -1029,7 +1176,7 @@
 
   visitAsExpression(AsExpression node) {
     final Constant constant = node.operand.accept(this);
-    ensureIsSubtype(constant, evaluateDartType(node.type), node);
+    ensureIsSubtype(constant, evaluateDartType(node, node.type), node);
     return constant;
   }
 
@@ -1054,8 +1201,9 @@
     if (constant is TearOffConstant) {
       if (node.typeArguments.length ==
           constant.procedure.function.typeParameters.length) {
+        final typeArguments = evaluateDartTypes(node, node.typeArguments);
         return canonicalize(
-            new PartialInstantiationConstant(constant, node.typeArguments));
+            new PartialInstantiationConstant(constant, typeArguments));
       }
       throw new Exception(
           'The number of type arguments supplied in the partial instantiation '
@@ -1107,21 +1255,30 @@
     }
   }
 
-  List<DartType> evaluateTypeArguments(Arguments arguments) {
-    return evaluateDartTypes(arguments.types);
+  List<DartType> evaluateTypeArguments(TreeNode node, Arguments arguments) {
+    return evaluateDartTypes(node, arguments.types);
   }
 
-  List<DartType> evaluateSuperTypeArguments(Supertype type) {
-    return evaluateDartTypes(type.typeArguments);
+  List<DartType> evaluateSuperTypeArguments(TreeNode node, Supertype type) {
+    return evaluateDartTypes(node, type.typeArguments);
   }
 
-  List<DartType> evaluateDartTypes(List<DartType> types) {
-    if (env.isEmpty) return types;
-    return types.map(evaluateDartType).toList();
+  List<DartType> evaluateDartTypes(TreeNode node, List<DartType> types) {
+    // TODO: Once the frontend gurantees that there are no free type variables
+    // left over after stubstitution, we can enable this shortcut again:
+    // if (env.isEmpty) return types;
+    return types.map((t) => evaluateDartType(node, t)).toList();
   }
 
-  DartType evaluateDartType(DartType type) {
-    return env.subsituteType(type);
+  DartType evaluateDartType(TreeNode node, DartType type) {
+    final result = env.subsituteType(type);
+
+    if (!isInstantiated(result)) {
+      errorReporter.freeTypeParameter(contextChain, node, type);
+      throw const _AbortCurrentEvaluation();
+    }
+
+    return result;
   }
 
   List<Constant> evaluatePositionalArguments(Arguments arguments) {
@@ -1315,6 +1472,7 @@
 abstract class ErrorReporter {
   const ErrorReporter();
 
+  freeTypeParameter(List<TreeNode> context, TreeNode node, DartType type);
   invalidDartType(List<TreeNode> context, TreeNode node, Constant receiver,
       DartType expectedType);
   invalidBinaryOperandType(List<TreeNode> context, TreeNode node,
@@ -1325,6 +1483,7 @@
       List<TreeNode> context, TreeNode node, Procedure target);
   invalidStringInterpolationOperand(
       List<TreeNode> context, TreeNode node, Constant constant);
+  invalidSymbolName(List<TreeNode> context, TreeNode node, Constant constant);
   zeroDivisor(
       List<TreeNode> context, TreeNode node, IntConstant receiver, String op);
   negativeShift(List<TreeNode> context, TreeNode node, IntConstant receiver,
@@ -1356,6 +1515,10 @@
     return node == null ? TreeNode.noOffset : node.fileOffset;
   }
 
+  freeTypeParameter(List<TreeNode> context, TreeNode node, DartType type) {
+    report(context, 'Expected type to be instantiated but was ${type}', node);
+  }
+
   invalidDartType(List<TreeNode> context, TreeNode node, Constant receiver,
       DartType expectedType) {
     report(
@@ -1399,6 +1562,14 @@
         node);
   }
 
+  invalidSymbolName(List<TreeNode> context, TreeNode node, Constant constant) {
+    report(
+        context,
+        'The symbol name must be a valid public Dart member name, public '
+        'constructor name, or library name, optionally qualified.',
+        node);
+  }
+
   zeroDivisor(
       List<TreeNode> context, TreeNode node, IntConstant receiver, String op) {
     report(
@@ -1468,6 +1639,46 @@
   }
 }
 
+class IsInstantiatedVisitor extends DartTypeVisitor<bool> {
+  final _availableVariables = new Set<TypeParameter>();
+
+  bool isInstantiated(DartType type) {
+    return type.accept(this);
+  }
+
+  bool defaultDartType(DartType node) {
+    throw 'A visitor method seems to be unimplemented!';
+  }
+
+  bool visitInvalidType(InvalidType node) => true;
+  bool visitDynamicType(DynamicType node) => true;
+  bool visitVoidType(VoidType node) => true;
+  bool visitBottomType(BottomType node) => true;
+
+  bool visitTypeParameterType(TypeParameterType node) {
+    return _availableVariables.contains(node.parameter);
+  }
+
+  bool visitInterfaceType(InterfaceType node) {
+    return node.typeArguments
+        .every((DartType typeArgument) => typeArgument.accept(this));
+  }
+
+  bool visitFunctionType(FunctionType node) {
+    final parameters = node.typeParameters;
+    _availableVariables.addAll(parameters);
+    final bool result = node.returnType.accept(this) &&
+        node.positionalParameters.every((p) => p.accept(this)) &&
+        node.namedParameters.every((p) => p.type.accept(this));
+    _availableVariables.removeAll(parameters);
+    return result;
+  }
+
+  bool visitTypedefType(TypedefType node) {
+    return node.unalias.accept(this);
+  }
+}
+
 bool _isFormalParameter(VariableDeclaration variable) {
   final parent = variable.parent;
   if (parent is FunctionNode) {
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index 625bc5b..7268136 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -252,7 +252,8 @@
       namedParameters: type.namedParameters.map(substituteNamed).toList(),
       typeParameters: freshTypeParameters,
       requiredParameterCount: type.requiredParameterCount,
-      typedefReference: type.typedefReference);
+      typedefType:
+          type.typedefType == null ? null : substitute(type.typedefType));
 
   DartType substitute(DartType type) => substitution.substituteType(type);
 
@@ -582,12 +583,14 @@
         : node.namedParameters.map(inner.visitNamedType).toList();
     inner.invertVariance();
     var returnType = inner.visit(node.returnType);
+    DartType typedefType =
+        node.typedefType == null ? null : inner.visit(node.typedefType);
     if (this.useCounter == before) return node;
     return new FunctionType(positionalParameters, returnType,
         namedParameters: namedParameters,
         typeParameters: typeParameters,
         requiredParameterCount: node.requiredParameterCount,
-        typedefReference: node.typedefReference);
+        typedefType: typedefType);
   }
 
   void bumpCountersUntil(_TypeSubstitutor target) {
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index 5e216eb..5b4e5ba 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -151,263 +151,6 @@
     }
     return !hierarchy.hasProperSubtypes(class_);
   }
-
-  bool isObject(DartType type) {
-    return type is InterfaceType && type.classNode == objectType.classNode;
-  }
-
-  bool isNull(DartType type) {
-    return type is InterfaceType && type.classNode == nullType.classNode;
-  }
-
-  /// Replaces all covariant occurrences of `dynamic`, `Object`, and `void` with
-  /// [BottomType] and all contravariant occurrences of `Null` and [BottomType]
-  /// with `Object`.
-  DartType convertSuperBoundedToRegularBounded(DartType type,
-      {bool isCovariant = true}) {
-    if ((type is DynamicType || type is VoidType || isObject(type)) &&
-        isCovariant) {
-      return const BottomType();
-    } else if ((type is BottomType || isNull(type)) && !isCovariant) {
-      return objectType;
-    } else if (type is InterfaceType && type.classNode.typeParameters != null) {
-      List<DartType> replacedTypeArguments =
-          new List<DartType>(type.typeArguments.length);
-      for (int i = 0; i < replacedTypeArguments.length; i++) {
-        replacedTypeArguments[i] = convertSuperBoundedToRegularBounded(
-            type.typeArguments[i],
-            isCovariant: isCovariant);
-      }
-      return new InterfaceType(type.classNode, replacedTypeArguments);
-    } else if (type is TypedefType && type.typedefNode.typeParameters != null) {
-      List<DartType> replacedTypeArguments =
-          new List<DartType>(type.typeArguments.length);
-      for (int i = 0; i < replacedTypeArguments.length; i++) {
-        replacedTypeArguments[i] = convertSuperBoundedToRegularBounded(
-            type.typeArguments[i],
-            isCovariant: isCovariant);
-      }
-      return new TypedefType(type.typedefNode, replacedTypeArguments);
-    } else if (type is FunctionType) {
-      var replacedReturnType = convertSuperBoundedToRegularBounded(
-          type.returnType,
-          isCovariant: isCovariant);
-      var replacedPositionalParameters =
-          new List<DartType>(type.positionalParameters.length);
-      for (int i = 0; i < replacedPositionalParameters.length; i++) {
-        replacedPositionalParameters[i] = convertSuperBoundedToRegularBounded(
-            type.positionalParameters[i],
-            isCovariant: !isCovariant);
-      }
-      var replacedNamedParameters =
-          new List<NamedType>(type.namedParameters.length);
-      for (int i = 0; i < replacedNamedParameters.length; i++) {
-        replacedNamedParameters[i] = new NamedType(
-            type.namedParameters[i].name,
-            convertSuperBoundedToRegularBounded(type.namedParameters[i].type,
-                isCovariant: !isCovariant));
-      }
-      return new FunctionType(replacedPositionalParameters, replacedReturnType,
-          namedParameters: replacedNamedParameters,
-          typeParameters: type.typeParameters,
-          requiredParameterCount: type.requiredParameterCount,
-          typedefReference: type.typedefReference);
-    }
-    return type;
-  }
-
-  // TODO(dmitryas):  Remove [typedefInstantiations] when type arguments passed
-  // to typedefs are preserved in the Kernel output.
-  List<Object> findBoundViolations(DartType type,
-      {bool allowSuperBounded = false,
-      Map<FunctionType, List<DartType>> typedefInstantiations}) {
-    List<TypeParameter> variables;
-    List<DartType> arguments;
-    List<Object> typedefRhsResult;
-
-    if (typedefInstantiations != null &&
-        typedefInstantiations.containsKey(type)) {
-      // [type] is a function type that is an application of a parametrized
-      // typedef.  We need to check both the l.h.s. and the r.h.s. of the
-      // definition in that case.  For details, see [link]
-      // (https://github.com/dart-lang/sdk/blob/master/docs/language/informal/super-bounded-types.md).
-      FunctionType functionType = type;
-      FunctionType cloned = new FunctionType(
-          functionType.positionalParameters, functionType.returnType,
-          namedParameters: functionType.namedParameters,
-          typeParameters: functionType.typeParameters,
-          requiredParameterCount: functionType.requiredParameterCount,
-          typedefReference: null);
-      typedefRhsResult = findBoundViolations(cloned,
-          allowSuperBounded: true,
-          typedefInstantiations: typedefInstantiations);
-      type = new TypedefType(functionType.typedef, typedefInstantiations[type]);
-    }
-
-    if (type is InterfaceType) {
-      variables = type.classNode.typeParameters;
-      arguments = type.typeArguments;
-    } else if (type is TypedefType) {
-      variables = type.typedefNode.typeParameters;
-      arguments = type.typeArguments;
-    } else if (type is FunctionType) {
-      List<Object> result = <Object>[];
-      for (TypeParameter parameter in type.typeParameters) {
-        result.addAll(findBoundViolations(parameter.bound,
-                allowSuperBounded: true,
-                typedefInstantiations: typedefInstantiations) ??
-            const <Object>[]);
-      }
-      for (DartType formal in type.positionalParameters) {
-        result.addAll(findBoundViolations(formal,
-                allowSuperBounded: true,
-                typedefInstantiations: typedefInstantiations) ??
-            const <Object>[]);
-      }
-      for (NamedType named in type.namedParameters) {
-        result.addAll(findBoundViolations(named.type,
-                allowSuperBounded: true,
-                typedefInstantiations: typedefInstantiations) ??
-            const <Object>[]);
-      }
-      result.addAll(findBoundViolations(type.returnType,
-              allowSuperBounded: true,
-              typedefInstantiations: typedefInstantiations) ??
-          const <Object>[]);
-      return result.isEmpty ? null : result;
-    } else {
-      return null;
-    }
-
-    if (variables == null) return null;
-
-    List<Object> result;
-    List<Object> argumentsResult;
-
-    Map<TypeParameter, DartType> substitutionMap =
-        new Map<TypeParameter, DartType>.fromIterables(variables, arguments);
-    for (int i = 0; i < arguments.length; ++i) {
-      DartType argument = arguments[i];
-      if (argument is FunctionType && argument.typeParameters.length > 0) {
-        // Generic function types aren't allowed as type arguments either.
-        result ??= <Object>[];
-        result.add(argument);
-        result.add(variables[i]);
-        result.add(type);
-      } else if (!isSubtypeOf(
-          argument, substitute(variables[i].bound, substitutionMap))) {
-        result ??= <Object>[];
-        result.add(argument);
-        result.add(variables[i]);
-        result.add(type);
-      }
-
-      List<Object> violations = findBoundViolations(argument,
-          allowSuperBounded: true,
-          typedefInstantiations: typedefInstantiations);
-      if (violations != null) {
-        argumentsResult ??= <Object>[];
-        argumentsResult.addAll(violations);
-      }
-    }
-    if (argumentsResult != null) {
-      result ??= <Object>[];
-      result.addAll(argumentsResult);
-    }
-    if (typedefRhsResult != null) {
-      result ??= <Object>[];
-      result.addAll(typedefRhsResult);
-    }
-
-    // [type] is regular-bounded.
-    if (result == null) return null;
-    if (!allowSuperBounded) return result;
-
-    result = null;
-    type = convertSuperBoundedToRegularBounded(type);
-    List<DartType> argumentsToReport = arguments.toList();
-    if (type is InterfaceType) {
-      variables = type.classNode.typeParameters;
-      arguments = type.typeArguments;
-    } else if (type is TypedefType) {
-      variables = type.typedefNode.typeParameters;
-      arguments = type.typeArguments;
-    }
-    substitutionMap =
-        new Map<TypeParameter, DartType>.fromIterables(variables, arguments);
-    for (int i = 0; i < arguments.length; ++i) {
-      DartType argument = arguments[i];
-      if (argument is FunctionType && argument.typeParameters.length > 0) {
-        // Generic function types aren't allowed as type arguments either.
-        result ??= <Object>[];
-        result.add(argumentsToReport[i]);
-        result.add(variables[i]);
-        result.add(type);
-      } else if (!isSubtypeOf(
-          argument, substitute(variables[i].bound, substitutionMap))) {
-        result ??= <Object>[];
-        result.add(argumentsToReport[i]);
-        result.add(variables[i]);
-        result.add(type);
-      }
-    }
-    if (argumentsResult != null) {
-      result ??= <Object>[];
-      result.addAll(argumentsResult);
-    }
-    if (typedefRhsResult != null) {
-      result ??= <Object>[];
-      result.addAll(typedefRhsResult);
-    }
-    return result;
-  }
-
-  // TODO(dmitryas):  Remove [typedefInstantiations] when type arguments passed
-  // to typedefs are preserved in the Kernel output.
-  List<Object> findBoundViolationsElementwise(
-      List<TypeParameter> parameters, List<DartType> arguments,
-      {Map<FunctionType, List<DartType>> typedefInstantiations}) {
-    assert(arguments.length == parameters.length);
-    List<Object> result;
-    var substitutionMap = <TypeParameter, DartType>{};
-    for (int i = 0; i < arguments.length; ++i) {
-      substitutionMap[parameters[i]] = arguments[i];
-    }
-    for (int i = 0; i < arguments.length; ++i) {
-      DartType argument = arguments[i];
-      if (argument is FunctionType && argument.typeParameters.length > 0) {
-        // Generic function types aren't allowed as type arguments either.
-        result ??= <Object>[];
-        result.add(argument);
-        result.add(parameters[i]);
-        result.add(null);
-      } else if (!isSubtypeOf(
-          argument, substitute(parameters[i].bound, substitutionMap))) {
-        result ??= <Object>[];
-        result.add(argument);
-        result.add(parameters[i]);
-        result.add(null);
-      }
-
-      List<Object> violations = findBoundViolations(argument,
-          allowSuperBounded: true,
-          typedefInstantiations: typedefInstantiations);
-      if (violations != null) {
-        result ??= <Object>[];
-        result.addAll(violations);
-      }
-    }
-    return result;
-  }
-
-  String getGenericTypeName(DartType type) {
-    if (type is InterfaceType) {
-      return type.classNode.name;
-    } else if (type is TypedefType) {
-      return type.typedefNode.name;
-    }
-    return type.toString();
-  }
 }
 
 /// The part of [TypeEnvironment] that deals with subtype tests.
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index ad879a2..a93186e 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -261,6 +261,20 @@
   R visitTypedefType(TypedefType node) => defaultDartType(node);
 }
 
+class DartTypeVisitor1<R, T> {
+  R defaultDartType(DartType node, T arg) => null;
+
+  R visitInvalidType(InvalidType node, T arg) => defaultDartType(node, arg);
+  R visitDynamicType(DynamicType node, T arg) => defaultDartType(node, arg);
+  R visitVoidType(VoidType node, T arg) => defaultDartType(node, arg);
+  R visitBottomType(BottomType node, T arg) => defaultDartType(node, arg);
+  R visitInterfaceType(InterfaceType node, T arg) => defaultDartType(node, arg);
+  R visitFunctionType(FunctionType node, T arg) => defaultDartType(node, arg);
+  R visitTypeParameterType(TypeParameterType node, T arg) =>
+      defaultDartType(node, arg);
+  R visitTypedefType(TypedefType node, T arg) => defaultDartType(node, arg);
+}
+
 class ConstantVisitor<R> {
   R defaultConstant(Constant node) => null;
 
diff --git a/pkg/meta/lib/meta.dart b/pkg/meta/lib/meta.dart
index 38a8283..0b1699f 100644
--- a/pkg/meta/lib/meta.dart
+++ b/pkg/meta/lib/meta.dart
@@ -203,6 +203,11 @@
 const _Sealed sealed = const _Sealed();
 
 /// Used to annotate a field that is allowed to be overridden in Strong Mode.
+///
+/// Deprecated: Most of strong mode is now the default in 2.0, but the notion of
+/// virtual fields was dropped, so this annotation no longer has any meaning.
+/// Uses of the annotation should be removed.
+@deprecated
 const _Virtual virtual = const _Virtual();
 
 /// Used to annotate an instance member that was made public so that it could be
@@ -302,6 +307,7 @@
   const _Sealed();
 }
 
+@deprecated
 class _Virtual {
   const _Virtual();
 }
diff --git a/pkg/pkg.status b/pkg/pkg.status
index e276440..75a8ca5 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -9,7 +9,6 @@
 */*/*/packages/*/*: Skip
 */*/packages/*/*: Skip
 */packages/*/*: Skip
-analysis_server/tool/spec/check_all_test: Skip # Issue 29133
 analyzer/test/generated/compile_time_error_code_driver_test: Slow, Pass
 analyzer/test/generated/compile_time_error_code_kernel_test: Slow, Pass
 analyzer/test/generated/compile_time_error_code_test: Slow, Pass
@@ -25,7 +24,6 @@
 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
-analyzer_plugin/tool/spec/check_all_test: Skip # Issue 29133
 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
@@ -33,7 +31,7 @@
 front_end/test/fasta/analyze_test: Pass, Slow
 front_end/test/fasta/ast_builder_test: Pass, Slow
 front_end/test/fasta/bootstrap_test: Pass, Slow
-front_end/test/fasta/compile_test: Pass, ExtraSlow
+front_end/test/fasta/legacy_test: Pass, ExtraSlow
 front_end/test/fasta/outline_test: Pass, Slow
 front_end/test/fasta/rasta/*: SkipByDesign # Anything in rasta is input to fasta unit tests and shouldn't be run as tests.
 front_end/test/fasta/sdk_test: SkipByDesign # sdk_test would take too long to complete, and should be run in a different way.
@@ -58,6 +56,8 @@
 
 [ $compiler == dart2js ]
 analysis_server/test/integration: SkipByDesign # Analysis server integration tests don't make sense to run under dart2js, since the code under test always runs in the Dart vm as a subprocess.
+analysis_server/tool/*: SkipByDesign # Only meant to run on vm
+analysis_server_client/test/live_test: SkipByDesign # Only meant to run on vm
 analyzer_cli/test/*: SkipByDesign # Only meant to run on vm
 analyzer_plugin/test/*: SkipByDesign # Only meant to run on vm
 analyzer_plugin/tool/*: SkipByDesign # Only meant to run on vm
diff --git a/pkg/status_file/lib/status_file_linter.dart b/pkg/status_file/lib/status_file_linter.dart
index fa98680..c8e08c6 100644
--- a/pkg/status_file/lib/status_file_linter.dart
+++ b/pkg/status_file/lib/status_file_linter.dart
@@ -61,7 +61,7 @@
     }
     return lintingErrors;
   }
-  return section.entries.where((entry) => entry is CommentEntry).map((entry) =>
+  return section.entries.whereType<CommentEntry>().map((entry) =>
       new LintingError(entry.lineNumber, "Comment is on a line by itself."));
 }
 
@@ -97,7 +97,7 @@
 /// ordered alphabetically.
 Iterable<LintingError> lintAlphabeticalOrderingOfPaths(StatusSection section) {
   var entries = section.entries
-      .where((entry) => entry is StatusEntry)
+      .whereType<StatusEntry>()
       .map((entry) => (entry as StatusEntry).path)
       .toList();
   var sortedList = entries.toList()..sort((a, b) => a.compareTo(b));
@@ -132,10 +132,8 @@
 /// Checks for duplicate section entries in the body of a section.
 Iterable<LintingError> lintSectionEntryDuplicates(StatusSection section) {
   var errors = <LintingError>[];
-  // TODO(whereType): When whereType is supported, use that.
   List<StatusEntry> statusEntries = section.entries
-      .where((entry) => entry is StatusEntry)
-      .cast<StatusEntry>()
+      .whereType<StatusEntry>()
       .toList();
   for (var i = 0; i < statusEntries.length; i++) {
     var entry = statusEntries[i];
diff --git a/pkg/testing/analysis_options.yaml b/pkg/testing/analysis_options.yaml
index c36c46e..b5516058 100644
--- a/pkg/testing/analysis_options.yaml
+++ b/pkg/testing/analysis_options.yaml
@@ -3,7 +3,6 @@
 # BSD-style license that can be found in the LICENSE file.
 
 analyzer:
-  strong-mode: true
   errors:
     # Allow having TODOs in the code
     todo: ignore
diff --git a/pkg/testing/lib/src/run.dart b/pkg/testing/lib/src/run.dart
index a06d328..c93303a 100644
--- a/pkg/testing/lib/src/run.dart
+++ b/pkg/testing/lib/src/run.dart
@@ -23,7 +23,13 @@
 
 import 'analyze.dart' show Analyze;
 
-import 'log.dart' show isVerbose, logMessage, logNumberedLines, splitLines;
+import 'log.dart'
+    show
+        enableVerboseOutput,
+        isVerbose,
+        logMessage,
+        logNumberedLines,
+        splitLines;
 
 import 'suite.dart' show Dart, Suite;
 
@@ -54,6 +60,7 @@
     TestRoot testRoot =
         await computeTestRoot(configurationPath, Platform.script);
     CommandLine cl = CommandLine.parse(arguments);
+    if (cl.verbose) enableVerboseOutput();
     for (Chain suite in testRoot.toolChains) {
       if (Platform.script == suite.source) {
         print("Running suite ${suite.name}...");
diff --git a/pkg/vm/analysis_options.yaml b/pkg/vm/analysis_options.yaml
index 27c9e25..76886bd 100644
--- a/pkg/vm/analysis_options.yaml
+++ b/pkg/vm/analysis_options.yaml
@@ -3,9 +3,6 @@
 # BSD-style license that can be found in the LICENSE file.
 
 analyzer:
-  strong-mode: true
-  language:
-    enableSuperMixins: false
   exclude:
     - testcases/**
     - tool/**
diff --git a/pkg/vm/bin/dump_bytecode_ngrams.dart b/pkg/vm/bin/dump_bytecode_ngrams.dart
new file mode 100644
index 0000000..dead72c
--- /dev/null
+++ b/pkg/vm/bin/dump_bytecode_ngrams.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io' as io;
+
+import 'package:args/args.dart' show ArgParser, ArgResults;
+import 'package:vm/bytecode/ngrams.dart';
+
+final ArgParser _argParser = new ArgParser(allowTrailingOptions: true)
+  ..addFlag('basic-blocks',
+      help: 'Only allow control flow as the last instruction in a window',
+      defaultsTo: true)
+  ..addOption('output',
+      abbr: 'o', help: 'Path to output file', defaultsTo: null)
+  ..addFlag('merge-pushes',
+      help: 'Do not distinguish among different kinds of Push opcodes',
+      defaultsTo: false)
+  ..addFlag('sort',
+      abbr: 's', help: 'Sort the output by ngram frequency', defaultsTo: true)
+  ..addOption('threshold',
+      abbr: 't', help: 'Minimum ngram count threshold', defaultsTo: "1")
+  ..addOption('window', abbr: 'w', help: 'Window size', defaultsTo: "3");
+
+final String _usage = '''
+Usage: dump_bytecode_ngrams [options] input.trace
+
+Dumps stats about a dynamic bytecode instruction trace produced with the
+Dart VM option --interpreter-trace-file, e.g.:
+
+\$ dart --enable-interpreter --interpreter-trace-file=trace program.dart
+
+Options:
+${_argParser.usage}
+''';
+
+const int _badUsageExitCode = 1;
+
+int main(List<String> arguments) {
+  final ArgResults options = _argParser.parse(arguments);
+  if ((options.rest.length != 1) || (options['output'] == null)) {
+    print(_usage);
+    return _badUsageExitCode;
+  }
+
+  final basicBlocks = options['basic-blocks'];
+  final input = options.rest.single;
+  final output = options['output'];
+  final mergePushes = options['merge-pushes'];
+  final windowSize = int.parse(options['window']);
+  final sort = options['sort'];
+  final threshold = int.parse(options['threshold']);
+
+  if (!(new io.File(input).existsSync())) {
+    print("The file '$input' does not exist");
+    print(_usage);
+    return _badUsageExitCode;
+  }
+
+  NGramReader nGramReader = new NGramReader(input);
+  nGramReader.readAllNGrams(windowSize,
+      basicBlocks: basicBlocks, mergePushes: mergePushes);
+  nGramReader.writeNGramStats(output, sort: sort, minCount: threshold);
+  return 0;
+}
diff --git a/pkg/vm/bin/gen_kernel.dart b/pkg/vm/bin/gen_kernel.dart
index 5acfd26..bdb5df6 100644
--- a/pkg/vm/bin/gen_kernel.dart
+++ b/pkg/vm/bin/gen_kernel.dart
@@ -44,6 +44,8 @@
       help: 'Whether kernel constant evaluation will be enabled.',
       defaultsTo: true)
   ..addFlag('gen-bytecode', help: 'Generate bytecode', defaultsTo: false)
+  ..addFlag('emit-bytecode-source-positions',
+      help: 'Emit source positions in bytecode', defaultsTo: false)
   ..addFlag('drop-ast',
       help: 'Drop AST for members with bytecode', defaultsTo: false)
   ..addFlag('use-future-bytecode-format',
@@ -83,6 +85,8 @@
   final bool aot = options['aot'];
   final bool tfa = options['tfa'];
   final bool genBytecode = options['gen-bytecode'];
+  final bool emitBytecodeSourcePositions =
+      options['emit-bytecode-source-positions'];
   final bool dropAST = options['drop-ast'];
   final bool useFutureBytecodeFormat = options['use-future-bytecode-format'];
   final bool enableAsserts = options['enable-asserts'];
@@ -104,7 +108,6 @@
     ..packagesFileUri =
         packages != null ? Uri.base.resolveUri(new Uri.file(packages)) : null
     ..onDiagnostic = (DiagnosticMessage m) {
-      printDiagnosticMessage(m, stderr.writeln);
       errorDetector(m);
     }
     ..embedSourceText = options['embed-sources'];
@@ -116,6 +119,7 @@
       useGlobalTypeFlowAnalysis: tfa,
       environmentDefines: environmentDefines,
       genBytecode: genBytecode,
+      emitBytecodeSourcePositions: emitBytecodeSourcePositions,
       dropAST: dropAST,
       useFutureBytecodeFormat: useFutureBytecodeFormat,
       enableAsserts: enableAsserts,
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 01d4c2c..69c2c9f 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -477,6 +477,13 @@
   if (verbose) print("DFE:> ${result}");
 
   if (tag == kTrainTag) {
+    // In training mode make sure to read the sdk a few more times...
+    ProcessedOptions p = new ProcessedOptions(options: compiler.options);
+    var bytes = await p.loadSdkSummaryBytes();
+    for (int i = 0; i < 100; i++) {
+      p.loadComponent(bytes, null);
+    }
+
     if (result.status != Status.ok) {
       tag = -tag;
     }
diff --git a/pkg/vm/lib/bytecode/assembler.dart b/pkg/vm/lib/bytecode/assembler.dart
index b45b4c1..f937116 100644
--- a/pkg/vm/lib/bytecode/assembler.dart
+++ b/pkg/vm/lib/bytecode/assembler.dart
@@ -6,8 +6,11 @@
 
 import 'dart:typed_data';
 
+import 'package:kernel/ast.dart' show TreeNode;
+
 import 'dbc.dart';
 import 'exceptions.dart' show ExceptionsTable;
+import 'source_positions.dart' show SourcePositions;
 
 class Label {
   final bool allowsBackwardJumps;
@@ -48,7 +51,9 @@
   final Uint32List _encodeBufferIn;
   final Uint8List _encodeBufferOut;
   final ExceptionsTable exceptionsTable = new ExceptionsTable();
+  final SourcePositions sourcePositions = new SourcePositions();
   bool isUnreachable = false;
+  int currentSourcePosition = TreeNode.noOffset;
 
   BytecodeAssembler._(this._encodeBufferIn, this._encodeBufferOut);
 
@@ -70,6 +75,12 @@
     }
   }
 
+  void emitSourcePosition() {
+    if (currentSourcePosition != TreeNode.noOffset && !isUnreachable) {
+      sourcePositions.add(offsetInWords, currentSourcePosition);
+    }
+  }
+
   void emitWord(int word) {
     if (isUnreachable) {
       return;
@@ -121,11 +132,8 @@
   int _encodeAD(Opcode opcode, int ra, int rd) =>
       _uint8(opcode.index) | (_uint8(ra) << 8) | (_uint16(rd) << 16);
 
-// TODO(alexmarkov) This format is currently unused. Restore it if needed, or
-// remove it once bytecode instruction set is finalized.
-//
-//  int _encodeAX(Opcode opcode, int ra, int rx) =>
-//      _uint8(opcode.index) | (_uint8(ra) << 8) | (_int16(rx) << 16);
+  int _encodeAX(Opcode opcode, int ra, int rx) =>
+      _uint8(opcode.index) | (_uint8(ra) << 8) | (_int16(rx) << 16);
 
   int _encodeD(Opcode opcode, int rd) =>
       _uint8(opcode.index) | (_uint16(rd) << 16);
@@ -153,6 +161,7 @@
 
   void emitBytecode0(Opcode opcode) {
     assert(BytecodeFormats[opcode].encoding == Encoding.k0);
+    emitSourcePosition();
     emitWord(_encode0(opcode));
   }
 
@@ -258,18 +267,22 @@
   }
 
   void emitIndirectStaticCall(int ra, int rd) {
+    emitSourcePosition();
     emitWord(_encodeAD(Opcode.kIndirectStaticCall, ra, rd));
   }
 
   void emitInstanceCall(int ra, int rd) {
+    emitSourcePosition();
     emitWord(_encodeAD(Opcode.kInstanceCall, ra, rd));
   }
 
   void emitNativeCall(int rd) {
+    emitSourcePosition();
     emitWord(_encodeD(Opcode.kNativeCall, rd));
   }
 
   void emitStoreStaticTOS(int rd) {
+    emitSourcePosition();
     emitWord(_encodeD(Opcode.kStoreStaticTOS, rd));
   }
 
@@ -282,10 +295,12 @@
   }
 
   void emitAllocate(int rd) {
+    emitSourcePosition();
     emitWord(_encodeD(Opcode.kAllocate, rd));
   }
 
   void emitAllocateT() {
+    emitSourcePosition();
     emitWord(_encode0(Opcode.kAllocateT));
   }
 
@@ -294,6 +309,7 @@
   }
 
   void emitStoreFieldTOS(int rd) {
+    emitSourcePosition();
     emitWord(_encodeD(Opcode.kStoreFieldTOS, rd));
   }
 
@@ -301,8 +317,8 @@
     emitWord(_encode0(Opcode.kStoreContextParent));
   }
 
-  void emitStoreContextVar(int rd) {
-    emitWord(_encodeD(Opcode.kStoreContextVar, rd));
+  void emitStoreContextVar(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kStoreContextVar, ra, rd));
   }
 
   void emitLoadFieldTOS(int rd) {
@@ -317,8 +333,8 @@
     emitWord(_encode0(Opcode.kLoadContextParent));
   }
 
-  void emitLoadContextVar(int rd) {
-    emitWord(_encodeD(Opcode.kLoadContextVar, rd));
+  void emitLoadContextVar(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kLoadContextVar, ra, rd));
   }
 
   void emitBooleanNegateTOS() {
@@ -326,6 +342,7 @@
   }
 
   void emitThrow(int ra) {
+    emitSourcePosition();
     emitWord(_encodeA(Opcode.kThrow, ra));
     isUnreachable = true;
   }
@@ -342,43 +359,50 @@
     emitWord(_encodeA(Opcode.kSetFrame, ra));
   }
 
-  void emitAllocateContext(int rd) {
-    emitWord(_encodeD(Opcode.kAllocateContext, rd));
+  void emitAllocateContext(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kAllocateContext, ra, rd));
   }
 
-  void emitCloneContext() {
-    emitWord(_encode0(Opcode.kCloneContext));
+  void emitCloneContext(int ra, int rd) {
+    emitWord(_encodeAD(Opcode.kCloneContext, ra, rd));
   }
 
-  void emitMoveSpecial(int ra, SpecialIndex rd) {
-    emitWord(_encodeAD(Opcode.kMoveSpecial, ra, rd.index));
+  void emitMoveSpecial(SpecialIndex ra, int rx) {
+    emitWord(_encodeAX(Opcode.kMoveSpecial, ra.index, rx));
   }
 
   void emitInstantiateType(int rd) {
+    emitSourcePosition();
     emitWord(_encodeD(Opcode.kInstantiateType, rd));
   }
 
   void emitInstantiateTypeArgumentsTOS(int ra, int rd) {
+    emitSourcePosition();
     emitWord(_encodeAD(Opcode.kInstantiateTypeArgumentsTOS, ra, rd));
   }
 
   void emitAssertAssignable(int ra, int rd) {
+    emitSourcePosition();
     emitWord(_encodeAD(Opcode.kAssertAssignable, ra, rd));
   }
 
   void emitAssertSubtype() {
+    emitSourcePosition();
     emitWord(_encode0(Opcode.kAssertSubtype));
   }
 
   void emitAssertBoolean(int ra) {
+    emitSourcePosition();
     emitWord(_encodeA(Opcode.kAssertBoolean, ra));
   }
 
-  void emitCheckStack() {
-    emitWord(_encode0(Opcode.kCheckStack));
+  void emitCheckStack(int ra) {
+    emitSourcePosition();
+    emitWord(_encodeA(Opcode.kCheckStack, ra));
   }
 
   void emitCheckFunctionTypeArgs(int ra, int rd) {
+    emitSourcePosition();
     emitWord(_encodeAD(Opcode.kCheckFunctionTypeArgs, ra, rd));
   }
 
diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart
index 2a8bbef..13eb462 100644
--- a/pkg/vm/lib/bytecode/dbc.dart
+++ b/pkg/vm/lib/bytecode/dbc.dart
@@ -163,9 +163,9 @@
   Opcode.kFrame: const Format(
       Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
   Opcode.kCheckFunctionTypeArgs: const Format(
-      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
+      Encoding.kAD, const [Operand.imm, Operand.reg, Operand.none]),
   Opcode.kCheckStack: const Format(
-      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+      Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
   Opcode.kAllocate: const Format(
       Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
   Opcode.kAllocateT: const Format(
@@ -173,17 +173,17 @@
   Opcode.kCreateArrayTOS: const Format(
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
   Opcode.kAllocateContext: const Format(
-      Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
+      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
   Opcode.kCloneContext: const Format(
-      Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
   Opcode.kLoadContextParent: const Format(
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
   Opcode.kStoreContextParent: const Format(
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
   Opcode.kLoadContextVar: const Format(
-      Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
+      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
   Opcode.kStoreContextVar: const Format(
-      Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
+      Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
   Opcode.kPushConstant: const Format(
       Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
   Opcode.kPushNull: const Format(
@@ -253,7 +253,7 @@
   Opcode.kThrow: const Format(
       Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
   Opcode.kMoveSpecial: const Format(
-      Encoding.kAD, const [Operand.reg, Operand.spe, Operand.none]),
+      Encoding.kAX, const [Operand.spe, Operand.xeg, Operand.none]),
   Opcode.kSetFrame: const Format(
       Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
   Opcode.kBooleanNegateTOS: const Format(
@@ -304,6 +304,39 @@
 
 bool isJump(Opcode opcode) => BytecodeFormats[opcode].encoding == Encoding.kT;
 
+bool isThrow(Opcode opcode) => opcode == Opcode.kThrow;
+
+bool isCall(Opcode opcode) {
+  switch (opcode) {
+    case Opcode.kIndirectStaticCall:
+    case Opcode.kInstanceCall:
+    case Opcode.kNativeCall:
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool isReturn(Opcode opcode) => opcode == Opcode.kReturnTOS;
+
+bool isControlFlow(Opcode opcode) =>
+    isJump(opcode) || isThrow(opcode) || isCall(opcode) || isReturn(opcode);
+
+bool isPush(Opcode opcode) {
+  switch (opcode) {
+    case Opcode.kPush:
+    case Opcode.kPushConstant:
+    case Opcode.kPushNull:
+    case Opcode.kPushTrue:
+    case Opcode.kPushFalse:
+    case Opcode.kPushInt:
+    case Opcode.kPushStatic:
+      return true;
+    default:
+      return false;
+  }
+}
+
 // Bytecode instructions reference constant pool indices using
 // unsigned 16-bit operands.
 const int constantPoolIndexLimit = 1 << 16;
@@ -314,6 +347,9 @@
 // Captured variables are referenced using 16-bit unsigned operands.
 const int capturedVariableIndexLimit = 1 << 16;
 
+// Context IDs are referenced using 8-bit unsigned operands.
+const int contextIdLimit = 1 << 8;
+
 // Base class for exceptions thrown when certain limit of bytecode
 // format is exceeded.
 abstract class BytecodeLimitExceededException {}
diff --git a/pkg/vm/lib/bytecode/disassembler.dart b/pkg/vm/lib/bytecode/disassembler.dart
index c9b6e46..153e837 100644
--- a/pkg/vm/lib/bytecode/disassembler.dart
+++ b/pkg/vm/lib/bytecode/disassembler.dart
@@ -6,28 +6,44 @@
 
 import 'dart:typed_data';
 
+import 'package:kernel/ast.dart' show listEquals, listHashCode;
+
 import 'dbc.dart';
 import 'exceptions.dart';
 
-class _Instruction {
+class Instruction {
   final Opcode opcode;
   final List<int> operands;
-  _Instruction(this.opcode, this.operands);
+  Instruction(this.opcode, this.operands);
+
+  @override
+  int get hashCode => opcode.index.hashCode ^ listHashCode(operands);
+
+  @override
+  bool operator ==(other) {
+    return (other is Instruction) &&
+        (opcode == other.opcode) &&
+        listEquals(operands, other.operands);
+  }
 }
 
 class BytecodeDisassembler {
   static const int kOpcodeMask = 0xFF;
   static const int kBitsPerInt = 64;
 
-  List<_Instruction> _instructions;
+  List<Instruction> _instructions;
   int _labelCount;
   Map<int, String> _labels;
   Map<int, List<String>> _markers;
 
-  String disassemble(List<int> bytecode, ExceptionsTable exceptionsTable) {
+  String disassemble(List<int> bytecode, ExceptionsTable exceptionsTable,
+      {List<Map<int, String>> annotations}) {
     _init(bytecode);
     _scanForJumpTargets();
     _markTryBlocks(exceptionsTable);
+    if (annotations != null) {
+      _markAnnotations(annotations);
+    }
     return _disasm();
   }
 
@@ -36,9 +52,9 @@
     // TODO(alexmarkov): endianness?
     Uint32List words = uint8list.buffer.asUint32List();
 
-    _instructions = new List<_Instruction>(words.length);
+    _instructions = new List<Instruction>(words.length);
     for (int i = 0; i < words.length; i++) {
-      _instructions[i] = _decodeInstruction(words[i]);
+      _instructions[i] = decodeInstruction(words[i]);
     }
 
     _labelCount = 0;
@@ -46,10 +62,10 @@
     _markers = <int, List<String>>{};
   }
 
-  _Instruction _decodeInstruction(int word) {
+  Instruction decodeInstruction(int word) {
     final opcode = Opcode.values[word & kOpcodeMask];
     final format = BytecodeFormats[opcode];
-    return new _Instruction(opcode, _decodeOperands(format, word));
+    return new Instruction(opcode, _decodeOperands(format, word));
   }
 
   List<int> _decodeOperands(Format format, int word) {
@@ -116,6 +132,14 @@
     }
   }
 
+  void _markAnnotations(List<Map<int, String>> annotations) {
+    for (var map in annotations) {
+      map.forEach((int pc, String annotation) {
+        _addMarker(pc, '# $annotation');
+      });
+    }
+  }
+
   void _addMarker(int pc, String marker) {
     final markers = (_markers[pc] ??= <String>[]);
     markers.add(marker);
@@ -128,12 +152,12 @@
       if (markers != null) {
         markers.forEach(out.writeln);
       }
-      _writeInstruction(out, i, _instructions[i]);
+      writeInstruction(out, i, _instructions[i]);
     }
     return out.toString();
   }
 
-  void _writeInstruction(StringBuffer out, int bci, _Instruction instr) {
+  void writeInstruction(StringBuffer out, int bci, Instruction instr) {
     final format = BytecodeFormats[instr.opcode];
     assert(format != null);
 
@@ -180,7 +204,9 @@
       case Operand.xeg:
         return (value < 0) ? 'FP[$value]' : 'r$value';
       case Operand.tgt:
-        return _labels[bci + value] ?? (throw 'Label not found');
+        return (_labels == null)
+            ? value.toString()
+            : _labels[bci + value] ?? (throw 'Label not found');
       case Operand.spe:
         return SpecialIndex.values[value]
             .toString()
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 06c8592..4ff3fb7 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -27,6 +27,7 @@
 import 'dbc.dart';
 import 'exceptions.dart';
 import 'local_vars.dart' show LocalVariables;
+import 'nullability_detector.dart' show NullabilityDetector;
 import 'recognized_methods.dart' show RecognizedMethods;
 import '../constants_error_reporter.dart' show ForwardConstantEvaluationErrors;
 import '../metadata/bytecode.dart';
@@ -38,7 +39,8 @@
 
 void generateBytecode(Component component,
     {bool dropAST: false,
-    bool omitSourcePositions: false,
+    bool emitSourcePositions: false,
+    bool omitAssertSourcePositions: false,
     bool useFutureBytecodeFormat: false,
     Map<String, String> environmentDefines,
     ErrorReporter errorReporter}) {
@@ -57,7 +59,8 @@
           hierarchy,
           typeEnvironment,
           constantsBackend,
-          omitSourcePositions,
+          emitSourcePositions,
+          omitAssertSourcePositions,
           useFutureBytecodeFormat,
           errorReporter)
       .visitComponent(component);
@@ -72,11 +75,13 @@
   final ClassHierarchy hierarchy;
   final TypeEnvironment typeEnvironment;
   final ConstantsBackend constantsBackend;
-  final bool omitSourcePositions;
+  final bool emitSourcePositions;
+  final bool omitAssertSourcePositions;
   final bool useFutureBytecodeFormat;
   final ErrorReporter errorReporter;
   final BytecodeMetadataRepository metadata = new BytecodeMetadataRepository();
   final RecognizedMethods recognizedMethods;
+  NullabilityDetector nullabilityDetector;
 
   Class enclosingClass;
   Member enclosingMember;
@@ -84,7 +89,8 @@
   FunctionNode parentFunction;
   bool isClosure;
   Set<TypeParameter> classTypeParameters;
-  Set<TypeParameter> functionTypeParameters;
+  List<TypeParameter> functionTypeParameters;
+  Set<TypeParameter> functionTypeParametersSet;
   List<DartType> instantiatorTypeArguments;
   LocalVariables locals;
   ConstantEvaluator constantEvaluator;
@@ -102,6 +108,7 @@
   BytecodeAssembler asm;
   List<BytecodeAssembler> savedAssemblers;
   bool hasErrors;
+  int currentLoopDepth;
 
   BytecodeGenerator(
       this.component,
@@ -109,10 +116,12 @@
       this.hierarchy,
       this.typeEnvironment,
       this.constantsBackend,
-      this.omitSourcePositions,
+      this.emitSourcePositions,
+      this.omitAssertSourcePositions,
       this.useFutureBytecodeFormat,
       this.errorReporter)
       : recognizedMethods = new RecognizedMethods(typeEnvironment) {
+    nullabilityDetector = new NullabilityDetector(recognizedMethods);
     component.addMetadataRepository(metadata);
   }
 
@@ -148,7 +157,7 @@
           if (node.isConst) {
             _genPushConstExpr(node.initializer);
           } else {
-            node.initializer.accept(this);
+            _generateNode(node.initializer);
           }
           _genReturnTOS();
           end(node);
@@ -166,7 +175,7 @@
           }
           _genNativeCall(nativeName);
         } else {
-          node.function?.body?.accept(this);
+          _generateNode(node.function?.body);
           // BytecodeAssembler eliminates this bytecode if it is unreachable.
           asm.emitPushNull();
         }
@@ -285,6 +294,26 @@
   Procedure get unsafeCast => _unsafeCast ??=
       libraryIndex.getTopLevelMember('dart:_internal', 'unsafeCast');
 
+  void _recordSourcePosition(TreeNode node) {
+    if (emitSourcePositions) {
+      asm.currentSourcePosition = node.fileOffset;
+    }
+  }
+
+  void _generateNode(TreeNode node) {
+    if (node == null) {
+      return;
+    }
+    final savedSourcePosition = asm.currentSourcePosition;
+    _recordSourcePosition(node);
+    node.accept(this);
+    asm.currentSourcePosition = savedSourcePosition;
+  }
+
+  void _generateNodeList(List<TreeNode> nodes) {
+    nodes.forEach(_generateNode);
+  }
+
   void _genConstructorInitializers(Constructor node) {
     final bool isRedirecting =
         node.initializers.any((init) => init is RedirectingInitializer);
@@ -298,7 +327,7 @@
       }
     }
 
-    visitList(node.initializers, this);
+    _generateNodeList(node.initializers);
 
     if (!isRedirecting) {
       nullableFields = <Reference>[];
@@ -319,7 +348,7 @@
     }
 
     _genPushReceiver();
-    initializer.accept(this);
+    _generateNode(initializer);
 
     final int cpIndex = cp.add(new ConstantInstanceField(field));
     asm.emitStoreFieldTOS(cpIndex);
@@ -331,9 +360,9 @@
     if (arguments.types.isNotEmpty) {
       _genTypeArguments(arguments.types);
     }
-    receiver?.accept(this);
-    visitList(arguments.positional, this);
-    arguments.named.forEach((NamedExpression ne) => ne.value.accept(this));
+    _generateNode(receiver);
+    _generateNodeList(arguments.positional);
+    arguments.named.forEach((NamedExpression ne) => _generateNode(ne.value));
   }
 
   void _genPushBool(bool value) {
@@ -434,8 +463,15 @@
     if (typeArgs.isEmpty || !hasFreeTypeParameters(typeArgs)) {
       asm.emitPushConstant(typeArgsCPIndex());
     } else {
-      if (_canReuseInstantiatorTypeArguments(typeArgs, instantiatingClass)) {
+      final flattenedTypeArgs = (instantiatingClass != null &&
+              (instantiatorTypeArguments != null ||
+                  functionTypeParameters != null))
+          ? _flattenInstantiatorTypeArguments(instantiatingClass, typeArgs)
+          : typeArgs;
+      if (_canReuseInstantiatorTypeArguments(flattenedTypeArgs)) {
         _genPushInstantiatorTypeArguments();
+      } else if (_canReuseFunctionTypeArguments(flattenedTypeArgs)) {
+        _genPushFunctionTypeArguments();
       } else {
         _genPushInstantiatorAndFunctionTypeArguments(typeArgs);
         // TODO(alexmarkov): Optimize type arguments instantiation
@@ -458,8 +494,8 @@
     } else {
       asm.emitPushNull();
     }
-    if (functionTypeParameters != null &&
-        types.any((t) => containsTypeVariable(t, functionTypeParameters))) {
+    if (functionTypeParametersSet != null &&
+        types.any((t) => containsTypeVariable(t, functionTypeParametersSet))) {
       _genPushFunctionTypeArguments();
     } else {
       asm.emitPushNull();
@@ -529,17 +565,11 @@
     return flatTypeArgs;
   }
 
-  bool _canReuseInstantiatorTypeArguments(
-      List<DartType> typeArgs, Class instantiatingClass) {
+  bool _canReuseInstantiatorTypeArguments(List<DartType> typeArgs) {
     if (instantiatorTypeArguments == null) {
       return false;
     }
 
-    if (instantiatingClass != null) {
-      typeArgs =
-          _flattenInstantiatorTypeArguments(instantiatingClass, typeArgs);
-    }
-
     if (typeArgs.length > instantiatorTypeArguments.length) {
       return false;
     }
@@ -553,6 +583,26 @@
     return true;
   }
 
+  bool _canReuseFunctionTypeArguments(List<DartType> typeArgs) {
+    if (functionTypeParameters == null) {
+      return false;
+    }
+
+    if (typeArgs.length > functionTypeParameters.length) {
+      return false;
+    }
+
+    for (int i = 0; i < typeArgs.length; ++i) {
+      final typeArg = typeArgs[i];
+      if (!(typeArg is TypeParameterType &&
+          typeArg.parameter == functionTypeParameters[i])) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
   void _genPushFunctionTypeArguments() {
     if (locals.hasFunctionTypeArgsVar) {
       asm.emitPush(locals.functionTypeArgsVarIndexInFrame);
@@ -584,7 +634,8 @@
   void _genLoadVar(VariableDeclaration v, {int currentContextLevel}) {
     if (locals.isCaptured(v)) {
       _genPushContextForVariable(v, currentContextLevel: currentContextLevel);
-      asm.emitLoadContextVar(locals.getVarIndexInContext(v));
+      asm.emitLoadContextVar(
+          locals.getVarContextId(v), locals.getVarIndexInContext(v));
     } else {
       asm.emitPush(locals.getVarIndexInFrame(v));
     }
@@ -600,7 +651,8 @@
   // If variable is captured, context should be pushed before value.
   void _genStoreVar(VariableDeclaration variable) {
     if (locals.isCaptured(variable)) {
-      asm.emitStoreContextVar(locals.getVarIndexInContext(variable));
+      asm.emitStoreContextVar(locals.getVarContextId(variable),
+          locals.getVarIndexInContext(variable));
     } else {
       asm.emitPopLocal(locals.getVarIndexInFrame(variable));
     }
@@ -613,8 +665,10 @@
       condition = (condition as Not).operand;
       negated = true;
     }
-    condition.accept(this);
-    asm.emitAssertBoolean(0);
+    _generateNode(condition);
+    if (nullabilityDetector.isNullable(condition)) {
+      asm.emitAssertBoolean(0);
+    }
     return negated;
   }
 
@@ -754,7 +808,8 @@
     if (enclosingFunction != null &&
         enclosingFunction.typeParameters.isNotEmpty) {
       functionTypeParameters =
-          new Set<TypeParameter>.from(enclosingFunction.typeParameters);
+          new List<TypeParameter>.from(enclosingFunction.typeParameters);
+      functionTypeParametersSet = functionTypeParameters.toSet();
     }
     locals = new LocalVariables(node);
     // TODO(alexmarkov): improve caching in ConstantEvaluator and reuse it
@@ -775,10 +830,12 @@
     constantEmitter = new ConstantEmitter(cp);
     asm = new BytecodeAssembler();
     savedAssemblers = <BytecodeAssembler>[];
+    currentLoopDepth = 0;
 
     locals.enterScope(node);
     assert(!locals.isSyncYieldingFrame);
 
+    _recordSourcePosition(node);
     _genPrologue(node, node.function);
     _setupInitialContext(node.function);
     if (node is Procedure && node.isInstanceMember) {
@@ -811,8 +868,14 @@
       final formatVersion = useFutureBytecodeFormat
           ? futureBytecodeFormatVersion
           : stableBytecodeFormatVersion;
-      metadata.mapping[node] = new BytecodeMetadata(formatVersion, cp,
-          asm.bytecode, asm.exceptionsTable, nullableFields, closures);
+      metadata.mapping[node] = new BytecodeMetadata(
+          formatVersion,
+          cp,
+          asm.bytecode,
+          asm.exceptionsTable,
+          asm.sourcePositions,
+          nullableFields,
+          closures);
     }
 
     typeEnvironment.thisType = null;
@@ -823,6 +886,7 @@
     isClosure = null;
     classTypeParameters = null;
     functionTypeParameters = null;
+    functionTypeParametersSet = null;
     instantiatorTypeArguments = null;
     locals = null;
     constantEvaluator = null;
@@ -875,7 +939,7 @@
     } else {
       asm.emitEntry(locals.frameSize);
     }
-    asm.emitCheckStack();
+    asm.emitCheckStack(0);
 
     if (isClosure) {
       asm.emitPush(locals.closureVarIndexInFrame);
@@ -959,7 +1023,7 @@
     // instantiate default types.
     if (isClosure &&
         defaultTypes
-            .any((t) => containsTypeVariable(t, functionTypeParameters))) {
+            .any((t) => containsTypeVariable(t, functionTypeParametersSet))) {
       asm.emitPush(locals.closureVarIndexInFrame);
       asm.emitLoadFieldTOS(
           cp.add(new ConstantInstanceField(closureFunctionTypeArguments)));
@@ -1207,10 +1271,13 @@
     final savedIsClosure = isClosure;
     isClosure = true;
     enclosingFunction = function;
+    final savedLoopDepth = currentLoopDepth;
+    currentLoopDepth = 0;
 
     if (function.typeParameters.isNotEmpty) {
-      functionTypeParameters ??= new Set<TypeParameter>();
+      functionTypeParameters ??= new List<TypeParameter>();
       functionTypeParameters.addAll(function.typeParameters);
+      functionTypeParametersSet = functionTypeParameters.toSet();
     }
 
     List<Label> savedYieldPoints = yieldPoints;
@@ -1241,7 +1308,7 @@
 
     // TODO(alexmarkov): support --causal_async_stacks.
 
-    function.body.accept(this);
+    _generateNode(function.body);
 
     // BytecodeAssembler eliminates this bytecode if it is unreachable.
     asm.emitPushNull();
@@ -1255,17 +1322,19 @@
     cp.add(new ConstantEndClosureFunctionScope());
 
     if (function.typeParameters.isNotEmpty) {
-      functionTypeParameters.removeAll(function.typeParameters);
+      functionTypeParameters.length -= function.typeParameters.length;
+      functionTypeParametersSet = functionTypeParameters.toSet();
     }
 
     enclosingFunction = parentFunction;
     parentFunction = savedParentFunction;
     isClosure = savedIsClosure;
+    currentLoopDepth = savedLoopDepth;
 
     locals.leaveScope();
 
-    closures.add(new ClosureBytecode(
-        closureFunctionIndex, asm.bytecode, asm.exceptionsTable));
+    closures.add(new ClosureBytecode(closureFunctionIndex, asm.bytecode,
+        asm.exceptionsTable, asm.sourcePositions));
 
     _popAssemblerState();
     yieldPoints = savedYieldPoints;
@@ -1359,7 +1428,7 @@
   void _allocateContextIfNeeded() {
     final int contextSize = locals.currentContextSize;
     if (contextSize > 0) {
-      asm.emitAllocateContext(contextSize);
+      asm.emitAllocateContext(locals.currentContextId, contextSize);
 
       if (locals.currentContextLevel > 0) {
         _genDupTOS(locals.scratchVarIndexInFrame);
@@ -1487,7 +1556,7 @@
     for (Expression arg in args) {
       asm.emitPush(temp);
       _genPushInt(index++);
-      arg.accept(this);
+      _generateNode(arg);
       if (storeLastArgumentToTemp && index == totalCount) {
         // Arguments array in 'temp' is replaced with the last argument
         // in order to return result of RHS value in case of setter.
@@ -1529,7 +1598,7 @@
 
   @override
   visitAsExpression(AsExpression node) {
-    node.operand.accept(this);
+    _generateNode(node.operand);
 
     final type = node.type;
     if (typeEnvironment.isTop(type)) {
@@ -1563,12 +1632,12 @@
 
     _genConditionAndJumpIf(node.condition, false, otherwisePart);
 
-    node.then.accept(this);
+    _generateNode(node.then);
     asm.emitPopLocal(temp);
     asm.emitJump(done);
 
     asm.bind(otherwisePart);
-    node.otherwise.accept(this);
+    _generateNode(node.otherwise);
     asm.emitPopLocal(temp);
 
     asm.bind(done);
@@ -1622,7 +1691,7 @@
 
   @override
   visitDirectPropertyGet(DirectPropertyGet node) {
-    node.receiver.accept(this);
+    _generateNode(node.receiver);
     final target = node.target;
     if (target is Field || (target is Procedure && target.isGetter)) {
       _genStaticCall(target, new ConstantArgDesc(1), 1, isGet: true);
@@ -1637,8 +1706,8 @@
     final int temp = locals.tempIndexInFrame(node);
     final bool hasResult = !isExpressionWithoutResult(node);
 
-    node.receiver.accept(this);
-    node.value.accept(this);
+    _generateNode(node.receiver);
+    _generateNode(node.value);
 
     if (hasResult) {
       asm.emitStoreLocal(temp);
@@ -1665,7 +1734,7 @@
     final int newClosure = locals.tempIndexInFrame(node, tempIndex: 1);
     final int typeArguments = locals.tempIndexInFrame(node, tempIndex: 2);
 
-    node.expression.accept(this);
+    _generateNode(node.expression);
     asm.emitStoreLocal(oldClosure);
 
     _genTypeArguments(node.typeArguments);
@@ -1704,15 +1773,15 @@
 
   @override
   visitIsExpression(IsExpression node) {
-    node.operand.accept(this);
+    _generateNode(node.operand);
     _genInstanceOf(node.type);
   }
 
   @override
   visitLet(Let node) {
     _enterScope(node);
-    node.variable.accept(this);
-    node.body.accept(this);
+    _generateNode(node.variable);
+    _generateNode(node.body);
     _leaveScope();
   }
 
@@ -1736,7 +1805,7 @@
     for (int i = 0; i < node.expressions.length; i++) {
       asm.emitPush(temp);
       _genPushInt(i);
-      node.expressions[i].accept(this);
+      _generateNode(node.expressions[i]);
       asm.emitStoreIndexedTOS();
     }
 
@@ -1797,12 +1866,12 @@
         // key
         asm.emitPush(temp);
         _genPushInt(i * 2);
-        node.entries[i].key.accept(this);
+        _generateNode(node.entries[i].key);
         asm.emitStoreIndexedTOS();
         // value
         asm.emitPush(temp);
         _genPushInt(i * 2 + 1);
-        node.entries[i].value.accept(this);
+        _generateNode(node.entries[i].value);
         asm.emitStoreIndexedTOS();
       }
     }
@@ -1819,14 +1888,14 @@
     switch (opcode) {
       case Opcode.kEqualsNull:
         if (node.receiver is NullLiteral) {
-          node.arguments.positional.single.accept(this);
+          _generateNode(node.arguments.positional.single);
         } else {
-          node.receiver.accept(this);
+          _generateNode(node.receiver);
         }
         break;
 
       case Opcode.kNegateInt:
-        node.receiver.accept(this);
+        _generateNode(node.receiver);
         break;
 
       case Opcode.kAddInt:
@@ -1844,8 +1913,8 @@
       case Opcode.kCompareIntLt:
       case Opcode.kCompareIntGe:
       case Opcode.kCompareIntLe:
-        node.receiver.accept(this);
-        node.arguments.positional.single.accept(this);
+        _generateNode(node.receiver);
+        _generateNode(node.arguments.positional.single);
         break;
 
       default:
@@ -1878,7 +1947,7 @@
 
   @override
   visitPropertyGet(PropertyGet node) {
-    node.receiver.accept(this);
+    _generateNode(node.receiver);
     final argDescIndex = cp.add(new ConstantArgDesc(1));
     final icdataIndex = cp.add(new ConstantICData(
         InvocationKind.getter, node.name, argDescIndex,
@@ -1891,8 +1960,8 @@
     final int temp = locals.tempIndexInFrame(node);
     final bool hasResult = !isExpressionWithoutResult(node);
 
-    node.receiver.accept(this);
-    node.value.accept(this);
+    _generateNode(node.receiver);
+    _generateNode(node.value);
 
     if (hasResult) {
       asm.emitStoreLocal(temp);
@@ -1958,7 +2027,7 @@
           storeLastArgumentToTemp: hasResult);
     } else {
       _genPushReceiver();
-      node.value.accept(this);
+      _generateNode(node.value);
 
       if (hasResult) {
         asm.emitStoreLocal(temp);
@@ -2050,7 +2119,7 @@
       // The result of the unsafeCast() intrinsic method is its sole argument,
       // without any additional checks or type casts.
       assert(args.named.isEmpty);
-      args.positional.single.accept(this);
+      _generateNode(args.positional.single);
       return;
     }
     if (target.isFactory) {
@@ -2074,7 +2143,7 @@
   visitStaticSet(StaticSet node) {
     final bool hasResult = !isExpressionWithoutResult(node);
 
-    node.value.accept(this);
+    _generateNode(node.value);
 
     if (hasResult) {
       _genDupTOS(locals.tempIndexInFrame(node));
@@ -2093,7 +2162,7 @@
   @override
   visitStringConcatenation(StringConcatenation node) {
     if (node.expressions.length == 1) {
-      node.expressions.single.accept(this);
+      _generateNode(node.expressions.single);
       _genStaticCall(interpolateSingle, new ConstantArgDesc(1), 1);
     } else {
       asm.emitPushNull();
@@ -2106,7 +2175,7 @@
       for (int i = 0; i < node.expressions.length; i++) {
         asm.emitPush(temp);
         _genPushInt(i);
-        node.expressions[i].accept(this);
+        _generateNode(node.expressions[i]);
         asm.emitStoreIndexedTOS();
       }
 
@@ -2132,7 +2201,7 @@
 
   @override
   visitThrow(Throw node) {
-    node.expression.accept(this);
+    _generateNode(node.expression);
     asm.emitThrow(0);
   }
 
@@ -2166,7 +2235,7 @@
     if (locals.isCaptured(v)) {
       _genPushContextForVariable(v);
 
-      node.value.accept(this);
+      _generateNode(node.value);
 
       final int temp = locals.tempIndexInFrame(node);
       if (hasResult) {
@@ -2179,7 +2248,7 @@
         asm.emitPush(temp);
       }
     } else {
-      node.value.accept(this);
+      _generateNode(node.value);
 
       final int localIndex = locals.getVarIndexInFrame(v);
       if (hasResult) {
@@ -2212,11 +2281,11 @@
 
     _genConditionAndJumpIf(node.condition, true, done);
 
-    _genPushInt(omitSourcePositions ? 0 : node.conditionStartOffset);
-    _genPushInt(omitSourcePositions ? 0 : node.conditionEndOffset);
+    _genPushInt(omitAssertSourcePositions ? 0 : node.conditionStartOffset);
+    _genPushInt(omitAssertSourcePositions ? 0 : node.conditionEndOffset);
 
     if (node.message != null) {
-      node.message.accept(this);
+      _generateNode(node.message);
     } else {
       asm.emitPushNull();
     }
@@ -2230,7 +2299,7 @@
   @override
   visitBlock(Block node) {
     _enterScope(node);
-    visitList(node.statements, this);
+    _generateNodeList(node.statements);
     _leaveScope();
   }
 
@@ -2240,7 +2309,7 @@
     asm.emitJumpIfNoAsserts(done);
 
     _enterScope(node);
-    visitList(node.statements, this);
+    _generateNodeList(node.statements);
     _leaveScope();
 
     asm.bind(done);
@@ -2281,11 +2350,13 @@
     final Label join = new Label(allowsBackwardJumps: true);
     asm.bind(join);
 
-    asm.emitCheckStack();
+    asm.emitCheckStack(++currentLoopDepth);
 
-    node.body.accept(this);
+    _generateNode(node.body);
 
     _genConditionAndJumpIf(node.condition, true, join);
+
+    --currentLoopDepth;
   }
 
   @override
@@ -2296,7 +2367,7 @@
   @override
   visitExpressionStatement(ExpressionStatement node) {
     final expr = node.expression;
-    expr.accept(this);
+    _generateNode(expr);
     if (!isExpressionWithoutResult(expr)) {
       asm.emitDrop1();
     }
@@ -2304,7 +2375,7 @@
 
   @override
   visitForInStatement(ForInStatement node) {
-    node.iterable.accept(this);
+    _generateNode(node.iterable);
 
     const kIterator = 'iterator'; // Iterable.iterator
     const kMoveNext = 'moveNext'; // Iterator.moveNext
@@ -2335,7 +2406,7 @@
     final Label join = new Label(allowsBackwardJumps: true);
 
     asm.bind(join);
-    asm.emitCheckStack();
+    asm.emitCheckStack(++currentLoopDepth);
 
     if (capturedIteratorVar != null) {
       _genLoadVar(capturedIteratorVar);
@@ -2362,19 +2433,20 @@
 
     _genStoreVar(node.variable);
 
-    node.body.accept(this);
+    _generateNode(node.body);
 
     _leaveScope();
     asm.emitJump(join);
 
     asm.bind(done);
+    --currentLoopDepth;
   }
 
   @override
   visitForStatement(ForStatement node) {
     _enterScope(node);
     try {
-      visitList(node.variables, this);
+      _generateNodeList(node.variables);
 
       if (asm.isUnreachable) {
         // Bail out before binding a label which allows backward jumps,
@@ -2386,28 +2458,30 @@
       final Label join = new Label(allowsBackwardJumps: true);
       asm.bind(join);
 
-      asm.emitCheckStack();
+      asm.emitCheckStack(++currentLoopDepth);
 
       if (node.condition != null) {
         _genConditionAndJumpIf(node.condition, false, done);
       }
 
-      node.body.accept(this);
+      _generateNode(node.body);
 
       if (locals.currentContextSize > 0) {
         asm.emitPush(locals.contextVarIndexInFrame);
-        asm.emitCloneContext();
+        asm.emitCloneContext(
+            locals.currentContextId, locals.currentContextSize);
         asm.emitPopLocal(locals.contextVarIndexInFrame);
       }
 
       for (var update in node.updates) {
-        update.accept(this);
+        _generateNode(update);
         asm.emitDrop1();
       }
 
       asm.emitJump(join);
 
       asm.bind(done);
+      --currentLoopDepth;
     } finally {
       _leaveScope();
     }
@@ -2426,13 +2500,13 @@
 
     _genConditionAndJumpIf(node.condition, false, otherwisePart);
 
-    node.then.accept(this);
+    _generateNode(node.then);
 
     if (node.otherwise != null) {
       final Label done = new Label();
       asm.emitJump(done);
       asm.bind(otherwisePart);
-      node.otherwise.accept(this);
+      _generateNode(node.otherwise);
       asm.bind(done);
     } else {
       asm.bind(otherwisePart);
@@ -2444,7 +2518,7 @@
     final label = new Label();
     labeledStatements[node] = label;
     contextLevels[node] = locals.currentContextLevel;
-    node.body.accept(this);
+    _generateNode(node.body);
     asm.bind(label);
     labeledStatements.remove(node);
     contextLevels.remove(node);
@@ -2457,18 +2531,18 @@
     final List<TryFinally> tryFinallyBlocks =
         _getEnclosingTryFinallyBlocks(node, null);
     if (tryFinallyBlocks.isEmpty) {
-      expr.accept(this);
+      _generateNode(expr);
       asm.emitReturnTOS();
     } else {
       if (expr is BasicLiteral) {
         _addFinallyBlocks(tryFinallyBlocks, () {
-          expr.accept(this);
+          _generateNode(expr);
           asm.emitReturnTOS();
         });
       } else {
         // Keep return value in a variable as try-catch statements
         // inside finally can zap expression stack.
-        node.expression.accept(this);
+        _generateNode(node.expression);
         asm.emitPopLocal(locals.returnVarIndexInFrame);
 
         _addFinallyBlocks(tryFinallyBlocks, () {
@@ -2483,7 +2557,7 @@
   visitSwitchStatement(SwitchStatement node) {
     contextLevels[node] = locals.currentContextLevel;
 
-    node.expression.accept(this);
+    _generateNode(node.expression);
 
     if (asm.isUnreachable) {
       // Bail out before binding labels which allow backward jumps,
@@ -2527,7 +2601,7 @@
       final Label caseLabel = caseLabels[i];
 
       asm.bind(caseLabel);
-      switchCase.body.accept(this);
+      _generateNode(switchCase.body);
 
       // Front-end issues a compile-time error if there is a fallthrough
       // between cases. Also, default case should be the last one.
@@ -2617,8 +2691,8 @@
 
     _restoreContextForTryBlock(node);
 
-    asm.emitMoveSpecial(_exceptionVar(node), SpecialIndex.exception);
-    asm.emitMoveSpecial(_stackTraceVar(node), SpecialIndex.stackTrace);
+    asm.emitMoveSpecial(SpecialIndex.exception, _exceptionVar(node));
+    asm.emitMoveSpecial(SpecialIndex.stackTrace, _stackTraceVar(node));
 
     final capturedExceptionVar = locals.capturedExceptionVar(node);
     if (capturedExceptionVar != null) {
@@ -2667,7 +2741,7 @@
     tryBlock.isSynthetic = node.isSynthetic;
     tryCatches[node] = tryBlock; // Used by rethrow.
 
-    node.body.accept(this);
+    _generateNode(node.body);
     asm.emitJump(done);
 
     _endTryBlock(node, tryBlock);
@@ -2706,7 +2780,7 @@
         _genStoreVar(catchClause.stackTrace);
       }
 
-      catchClause.body.accept(this);
+      _generateNode(catchClause.body);
 
       _leaveScope();
       asm.emitJump(done);
@@ -2734,7 +2808,7 @@
     final TryBlock tryBlock = _startTryBlock(node);
     finallyBlocks[node] = <FinallyBlock>[];
 
-    node.body.accept(this);
+    _generateNode(node.body);
 
     if (!asm.isUnreachable) {
       final normalContinuation = new FinallyBlock(() {
@@ -2748,7 +2822,7 @@
 
     tryBlock.types.add(cp.add(new ConstantType(const DynamicType())));
 
-    node.finalizer.accept(this);
+    _generateNode(node.finalizer);
 
     tryBlock.needsStackTrace = true; // For rethrowing.
     _genRethrow(node);
@@ -2756,7 +2830,7 @@
     for (var finallyBlock in finallyBlocks[node]) {
       asm.bind(finallyBlock.entry);
       _restoreContextForTryBlock(node);
-      node.finalizer.accept(this);
+      _generateNode(node.finalizer);
       finallyBlock.generateContinuation();
     }
 
@@ -2774,15 +2848,11 @@
         _genPushContextForVariable(node);
       }
       if (node.initializer != null) {
-        node.initializer.accept(this);
+        _generateNode(node.initializer);
       } else {
         asm.emitPushNull();
       }
-      if (isCaptured) {
-        asm.emitStoreContextVar(locals.getVarIndexInContext(node));
-      } else {
-        asm.emitPopLocal(locals.getVarIndexInFrame(node));
-      }
+      _genStoreVar(node);
     }
   }
 
@@ -2798,13 +2868,14 @@
     final Label join = new Label(allowsBackwardJumps: true);
     asm.bind(join);
 
-    asm.emitCheckStack();
+    asm.emitCheckStack(++currentLoopDepth);
 
     _genConditionAndJumpIf(node.condition, false, done);
 
-    node.body.accept(this);
+    _generateNode(node.body);
 
     asm.emitJump(join);
+    --currentLoopDepth;
 
     asm.bind(done);
   }
@@ -2838,7 +2909,7 @@
 
     // return <expression>
     // Note: finally blocks are *not* executed on the way out.
-    node.expression.accept(this);
+    _generateNode(node.expression);
     asm.emitReturnTOS();
 
     asm.bind(continuationLabel);
@@ -2895,12 +2966,12 @@
 
   @override
   visitLocalInitializer(LocalInitializer node) {
-    node.variable.accept(this);
+    _generateNode(node.variable);
   }
 
   @override
   visitAssertInitializer(AssertInitializer node) {
-    node.statement.accept(this);
+    _generateNode(node.statement);
   }
 
   @override
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart
index 94c3880..b3fac13 100644
--- a/pkg/vm/lib/bytecode/local_vars.dart
+++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -63,6 +63,7 @@
 
   int get currentContextSize => _currentScope.contextSize;
   int get currentContextLevel => _currentScope.contextLevel;
+  int get currentContextId => _currentScope.contextId;
 
   int get contextLevelAtEntry =>
       _currentFrame.contextLevelAtEntry ??
@@ -74,6 +75,12 @@
     return v.scope.contextLevel;
   }
 
+  int getVarContextId(VariableDeclaration variable) {
+    final v = _getVarDesc(variable);
+    assert(v.isCaptured);
+    return v.scope.contextId;
+  }
+
   int get closureVarIndexInFrame => getVarIndexInFrame(_currentFrame
           .closureVar ??
       (throw 'Closure variable is not declared in ${_currentFrame.function}'));
@@ -257,6 +264,7 @@
   int contextUsed = 0;
   int contextSize = 0;
   int contextLevel;
+  int contextId;
 
   Scope(this.parent, this.frame, this.loopDepth);
 
@@ -699,6 +707,7 @@
 
   Scope _currentScope;
   Frame _currentFrame;
+  int _contextIdCounter = 0;
 
   _Allocator(this.locals);
 
@@ -738,6 +747,7 @@
 
     assert(_currentScope.contextOwner == null);
     assert(_currentScope.contextLevel == null);
+    assert(_currentScope.contextId == null);
 
     final int parentContextLevel =
         _currentScope.parent != null ? _currentScope.parent.contextLevel : -1;
@@ -763,8 +773,13 @@
 
       if (_currentScope.contextOwner == _currentScope) {
         _currentScope.contextLevel = parentContextLevel + 1;
+        _currentScope.contextId = _contextIdCounter++;
+        if (_currentScope.contextId >= contextIdLimit) {
+          throw new ContextIdOverflowException();
+        }
       } else {
         _currentScope.contextLevel = _currentScope.contextOwner.contextLevel;
+        _currentScope.contextId = _currentScope.contextOwner.contextId;
       }
     } else {
       _currentScope.contextLevel = parentContextLevel;
@@ -1126,8 +1141,7 @@
 
   @override
   visitStaticSet(StaticSet node) {
-    _allocateTemp(node);
-    super.visitStaticSet(node);
+    _visit(node, temps: 1);
   }
 
   @override
@@ -1148,3 +1162,5 @@
 
 class LocalVariableIndexOverflowException
     extends BytecodeLimitExceededException {}
+
+class ContextIdOverflowException extends BytecodeLimitExceededException {}
diff --git a/pkg/vm/lib/bytecode/ngrams.dart b/pkg/vm/lib/bytecode/ngrams.dart
new file mode 100644
index 0000000..040b51b
--- /dev/null
+++ b/pkg/vm/lib/bytecode/ngrams.dart
@@ -0,0 +1,147 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library vm.bytecode.ngrams;
+
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:kernel/ast.dart' show listEquals, listHashCode;
+
+import 'dbc.dart';
+import 'disassembler.dart' show Instruction, BytecodeDisassembler;
+
+bool isControlFlowInstr(Instruction instr) => isControlFlow(instr.opcode);
+
+class NGram {
+  List<Instruction> instrs;
+  List<int> _words;
+  BytecodeDisassembler _disassembler;
+
+  NGram(List<int> words, {bool mergePushes = false}) {
+    _disassembler = new BytecodeDisassembler();
+    _words = words;
+    instrs = new List<Instruction>(words.length);
+    for (int i = 0; i < instrs.length; i++) {
+      instrs[i] = _disassembler.decodeInstruction(words[i]);
+    }
+    if (mergePushes) {
+      _mergePushes(instrs);
+    }
+    _canonicalize(instrs);
+  }
+
+  /// Tests if any instructions that are not the last instruction in the window
+  /// are a jump, throw, or call.
+  bool get controlFlowIsNotLast =>
+      instrs.sublist(0, instrs.length - 1).any(isControlFlowInstr);
+
+  @override
+  int get hashCode => listHashCode(instrs);
+
+  @override
+  bool operator ==(other) =>
+      (other is NGram) && listEquals(instrs, other.instrs);
+
+  @override
+  String toString() {
+    StringBuffer out = new StringBuffer();
+    for (var instr in instrs) {
+      _disassembler.writeInstruction(out, 0, instr);
+    }
+    return out.toString();
+  }
+
+  /// Rewrites all Push-like instructions as 'Push r0'.
+  static void _mergePushes(List<Instruction> instrs) {
+    for (int i = 0; i < instrs.length; i++) {
+      if (isPush(instrs[i].opcode)) {
+        instrs[i] = new Instruction(Opcode.kPush, <int>[0]);
+      }
+    }
+  }
+
+  /// Rewrites the operands of instructions so that ngrams that differ only in
+  /// operands can be considered the same.
+  ///
+  /// Each type of operand is considered to come from a different space, and
+  /// each operand is re-indexed in that space starting from 0 such that each
+  /// distinct operand before canonicalization remains distinct afterwords. E.g.
+  ///
+  /// Push r3
+  /// Push r3
+  /// Push r4
+  ///
+  /// Becomes
+  ///
+  /// Push r0
+  /// Push r0
+  /// Push r1
+  static void _canonicalize(List<Instruction> instrs) {
+    Map<Operand, Map<int, int>> operandMaps = <Operand, Map<int, int>>{
+      // No mapping for Operand.none.
+      Operand.imm: <int, int>{},
+      Operand.lit: <int, int>{},
+      Operand.reg: <int, int>{},
+      Operand.xeg: <int, int>{},
+      Operand.tgt: <int, int>{},
+      // No mapping for Operand.spe.
+    };
+    for (Instruction instr in instrs) {
+      Format fmt = BytecodeFormats[instr.opcode];
+      for (int i = 0; i < instr.operands.length; i++) {
+        Operand op = fmt.operands[i];
+        if (!operandMaps.containsKey(op)) {
+          continue;
+        }
+        int newOperand = operandMaps[op]
+            .putIfAbsent(instr.operands[i], () => operandMaps[op].length);
+        instr.operands[i] = newOperand;
+      }
+    }
+  }
+}
+
+class NGramReader {
+  Uint32List _words;
+
+  Map<NGram, int> _ngramCounts = <NGram, int>{};
+
+  NGramReader(String traceFilename) {
+    File traceFile = File(traceFilename);
+    Uint8List data = traceFile.readAsBytesSync();
+    _words = Uint32List.view(data.buffer);
+  }
+
+  Map<NGram, int> get ngramCounts => _ngramCounts;
+
+  void readAllNGrams(int windowSize,
+      {bool basicBlocks: true, bool mergePushes: false}) {
+    int offset = 0;
+    while (offset + windowSize < _words.length) {
+      Uint32List window = _words.sublist(offset, offset + windowSize);
+      offset += 1;
+      NGram ngram = new NGram(window, mergePushes: mergePushes);
+      if (basicBlocks && ngram.controlFlowIsNotLast) {
+        continue;
+      }
+      _ngramCounts.update(ngram, (count) => count + 1, ifAbsent: () => 1);
+    }
+  }
+
+  void writeNGramStats(String outputFilename,
+      {bool sort = true, int minCount = 1000}) {
+    File outputFile = new File(outputFilename);
+    IOSink file = outputFile.openWrite();
+    List<MapEntry<NGram, int>> entries =
+        _ngramCounts.entries.where((e) => e.value > minCount).toList();
+    if (sort) {
+      entries.sort((e1, e2) => e2.value - e1.value);
+    }
+    entries.forEach((e) {
+      file.write("count: ${e.value}\n${e.key}\n");
+    });
+    file.close();
+  }
+}
diff --git a/pkg/vm/lib/bytecode/nullability_detector.dart b/pkg/vm/lib/bytecode/nullability_detector.dart
new file mode 100644
index 0000000..961dfef
--- /dev/null
+++ b/pkg/vm/lib/bytecode/nullability_detector.dart
@@ -0,0 +1,132 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library vm.bytecode.nullability_detector;
+
+import 'package:kernel/ast.dart';
+import 'dbc.dart';
+import 'recognized_methods.dart' show RecognizedMethods;
+
+class NullabilityDetector {
+  final _IsNullableVisitor _isNullableVisitor;
+
+  NullabilityDetector(RecognizedMethods recognizedMethods)
+      : _isNullableVisitor = new _IsNullableVisitor(recognizedMethods);
+
+  bool isNullable(Expression expr) => expr.accept(_isNullableVisitor);
+}
+
+class _IsNullableVisitor extends ExpressionVisitor<bool> {
+  final RecognizedMethods recognizedMethods;
+
+  _IsNullableVisitor(this.recognizedMethods);
+
+  @override
+  bool defaultExpression(Expression node) => true;
+
+  @override
+  bool visitNullLiteral(NullLiteral node) => true;
+
+  // All basic literals except NullLiteral are non-nullable.
+  @override
+  bool defaultBasicLiteral(BasicLiteral node) => false;
+
+  @override
+  bool visitVariableGet(VariableGet node) {
+    final v = node.variable;
+    if ((v.isConst || v.isFinal) && v.initializer != null) {
+      return v.initializer.accept(this);
+    }
+    return true;
+  }
+
+  @override
+  bool visitVariableSet(VariableSet node) => node.value.accept(this);
+
+  @override
+  bool visitMethodInvocation(MethodInvocation node) {
+    final Opcode opcode = recognizedMethods.specializedBytecodeFor(node);
+    if (opcode != null) {
+      return !_nonNullableBytecodeInstructions.contains(opcode);
+    }
+    return true;
+  }
+
+  @override
+  bool visitConstructorInvocation(ConstructorInvocation node) => false;
+
+  @override
+  bool visitNot(Not node) => false;
+
+  @override
+  bool visitLogicalExpression(LogicalExpression node) => false;
+
+  @override
+  bool visitConditionalExpression(ConditionalExpression node) =>
+      node.then.accept(this) || node.otherwise.accept(this);
+
+  @override
+  bool visitStringConcatenation(StringConcatenation node) => false;
+
+  @override
+  bool visitIsExpression(IsExpression node) => false;
+
+  @override
+  bool visitAsExpression(AsExpression node) => node.operand.accept(this);
+
+  @override
+  bool visitSymbolLiteral(SymbolLiteral node) => false;
+
+  @override
+  bool visitTypeLiteral(TypeLiteral node) => false;
+
+  @override
+  bool visitThisExpression(ThisExpression node) => false;
+
+  @override
+  bool visitRethrow(Rethrow node) => false;
+
+  @override
+  bool visitThrow(Throw node) => false;
+
+  @override
+  bool visitListLiteral(ListLiteral node) => false;
+
+  @override
+  bool visitMapLiteral(MapLiteral node) => false;
+
+  @override
+  bool visitFunctionExpression(FunctionExpression node) => false;
+
+  @override
+  bool visitConstantExpression(ConstantExpression node) =>
+      node.constant is NullConstant;
+
+  @override
+  bool visitLet(Let node) => node.body.accept(this);
+
+  @override
+  bool visitInstantiation(Instantiation node) => false;
+}
+
+final _nonNullableBytecodeInstructions = new Set<Opcode>.from([
+  Opcode.kBooleanNegateTOS,
+  Opcode.kEqualsNull,
+  Opcode.kNegateInt,
+  Opcode.kAddInt,
+  Opcode.kSubInt,
+  Opcode.kMulInt,
+  Opcode.kTruncDivInt,
+  Opcode.kModInt,
+  Opcode.kBitAndInt,
+  Opcode.kBitOrInt,
+  Opcode.kBitXorInt,
+  Opcode.kShlInt,
+  Opcode.kShrInt,
+  Opcode.kCompareIntEq,
+  Opcode.kCompareIntGt,
+  Opcode.kCompareIntLt,
+  Opcode.kCompareIntGe,
+  Opcode.kCompareIntLe,
+]);
diff --git a/pkg/vm/lib/bytecode/source_positions.dart b/pkg/vm/lib/bytecode/source_positions.dart
new file mode 100644
index 0000000..055f394
--- /dev/null
+++ b/pkg/vm/lib/bytecode/source_positions.dart
@@ -0,0 +1,174 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library vm.bytecode.source_positions;
+
+import 'dart:io' show BytesBuilder;
+
+/// Maintains mapping between bytecode instructions and source positions.
+class SourcePositions {
+  final Map<int, int> mapping = <int, int>{}; // PC -> fileOffset
+  int _lastPc = 0;
+  int _lastOffset = 0;
+
+  SourcePositions();
+
+  void add(int pc, int fileOffset) {
+    assert(pc > _lastPc);
+    assert(fileOffset >= 0);
+    if (fileOffset != _lastOffset) {
+      mapping[pc] = fileOffset;
+      _lastPc = pc;
+      _lastOffset = fileOffset;
+    }
+  }
+
+  List<int> toBytes() {
+    final write = new BufferedWriter();
+    write.writePackedUInt30(mapping.length);
+    final encodePC = new PackedUInt30DeltaEncoder();
+    final encodeOffset = new SLEB128DeltaEncoder();
+    mapping.forEach((int pc, int fileOffset) {
+      encodePC.write(write, pc);
+      encodeOffset.write(write, fileOffset);
+    });
+    return write.buffer.takeBytes();
+  }
+
+  SourcePositions.fromBytes(List<int> bytes) {
+    final reader = new BufferedReader(bytes);
+    final int length = reader.readPackedUInt30();
+    final decodePC = new PackedUInt30DeltaDecoder();
+    final decodeOffset = new SLEB128DeltaDecoder();
+    for (int i = 0; i < length; ++i) {
+      int pc = decodePC.read(reader);
+      int fileOffset = decodeOffset.read(reader);
+      add(pc, fileOffset);
+    }
+  }
+
+  @override
+  String toString() => mapping.toString();
+
+  Map<int, String> getBytecodeAnnotations() {
+    return mapping.map((int pc, int fileOffset) =>
+        new MapEntry(pc, 'source position $fileOffset'));
+  }
+}
+
+class BufferedWriter {
+  final BytesBuilder buffer = new BytesBuilder();
+
+  void writePackedUInt30(int value) {
+    if ((value >> 30) != 0) {
+      throw 'Value $value is out of range';
+    }
+    if (value < 0x80) {
+      buffer.addByte(value);
+    } else if (value < 0x4000) {
+      buffer.addByte((value >> 8) | 0x80);
+      buffer.addByte(value & 0xFF);
+    } else {
+      buffer.addByte((value >> 24) | 0xC0);
+      buffer.addByte((value >> 16) & 0xFF);
+      buffer.addByte((value >> 8) & 0xFF);
+      buffer.addByte(value & 0xFF);
+    }
+  }
+
+  void writeSLEB128(int value) {
+    bool last = false;
+    do {
+      int part = value & 0x7f;
+      value >>= 7;
+      if ((value == 0 && (part & 0x40) == 0) ||
+          (value == -1 && (part & 0x40) != 0)) {
+        last = true;
+      } else {
+        part |= 0x80;
+      }
+      buffer.addByte(part);
+    } while (!last);
+  }
+}
+
+class BufferedReader {
+  final List<int> _buffer;
+  int _pos = 0;
+
+  BufferedReader(this._buffer);
+
+  int readByte() => _buffer[_pos++];
+
+  int readPackedUInt30() {
+    var byte = readByte();
+    if (byte & 0x80 == 0) {
+      // 0xxxxxxx
+      return byte;
+    } else if (byte & 0x40 == 0) {
+      // 10xxxxxx
+      return ((byte & 0x3F) << 8) | readByte();
+    } else {
+      // 11xxxxxx
+      return ((byte & 0x3F) << 24) |
+          (readByte() << 16) |
+          (readByte() << 8) |
+          readByte();
+    }
+  }
+
+  int readSLEB128() {
+    int value = 0;
+    int shift = 0;
+    int part = 0;
+    do {
+      part = readByte();
+      value |= (part & 0x7f) << shift;
+      shift += 7;
+    } while ((part & 0x80) != 0);
+    const int kBitsPerInt = 64;
+    if ((shift < kBitsPerInt) && ((part & 0x40) != 0)) {
+      value |= (-1) << shift;
+    }
+    return value;
+  }
+}
+
+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/constants_error_reporter.dart b/pkg/vm/lib/constants_error_reporter.dart
index b736b22..eba53b4 100644
--- a/pkg/vm/lib/constants_error_reporter.dart
+++ b/pkg/vm/lib/constants_error_reporter.dart
@@ -25,6 +25,12 @@
 
   ForwardConstantEvaluationErrors(this.typeEnvironment);
 
+  freeTypeParameter(List<TreeNode> context, TreeNode node, DartType type) {
+    final message =
+        codes.templateConstEvalFreeTypeParameter.withArguments(type);
+    reportIt(context, message, node);
+  }
+
   duplicateKey(List<TreeNode> context, TreeNode node, Constant key) {
     final message = codes.templateConstEvalDuplicateKey.withArguments(key);
     reportIt(context, message, node);
@@ -70,6 +76,12 @@
     reportIt(context, message, node);
   }
 
+  invalidSymbolName(List<TreeNode> context, TreeNode node, Constant constant) {
+    final message =
+        codes.templateConstEvalInvalidSymbolName.withArguments(constant);
+    reportIt(context, message, node);
+  }
+
   zeroDivisor(
       List<TreeNode> context, TreeNode node, IntConstant receiver, String op) {
     final message = codes.templateConstEvalZeroDivisor
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index 7cbbe56..fc88b69 100644
--- a/pkg/vm/lib/frontend_server.dart
+++ b/pkg/vm/lib/frontend_server.dart
@@ -69,7 +69,7 @@
       help: '.packages file to use for compilation', defaultsTo: null)
   ..addOption('target',
       help: 'Target model that determines what core libraries are available',
-      allowed: <String>['vm', 'flutter'],
+      allowed: <String>['vm', 'flutter', 'flutter_runner', 'dart_runner'],
       defaultsTo: 'vm')
   ..addMultiOption('filesystem-root',
       help: 'File path that is used as a root in virtual filesystem used in'
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 03c4a51..be0184f 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -50,6 +50,7 @@
     bool useGlobalTypeFlowAnalysis: false,
     Map<String, String> environmentDefines,
     bool genBytecode: false,
+    bool emitBytecodeSourcePositions: false,
     bool dropAST: false,
     bool useFutureBytecodeFormat: false,
     bool enableAsserts: false,
@@ -95,6 +96,7 @@
     await runWithFrontEndCompilerContext(source, options, component, () {
       generateBytecode(component,
           dropAST: dropAST,
+          emitSourcePositions: emitBytecodeSourcePositions,
           useFutureBytecodeFormat: useFutureBytecodeFormat,
           environmentDefines: environmentDefines);
     });
diff --git a/pkg/vm/lib/metadata/bytecode.dart b/pkg/vm/lib/metadata/bytecode.dart
index 573bd02..e333cfc 100644
--- a/pkg/vm/lib/metadata/bytecode.dart
+++ b/pkg/vm/lib/metadata/bytecode.dart
@@ -10,6 +10,7 @@
     show stableBytecodeFormatVersion, futureBytecodeFormatVersion;
 import '../bytecode/disassembler.dart' show BytecodeDisassembler;
 import '../bytecode/exceptions.dart' show ExceptionsTable;
+import '../bytecode/source_positions.dart' show SourcePositions;
 
 /// Metadata containing bytecode.
 ///
@@ -17,14 +18,21 @@
 ///
 /// type BytecodeMetadata {
 ///   UInt bytecodeFormatVersion
-///   UInt flags (HasExceptionsTable, HasNullableFields, HasClosures)
-///
+///   UInt flags (HasExceptionsTable, HasSourcePositions, HasNullableFields,
+///               HasClosures)
 ///   ConstantPool constantPool
-///   List<Byte> bytecodes
+///
+///   UInt bytecodeSizeInBytes
+///   Byte paddingSizeInBytes
+///   Byte[paddingSizeInBytes] padding
+///   Byte[bytecodeSizeInBytes] bytecodes
 ///
 ///   (optional, present if HasExceptionsTable)
 ///   ExceptionsTable exceptionsTable
 ///
+///   (optional, present if HasSourcePositions)
+///   SourcePositions sourcePositionsTabe
+///
 ///   (optional, present if HasNullableFields)
 ///   List<CanonicalName> nullableFields
 ///
@@ -34,8 +42,18 @@
 ///
 /// type ClosureBytecode {
 ///   ConstantIndex closureFunction
-///   List<Byte> bytecodes
+///   UInt flags (HasExceptionsTable, HasSourcePositions)
+///
+///   UInt bytecodeSizeInBytes
+///   Byte paddingSizeInBytes
+///   Byte[paddingSizeInBytes] padding
+///   Byte[bytecodeSizeInBytes] bytecodes
+///
+///   (optional, present if HasExceptionsTable)
 ///   ExceptionsTable exceptionsTable
+///
+///   (optional, present if HasSourcePositions)
+///   SourcePositions sourcePositionsTabe
 /// }
 ///
 /// Encoding of ExceptionsTable is described in
@@ -46,27 +64,37 @@
 ///
 class BytecodeMetadata {
   static const hasExceptionsTableFlag = 1 << 0;
-  static const hasNullableFieldsFlag = 1 << 1;
-  static const hasClosuresFlag = 1 << 2;
+  static const hasSourcePositionsFlag = 1 << 1;
+  static const hasNullableFieldsFlag = 1 << 2;
+  static const hasClosuresFlag = 1 << 3;
 
   final int version;
   final ConstantPool constantPool;
   final List<int> bytecodes;
   final ExceptionsTable exceptionsTable;
+  final SourcePositions sourcePositions;
   final List<Reference> nullableFields;
   final List<ClosureBytecode> closures;
 
   bool get hasExceptionsTable => exceptionsTable.blocks.isNotEmpty;
+  bool get hasSourcePositions => sourcePositions.mapping.isNotEmpty;
   bool get hasNullableFields => nullableFields.isNotEmpty;
   bool get hasClosures => closures.isNotEmpty;
 
   int get flags =>
       (hasExceptionsTable ? hasExceptionsTableFlag : 0) |
+      (hasSourcePositions ? hasSourcePositionsFlag : 0) |
       (hasNullableFields ? hasNullableFieldsFlag : 0) |
       (hasClosures ? hasClosuresFlag : 0);
 
-  BytecodeMetadata(this.version, this.constantPool, this.bytecodes,
-      this.exceptionsTable, this.nullableFields, this.closures);
+  BytecodeMetadata(
+      this.version,
+      this.constantPool,
+      this.bytecodes,
+      this.exceptionsTable,
+      this.sourcePositions,
+      this.nullableFields,
+      this.closures);
 
   // TODO(alexmarkov): Consider printing constant pool before bytecode.
   @override
@@ -75,7 +103,9 @@
       " (version: "
       "${version == stableBytecodeFormatVersion ? 'stable' : version == futureBytecodeFormatVersion ? 'future' : "v$version"}"
       ") {\n"
-      "${new BytecodeDisassembler().disassemble(bytecodes, exceptionsTable)}}\n"
+      "${new BytecodeDisassembler().disassemble(bytecodes, exceptionsTable, annotations: [
+        sourcePositions.getBytecodeAnnotations()
+      ])}}\n"
       "$exceptionsTable"
       "${nullableFields.isEmpty ? '' : 'Nullable fields: ${nullableFields.map((ref) => ref.asField).toList()}\n'}"
       "$constantPool"
@@ -88,30 +118,53 @@
   final int closureFunctionConstantIndex;
   final List<int> bytecodes;
   final ExceptionsTable exceptionsTable;
+  final SourcePositions sourcePositions;
 
-  ClosureBytecode(
-      this.closureFunctionConstantIndex, this.bytecodes, this.exceptionsTable);
+  bool get hasExceptionsTable => exceptionsTable.blocks.isNotEmpty;
+  bool get hasSourcePositions => sourcePositions.mapping.isNotEmpty;
+
+  int get flags =>
+      (hasExceptionsTable ? BytecodeMetadata.hasExceptionsTableFlag : 0) |
+      (hasSourcePositions ? BytecodeMetadata.hasSourcePositionsFlag : 0);
+
+  ClosureBytecode(this.closureFunctionConstantIndex, this.bytecodes,
+      this.exceptionsTable, this.sourcePositions);
 
   void writeToBinary(BinarySink sink) {
     sink.writeUInt30(closureFunctionConstantIndex);
-    sink.writeByteList(bytecodes);
-    exceptionsTable.writeToBinary(sink);
+    sink.writeUInt30(flags);
+    _writeBytecodeInstructions(sink, bytecodes);
+    if (hasExceptionsTable) {
+      exceptionsTable.writeToBinary(sink);
+    }
+    if (hasSourcePositions) {
+      sink.writeByteList(sourcePositions.toBytes());
+    }
   }
 
   factory ClosureBytecode.readFromBinary(BinarySource source) {
     final closureFunctionConstantIndex = source.readUInt();
-    final List<int> bytecodes = source.readByteList();
-    final exceptionsTable = new ExceptionsTable.readFromBinary(source);
-    return new ClosureBytecode(
-        closureFunctionConstantIndex, bytecodes, exceptionsTable);
+    final int flags = source.readUInt();
+    final List<int> bytecodes = _readBytecodeInstructions(source);
+    final exceptionsTable =
+        ((flags & BytecodeMetadata.hasExceptionsTableFlag) != 0)
+            ? new ExceptionsTable.readFromBinary(source)
+            : new ExceptionsTable();
+    final sourcePositions =
+        ((flags & BytecodeMetadata.hasSourcePositionsFlag) != 0)
+            ? new SourcePositions.fromBytes(source.readByteList())
+            : new SourcePositions();
+    return new ClosureBytecode(closureFunctionConstantIndex, bytecodes,
+        exceptionsTable, sourcePositions);
   }
 
   @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.writeln('Closure CP#$closureFunctionConstantIndex {');
-    sb.writeln(
-        new BytecodeDisassembler().disassemble(bytecodes, exceptionsTable));
+    sb.writeln(new BytecodeDisassembler().disassemble(
+        bytecodes, exceptionsTable,
+        annotations: [sourcePositions.getBytecodeAnnotations()]));
     sb.writeln('}');
     return sb.toString();
   }
@@ -131,10 +184,13 @@
     sink.writeUInt30(metadata.version);
     sink.writeUInt30(metadata.flags);
     metadata.constantPool.writeToBinary(node, sink);
-    sink.writeByteList(metadata.bytecodes);
+    _writeBytecodeInstructions(sink, metadata.bytecodes);
     if (metadata.hasExceptionsTable) {
       metadata.exceptionsTable.writeToBinary(sink);
     }
+    if (metadata.hasSourcePositions) {
+      sink.writeByteList(metadata.sourcePositions.toBytes());
+    }
     if (metadata.hasNullableFields) {
       sink.writeUInt30(metadata.nullableFields.length);
       metadata.nullableFields.forEach((ref) => sink
@@ -156,11 +212,15 @@
     int flags = source.readUInt();
     final ConstantPool constantPool =
         new ConstantPool.readFromBinary(node, source);
-    final List<int> bytecodes = source.readByteList();
+    final List<int> bytecodes = _readBytecodeInstructions(source);
     final exceptionsTable =
         ((flags & BytecodeMetadata.hasExceptionsTableFlag) != 0)
             ? new ExceptionsTable.readFromBinary(source)
             : new ExceptionsTable();
+    final sourcePositions =
+        ((flags & BytecodeMetadata.hasSourcePositionsFlag) != 0)
+            ? new SourcePositions.fromBytes(source.readByteList())
+            : new SourcePositions();
     final List<Reference> nullableFields =
         ((flags & BytecodeMetadata.hasNullableFieldsFlag) != 0)
             ? new List<Reference>.generate(source.readUInt(),
@@ -172,6 +232,36 @@
                 (_) => new ClosureBytecode.readFromBinary(source))
             : const <ClosureBytecode>[];
     return new BytecodeMetadata(version, constantPool, bytecodes,
-        exceptionsTable, nullableFields, closures);
+        exceptionsTable, sourcePositions, nullableFields, closures);
+  }
+}
+
+void _writeBytecodeInstructions(BinarySink sink, List<int> bytecodes) {
+  sink.writeUInt30(bytecodes.length);
+  _writeBytecodePadding(sink);
+  sink.writeBytes(bytecodes);
+}
+
+List<int> _readBytecodeInstructions(BinarySource source) {
+  int len = source.readUInt();
+  _readBytecodePadding(source);
+  return source.readBytes(len);
+}
+
+void _writeBytecodePadding(BinarySink sink) {
+  const int bytecodeAlignment = 4;
+  int offset = sink.getBufferOffset() + 1; // +1 is for the length.
+  int len = ((offset + bytecodeAlignment - 1) & -bytecodeAlignment) - offset;
+  sink.writeByte(len);
+  for (int i = 0; i < len; ++i) {
+    sink.writeByte(0);
+  }
+  assert((sink.getBufferOffset() & (bytecodeAlignment - 1)) == 0);
+}
+
+void _readBytecodePadding(BinarySource source) {
+  int len = source.readByte();
+  for (int i = 0; i < len; ++i) {
+    source.readByte();
   }
 }
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index 0937ab8..71df95d 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -452,6 +452,7 @@
   @override
   visitTypedefType(TypedefType node) {
     shaker.addUsedTypedef(node.typedefNode);
+    node.visitChildren(this);
   }
 
   @override
diff --git a/pkg/vm/pubspec.yaml b/pkg/vm/pubspec.yaml
index c1ba691..ef74ee0 100644
--- a/pkg/vm/pubspec.yaml
+++ b/pkg/vm/pubspec.yaml
@@ -6,8 +6,8 @@
 dependencies:
   build_integration:
     path: ../build_integration
-  front_end: 0.1.6
-  kernel: 0.3.6
+  front_end: ^0.1.6
+  kernel: ^0.3.6
 
 dev_dependencies:
   args: ^1.4.4
diff --git a/pkg/vm/test/bytecode/gen_bytecode_test.dart b/pkg/vm/test/bytecode/gen_bytecode_test.dart
index 758f47f..1cb36de 100644
--- a/pkg/vm/test/bytecode/gen_bytecode_test.dart
+++ b/pkg/vm/test/bytecode/gen_bytecode_test.dart
@@ -31,7 +31,7 @@
   await runWithFrontEndCompilerContext(source, options, component, () {
     // Need to omit source positions from bytecode as they are different on
     // Linux and Windows (due to differences in newline characters).
-    generateBytecode(component, omitSourcePositions: true);
+    generateBytecode(component, omitAssertSourcePositions: true);
   });
 
   final actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
diff --git a/pkg/vm/testcases/bytecode/asserts.dart.expect b/pkg/vm/testcases/bytecode/asserts.dart.expect
index 8c9b60b..e61e22a 100644
--- a/pkg/vm/testcases/bytecode/asserts.dart.expect
+++ b/pkg/vm/testcases/bytecode/asserts.dart.expect
@@ -5,7 +5,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   JumpIfNoAsserts      L1
   Push                 FP[-5]
   AssertBoolean        0
@@ -30,7 +30,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   JumpIfNoAsserts      L1
   Push                 FP[-6]
   InstanceCall         1, CP#1
@@ -60,7 +60,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   ReturnTOS
 }
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
index 7b37aaa..52a3d89 100644
--- a/pkg/vm/testcases/bytecode/async.dart.expect
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -6,7 +6,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                3
-  CheckStack
+  CheckStack           0
   Allocate             CP#19
   StoreLocal           r2
   Push                 r2
@@ -70,33 +70,33 @@
   LoadConstant         r2, CP#10
   LoadConstant         r3, CP#10
   Frame                6
-  CheckStack
+  CheckStack           0
   Push                 r0
   LoadFieldTOS         CP#1
   PopLocal             r4
   Push                 r4
-  LoadContextVar       5
+  LoadContextVar       0, 5
   StoreLocal           r5
   PushInt              0
   JumpIfNeStrict       L1
   Push                 r4
   Push                 r4
-  StoreContextVar      7
+  StoreContextVar      0, 7
 Try #0 start:
   Push                 r4
   PushInt              1
-  StoreContextVar      5
+  StoreContextVar      0, 5
   Push                 r4
   Push                 r4
-  StoreContextVar      6
+  StoreContextVar      0, 6
   Push                 r4
-  LoadContextVar       0
+  LoadContextVar       0, 0
   Push                 r4
-  LoadContextVar       3
+  LoadContextVar       0, 3
   Push                 r4
-  LoadContextVar       4
+  LoadContextVar       0, 4
   Push                 r4
-  LoadContextVar       8
+  LoadContextVar       0, 8
   PushConstant         CP#12
   IndirectStaticCall   4, CP#11
   PopLocal             r8
@@ -112,9 +112,9 @@
   Push                 r1
   Drop1
   Push                 r4
-  LoadContextVar       1
+  LoadContextVar       0, 1
   Push                 r4
-  LoadContextVar       2
+  LoadContextVar       0, 2
   PushConstant         CP#14
   IndirectStaticCall   2, CP#13
   Drop1
@@ -127,16 +127,16 @@
   LoadFieldTOS         CP#1
   PopLocal             r4
   Push                 r4
-  LoadContextVar       7
+  LoadContextVar       0, 7
   PopLocal             r4
-  MoveSpecial          r6, exception
-  MoveSpecial          r7, stackTrace
+  MoveSpecial          exception, r6
+  MoveSpecial          stackTrace, r7
   Push                 r6
   PopLocal             r8
   Push                 r7
   PopLocal             r9
   Push                 r4
-  LoadContextVar       1
+  LoadContextVar       0, 1
   Push                 r8
   Push                 r9
   InstanceCall         3, CP#17
@@ -147,7 +147,7 @@
   ReturnTOS
 L1:
   Push                 r4
-  LoadContextVar       6
+  LoadContextVar       0, 6
   PopLocal             r4
   Jump                 L4
 
@@ -155,15 +155,15 @@
 
 Closure CP#0 {
   EntryFixed           2, 4
-  CheckStack
+  CheckStack           0
   Push                 FP[-6]
   LoadFieldTOS         CP#1
   PopLocal             r0
-  AllocateContext      9
+  AllocateContext      0, 9
   PopLocal             r0
   Push                 r0
   Push                 FP[-5]
-  StoreContextVar      0
+  StoreContextVar      0, 0
   Push                 FP[-5]
   PushConstant         CP#3
   PushNull
@@ -175,27 +175,27 @@
   PushConstant         CP#6
   PushConstant         CP#8
   IndirectStaticCall   1, CP#7
-  StoreContextVar      1
+  StoreContextVar      0, 1
   Push                 r0
   PushNull
-  StoreContextVar      2
+  StoreContextVar      0, 2
   PushNull
   PopLocal             r2
   Push                 r0
   PushNull
-  StoreContextVar      3
+  StoreContextVar      0, 3
   Push                 r0
   PushNull
-  StoreContextVar      4
+  StoreContextVar      0, 4
   Push                 r0
   PushInt              0
-  StoreContextVar      5
+  StoreContextVar      0, 5
   Push                 r0
   PushNull
-  StoreContextVar      6
+  StoreContextVar      0, 6
   Push                 r0
   PushNull
-  StoreContextVar      7
+  StoreContextVar      0, 7
   Push                 r0
   Allocate             CP#19
   StoreLocal           r3
@@ -214,32 +214,32 @@
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#1
-  StoreContextVar      8
+  StoreContextVar      0, 8
   Push                 r0
-  LoadContextVar       8
+  LoadContextVar       0, 8
   PushConstant         CP#29
   IndirectStaticCall   1, CP#7
   PopLocal             r2
   Push                 r0
   Push                 r0
-  LoadContextVar       8
+  LoadContextVar       0, 8
   PushConstant         CP#30
   IndirectStaticCall   1, CP#7
-  StoreContextVar      3
+  StoreContextVar      0, 3
   Push                 r0
   Push                 r0
-  LoadContextVar       8
+  LoadContextVar       0, 8
   PushConstant         CP#31
   IndirectStaticCall   1, CP#7
-  StoreContextVar      4
+  StoreContextVar      0, 4
   PushConstant         CP#32
   Push                 r0
-  LoadContextVar       8
+  LoadContextVar       0, 8
   PushConstant         CP#33
   IndirectStaticCall   2, CP#13
   Drop1
   Push                 r0
-  LoadContextVar       1
+  LoadContextVar       0, 1
   InstanceCall         1, CP#34
   ReturnTOS
 
@@ -275,17 +275,17 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                7
-  CheckStack
-  AllocateContext      4
+  CheckStack           0
+  AllocateContext      0, 4
   PopLocal             r0
   Push                 r0
   PushConstant         CP#0
   PushConstant         CP#2
   IndirectStaticCall   1, CP#1
-  StoreContextVar      0
+  StoreContextVar      0, 0
   Push                 r0
   PushNull
-  StoreContextVar      1
+  StoreContextVar      0, 1
   PushNull
   PopLocal             r2
   PushNull
@@ -294,10 +294,10 @@
   PopLocal             r4
   Push                 r0
   PushInt              0
-  StoreContextVar      2
+  StoreContextVar      0, 2
   Push                 r0
   PushNull
-  StoreContextVar      3
+  StoreContextVar      0, 3
   Allocate             CP#13
   StoreLocal           r6
   Push                 r6
@@ -334,7 +334,7 @@
   IndirectStaticCall   2, CP#7
   Drop1
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   InstanceCall         1, CP#28
   ReturnTOS
 }
@@ -375,12 +375,12 @@
   LoadConstant         r2, CP#4
   LoadConstant         r3, CP#4
   Frame                6
-  CheckStack
+  CheckStack           0
   Push                 r0
   LoadFieldTOS         CP#5
   PopLocal             r4
   Push                 r4
-  LoadContextVar       2
+  LoadContextVar       0, 2
   StoreLocal           r5
   PushInt              0
   JumpIfNeStrict       L1
@@ -389,13 +389,13 @@
 Try #0 start:
   Push                 r4
   PushInt              42
-  StoreContextVar      1
+  StoreContextVar      0, 1
   Jump                 L2
 L2:
   Push                 r4
-  LoadContextVar       0
+  LoadContextVar       0, 0
   Push                 r4
-  LoadContextVar       1
+  LoadContextVar       0, 1
   PushConstant         CP#8
   IndirectStaticCall   2, CP#7
   Drop1
@@ -406,14 +406,14 @@
   SetFrame             10
   Push                 r6
   PopLocal             r4
-  MoveSpecial          r6, exception
-  MoveSpecial          r7, stackTrace
+  MoveSpecial          exception, r6
+  MoveSpecial          stackTrace, r7
   Push                 r6
   PopLocal             r8
   Push                 r7
   PopLocal             r9
   Push                 r4
-  LoadContextVar       0
+  LoadContextVar       0, 0
   Push                 r8
   Push                 r9
   InstanceCall         3, CP#11
@@ -456,43 +456,43 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                4
-  CheckStack
-  AllocateContext      11
+  CheckStack           0
+  AllocateContext      0, 11
   PopLocal             r0
   Push                 r0
   Push                 FP[-6]
-  StoreContextVar      0
+  StoreContextVar      0, 0
   Push                 r0
   Push                 FP[-5]
-  StoreContextVar      1
+  StoreContextVar      0, 1
   Push                 r0
   PushConstant         CP#0
   PushConstant         CP#2
   IndirectStaticCall   1, CP#1
-  StoreContextVar      2
+  StoreContextVar      0, 2
   Push                 r0
   PushNull
-  StoreContextVar      3
+  StoreContextVar      0, 3
   PushNull
   PopLocal             r2
   Push                 r0
   PushNull
-  StoreContextVar      4
+  StoreContextVar      0, 4
   Push                 r0
   PushNull
-  StoreContextVar      5
+  StoreContextVar      0, 5
   Push                 r0
   PushInt              0
-  StoreContextVar      6
+  StoreContextVar      0, 6
   Push                 r0
   PushNull
-  StoreContextVar      7
+  StoreContextVar      0, 7
   Push                 r0
   PushNull
-  StoreContextVar      8
+  StoreContextVar      0, 8
   Push                 r0
   PushNull
-  StoreContextVar      9
+  StoreContextVar      0, 9
   Push                 r0
   Allocate             CP#17
   StoreLocal           r3
@@ -511,32 +511,32 @@
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#5
-  StoreContextVar      10
+  StoreContextVar      0, 10
   Push                 r0
-  LoadContextVar       10
+  LoadContextVar       0, 10
   PushConstant         CP#27
   IndirectStaticCall   1, CP#1
   PopLocal             r2
   Push                 r0
   Push                 r0
-  LoadContextVar       10
+  LoadContextVar       0, 10
   PushConstant         CP#28
   IndirectStaticCall   1, CP#1
-  StoreContextVar      4
+  StoreContextVar      0, 4
   Push                 r0
   Push                 r0
-  LoadContextVar       10
+  LoadContextVar       0, 10
   PushConstant         CP#29
   IndirectStaticCall   1, CP#1
-  StoreContextVar      5
+  StoreContextVar      0, 5
   PushConstant         CP#30
   Push                 r0
-  LoadContextVar       10
+  LoadContextVar       0, 10
   PushConstant         CP#31
   IndirectStaticCall   2, CP#10
   Drop1
   Push                 r0
-  LoadContextVar       2
+  LoadContextVar       0, 2
   InstanceCall         1, CP#32
   ReturnTOS
 }
@@ -581,33 +581,33 @@
   LoadConstant         r2, CP#4
   LoadConstant         r3, CP#4
   Frame                6
-  CheckStack
+  CheckStack           0
   Push                 r0
   LoadFieldTOS         CP#5
   PopLocal             r4
   Push                 r4
-  LoadContextVar       6
+  LoadContextVar       0, 6
   StoreLocal           r5
   PushInt              0
   JumpIfNeStrict       L1
   Push                 r4
   Push                 r4
-  StoreContextVar      8
+  StoreContextVar      0, 8
 Try #0 start:
   Push                 r4
   PushInt              1
-  StoreContextVar      6
+  StoreContextVar      0, 6
   Push                 r4
   Push                 r4
-  StoreContextVar      7
+  StoreContextVar      0, 7
   Push                 r4
-  LoadContextVar       0
+  LoadContextVar       0, 0
   Push                 r4
-  LoadContextVar       4
+  LoadContextVar       0, 4
   Push                 r4
-  LoadContextVar       5
+  LoadContextVar       0, 5
   Push                 r4
-  LoadContextVar       10
+  LoadContextVar       0, 10
   PushConstant         CP#8
   IndirectStaticCall   4, CP#7
   PopLocal             r8
@@ -622,21 +622,21 @@
 L2:
   Push                 r4
   Push                 r1
-  StoreContextVar      9
+  StoreContextVar      0, 9
   Push                 r4
   PushInt              2
-  StoreContextVar      6
+  StoreContextVar      0, 6
   Push                 r4
   Push                 r4
-  StoreContextVar      7
+  StoreContextVar      0, 7
   Push                 r4
-  LoadContextVar       1
+  LoadContextVar       0, 1
   Push                 r4
-  LoadContextVar       4
+  LoadContextVar       0, 4
   Push                 r4
-  LoadContextVar       5
+  LoadContextVar       0, 5
   Push                 r4
-  LoadContextVar       10
+  LoadContextVar       0, 10
   PushConstant         CP#9
   IndirectStaticCall   4, CP#7
   PopLocal             r9
@@ -651,16 +651,16 @@
 L3:
   Push                 r4
   Push                 r4
-  LoadContextVar       9
+  LoadContextVar       0, 9
   Push                 r1
   InstanceCall         2, CP#11
-  StoreContextVar      3
+  StoreContextVar      0, 3
   Jump                 L4
 L4:
   Push                 r4
-  LoadContextVar       2
+  LoadContextVar       0, 2
   Push                 r4
-  LoadContextVar       3
+  LoadContextVar       0, 3
   PushConstant         CP#12
   IndirectStaticCall   2, CP#10
   Drop1
@@ -673,16 +673,16 @@
   LoadFieldTOS         CP#5
   PopLocal             r4
   Push                 r4
-  LoadContextVar       8
+  LoadContextVar       0, 8
   PopLocal             r4
-  MoveSpecial          r6, exception
-  MoveSpecial          r7, stackTrace
+  MoveSpecial          exception, r6
+  MoveSpecial          stackTrace, r7
   Push                 r6
   PopLocal             r8
   Push                 r7
   PopLocal             r9
   Push                 r4
-  LoadContextVar       2
+  LoadContextVar       0, 2
   Push                 r8
   Push                 r9
   InstanceCall         3, CP#15
@@ -693,7 +693,7 @@
   ReturnTOS
 L1:
   Push                 r4
-  LoadContextVar       7
+  LoadContextVar       0, 7
   PopLocal             r4
   Push                 r5
   PushInt              1
@@ -736,43 +736,43 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                4
-  CheckStack
-  AllocateContext      11
+  CheckStack           0
+  AllocateContext      0, 11
   PopLocal             r0
   Push                 r0
   Push                 FP[-5]
-  StoreContextVar      0
+  StoreContextVar      0, 0
   Push                 r0
   PushConstant         CP#0
   PushConstant         CP#2
   IndirectStaticCall   1, CP#1
-  StoreContextVar      1
+  StoreContextVar      0, 1
   Push                 r0
   PushNull
-  StoreContextVar      2
+  StoreContextVar      0, 2
   PushNull
   PopLocal             r2
   Push                 r0
   PushNull
-  StoreContextVar      3
+  StoreContextVar      0, 3
   Push                 r0
   PushNull
-  StoreContextVar      4
+  StoreContextVar      0, 4
   Push                 r0
   PushInt              0
-  StoreContextVar      5
+  StoreContextVar      0, 5
   Push                 r0
   PushNull
-  StoreContextVar      6
+  StoreContextVar      0, 6
   Push                 r0
   PushNull
-  StoreContextVar      7
+  StoreContextVar      0, 7
   Push                 r0
   PushNull
-  StoreContextVar      8
+  StoreContextVar      0, 8
   Push                 r0
   PushNull
-  StoreContextVar      9
+  StoreContextVar      0, 9
   Push                 r0
   Allocate             CP#22
   StoreLocal           r3
@@ -791,32 +791,32 @@
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#5
-  StoreContextVar      10
+  StoreContextVar      0, 10
   Push                 r0
-  LoadContextVar       10
+  LoadContextVar       0, 10
   PushConstant         CP#32
   IndirectStaticCall   1, CP#1
   PopLocal             r2
   Push                 r0
   Push                 r0
-  LoadContextVar       10
+  LoadContextVar       0, 10
   PushConstant         CP#33
   IndirectStaticCall   1, CP#1
-  StoreContextVar      3
+  StoreContextVar      0, 3
   Push                 r0
   Push                 r0
-  LoadContextVar       10
+  LoadContextVar       0, 10
   PushConstant         CP#34
   IndirectStaticCall   1, CP#1
-  StoreContextVar      4
+  StoreContextVar      0, 4
   PushConstant         CP#35
   Push                 r0
-  LoadContextVar       10
+  LoadContextVar       0, 10
   PushConstant         CP#36
   IndirectStaticCall   2, CP#14
   Drop1
   Push                 r0
-  LoadContextVar       1
+  LoadContextVar       0, 1
   InstanceCall         1, CP#37
   ReturnTOS
 }
@@ -866,20 +866,20 @@
   LoadConstant         r2, CP#4
   LoadConstant         r3, CP#4
   Frame                7
-  CheckStack
+  CheckStack           0
   Push                 r0
   LoadFieldTOS         CP#5
   PopLocal             r4
   Push                 r4
-  LoadContextVar       5
+  LoadContextVar       0, 5
   StoreLocal           r5
   PushInt              0
   JumpIfNeStrict       L1
   Push                 r4
   Push                 r4
-  StoreContextVar      7
+  StoreContextVar      0, 7
 Try #0 start:
-  AllocateContext      1
+  AllocateContext      1, 1
   StoreLocal           r5
   Push                 r5
   Push                 r4
@@ -887,8 +887,8 @@
   PopLocal             r4
   Push                 r4
   PushInt              0
-  StoreContextVar      0
-  AllocateContext      2
+  StoreContextVar      1, 0
+  AllocateContext      2, 2
   StoreLocal           r5
   Push                 r5
   Push                 r4
@@ -896,32 +896,31 @@
   PopLocal             r4
   Push                 r4
   PushInt              0
-  StoreContextVar      0
+  StoreContextVar      2, 0
 L6:
-  CheckStack
+  CheckStack           1
   Push                 r4
-  LoadContextVar       0
+  LoadContextVar       2, 0
   PushInt              10
   CompareIntLt
-  AssertBoolean        0
   JumpIfFalse          L2
   Push                 r4
   LoadContextParent
   LoadContextParent
-  LoadContextVar       0
+  LoadContextVar       0, 0
   InstanceCall         1, CP#7
   PopLocal             r8
   Push                 r4
   Push                 r8
-  StoreContextVar      1
+  StoreContextVar      2, 1
 L5:
-  CheckStack
+  CheckStack           2
   Push                 r4
-  LoadContextVar       1
+  LoadContextVar       2, 1
   StoreLocal           r8
   InstanceCall         1, CP#8
   JumpIfFalse          L3
-  AllocateContext      1
+  AllocateContext      3, 1
   StoreLocal           r5
   Push                 r5
   Push                 r4
@@ -930,7 +929,7 @@
   Push                 r4
   Push                 r8
   InstanceCall         1, CP#9
-  StoreContextVar      0
+  StoreContextVar      3, 0
   Push                 r4
   LoadContextParent
   LoadContextParent
@@ -938,48 +937,48 @@
   Push                 r4
   LoadContextParent
   LoadContextParent
-  LoadContextVar       0
-  StoreContextVar      9
+  LoadContextVar       1, 0
+  StoreContextVar      0, 9
   Push                 r4
   LoadContextParent
   LoadContextParent
   LoadContextParent
   Push                 r4
   LoadContextParent
-  LoadContextVar       0
+  LoadContextVar       2, 0
   Push                 r4
-  LoadContextVar       0
+  LoadContextVar       3, 0
   AddInt
-  StoreContextVar      8
+  StoreContextVar      0, 8
   Push                 r4
   LoadContextParent
   LoadContextParent
   LoadContextParent
   PushInt              1
-  StoreContextVar      5
+  StoreContextVar      0, 5
   Push                 r4
   LoadContextParent
   LoadContextParent
   LoadContextParent
   Push                 r4
-  StoreContextVar      6
+  StoreContextVar      0, 6
   PushConstant         CP#11
   IndirectStaticCall   0, CP#10
   Push                 r4
   LoadContextParent
   LoadContextParent
   LoadContextParent
-  LoadContextVar       3
+  LoadContextVar       0, 3
   Push                 r4
   LoadContextParent
   LoadContextParent
   LoadContextParent
-  LoadContextVar       4
+  LoadContextVar       0, 4
   Push                 r4
   LoadContextParent
   LoadContextParent
   LoadContextParent
-  LoadContextVar       10
+  LoadContextVar       0, 10
   PushConstant         CP#13
   IndirectStaticCall   4, CP#12
   PopLocal             r10
@@ -999,31 +998,31 @@
   LoadContextParent
   LoadContextParent
   LoadContextParent
-  LoadContextVar       9
+  LoadContextVar       0, 9
   Push                 r4
   LoadContextParent
   LoadContextParent
   LoadContextParent
-  LoadContextVar       8
+  LoadContextVar       0, 8
   Push                 r1
   InstanceCall         2, CP#15
   InstanceCall         2, CP#16
-  StoreContextVar      0
+  StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
   PopLocal             r4
   Jump                 L5
 L3:
   Push                 r4
-  CloneContext
+  CloneContext         2, 2
   PopLocal             r4
   Push                 r4
   Push                 r4
-  LoadContextVar       0
+  LoadContextVar       2, 0
   PushInt              1
   AddInt
   StoreLocal           r8
-  StoreContextVar      0
+  StoreContextVar      2, 0
   Push                 r8
   Drop1
   Jump                 L6
@@ -1034,18 +1033,17 @@
   PushInt              0
   PopLocal             r8
 L8:
-  CheckStack
+  CheckStack           1
   Push                 r8
   PushInt              10
   CompareIntLt
-  AssertBoolean        0
   JumpIfFalse          L7
   Push                 r4
   Push                 r4
-  LoadContextVar       0
+  LoadContextVar       1, 0
   Push                 r8
   AddInt
-  StoreContextVar      0
+  StoreContextVar      1, 0
   Push                 r8
   PushInt              1
   AddInt
@@ -1056,17 +1054,17 @@
   Push                 r4
   LoadContextParent
   Push                 r4
-  LoadContextVar       0
-  StoreContextVar      2
+  LoadContextVar       1, 0
+  StoreContextVar      0, 2
   Push                 r4
   LoadContextParent
   PopLocal             r4
   Jump                 L9
 L9:
   Push                 r4
-  LoadContextVar       1
+  LoadContextVar       0, 1
   Push                 r4
-  LoadContextVar       2
+  LoadContextVar       0, 2
   PushConstant         CP#17
   IndirectStaticCall   2, CP#14
   Drop1
@@ -1079,16 +1077,16 @@
   LoadFieldTOS         CP#5
   PopLocal             r4
   Push                 r4
-  LoadContextVar       7
+  LoadContextVar       0, 7
   PopLocal             r4
-  MoveSpecial          r6, exception
-  MoveSpecial          r7, stackTrace
+  MoveSpecial          exception, r6
+  MoveSpecial          stackTrace, r7
   Push                 r6
   PopLocal             r8
   Push                 r7
   PopLocal             r9
   Push                 r4
-  LoadContextVar       1
+  LoadContextVar       0, 1
   Push                 r8
   Push                 r9
   InstanceCall         3, CP#20
@@ -1099,7 +1097,7 @@
   ReturnTOS
 L1:
   Push                 r4
-  LoadContextVar       6
+  LoadContextVar       0, 6
   PopLocal             r4
   Jump                 L11
 
@@ -1149,58 +1147,58 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                4
-  CheckStack
-  AllocateContext      16
+  CheckStack           0
+  AllocateContext      0, 16
   PopLocal             r0
   Push                 r0
   Push                 FP[-7]
-  StoreContextVar      0
+  StoreContextVar      0, 0
   Push                 r0
   Push                 FP[-6]
-  StoreContextVar      1
+  StoreContextVar      0, 1
   Push                 r0
   Push                 FP[-5]
-  StoreContextVar      2
+  StoreContextVar      0, 2
   Push                 r0
   PushConstant         CP#0
   PushConstant         CP#2
   IndirectStaticCall   1, CP#1
-  StoreContextVar      3
+  StoreContextVar      0, 3
   Push                 r0
   PushNull
-  StoreContextVar      4
+  StoreContextVar      0, 4
   PushNull
   PopLocal             r2
   Push                 r0
   PushNull
-  StoreContextVar      5
+  StoreContextVar      0, 5
   Push                 r0
   PushNull
-  StoreContextVar      6
+  StoreContextVar      0, 6
   Push                 r0
   PushInt              0
-  StoreContextVar      7
+  StoreContextVar      0, 7
   Push                 r0
   PushNull
-  StoreContextVar      8
+  StoreContextVar      0, 8
   Push                 r0
   PushNull
-  StoreContextVar      9
+  StoreContextVar      0, 9
   Push                 r0
   PushNull
-  StoreContextVar      10
+  StoreContextVar      0, 10
   Push                 r0
   PushNull
-  StoreContextVar      11
+  StoreContextVar      0, 11
   Push                 r0
   PushNull
-  StoreContextVar      12
+  StoreContextVar      0, 12
   Push                 r0
   PushNull
-  StoreContextVar      13
+  StoreContextVar      0, 13
   Push                 r0
   PushNull
-  StoreContextVar      14
+  StoreContextVar      0, 14
   Push                 r0
   Allocate             CP#30
   StoreLocal           r3
@@ -1219,32 +1217,32 @@
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#5
-  StoreContextVar      15
+  StoreContextVar      0, 15
   Push                 r0
-  LoadContextVar       15
+  LoadContextVar       0, 15
   PushConstant         CP#40
   IndirectStaticCall   1, CP#1
   PopLocal             r2
   Push                 r0
   Push                 r0
-  LoadContextVar       15
+  LoadContextVar       0, 15
   PushConstant         CP#41
   IndirectStaticCall   1, CP#1
-  StoreContextVar      5
+  StoreContextVar      0, 5
   Push                 r0
   Push                 r0
-  LoadContextVar       15
+  LoadContextVar       0, 15
   PushConstant         CP#42
   IndirectStaticCall   1, CP#1
-  StoreContextVar      6
+  StoreContextVar      0, 6
   PushConstant         CP#43
   Push                 r0
-  LoadContextVar       15
+  LoadContextVar       0, 15
   PushConstant         CP#44
   IndirectStaticCall   2, CP#9
   Drop1
   Push                 r0
-  LoadContextVar       3
+  LoadContextVar       0, 3
   InstanceCall         1, CP#45
   ReturnTOS
 }
@@ -1302,20 +1300,20 @@
   LoadConstant         r2, CP#4
   LoadConstant         r3, CP#4
   Frame                10
-  CheckStack
+  CheckStack           0
   Push                 r0
   LoadFieldTOS         CP#5
   PopLocal             r4
   Push                 r4
-  LoadContextVar       7
+  LoadContextVar       0, 7
   StoreLocal           r5
   PushInt              0
   JumpIfNeStrict       L1
   Push                 r4
   Push                 r4
-  StoreContextVar      9
+  StoreContextVar      0, 9
 Try #0 start:
-  AllocateContext      2
+  AllocateContext      1, 2
   StoreLocal           r5
   Push                 r5
   Push                 r4
@@ -1323,42 +1321,42 @@
   PopLocal             r4
   Push                 r4
   PushInt              1
-  StoreContextVar      0
+  StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
   Push                 r4
-  StoreContextVar      10
+  StoreContextVar      0, 10
 Try #1 start:
   Push                 r4
   LoadContextParent
   Push                 r4
-  StoreContextVar      11
+  StoreContextVar      0, 11
 Try #2 start:
   Push                 r4
   LoadContextParent
   Push                 r4
-  LoadContextVar       0
-  StoreContextVar      14
+  LoadContextVar       1, 0
+  StoreContextVar      0, 14
   Push                 r4
   LoadContextParent
   PushInt              1
-  StoreContextVar      7
+  StoreContextVar      0, 7
   Push                 r4
   LoadContextParent
   Push                 r4
-  StoreContextVar      8
+  StoreContextVar      0, 8
   Push                 r4
   LoadContextParent
-  LoadContextVar       0
+  LoadContextVar       0, 0
   Push                 r4
   LoadContextParent
-  LoadContextVar       5
+  LoadContextVar       0, 5
   Push                 r4
   LoadContextParent
-  LoadContextVar       6
+  LoadContextVar       0, 6
   Push                 r4
   LoadContextParent
-  LoadContextVar       15
+  LoadContextVar       0, 15
   PushConstant         CP#8
   IndirectStaticCall   4, CP#7
   PopLocal             r13
@@ -1374,10 +1372,10 @@
   Push                 r4
   Push                 r4
   LoadContextParent
-  LoadContextVar       14
+  LoadContextVar       0, 14
   Push                 r1
   InstanceCall         2, CP#10
-  StoreContextVar      0
+  StoreContextVar      1, 0
   Jump                 L3
 Try #2 end:
 Try #2 handler:
@@ -1386,58 +1384,57 @@
   LoadFieldTOS         CP#5
   PopLocal             r4
   Push                 r4
-  LoadContextVar       11
+  LoadContextVar       0, 11
   PopLocal             r4
-  MoveSpecial          r10, exception
-  MoveSpecial          r11, stackTrace
+  MoveSpecial          exception, r10
+  MoveSpecial          stackTrace, r11
   Push                 r4
   LoadContextParent
   Push                 r10
-  StoreContextVar      12
+  StoreContextVar      0, 12
   Push                 r4
   LoadContextParent
   Push                 r11
-  StoreContextVar      13
+  StoreContextVar      0, 13
   Push                 r4
   Push                 r10
-  StoreContextVar      1
+  StoreContextVar      1, 1
   Push                 r4
-  LoadContextVar       1
+  LoadContextVar       1, 1
   PushConstant         CP#12
   InstanceCall         2, CP#13
-  AssertBoolean        0
   JumpIfFalse          L4
   Push                 r4
   LoadContextParent
   PushInt              42
-  StoreContextVar      4
+  StoreContextVar      0, 4
   Jump                 L5
 L4:
   Push                 r4
   LoadContextParent
   Push                 r4
-  LoadContextVar       0
-  StoreContextVar      14
+  LoadContextVar       1, 0
+  StoreContextVar      0, 14
   Push                 r4
   LoadContextParent
   PushInt              2
-  StoreContextVar      7
+  StoreContextVar      0, 7
   Push                 r4
   LoadContextParent
   Push                 r4
-  StoreContextVar      8
+  StoreContextVar      0, 8
   Push                 r4
   LoadContextParent
-  LoadContextVar       1
+  LoadContextVar       0, 1
   Push                 r4
   LoadContextParent
-  LoadContextVar       5
+  LoadContextVar       0, 5
   Push                 r4
   LoadContextParent
-  LoadContextVar       6
+  LoadContextVar       0, 6
   Push                 r4
   LoadContextParent
-  LoadContextVar       15
+  LoadContextVar       0, 15
   PushConstant         CP#14
   IndirectStaticCall   4, CP#7
   PopLocal             r13
@@ -1453,16 +1450,16 @@
   Push                 r4
   Push                 r4
   LoadContextParent
-  LoadContextVar       14
+  LoadContextVar       0, 14
   Push                 r1
   InstanceCall         2, CP#15
-  StoreContextVar      0
+  StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
-  LoadContextVar       12
+  LoadContextVar       0, 12
   Push                 r4
   LoadContextParent
-  LoadContextVar       13
+  LoadContextVar       0, 13
   Throw                1
 L3:
   Jump                 L7
@@ -1473,18 +1470,18 @@
   LoadFieldTOS         CP#5
   PopLocal             r4
   Push                 r4
-  LoadContextVar       10
+  LoadContextVar       0, 10
   PopLocal             r4
-  MoveSpecial          r8, exception
-  MoveSpecial          r9, stackTrace
+  MoveSpecial          exception, r8
+  MoveSpecial          stackTrace, r9
   Push                 r4
   LoadContextParent
   Push                 r8
-  StoreContextVar      12
+  StoreContextVar      0, 12
   Push                 r4
   LoadContextParent
   Push                 r9
-  StoreContextVar      13
+  StoreContextVar      0, 13
   PushConstant         CP#16
   PushConstant         CP#17
   IndirectStaticCall   1, CP#1
@@ -1492,28 +1489,28 @@
   Push                 r4
   LoadContextParent
   Push                 r4
-  LoadContextVar       0
-  StoreContextVar      14
+  LoadContextVar       1, 0
+  StoreContextVar      0, 14
   Push                 r4
   LoadContextParent
   PushInt              3
-  StoreContextVar      7
+  StoreContextVar      0, 7
   Push                 r4
   LoadContextParent
   Push                 r4
-  StoreContextVar      8
+  StoreContextVar      0, 8
   Push                 r4
   LoadContextParent
-  LoadContextVar       2
+  LoadContextVar       0, 2
   Push                 r4
   LoadContextParent
-  LoadContextVar       5
+  LoadContextVar       0, 5
   Push                 r4
   LoadContextParent
-  LoadContextVar       6
+  LoadContextVar       0, 6
   Push                 r4
   LoadContextParent
-  LoadContextVar       15
+  LoadContextVar       0, 15
   PushConstant         CP#18
   IndirectStaticCall   4, CP#7
   PopLocal             r12
@@ -1529,15 +1526,15 @@
   Push                 r4
   Push                 r4
   LoadContextParent
-  LoadContextVar       14
+  LoadContextVar       0, 14
   Push                 r1
   InstanceCall         2, CP#19
-  StoreContextVar      0
+  StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
   Push                 r4
-  LoadContextVar       0
-  StoreContextVar      4
+  LoadContextVar       1, 0
+  StoreContextVar      0, 4
   Push                 r4
   LoadContextParent
   PopLocal             r4
@@ -1547,7 +1544,7 @@
   LoadFieldTOS         CP#5
   PopLocal             r4
   Push                 r4
-  LoadContextVar       10
+  LoadContextVar       0, 10
   PopLocal             r4
   PushConstant         CP#16
   PushConstant         CP#20
@@ -1556,28 +1553,28 @@
   Push                 r4
   LoadContextParent
   Push                 r4
-  LoadContextVar       0
-  StoreContextVar      14
+  LoadContextVar       1, 0
+  StoreContextVar      0, 14
   Push                 r4
   LoadContextParent
   PushInt              4
-  StoreContextVar      7
+  StoreContextVar      0, 7
   Push                 r4
   LoadContextParent
   Push                 r4
-  StoreContextVar      8
+  StoreContextVar      0, 8
   Push                 r4
   LoadContextParent
-  LoadContextVar       2
+  LoadContextVar       0, 2
   Push                 r4
   LoadContextParent
-  LoadContextVar       5
+  LoadContextVar       0, 5
   Push                 r4
   LoadContextParent
-  LoadContextVar       6
+  LoadContextVar       0, 6
   Push                 r4
   LoadContextParent
-  LoadContextVar       15
+  LoadContextVar       0, 15
   PushConstant         CP#21
   IndirectStaticCall   4, CP#7
   PopLocal             r12
@@ -1593,15 +1590,15 @@
   Push                 r4
   Push                 r4
   LoadContextParent
-  LoadContextVar       14
+  LoadContextVar       0, 14
   Push                 r1
   InstanceCall         2, CP#22
-  StoreContextVar      0
+  StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
   Push                 r4
-  LoadContextVar       0
-  StoreContextVar      4
+  LoadContextVar       1, 0
+  StoreContextVar      0, 4
   Push                 r4
   LoadContextParent
   PopLocal             r4
@@ -1611,7 +1608,7 @@
   LoadFieldTOS         CP#5
   PopLocal             r4
   Push                 r4
-  LoadContextVar       10
+  LoadContextVar       0, 10
   PopLocal             r4
   PushConstant         CP#16
   PushConstant         CP#23
@@ -1620,28 +1617,28 @@
   Push                 r4
   LoadContextParent
   Push                 r4
-  LoadContextVar       0
-  StoreContextVar      14
+  LoadContextVar       1, 0
+  StoreContextVar      0, 14
   Push                 r4
   LoadContextParent
   PushInt              5
-  StoreContextVar      7
+  StoreContextVar      0, 7
   Push                 r4
   LoadContextParent
   Push                 r4
-  StoreContextVar      8
+  StoreContextVar      0, 8
   Push                 r4
   LoadContextParent
-  LoadContextVar       2
+  LoadContextVar       0, 2
   Push                 r4
   LoadContextParent
-  LoadContextVar       5
+  LoadContextVar       0, 5
   Push                 r4
   LoadContextParent
-  LoadContextVar       6
+  LoadContextVar       0, 6
   Push                 r4
   LoadContextParent
-  LoadContextVar       15
+  LoadContextVar       0, 15
   PushConstant         CP#24
   IndirectStaticCall   4, CP#7
   PopLocal             r12
@@ -1657,24 +1654,24 @@
   Push                 r4
   Push                 r4
   LoadContextParent
-  LoadContextVar       14
+  LoadContextVar       0, 14
   Push                 r1
   InstanceCall         2, CP#25
-  StoreContextVar      0
+  StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
   Push                 r4
-  LoadContextVar       0
-  StoreContextVar      4
+  LoadContextVar       1, 0
+  StoreContextVar      0, 4
   Push                 r4
   LoadContextParent
   PopLocal             r4
   Jump                 L9
 L9:
   Push                 r4
-  LoadContextVar       3
+  LoadContextVar       0, 3
   Push                 r4
-  LoadContextVar       4
+  LoadContextVar       0, 4
   PushConstant         CP#26
   IndirectStaticCall   2, CP#9
   Drop1
@@ -1687,16 +1684,16 @@
   LoadFieldTOS         CP#5
   PopLocal             r4
   Push                 r4
-  LoadContextVar       9
+  LoadContextVar       0, 9
   PopLocal             r4
-  MoveSpecial          r6, exception
-  MoveSpecial          r7, stackTrace
+  MoveSpecial          exception, r6
+  MoveSpecial          stackTrace, r7
   Push                 r6
   PopLocal             r8
   Push                 r7
   PopLocal             r9
   Push                 r4
-  LoadContextVar       3
+  LoadContextVar       0, 3
   Push                 r8
   Push                 r9
   InstanceCall         3, CP#28
@@ -1707,7 +1704,7 @@
   ReturnTOS
 L1:
   Push                 r4
-  LoadContextVar       8
+  LoadContextVar       0, 8
   PopLocal             r4
   Push                 r5
   PushInt              1
@@ -1783,15 +1780,15 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                4
-  CheckStack
-  AllocateContext      2
+  CheckStack           0
+  AllocateContext      0, 2
   PopLocal             r0
   Push                 r0
   Push                 FP[-5]
-  StoreContextVar      0
+  StoreContextVar      0, 0
   Push                 r0
   PushInt              3
-  StoreContextVar      1
+  StoreContextVar      0, 1
   Allocate             CP#19
   StoreLocal           r3
   Push                 r3
@@ -1857,20 +1854,20 @@
   LoadConstant         r2, CP#7
   LoadConstant         r3, CP#7
   Frame                8
-  CheckStack
+  CheckStack           0
   Push                 r0
   LoadFieldTOS         CP#1
   PopLocal             r4
   Push                 r4
-  LoadContextVar       4
+  LoadContextVar       1, 4
   StoreLocal           r5
   PushInt              0
   JumpIfNeStrict       L1
   Push                 r4
   Push                 r4
-  StoreContextVar      6
+  StoreContextVar      1, 6
 Try #0 start:
-  AllocateContext      1
+  AllocateContext      2, 1
   StoreLocal           r5
   Push                 r5
   Push                 r4
@@ -1878,38 +1875,38 @@
   PopLocal             r4
   Push                 r4
   PushInt              4
-  StoreContextVar      0
+  StoreContextVar      2, 0
   Push                 r4
   LoadContextParent
   Push                 r4
-  StoreContextVar      7
+  StoreContextVar      1, 7
 Try #1 start:
   Push                 r4
   LoadContextParent
   LoadContextParent
   PushInt              5
-  StoreContextVar      1
+  StoreContextVar      0, 1
   Push                 r4
   LoadContextParent
   PushInt              1
-  StoreContextVar      4
+  StoreContextVar      1, 4
   Push                 r4
   LoadContextParent
   Push                 r4
-  StoreContextVar      5
+  StoreContextVar      1, 5
   Push                 r4
   LoadContextParent
   LoadContextParent
-  LoadContextVar       0
+  LoadContextVar       0, 0
   Push                 r4
   LoadContextParent
-  LoadContextVar       2
+  LoadContextVar       1, 2
   Push                 r4
   LoadContextParent
-  LoadContextVar       3
+  LoadContextVar       1, 3
   Push                 r4
   LoadContextParent
-  LoadContextVar       8
+  LoadContextVar       1, 8
   PushConstant         CP#9
   IndirectStaticCall   4, CP#8
   PopLocal             r11
@@ -1924,17 +1921,17 @@
 L2:
   Push                 r4
   Push                 r1
-  StoreContextVar      0
+  StoreContextVar      2, 0
   Push                 r4
   LoadContextParent
   Push                 r4
   LoadContextParent
   LoadContextParent
-  LoadContextVar       1
+  LoadContextVar       0, 1
   Push                 r4
-  LoadContextVar       0
+  LoadContextVar       2, 0
   AddInt
-  StoreContextVar      1
+  StoreContextVar      1, 1
   Jump                 L3
 Try #1 end:
 Try #1 handler:
@@ -1943,10 +1940,10 @@
   LoadFieldTOS         CP#1
   PopLocal             r4
   Push                 r4
-  LoadContextVar       7
+  LoadContextVar       1, 7
   PopLocal             r4
-  MoveSpecial          r8, exception
-  MoveSpecial          r9, stackTrace
+  MoveSpecial          exception, r8
+  MoveSpecial          stackTrace, r9
   PushConstant         CP#11
   PushConstant         CP#12
   IndirectStaticCall   1, CP#4
@@ -1959,7 +1956,7 @@
   LoadFieldTOS         CP#1
   PopLocal             r4
   Push                 r4
-  LoadContextVar       7
+  LoadContextVar       1, 7
   PopLocal             r4
   PushConstant         CP#11
   PushConstant         CP#13
@@ -1971,9 +1968,9 @@
   Jump                 L4
 L4:
   Push                 r4
-  LoadContextVar       0
+  LoadContextVar       1, 0
   Push                 r4
-  LoadContextVar       1
+  LoadContextVar       1, 1
   PushConstant         CP#15
   IndirectStaticCall   2, CP#14
   Drop1
@@ -1986,16 +1983,16 @@
   LoadFieldTOS         CP#1
   PopLocal             r4
   Push                 r4
-  LoadContextVar       6
+  LoadContextVar       1, 6
   PopLocal             r4
-  MoveSpecial          r6, exception
-  MoveSpecial          r7, stackTrace
+  MoveSpecial          exception, r6
+  MoveSpecial          stackTrace, r7
   Push                 r6
   PopLocal             r8
   Push                 r7
   PopLocal             r9
   Push                 r4
-  LoadContextVar       0
+  LoadContextVar       1, 0
   Push                 r8
   Push                 r9
   InstanceCall         3, CP#17
@@ -2006,7 +2003,7 @@
   ReturnTOS
 L1:
   Push                 r4
-  LoadContextVar       5
+  LoadContextVar       1, 5
   PopLocal             r4
   Jump                 L6
 
@@ -2014,11 +2011,11 @@
 
 Closure CP#0 {
   EntryFixed           1, 4
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r0
-  AllocateContext      9
+  AllocateContext      1, 9
   StoreLocal           r1
   Push                 r1
   Push                 r0
@@ -2028,30 +2025,30 @@
   PushConstant         CP#3
   PushConstant         CP#5
   IndirectStaticCall   1, CP#4
-  StoreContextVar      0
+  StoreContextVar      1, 0
   Push                 r0
   PushNull
-  StoreContextVar      1
+  StoreContextVar      1, 1
   PushNull
   PopLocal             r2
   Push                 r0
   PushNull
-  StoreContextVar      2
+  StoreContextVar      1, 2
   Push                 r0
   PushNull
-  StoreContextVar      3
+  StoreContextVar      1, 3
   Push                 r0
   PushInt              0
-  StoreContextVar      4
+  StoreContextVar      1, 4
   Push                 r0
   PushNull
-  StoreContextVar      5
+  StoreContextVar      1, 5
   Push                 r0
   PushNull
-  StoreContextVar      6
+  StoreContextVar      1, 6
   Push                 r0
   PushNull
-  StoreContextVar      7
+  StoreContextVar      1, 7
   Push                 r0
   Allocate             CP#19
   StoreLocal           r3
@@ -2070,32 +2067,32 @@
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#1
-  StoreContextVar      8
+  StoreContextVar      1, 8
   Push                 r0
-  LoadContextVar       8
+  LoadContextVar       1, 8
   PushConstant         CP#29
   IndirectStaticCall   1, CP#4
   PopLocal             r2
   Push                 r0
   Push                 r0
-  LoadContextVar       8
+  LoadContextVar       1, 8
   PushConstant         CP#30
   IndirectStaticCall   1, CP#4
-  StoreContextVar      2
+  StoreContextVar      1, 2
   Push                 r0
   Push                 r0
-  LoadContextVar       8
+  LoadContextVar       1, 8
   PushConstant         CP#31
   IndirectStaticCall   1, CP#4
-  StoreContextVar      3
+  StoreContextVar      1, 3
   PushConstant         CP#32
   Push                 r0
-  LoadContextVar       8
+  LoadContextVar       1, 8
   PushConstant         CP#33
   IndirectStaticCall   2, CP#14
   Drop1
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       1, 0
   InstanceCall         1, CP#34
   ReturnTOS
 
@@ -2145,37 +2142,37 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                4
-  CheckStack
-  AllocateContext      9
+  CheckStack           0
+  AllocateContext      0, 9
   PopLocal             r0
   Push                 r0
   Push                 FP[-5]
-  StoreContextVar      0
+  StoreContextVar      0, 0
   Push                 r0
   PushConstant         CP#0
   PushConstant         CP#2
   IndirectStaticCall   1, CP#1
-  StoreContextVar      1
+  StoreContextVar      0, 1
   Push                 r0
   PushNull
-  StoreContextVar      2
+  StoreContextVar      0, 2
   PushNull
   PopLocal             r2
   Push                 r0
   PushNull
-  StoreContextVar      3
+  StoreContextVar      0, 3
   Push                 r0
   PushNull
-  StoreContextVar      4
+  StoreContextVar      0, 4
   Push                 r0
   PushInt              0
-  StoreContextVar      5
+  StoreContextVar      0, 5
   Push                 r0
   PushNull
-  StoreContextVar      6
+  StoreContextVar      0, 6
   Push                 r0
   PushNull
-  StoreContextVar      7
+  StoreContextVar      0, 7
   Push                 r0
   Allocate             CP#17
   StoreLocal           r3
@@ -2194,32 +2191,32 @@
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#5
-  StoreContextVar      8
+  StoreContextVar      0, 8
   Push                 r0
-  LoadContextVar       8
+  LoadContextVar       0, 8
   PushConstant         CP#27
   IndirectStaticCall   1, CP#1
   PopLocal             r2
   Push                 r0
   Push                 r0
-  LoadContextVar       8
+  LoadContextVar       0, 8
   PushConstant         CP#28
   IndirectStaticCall   1, CP#1
-  StoreContextVar      3
+  StoreContextVar      0, 3
   Push                 r0
   Push                 r0
-  LoadContextVar       8
+  LoadContextVar       0, 8
   PushConstant         CP#29
   IndirectStaticCall   1, CP#1
-  StoreContextVar      4
+  StoreContextVar      0, 4
   PushConstant         CP#30
   Push                 r0
-  LoadContextVar       8
+  LoadContextVar       0, 8
   PushConstant         CP#31
   IndirectStaticCall   2, CP#9
   Drop1
   Push                 r0
-  LoadContextVar       1
+  LoadContextVar       0, 1
   InstanceCall         1, CP#32
   ReturnTOS
 }
@@ -2264,34 +2261,34 @@
   LoadConstant         r2, CP#4
   LoadConstant         r3, CP#4
   Frame                6
-  CheckStack
+  CheckStack           0
   Push                 r0
   LoadFieldTOS         CP#5
   PopLocal             r4
   Push                 r4
-  LoadContextVar       5
+  LoadContextVar       0, 5
   StoreLocal           r5
   PushInt              0
   JumpIfNeStrict       L1
   Push                 r4
   Push                 r4
-  StoreContextVar      7
+  StoreContextVar      0, 7
 Try #0 start:
   JumpIfNoAsserts      L2
   Push                 r4
   PushInt              1
-  StoreContextVar      5
+  StoreContextVar      0, 5
   Push                 r4
   Push                 r4
-  StoreContextVar      6
+  StoreContextVar      0, 6
   Push                 r4
-  LoadContextVar       0
+  LoadContextVar       0, 0
   Push                 r4
-  LoadContextVar       3
+  LoadContextVar       0, 3
   Push                 r4
-  LoadContextVar       4
+  LoadContextVar       0, 4
   Push                 r4
-  LoadContextVar       8
+  LoadContextVar       0, 8
   PushConstant         CP#8
   IndirectStaticCall   4, CP#7
   PopLocal             r8
@@ -2319,13 +2316,13 @@
 L2:
   Push                 r4
   PushInt              7
-  StoreContextVar      2
+  StoreContextVar      0, 2
   Jump                 L4
 L4:
   Push                 r4
-  LoadContextVar       1
+  LoadContextVar       0, 1
   Push                 r4
-  LoadContextVar       2
+  LoadContextVar       0, 2
   PushConstant         CP#13
   IndirectStaticCall   2, CP#9
   Drop1
@@ -2338,16 +2335,16 @@
   LoadFieldTOS         CP#5
   PopLocal             r4
   Push                 r4
-  LoadContextVar       7
+  LoadContextVar       0, 7
   PopLocal             r4
-  MoveSpecial          r6, exception
-  MoveSpecial          r7, stackTrace
+  MoveSpecial          exception, r6
+  MoveSpecial          stackTrace, r7
   Push                 r6
   PopLocal             r8
   Push                 r7
   PopLocal             r9
   Push                 r4
-  LoadContextVar       1
+  LoadContextVar       0, 1
   Push                 r8
   Push                 r9
   InstanceCall         3, CP#15
@@ -2358,7 +2355,7 @@
   ReturnTOS
 L1:
   Push                 r4
-  LoadContextVar       6
+  LoadContextVar       0, 6
   PopLocal             r4
   Jump                 L6
 
@@ -2398,7 +2395,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   ReturnTOS
 }
diff --git a/pkg/vm/testcases/bytecode/bootstrapping.dart b/pkg/vm/testcases/bytecode/bootstrapping.dart
index 8f79be8..3f8c850 100644
--- a/pkg/vm/testcases/bytecode/bootstrapping.dart
+++ b/pkg/vm/testcases/bytecode/bootstrapping.dart
@@ -137,6 +137,19 @@
   VMLibraryHooks.platformScript = _scriptUri;
 }
 
+class Stdin {}
+
+Stdin _stdin;
+
+class _StdIOUtils {
+  static Stdin _getStdioInputStream(int fd) => null;
+}
+
+Stdin get stdin {
+  _stdin ??= _StdIOUtils._getStdioInputStream(_stdinFD);
+  return _stdin;
+}
+
 // -----------------------------------------------------------------
 
 main() {}
diff --git a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
index c47aadf..774c558 100644
--- a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
+++ b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
@@ -9,7 +9,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -30,7 +30,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -48,7 +48,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-6]
   Push                 FP[-5]
   NativeCall           CP#0
@@ -62,7 +62,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   NativeCall           CP#0
   ReturnTOS
@@ -75,7 +75,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   NativeCall           CP#0
   ReturnTOS
 }
@@ -87,7 +87,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                2
-  CheckStack
+  CheckStack           0
   Allocate             CP#0
   StoreLocal           r1
   Push                 r1
@@ -115,11 +115,10 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                2
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   PushStatic           CP#0
   EqualsNull
-  AssertBoolean        0
   JumpIfFalse          L1
   Allocate             CP#1
   StoreLocal           r1
@@ -156,7 +155,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#1
   IndirectStaticCall   0, CP#0
   PushConstant         CP#3
@@ -176,7 +175,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -194,7 +193,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -212,7 +211,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#1
   IndirectStaticCall   0, CP#0
   ReturnTOS
@@ -226,7 +225,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#1
   IndirectStaticCall   0, CP#0
   ReturnTOS
@@ -253,7 +252,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -270,8 +269,8 @@
     ;
 [@vm.bytecode=
 Bytecode (version: stable) {
-  Entry                2
-  CheckStack
+  Entry                1
+  CheckStack           0
   Push                 FP[-5]
   StoreStaticTOS       CP#0
   PushNull
@@ -290,16 +289,14 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   PushStatic           CP#0
   EqualsNull
-  AssertBoolean        0
   JumpIfFalse          L1
   PushConstant         CP#1
   PushStatic           CP#1
   EqualsNull
-  AssertBoolean        0
   BooleanNegateTOS
   PopLocal             r0
   Jump                 L2
@@ -308,7 +305,6 @@
   PopLocal             r0
 L2:
   Push                 r0
-  AssertBoolean        0
   JumpIfFalse          L3
   PushConstant         CP#1
   PushStatic           CP#1
@@ -332,14 +328,66 @@
     return self::VMLibraryHooks::_cachedScript;
   }
 }
+class Stdin extends core::Object {
+[@vm.bytecode=
+Bytecode (version: stable) {
+  Entry                0
+  CheckStack           0
+  Push                 FP[-5]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushNull
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target 'dart.core::Object::', arg-desc CP#0
+}
+]  synthetic constructor •() → self::Stdin
+    : super core::Object::•()
+    ;
+}
+class _StdIOUtils extends core::Object {
+[@vm.bytecode=
+Bytecode (version: stable) {
+  Entry                0
+  CheckStack           0
+  Push                 FP[-5]
+  PushConstant         CP#1
+  IndirectStaticCall   1, CP#0
+  Drop1
+  PushNull
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [1] = StaticICData target 'dart.core::Object::', arg-desc CP#0
+}
+]  synthetic constructor •() → self::_StdIOUtils
+    : super core::Object::•()
+    ;
+[@vm.bytecode=
+Bytecode (version: stable) {
+  Entry                0
+  CheckStack           0
+  PushNull
+  ReturnTOS
+}
+ConstantPool {
+}
+]  static method _getStdioInputStream(core::int fd) → self::Stdin
+    return null;
+}
 static field core::int _stdinFD = 0;
 static field core::int _stdoutFD = 1;
 static field core::int _stderrFD = 2;
 static field core::String _rawScript;
+static field self::Stdin _stdin;
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   NativeCall           CP#0
   ReturnTOS
@@ -352,7 +400,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   InstanceCall         1, CP#1
   PushConstant         CP#2
@@ -372,7 +420,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   ReturnTOS
 }
@@ -384,7 +432,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   StoreStaticTOS       CP#0
   PushNull
@@ -398,8 +446,8 @@
 }
 [@vm.bytecode=
 Bytecode (version: stable) {
-  Entry                3
-  CheckStack
+  Entry                1
+  CheckStack           0
   Push                 FP[-7]
   StoreStaticTOS       CP#0
   Push                 FP[-6]
@@ -422,7 +470,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                2
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   PushStatic           CP#0
   PushConstant         CP#1
@@ -441,7 +489,6 @@
   PopLocal             r1
 L2:
   Push                 r1
-  AssertBoolean        0
   JumpIfTrue           L3
   PushConstant         CP#0
   PushStatic           CP#0
@@ -455,7 +502,6 @@
   PopLocal             r0
 L4:
   Push                 r0
-  AssertBoolean        0
   JumpIfFalse          L5
   PushConstant         CP#0
   PushStatic           CP#0
@@ -500,7 +546,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   PushConstant         CP#2
   IndirectStaticCall   1, CP#1
@@ -518,8 +564,45 @@
 }
 [@vm.bytecode=
 Bytecode (version: stable) {
+  Entry                2
+  CheckStack           0
+  PushConstant         CP#0
+  PushStatic           CP#0
+  EqualsNull
+  JumpIfFalse          L1
+  PushConstant         CP#1
+  PushStatic           CP#1
+  PushConstant         CP#3
+  IndirectStaticCall   1, CP#2
+  StoreLocal           r1
+  Push                 r1
+  StoreStaticTOS       CP#0
+  PopLocal             r0
+  Jump                 L2
+L1:
+  PushNull
+  PopLocal             r0
+L2:
+  Push                 r0
+  Drop1
+  PushConstant         CP#0
+  PushStatic           CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = StaticField #lib::_stdin
+  [1] = StaticField #lib::_stdinFD
+  [2] = ArgDesc num-args 1, num-type-args 0, names []
+  [3] = StaticICData target '#lib::_StdIOUtils::_getStdioInputStream', arg-desc CP#2
+}
+]static get stdin() → self::Stdin {
+  self::_stdin.{core::Object::==}(null) ?{self::Stdin} self::_stdin = self::_StdIOUtils::_getStdioInputStream(self::_stdinFD) : null;
+  return self::_stdin;
+}
+[@vm.bytecode=
+Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   ReturnTOS
 }
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index d73647e..2add8c9 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -7,7 +7,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -27,7 +27,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -47,7 +47,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -67,7 +67,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -87,7 +87,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -107,7 +107,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -127,7 +127,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -147,7 +147,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -167,7 +167,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -185,13 +185,13 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                5
-  CheckStack
-  CheckFunctionTypeArgs 2, 0
-  AllocateContext      1
+  CheckStack           0
+  CheckFunctionTypeArgs 2, r0
+  AllocateContext      0, 1
   PopLocal             r1
   Push                 r1
   Push                 FP[-5]
-  StoreContextVar      0
+  StoreContextVar      0, 0
   Allocate             CP#31
   StoreLocal           r4
   Push                 r4
@@ -274,7 +274,7 @@
 }
 Closure CP#12 {
   EntryFixed           1, 4
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r1
@@ -290,7 +290,7 @@
   Push                 r3
   PushInt              0
   Push                 r1
-  LoadContextVar       0
+  LoadContextVar       0, 0
   LoadTypeArgumentsField CP#15
   PushNull
   InstantiateType      CP#14
@@ -298,7 +298,7 @@
   Push                 r3
   PushInt              1
   Push                 r1
-  LoadContextVar       0
+  LoadContextVar       0, 0
   LoadTypeArgumentsField CP#15
   PushNull
   InstantiateType      CP#16
@@ -345,7 +345,7 @@
   IndirectStaticCall   1, CP#25
   Drop1
   Push                 r1
-  LoadContextVar       0
+  LoadContextVar       0, 0
   LoadTypeArgumentsField CP#15
   Push                 r0
   InstantiateTypeArgumentsTOS 0, CP#27
@@ -359,7 +359,7 @@
 
 Closure CP#10 {
   EntryFixed           1, 5
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r1
@@ -368,10 +368,10 @@
   StoreLocal           r0
   PushConstant         CP#5
   JumpIfEqStrict       L1
-  CheckFunctionTypeArgs 0, 2
+  CheckFunctionTypeArgs 0, r2
   Jump                 L2
 L1:
-  CheckFunctionTypeArgs 2, 0
+  CheckFunctionTypeArgs 2, r0
 L2:
   Push                 r0
   Push                 FP[-5]
@@ -385,7 +385,7 @@
   StoreLocal           r4
   Push                 r4
   Push                 r1
-  LoadContextVar       0
+  LoadContextVar       0, 0
   LoadTypeArgumentsField CP#15
   StoreFieldTOS        CP#32
   Push                 r4
@@ -411,7 +411,7 @@
 
 Closure CP#0 {
   EntryFixed           1, 5
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r1
@@ -420,10 +420,10 @@
   StoreLocal           r0
   PushConstant         CP#5
   JumpIfEqStrict       L1
-  CheckFunctionTypeArgs 0, 2
+  CheckFunctionTypeArgs 0, r2
   Jump                 L2
 L1:
-  CheckFunctionTypeArgs 2, 0
+  CheckFunctionTypeArgs 2, r0
 L2:
   Push                 r0
   Push                 FP[-5]
@@ -437,7 +437,7 @@
   StoreLocal           r4
   Push                 r4
   Push                 r1
-  LoadContextVar       0
+  LoadContextVar       0, 0
   LoadTypeArgumentsField CP#15
   StoreFieldTOS        CP#32
   Push                 r4
@@ -486,7 +486,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -505,20 +505,20 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                5
-  CheckStack
-  AllocateContext      4
+  CheckStack           0
+  AllocateContext      0, 4
   PopLocal             r0
   Push                 r0
   Push                 FP[-5]
-  StoreContextVar      0
+  StoreContextVar      0, 0
   Push                 r0
   PushInt              1
-  StoreContextVar      1
+  StoreContextVar      0, 1
   PushInt              2
   PopLocal             r2
   Push                 r0
   PushInt              3
-  StoreContextVar      2
+  StoreContextVar      0, 2
   Allocate             CP#10
   StoreLocal           r4
   Push                 r4
@@ -550,18 +550,18 @@
   IndirectStaticCall   1, CP#7
   Drop1
   Push                 r0
-  LoadContextVar       2
+  LoadContextVar       0, 2
   PushConstant         CP#27
   IndirectStaticCall   1, CP#7
   Drop1
   Push                 r0
-  LoadContextVar       1
+  LoadContextVar       0, 1
   PushConstant         CP#28
   IndirectStaticCall   1, CP#7
   Drop1
   Push                 r0
   PushInt              42
-  StoreContextVar      3
+  StoreContextVar      0, 3
   Allocate             CP#10
   StoreLocal           r3
   Push                 r3
@@ -623,7 +623,7 @@
 }
 Closure CP#6 {
   EntryFixed           1, 3
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r0
@@ -631,19 +631,19 @@
   LoadContextParent
   Push                 r0
   LoadContextParent
-  LoadContextVar       1
+  LoadContextVar       0, 1
   PushInt              2
   AddInt
-  StoreContextVar      2
+  StoreContextVar      0, 2
   Push                 r0
   Push                 r0
   LoadContextParent
-  LoadContextVar       0
+  LoadContextVar       0, 0
   InstanceCall         1, CP#8
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       1, 0
   AddInt
-  StoreContextVar      1
+  StoreContextVar      1, 1
   PushNull
   ReturnTOS
 
@@ -651,11 +651,11 @@
 
 Closure CP#0 {
   EntryFixed           2, 4
-  CheckStack
+  CheckStack           0
   Push                 FP[-6]
   LoadFieldTOS         CP#1
   PopLocal             r0
-  AllocateContext      2
+  AllocateContext      1, 2
   StoreLocal           r1
   Push                 r1
   Push                 r0
@@ -663,7 +663,7 @@
   PopLocal             r0
   Push                 r0
   Push                 FP[-5]
-  StoreContextVar      0
+  StoreContextVar      1, 0
   Push                 FP[-5]
   PushConstant         CP#3
   PushNull
@@ -674,20 +674,19 @@
   Push                 r0
   LoadContextParent
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       1, 0
   PushInt              1
   AddInt
-  StoreContextVar      1
+  StoreContextVar      0, 1
   Push                 r0
   LoadContextParent
-  LoadContextVar       1
+  LoadContextVar       0, 1
   PushInt              5
   CompareIntGt
-  AssertBoolean        0
   JumpIfFalse          L1
   Push                 r0
   PushInt              4
-  StoreContextVar      1
+  StoreContextVar      1, 1
   Allocate             CP#10
   StoreLocal           r2
   Push                 r2
@@ -710,7 +709,7 @@
   InstanceCall         1, CP#20
   Drop1
   Push                 r0
-  LoadContextVar       1
+  LoadContextVar       1, 1
   PushConstant         CP#21
   IndirectStaticCall   1, CP#7
   Drop1
@@ -722,14 +721,14 @@
 
 Closure CP#29 {
   EntryFixed           1, 3
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r0
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   Push                 r0
-  LoadContextVar       3
+  LoadContextVar       0, 3
   InstanceCall         2, CP#30
   Drop1
   PushNull
@@ -774,7 +773,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -792,12 +791,12 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                5
-  CheckStack
-  AllocateContext      1
+  CheckStack           0
+  AllocateContext      0, 1
   PopLocal             r0
   Push                 r0
   PushInt              0
-  StoreContextVar      0
+  StoreContextVar      0, 0
   PushConstant         CP#0
   StoreLocal           r3
   Push                 r3
@@ -816,7 +815,7 @@
   PushConstant         CP#3
   IndirectStaticCall   2, CP#1
   PopLocal             r4
-  AllocateContext      1
+  AllocateContext      1, 1
   StoreLocal           r1
   Push                 r1
   Push                 r0
@@ -824,14 +823,13 @@
   PopLocal             r0
   Push                 r0
   PushInt              0
-  StoreContextVar      0
+  StoreContextVar      1, 0
 L2:
-  CheckStack
+  CheckStack           1
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       1, 0
   PushInt              10
   CompareIntLt
-  AssertBoolean        0
   JumpIfFalse          L1
   Push                 r2
   Allocate             CP#8
@@ -874,15 +872,15 @@
   InstanceCall         2, CP#24
   Drop1
   Push                 r0
-  CloneContext
+  CloneContext         1, 1
   PopLocal             r0
   Push                 r0
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       1, 0
   PushInt              1
   AddInt
   StoreLocal           r3
-  StoreContextVar      0
+  StoreContextVar      1, 0
   Push                 r3
   Drop1
   Jump                 L2
@@ -925,15 +923,15 @@
 }
 Closure CP#4 {
   EntryFixed           1, 2
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#5
   PopLocal             r0
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       1, 0
   Push                 r0
   LoadContextParent
-  LoadContextVar       0
+  LoadContextVar       0, 0
   AddInt
   ReturnTOS
 
@@ -941,7 +939,7 @@
 
 Closure CP#19 {
   EntryFixed           2, 3
-  CheckStack
+  CheckStack           0
   Push                 FP[-6]
   LoadFieldTOS         CP#5
   PopLocal             r0
@@ -956,9 +954,9 @@
   Push                 FP[-5]
   Push                 r0
   LoadContextParent
-  LoadContextVar       0
+  LoadContextVar       0, 0
   AddInt
-  StoreContextVar      0
+  StoreContextVar      1, 0
   PushNull
   ReturnTOS
 
@@ -977,21 +975,21 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                5
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   InstanceCall         1, CP#1
   PopLocal             r2
 L2:
-  CheckStack
+  CheckStack           1
   Push                 r2
   InstanceCall         1, CP#2
   JumpIfFalse          L1
-  AllocateContext      1
+  AllocateContext      0, 1
   PopLocal             r0
   Push                 r0
   Push                 r2
   InstanceCall         1, CP#3
-  StoreContextVar      0
+  StoreContextVar      0, 0
   Allocate             CP#8
   StoreLocal           r4
   Push                 r4
@@ -1014,7 +1012,7 @@
   InstanceCall         1, CP#18
   Drop1
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   PushConstant         CP#19
   IndirectStaticCall   1, CP#0
   Drop1
@@ -1050,16 +1048,16 @@
 }
 Closure CP#4 {
   EntryFixed           1, 3
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#5
   PopLocal             r0
   Push                 r0
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   PushInt              1
   AddInt
-  StoreContextVar      0
+  StoreContextVar      0, 0
   PushNull
   ReturnTOS
 
@@ -1078,7 +1076,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -1096,12 +1094,12 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                3
-  CheckStack
-  AllocateContext      1
+  CheckStack           0
+  AllocateContext      0, 1
   PopLocal             r0
   Push                 r0
   Push                 FP[-5]
-  StoreContextVar      0
+  StoreContextVar      0, 0
   Push                 FP[-5]
   PushConstant         CP#0
   Push                 FP[-6]
@@ -1152,12 +1150,12 @@
 }
 Closure CP#4 {
   EntryFixed           1, 2
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#5
   PopLocal             r0
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   ReturnTOS
 
 }
@@ -1168,12 +1166,12 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                4
-  CheckStack
-  AllocateContext      1
+  CheckStack           0
+  AllocateContext      0, 1
   PopLocal             r0
   Push                 r0
   PushInt              5
-  StoreContextVar      0
+  StoreContextVar      0, 0
   Allocate             CP#7
   StoreLocal           r3
   Push                 r3
@@ -1197,7 +1195,7 @@
   InstanceCall         2, CP#18
   Drop1
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   ReturnTOS
 }
 ConstantPool {
@@ -1223,7 +1221,7 @@
 }
 Closure CP#0 {
   EntryFixed           2, 3
-  CheckStack
+  CheckStack           0
   Push                 FP[-6]
   LoadFieldTOS         CP#1
   PopLocal             r0
@@ -1236,10 +1234,10 @@
   Drop1
   Push                 r0
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   Push                 FP[-5]
   AddInt
-  StoreContextVar      0
+  StoreContextVar      0, 0
   PushNull
   ReturnTOS
 
@@ -1255,8 +1253,8 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                2
-  CheckStack
-  CheckFunctionTypeArgs 8, 0
+  CheckStack           0
+  CheckFunctionTypeArgs 8, r0
   PushConstant         CP#0
   StoreLocal           r1
   Push                 r1
@@ -1340,7 +1338,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   PushConstant         CP#2
   PushConstant         CP#1
@@ -1400,7 +1398,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                7
-  CheckStack
+  CheckStack           0
   Allocate             CP#14
   StoreLocal           r3
   Push                 r3
@@ -1477,7 +1475,7 @@
 }
 Closure CP#0 {
   EntryFixed           2, 3
-  CheckStack
+  CheckStack           0
   Push                 FP[-6]
   LoadFieldTOS         CP#1
   PopLocal             r1
@@ -1486,10 +1484,10 @@
   StoreLocal           r0
   PushConstant         CP#5
   JumpIfEqStrict       L1
-  CheckFunctionTypeArgs 0, 2
+  CheckFunctionTypeArgs 0, r2
   Jump                 L2
 L1:
-  CheckFunctionTypeArgs 1, 0
+  CheckFunctionTypeArgs 1, r0
 L2:
   Push                 r0
   Push                 FP[-6]
@@ -1518,7 +1516,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   ReturnTOS
 }
diff --git a/pkg/vm/testcases/bytecode/deferred_lib.dart.expect b/pkg/vm/testcases/bytecode/deferred_lib.dart.expect
index 67139cb..9004858 100644
--- a/pkg/vm/testcases/bytecode/deferred_lib.dart.expect
+++ b/pkg/vm/testcases/bytecode/deferred_lib.dart.expect
@@ -5,7 +5,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   PushNull
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -25,7 +25,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -40,7 +40,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   ReturnTOS
 }
diff --git a/pkg/vm/testcases/bytecode/field_initializers.dart.expect b/pkg/vm/testcases/bytecode/field_initializers.dart.expect
index d28770d..a375935 100644
--- a/pkg/vm/testcases/bytecode/field_initializers.dart.expect
+++ b/pkg/vm/testcases/bytecode/field_initializers.dart.expect
@@ -11,7 +11,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-6]
   PushInt              42
   StoreFieldTOS        CP#0
@@ -48,7 +48,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-7]
   PushInt              42
   StoreFieldTOS        CP#0
@@ -87,7 +87,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushInt              45
   PushConstant         CP#1
@@ -106,7 +106,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-8]
   Push                 FP[-7]
   Push                 FP[-6]
@@ -133,7 +133,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushInt              46
   StoreFieldTOS        CP#0
@@ -157,7 +157,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-7]
   PushInt              46
   StoreFieldTOS        CP#0
@@ -187,7 +187,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   ReturnTOS
 }
diff --git a/pkg/vm/testcases/bytecode/hello.dart.expect b/pkg/vm/testcases/bytecode/hello.dart.expect
index db4aaaf..1bc42dd 100644
--- a/pkg/vm/testcases/bytecode/hello.dart.expect
+++ b/pkg/vm/testcases/bytecode/hello.dart.expect
@@ -5,7 +5,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   PushConstant         CP#2
   IndirectStaticCall   1, CP#1
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
index 1cd0231..8f84e7e 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart.expect
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
@@ -9,7 +9,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -69,7 +69,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-6]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -89,7 +89,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -135,7 +135,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-6]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -176,7 +176,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -194,7 +194,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadTypeArgumentsField CP#0
   PushConstant         CP#2
@@ -213,7 +213,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -231,7 +231,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadTypeArgumentsField CP#0
   PushConstant         CP#2
@@ -250,7 +250,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -268,7 +268,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushNull
   InstantiateTypeArgumentsTOS 0, CP#1
@@ -294,7 +294,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -314,7 +314,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-6]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -335,7 +335,7 @@
   LoadConstant         r1, CP#0
   LoadConstant         r1, CP#1
   Frame                1
-  CheckStack
+  CheckStack           0
   Allocate             CP#2
   StoreLocal           r2
   Push                 r2
@@ -359,7 +359,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   NativeCall           CP#0
   ReturnTOS
@@ -374,7 +374,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#0
   AllocateT
@@ -397,7 +397,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -416,7 +416,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Allocate             CP#0
   StoreLocal           r0
   Push                 r0
@@ -437,7 +437,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   PushConstant         CP#1
   PushConstant         CP#0
   AllocateT
@@ -478,8 +478,8 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                2
-  CheckStack
-  CheckFunctionTypeArgs 1, 0
+  CheckStack           0
+  CheckFunctionTypeArgs 1, r0
   PushNull
   Push                 r0
   InstantiateTypeArgumentsTOS 0, CP#1
@@ -506,7 +506,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   PushConstant         CP#2
   IndirectStaticCall   1, CP#1
@@ -525,7 +525,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -551,7 +551,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   PushInt              0
   PushConstant         CP#2
@@ -568,7 +568,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   Push                 FP[-5]
   PushConstant         CP#2
@@ -585,7 +585,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#1
   IndirectStaticCall   0, CP#0
   Drop1
diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect
index e5ace82..f3fe8f4 100644
--- a/pkg/vm/testcases/bytecode/literals.dart.expect
+++ b/pkg/vm/testcases/bytecode/literals.dart.expect
@@ -9,7 +9,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#13
   ReturnTOS
 }
@@ -33,7 +33,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#3
   ReturnTOS
 }
@@ -47,7 +47,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#3
   ReturnTOS
 }
@@ -61,7 +61,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#3
   ReturnTOS
 }
@@ -75,7 +75,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#3
   ReturnTOS
 }
@@ -89,7 +89,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-7]
   Push                 FP[-6]
   StoreFieldTOS        CP#0
@@ -117,7 +117,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -135,7 +135,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-6]
   Push                 FP[-5]
   StoreFieldTOS        CP#0
@@ -161,7 +161,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-8]
   Push                 FP[-7]
   Push                 FP[-6]
@@ -195,7 +195,7 @@
   EntryOptional        2, 1, 0
   LoadConstant         r2, CP#0
   Frame                0
-  CheckStack
+  CheckStack           0
   Push                 r0
   Push                 r1
   StoreFieldTOS        CP#1
@@ -226,7 +226,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -246,7 +246,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -265,7 +265,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#3
   ReturnTOS
 }
@@ -280,7 +280,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushInt              6
   ReturnTOS
 }
@@ -290,7 +290,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#3
   ReturnTOS
 }
@@ -304,7 +304,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#3
   ReturnTOS
 }
@@ -319,7 +319,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#3
   PushConstant         CP#5
   IndirectStaticCall   1, CP#4
@@ -372,7 +372,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushInt              42
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -446,7 +446,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   StoreLocal           r0
   Push                 r0
@@ -517,8 +517,8 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                2
-  CheckStack
-  CheckFunctionTypeArgs 1, 0
+  CheckStack           0
+  CheckFunctionTypeArgs 1, r0
   PushConstant         CP#0
   PushConstant         CP#1
   PushInt              4
@@ -633,7 +633,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   PushConstant         CP#2
   IndirectStaticCall   1, CP#1
@@ -659,8 +659,8 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
-  CheckFunctionTypeArgs 1, 0
+  CheckStack           0
+  CheckFunctionTypeArgs 1, r0
   PushConstant         CP#0
   PushConstant         CP#2
   IndirectStaticCall   1, CP#1
@@ -688,7 +688,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#1
   ReturnTOS
 }
@@ -701,7 +701,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   ReturnTOS
 }
@@ -713,7 +713,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   PushStatic           CP#0
   ReturnTOS
@@ -726,7 +726,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   ReturnTOS
 }
diff --git a/pkg/vm/testcases/bytecode/loops.dart.expect b/pkg/vm/testcases/bytecode/loops.dart.expect
index 3c0804e..77b4601 100644
--- a/pkg/vm/testcases/bytecode/loops.dart.expect
+++ b/pkg/vm/testcases/bytecode/loops.dart.expect
@@ -5,18 +5,17 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                2
-  CheckStack
+  CheckStack           0
   PushInt              0
   PopLocal             r0
   PushInt              0
   PopLocal             r1
 L2:
-  CheckStack
+  CheckStack           1
   Push                 r1
   Push                 FP[-5]
   InstanceCall         1, CP#1
   CompareIntLt
-  AssertBoolean        0
   JumpIfFalse          L1
   Push                 r0
   Push                 FP[-5]
@@ -50,23 +49,21 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                2
-  CheckStack
+  CheckStack           0
   PushInt              0
   PopLocal             r0
   PushInt              0
   PopLocal             r1
 L3:
-  CheckStack
+  CheckStack           1
   Push                 r1
   PushInt              0
   CompareIntGe
-  AssertBoolean        0
   JumpIfFalse          L1
   Push                 r1
   Push                 FP[-5]
   InstanceCall         1, CP#1
   CompareIntGe
-  AssertBoolean        0
   JumpIfFalse          L2
   Jump                 L1
 L2:
@@ -106,24 +103,22 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                2
-  CheckStack
+  CheckStack           0
   PushInt              0
   PopLocal             r0
   PushInt              100
   NegateInt
   PopLocal             r1
 L4:
-  CheckStack
+  CheckStack           1
   Push                 r1
   Push                 FP[-5]
   InstanceCall         1, CP#1
   CompareIntLt
-  AssertBoolean        0
   JumpIfFalse          L1
   Push                 r1
   PushInt              0
   CompareIntLt
-  AssertBoolean        0
   JumpIfFalse          L2
   Jump                 L3
 L2:
@@ -165,18 +160,17 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                4
-  CheckStack
+  CheckStack           0
   PushInt              0
   PopLocal             r0
   PushInt              0
   PopLocal             r1
 L2:
-  CheckStack
+  CheckStack           1
   Push                 r1
   Push                 FP[-5]
   InstanceCall         1, CP#1
   CompareIntLt
-  AssertBoolean        0
   JumpIfFalse          L1
   Push                 r0
   Push                 FP[-5]
@@ -213,13 +207,13 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                2
-  CheckStack
+  CheckStack           0
   PushInt              0
   PopLocal             r0
   PushInt              0
   PopLocal             r1
 L1:
-  CheckStack
+  CheckStack           1
   Push                 r0
   Push                 FP[-5]
   Push                 r1
@@ -234,7 +228,6 @@
   Push                 FP[-5]
   InstanceCall         1, CP#3
   CompareIntLt
-  AssertBoolean        0
   JumpIfTrue           L1
   Push                 r0
   ReturnTOS
@@ -258,14 +251,14 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                3
-  CheckStack
+  CheckStack           0
   PushInt              0
   PopLocal             r0
   Push                 FP[-5]
   InstanceCall         1, CP#1
   PopLocal             r1
 L2:
-  CheckStack
+  CheckStack           1
   Push                 r1
   InstanceCall         1, CP#2
   JumpIfFalse          L1
@@ -297,7 +290,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                4
-  CheckStack
+  CheckStack           0
   PushInt              0
   PopLocal             r0
   PushInt              42
@@ -306,7 +299,7 @@
   InstanceCall         1, CP#1
   PopLocal             r2
 L2:
-  CheckStack
+  CheckStack           1
   Push                 r2
   InstanceCall         1, CP#2
   JumpIfFalse          L1
@@ -342,7 +335,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   ReturnTOS
 }
diff --git a/pkg/vm/testcases/bytecode/optional_params.dart.expect b/pkg/vm/testcases/bytecode/optional_params.dart.expect
index bd33fe5..8fa1589 100644
--- a/pkg/vm/testcases/bytecode/optional_params.dart.expect
+++ b/pkg/vm/testcases/bytecode/optional_params.dart.expect
@@ -8,7 +8,7 @@
   LoadConstant         r1, CP#0
   LoadConstant         r2, CP#1
   Frame                1
-  CheckStack
+  CheckStack           0
   PushNull
   PushInt              2
   CreateArrayTOS
@@ -92,7 +92,7 @@
   LoadConstant         r4, CP#5
   LoadConstant         r4, CP#6
   Frame                1
-  CheckStack
+  CheckStack           0
   PushNull
   PushInt              2
   CreateArrayTOS
@@ -221,8 +221,8 @@
   LoadConstant         r3, CP#2
   LoadConstant         r3, CP#3
   Frame                1
-  CheckStack
-  CheckFunctionTypeArgs 2, 4
+  CheckStack           0
+  CheckFunctionTypeArgs 2, r4
   PushNull
   Push                 r4
   InstantiateType      CP#4
@@ -259,7 +259,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   PushConstant         CP#1
   PushConstant         CP#3
diff --git a/pkg/vm/testcases/bytecode/super_calls.dart.expect b/pkg/vm/testcases/bytecode/super_calls.dart.expect
index f466a6d..7966de3 100644
--- a/pkg/vm/testcases/bytecode/super_calls.dart.expect
+++ b/pkg/vm/testcases/bytecode/super_calls.dart.expect
@@ -6,7 +6,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -24,8 +24,8 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
-  CheckFunctionTypeArgs 1, 0
+  CheckStack           0
+  CheckFunctionTypeArgs 1, r0
   PushNull
   ReturnTOS
 }
@@ -35,7 +35,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushInt              42
   ReturnTOS
 }
@@ -46,7 +46,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   ReturnTOS
 }
@@ -58,7 +58,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -76,7 +76,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   Push                 FP[-6]
   PushConstant         CP#1
@@ -96,7 +96,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -111,7 +111,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -126,7 +126,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   Push                 FP[-5]
   PushConstant         CP#2
@@ -148,7 +148,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushInt              3
   PushConstant         CP#1
@@ -169,7 +169,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -192,7 +192,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -210,7 +210,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-6]
   PushConstant         CP#0
   PushConstant         CP#1
@@ -262,7 +262,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#0
   PushConstant         CP#1
@@ -295,7 +295,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#0
   PushConstant         CP#1
@@ -328,7 +328,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   PushConstant         CP#0
   Push                 FP[-5]
   PushConstant         CP#1
@@ -368,7 +368,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#0
   PushConstant         CP#1
@@ -408,7 +408,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   ReturnTOS
 }
diff --git a/pkg/vm/testcases/bytecode/switch.dart.expect b/pkg/vm/testcases/bytecode/switch.dart.expect
index bb4fbbb..3ed2d95 100644
--- a/pkg/vm/testcases/bytecode/switch.dart.expect
+++ b/pkg/vm/testcases/bytecode/switch.dart.expect
@@ -5,7 +5,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                2
-  CheckStack
+  CheckStack           0
   PushNull
   PopLocal             r0
   Push                 FP[-5]
@@ -73,7 +73,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                2
-  CheckStack
+  CheckStack           0
   PushNull
   PopLocal             r0
   Push                 FP[-5]
@@ -158,7 +158,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                2
-  CheckStack
+  CheckStack           0
   PushNull
   PopLocal             r0
   Push                 FP[-5]
@@ -242,7 +242,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   ReturnTOS
 }
diff --git a/pkg/vm/testcases/bytecode/try_blocks.dart.expect b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
index e513f1e..8b87d84 100644
--- a/pkg/vm/testcases/bytecode/try_blocks.dart.expect
+++ b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
@@ -5,7 +5,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                4
-  CheckStack
+  CheckStack           0
 Try #0 start:
   PushConstant         CP#0
   PushConstant         CP#2
@@ -15,8 +15,8 @@
 Try #0 end:
 Try #0 handler:
   SetFrame             4
-  MoveSpecial          r0, exception
-  MoveSpecial          r1, stackTrace
+  MoveSpecial          exception, r0
+  MoveSpecial          stackTrace, r1
   Push                 r0
   PopLocal             r2
   PushNull
@@ -64,7 +64,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                5
-  CheckStack
+  CheckStack           0
 Try #0 start:
   PushConstant         CP#0
   PushConstant         CP#2
@@ -74,8 +74,8 @@
 Try #0 end:
 Try #0 handler:
   SetFrame             5
-  MoveSpecial          r0, exception
-  MoveSpecial          r1, stackTrace
+  MoveSpecial          exception, r0
+  MoveSpecial          stackTrace, r1
   Push                 r0
   PushConstant         CP#3
   InstanceCall         2, CP#5
@@ -228,18 +228,18 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                7
-  CheckStack
-  AllocateContext      3
+  CheckStack           0
+  AllocateContext      0, 3
   PopLocal             r0
   Push                 r0
   PushInt              1
-  StoreContextVar      0
+  StoreContextVar      0, 0
   Push                 r0
   PopLocal             r2
 Try #0 start:
   Push                 r0
   PushInt              2
-  StoreContextVar      1
+  StoreContextVar      0, 1
   Allocate             CP#9
   StoreLocal           r5
   Push                 r5
@@ -262,7 +262,7 @@
   InstanceCall         1, CP#19
   Drop1
   Push                 r0
-  LoadContextVar       1
+  LoadContextVar       0, 1
   PushConstant         CP#20
   IndirectStaticCall   1, CP#4
   Drop1
@@ -272,13 +272,13 @@
   SetFrame             7
   Push                 r2
   PopLocal             r0
-  MoveSpecial          r2, exception
-  MoveSpecial          r3, stackTrace
+  MoveSpecial          exception, r2
+  MoveSpecial          stackTrace, r3
   Push                 r2
   PopLocal             r4
   Push                 r0
   Push                 r3
-  StoreContextVar      2
+  StoreContextVar      0, 2
   PushNull
   PushInt              4
   CreateArrayTOS
@@ -298,7 +298,7 @@
   Push                 r5
   PushInt              3
   Push                 r0
-  LoadContextVar       2
+  LoadContextVar       0, 2
   StoreIndexedTOS
   PushConstant         CP#23
   IndirectStaticCall   1, CP#4
@@ -375,7 +375,7 @@
 }
 Closure CP#0 {
   EntryFixed           1, 6
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r0
@@ -392,18 +392,18 @@
   SetFrame             6
   Push                 r2
   PopLocal             r0
-  MoveSpecial          r2, exception
-  MoveSpecial          r3, stackTrace
+  MoveSpecial          exception, r2
+  MoveSpecial          stackTrace, r3
   Push                 r2
   PopLocal             r4
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   PushConstant         CP#7
   IndirectStaticCall   1, CP#4
   Drop1
   Push                 r0
   PushInt              3
-  StoreContextVar      1
+  StoreContextVar      0, 1
   Jump                 L1
 L1:
   PushNull
@@ -413,7 +413,7 @@
 
 Closure CP#25 {
   EntryFixed           1, 6
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r0
@@ -430,8 +430,8 @@
   SetFrame             6
   Push                 r2
   PopLocal             r0
-  MoveSpecial          r2, exception
-  MoveSpecial          r3, stackTrace
+  MoveSpecial          exception, r2
+  MoveSpecial          stackTrace, r3
   Push                 r2
   PushConstant         CP#28
   InstanceCall         2, CP#30
@@ -457,7 +457,7 @@
   Push                 r5
   PushInt              3
   Push                 r0
-  LoadContextVar       2
+  LoadContextVar       0, 2
   StoreIndexedTOS
   PushConstant         CP#33
   IndirectStaticCall   1, CP#4
@@ -506,7 +506,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                8
-  CheckStack
+  CheckStack           0
 Try #0 start:
 Try #1 start:
   PushConstant         CP#0
@@ -517,8 +517,8 @@
 Try #1 end:
 Try #1 handler:
   SetFrame             8
-  MoveSpecial          r2, exception
-  MoveSpecial          r3, stackTrace
+  MoveSpecial          exception, r2
+  MoveSpecial          stackTrace, r3
   Push                 r2
   PopLocal             r4
 Try #2 start:
@@ -537,8 +537,8 @@
 Try #2 end:
 Try #2 handler:
   SetFrame             8
-  MoveSpecial          r5, exception
-  MoveSpecial          r6, stackTrace
+  MoveSpecial          exception, r5
+  MoveSpecial          stackTrace, r6
   Push                 r5
   PopLocal             r7
   PushConstant         CP#6
@@ -553,8 +553,8 @@
 Try #0 end:
 Try #0 handler:
   SetFrame             8
-  MoveSpecial          r0, exception
-  MoveSpecial          r1, stackTrace
+  MoveSpecial          exception, r0
+  MoveSpecial          stackTrace, r1
   Push                 r0
   PopLocal             r2
   Push                 r1
@@ -615,21 +615,19 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                3
-  CheckStack
+  CheckStack           0
   PushInt              0
   PopLocal             r0
 L5:
-  CheckStack
+  CheckStack           1
   Push                 r0
   PushInt              10
   CompareIntLt
-  AssertBoolean        0
   JumpIfFalse          L1
 Try #0 start:
   Push                 r0
   PushInt              5
   CompareIntGt
-  AssertBoolean        0
   JumpIfFalse          L2
   Jump                 L3
 L2:
@@ -637,8 +635,8 @@
 Try #0 end:
 Try #0 handler:
   SetFrame             3
-  MoveSpecial          r1, exception
-  MoveSpecial          r2, stackTrace
+  MoveSpecial          exception, r1
+  MoveSpecial          stackTrace, r2
   Push                 r0
   PushConstant         CP#2
   IndirectStaticCall   1, CP#1
@@ -668,7 +666,7 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 10, end 17, handler 17, needs-stack-trace, types [CP#0]
+  try-index 0, outer -1, start 9, end 15, handler 15, needs-stack-trace, types [CP#0]
 }
 ConstantPool {
   [0] = Type dynamic
@@ -693,14 +691,14 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                9
-  CheckStack
-  AllocateContext      2
+  CheckStack           0
+  AllocateContext      0, 2
   PopLocal             r0
   Push                 r0
   Push                 FP[-5]
-  StoreContextVar      0
+  StoreContextVar      0, 0
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   PopLocal             r2
   Push                 r2
   PushInt              1
@@ -721,7 +719,7 @@
   Drop1
   Push                 r0
   PushInt              3
-  StoreContextVar      1
+  StoreContextVar      0, 1
   Push                 r0
   PopLocal             r5
 Try #1 start:
@@ -756,8 +754,8 @@
   SetFrame             9
   Push                 r5
   PopLocal             r0
-  MoveSpecial          r5, exception
-  MoveSpecial          r6, stackTrace
+  MoveSpecial          exception, r5
+  MoveSpecial          stackTrace, r6
   PushConstant         CP#26
   PushConstant         CP#27
   IndirectStaticCall   1, CP#4
@@ -778,8 +776,8 @@
   SetFrame             9
   Push                 r3
   PopLocal             r0
-  MoveSpecial          r3, exception
-  MoveSpecial          r4, stackTrace
+  MoveSpecial          exception, r3
+  MoveSpecial          stackTrace, r4
   PushConstant         CP#31
   PushConstant         CP#32
   IndirectStaticCall   1, CP#4
@@ -849,17 +847,17 @@
 }
 Closure CP#8 {
   EntryFixed           1, 2
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#9
   PopLocal             r0
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   PushConstant         CP#11
   IndirectStaticCall   1, CP#4
   Drop1
   Push                 r0
-  LoadContextVar       1
+  LoadContextVar       0, 1
   PushConstant         CP#12
   IndirectStaticCall   1, CP#4
   Drop1
@@ -906,12 +904,12 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                6
-  CheckStack
-  AllocateContext      1
+  CheckStack           0
+  AllocateContext      0, 1
   PopLocal             r0
   Push                 r0
   PushInt              11
-  StoreContextVar      0
+  StoreContextVar      0, 0
   PushNull
   PopLocal             r2
   Push                 r0
@@ -941,10 +939,10 @@
   SetFrame             6
   Push                 r3
   PopLocal             r0
-  MoveSpecial          r3, exception
-  MoveSpecial          r4, stackTrace
+  MoveSpecial          exception, r3
+  MoveSpecial          stackTrace, r4
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   PushConstant         CP#26
   IndirectStaticCall   1, CP#3
   Drop1
@@ -958,7 +956,7 @@
   Push                 r3
   PopLocal             r0
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   PushConstant         CP#28
   IndirectStaticCall   1, CP#3
   Drop1
@@ -1008,12 +1006,12 @@
 }
 Closure CP#0 {
   EntryFixed           1, 6
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r0
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   PushConstant         CP#4
   IndirectStaticCall   1, CP#3
   Drop1
@@ -1030,8 +1028,8 @@
   SetFrame             6
   Push                 r2
   PopLocal             r0
-  MoveSpecial          r2, exception
-  MoveSpecial          r3, stackTrace
+  MoveSpecial          exception, r2
+  MoveSpecial          stackTrace, r3
   Push                 r0
   PopLocal             r4
 Try #1 start:
@@ -1045,10 +1043,10 @@
   SetFrame             6
   Push                 r4
   PopLocal             r0
-  MoveSpecial          r4, exception
-  MoveSpecial          r5, stackTrace
+  MoveSpecial          exception, r4
+  MoveSpecial          stackTrace, r5
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   PushConstant         CP#10
   IndirectStaticCall   1, CP#3
   Drop1
@@ -1059,7 +1057,7 @@
   Push                 r4
   PopLocal             r0
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   PushConstant         CP#11
   IndirectStaticCall   1, CP#3
   Drop1
@@ -1081,10 +1079,10 @@
   SetFrame             6
   Push                 r4
   PopLocal             r0
-  MoveSpecial          r4, exception
-  MoveSpecial          r5, stackTrace
+  MoveSpecial          exception, r4
+  MoveSpecial          stackTrace, r5
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   PushConstant         CP#13
   IndirectStaticCall   1, CP#3
   Drop1
@@ -1095,7 +1093,7 @@
   Push                 r4
   PopLocal             r0
   Push                 r0
-  LoadContextVar       0
+  LoadContextVar       0, 0
   PushConstant         CP#14
   IndirectStaticCall   1, CP#3
   Drop1
@@ -1132,7 +1130,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                5
-  CheckStack
+  CheckStack           0
 Try #0 start:
 Try #1 start:
   PushConstant         CP#0
@@ -1143,8 +1141,8 @@
 Try #1 end:
 Try #1 handler:
   SetFrame             5
-  MoveSpecial          r2, exception
-  MoveSpecial          r3, stackTrace
+  MoveSpecial          exception, r2
+  MoveSpecial          stackTrace, r3
   Push                 r2
   PopLocal             r4
   PushConstant         CP#4
@@ -1157,8 +1155,8 @@
 Try #0 end:
 Try #0 handler:
   SetFrame             5
-  MoveSpecial          r0, exception
-  MoveSpecial          r1, stackTrace
+  MoveSpecial          exception, r0
+  MoveSpecial          stackTrace, r1
   PushConstant         CP#6
   PushConstant         CP#7
   IndirectStaticCall   1, CP#1
@@ -1204,7 +1202,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   ReturnTOS
 }
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
index ef13709..292a062 100644
--- a/pkg/vm/testcases/bytecode/type_ops.dart.expect
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -6,7 +6,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -26,7 +26,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -46,7 +46,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#1
   IndirectStaticCall   1, CP#0
@@ -67,7 +67,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-6]
   Push                 FP[-5]
   PushConstant         CP#0
@@ -100,14 +100,13 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   Push                 FP[-6]
   LoadTypeArgumentsField CP#0
   PushNull
   PushConstant         CP#1
   InstanceCall         4, CP#3
-  AssertBoolean        0
   JumpIfFalse          L1
   PushConstant         CP#4
   PushConstant         CP#6
@@ -120,7 +119,6 @@
   PushNull
   PushConstant         CP#7
   InstanceCall         4, CP#8
-  AssertBoolean        0
   JumpIfFalse          L2
   PushConstant         CP#9
   PushConstant         CP#10
@@ -170,14 +168,13 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
-  CheckFunctionTypeArgs 2, 0
+  CheckStack           0
+  CheckFunctionTypeArgs 2, r0
   Push                 FP[-5]
   PushNull
   Push                 r0
   PushConstant         CP#0
   InstanceCall         4, CP#2
-  AssertBoolean        0
   JumpIfFalse          L1
   PushConstant         CP#3
   PushConstant         CP#5
@@ -190,7 +187,6 @@
   Push                 r0
   PushConstant         CP#7
   InstanceCall         4, CP#8
-  AssertBoolean        0
   JumpIfFalse          L2
   PushConstant         CP#9
   PushConstant         CP#10
@@ -236,7 +232,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                2
-  CheckStack
+  CheckStack           0
   Push                 FP[-6]
   LoadTypeArgumentsField CP#0
   PushNull
@@ -287,7 +283,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   ReturnTOS
 }
@@ -298,8 +294,8 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
-  CheckFunctionTypeArgs 2, 0
+  CheckStack           0
+  CheckFunctionTypeArgs 2, r0
   JumpIfNotZeroTypeArgs L1
   Push                 FP[-6]
   LoadTypeArgumentsField CP#0
@@ -330,11 +326,10 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#0
   InstanceCall         2, CP#2
-  AssertBoolean        0
   JumpIfFalse          L1
   PushConstant         CP#3
   PushConstant         CP#5
@@ -346,7 +341,6 @@
   PushNull
   PushConstant         CP#6
   InstanceCall         4, CP#8
-  AssertBoolean        0
   JumpIfFalse          L2
   PushConstant         CP#9
   PushConstant         CP#10
@@ -389,7 +383,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                1
-  CheckStack
+  CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#0
   PushNull
@@ -412,7 +406,7 @@
 [@vm.bytecode=
 Bytecode (version: stable) {
   Entry                0
-  CheckStack
+  CheckStack           0
   PushNull
   ReturnTOS
 }
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index ecf8a5d..adbfaa6 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -133,7 +133,7 @@
     defines += [ "NDEBUG" ]
   }
 
-  include_dirs = []
+  include_dirs = [ "include" ]
   if (dart_use_tcmalloc) {
     defines += [ "DART_USE_TCMALLOC" ]
     include_dirs += [ "../third_party/tcmalloc/gperftools/src" ]
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 8689f2c..cec8c52 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -89,6 +89,35 @@
   ]
 }
 
+static_library("crashpad") {
+  configs += [
+    "..:dart_arch_config",
+    "..:dart_config",
+    "..:dart_product_config",
+    "..:dart_os_fuchsia_config",
+  ]
+  if (is_fuchsia) {
+    configs -= [ "//build/config:symbol_visibility_hidden" ]
+  }
+  include_dirs = [ ".." ]
+  sources = [
+    "crashpad.cc",
+  ]
+
+  if (dart_use_crashpad) {
+    assert(is_win, "dart_use_crashpad is only supported on Windows")
+    deps = [
+      "//third_party/crashpad/crashpad/client",
+      "//third_party/mini_chromium/mini_chromium/base",
+
+      # This binary is used to handle crashes of the dart binary.
+      "//third_party/crashpad/crashpad/handler:crashpad_handler",
+    ]
+    include_dirs += [ "//third_party/crashpad" ]
+    defines = [ "DART_USE_CRASHPAD" ]
+  }
+}
+
 template("build_gen_snapshot") {
   extra_configs = []
   if (defined(invoker.extra_configs)) {
@@ -664,6 +693,7 @@
              ":libdart_builtin",
              "//third_party/boringssl",
              "//third_party/zlib",
+             ":crashpad",
            ] + extra_deps
 
     defines = extra_defines
@@ -680,19 +710,6 @@
       "//third_party",
     ]
 
-    if (dart_use_crashpad) {
-      assert(is_win, "dart_use_crashpad is only supported on Windows")
-      deps += [
-        "//third_party/crashpad/crashpad/client",
-        "//third_party/mini_chromium/mini_chromium/base",
-
-        # This binary is used to handle crashes of the dart binary.
-        "//third_party/crashpad/crashpad/handler:crashpad_handler",
-      ]
-      include_dirs += [ "//third_party/crashpad" ]
-      defines += [ "DART_USE_CRASHPAD" ]
-    }
-
     sources = [
                 "dart_embedder_api_impl.cc",
                 "error_exit.cc",
@@ -882,6 +899,7 @@
   }
 
   deps = [
+    ":crashpad",
     ":dart_kernel_platform_cc",
     ":dart_snapshot_cc",
     ":gen_kernel_bytecode_dill",
diff --git a/runtime/bin/crashpad.cc b/runtime/bin/crashpad.cc
new file mode 100644
index 0000000..184dba1
--- /dev/null
+++ b/runtime/bin/crashpad.cc
@@ -0,0 +1,81 @@
+// 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 "bin/crashpad.h"
+
+#if defined(DART_USE_CRASHPAD)
+#include <map>
+#include <string>
+#include <vector>
+
+#include "crashpad/client/crashpad_client.h"
+#include "crashpad/client/crashpad_info.h"
+#endif
+
+#include "bin/error_exit.h"
+#include "bin/log.h"
+#include "bin/platform.h"
+
+namespace dart {
+namespace bin {
+
+#if defined(DART_USE_CRASHPAD)
+#if !defined(HOST_OS_WINDOWS)
+#error "Currently we only support Crashpad on Windows"
+#endif
+
+void InitializeCrashpadClient() {
+  // DART_CRASHPAD_HANDLER and DART_CRASHPAD_CRASHES_DIR are set by the
+  // testing framework.
+  wchar_t* handler = _wgetenv(L"DART_CRASHPAD_HANDLER");
+  wchar_t* crashes_dir = _wgetenv(L"DART_CRASHPAD_CRASHES_DIR");
+  if (handler == nullptr || crashes_dir == nullptr || wcslen(handler) == 0 ||
+      wcslen(crashes_dir) == 0) {
+    return;
+  }
+
+  // Crashpad uses STL so we use it here too even though in general we
+  // avoid it.
+  const base::FilePath handler_path{std::wstring(handler)};
+  const base::FilePath crashes_dir_path{std::wstring(crashes_dir)};
+  const std::string url("");
+  std::map<std::string, std::string> annotations;
+  char* test_name = getenv("DART_TEST_NAME");
+  if (test_name != nullptr) {
+    annotations["dart_test_name"] = test_name;
+  }
+
+  std::vector<std::string> arguments;
+
+  crashpad::CrashpadClient client;
+
+  // Prevent crashpad_handler from inheriting our standard output and error
+  // handles. Otherwise we would not be able to close them ourselves making
+  // tests that rely on that fail.
+  HANDLE original_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
+  HANDLE original_stderr = GetStdHandle(STD_ERROR_HANDLE);
+  SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE);
+  SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE);
+  const bool success =
+      client.StartHandler(handler_path, crashes_dir_path, crashes_dir_path, url,
+                          annotations, arguments,
+                          /*restartable=*/true,
+                          /*asynchronous_start=*/false);
+  SetStdHandle(STD_OUTPUT_HANDLE, original_stdout);
+  SetStdHandle(STD_ERROR_HANDLE, original_stderr);
+
+  if (!success) {
+    Log::PrintErr("Failed to start the crash handler!\n");
+    Platform::Exit(kErrorExitCode);
+  }
+  crashpad::CrashpadInfo::GetCrashpadInfo()
+      ->set_gather_indirectly_referenced_memory(crashpad::TriState::kEnabled,
+                                                /*limit=*/500 * MB);
+}
+#else
+void InitializeCrashpadClient() {}
+#endif  // DART_USE_CRASHPAD
+
+}  // namespace bin
+}  // namespace dart
diff --git a/runtime/bin/crashpad.h b/runtime/bin/crashpad.h
new file mode 100644
index 0000000..2534fd1
--- /dev/null
+++ b/runtime/bin/crashpad.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_BIN_CRASHPAD_H_
+#define RUNTIME_BIN_CRASHPAD_H_
+
+namespace dart {
+namespace bin {
+
+void InitializeCrashpadClient();
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // RUNTIME_BIN_CRASHPAD_H_
diff --git a/runtime/bin/dart_embedder_api_impl.cc b/runtime/bin/dart_embedder_api_impl.cc
index 072a279..ba47d33 100644
--- a/runtime/bin/dart_embedder_api_impl.cc
+++ b/runtime/bin/dart_embedder_api_impl.cc
@@ -36,7 +36,6 @@
                                   err.message());
     return false;
   }
-  bin::Thread::InitOnce();
   bin::TimerUtils::InitOnce();
   bin::EventHandler::Start();
   return true;
diff --git a/runtime/bin/dart_io_api_impl.cc b/runtime/bin/dart_io_api_impl.cc
index 82645e7..e8ab2ad 100644
--- a/runtime/bin/dart_io_api_impl.cc
+++ b/runtime/bin/dart_io_api_impl.cc
@@ -18,7 +18,6 @@
 
 void BootstrapDartIo() {
   // Bootstrap 'dart:io' event handler.
-  Thread::InitOnce();
   TimerUtils::InitOnce();
   EventHandler::Start();
 }
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index db0ef11..bbda5dc 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -937,7 +937,7 @@
 }
 
 int main(int argc, char** argv) {
-  const int EXTRA_VM_ARGUMENTS = 4;
+  const int EXTRA_VM_ARGUMENTS = 7;
   CommandLineOptions vm_options(argc + EXTRA_VM_ARGUMENTS);
 
   // Initialize the URL mapping array.
@@ -953,6 +953,7 @@
     vm_options.AddArgument("--new_gen_semi_max_size=32");
   }
   vm_options.AddArgument("--new_gen_growth_factor=4");
+  vm_options.AddArgument("--deterministic");
 
   // Parse command line arguments.
   if (ParseArguments(argc, argv, &vm_options, &app_script_name) < 0) {
@@ -979,7 +980,6 @@
     return kErrorExitCode;
   }
   Console::SaveConfig();
-  Thread::InitOnce();
   Loader::InitOnce();
   DartUtils::SetOriginalWorkingDirectory();
   // Start event handler.
@@ -993,9 +993,8 @@
 
   if (IsSnapshottingForPrecompilation()) {
     vm_options.AddArgument("--precompilation");
-  }
-  if ((snapshot_kind == kCoreJITAll) || (snapshot_kind == kCoreJIT) ||
-      (snapshot_kind == kAppJIT)) {
+  } else if ((snapshot_kind == kCoreJITAll) || (snapshot_kind == kCoreJIT) ||
+             (snapshot_kind == kAppJIT)) {
     vm_options.AddArgument("--fields_may_be_reset");
     vm_options.AddArgument("--link_natives_lazily");
 #if !defined(PRODUCT)
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 5473185..aa10c51 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -11,13 +11,9 @@
 #include "include/dart_embedder_api.h"
 #include "include/dart_tools_api.h"
 
-#if defined(DART_USE_CRASHPAD)
-#include "crashpad/client/crashpad_client.h"
-#include "crashpad/client/crashpad_info.h"
-#endif
-
 #include "bin/builtin.h"
 #include "bin/console.h"
+#include "bin/crashpad.h"
 #include "bin/dartutils.h"
 #include "bin/dfe.h"
 #include "bin/directory.h"
@@ -25,6 +21,7 @@
 #include "bin/eventhandler.h"
 #include "bin/extensions.h"
 #include "bin/file.h"
+#include "bin/gzip.h"
 #include "bin/isolate_data.h"
 #include "bin/loader.h"
 #include "bin/log.h"
@@ -39,7 +36,6 @@
 #include "platform/growable_array.h"
 #include "platform/hashmap.h"
 #include "platform/text_buffer.h"
-#include "bin/gzip.h"
 
 #include "vm/flags.h"
 
@@ -952,45 +948,6 @@
 static Dart_GetVMServiceAssetsArchive GetVMServiceAssetsArchiveCallback = NULL;
 #endif  // !defined(NO_OBSERVATORY)
 
-#if defined(DART_USE_CRASHPAD)
-#if !defined(HOST_OS_WINDOWS)
-#error "Currently we only support Crashpad on Windows"
-#endif
-
-static void ConfigureCrashpadClient(crashpad::CrashpadClient* client) {
-  // DART_CRASHPAD_HANDLER and DART_CRASHPAD_CRASHES_DIR are set by the
-  // testing framework.
-  wchar_t* handler = _wgetenv(L"DART_CRASHPAD_HANDLER");
-  wchar_t* crashes_dir = _wgetenv(L"DART_CRASHPAD_CRASHES_DIR");
-  if (handler == nullptr || crashes_dir == nullptr) {
-    return;
-  }
-
-  // Crashpad uses STL so we use it here too even though in general we
-  // avoid it.
-  const base::FilePath handler_path{std::wstring(handler)};
-  const base::FilePath crashes_dir_path{std::wstring(crashes_dir)};
-  const std::string url("");
-  std::map<std::string, std::string> annotations;
-  char* test_name = getenv("DART_TEST_NAME");
-  if (test_name != nullptr) {
-    annotations["dart_test_name"] = test_name;
-  }
-
-  std::vector<std::string> arguments;
-  if (!client->StartHandler(handler_path, crashes_dir_path, crashes_dir_path,
-                            url, annotations, arguments,
-                            /*restartable=*/true,
-                            /*asynchronous_start=*/false)) {
-    Log::PrintErr("Failed to start the crash handler!\n");
-    Platform::Exit(kErrorExitCode);
-  }
-  crashpad::CrashpadInfo::GetCrashpadInfo()
-      ->set_gather_indirectly_referenced_memory(crashpad::TriState::kEnabled,
-                                                /*limit=*/500 * MB);
-}
-#endif  // DART_USE_CRASHPAD
-
 void main(int argc, char** argv) {
   char* script_name;
   const int EXTRA_VM_ARGUMENTS = 10;
@@ -1054,10 +1011,7 @@
   }
   DartUtils::SetEnvironment(Options::environment());
 
-#if defined(DART_USE_CRASHPAD)
-  crashpad::CrashpadClient crashpad_client;
-  ConfigureCrashpadClient(&crashpad_client);
-#endif
+  InitializeCrashpadClient();
 
   Loader::InitOnce();
 
diff --git a/runtime/bin/namespace_patch.dart b/runtime/bin/namespace_patch.dart
index 488aaf5..f28c104 100644
--- a/runtime/bin/namespace_patch.dart
+++ b/runtime/bin/namespace_patch.dart
@@ -32,6 +32,7 @@
 }
 
 @patch
+@pragma("vm:entry-point")
 class _Namespace {
   @patch
   @pragma("vm:entry-point")
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index 2240355..f488063 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "bin/console.h"
+#include "bin/crashpad.h"
 #include "bin/dartutils.h"
 #include "bin/dfe.h"
 #include "bin/eventhandler.h"
@@ -220,6 +221,8 @@
     return 1;
   }
 
+  dart::bin::InitializeCrashpadClient();
+
   // Save the console state so we can restore it later.
   dart::bin::Console::SaveConfig();
 
@@ -273,7 +276,6 @@
     dart_argv = &argv[1];
   }
 
-  bin::Thread::InitOnce();
   bin::TimerUtils::InitOnce();
   bin::EventHandler::Start();
 
diff --git a/runtime/bin/security_context_macos.cc b/runtime/bin/security_context_macos.cc
index 73f0fa8..2964d67 100644
--- a/runtime/bin/security_context_macos.cc
+++ b/runtime/bin/security_context_macos.cc
@@ -62,7 +62,7 @@
   if (length < 0) {
     return 0;
   }
-  auto deb_cert = std::make_unique<unsigned char[]>(length);
+  auto deb_cert = std::unique_ptr<unsigned char[]>(new unsigned char[length]);
   unsigned char* temp = deb_cert.get();
   if (i2d_X509(cert, &temp) != length) {
     return NULL;
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index 7af4d65..abcb7ba 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -350,6 +350,7 @@
       ErrorExit(kErrorExitCode, "%s\n", result.error);
     }
     WriteSnapshotFile(snapshot_filename, result.kernel, result.kernel_size);
+    free(result.kernel);
   }
 #else
   UNREACHABLE();
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index 7d07146..42fd447 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -110,8 +110,14 @@
         __FILE__, __LINE__);
   }
 
-  VOID_NO_RETRY_EXPECTED(
-      setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)));
+  if (!SocketBase::SetMulticastHops(fd,
+                                    addr.addr.sa_family == AF_INET
+                                        ? SocketAddress::TYPE_IPV4
+                                        : SocketAddress::TYPE_IPV6,
+                                    ttl)) {
+    FDUtils::SaveErrorAndClose(fd);
+    return -1;
+  }
 
   if (NO_RETRY_EXPECTED(
           bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index 6d7e874..979db01 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -116,8 +116,14 @@
 #endif  // SO_REUSEPORT
   }
 
-  VOID_NO_RETRY_EXPECTED(
-      setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)));
+  if (!SocketBase::SetMulticastHops(fd,
+                                    addr.addr.sa_family == AF_INET
+                                        ? SocketAddress::TYPE_IPV4
+                                        : SocketAddress::TYPE_IPV6,
+                                    ttl)) {
+    FDUtils::SaveErrorAndClose(fd);
+    return -1;
+  }
 
   if (NO_RETRY_EXPECTED(
           bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index 7e2f8f0..81ede2e 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -107,8 +107,14 @@
         setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)));
   }
 
-  VOID_NO_RETRY_EXPECTED(
-      setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)));
+  if (!SocketBase::SetMulticastHops(fd,
+                                    addr.addr.sa_family == AF_INET
+                                        ? SocketAddress::TYPE_IPV4
+                                        : SocketAddress::TYPE_IPV6,
+                                    ttl)) {
+    FDUtils::SaveErrorAndClose(fd);
+    return -1;
+  }
 
   if (NO_RETRY_EXPECTED(
           bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
diff --git a/runtime/bin/socket_win.cc b/runtime/bin/socket_win.cc
index c02c1bb..957ac92 100644
--- a/runtime/bin/socket_win.cc
+++ b/runtime/bin/socket_win.cc
@@ -173,13 +173,19 @@
     // ignore reusePort - not supported on this platform.
     Log::PrintErr(
         "Dart Socket ERROR: %s:%d: `reusePort` not supported for "
-        "Windows." __FILE__,
-        __LINE__);
+        "Windows.",
+        __FILE__, __LINE__);
   }
 
-  status = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
-                      reinterpret_cast<const char*>(&ttl), sizeof(ttl));
-  if (status == SOCKET_ERROR) {
+  // Can't use SocketBase::SetMulticastHops here - we'd need to create
+  // the DatagramSocket object and reinterpret_cast it here, just for that
+  // method to reinterpret_cast it again.
+  int ttlValue = ttl;
+  int ttlLevel = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
+  int ttlOptname =
+      addr.addr.sa_family == AF_INET ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS;
+  if (setsockopt(s, ttlLevel, ttlOptname, reinterpret_cast<char*>(&ttlValue),
+                 sizeof(ttlValue)) != 0) {
     DWORD rc = WSAGetLastError();
     closesocket(s);
     SetLastError(rc);
@@ -196,6 +202,7 @@
 
   DatagramSocket* datagram_socket = new DatagramSocket(s);
   datagram_socket->EnsureInitialized(EventHandler::delegate());
+
   return reinterpret_cast<intptr_t>(datagram_socket);
 }
 
diff --git a/runtime/bin/thread_android.cc b/runtime/bin/thread_android.cc
index ab0d7a2..4970240 100644
--- a/runtime/bin/thread_android.cc
+++ b/runtime/bin/thread_android.cc
@@ -152,10 +152,6 @@
   return (a == b);
 }
 
-void Thread::InitOnce() {
-  // Nothing to be done.
-}
-
 Mutex::Mutex() {
   pthread_mutexattr_t attr;
   int result = pthread_mutexattr_init(&attr);
diff --git a/runtime/bin/thread_fuchsia.cc b/runtime/bin/thread_fuchsia.cc
index 64e7fce..793e9c1 100644
--- a/runtime/bin/thread_fuchsia.cc
+++ b/runtime/bin/thread_fuchsia.cc
@@ -151,10 +151,6 @@
   return (pthread_equal(a, b) != 0);
 }
 
-void Thread::InitOnce() {
-  // Nothing to be done.
-}
-
 Mutex::Mutex() {
   pthread_mutexattr_t attr;
   int result = pthread_mutexattr_init(&attr);
diff --git a/runtime/bin/thread_linux.cc b/runtime/bin/thread_linux.cc
index b30bbf0..1140ed4 100644
--- a/runtime/bin/thread_linux.cc
+++ b/runtime/bin/thread_linux.cc
@@ -152,10 +152,6 @@
   return (pthread_equal(a, b) != 0);
 }
 
-void Thread::InitOnce() {
-  // Nothing to be done.
-}
-
 Mutex::Mutex() {
   pthread_mutexattr_t attr;
   int result = pthread_mutexattr_init(&attr);
diff --git a/runtime/bin/thread_macos.cc b/runtime/bin/thread_macos.cc
index 249a476..6618ba8 100644
--- a/runtime/bin/thread_macos.cc
+++ b/runtime/bin/thread_macos.cc
@@ -146,10 +146,6 @@
   return (pthread_equal(a, b) != 0);
 }
 
-void Thread::InitOnce() {
-  // Nothing to be done.
-}
-
 Mutex::Mutex() {
   pthread_mutexattr_t attr;
   int result = pthread_mutexattr_init(&attr);
diff --git a/runtime/bin/thread_win.cc b/runtime/bin/thread_win.cc
index ab3e9b9..cba3652 100644
--- a/runtime/bin/thread_win.cc
+++ b/runtime/bin/thread_win.cc
@@ -40,14 +40,9 @@
   uword parameter = data->parameter();
   delete data;
 
-  MonitorData::GetMonitorWaitDataForThread();
-
   // Call the supplied thread start function handing it its parameters.
   function(parameter);
 
-  // Clean up the monitor wait data for this thread.
-  MonitorWaitData::ThreadExit();
-
   return 0;
 }
 
@@ -114,63 +109,34 @@
   }
 }
 
-void Thread::InitOnce() {
-  MonitorWaitData::monitor_wait_data_key_ = Thread::CreateThreadLocal();
-  MonitorData::GetMonitorWaitDataForThread();
-}
-
 Mutex::Mutex() {
-  // Allocate unnamed semaphore with initial count 1 and max count 1.
-  data_.semaphore_ = CreateSemaphore(NULL, 1, 1, NULL);
-  if (data_.semaphore_ == NULL) {
-    FATAL1("Mutex allocation failed %d", GetLastError());
-  }
+  InitializeSRWLock(&data_.lock_);
 }
 
-Mutex::~Mutex() {
-  CloseHandle(data_.semaphore_);
-}
+Mutex::~Mutex() {}
 
 void Mutex::Lock() {
-  DWORD result = WaitForSingleObject(data_.semaphore_, INFINITE);
-  if (result != WAIT_OBJECT_0) {
-    FATAL1("Mutex lock failed %d", GetLastError());
-  }
+  AcquireSRWLockExclusive(&data_.lock_);
 }
 
 bool Mutex::TryLock() {
-  // Attempt to pass the semaphore but return immediately.
-  DWORD result = WaitForSingleObject(data_.semaphore_, 0);
-  if (result == WAIT_OBJECT_0) {
+  if (TryAcquireSRWLockExclusive(&data_.lock_) != 0) {
     return true;
   }
-  if ((result == WAIT_ABANDONED) || (result == WAIT_FAILED)) {
-    FATAL1("Mutex try lock failed %d", GetLastError());
-  }
-  ASSERT(result == WAIT_TIMEOUT);
   return false;
 }
 
 void Mutex::Unlock() {
-  BOOL result = ReleaseSemaphore(data_.semaphore_, 1, NULL);
-  if (result == 0) {
-    FATAL1("Mutex unlock failed %d", GetLastError());
-  }
+  ReleaseSRWLockExclusive(&data_.lock_);
 }
 
-ThreadLocalKey MonitorWaitData::monitor_wait_data_key_ =
-    Thread::kUnsetThreadLocalKey;
-
 Monitor::Monitor() {
   InitializeCriticalSection(&data_.cs_);
-  InitializeCriticalSection(&data_.waiters_cs_);
-  data_.waiters_head_ = NULL;
-  data_.waiters_tail_ = NULL;
+  InitializeConditionVariable(&data_.cond_);
 }
 
 Monitor::~Monitor() {
   DeleteCriticalSection(&data_.cs_);
-  DeleteCriticalSection(&data_.waiters_cs_);
 }
 
 void Monitor::Enter() {
@@ -181,188 +147,19 @@
   LeaveCriticalSection(&data_.cs_);
 }
 
-void MonitorWaitData::ThreadExit() {
-  if (MonitorWaitData::monitor_wait_data_key_ != Thread::kUnsetThreadLocalKey) {
-    uword raw_wait_data =
-        Thread::GetThreadLocal(MonitorWaitData::monitor_wait_data_key_);
-    if (raw_wait_data != 0) {
-      MonitorWaitData* wait_data =
-          reinterpret_cast<MonitorWaitData*>(raw_wait_data);
-      delete wait_data;
-    }
-  }
-}
-
-void MonitorData::AddWaiter(MonitorWaitData* wait_data) {
-  // Add the MonitorWaitData object to the list of objects waiting for
-  // this monitor.
-  EnterCriticalSection(&waiters_cs_);
-  if (waiters_tail_ == NULL) {
-    ASSERT(waiters_head_ == NULL);
-    waiters_head_ = wait_data;
-    waiters_tail_ = wait_data;
-  } else {
-    waiters_tail_->next_ = wait_data;
-    waiters_tail_ = wait_data;
-  }
-  LeaveCriticalSection(&waiters_cs_);
-}
-
-void MonitorData::RemoveWaiter(MonitorWaitData* wait_data) {
-  // Remove the MonitorWaitData object from the list of objects
-  // waiting for this monitor.
-  EnterCriticalSection(&waiters_cs_);
-  MonitorWaitData* previous = NULL;
-  MonitorWaitData* current = waiters_head_;
-  while (current != NULL) {
-    if (current == wait_data) {
-      if (waiters_head_ == waiters_tail_) {
-        waiters_head_ = NULL;
-        waiters_tail_ = NULL;
-      } else if (current == waiters_head_) {
-        waiters_head_ = waiters_head_->next_;
-      } else if (current == waiters_tail_) {
-        ASSERT(previous != NULL);
-        waiters_tail_ = previous;
-        previous->next_ = NULL;
-      } else {
-        ASSERT(previous != NULL);
-        previous->next_ = current->next_;
-      }
-      // Clear next.
-      wait_data->next_ = NULL;
-      break;
-    }
-    previous = current;
-    current = current->next_;
-  }
-  LeaveCriticalSection(&waiters_cs_);
-}
-
-void MonitorData::SignalAndRemoveFirstWaiter() {
-  EnterCriticalSection(&waiters_cs_);
-  MonitorWaitData* first = waiters_head_;
-  if (first != NULL) {
-    // Remove from list.
-    if (waiters_head_ == waiters_tail_) {
-      waiters_tail_ = NULL;
-      waiters_head_ = NULL;
-    } else {
-      waiters_head_ = waiters_head_->next_;
-    }
-    // Clear next.
-    first->next_ = NULL;
-    // Signal event.
-    BOOL result = SetEvent(first->event_);
-    if (result == 0) {
-      FATAL1("Monitor::Notify failed to signal event %d", GetLastError());
-    }
-  }
-  LeaveCriticalSection(&waiters_cs_);
-}
-
-void MonitorData::SignalAndRemoveAllWaiters() {
-  EnterCriticalSection(&waiters_cs_);
-  // Extract list to signal.
-  MonitorWaitData* current = waiters_head_;
-  // Clear list.
-  waiters_head_ = NULL;
-  waiters_tail_ = NULL;
-  // Iterate and signal all events.
-  while (current != NULL) {
-    // Copy next.
-    MonitorWaitData* next = current->next_;
-    // Clear next.
-    current->next_ = NULL;
-    // Signal event.
-    BOOL result = SetEvent(current->event_);
-    if (result == 0) {
-      FATAL1("Failed to set event for NotifyAll %d", GetLastError());
-    }
-    current = next;
-  }
-  LeaveCriticalSection(&waiters_cs_);
-}
-
-MonitorWaitData* MonitorData::GetMonitorWaitDataForThread() {
-  // Ensure that the thread local key for monitor wait data objects is
-  // initialized.
-  ASSERT(MonitorWaitData::monitor_wait_data_key_ !=
-         Thread::kUnsetThreadLocalKey);
-
-  // Get the MonitorWaitData object containing the event for this
-  // thread from thread local storage. Create it if it does not exist.
-  uword raw_wait_data =
-      Thread::GetThreadLocal(MonitorWaitData::monitor_wait_data_key_);
-  MonitorWaitData* wait_data = NULL;
-  if (raw_wait_data == 0) {
-    HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
-    wait_data = new MonitorWaitData(event);
-    Thread::SetThreadLocal(MonitorWaitData::monitor_wait_data_key_,
-                           reinterpret_cast<uword>(wait_data));
-  } else {
-    wait_data = reinterpret_cast<MonitorWaitData*>(raw_wait_data);
-    ASSERT(wait_data->next_ == NULL);
-  }
-  return wait_data;
-}
-
 Monitor::WaitResult Monitor::Wait(int64_t millis) {
   Monitor::WaitResult retval = kNotified;
-
-  // Get the wait data object containing the event to wait for.
-  MonitorWaitData* wait_data = MonitorData::GetMonitorWaitDataForThread();
-
-  // Start waiting by adding the MonitorWaitData to the list of
-  // waiters.
-  data_.AddWaiter(wait_data);
-
-  // Leave the monitor critical section while waiting.
-  LeaveCriticalSection(&data_.cs_);
-
-  // Perform the actual wait on the event.
-  DWORD result = WAIT_FAILED;
-  if (millis == 0) {
-    // Wait forever for a Notify or a NotifyAll event.
-    result = WaitForSingleObject(wait_data->event_, INFINITE);
-    if (result == WAIT_FAILED) {
-      FATAL1("Monitor::Wait failed %d", GetLastError());
-    }
+  if (millis == kNoTimeout) {
+    SleepConditionVariableCS(&data_.cond_, &data_.cs_, INFINITE);
   } else {
     // Wait for the given period of time for a Notify or a NotifyAll
     // event.
-    result = WaitForSingleObject(wait_data->event_, millis);
-    if (result == WAIT_FAILED) {
-      FATAL1("Monitor::Wait with timeout failed %d", GetLastError());
-    }
-    if (result == WAIT_TIMEOUT) {
-      // No longer waiting. Remove from the list of waiters.
-      data_.RemoveWaiter(wait_data);
-      // Caveat: wait_data->event_ might have been signaled between
-      // WaitForSingleObject and RemoveWaiter because we are not in any critical
-      // section here. Leaving it in a signaled state would break invariants
-      // that Monitor::Wait code relies on. We assume that when
-      // WaitForSingleObject(wait_data->event_, ...) returns successfully then
-      // corresponding wait_data is not on the waiters list anymore.
-      // This is guaranteed because we only signal these events from
-      // SignalAndRemoveAllWaiters/SignalAndRemoveFirstWaiter which
-      // simultaneously remove MonitorWaitData from the list.
-      // Now imagine that wait_data->event_ is left signaled here. In this case
-      // the next WaitForSingleObject(wait_data->event_, ...) will immediately
-      // return while wait_data is still on the waiters list. This would
-      // leave waiters list in the inconsistent state.
-      // To prevent this from happening simply reset the event.
-      // Note: wait_data is no longer on the waiters list so it can't be
-      // signaled anymore at this point so there is no race possible from
-      // this point onward.
-      ResetEvent(wait_data->event_);
+    if (!SleepConditionVariableCS(&data_.cond_, &data_.cs_, millis)) {
+      ASSERT(GetLastError() == ERROR_TIMEOUT);
       retval = kTimedOut;
     }
   }
 
-  // Reacquire the monitor critical section before continuing.
-  EnterCriticalSection(&data_.cs_);
-
   return retval;
 }
 
@@ -379,16 +176,11 @@
 }
 
 void Monitor::Notify() {
-  data_.SignalAndRemoveFirstWaiter();
+  WakeConditionVariable(&data_.cond_);
 }
 
 void Monitor::NotifyAll() {
-  // If one of the objects in the list of waiters wakes because of a
-  // timeout before we signal it, that object will get an extra
-  // signal. This will be treated as a spurious wake-up and is OK
-  // since all uses of monitors should recheck the condition after a
-  // Wait.
-  data_.SignalAndRemoveAllWaiters();
+  WakeAllConditionVariable(&data_.cond_);
 }
 
 }  // namespace bin
diff --git a/runtime/bin/thread_win.h b/runtime/bin/thread_win.h
index cd14e44..611b06b 100644
--- a/runtime/bin/thread_win.h
+++ b/runtime/bin/thread_win.h
@@ -41,7 +41,7 @@
   MutexData() {}
   ~MutexData() {}
 
-  HANDLE semaphore_;
+  SRWLOCK lock_;
 
   friend class Mutex;
 
@@ -49,64 +49,15 @@
   DISALLOW_COPY_AND_ASSIGN(MutexData);
 };
 
-class MonitorWaitData {
- public:
-  static void ThreadExit();
-
- private:
-  explicit MonitorWaitData(HANDLE event) : event_(event), next_(NULL) {}
-  ~MonitorWaitData() {
-    CloseHandle(event_);
-    ASSERT(next_ == NULL);
-  }
-
-  // ThreadLocalKey used to fetch and store the MonitorWaitData object
-  // for a given thread.
-  static ThreadLocalKey monitor_wait_data_key_;
-
-  // Auto-reset event used for waiting.
-  HANDLE event_;
-  // Link to next element in the singly-linked list of waiters.
-  MonitorWaitData* next_;
-
-  friend class Monitor;
-  friend class MonitorData;
-  friend class Thread;
-
-  DISALLOW_COPY_AND_ASSIGN(MonitorWaitData);
-};
-
 class MonitorData {
  private:
   MonitorData() {}
   ~MonitorData() {}
 
-  // Helper methods to manipulate the list of waiters for this
-  // monitor.
-  void AddWaiter(MonitorWaitData* wait_data);
-  void RemoveWaiter(MonitorWaitData* wait_data);
-  void SignalAndRemoveFirstWaiter();
-  void SignalAndRemoveAllWaiters();
-  static MonitorWaitData* GetMonitorWaitDataForThread();
-
-  // The external critical section for the monitor.
   CRITICAL_SECTION cs_;
-
-  // Condition variables are only available since Windows Vista. To
-  // support at least Windows XP, we implement our own condition
-  // variables using SetEvent on Event objects.
-
-  // Singly-linked list of event objects, one for each thread waiting
-  // on this monitor. New waiters are added at the end of the list.
-  // Notify signals the first element of the list (FIFO
-  // order). NotifyAll, signals all the elements of the list.
-  CRITICAL_SECTION waiters_cs_;
-  MonitorWaitData* waiters_head_;
-  MonitorWaitData* waiters_tail_;
+  CONDITION_VARIABLE cond_;
 
   friend class Monitor;
-  friend class Thread;
-  friend unsigned int __stdcall ThreadEntry(void* data_ptr);
 
   DISALLOW_ALLOCATION();
   DISALLOW_COPY_AND_ASSIGN(MonitorData);
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index a4b8956..f4733ae 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -238,6 +238,8 @@
   Future _requestHandler(HttpRequest request) async {
     if (!_originCheck(request)) {
       // This is a cross origin attempt to connect
+      request.response.statusCode = HttpStatus.forbidden;
+      request.response.write("forbidden origin");
       request.response.close();
       return;
     }
@@ -293,6 +295,8 @@
     }
     if (request.method != 'GET') {
       // Not a GET request. Do nothing.
+      request.response.statusCode = HttpStatus.methodNotAllowed;
+      request.response.write("method not allowed");
       request.response.close();
       return;
     }
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index 1ed1327..04a3e89 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -86,6 +86,18 @@
   return NULL;
 }
 
+const uint8_t* VmServiceIONativeSymbol(Dart_NativeFunction nf) {
+  intptr_t n =
+      sizeof(_VmServiceIONativeEntries) / sizeof(_VmServiceIONativeEntries[0]);
+  for (intptr_t i = 0; i < n; i++) {
+    VmServiceIONativeEntry entry = _VmServiceIONativeEntries[i];
+    if (reinterpret_cast<Dart_NativeFunction>(entry.function) == nf) {
+      return reinterpret_cast<const uint8_t*>(entry.name);
+    }
+  }
+  return NULL;
+}
+
 const char* VmService::error_msg_ = NULL;
 char VmService::server_uri_[kServerUriStringBufferSize];
 
@@ -93,7 +105,8 @@
   Dart_Handle url = DartUtils::NewString(kVMServiceIOLibraryUri);
   Dart_Handle library = Dart_LookupLibrary(url);
   if (!Dart_IsError(library)) {
-    Dart_SetNativeResolver(library, VmServiceIONativeResolver, NULL);
+    Dart_SetNativeResolver(library, VmServiceIONativeResolver,
+                           VmServiceIONativeSymbol);
   }
 }
 
@@ -120,7 +133,8 @@
   SHUTDOWN_ON_ERROR(library);
   result = Dart_SetRootLibrary(library);
   SHUTDOWN_ON_ERROR(library);
-  result = Dart_SetNativeResolver(library, VmServiceIONativeResolver, NULL);
+  result = Dart_SetNativeResolver(library, VmServiceIONativeResolver,
+                                  VmServiceIONativeSymbol);
   SHUTDOWN_ON_ERROR(result);
 
   // Make runnable.
diff --git a/runtime/configs.gni b/runtime/configs.gni
index b678f17..a476622 100644
--- a/runtime/configs.gni
+++ b/runtime/configs.gni
@@ -36,16 +36,6 @@
       "$_dart_runtime:dart_product_config",
     ]
 
-_precompiler_config = _base_config + [
-                        "$_dart_runtime:dart_maybe_product_config",
-                        "$_dart_runtime:dart_precompiler_config",
-                      ]
-
-_precompiler_product_config = _base_config + [
-                                "$_dart_runtime:dart_product_config",
-                                "$_dart_runtime:dart_precompiler_config",
-                              ]
-
 _nosnapshot_precompiler_base = [
   "$_dart_runtime:dart_nosnapshot_config",
   "$_dart_runtime:dart_precompiler_config",
@@ -85,16 +75,6 @@
     snapshot = true
   },
   {
-    suffix = "_with_precompiler"
-    configs = _precompiler_config
-    snapshot = true
-  },
-  {
-    suffix = "_with_precompiler_product"
-    configs = _precompiler_product_config
-    snapshot = true
-  },
-  {
     suffix = "_nosnapshot_with_precompiler"
     configs = _nosnapshot_with_precompiler_config
     snapshot = false
diff --git a/runtime/vm/compiler/aot/entry_points_pragma.md b/runtime/docs/compiler/aot/entry_point_pragma.md
similarity index 75%
rename from runtime/vm/compiler/aot/entry_points_pragma.md
rename to runtime/docs/compiler/aot/entry_point_pragma.md
index dfdecfe..69cf760 100644
--- a/runtime/vm/compiler/aot/entry_points_pragma.md
+++ b/runtime/docs/compiler/aot/entry_point_pragma.md
@@ -1,15 +1,21 @@
-# Entry points @pragma annotations
+# `vm:entry-point` pragma
+
+The annotation `@pragma("vm:entry-point", ...)` **must** be placed on a class or
+member to indicate that it may be resolved, allocated or invoked directly from
+native or VM code _in AOT mode_.
+
+## Background
 
 Dart VM precompiler (AOT compiler) performs whole-program optimizations such as
-tree shaking in order to decrease size of the resulting compiled apps and
-improve their performance. Such optimizations assume that compiler can see the
-whole Dart program, and is able to discover and analyze all Dart functions and
-members which can be potentially executed at run time. While the Dart code is
-fully available for precompiler, native code of the embedder and native methods
-are out of reach of the compiler. Such native code can call back to Dart via
-native Dart API.
+tree shaking and type flow analysis (TFA) in order to decrease size of the
+resulting compiled apps and improve their performance. Such optimizations
+assume that compiler can see the whole Dart program, and is able to discover
+and analyse all Dart functions and members which can be potentially executed at
+run time. While the Dart code is fully available for precompiler, native code
+of the embedder and native methods are out of reach of the compiler. Such
+native code can call back to Dart via native Dart API.
 
-In order to aid precompiler, programmer can explicitly list entry points
+In order to guide precompiler, programmer **must** explicitly list entry points
 (roots) - Dart classes and members which are accessed from native code. Note
 that listing entry points is not optional: as long as program defines native
 methods which call into Dart, the entry points are required for the correctness
@@ -18,15 +24,11 @@
 In addition, when obfuscation is enabled, the precompiler needs to know which
 symbols need to be preserved to ensure they can be resolved from native code.
 
-# Pragma annotation
-
-The annotation `@pragma("vm:entry-point", ...)` can be placed on a class or
-member to indicate that it may be resolved, allocated or invoked directly from
-native or VM code.
+## Syntax
 
 The allowed uses of the annotation are as follows.
 
-## Classes
+### Classes
 
 Any one of the following forms may be attached to a class:
 
@@ -44,7 +46,7 @@
 this case, their name will survive obfuscation, but they won't have any
 allocation stubs.
 
-## Procedures
+### Procedures
 
 Any one of the following forms may be attached to a procedure (including
 getters, setters and constructors):
@@ -61,7 +63,7 @@
 procedure is a *generative* constructor, the enclosing class will also be marked
 for allocation from native or VM code.
 
-## Fields
+### Fields
 
 Any one of the following forms may be attached to a non-static field. The first
 three forms may be attached to static fields.
@@ -72,7 +74,7 @@
 @pragma("vm:entry-point", true/false)
 @pragma("vm:entry-point", !const bool.formEnvironment("dart.vm.product"))
 @pragma("vm:entry-point", "get"/"set")
-void foo() { ... }
+int foo;
 ```
 
 If the second parameter is missing, `null` or `true, the field is marked for
diff --git a/runtime/docs/compiler/frontend/testing_trace_entrypoints_pragma.md b/runtime/docs/compiler/frontend/testing_trace_entrypoints_pragma.md
new file mode 100644
index 0000000..fe4e8b0
--- /dev/null
+++ b/runtime/docs/compiler/frontend/testing_trace_entrypoints_pragma.md
@@ -0,0 +1,31 @@
+# `vm:testing.unsafe.trace-entrypoints-fn` pragma
+
+This pragma is used for testing purposes in the test suite.
+
+Example:
+
+```dart
+void hook(String functionName, int entryPointId) {
+  // ...
+}
+
+class C<T> {
+  @pragma('vm:testing.unsafe.trace-entrypoints-fn', hook)
+  void foo(T x) {
+    // ...
+  }
+}
+```
+
+When `foo` is invoked, `hook` will be called in `foo`'s prologue if `foo` was
+compiled with multiple entry points. `hook` will be passed the name of the
+function it was called for and the ID of the entry point used for the
+invocation:
+
+- 0: Normal entry.
+
+- 1: Unchecked entry: prologue was short so separate prologues for normal and
+  unchecked entry were compiled.
+
+- 2: Unchecked shared entry: prologue was long, so normal and unchecked entry
+  set a temporary and type-checks are predicated on the temporary.
diff --git a/runtime/docs/compiler/result_type_pragma.md b/runtime/docs/compiler/result_type_pragma.md
new file mode 100644
index 0000000..2bc5032
--- /dev/null
+++ b/runtime/docs/compiler/result_type_pragma.md
@@ -0,0 +1,42 @@
+# `vm:exact-result-type` pragma
+
+To facilitate type-flow analysis and other optimizations, Dart methods may use
+the pragma `vm:exact-result-type` to declare an exact return type different than
+the return type in the signature of the method. There are three limitations on
+this pragma:
+
+0. The Dart object returned by the method at runtime must have exactly the type
+specified in the annotation (not a subtype).
+
+1. The exact return type declared in the pragma must be a subtype of the return
+   type declared in the method signature.
+   Note that this restriction is not enforced automatically by the compiler.
+
+2. `vm:exact-result-type` may only be attached to methods in the `dart:*`
+   libraries.
+   This pragma can introduce unsafe behavior since it allows the compiler to
+   make stronger assumptions during optimization than what the sound strong-mode
+   type system allows, so it is only allowed in the core library where the Dart
+   VM team can ensure that it is not misused.
+
+If limitations 0 or 1 are violated, undefined behavior may result.
+Note that since `null` is an instance of the `Null` type, which is a subtype of any other, exactness of the annotated result type implies that the result must be non-null.
+
+## Syntax
+
+### Reference to type via type literal
+
+```dart
+class A {}
+class B extends A {}
+
+@pragma('vm:exact-result-type', B)
+A foo() native 'foo_impl';
+```
+
+### Reference to type via path
+
+```dart
+@pragma('vm:exact-result-type', 'dart:core#_Smi');
+int foo() native 'foo_impl';
+```
diff --git a/runtime/docs/infra/coredumps.md b/runtime/docs/infra/coredumps.md
new file mode 100644
index 0000000..e24a3b6
--- /dev/null
+++ b/runtime/docs/infra/coredumps.md
@@ -0,0 +1,208 @@
+# Crash Dumps Archiving
+
+Testing framework and buildbot/LUCI infrastructure have support for archiving
+crash dumps and crashed binaries for unexpected crashes for postmortem
+debugging.
+
+This feature is enabled by passing `--copy-coredumps` to `tools/test.py` and
+is supported on all three major OSes we run our tests on.
+
+Currently crash dump archiving should be enabled on the majority of the VM
+bots, including those running in CQ.
+
+### Known limitations
+
+* We don't archive crash dumps produced by subprocesses (e.g. service tests);
+* We don't produce and archive crash dumps for hanged processes.
+
+### Maintainers
+
+For any questions about this infrastructure contact vegorov@, kustermann@ or
+athom@.
+
+## Downloading dumps
+
+To find if a bot managed to upload any crashdumps open its log and search for
+`Archiving coredumps for crash`. Depending on the bot configuration you
+might need to look for uploaded artifacts in two different locations.
+
+### Isolate Server
+
+Swarming bots upload dumps to the isolate server. In this case you will see
+something like this in the log:
+
+```
+INFO: Core dump archiving is activated
+Archiving coredumps for crash (if possible):
+----> Crash(language_2/call_method_implicit_tear_off_test/02: binary.release_x64_dart.exe 1556)
++++ Copying 6e3e4b40-206e-4ae6-99e8-c2c94cc21a98.dmp.tar.gz to output_directory (C:\b\s\w\ioz_p_ei)
++++ Copying release_x64_dart.exe.tar.gz to output_directory (C:\b\s\w\ioz_p_ei)
+```
+
+If you see `+++ Copying ... to output_directory` this means that the bot
+is using isolate storage. In this case you need to look for
+`shard #... isolated out` link under the failed step.
+
+![shard isolate out](images/isolated-out-link.png)
+
+This link would bring you to isolate server file browser where you will be
+able to download archived artifacts.
+
+![Isolate Server Browser](images/isolated-out-browser.png)
+
+### Cloud Storage
+
+Other bots upload collected artifacts into a `dart-temp-crash-archive` Cloud Storage bucket. In this case you will see
+`+++ Uploaded gs://dart-temp-crash-archive/...` in the output log. For example:
+
+```
+Archiving coredumps for crash (if possible):
+----> Crash(language_2/mixin_interface_check_test/mixin: binary.release_ia32_dart.exe 10620)
+
+--- Uploading into gs://dart-temp-crash-archive/0da77e10-d349-4c45-a146-0ce052972b03/ (https://storage.cloud.google.com/dart-temp-crash-archive/0da77e10-d349-4c45-a146-0ce052972b03/) ---
+Running command:  ['C:\\b\\s\\w\\ir\\cache\\vpython\\2d366b\\Scripts\\python.exe', 'C:\\b\\s\\w\\ir\\cache\\builder\\sdk\\third_party\\gsutil\\gsutil', 'cp', 'release_ia32_dart.exe.tar.gz', 'gs://dart-temp-crash-archive/0da77e10-d349-4c45-a146-0ce052972b03/release_ia32_dart.exe.tar.gz']
++++ Uploaded gs://dart-temp-crash-archive/0da77e10-d349-4c45-a146-0ce052972b03/release_ia32_dart.exe.tar.gz (https://storage.cloud.google.com/dart-temp-crash-archive/0da77e10-d349-4c45-a146-0ce052972b03/release_ia32_dart.exe.tar.gz)
+Running command:  ['C:\\b\\s\\w\\ir\\cache\\vpython\\2d366b\\Scripts\\python.exe', 'C:\\b\\s\\w\\ir\\cache\\builder\\sdk\\third_party\\gsutil\\gsutil', 'cp', 'a92618b1-0f99-4c87-a9fb-adb3e44ad458.dmp.tar.gz', 'gs://dart-temp-crash-archive/0da77e10-d349-4c45-a146-0ce052972b03/a92618b1-0f99-4c87-a9fb-adb3e44ad458.dmp.tar.gz']
++++ Uploaded gs://dart-temp-crash-archive/0da77e10-d349-4c45-a146-0ce052972b03/a92618b1-0f99-4c87-a9fb-adb3e44ad458.dmp.tar.gz (https://storage.cloud.google.com/dart-temp-crash-archive/0da77e10-d349-4c45-a146-0ce052972b03/a92618b1-0f99-4c87-a9fb-adb3e44ad458.dmp.tar.gz)
+--- Done ---
+```
+
+In this case you can use `gsutil.py` from `depot_tools` (or `gsutil` from Cloud
+SDK) to download these artifacts:
+
+```console
+$ gsutil.py cp gs://dart-temp-crash-archive/<src-path> <dst-path>
+```
+
+## Analyzing Dumps
+
+### Linux
+
+```console
+$ gdb <binary> <core>
+```
+
+Because bots are running slightly different Linux versions that what is
+available on development machines `gdb` might not be able to properly
+resolve symbols and unwind the stack by itself.
+
+In this case you can:
+
+* spin up a Cloud Instance with a matching OS version and debug the dump
+on that instance;
+* create a sysroot that matches operating system on the bots and tell gdb to
+use that sysroot with `set sysroot` command.
+
+#### ARM/ARM64
+
+If you have a core produced on ARM or ARM64 bot and you would like to inspect
+it on a non-ARM development machine, then you will need `gdb-multiarch` and
+sysroot that matches OS version on the bot. Then you can use `set sysroot ...`
+and `set architecture ...` to configure `gdb-multiarch` before loading `core`.
+
+### Mac
+
+```console
+$ lldb <binary> -c <core>
+```
+
+### Windows
+
+Googlers can find WinDBG and CDB in `%depot_tools%\win_toolchain\vs_files\%toolchain_version%\win_sdk\Debuggers\x64\`.
+
+For quick investigation you can do
+
+```console
+> cdb.exe -z <coredump.dmp>
+...
+0:000> !uniqstack
+...
+```
+
+## Implementation details
+
+Implementation of crash dump archiving consists of two parts:
+
+* Code in the testing framework (`UnexpectedCrashLogger` in
+`tools/testing/dart/test_progress.dart`) that detects unexpected crashes, that
+is situations when test _unexpectedly_ completes with a `Crash` status. In this
+case it logs a line about this crash into `unexpected-crashes` file in the
+root of the SDK checkout. This line has format `test,pid,binary` and identifies
+which test crashed, what was the process id and which binary crashed.
+* Code in the Python wrapper around testing framework (see `CoreDumpArchiver`
+in `tools/utils.py`) is responsible for
+    * Before tests: configuring OS and/or environment to setup crashdump
+      archiving in the OS specific way (see classes with names ending at
+      `CoreDumpEnabler`);
+    * After tests: trying to locate crashdumps written by OS or crash reporting
+      library and match those to unexpected crashes reporting by testing
+      framework (see classes with names ending at `CoreDumpArchiver`);
+    * Selecting a subset of crashdumps and uploading those into a persistent
+      storage (isolate server or Cloud Storage bucket).
+
+### Linux
+
+We rely on builtin ability of the OS to generate core files (`man core`) when
+the program is terminated abnormally.
+
+We adjust core resource limits to `unlimited` before running tests. See `man setrlimit` for more information (search for `RLIMIT_CORE`).
+
+We verify that `/proc/sys/kernel/core_pattern` is set to `core.%p` which
+means that crash dumps would be produced in the current working directory (root of the SDK checkout for most tests) and mangled with the pid of the crashed
+process.
+
+Core dump archiving code then uses pids to match unexpected crashes with core
+dumps.
+
+See `LinuxCoreDumpArchiver` and `LinuxCoreDumpEnabler` in `tools/utils.py`.
+
+### Mac
+
+Just like on Linux we rely on OS to produce core files (`man core`) and
+similarly set core resource limits to `unlimited`.
+
+Core files are also mangled with PID of the crashing process.
+
+The only difference from Linux is that on Mac core files are written into
+`/cores` directory instead of current working directory.
+
+See `MacOSCoreDumpArchiver` and `PosixCoreDumpEnabler` in `tools/utils.py`.
+
+### Windows
+
+On Windows we rely on [Crashpad](https://chromium.googlesource.com/crashpad/crashpad/+/master/README.md)
+library to produce minidumps of the crashed process, because configuring
+builtin crash reporting functionality requires registry changes that are global,
+impossible without Administrator privileges and are overwritten by buildbot
+fleet management software running in background.
+
+Crashpad integration for `dart.exe` and `run_vm_tests.exe` binaries is
+controlled by `dart_use_crashpad` GN argument.
+
+This argument is set to `true` when `tools/gn.py` is run with `--use-crashpad`
+flag or with `DART_USE_CRASHPAD` environment variable set.
+
+If the binary is built with Crashpad integration it checks two environment
+variables on startup:
+
+* `DART_CRASHPAD_HANDLER` should contain path to `crashpad_handler.exe`
+Crashpad binary that implements out-of-process crash monitoring;
+* `DART_CRASHPAD_CRASHES_DIR` should contain path to a folder, which would be
+used as Crashpad crash database.
+
+If both variables are set then Crashpad handler will be started. If the handler
+catches main binary crashing it would write [minidump](https://docs.microsoft.com/en-us/windows/desktop/debug/minidump-files)
+into `%DART_CRASHPAD_CRASHES_DIR%\crashes` from where it would be picked up
+by crash archiving machinery.
+
+We match crash dumps to unexpected crashes by parsing them and extracting
+process id of the crashed process (see `utils/minidump.py` library).
+
+See `WindowsCoreDumpEnabler` and `WindowsCoreDumpArchiver` in `tools/utils.py`.
+
+**Note: `DART_CRASHPAD_CRASHES_DIR` is set by `WindowsCoreDumpEnabler` in
+`tools/utils.py`, while `DART_CRASHPAD_HANDLER` is set by `TestSuite` in
+`tools/testing/dart/test_suite.dart`.**
+
+**Note: Crashpad is optimized for end-user crash reporting use case and does not write full crash dumps.**
+
diff --git a/runtime/docs/infra/images/isolated-out-browser.png b/runtime/docs/infra/images/isolated-out-browser.png
new file mode 100644
index 0000000..cdf37ab
--- /dev/null
+++ b/runtime/docs/infra/images/isolated-out-browser.png
Binary files differ
diff --git a/runtime/docs/infra/images/isolated-out-link.png b/runtime/docs/infra/images/isolated-out-link.png
new file mode 100644
index 0000000..a996098
--- /dev/null
+++ b/runtime/docs/infra/images/isolated-out-link.png
Binary files differ
diff --git a/runtime/docs/pragmas.md b/runtime/docs/pragmas.md
index c739826..a896592 100644
--- a/runtime/docs/pragmas.md
+++ b/runtime/docs/pragmas.md
@@ -4,19 +4,17 @@
 
 These pragmas are part of the VM's API and are safe for use in external code.
 
-- **vm:entry-point**
-
-  [Defining entry-points into Dart code for an embedder or native methods]
-  (file://../vm/compiler/aot/entry_points_pragma.md)
+| Pragma | Meaning |
+| --- | --- |
+| `vm:entry-point` | [Defining entry-points into Dart code for an embedder or native methods](compiler/aot/entry_point_pragma.md) |
 
 ## Pragmas for internal use
 
 These pragmas can cause unsound behavior if used incorrectly and therefore are only allowed within the core SDK libraries.
 
-- **vm:exact-result-type**
-
-  [Declaring an exact result type of a method]
-  (file://../vm/compiler/result_type_pragma.md)
+| Pragma | Meaning |
+| --- | --- |
+| `vm:exact-result-type` | [Declaring an exact result type of a method](compiler/result_type_pragma.md) |
 
 ## Pragmas for internal testing
 
@@ -25,7 +23,6 @@
 The names of these pragmas are prefixed with "testing".
 Additionally, they are categorized into "safe" and "unsafe" forms: "safe" pragmas should not affect the behavior of the program and can be safely added anywhere, whereas "unsafe" pragmas may change the code's behavior or may cause the VM to crash if used improperly.
 
-- **vm:testing.unsafe.trace-entrypoints-fn**
-
-  [Observing which flow-graph-level entry-point was used when a function was called]
-  (file://../vm/compiler/frontend/entrypoints_pragma.md)
+| Pragma | Meaning |
+| --- | --- |
+| `vm:testing.unsafe.trace-entrypoints-fn` | [Observing which flow-graph-level entry-point was used when a function was called](compiler/frontend/testing_trace_entrypoints_pragma.md) |
diff --git a/runtime/include/dart_tools_api.h b/runtime/include/dart_tools_api.h
index 5452c25..809177b 100644
--- a/runtime/include/dart_tools_api.h
+++ b/runtime/include/dart_tools_api.h
@@ -5,7 +5,7 @@
 #ifndef RUNTIME_INCLUDE_DART_TOOLS_API_H_
 #define RUNTIME_INCLUDE_DART_TOOLS_API_H_
 
-#include "include/dart_api.h"
+#include "dart_api.h"
 
 /** \mainpage Dart Tools Embedding API Reference
  *
diff --git a/runtime/lib/array.cc b/runtime/lib/array.cc
index e2c0998..3322745 100644
--- a/runtime/lib/array.cc
+++ b/runtime/lib/array.cc
@@ -23,7 +23,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(List_getIndexed, 2) {
-  const Array& array = Array::CheckedHandle(arguments->NativeArgAt(0));
+  const Array& array = Array::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
   if ((index.Value() < 0) || (index.Value() >= array.Length())) {
     Exceptions::ThrowRangeError("index", index, 0, array.Length() - 1);
@@ -32,9 +32,10 @@
 }
 
 DEFINE_NATIVE_ENTRY(List_setIndexed, 3) {
-  const Array& array = Array::CheckedHandle(arguments->NativeArgAt(0));
+  const Array& array = Array::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
-  const Instance& value = Instance::CheckedHandle(arguments->NativeArgAt(2));
+  const Instance& value =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(2));
   if ((index.Value() < 0) || (index.Value() >= array.Length())) {
     Exceptions::ThrowRangeError("index", index, 0, array.Length() - 1);
   }
@@ -43,13 +44,13 @@
 }
 
 DEFINE_NATIVE_ENTRY(List_getLength, 1) {
-  const Array& array = Array::CheckedHandle(arguments->NativeArgAt(0));
+  const Array& array = Array::CheckedHandle(zone, arguments->NativeArgAt(0));
   return Smi::New(array.Length());
 }
 
 // ObjectArray src, int start, int count, bool needTypeArgument.
 DEFINE_NATIVE_ENTRY(List_slice, 4) {
-  const Array& src = Array::CheckedHandle(arguments->NativeArgAt(0));
+  const Array& src = Array::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, start, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, count, arguments->NativeArgAt(2));
   GET_NON_NULL_NATIVE_ARGUMENT(Bool, needs_type_arg, arguments->NativeArgAt(3));
@@ -71,9 +72,10 @@
 // Private factory, expects correct arguments.
 DEFINE_NATIVE_ENTRY(ImmutableList_from, 4) {
   // Ignore first argument of a thsi factory (type argument).
-  const Array& from_array = Array::CheckedHandle(arguments->NativeArgAt(1));
-  const Smi& smi_offset = Smi::CheckedHandle(arguments->NativeArgAt(2));
-  const Smi& smi_length = Smi::CheckedHandle(arguments->NativeArgAt(3));
+  const Array& from_array =
+      Array::CheckedHandle(zone, arguments->NativeArgAt(1));
+  const Smi& smi_offset = Smi::CheckedHandle(zone, arguments->NativeArgAt(2));
+  const Smi& smi_length = Smi::CheckedHandle(zone, arguments->NativeArgAt(3));
   const intptr_t length = smi_length.Value();
   const intptr_t offset = smi_offset.Value();
   const Array& result = Array::Handle(Array::New(length));
diff --git a/runtime/lib/array.dart b/runtime/lib/array.dart
index 2e93901..3797c4a 100644
--- a/runtime/lib/array.dart
+++ b/runtime/lib/array.dart
@@ -65,6 +65,30 @@
     }
   }
 
+  void setAll(int index, Iterable<E> iterable) {
+    if (index < 0 || index > this.length) {
+      throw new RangeError.range(index, 0, this.length, "index");
+    }
+    List<E> iterableAsList;
+    if (identical(this, iterable)) {
+      iterableAsList = this;
+    } else if (ClassID.getID(iterable) == ClassID.cidArray) {
+      iterableAsList = iterable;
+    } else if (iterable is List<E>) {
+      iterableAsList = iterable;
+    } else {
+      for (var value in iterable) {
+        this[index++] = value;
+      }
+      return;
+    }
+    int length = iterableAsList.length;
+    if (index + length > this.length) {
+      throw new RangeError.range(index + length, 0, this.length);
+    }
+    Lists.copy(iterableAsList, 0, this, index, length);
+  }
+
   List<E> sublist(int start, [int end]) {
     end = RangeError.checkValidRange(start, end, this.length);
     int length = end - start;
diff --git a/runtime/lib/async_patch.dart b/runtime/lib/async_patch.dart
index 0cd4bd8..c293221 100644
--- a/runtime/lib/async_patch.dart
+++ b/runtime/lib/async_patch.dart
@@ -200,8 +200,7 @@
     // If stream is cancelled, tell caller to exit the async generator.
     if (!controller.hasListener) return true;
     isAdding = true;
-    var whenDoneAdding =
-        controller.addStream(stream as Stream<T>, cancelOnError: false);
+    var whenDoneAdding = controller.addStream(stream, cancelOnError: false);
     whenDoneAdding.then((_) {
       isAdding = false;
       scheduleGenerator();
diff --git a/runtime/lib/bigint_patch.dart b/runtime/lib/bigint_patch.dart
index 0ae7425..0341923 100644
--- a/runtime/lib/bigint_patch.dart
+++ b/runtime/lib/bigint_patch.dart
@@ -2572,9 +2572,6 @@
   //   args[_rhoDigit.._rhoHighDigit] =
   //     1/args[_xDigit.._xHighDigit] mod _digitBase^2.
   static void _invDigitPair(Uint32List args) {
-    var two = _BigIntImpl.two;
-    var mask32 = _BigIntImpl._oneDigitMask;
-    var mask64 = _BigIntImpl._twoDigitMask;
     var xl = args[_xDigit]; // Lower 32-bit digit of x.
     var y = xl & 3; // y == 1/x mod 2^2
     y = (y * (2 - (xl & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
diff --git a/runtime/lib/collection_patch.dart b/runtime/lib/collection_patch.dart
index 05cf6e1..664f619 100644
--- a/runtime/lib/collection_patch.dart
+++ b/runtime/lib/collection_patch.dart
@@ -34,17 +34,11 @@
             identical(identical, equals)) {
           return new _IdentityHashMap<K, V>();
         }
-        if (equals == null) {
-          equals = _defaultEquals;
-        }
+        equals ??= _defaultEquals;
       }
     } else {
-      if (hashCode == null) {
-        hashCode = _defaultHashCode;
-      }
-      if (equals == null) {
-        equals = _defaultEquals;
-      }
+      hashCode ??= _defaultHashCode;
+      equals ??= _defaultEquals;
     }
     return new _CustomHashMap<K, V>(equals, hashCode, isValidKey);
   }
@@ -536,17 +530,11 @@
             identical(identical, equals)) {
           return new _IdentityHashSet<E>();
         }
-        if (equals == null) {
-          equals = _defaultEquals;
-        }
+        equals ??= _defaultEquals;
       }
     } else {
-      if (hashCode == null) {
-        hashCode = _defaultHashCode;
-      }
-      if (equals == null) {
-        equals = _defaultEquals;
-      }
+      hashCode ??= _defaultHashCode;
+      equals ??= _defaultEquals;
     }
     return new _CustomHashSet<E>(equals, hashCode, isValidKey);
   }
@@ -637,9 +625,7 @@
   }
 
   void addAll(Iterable<E> objects) {
-    int ctr = 0;
     for (E object in objects) {
-      ctr++;
       add(object);
     }
   }
@@ -879,17 +865,11 @@
             identical(identical, equals)) {
           return new _CompactLinkedIdentityHashMap<K, V>();
         }
-        if (equals == null) {
-          equals = _defaultEquals;
-        }
+        equals ??= _defaultEquals;
       }
     } else {
-      if (hashCode == null) {
-        hashCode = _defaultHashCode;
-      }
-      if (equals == null) {
-        equals = _defaultEquals;
-      }
+      hashCode ??= _defaultHashCode;
+      equals ??= _defaultEquals;
     }
     return new _CompactLinkedCustomHashMap<K, V>(equals, hashCode, isValidKey);
   }
@@ -916,17 +896,11 @@
             identical(identical, equals)) {
           return new _CompactLinkedIdentityHashSet<E>();
         }
-        if (equals == null) {
-          equals = _defaultEquals;
-        }
+        equals ??= _defaultEquals;
       }
     } else {
-      if (hashCode == null) {
-        hashCode = _defaultHashCode;
-      }
-      if (equals == null) {
-        equals = _defaultEquals;
-      }
+      hashCode ??= _defaultHashCode;
+      equals ??= _defaultEquals;
     }
     return new _CompactLinkedCustomHashSet<E>(equals, hashCode, isValidKey);
   }
diff --git a/runtime/lib/compact_hash.dart b/runtime/lib/compact_hash.dart
index c374ec6..20ddf7a 100644
--- a/runtime/lib/compact_hash.dart
+++ b/runtime/lib/compact_hash.dart
@@ -256,7 +256,6 @@
 
   void operator []=(K key, V value) {
     final int size = _index.length;
-    final int sizeMask = size - 1;
     final int fullHash = _hashCode(key);
     final int hashPattern = _HashBase._hashPattern(fullHash, _hashMask, size);
     final int d = _findValueOrInsertPoint(key, fullHash, hashPattern, size);
@@ -270,8 +269,6 @@
 
   V putIfAbsent(K key, V ifAbsent()) {
     final int size = _index.length;
-    final int sizeMask = size - 1;
-    final int maxEntries = size >> 1;
     final int fullHash = _hashCode(key);
     final int hashPattern = _HashBase._hashPattern(fullHash, _hashMask, size);
     final int d = _findValueOrInsertPoint(key, fullHash, hashPattern, size);
diff --git a/runtime/lib/convert_patch.dart b/runtime/lib/convert_patch.dart
index 6ba8444..0802cbb 100644
--- a/runtime/lib/convert_patch.dart
+++ b/runtime/lib/convert_patch.dart
@@ -177,7 +177,6 @@
   }
 
   void arrayElement() {
-    List list = currentContainer;
     currentContainer.add(value);
     value = null;
   }
diff --git a/runtime/lib/date_patch.dart b/runtime/lib/date_patch.dart
index 481cb16..1899e0c 100644
--- a/runtime/lib/date_patch.dart
+++ b/runtime/lib/date_patch.dart
@@ -57,7 +57,7 @@
   @patch
   DateTime._now()
       : isUtc = false,
-        _value = _getCurrentMicros() {}
+        _value = _getCurrentMicros();
 
   @patch
   String get timeZoneName {
@@ -72,6 +72,26 @@
     return new Duration(seconds: offsetInSeconds);
   }
 
+  @patch
+  bool operator ==(dynamic other) =>
+      other is DateTime &&
+      _value == other.microsecondsSinceEpoch &&
+      isUtc == other.isUtc;
+
+  @patch
+  bool isBefore(DateTime other) => _value < other.microsecondsSinceEpoch;
+
+  @patch
+  bool isAfter(DateTime other) => _value > other.microsecondsSinceEpoch;
+
+  @patch
+  bool isAtSameMomentAs(DateTime other) =>
+      _value == other.microsecondsSinceEpoch;
+
+  @patch
+  int compareTo(DateTime other) =>
+      _value.compareTo(other.microsecondsSinceEpoch);
+
   /** The first list contains the days until each month in non-leap years. The
     * second list contains the days in leap years. */
   static const List<List<int>> _DAYS_UNTIL_MONTH = const [
@@ -160,9 +180,7 @@
   }
 
   get _parts {
-    if (__parts == null) {
-      __parts = _computeUpperPart(_localDateInUtcMicros);
-    }
+    __parts ??= _computeUpperPart(_localDateInUtcMicros);
     return __parts;
   }
 
diff --git a/runtime/lib/developer.dart b/runtime/lib/developer.dart
index 96577e1..12ad8b7 100644
--- a/runtime/lib/developer.dart
+++ b/runtime/lib/developer.dart
@@ -35,9 +35,7 @@
   if (message is! String) {
     throw new ArgumentError.value(message, "message", "Must be a String");
   }
-  if (time == null) {
-    time = new DateTime.now();
-  }
+  time ??= new DateTime.now();
   if (time is! DateTime) {
     throw new ArgumentError.value(time, "time", "Must be a DateTime");
   }
diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc
index 3aaeaa9..eb24241 100644
--- a/runtime/lib/double.cc
+++ b/runtime/lib/double.cc
@@ -17,11 +17,11 @@
 
 namespace dart {
 
-DECLARE_FLAG(bool, trace_intrinsified_natives);
-
 DEFINE_NATIVE_ENTRY(Double_doubleFromInteger, 2) {
-  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
-  const Integer& value = Integer::CheckedHandle(arguments->NativeArgAt(1));
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
+  const Integer& value =
+      Integer::CheckedHandle(zone, arguments->NativeArgAt(1));
   if (FLAG_trace_intrinsified_natives) {
     OS::PrintErr("Double_doubleFromInteger %s\n", value.ToCString());
   }
@@ -29,7 +29,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Double_add, 2) {
-  double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
+  double left = Double::CheckedHandle(zone, arguments->NativeArgAt(0)).value();
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
@@ -39,7 +39,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Double_sub, 2) {
-  double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
+  double left = Double::CheckedHandle(zone, arguments->NativeArgAt(0)).value();
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
@@ -49,7 +49,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Double_mul, 2) {
-  double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
+  double left = Double::CheckedHandle(zone, arguments->NativeArgAt(0)).value();
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
@@ -59,7 +59,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Double_div, 2) {
-  double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
+  double left = Double::CheckedHandle(zone, arguments->NativeArgAt(0)).value();
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
@@ -86,7 +86,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Double_hashCode, 1) {
-  double val = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
+  double val = Double::CheckedHandle(zone, arguments->NativeArgAt(0)).value();
   if (FLAG_trace_intrinsified_natives) {
     OS::PrintErr("Double_hashCode %f\n", val);
   }
@@ -103,7 +103,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Double_trunc_div, 2) {
-  double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
+  double left = Double::CheckedHandle(zone, arguments->NativeArgAt(0)).value();
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
@@ -114,21 +114,21 @@
 }
 
 DEFINE_NATIVE_ENTRY(Double_modulo, 2) {
-  double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
+  double left = Double::CheckedHandle(zone, arguments->NativeArgAt(0)).value();
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   return Double::New(DartModulo(left, right));
 }
 
 DEFINE_NATIVE_ENTRY(Double_remainder, 2) {
-  double left = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
+  double left = Double::CheckedHandle(zone, arguments->NativeArgAt(0)).value();
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   return Double::New(fmod_ieee(left, right));
 }
 
 DEFINE_NATIVE_ENTRY(Double_greaterThan, 2) {
-  const Double& left = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& left = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right, arguments->NativeArgAt(1));
   bool result = right.IsNull() ? false : (left.value() > right.value());
   if (FLAG_trace_intrinsified_natives) {
@@ -139,13 +139,13 @@
 }
 
 DEFINE_NATIVE_ENTRY(Double_greaterThanFromInteger, 2) {
-  const Double& right = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& right = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
   return Bool::Get(left.AsDoubleValue() > right.value()).raw();
 }
 
 DEFINE_NATIVE_ENTRY(Double_equal, 2) {
-  const Double& left = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& left = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right, arguments->NativeArgAt(1));
   bool result = right.IsNull() ? false : (left.value() == right.value());
   if (FLAG_trace_intrinsified_natives) {
@@ -156,28 +156,28 @@
 }
 
 DEFINE_NATIVE_ENTRY(Double_equalToInteger, 2) {
-  const Double& left = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& left = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, right, arguments->NativeArgAt(1));
   return Bool::Get(left.value() == right.AsDoubleValue()).raw();
 }
 
 DEFINE_NATIVE_ENTRY(Double_round, 1) {
-  const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   return Double::New(round(arg.value()));
 }
 
 DEFINE_NATIVE_ENTRY(Double_floor, 1) {
-  const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   return Double::New(floor(arg.value()));
 }
 
 DEFINE_NATIVE_ENTRY(Double_ceil, 1) {
-  const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   return Double::New(ceil(arg.value()));
 }
 
 DEFINE_NATIVE_ENTRY(Double_truncate, 1) {
-  const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   return Double::New(trunc(arg.value()));
 }
 
@@ -187,7 +187,7 @@
 #endif
 
 DEFINE_NATIVE_ENTRY(Double_toInt, 1) {
-  const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   return DoubleToInteger(arg.value(), "Infinity or NaN toInt");
 }
 
@@ -211,7 +211,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Double_toString, 1) {
-  const Number& number = Number::CheckedHandle(arguments->NativeArgAt(0));
+  const Number& number = Number::CheckedHandle(zone, arguments->NativeArgAt(0));
   return number.ToString(Heap::kNew);
 }
 
@@ -220,7 +220,7 @@
   static const double kLowerBoundary = -1e21;
   static const double kUpperBoundary = 1e21;
 
-  const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, fraction_digits, arguments->NativeArgAt(1));
   double d = arg.value();
   intptr_t fraction_digits_value = fraction_digits.Value();
@@ -235,7 +235,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Double_toStringAsExponential, 2) {
-  const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, fraction_digits, arguments->NativeArgAt(1));
   double d = arg.value();
   intptr_t fraction_digits_value = fraction_digits.Value();
@@ -250,7 +250,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Double_toStringAsPrecision, 2) {
-  const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, precision, arguments->NativeArgAt(1));
   double d = arg.value();
   intptr_t precision_value = precision.Value();
@@ -264,24 +264,24 @@
 }
 
 DEFINE_NATIVE_ENTRY(Double_getIsInfinite, 1) {
-  const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   return Bool::Get(isinf(arg.value())).raw();
 }
 
 DEFINE_NATIVE_ENTRY(Double_getIsNaN, 1) {
-  const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   return Bool::Get(isnan(arg.value())).raw();
 }
 
 DEFINE_NATIVE_ENTRY(Double_getIsNegative, 1) {
-  const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   // Include negative zero, infinity.
   double dval = arg.value();
   return Bool::Get(signbit(dval) && !isnan(dval)).raw();
 }
 
 DEFINE_NATIVE_ENTRY(Double_flipSignBit, 1) {
-  const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0));
+  const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   const double in_val = arg.value();
   const int64_t bits = bit_cast<int64_t, double>(in_val) ^ kSignBitDouble;
   return Double::New(bit_cast<double, int64_t>(bits));
diff --git a/runtime/lib/errors.cc b/runtime/lib/errors.cc
index c0dc588..22c1130 100644
--- a/runtime/lib/errors.cc
+++ b/runtime/lib/errors.cc
@@ -30,29 +30,33 @@
       Class::Handle(Library::LookupCoreClass(Symbols::AssertionError()));
   ASSERT(!assert_error_class.IsNull());
   bool hit_assertion_error = false;
-  while (stack_frame != NULL) {
-    code ^= stack_frame->LookupDartCode();
-    if (code.is_optimized()) {
-      InlinedFunctionsIterator inlined_iterator(code, stack_frame->pc());
-      while (!inlined_iterator.Done()) {
-        func ^= inlined_iterator.function();
-        if (hit_assertion_error) {
-          return func.script();
-        }
-        ASSERT(!hit_assertion_error);
-        hit_assertion_error = (func.Owner() == assert_error_class.raw());
-        inlined_iterator.Advance();
-      }
+  for (; stack_frame != NULL; stack_frame = iterator->NextFrame()) {
+    if (stack_frame->is_interpreted()) {
+      func = stack_frame->LookupDartFunction();
     } else {
-      func ^= code.function();
-      ASSERT(!func.IsNull());
-      if (hit_assertion_error) {
-        return func.script();
+      code ^= stack_frame->LookupDartCode();
+      if (code.is_optimized()) {
+        InlinedFunctionsIterator inlined_iterator(code, stack_frame->pc());
+        while (!inlined_iterator.Done()) {
+          func ^= inlined_iterator.function();
+          if (hit_assertion_error) {
+            return func.script();
+          }
+          ASSERT(!hit_assertion_error);
+          hit_assertion_error = (func.Owner() == assert_error_class.raw());
+          inlined_iterator.Advance();
+        }
+        continue;
+      } else {
+        func = code.function();
       }
-      ASSERT(!hit_assertion_error);
-      hit_assertion_error = (func.Owner() == assert_error_class.raw());
     }
-    stack_frame = iterator->NextFrame();
+    ASSERT(!func.IsNull());
+    if (hit_assertion_error) {
+      return func.script();
+    }
+    ASSERT(!hit_assertion_error);
+    hit_assertion_error = (func.Owner() == assert_error_class.raw());
   }
   UNREACHABLE();
   return Script::null();
@@ -67,13 +71,14 @@
 DEFINE_NATIVE_ENTRY(AssertionError_throwNew, 3) {
   // No need to type check the arguments. This function can only be called
   // internally from the VM.
-  const TokenPosition assertion_start =
-      TokenPosition(Smi::CheckedHandle(arguments->NativeArgAt(0)).Value());
-  const TokenPosition assertion_end =
-      TokenPosition(Smi::CheckedHandle(arguments->NativeArgAt(1)).Value());
+  const TokenPosition assertion_start = TokenPosition(
+      Smi::CheckedHandle(zone, arguments->NativeArgAt(0)).Value());
+  const TokenPosition assertion_end = TokenPosition(
+      Smi::CheckedHandle(zone, arguments->NativeArgAt(1)).Value());
 
-  const Instance& message = Instance::CheckedHandle(arguments->NativeArgAt(2));
-  const Array& args = Array::Handle(Array::New(5));
+  const Instance& message =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(2));
+  const Array& args = Array::Handle(zone, Array::New(5));
 
   DartFrameIterator iterator(thread,
                              StackFrameIterator::kNoCrossThreadIteration);
@@ -112,14 +117,16 @@
 DEFINE_NATIVE_ENTRY(TypeError_throwNew, 5) {
   // No need to type check the arguments. This function can only be called
   // internally from the VM.
-  const TokenPosition location =
-      TokenPosition(Smi::CheckedHandle(arguments->NativeArgAt(0)).Value());
+  const TokenPosition location = TokenPosition(
+      Smi::CheckedHandle(zone, arguments->NativeArgAt(0)).Value());
   const Instance& src_value =
-      Instance::CheckedHandle(arguments->NativeArgAt(1));
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
   const AbstractType& dst_type =
-      AbstractType::CheckedHandle(arguments->NativeArgAt(2));
-  const String& dst_name = String::CheckedHandle(arguments->NativeArgAt(3));
-  const String& error_msg = String::CheckedHandle(arguments->NativeArgAt(4));
+      AbstractType::CheckedHandle(zone, arguments->NativeArgAt(2));
+  const String& dst_name =
+      String::CheckedHandle(zone, arguments->NativeArgAt(3));
+  const String& error_msg =
+      String::CheckedHandle(zone, arguments->NativeArgAt(4));
   const AbstractType& src_type =
       AbstractType::Handle(src_value.GetType(Heap::kNew));
   Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name,
diff --git a/runtime/lib/function.dart b/runtime/lib/function.dart
index 8a47f00..ae3902a 100644
--- a/runtime/lib/function.dart
+++ b/runtime/lib/function.dart
@@ -9,9 +9,7 @@
   bool operator ==(Object other) native "Closure_equals";
 
   int get hashCode {
-    if (_hash == null) {
-      _hash = _computeHash();
-    }
+    _hash ??= _computeHash();
     return _hash;
   }
 
diff --git a/runtime/lib/growable_array.cc b/runtime/lib/growable_array.cc
index 6f7f254..1d57b7a 100644
--- a/runtime/lib/growable_array.cc
+++ b/runtime/lib/growable_array.cc
@@ -13,7 +13,7 @@
 
 DEFINE_NATIVE_ENTRY(GrowableList_allocate, 2) {
   const TypeArguments& type_arguments =
-      TypeArguments::CheckedHandle(arguments->NativeArgAt(0));
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Array, data, arguments->NativeArgAt(1));
   if (data.Length() < 0) {
     Exceptions::ThrowRangeError("length",
@@ -29,18 +29,18 @@
 
 DEFINE_NATIVE_ENTRY(GrowableList_getIndexed, 2) {
   const GrowableObjectArray& array =
-      GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0));
+      GrowableObjectArray::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
   if ((index.Value() < 0) || (index.Value() >= array.Length())) {
     Exceptions::ThrowRangeError("index", index, 0, array.Length() - 1);
   }
-  const Instance& obj = Instance::CheckedHandle(array.At(index.Value()));
+  const Instance& obj = Instance::CheckedHandle(zone, array.At(index.Value()));
   return obj.raw();
 }
 
 DEFINE_NATIVE_ENTRY(GrowableList_setIndexed, 3) {
   const GrowableObjectArray& array =
-      GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0));
+      GrowableObjectArray::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
   if ((index.Value() < 0) || (index.Value() >= array.Length())) {
     Exceptions::ThrowRangeError("index", index, 0, array.Length() - 1);
@@ -52,19 +52,19 @@
 
 DEFINE_NATIVE_ENTRY(GrowableList_getLength, 1) {
   const GrowableObjectArray& array =
-      GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0));
+      GrowableObjectArray::CheckedHandle(zone, arguments->NativeArgAt(0));
   return Smi::New(array.Length());
 }
 
 DEFINE_NATIVE_ENTRY(GrowableList_getCapacity, 1) {
   const GrowableObjectArray& array =
-      GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0));
+      GrowableObjectArray::CheckedHandle(zone, arguments->NativeArgAt(0));
   return Smi::New(array.Capacity());
 }
 
 DEFINE_NATIVE_ENTRY(GrowableList_setLength, 2) {
   const GrowableObjectArray& array =
-      GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0));
+      GrowableObjectArray::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(1));
   ASSERT((length.Value() >= 0) && (length.Value() <= array.Capacity()));
   array.SetLength(length.Value());
@@ -73,7 +73,7 @@
 
 DEFINE_NATIVE_ENTRY(GrowableList_setData, 2) {
   const GrowableObjectArray& array =
-      GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0));
+      GrowableObjectArray::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Array, data, arguments->NativeArgAt(1));
   ASSERT(data.Length() >= 0);
   array.SetData(data);
diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart
index d23632f..0dbe008 100644
--- a/runtime/lib/growable_array.dart
+++ b/runtime/lib/growable_array.dart
@@ -224,7 +224,6 @@
     if (length == 1) return this[0];
     if (length == 0) throw IterableElementError.noElement();
     throw IterableElementError.tooMany();
-    ;
   }
 
   // Shared array used as backing for new empty growable arrays.
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index 3f1c653..1c8cf7c 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -16,11 +16,6 @@
 
 namespace dart {
 
-DEFINE_FLAG(bool,
-            trace_intrinsified_natives,
-            false,
-            "Report if any of the intrinsified natives are called");
-
 // Smi natives.
 
 // Returns false if integer is in wrong representation, e.g., as is a Mint
@@ -34,7 +29,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Integer_bitAndFromInteger, 2) {
-  const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0));
+  const Integer& right =
+      Integer::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right));
   ASSERT(CheckInteger(left));
@@ -46,7 +42,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Integer_bitOrFromInteger, 2) {
-  const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0));
+  const Integer& right =
+      Integer::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right));
   ASSERT(CheckInteger(left));
@@ -58,7 +55,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Integer_bitXorFromInteger, 2) {
-  const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0));
+  const Integer& right =
+      Integer::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right));
   ASSERT(CheckInteger(left));
@@ -70,7 +68,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Integer_addFromInteger, 2) {
-  const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0));
+  const Integer& right_int =
+      Integer::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right_int));
   ASSERT(CheckInteger(left_int));
@@ -82,7 +81,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Integer_subFromInteger, 2) {
-  const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0));
+  const Integer& right_int =
+      Integer::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right_int));
   ASSERT(CheckInteger(left_int));
@@ -94,7 +94,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Integer_mulFromInteger, 2) {
-  const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0));
+  const Integer& right_int =
+      Integer::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right_int));
   ASSERT(CheckInteger(left_int));
@@ -106,7 +107,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Integer_truncDivFromInteger, 2) {
-  const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0));
+  const Integer& right_int =
+      Integer::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right_int));
   ASSERT(CheckInteger(left_int));
@@ -115,7 +117,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Integer_moduloFromInteger, 2) {
-  const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0));
+  const Integer& right_int =
+      Integer::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right_int));
   ASSERT(CheckInteger(left_int));
@@ -131,7 +134,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Integer_greaterThanFromInteger, 2) {
-  const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0));
+  const Integer& right =
+      Integer::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right));
   ASSERT(CheckInteger(left));
@@ -143,7 +147,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Integer_equalToInteger, 2) {
-  const Integer& left = Integer::CheckedHandle(arguments->NativeArgAt(0));
+  const Integer& left = Integer::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, right, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(left));
   ASSERT(CheckInteger(right));
@@ -172,18 +176,7 @@
     }
   }
 
-  const String* int_string;
-  bool is_positive;
-  if (Scanner::IsValidInteger(value, &is_positive, &int_string)) {
-    if (is_positive) {
-      return Integer::New(*int_string);
-    }
-    String& temp = String::Handle();
-    temp = String::Concat(Symbols::Dash(), *int_string);
-    return Integer::New(temp);
-  }
-
-  return Integer::null();
+  return Integer::New(value);
 }
 
 DEFINE_NATIVE_ENTRY(Integer_parse, 1) {
@@ -219,7 +212,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Integer_shrFromInteger, 2) {
-  const Integer& amount = Integer::CheckedHandle(arguments->NativeArgAt(0));
+  const Integer& amount =
+      Integer::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(amount));
   ASSERT(CheckInteger(value));
@@ -231,7 +225,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Integer_shlFromInteger, 2) {
-  const Integer& amount = Integer::CheckedHandle(arguments->NativeArgAt(0));
+  const Integer& amount =
+      Integer::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(amount));
   ASSERT(CheckInteger(value));
@@ -243,7 +238,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Smi_bitAndFromSmi, 2) {
-  const Smi& left = Smi::CheckedHandle(arguments->NativeArgAt(0));
+  const Smi& left = Smi::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, right, arguments->NativeArgAt(1));
   if (FLAG_trace_intrinsified_natives) {
     OS::PrintErr("Smi_bitAndFromSmi %s & %s\n", left.ToCString(),
@@ -255,7 +250,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Smi_bitNegate, 1) {
-  const Smi& operand = Smi::CheckedHandle(arguments->NativeArgAt(0));
+  const Smi& operand = Smi::CheckedHandle(zone, arguments->NativeArgAt(0));
   if (FLAG_trace_intrinsified_natives) {
     OS::PrintErr("Smi_bitNegate: %s\n", operand.ToCString());
   }
@@ -265,7 +260,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Smi_bitLength, 1) {
-  const Smi& operand = Smi::CheckedHandle(arguments->NativeArgAt(0));
+  const Smi& operand = Smi::CheckedHandle(zone, arguments->NativeArgAt(0));
   if (FLAG_trace_intrinsified_natives) {
     OS::PrintErr("Smi_bitLength: %s\n", operand.ToCString());
   }
@@ -278,7 +273,7 @@
 // Mint natives.
 
 DEFINE_NATIVE_ENTRY(Mint_bitNegate, 1) {
-  const Mint& operand = Mint::CheckedHandle(arguments->NativeArgAt(0));
+  const Mint& operand = Mint::CheckedHandle(zone, arguments->NativeArgAt(0));
   ASSERT(CheckInteger(operand));
   if (FLAG_trace_intrinsified_natives) {
     OS::PrintErr("Mint_bitNegate: %s\n", operand.ToCString());
@@ -288,7 +283,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Mint_bitLength, 1) {
-  const Mint& operand = Mint::CheckedHandle(arguments->NativeArgAt(0));
+  const Mint& operand = Mint::CheckedHandle(zone, arguments->NativeArgAt(0));
   ASSERT(CheckInteger(operand));
   if (FLAG_trace_intrinsified_natives) {
     OS::PrintErr("Mint_bitLength: %s\n", operand.ToCString());
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index 3e427c4..b39ae32 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -4,10 +4,6 @@
 
 // part of "core_patch.dart";
 
-// This marker interface represents 64-bit integers in the compiler for type
-// propagation and range analysis.  It is implemented by _Smi and _Mint.
-abstract class _int64 implements int {}
-
 abstract class _IntegerImplementation implements int {
   num operator +(num other) => other._addFromInteger(this);
   num operator -(num other) => other._subFromInteger(this);
@@ -460,7 +456,7 @@
 }
 
 @pragma("vm:entry-point")
-class _Smi extends _IntegerImplementation implements _int64 {
+class _Smi extends _IntegerImplementation {
   factory _Smi._uninstantiable() {
     throw new UnsupportedError("_Smi can only be allocated by the VM");
   }
@@ -662,7 +658,7 @@
 
 // Represents integers that cannot be represented by Smi but fit into 64bits.
 @pragma("vm:entry-point")
-class _Mint extends _IntegerImplementation implements _int64 {
+class _Mint extends _IntegerImplementation {
   factory _Mint._uninstantiable() {
     throw new UnsupportedError("_Mint can only be allocated by the VM");
   }
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 261ed5d..e422704 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -26,7 +26,8 @@
 namespace dart {
 
 DEFINE_NATIVE_ENTRY(CapabilityImpl_factory, 1) {
-  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
   uint64_t id = isolate->random()->NextUInt64();
   return Capability::New(id);
 }
@@ -47,7 +48,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(RawReceivePortImpl_factory, 1) {
-  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
   Dart_Port port_id = PortMap::CreatePort(isolate->message_handler());
   return ReceivePort::New(port_id, false /* not control port */);
 }
@@ -255,14 +257,9 @@
   const char* result = NULL;
   Zone* zone = thread->zone();
   Isolate* isolate = thread->isolate();
-  Dart_LibraryTagHandler handler = isolate->library_tag_handler();
-  if (handler != NULL) {
-    TransitionVMToNative transition(thread);
-    Dart_EnterScope();
-    Dart_Handle handle =
-        handler(Dart_kCanonicalizeUrl, Api::NewHandle(thread, library.raw()),
-                Api::NewHandle(thread, uri.raw()));
-    const Object& obj = Object::Handle(Api::UnwrapHandle(handle));
+  if (isolate->HasTagHandler()) {
+    const Object& obj = Object::Handle(
+        isolate->CallTagHandler(Dart_kCanonicalizeUrl, library, uri));
     if (obj.IsString()) {
       result = String2UTF8(String::Cast(obj));
     } else if (obj.IsError()) {
@@ -276,7 +273,6 @@
           "library tag handler returned wrong type",
           uri.ToCString());
     }
-    Dart_ExitScope();
   } else {
     *error = zone->PrintToString(
         "Unable to canonicalize uri '%s': no library tag handler found.",
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index 0767bb6..972d9af 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -458,7 +458,7 @@
           packageRootString,
           packageConfigString);
       return await _spawnCommon(readyPort);
-    } catch (e, st) {
+    } catch (e) {
       if (readyPort != null) {
         readyPort.close();
       }
@@ -632,7 +632,7 @@
   static Uri _getCurrentRootUri() {
     try {
       return Uri.parse(_getCurrentRootUriStr());
-    } catch (e, s) {
+    } catch (e) {
       return null;
     }
   }
diff --git a/runtime/lib/lib_prefix.dart b/runtime/lib/lib_prefix.dart
index 8b1fed1..c895931 100644
--- a/runtime/lib/lib_prefix.dart
+++ b/runtime/lib/lib_prefix.dart
@@ -54,7 +54,6 @@
   // which have not completed, remember them for next time in
   // stillOutstandingLoadRequests.
   var stillOutstandingLoadRequests = new List<List>();
-  var completedLoadRequests = new List<List>();
 
   // Make a copy of the outstandingRequests because the call to _load below
   // may recursively trigger another call to |_completeDeferredLoads|, which
diff --git a/runtime/lib/linked_hash_map.cc b/runtime/lib/linked_hash_map.cc
index 94f7a27..cd09658 100644
--- a/runtime/lib/linked_hash_map.cc
+++ b/runtime/lib/linked_hash_map.cc
@@ -14,70 +14,71 @@
 
 DEFINE_NATIVE_ENTRY(LinkedHashMap_getIndex, 1) {
   const LinkedHashMap& map =
-      LinkedHashMap::CheckedHandle(arguments->NativeArgAt(0));
+      LinkedHashMap::CheckedHandle(zone, arguments->NativeArgAt(0));
   return map.index();
 }
 
 DEFINE_NATIVE_ENTRY(LinkedHashMap_setIndex, 2) {
   const LinkedHashMap& map =
-      LinkedHashMap::CheckedHandle(arguments->NativeArgAt(0));
-  const TypedData& index = TypedData::CheckedHandle(arguments->NativeArgAt(1));
+      LinkedHashMap::CheckedHandle(zone, arguments->NativeArgAt(0));
+  const TypedData& index =
+      TypedData::CheckedHandle(zone, arguments->NativeArgAt(1));
   map.SetIndex(index);
   return Object::null();
 }
 
 DEFINE_NATIVE_ENTRY(LinkedHashMap_getData, 1) {
   const LinkedHashMap& map =
-      LinkedHashMap::CheckedHandle(arguments->NativeArgAt(0));
+      LinkedHashMap::CheckedHandle(zone, arguments->NativeArgAt(0));
   return map.data();
 }
 
 DEFINE_NATIVE_ENTRY(LinkedHashMap_setData, 2) {
   const LinkedHashMap& map =
-      LinkedHashMap::CheckedHandle(arguments->NativeArgAt(0));
-  const Array& data = Array::CheckedHandle(arguments->NativeArgAt(1));
+      LinkedHashMap::CheckedHandle(zone, arguments->NativeArgAt(0));
+  const Array& data = Array::CheckedHandle(zone, arguments->NativeArgAt(1));
   map.SetData(data);
   return Object::null();
 }
 
 DEFINE_NATIVE_ENTRY(LinkedHashMap_getHashMask, 1) {
   const LinkedHashMap& map =
-      LinkedHashMap::CheckedHandle(arguments->NativeArgAt(0));
+      LinkedHashMap::CheckedHandle(zone, arguments->NativeArgAt(0));
   return map.hash_mask();
 }
 
 DEFINE_NATIVE_ENTRY(LinkedHashMap_setHashMask, 2) {
   const LinkedHashMap& map =
-      LinkedHashMap::CheckedHandle(arguments->NativeArgAt(0));
-  const Smi& hashMask = Smi::CheckedHandle(arguments->NativeArgAt(1));
+      LinkedHashMap::CheckedHandle(zone, arguments->NativeArgAt(0));
+  const Smi& hashMask = Smi::CheckedHandle(zone, arguments->NativeArgAt(1));
   map.SetHashMask(hashMask.Value());
   return Object::null();
 }
 
 DEFINE_NATIVE_ENTRY(LinkedHashMap_getDeletedKeys, 1) {
   const LinkedHashMap& map =
-      LinkedHashMap::CheckedHandle(arguments->NativeArgAt(0));
+      LinkedHashMap::CheckedHandle(zone, arguments->NativeArgAt(0));
   return map.deleted_keys();
 }
 
 DEFINE_NATIVE_ENTRY(LinkedHashMap_setDeletedKeys, 2) {
   const LinkedHashMap& map =
-      LinkedHashMap::CheckedHandle(arguments->NativeArgAt(0));
-  const Smi& deletedKeys = Smi::CheckedHandle(arguments->NativeArgAt(1));
+      LinkedHashMap::CheckedHandle(zone, arguments->NativeArgAt(0));
+  const Smi& deletedKeys = Smi::CheckedHandle(zone, arguments->NativeArgAt(1));
   map.SetDeletedKeys(deletedKeys.Value());
   return Object::null();
 }
 
 DEFINE_NATIVE_ENTRY(LinkedHashMap_getUsedData, 1) {
   const LinkedHashMap& map =
-      LinkedHashMap::CheckedHandle(arguments->NativeArgAt(0));
+      LinkedHashMap::CheckedHandle(zone, arguments->NativeArgAt(0));
   return map.used_data();
 }
 
 DEFINE_NATIVE_ENTRY(LinkedHashMap_setUsedData, 2) {
   const LinkedHashMap& map =
-      LinkedHashMap::CheckedHandle(arguments->NativeArgAt(0));
-  const Smi& usedData = Smi::CheckedHandle(arguments->NativeArgAt(1));
+      LinkedHashMap::CheckedHandle(zone, arguments->NativeArgAt(0));
+  const Smi& usedData = Smi::CheckedHandle(zone, arguments->NativeArgAt(1));
   map.SetUsedData(usedData.Value());
   return Object::null();
 }
diff --git a/runtime/lib/math.cc b/runtime/lib/math.cc
index 6b6ac56..e3ef926 100644
--- a/runtime/lib/math.cc
+++ b/runtime/lib/math.cc
@@ -9,7 +9,6 @@
 #include "vm/exceptions.h"
 #include "vm/native_entry.h"
 #include "vm/object.h"
-#include "vm/scanner.h"
 #include "vm/symbols.h"
 
 namespace dart {
@@ -67,7 +66,7 @@
 
 DEFINE_NATIVE_ENTRY(Math_doublePow, 2) {
   const double operand =
-      Double::CheckedHandle(arguments->NativeArgAt(0)).value();
+      Double::CheckedHandle(zone, arguments->NativeArgAt(0)).value();
   GET_NON_NULL_NATIVE_ARGUMENT(Double, exponent_object,
                                arguments->NativeArgAt(1));
   const double exponent = exponent_object.value();
diff --git a/runtime/lib/math_patch.dart b/runtime/lib/math_patch.dart
index 73eb844..fb68674 100644
--- a/runtime/lib/math_patch.dart
+++ b/runtime/lib/math_patch.dart
@@ -245,7 +245,7 @@
   static const _POW2_27_D = 1.0 * (1 << 27);
 
   // Use a singleton Random object to get a new seed if no seed was passed.
-  static var _prng = new _Random._withState(_initialSeed());
+  static final _prng = new _Random._withState(_initialSeed());
 
   // This is a native to prevent 64-bit operations in Dart, which
   // fail with --throw_on_javascript_int_overflow.
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 5b64e98..86ed771 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -523,7 +523,7 @@
       return CreateFunctionTypeMirror(type);
     }
   }
-  if (type.HasResolvedTypeClass()) {
+  if (type.HasTypeClass()) {
     const Class& cls = Class::Handle(type.type_class());
     // Handle void and dynamic types.
     if (cls.IsVoidClass()) {
@@ -650,8 +650,7 @@
 DEFINE_NATIVE_ENTRY(IsolateMirror_loadUri, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(String, uri, arguments->NativeArgAt(0));
 
-  Dart_LibraryTagHandler handler = isolate->library_tag_handler();
-  if (handler == NULL) {
+  if (!isolate->HasTagHandler()) {
     ThrowLanguageError("no library handler registered");
   }
 
@@ -663,16 +662,12 @@
     canonical_uri = uri.raw();
   } else {
     isolate->BlockClassFinalization();
-    Object& result = Object::Handle(zone);
-    {
-      TransitionVMToNative transition(thread);
-      Api::Scope api_scope(thread);
-      Dart_Handle retval = handler(
-          Dart_kCanonicalizeUrl,
-          Api::NewHandle(thread, isolate->object_store()->root_library()),
-          Api::NewHandle(thread, uri.raw()));
-      result = Api::UnwrapHandle(retval);
-    }
+    const Object& result = Object::Handle(
+        zone,
+        isolate->CallTagHandler(
+            Dart_kCanonicalizeUrl,
+            Library::Handle(zone, isolate->object_store()->root_library()),
+            uri));
     isolate->UnblockClassFinalization();
     if (result.IsError()) {
       if (result.IsLanguageError()) {
@@ -695,16 +690,11 @@
 
   // Request the embedder to load the library.
   isolate->BlockClassFinalization();
-  Object& result = Object::Handle(zone);
-  {
-    TransitionVMToNative transition(thread);
-    Api::Scope api_scope(thread);
-    Dart_Handle retval =
-        handler(Dart_kImportTag,
-                Api::NewHandle(thread, isolate->object_store()->root_library()),
-                Api::NewHandle(thread, canonical_uri.raw()));
-    result = Api::UnwrapHandle(retval);
-  }
+  Object& result = Object::Handle(
+      zone, isolate->CallTagHandler(
+                Dart_kImportTag,
+                Library::Handle(zone, isolate->object_store()->root_library()),
+                canonical_uri));
   isolate->UnblockClassFinalization();
   if (result.IsError()) {
     if (result.IsLanguageError()) {
@@ -740,7 +730,7 @@
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   PROPAGATE_IF_MALFORMED(type);
   ASSERT(type.IsFinalized());
-  ASSERT(type.HasResolvedTypeClass());
+  ASSERT(type.HasTypeClass());
   const Class& cls = Class::Handle(type.type_class());
   ASSERT(!cls.IsNull());
   if (cls.IsDynamicClass() || cls.IsVoidClass() || cls.IsTypedefClass()) {
@@ -761,7 +751,7 @@
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(1));
 
-  ASSERT(type.HasResolvedTypeClass());
+  ASSERT(type.HasTypeClass());
   const Class& clz = Class::Handle(type.type_class());
   if (!clz.IsGeneric()) {
     const Array& error_args = Array::Handle(Array::New(3));
@@ -1444,6 +1434,13 @@
                       InvocationMirror::kMethod);
     UNREACHABLE();
   }
+  const Object& type_error =
+      Object::Handle(redirected_constructor.DoArgumentTypesMatch(
+          args, args_descriptor, type_arguments));
+  if (!type_error.IsNull()) {
+    Exceptions::PropagateError(Error::Cast(type_error));
+    UNREACHABLE();
+  }
 
   Instance& new_object = Instance::Handle();
   if (redirected_constructor.IsGenerativeConstructor()) {
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index b067593..8fc3b5a 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -15,11 +15,10 @@
 
 namespace dart {
 
-DECLARE_FLAG(bool, trace_type_checks);
-
 DEFINE_NATIVE_ENTRY(DartAsync_fatal, 1) {
   // The dart:async library code entered an unrecoverable state.
-  const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0));
+  const Instance& instance =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
   const char* msg = instance.ToCString();
   OS::PrintErr("Fatal error in dart:async: %s\n", msg);
   FATAL(msg);
@@ -50,7 +49,8 @@
 #if defined(HASH_IN_OBJECT_HEADER)
   Object::SetCachedHash(arguments->NativeArgAt(0), hash.Value());
 #else
-  const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0));
+  const Instance& instance =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
   Heap* heap = isolate->heap();
   heap->SetHash(instance.raw(), hash.Value());
 #endif
@@ -58,7 +58,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Object_toString, 1) {
-  const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0));
+  const Instance& instance =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
   if (instance.IsString()) {
     return instance.raw();
   }
@@ -70,7 +71,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Object_runtimeType, 1) {
-  const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0));
+  const Instance& instance =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
   if (instance.IsString()) {
     return Type::StringType();
   } else if (instance.IsInteger()) {
@@ -82,8 +84,10 @@
 }
 
 DEFINE_NATIVE_ENTRY(Object_haveSameRuntimeType, 2) {
-  const Instance& left = Instance::CheckedHandle(arguments->NativeArgAt(0));
-  const Instance& right = Instance::CheckedHandle(arguments->NativeArgAt(1));
+  const Instance& left =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
+  const Instance& right =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
 
   const intptr_t left_cid = left.GetClassId();
   const intptr_t right_cid = right.GetClassId();
@@ -502,7 +506,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(NoSuchMethodError_existingMethodSignature, 3) {
-  const Instance& receiver = Instance::CheckedHandle(arguments->NativeArgAt(0));
+  const Instance& receiver =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(String, method_name, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, invocation_type, arguments->NativeArgAt(2));
   InvocationMirror::Level level;
diff --git a/runtime/lib/profiler.cc b/runtime/lib/profiler.cc
index d892a5c..009a2d3 100644
--- a/runtime/lib/profiler.cc
+++ b/runtime/lib/profiler.cc
@@ -13,27 +13,26 @@
 
 namespace dart {
 
-DECLARE_FLAG(bool, trace_intrinsified_natives);
-
 // Native implementations of the profiler parts of the dart:developer library.
 
 DEFINE_NATIVE_ENTRY(UserTag_new, 2) {
-  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(String, tag_label, arguments->NativeArgAt(1));
   return UserTag::New(tag_label);
 }
 
 DEFINE_NATIVE_ENTRY(UserTag_label, 1) {
-  const UserTag& self = UserTag::CheckedHandle(arguments->NativeArgAt(0));
+  const UserTag& self = UserTag::CheckedHandle(zone, arguments->NativeArgAt(0));
   return self.label();
 }
 
 DEFINE_NATIVE_ENTRY(UserTag_makeCurrent, 1) {
-  const UserTag& self = UserTag::CheckedHandle(arguments->NativeArgAt(0));
+  const UserTag& self = UserTag::CheckedHandle(zone, arguments->NativeArgAt(0));
   if (FLAG_trace_intrinsified_natives) {
     OS::PrintErr("UserTag_makeCurrent: %s\n", self.ToCString());
   }
-  const UserTag& old = UserTag::Handle(isolate->current_tag());
+  const UserTag& old = UserTag::Handle(zone, isolate->current_tag());
   self.MakeActive();
   return old.raw();
 }
diff --git a/runtime/lib/regexp.cc b/runtime/lib/regexp.cc
index 92f411f..96b0ed1 100644
--- a/runtime/lib/regexp.cc
+++ b/runtime/lib/regexp.cc
@@ -15,7 +15,8 @@
 namespace dart {
 
 DEFINE_NATIVE_ENTRY(RegExp_factory, 4) {
-  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(String, pattern, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, handle_multi_line,
                                arguments->NativeArgAt(2));
@@ -37,25 +38,25 @@
 }
 
 DEFINE_NATIVE_ENTRY(RegExp_getPattern, 1) {
-  const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
+  const RegExp& regexp = RegExp::CheckedHandle(zone, arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
   return regexp.pattern();
 }
 
 DEFINE_NATIVE_ENTRY(RegExp_getIsMultiLine, 1) {
-  const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
+  const RegExp& regexp = RegExp::CheckedHandle(zone, arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
   return Bool::Get(regexp.is_multi_line()).raw();
 }
 
 DEFINE_NATIVE_ENTRY(RegExp_getIsCaseSensitive, 1) {
-  const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
+  const RegExp& regexp = RegExp::CheckedHandle(zone, arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
   return Bool::Get(!regexp.is_ignore_case()).raw();
 }
 
 DEFINE_NATIVE_ENTRY(RegExp_getGroupCount, 1) {
-  const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
+  const RegExp& regexp = RegExp::CheckedHandle(zone, arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
   if (regexp.is_initialized()) {
     return regexp.num_bracket_expressions();
@@ -73,7 +74,7 @@
 static RawObject* ExecuteMatch(Zone* zone,
                                NativeArguments* arguments,
                                bool sticky) {
-  const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
+  const RegExp& regexp = RegExp::CheckedHandle(zone, arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(String, subject, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_index, arguments->NativeArgAt(2));
diff --git a/runtime/lib/simd128.cc b/runtime/lib/simd128.cc
index 45c3862..41f0602 100644
--- a/runtime/lib/simd128.cc
+++ b/runtime/lib/simd128.cc
@@ -19,7 +19,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Float32x4_fromDoubles, 5) {
-  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(Double, x, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Double, y, arguments->NativeArgAt(2));
   GET_NON_NULL_NATIVE_ARGUMENT(Double, z, arguments->NativeArgAt(3));
@@ -32,14 +33,16 @@
 }
 
 DEFINE_NATIVE_ENTRY(Float32x4_splat, 2) {
-  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(Double, v, arguments->NativeArgAt(1));
   float _v = v.value();
   return Float32x4::New(_v, _v, _v, _v);
 }
 
 DEFINE_NATIVE_ENTRY(Float32x4_zero, 1) {
-  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
   return Float32x4::New(0.0f, 0.0f, 0.0f, 0.0f);
 }
 
@@ -361,7 +364,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Int32x4_fromInts, 5) {
-  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, x, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, y, arguments->NativeArgAt(2));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, z, arguments->NativeArgAt(3));
@@ -374,7 +378,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Int32x4_fromBools, 5) {
-  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(Bool, x, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Bool, y, arguments->NativeArgAt(2));
   GET_NON_NULL_NATIVE_ARGUMENT(Bool, z, arguments->NativeArgAt(3));
@@ -636,25 +641,29 @@
 }
 
 DEFINE_NATIVE_ENTRY(Float64x2_fromDoubles, 3) {
-  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(Double, x, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Double, y, arguments->NativeArgAt(2));
   return Float64x2::New(x.value(), y.value());
 }
 
 DEFINE_NATIVE_ENTRY(Float64x2_splat, 2) {
-  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(Double, v, arguments->NativeArgAt(1));
   return Float64x2::New(v.value(), v.value());
 }
 
 DEFINE_NATIVE_ENTRY(Float64x2_zero, 1) {
-  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
   return Float64x2::New(0.0, 0.0);
 }
 
 DEFINE_NATIVE_ENTRY(Float64x2_fromFloat32x4, 2) {
-  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
+  ASSERT(
+      TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, v, arguments->NativeArgAt(1));
   double _x = v.x();
   double _y = v.y();
diff --git a/runtime/lib/stacktrace.cc b/runtime/lib/stacktrace.cc
index 28edcf1..2575da5 100644
--- a/runtime/lib/stacktrace.cc
+++ b/runtime/lib/stacktrace.cc
@@ -145,15 +145,22 @@
   StackFrame* frame = frames.NextFrame();
   ASSERT(frame != NULL);  // We expect to find a dart invocation frame.
   Code& code = Code::Handle();
+  Bytecode& bytecode = Bytecode::Handle();
   Smi& offset = Smi::Handle();
   while (frame != NULL) {
     if (frame->IsDartFrame()) {
       if (skip_frames > 0) {
         skip_frames--;
       } else {
-        code = frame->LookupDartCode();
-        offset = Smi::New(frame->pc() - code.PayloadStart());
-        code_list.Add(code);
+        if (frame->is_interpreted()) {
+          bytecode = frame->LookupDartBytecode();
+          offset = Smi::New(frame->pc() - bytecode.PayloadStart());
+          code_list.Add(bytecode);
+        } else {
+          code = frame->LookupDartCode();
+          offset = Smi::New(frame->pc() - code.PayloadStart());
+          code_list.Add(code);
+        }
         pc_offset_list.Add(offset);
       }
     }
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index fe749e4..103959b 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -124,7 +124,6 @@
     if (charCodes == null) throw new ArgumentError(charCodes);
     // TODO(srdjan): Also skip copying of wide typed arrays.
     final ccid = ClassID.getID(charCodes);
-    bool isOneByteString = false;
     if ((ccid != ClassID.cidArray) &&
         (ccid != ClassID.cidGrowableObjectArray) &&
         (ccid != ClassID.cidImmutableArray)) {
@@ -139,9 +138,7 @@
     end = RangeError.checkValidRange(start, end, codeCount);
     final len = end - start;
     if (len == 0) return "";
-    if (limit == null) {
-      limit = _scanCodeUnits(charCodes, start, end);
-    }
+    limit ??= _scanCodeUnits(charCodes, start, end);
     if (limit < 0) {
       throw new ArgumentError(charCodes);
     }
@@ -368,7 +365,7 @@
   }
 
   String substring(int startIndex, [int endIndex]) {
-    if (endIndex == null) endIndex = this.length;
+    endIndex ??= this.length;
 
     if ((startIndex < 0) || (startIndex > this.length)) {
       throw new RangeError.value(startIndex);
@@ -623,7 +620,6 @@
     int replacementLength = replacement.length;
     int startIndex = 0;
     if (replacementLength == 0) {
-      int count = 0;
       for (Match match in pattern.allMatches(this)) {
         length += _addReplaceSlice(matches, startIndex, match.start);
         startIndex = match.end;
@@ -782,8 +778,8 @@
     if (pattern is! Pattern) {
       throw new ArgumentError("${pattern} is not a Pattern");
     }
-    if (onMatch == null) onMatch = _matchString;
-    if (onNonMatch == null) onNonMatch = _stringIdentity;
+    onMatch ??= _matchString;
+    onNonMatch ??= _stringIdentity;
     if (pattern is String) {
       String stringPattern = pattern;
       if (stringPattern.isEmpty) {
diff --git a/runtime/lib/timer_impl.dart b/runtime/lib/timer_impl.dart
index 89cb6cd..01db53f 100644
--- a/runtime/lib/timer_impl.dart
+++ b/runtime/lib/timer_impl.dart
@@ -124,7 +124,7 @@
 
   // Timers are ordered by wakeup time. Timers with a timeout value of > 0 do
   // end up on the TimerHeap. Timers with a timeout of 0 are queued in a list.
-  static _TimerHeap _heap = new _TimerHeap();
+  static final _heap = new _TimerHeap();
   static _Timer _firstZeroTimer;
   static _Timer _lastZeroTimer;
 
diff --git a/runtime/lib/timer_patch.dart b/runtime/lib/timer_patch.dart
index 3104ecb..88940ff 100644
--- a/runtime/lib/timer_patch.dart
+++ b/runtime/lib/timer_patch.dart
@@ -26,9 +26,7 @@
   static Timer _createPeriodicTimer(
       Duration duration, void callback(Timer timer)) {
     // TODO(iposva): Remove _TimerFactory and use VMLibraryHooks exclusively.
-    if (_TimerFactory._factory == null) {
-      _TimerFactory._factory = VMLibraryHooks.timerFactory;
-    }
+    _TimerFactory._factory ??= VMLibraryHooks.timerFactory;
     if (_TimerFactory._factory == null) {
       throw new UnsupportedError("Timer interface not supported.");
     }
diff --git a/runtime/lib/typed_data.cc b/runtime/lib/typed_data.cc
index 90fed75..0a81886 100644
--- a/runtime/lib/typed_data.cc
+++ b/runtime/lib/typed_data.cc
@@ -106,13 +106,15 @@
 }
 
 DEFINE_NATIVE_ENTRY(TypedData_setRange, 7) {
-  const Instance& dst = Instance::CheckedHandle(arguments->NativeArgAt(0));
-  const Smi& dst_start = Smi::CheckedHandle(arguments->NativeArgAt(1));
-  const Smi& length = Smi::CheckedHandle(arguments->NativeArgAt(2));
-  const Instance& src = Instance::CheckedHandle(arguments->NativeArgAt(3));
-  const Smi& src_start = Smi::CheckedHandle(arguments->NativeArgAt(4));
-  const Smi& to_cid_smi = Smi::CheckedHandle(arguments->NativeArgAt(5));
-  const Smi& from_cid_smi = Smi::CheckedHandle(arguments->NativeArgAt(6));
+  const Instance& dst =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
+  const Smi& dst_start = Smi::CheckedHandle(zone, arguments->NativeArgAt(1));
+  const Smi& length = Smi::CheckedHandle(zone, arguments->NativeArgAt(2));
+  const Instance& src =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(3));
+  const Smi& src_start = Smi::CheckedHandle(zone, arguments->NativeArgAt(4));
+  const Smi& to_cid_smi = Smi::CheckedHandle(zone, arguments->NativeArgAt(5));
+  const Smi& from_cid_smi = Smi::CheckedHandle(zone, arguments->NativeArgAt(6));
 
   if (length.Value() < 0) {
     const String& error = String::Handle(String::NewFormatted(
diff --git a/runtime/lib/typed_data_patch.dart b/runtime/lib/typed_data_patch.dart
index 7387c96..9c5f7d6 100644
--- a/runtime/lib/typed_data_patch.dart
+++ b/runtime/lib/typed_data_patch.dart
@@ -165,7 +165,7 @@
   }
 
   void shuffle([Random random]) {
-    if (random == null) random = new Random();
+    random ??= new Random();
     var i = this.length;
     while (i > 1) {
       int pos = random.nextInt(i);
@@ -282,7 +282,6 @@
   int reduce(int combine(int value, int element)) {
     var len = this.length;
     if (len == 0) throw IterableElementError.noElement();
-    var i = 0;
     var value = this[0];
     for (var i = 1; i < len; ++i) {
       value = combine(value, this[i]);
@@ -330,7 +329,6 @@
   }
 
   int lastWhere(bool test(int element), {int orElse()}) {
-    var result = null;
     var len = this.length;
     for (var i = len - 1; i >= 0; --i) {
       var element = this[i];
@@ -518,7 +516,7 @@
   }
 
   void shuffle([Random random]) {
-    if (random == null) random = new Random();
+    random ??= new Random();
     var i = this.length;
     while (i > 1) {
       int pos = random.nextInt(i);
@@ -637,7 +635,6 @@
   double reduce(double combine(double value, double element)) {
     var len = this.length;
     if (len == 0) throw IterableElementError.noElement();
-    var i = 0;
     var value = this[0];
     for (var i = 1; i < len; ++i) {
       value = combine(value, this[i]);
@@ -686,7 +683,6 @@
   }
 
   double lastWhere(bool test(double element), {double orElse()}) {
-    var result = null;
     var len = this.length;
     for (var i = len - 1; i >= 0; --i) {
       var element = this[i];
@@ -874,7 +870,7 @@
   }
 
   void shuffle([Random random]) {
-    if (random == null) random = new Random();
+    random ??= new Random();
     var i = this.length;
     while (i > 1) {
       int pos = random.nextInt(i);
@@ -994,7 +990,6 @@
   Float32x4 reduce(Float32x4 combine(Float32x4 value, Float32x4 element)) {
     var len = this.length;
     if (len == 0) throw IterableElementError.noElement();
-    var i = 0;
     var value = this[0];
     for (var i = 1; i < len; ++i) {
       value = combine(value, this[i]);
@@ -1043,7 +1038,6 @@
   }
 
   Float32x4 lastWhere(bool test(Float32x4 element), {Float32x4 orElse()}) {
-    var result = null;
     var len = this.length;
     for (var i = len - 1; i >= 0; --i) {
       var element = this[i];
@@ -1234,7 +1228,7 @@
   }
 
   void shuffle([Random random]) {
-    if (random == null) random = new Random();
+    random ??= new Random();
     var i = this.length;
     while (i > 1) {
       int pos = random.nextInt(i);
@@ -1353,7 +1347,6 @@
   Int32x4 reduce(Int32x4 combine(Int32x4 value, Int32x4 element)) {
     var len = this.length;
     if (len == 0) throw IterableElementError.noElement();
-    var i = 0;
     var value = this[0];
     for (var i = 1; i < len; ++i) {
       value = combine(value, this[i]);
@@ -1402,7 +1395,6 @@
   }
 
   Int32x4 lastWhere(bool test(Int32x4 element), {Int32x4 orElse()}) {
-    var result = null;
     var len = this.length;
     for (var i = len - 1; i >= 0; --i) {
       var element = this[i];
@@ -1593,7 +1585,7 @@
   }
 
   void shuffle([Random random]) {
-    if (random == null) random = new Random();
+    random ??= new Random();
     var i = this.length;
     while (i > 1) {
       int pos = random.nextInt(i);
@@ -1713,7 +1705,6 @@
   Float64x2 reduce(Float64x2 combine(Float64x2 value, Float64x2 element)) {
     var len = this.length;
     if (len == 0) throw IterableElementError.noElement();
-    var i = 0;
     var value = this[0];
     for (var i = 1; i < len; ++i) {
       value = combine(value, this[i]);
@@ -1762,7 +1753,6 @@
   }
 
   Float64x2 lastWhere(bool test(Float64x2 element), {Float64x2 orElse()}) {
-    var result = null;
     var len = this.length;
     for (var i = len - 1; i >= 0; --i) {
       var element = this[i];
@@ -1913,118 +1903,88 @@
       (other is _ByteBuffer) && identical(_data, other._data);
 
   ByteData asByteData([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length = this.lengthInBytes - offsetInBytes;
-    }
+    length ??= this.lengthInBytes - offsetInBytes;
     return new _ByteDataView(this._data, offsetInBytes, length);
   }
 
   Int8List asInt8List([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length = this.lengthInBytes - offsetInBytes;
-    }
+    length ??= this.lengthInBytes - offsetInBytes;
     return new _Int8ArrayView(this, offsetInBytes, length);
   }
 
   Uint8List asUint8List([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length = this.lengthInBytes - offsetInBytes;
-    }
+    length ??= this.lengthInBytes - offsetInBytes;
     return new _Uint8ArrayView(this, offsetInBytes, length);
   }
 
   Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length = this.lengthInBytes - offsetInBytes;
-    }
+    length ??= this.lengthInBytes - offsetInBytes;
     return new _Uint8ClampedArrayView(this, offsetInBytes, length);
   }
 
   Int16List asInt16List([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length =
-          (this.lengthInBytes - offsetInBytes) ~/ Int16List.bytesPerElement;
-    }
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Int16List.bytesPerElement;
     return new _Int16ArrayView(this, offsetInBytes, length);
   }
 
   Uint16List asUint16List([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length =
-          (this.lengthInBytes - offsetInBytes) ~/ Uint16List.bytesPerElement;
-    }
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Uint16List.bytesPerElement;
     return new _Uint16ArrayView(this, offsetInBytes, length);
   }
 
   Int32List asInt32List([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length =
-          (this.lengthInBytes - offsetInBytes) ~/ Int32List.bytesPerElement;
-    }
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Int32List.bytesPerElement;
     return new _Int32ArrayView(this, offsetInBytes, length);
   }
 
   Uint32List asUint32List([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length =
-          (this.lengthInBytes - offsetInBytes) ~/ Uint32List.bytesPerElement;
-    }
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Uint32List.bytesPerElement;
     return new _Uint32ArrayView(this, offsetInBytes, length);
   }
 
   Int64List asInt64List([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length =
-          (this.lengthInBytes - offsetInBytes) ~/ Int64List.bytesPerElement;
-    }
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Int64List.bytesPerElement;
     return new _Int64ArrayView(this, offsetInBytes, length);
   }
 
   Uint64List asUint64List([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length =
-          (this.lengthInBytes - offsetInBytes) ~/ Uint64List.bytesPerElement;
-    }
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Uint64List.bytesPerElement;
     return new _Uint64ArrayView(this, offsetInBytes, length);
   }
 
   Float32List asFloat32List([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length =
-          (this.lengthInBytes - offsetInBytes) ~/ Float32List.bytesPerElement;
-    }
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Float32List.bytesPerElement;
     return new _Float32ArrayView(this, offsetInBytes, length);
   }
 
   Float64List asFloat64List([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length =
-          (this.lengthInBytes - offsetInBytes) ~/ Float64List.bytesPerElement;
-    }
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Float64List.bytesPerElement;
     return new _Float64ArrayView(this, offsetInBytes, length);
   }
 
   Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length =
-          (this.lengthInBytes - offsetInBytes) ~/ Float32x4List.bytesPerElement;
-    }
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Float32x4List.bytesPerElement;
     return new _Float32x4ArrayView(this, offsetInBytes, length);
   }
 
   Int32x4List asInt32x4List([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length =
-          (this.lengthInBytes - offsetInBytes) ~/ Int32x4List.bytesPerElement;
-    }
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Int32x4List.bytesPerElement;
     return new _Int32x4ArrayView(this, offsetInBytes, length);
   }
 
   Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]) {
-    if (length == null) {
-      length =
-          (this.lengthInBytes - offsetInBytes) ~/ Float64x2List.bytesPerElement;
-    }
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Float64x2List.bytesPerElement;
     return new _Float64x2ArrayView(this, offsetInBytes, length);
   }
 }
@@ -3572,7 +3532,7 @@
   _TypedListView(_ByteBuffer _buffer, int _offset, int _length)
       : _typedData = _buffer._data,
         offsetInBytes = _offset,
-        length = _length {}
+        length = _length;
 
   // Method(s) implementing the TypedData interface.
 
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index 76d5fc9..c288d6a 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -365,49 +365,51 @@
     return Object::null();
   }
   GET_NON_NULL_NATIVE_ARGUMENT(TypedData, data, arguments->NativeArgAt(0));
-  TransitionVMToNative transition(thread);
   Api::Scope scope(thread);
-
   Dart_Handle data_handle = Api::NewHandle(thread, data.raw());
+  Dart_Handle result_list;
+  {
+    TransitionVMToNative transition(thread);
 
-  Dart_TypedData_Type typ;
-  void* bytes;
-  intptr_t length;
-  Dart_Handle err =
-      Dart_TypedDataAcquireData(data_handle, &typ, &bytes, &length);
-  ASSERT(!Dart_IsError(err));
+    Dart_TypedData_Type typ;
+    void* bytes;
+    intptr_t length;
+    Dart_Handle err =
+        Dart_TypedDataAcquireData(data_handle, &typ, &bytes, &length);
+    ASSERT(!Dart_IsError(err));
 
-  TarArchive archive(reinterpret_cast<uint8_t*>(bytes), length);
-  archive.Read();
+    TarArchive archive(reinterpret_cast<uint8_t*>(bytes), length);
+    archive.Read();
 
-  err = Dart_TypedDataReleaseData(data_handle);
-  ASSERT(!Dart_IsError(err));
+    err = Dart_TypedDataReleaseData(data_handle);
+    ASSERT(!Dart_IsError(err));
 
-  intptr_t archive_size = archive.Length();
+    intptr_t archive_size = archive.Length();
 
-  Dart_Handle result_list = Dart_NewList(2 * archive_size);
-  ASSERT(!Dart_IsError(result_list));
+    result_list = Dart_NewList(2 * archive_size);
+    ASSERT(!Dart_IsError(result_list));
 
-  intptr_t idx = 0;
-  while (archive.HasMore()) {
-    char* filename = archive.NextFilename();
-    intptr_t filename_length = strlen(filename);
-    uint8_t* contents = archive.NextContent();
-    intptr_t contents_length = archive.NextContentLength();
+    intptr_t idx = 0;
+    while (archive.HasMore()) {
+      char* filename = archive.NextFilename();
+      intptr_t filename_length = strlen(filename);
+      uint8_t* contents = archive.NextContent();
+      intptr_t contents_length = archive.NextContentLength();
 
-    Dart_Handle dart_filename = Dart_NewExternalLatin1String(
-        reinterpret_cast<uint8_t*>(filename), filename_length, filename,
-        filename_length, FilenameFinalizer);
-    ASSERT(!Dart_IsError(dart_filename));
+      Dart_Handle dart_filename = Dart_NewExternalLatin1String(
+          reinterpret_cast<uint8_t*>(filename), filename_length, filename,
+          filename_length, FilenameFinalizer);
+      ASSERT(!Dart_IsError(dart_filename));
 
-    Dart_Handle dart_contents = Dart_NewExternalTypedDataWithFinalizer(
-        Dart_TypedData_kUint8, contents, contents_length, contents,
-        contents_length, ContentsFinalizer);
-    ASSERT(!Dart_IsError(dart_contents));
+      Dart_Handle dart_contents = Dart_NewExternalTypedDataWithFinalizer(
+          Dart_TypedData_kUint8, contents, contents_length, contents,
+          contents_length, ContentsFinalizer);
+      ASSERT(!Dart_IsError(dart_contents));
 
-    Dart_ListSetAt(result_list, idx, dart_filename);
-    Dart_ListSetAt(result_list, (idx + 1), dart_contents);
-    idx += 2;
+      Dart_ListSetAt(result_list, idx, dart_filename);
+      Dart_ListSetAt(result_list, (idx + 1), dart_contents);
+      idx += 2;
+    }
   }
   return Api::UnwrapArrayHandle(thread->zone(), result_list).raw();
 #else
diff --git a/runtime/observatory/lib/service_io.dart b/runtime/observatory/lib/service_io.dart
index 63857cb..4565d9f 100644
--- a/runtime/observatory/lib/service_io.dart
+++ b/runtime/observatory/lib/service_io.dart
@@ -32,7 +32,7 @@
   }
 
   bool get isOpen =>
-      (_webSocket != null) && (_webSocket.readyState == WebSocket.OPEN);
+      (_webSocket != null) && (_webSocket.readyState == WebSocket.open);
 
   void send(dynamic data) {
     _webSocket.add(data);
diff --git a/runtime/observatory/lib/src/app/page.dart b/runtime/observatory/lib/src/app/page.dart
index 0009df1..9563098 100644
--- a/runtime/observatory/lib/src/app/page.dart
+++ b/runtime/observatory/lib/src/app/page.dart
@@ -15,7 +15,6 @@
 final _heapSnapshotRepository = new HeapSnapshotRepository();
 final _icdataRepository = new ICDataRepository();
 final _inboundReferencesRepository = new InboundReferencesRepository();
-final _instanceRepository = new InstanceRepository();
 final _isolateSampleProfileRepository = new IsolateSampleProfileRepository();
 final _libraryRepository = new LibraryRepository();
 final _megamorphicCacheRepository = new MegamorphicCacheRepository();
diff --git a/runtime/observatory/lib/src/elements/function_view.dart b/runtime/observatory/lib/src/elements/function_view.dart
index 57d775a..3c32189 100644
--- a/runtime/observatory/lib/src/elements/function_view.dart
+++ b/runtime/observatory/lib/src/elements/function_view.dart
@@ -288,6 +288,21 @@
             ]
         ]);
     }
+    if (_function.bytecode != null) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'bytecode',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              new CodeRefElement(_isolate, _function.bytecode,
+                  queue: _r.queue),
+            ]
+        ]);
+    }
     members.add(new DivElement()
       ..classes = ['memberItem']
       ..text = ' ');
diff --git a/runtime/observatory/lib/src/models/objects/function.dart b/runtime/observatory/lib/src/models/objects/function.dart
index e619f5e..541dcad 100644
--- a/runtime/observatory/lib/src/models/objects/function.dart
+++ b/runtime/observatory/lib/src/models/objects/function.dart
@@ -87,6 +87,9 @@
   CodeRef get unoptimizedCode;
 
   /// [optional]
+  CodeRef get bytecode;
+
+  /// [optional]
   FieldRef get field;
   int get usageCounter;
   InstanceRef get icDataArray;
diff --git a/runtime/observatory/lib/src/repositories/eval.dart b/runtime/observatory/lib/src/repositories/eval.dart
index bf423ad..90b8b12 100644
--- a/runtime/observatory/lib/src/repositories/eval.dart
+++ b/runtime/observatory/lib/src/repositories/eval.dart
@@ -11,6 +11,6 @@
     assert(isolate != null);
     assert(object != null);
     assert(e != null);
-    return (await isolate.eval(object, e)) as M.ObjectRef;
+    return await isolate.eval(object, e);
   }
 }
diff --git a/runtime/observatory/lib/src/repositories/heap_snapshot.dart b/runtime/observatory/lib/src/repositories/heap_snapshot.dart
index cea60e2..198af19 100644
--- a/runtime/observatory/lib/src/repositories/heap_snapshot.dart
+++ b/runtime/observatory/lib/src/repositories/heap_snapshot.dart
@@ -90,12 +90,13 @@
   }
 
   void reuse() {
-    _onProgress =
+    final onProgress =
         new StreamController<HeapSnapshotLoadingProgressEvent>.broadcast();
-    (() async {
-      _triggerOnProgress();
-      _onProgress.close();
-    }());
+    Timer.run(() {
+      onProgress.add(new HeapSnapshotLoadingProgressEvent(this));
+      onProgress.close();
+    });
+    _onProgress = onProgress;
   }
 }
 
diff --git a/runtime/observatory/lib/src/repositories/sample_profile.dart b/runtime/observatory/lib/src/repositories/sample_profile.dart
index 3dace5a..27d03c5 100644
--- a/runtime/observatory/lib/src/repositories/sample_profile.dart
+++ b/runtime/observatory/lib/src/repositories/sample_profile.dart
@@ -115,12 +115,13 @@
   }
 
   void reuse() {
-    _onProgress =
+    final onProgress =
         new StreamController<SampleProfileLoadingProgressEvent>.broadcast();
-    (() async {
-      _triggerOnProgress();
-      _onProgress.close();
-    }());
+    Timer.run(() {
+      onProgress.add(new SampleProfileLoadingProgressEvent(this));
+      onProgress.close();
+    });
+    _onProgress = onProgress;
   }
 }
 
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index ab6ec7b..7ebc69c 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1990,8 +1990,7 @@
       'address': address,
       'ref': ref,
     };
-    return invokeRpc('_getObjectByAddress', params)
-        .then((result) => result as ServiceObject);
+    return invokeRpc('_getObjectByAddress', params);
   }
 
   final Map<String, ServiceMetric> dartMetrics = <String, ServiceMetric>{};
@@ -3136,6 +3135,7 @@
   SourceLocation location;
   Code code;
   Code unoptimizedCode;
+  Code bytecode;
   bool isOptimizable;
   bool isInlinable;
   bool hasIntrinsic;
@@ -3194,6 +3194,7 @@
     isInlinable = map['_inlinable'];
     isRecognized = map['_recognized'];
     unoptimizedCode = map['_unoptimizedCode'];
+    bytecode = map['_bytecode'];
     deoptimizations = map['_deoptimizations'];
     usageCounter = map['_usageCounter'];
     icDataArray = map['_icDataArray'];
@@ -3718,7 +3719,7 @@
       UnresolvedSourceLocation loc = bpt.location;
       line = loc.line;
     }
-    getLine(line).addBreakpoint(bpt);
+    getLine(line)?.addBreakpoint(bpt);
   }
 
   void _removeBreakpoint(Breakpoint bpt) {
@@ -3730,7 +3731,7 @@
       line = loc.line;
     }
     if (line != null) {
-      getLine(line).removeBreakpoint(bpt);
+      getLine(line)?.removeBreakpoint(bpt);
     }
   }
 
diff --git a/runtime/observatory/pubspec.yaml b/runtime/observatory/pubspec.yaml
index c1dcd02..76e6219 100644
--- a/runtime/observatory/pubspec.yaml
+++ b/runtime/observatory/pubspec.yaml
@@ -1 +1,3 @@
 name: observatory
+environment:
+  sdk: '>=2.0.0 <3.0.0'
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/function.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/function.dart
index bbe2c28..00f3ca5 100644
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/function.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks/objects/function.dart
@@ -33,6 +33,7 @@
   final M.SourceLocation location;
   final M.CodeRef code;
   final M.CodeRef unoptimizedCode;
+  final M.CodeRef bytecode;
   final M.FieldRef field;
   final int usageCounter;
   final M.InstanceRef icDataArray;
@@ -55,6 +56,7 @@
     this.location,
     this.code,
     this.unoptimizedCode,
+    this.bytecode,
     this.field,
     this.usageCounter: 0,
     this.icDataArray: const InstanceRefMock(),
diff --git a/runtime/observatory/tests/service/break_on_default_constructor_test.dart b/runtime/observatory/tests/service/break_on_default_constructor_test.dart
index ab5755c..8f5d9e5 100644
--- a/runtime/observatory/tests/service/break_on_default_constructor_test.dart
+++ b/runtime/observatory/tests/service/break_on_default_constructor_test.dart
@@ -3,12 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:io';
 
 import 'package:observatory/debugger.dart';
+import 'package:observatory/service.dart' as S;
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
-import 'package:observatory/service.dart' as S;
 
 import 'service_test_common.dart';
 import 'test_helper.dart';
@@ -36,7 +35,7 @@
 
 List<String> stops = [];
 
-var tests = [
+var tests = <IsolateTest>[
   hasPausedAtStart,
   // Load the isolate's libraries
   (Isolate isolate) async {
diff --git a/runtime/observatory/tests/service/dev_fs_http_put_test.dart b/runtime/observatory/tests/service/dev_fs_http_put_test.dart
index f3e78a1..3233420 100644
--- a/runtime/observatory/tests/service/dev_fs_http_put_test.dart
+++ b/runtime/observatory/tests/service/dev_fs_http_put_test.dart
@@ -39,7 +39,7 @@
         await client.putUrl(Uri.parse(serviceHttpAddress));
     request.headers.add('dev_fs_name', fsId);
     request.headers.add('dev_fs_path', filePath);
-    request.add(GZIP.encode([9]));
+    request.add(gzip.encode([9]));
     HttpClientResponse response = await request.close();
     String responseBody = await readResponse(response);
     result = jsonDecode(responseBody);
@@ -49,7 +49,7 @@
     request = await client.putUrl(Uri.parse(serviceHttpAddress));
     request.headers.add('dev_fs_name', fsId);
     // omit the 'dev_fs_path' parameter.
-    request.write(GZIP.encode(fileContents));
+    request.write(gzip.encode(fileContents));
     response = await request.close();
     responseBody = await readResponse(response);
     result = jsonDecode(responseBody);
@@ -62,7 +62,7 @@
     request = await client.putUrl(Uri.parse(serviceHttpAddress));
     request.headers.add('dev_fs_name', fsId);
     request.headers.add('dev_fs_path', filePath);
-    request.add(GZIP.encode(fileContents));
+    request.add(gzip.encode(fileContents));
     response = await request.close();
     responseBody = await readResponse(response);
     result = jsonDecode(responseBody);
diff --git a/runtime/observatory/tests/service/dev_fs_http_put_weird_char_test.dart b/runtime/observatory/tests/service/dev_fs_http_put_weird_char_test.dart
index 29aaa37..891a8f7 100644
--- a/runtime/observatory/tests/service/dev_fs_http_put_weird_char_test.dart
+++ b/runtime/observatory/tests/service/dev_fs_http_put_weird_char_test.dart
@@ -40,7 +40,7 @@
         await client.putUrl(Uri.parse(serviceHttpAddress));
     request.headers.add('dev_fs_name', fsId);
     request.headers.add('dev_fs_path_b64', filePathBase64);
-    request.add(GZIP.encode([9]));
+    request.add(gzip.encode([9]));
     HttpClientResponse response = await request.close();
     String responseBody = await readResponse(response);
     result = jsonDecode(responseBody);
@@ -50,7 +50,7 @@
     request = await client.putUrl(Uri.parse(serviceHttpAddress));
     request.headers.add('dev_fs_name', fsId);
     // omit the 'dev_fs_path' parameter.
-    request.write(GZIP.encode(fileContents));
+    request.write(gzip.encode(fileContents));
     response = await request.close();
     responseBody = await readResponse(response);
     result = jsonDecode(responseBody);
@@ -63,7 +63,7 @@
     request = await client.putUrl(Uri.parse(serviceHttpAddress));
     request.headers.add('dev_fs_name', fsId);
     request.headers.add('dev_fs_path_b64', filePathBase64);
-    request.add(GZIP.encode(fileContents));
+    request.add(gzip.encode(fileContents));
     response = await request.close();
     responseBody = await readResponse(response);
     result = jsonDecode(responseBody);
diff --git a/runtime/observatory/tests/service/dev_fs_uri_test.dart b/runtime/observatory/tests/service/dev_fs_uri_test.dart
index b00d699..8446316 100644
--- a/runtime/observatory/tests/service/dev_fs_uri_test.dart
+++ b/runtime/observatory/tests/service/dev_fs_uri_test.dart
@@ -45,7 +45,7 @@
         await client.putUrl(Uri.parse(serviceHttpAddress));
     request.headers.add('dev_fs_name', fsId);
     request.headers.add('dev_fs_uri_b64', fileUriBase64);
-    request.add(GZIP.encode([9]));
+    request.add(gzip.encode([9]));
     HttpClientResponse response = await request.close();
     String responseBody = await readResponse(response);
     result = jsonDecode(responseBody);
@@ -56,7 +56,7 @@
     request = await client.putUrl(Uri.parse(serviceHttpAddress));
     request.headers.add('dev_fs_name', fsId);
     // omit the 'dev_fs_path' parameter.
-    request.write(GZIP.encode(fileContents));
+    request.write(gzip.encode(fileContents));
     response = await request.close();
     responseBody = await readResponse(response);
     result = jsonDecode(responseBody);
@@ -69,7 +69,7 @@
     request = await client.putUrl(Uri.parse(serviceHttpAddress));
     request.headers.add('dev_fs_name', fsId);
     request.headers.add('dev_fs_uri_b64', fileUriBase64);
-    request.add(GZIP.encode(fileContents));
+    request.add(gzip.encode(fileContents));
     response = await request.close();
     responseBody = await readResponse(response);
     result = jsonDecode(responseBody);
diff --git a/runtime/observatory/tests/service/eval_test.dart b/runtime/observatory/tests/service/eval_test.dart
index 33e5efe..a83ef37 100644
--- a/runtime/observatory/tests/service/eval_test.dart
+++ b/runtime/observatory/tests/service/eval_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
 import 'dart:developer';
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/file_service_test.dart b/runtime/observatory/tests/service/file_service_test.dart
index fe9dd6f..8eb2dcf 100644
--- a/runtime/observatory/tests/service/file_service_test.dart
+++ b/runtime/observatory/tests/service/file_service_test.dart
@@ -35,7 +35,7 @@
     try {
       var filePath = dir.path + io.Platform.pathSeparator + "file";
       var f = new io.File(filePath);
-      writingFile = await f.open(mode: io.FileMode.WRITE);
+      writingFile = await f.open(mode: io.FileMode.write);
       await writingFile.writeByte(42);
       await writingFile.writeByte(42);
       await writingFile.writeByte(42);
diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart
index 15ed8df..3f0ff6c 100644
--- a/runtime/observatory/tests/service/get_object_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_rpc_test.dart
@@ -952,8 +952,8 @@
     };
     var result = await isolate.invokeRpcNoUpgrade('getObject', params);
     expect(result['type'], equals('Code'));
-    expect(result['name'], equals('_DummyClass.dummyFunction'));
-    expect(result['_vmName'], equals('dummyFunction'));
+    expect(result['name'], endsWith('_DummyClass.dummyFunction'));
+    expect(result['_vmName'], endsWith('dummyFunction'));
     expect(result['kind'], equals('Dart'));
     expect(result['_optimized'], new isInstanceOf<bool>());
     expect(result['function']['type'], equals('@Function'));
diff --git a/runtime/observatory/tests/service/get_scripts_rpc_test.dart b/runtime/observatory/tests/service/get_scripts_rpc_test.dart
new file mode 100644
index 0000000..c22da46
--- /dev/null
+++ b/runtime/observatory/tests/service/get_scripts_rpc_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    var params = {
+      'isolateId': vm.isolates.first.id,
+    };
+    var result = await vm.invokeRpcNoUpgrade('getScripts', params);
+    expect(result['type'], equals('ScriptList'));
+    expect(result['scripts'].length, isPositive);
+    expect(result['scripts'][0]['type'], equals('@Script'));
+  },
+
+  (VM vm) async {
+    var params = {
+      'isolateId': 'badid',
+    };
+    bool caughtException;
+    try {
+      await vm.invokeRpcNoUpgrade('getScripts', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message, "getScripts: invalid 'isolateId' parameter: badid");
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // Plausible isolate id, not found.
+  (VM vm) async {
+    var params = {
+      'isolateId': 'isolates/9999999999',
+    };
+    var result = await vm.invokeRpcNoUpgrade('getScripts', params);
+    expect(result['type'], equals('Sentinel'));
+    expect(result['kind'], equals('Collected'));
+    expect(result['valueAsString'], equals('<collected>'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index 7ee0bb1..dc2c129 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(11));
+    expect(result['minor'], equals(12));
     expect(result['_privateMajor'], equals(0));
     expect(result['_privateMinor'], equals(0));
   },
diff --git a/runtime/observatory/tests/service/invoke_test.dart b/runtime/observatory/tests/service/invoke_test.dart
index ace2169..437a86d 100644
--- a/runtime/observatory/tests/service/invoke_test.dart
+++ b/runtime/observatory/tests/service/invoke_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
 import 'dart:developer';
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/next_through_is_and_as_test.dart b/runtime/observatory/tests/service/next_through_is_and_as_test.dart
index b22110d..886be73 100644
--- a/runtime/observatory/tests/service/next_through_is_and_as_test.dart
+++ b/runtime/observatory/tests/service/next_through_is_and_as_test.dart
@@ -25,7 +25,7 @@
   }
   if (hex is int) {
     print("hex is int");
-    int x = hex as int;
+    int x = hex as dynamic;
     if (x.isEven) {
       print("it's even even!");
     } else {
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index 514119c..303ba57 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -5,26 +5,13 @@
 [ $compiler == app_jitk ]
 add_breakpoint_rpc_test: RuntimeError
 async_generator_breakpoint_test: Skip # No incremental compiler available.
-async_next_regession_18877_test: RuntimeError
-async_next_test: RuntimeError
-async_scope_test: RuntimeError
 async_single_step_exception_test: RuntimeError
-async_single_step_into_test: RuntimeError
 async_single_step_out_test: RuntimeError
-async_star_single_step_into_test: RuntimeError
-async_star_step_out_test: RuntimeError
-async_step_out_test: RuntimeError
 bad_reload_test: RuntimeError
 break_on_activation_test: Skip # No incremental compiler available.
-break_on_function_test: RuntimeError
-breakpoint_in_parts_class_test: RuntimeError
-breakpoint_two_args_checked_test: RuntimeError
-code_test: RuntimeError # Issue 34143
 complex_reload_test: RuntimeError
 debugger_inspect_test: Skip # No incremental compiler available.
 debugger_location_second_test: RuntimeError
-debugging_inlined_finally_test: RuntimeError
-debugging_test: RuntimeError
 developer_service_get_isolate_id_test: Skip #  No incremental compiler available.
 eval_internal_class_test: Skip # No incremental compiler available.
 eval_regression_flutter20255_test: Skip # No incremental compiler available.
@@ -48,59 +35,15 @@
 get_vm_rpc_test: RuntimeError
 get_vm_timeline_rpc_test: RuntimeError
 instance_field_order_rpc_test: Skip # No incremental compiler available.
-issue_25465_test: RuntimeError
-issue_27238_test: RuntimeError
 local_variable_declaration_test: RuntimeError
-mixin_break_test: RuntimeError
-next_through_assign_call_test: RuntimeError
-next_through_assign_int_test: RuntimeError
-next_through_call_on_field_in_class_test: RuntimeError
-next_through_call_on_field_test: RuntimeError
-next_through_call_on_static_field_in_class_test: RuntimeError
-next_through_catch_test: RuntimeError
-next_through_closure_test: RuntimeError
-next_through_create_list_and_map_test: RuntimeError
-next_through_for_each_loop_test: RuntimeError
-next_through_for_loop_with_break_and_continue_test: RuntimeError
-next_through_function_expression_test: RuntimeError
-next_through_implicit_call_test: RuntimeError
-next_through_is_and_as_test: RuntimeError
-next_through_multi_catch_test: RuntimeError
-next_through_new_test: RuntimeError
-next_through_operator_bracket_on_super_test: RuntimeError
-next_through_operator_bracket_on_this_test: RuntimeError
-next_through_operator_bracket_test: RuntimeError
-next_through_simple_async_test: RuntimeError
-next_through_simple_async_with_returns_test: RuntimeError
-next_through_simple_linear_2_test: RuntimeError
-next_through_simple_linear_test: RuntimeError
 pause_on_exceptions_test: Skip # No incremental compiler available.
 positive_token_pos_test: RuntimeError
-regress_28443_test: RuntimeError
-regress_28980_test: RuntimeError
 rewind_optimized_out_test: RuntimeError
 rewind_test: RuntimeError
 set_name_rpc_test: RuntimeError
 set_vm_name_rpc_test: RuntimeError
 simple_reload_test: RuntimeError
-steal_breakpoint_test: RuntimeError
-step_into_async_no_await_test: RuntimeError
-step_over_await_test: RuntimeError
-step_test: RuntimeError # Issue 34143
 step_through_arithmetic_test: RuntimeError
-step_through_constructor_calls_test: RuntimeError
-step_through_constructor_test: RuntimeError
-step_through_for_each_sync_star_2_test: RuntimeError
-step_through_for_each_sync_star_test: RuntimeError
-step_through_function_2_test: RuntimeError
-step_through_function_test: RuntimeError
-step_through_getter_test: RuntimeError
-step_through_mixin_from_sdk_test: RuntimeError
-step_through_property_get_test: RuntimeError
-step_through_property_set_test: RuntimeError
-step_through_setter_test: RuntimeError
-step_through_switch_test: RuntimeError
-step_through_switch_with_continue_test: RuntimeError
 unused_changes_in_last_reload_test: RuntimeError
 valid_source_locations_test: RuntimeError
 
@@ -136,6 +79,7 @@
 
 [ $arch == ia32 && $builder_tag == optimization_counter_threshold ]
 eval_regression_flutter20255_test: SkipSlow # Timeout
+get_vm_timeline_rpc_test: Pass, Slow
 rewind_optimized_out_test: SkipSlow # Timeout
 
 [ $arch != simarm && $arch != simarm64 && $arch != simdbc && $compiler == dartk ]
@@ -154,13 +98,6 @@
 get_object_rpc_test: RuntimeError
 get_stack_rpc_test: RuntimeError
 
-[ $arch == x64 && $compiler == dartk && $system == windows ]
-regexp_function_test: Pass, Crash # Issue http://dartbug.com/34422
-
-[ $compiler == app_jitk && $mode == debug ]
-code_test: RuntimeError
-step_test: RuntimeError
-
 [ $compiler == dartk && $mode == debug ]
 isolate_lifecycle_test: Skip # Flaky.
 pause_idle_isolate_test: Skip # Flaky
diff --git a/runtime/observatory/tests/service/step_through_function_2_test.dart b/runtime/observatory/tests/service/step_through_function_2_test.dart
index d5df807..b6b6ff5 100644
--- a/runtime/observatory/tests/service/step_through_function_2_test.dart
+++ b/runtime/observatory/tests/service/step_through_function_2_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 'test_helper.dart';
 import 'service_test_common.dart';
+import 'test_helper.dart';
 
 const int LINE = 11;
 const String file = "step_through_function_2_test.dart";
@@ -16,6 +16,7 @@
   fooXYZ2(42);
 }
 
+// ignore: unused_element
 int _xyz = -1;
 
 fooXYZ1(int i) {
@@ -42,31 +43,31 @@
 
 List<String> stops = [];
 List<String> expected = [
-  "$file:${LINE+0}:5", // after 'code'
-  "$file:${LINE+1}:17", // on 'Bar'
+  "$file:${LINE + 0}:5", // after 'code'
+  "$file:${LINE + 1}:17", // on 'Bar'
 
-  "$file:${LINE+2}:7", // on 'barXYZ1'
-  "$file:${LINE+21}:15", // on 'i'
-  "$file:${LINE+22}:14", // on '-'
-  "$file:${LINE+22}:5", // on '_xyz'
-  "$file:${LINE+23}:3", // on '}'
+  "$file:${LINE + 2}:7", // on 'barXYZ1'
+  "$file:${LINE + 22}:15", // on 'i'
+  "$file:${LINE + 23}:14", // on '-'
+  "$file:${LINE + 23}:5", // on '_xyz'
+  "$file:${LINE + 24}:3", // on '}'
 
-  "$file:${LINE+3}:7", // on 'barXYZ2'
-  "$file:${LINE+25}:15", // on 'i'
-  "$file:${LINE+26}:5", // on '_xyz'
-  "$file:${LINE+27}:3", // on '}'
+  "$file:${LINE + 3}:7", // on 'barXYZ2'
+  "$file:${LINE + 26}:15", // on 'i'
+  "$file:${LINE + 27}:5", // on '_xyz'
+  "$file:${LINE + 28}:3", // on '}'
 
-  "$file:${LINE+4}:3", // on 'fooXYZ1'
-  "$file:${LINE+10}:13", // on 'i'
-  "$file:${LINE+11}:12", // on '-'
-  "$file:${LINE+12}:1", // on '}'
+  "$file:${LINE + 4}:3", // on 'fooXYZ1'
+  "$file:${LINE + 11}:13", // on 'i'
+  "$file:${LINE + 12}:12", // on '-'
+  "$file:${LINE + 13}:1", // on '}'
 
-  "$file:${LINE+5}:3", // on 'fooXYZ2'
-  "$file:${LINE+14}:13", // on 'i'
-  "$file:${LINE+15}:3", // on '_xyz'
-  "$file:${LINE+16}:1", // on '}'
+  "$file:${LINE + 5}:3", // on 'fooXYZ2'
+  "$file:${LINE + 15}:13", // on 'i'
+  "$file:${LINE + 16}:3", // on '_xyz'
+  "$file:${LINE + 17}:1", // on '}'
 
-  "$file:${LINE+6}:1" // on ending '}'
+  "$file:${LINE + 6}:1" // on ending '}'
 ];
 
 var tests = <IsolateTest>[
diff --git a/runtime/observatory/tests/service/step_through_setter_test.dart b/runtime/observatory/tests/service/step_through_setter_test.dart
index 1274c2f..aa40fb1 100644
--- a/runtime/observatory/tests/service/step_through_setter_test.dart
+++ b/runtime/observatory/tests/service/step_through_setter_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 'test_helper.dart';
 import 'service_test_common.dart';
+import 'test_helper.dart';
 
 const int LINE = 11;
 const String file = "step_through_setter_test.dart";
@@ -14,6 +14,7 @@
   fooXYZ = 42;
 }
 
+// ignore: unused_element
 int _xyz = -1;
 
 set fooXYZ(int i) {
@@ -32,21 +33,21 @@
 
 List<String> stops = [];
 List<String> expected = [
-  "$file:${LINE+0}:5", // after 'code'
-  "$file:${LINE+1}:17", // on 'Bar'
+  "$file:${LINE + 0}:5", // after 'code'
+  "$file:${LINE + 1}:17", // on 'Bar'
 
-  "$file:${LINE+2}:7", // on 'barXYZ'
-  "$file:${LINE+15}:18", // on 'i'
-  "$file:${LINE+16}:14", // on '-'
-  "$file:${LINE+16}:5", // on '_xyz'
-  "$file:${LINE+17}:3", // on '}'
+  "$file:${LINE + 2}:7", // on 'barXYZ'
+  "$file:${LINE + 16}:18", // on 'i'
+  "$file:${LINE + 17}:14", // on '-'
+  "$file:${LINE + 17}:5", // on '_xyz'
+  "$file:${LINE + 18}:3", // on '}'
 
-  "$file:${LINE+3}:3", // on 'fooXYZ'
-  "$file:${LINE+8}:16", // on 'i'
-  "$file:${LINE+9}:12", // on '-'
-  "$file:${LINE+10}:1", // on '}'
+  "$file:${LINE + 3}:3", // on 'fooXYZ'
+  "$file:${LINE + 9}:16", // on 'i'
+  "$file:${LINE + 10}:12", // on '-'
+  "$file:${LINE + 11}:1", // on '}'
 
-  "$file:${LINE+4}:1" // on ending '}'
+  "$file:${LINE + 4}:1" // on ending '}'
 ];
 
 var tests = <IsolateTest>[
diff --git a/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart b/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart
index a995125..740a138 100644
--- a/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart
+++ b/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart
@@ -35,7 +35,7 @@
 
   var server = await io.RawDatagramSocket.bind('127.0.0.1', 0);
   server.listen((io.RawSocketEvent event) {
-    if (event == io.RawSocketEvent.READ) {
+    if (event == io.RawSocketEvent.read) {
       io.Datagram dg = server.receive();
       dg.data.forEach((x) => true);
       server.close();
diff --git a/runtime/observatory/tests/service/udp_socket_service_test.dart b/runtime/observatory/tests/service/udp_socket_service_test.dart
index 3d40eda..88f719f 100644
--- a/runtime/observatory/tests/service/udp_socket_service_test.dart
+++ b/runtime/observatory/tests/service/udp_socket_service_test.dart
@@ -10,16 +10,29 @@
 import 'test_helper.dart';
 
 Future setupUDP() async {
+  // Service might attach to us after we completed the setup but
+  // before we actually received a datagram - if it will start inspecting
+  // IO metrics at that point then it will see that no reads happened
+  // and the test will fail. That is why we don't consider setup complete
+  // until after we received the datagram.
+  final doneCompleter = Completer<void>();
+
   var server = await io.RawDatagramSocket.bind('127.0.0.1', 0);
   server.listen((io.RawSocketEvent event) {
-    if (event == io.RawSocketEvent.READ) {
+    if (event == io.RawSocketEvent.read) {
       io.Datagram dg = server.receive();
       dg.data.forEach((x) => true);
+      if (!doneCompleter.isCompleted) {
+        doneCompleter.complete(null);
+      }
     }
   });
   var client = await io.RawDatagramSocket.bind('127.0.0.1', 0);
   client.send(utf8.encoder.convert('foobar'),
       new io.InternetAddress('127.0.0.1'), server.port);
+
+  // Wait for datagram to arrive.
+  await doneCompleter.future;
 }
 
 var udpTests = <IsolateTest>[
@@ -46,12 +59,9 @@
     expect(server['listening'], isFalse);
     expect(server['socketType'], equals('UDP'));
     expect(server['port'], greaterThanOrEqualTo(1024));
-    // Stopwatch resolution on windows makes us sometimes report 0;
-    if (io.Platform.isWindows) {
-      expect(server['lastRead'], greaterThanOrEqualTo(0));
-    } else {
-      expect(server['lastRead'], greaterThan(0));
-    }
+    final now = DateTime.now().millisecondsSinceEpoch;
+    expect(
+        server['lastRead'], closeTo(now, Duration(seconds: 5).inMilliseconds));
     expect(server['totalRead'], equals(6));
     expect(server['lastWrite'], equals(0));
     expect(server['totalWritten'], equals(0));
diff --git a/runtime/observatory/tests/service/unused_changes_in_last_reload_test.dart b/runtime/observatory/tests/service/unused_changes_in_last_reload_test.dart
index 35f548a..223ac40 100644
--- a/runtime/observatory/tests/service/unused_changes_in_last_reload_test.dart
+++ b/runtime/observatory/tests/service/unused_changes_in_last_reload_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'test_helper.dart';
-import 'dart:async';
 import 'dart:developer';
 import 'dart:isolate' as I;
 import 'dart:io';
diff --git a/runtime/platform/atomic.h b/runtime/platform/atomic.h
index 37836e0..72d563b 100644
--- a/runtime/platform/atomic.h
+++ b/runtime/platform/atomic.h
@@ -49,6 +49,12 @@
   }
 
   template <typename T>
+  static T LoadAcquire(T* ptr);
+
+  template <typename T>
+  static void StoreRelease(T* ptr, T value);
+
+  template <typename T>
   static T* CompareAndSwapPointer(T** slot, T* old_value, T* new_value) {
     return reinterpret_cast<T*>(AtomicOperations::CompareAndSwapWord(
         reinterpret_cast<uword*>(slot), reinterpret_cast<uword>(old_value),
diff --git a/runtime/platform/atomic_android.h b/runtime/platform/atomic_android.h
index f95ba02..ef4e78a 100644
--- a/runtime/platform/atomic_android.h
+++ b/runtime/platform/atomic_android.h
@@ -68,6 +68,16 @@
   return __sync_val_compare_and_swap(ptr, old_value, new_value);
 }
 
+template <typename T>
+inline T AtomicOperations::LoadAcquire(T* ptr) {
+  return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
+}
+
+template <typename T>
+inline void AtomicOperations::StoreRelease(T* ptr, T value) {
+  __atomic_store_n(ptr, value, __ATOMIC_RELEASE);
+}
+
 }  // namespace dart
 
 #endif  // RUNTIME_PLATFORM_ATOMIC_ANDROID_H_
diff --git a/runtime/platform/atomic_fuchsia.h b/runtime/platform/atomic_fuchsia.h
index 2883e1e..8688987 100644
--- a/runtime/platform/atomic_fuchsia.h
+++ b/runtime/platform/atomic_fuchsia.h
@@ -65,6 +65,16 @@
   return __sync_val_compare_and_swap(ptr, old_value, new_value);
 }
 
+template <typename T>
+inline T AtomicOperations::LoadAcquire(T* ptr) {
+  return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
+}
+
+template <typename T>
+inline void AtomicOperations::StoreRelease(T* ptr, T value) {
+  __atomic_store_n(ptr, value, __ATOMIC_RELEASE);
+}
+
 }  // namespace dart
 
 #endif  // RUNTIME_PLATFORM_ATOMIC_FUCHSIA_H_
diff --git a/runtime/platform/atomic_linux.h b/runtime/platform/atomic_linux.h
index fd1773f..c309af7 100644
--- a/runtime/platform/atomic_linux.h
+++ b/runtime/platform/atomic_linux.h
@@ -68,6 +68,16 @@
   return __sync_val_compare_and_swap(ptr, old_value, new_value);
 }
 
+template <typename T>
+inline T AtomicOperations::LoadAcquire(T* ptr) {
+  return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
+}
+
+template <typename T>
+inline void AtomicOperations::StoreRelease(T* ptr, T value) {
+  __atomic_store_n(ptr, value, __ATOMIC_RELEASE);
+}
+
 }  // namespace dart
 
 #endif  // RUNTIME_PLATFORM_ATOMIC_LINUX_H_
diff --git a/runtime/platform/atomic_macos.h b/runtime/platform/atomic_macos.h
index b0bd31f..340ed40 100644
--- a/runtime/platform/atomic_macos.h
+++ b/runtime/platform/atomic_macos.h
@@ -68,6 +68,16 @@
   return __sync_val_compare_and_swap(ptr, old_value, new_value);
 }
 
+template <typename T>
+inline T AtomicOperations::LoadAcquire(T* ptr) {
+  return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
+}
+
+template <typename T>
+inline void AtomicOperations::StoreRelease(T* ptr, T value) {
+  __atomic_store_n(ptr, value, __ATOMIC_RELEASE);
+}
+
 }  // namespace dart
 
 #endif  // RUNTIME_PLATFORM_ATOMIC_MACOS_H_
diff --git a/runtime/platform/atomic_win.h b/runtime/platform/atomic_win.h
index 5e6db1b..bbef085 100644
--- a/runtime/platform/atomic_win.h
+++ b/runtime/platform/atomic_win.h
@@ -141,6 +141,24 @@
 #endif
 }
 
+template <typename T>
+inline T AtomicOperations::LoadAcquire(T* ptr) {
+#if (defined(HOST_ARCH_X64) || defined(HOST_ARCH_IA32))
+  return *ptr;
+#else
+#error Unsupported host architecture.
+#endif
+}
+
+template <typename T>
+inline void AtomicOperations::StoreRelease(T* ptr, T value) {
+#if (defined(HOST_ARCH_X64) || defined(HOST_ARCH_IA32))
+  *ptr = value;
+#else
+#error Unsupported host architecture.
+#endif
+}
+
 }  // namespace dart
 
 #endif  // RUNTIME_PLATFORM_ATOMIC_WIN_H_
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index 2917008..56c49bb 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -337,6 +337,26 @@
     return bit << n;
   }
 
+  // Decode integer in SLEB128 format from |data| and update |byte_index|.
+  static intptr_t DecodeSLEB128(const uint8_t* data,
+                                const intptr_t data_length,
+                                intptr_t* byte_index) {
+    ASSERT(*byte_index < data_length);
+    uword shift = 0;
+    intptr_t value = 0;
+    uint8_t part = 0;
+    do {
+      part = data[(*byte_index)++];
+      value |= static_cast<intptr_t>(part & 0x7f) << shift;
+      shift += 7;
+    } while ((part & 0x80) != 0);
+
+    if ((shift < (sizeof(value) * 8)) && ((part & 0x40) != 0)) {
+      value |= static_cast<intptr_t>(kUwordMax << shift);
+    }
+    return value;
+  }
+
   static char* StrError(int err, char* buffer, size_t bufsize);
 
   // Not all platforms support strndup.
diff --git a/runtime/tests/vm/dart/entrypoints/polymorphic_optional_this_inline_test.dart b/runtime/tests/vm/dart/entrypoints/polymorphic_optional_this_inline_test.dart
deleted file mode 100644
index 7d01f34..0000000
--- a/runtime/tests/vm/dart/entrypoints/polymorphic_optional_this_inline_test.dart
+++ /dev/null
@@ -1,9 +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.
-
-// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
-
-import "polymorphic_optional_this.dart";
-
-main(args) => test(args);
diff --git a/runtime/tests/vm/dart/entrypoints/polymorphic_optional_this_noinline_test.dart b/runtime/tests/vm/dart/entrypoints/polymorphic_optional_this_noinline_test.dart
deleted file mode 100644
index 5dbf571..0000000
--- a/runtime/tests/vm/dart/entrypoints/polymorphic_optional_this_noinline_test.dart
+++ /dev/null
@@ -1,9 +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.
-
-// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
-
-import "polymorphic_optional_this.dart";
-
-main(args) => test(args);
diff --git a/runtime/tests/vm/dart/entrypoints/polymorphic_optional_this.dart b/runtime/tests/vm/dart/entrypoints/polymorphic_optional_this_test.dart
similarity index 81%
rename from runtime/tests/vm/dart/entrypoints/polymorphic_optional_this.dart
rename to runtime/tests/vm/dart/entrypoints/polymorphic_optional_this_test.dart
index 6099194..026b6f4 100644
--- a/runtime/tests/vm/dart/entrypoints/polymorphic_optional_this.dart
+++ b/runtime/tests/vm/dart/entrypoints/polymorphic_optional_this_test.dart
@@ -1,6 +1,9 @@
 // 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.
+//
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
 
 // Test that 'PolymorphicInstanceCall's against "this" go through the unchecked
 // entrypoint. The use of optional arguments here encourages prologue sharing
@@ -48,7 +51,7 @@
   }
 }
 
-test(List<String> args) {
+main(List<String> args) {
   // Warmup.
   expectedEntryPoint = -1;
   for (int i = 0; i < 100; ++i) {
diff --git a/runtime/tests/vm/dart/entrypoints/polymorphic_this_inline_test.dart b/runtime/tests/vm/dart/entrypoints/polymorphic_this_inline_test.dart
deleted file mode 100644
index 99617e7..0000000
--- a/runtime/tests/vm/dart/entrypoints/polymorphic_this_inline_test.dart
+++ /dev/null
@@ -1,9 +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.
-
-// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
-
-import "polymorphic_this.dart";
-
-main(args) => test(args);
diff --git a/runtime/tests/vm/dart/entrypoints/polymorphic_this_noinline_test.dart b/runtime/tests/vm/dart/entrypoints/polymorphic_this_noinline_test.dart
deleted file mode 100644
index 7e2e1f0..0000000
--- a/runtime/tests/vm/dart/entrypoints/polymorphic_this_noinline_test.dart
+++ /dev/null
@@ -1,9 +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.
-
-// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
-
-import "polymorphic_this.dart";
-
-main(args) => test(args);
diff --git a/runtime/tests/vm/dart/entrypoints/polymorphic_this.dart b/runtime/tests/vm/dart/entrypoints/polymorphic_this_test.dart
similarity index 80%
rename from runtime/tests/vm/dart/entrypoints/polymorphic_this.dart
rename to runtime/tests/vm/dart/entrypoints/polymorphic_this_test.dart
index 5d4aac9..e1cb856 100644
--- a/runtime/tests/vm/dart/entrypoints/polymorphic_this.dart
+++ b/runtime/tests/vm/dart/entrypoints/polymorphic_this_test.dart
@@ -1,6 +1,9 @@
 // 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.
+//
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
 
 // Test that 'PolymorphicInstanceCall's against "this" go through the unchecked
 // entrypoint.
@@ -45,7 +48,7 @@
   }
 }
 
-test(List<String> args) {
+main(List<String> args) {
   // Warmup.
   expectedEntryPoint = -1;
   for (int i = 0; i < 100; ++i) {
diff --git a/runtime/tests/vm/dart/entrypoints/static_this_inline_test.dart b/runtime/tests/vm/dart/entrypoints/static_this_inline_test.dart
deleted file mode 100644
index ea7391e..0000000
--- a/runtime/tests/vm/dart/entrypoints/static_this_inline_test.dart
+++ /dev/null
@@ -1,9 +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.
-
-// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
-
-import "static_this.dart";
-
-main(args) => test(args);
diff --git a/runtime/tests/vm/dart/entrypoints/static_this_noinline_test.dart b/runtime/tests/vm/dart/entrypoints/static_this_noinline_test.dart
deleted file mode 100644
index 453677b..0000000
--- a/runtime/tests/vm/dart/entrypoints/static_this_noinline_test.dart
+++ /dev/null
@@ -1,9 +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.
-
-// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
-
-import "static_this.dart";
-
-main(args) => test(args);
diff --git a/runtime/tests/vm/dart/entrypoints/static_this.dart b/runtime/tests/vm/dart/entrypoints/static_this_test.dart
similarity index 76%
rename from runtime/tests/vm/dart/entrypoints/static_this.dart
rename to runtime/tests/vm/dart/entrypoints/static_this_test.dart
index d64f6be..fc9253e 100644
--- a/runtime/tests/vm/dart/entrypoints/static_this.dart
+++ b/runtime/tests/vm/dart/entrypoints/static_this_test.dart
@@ -1,6 +1,9 @@
 // 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.
+//
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
 
 // Test that 'StaticCall's against "this" go through the unchecked entry-point.
 
@@ -20,7 +23,7 @@
   }
 }
 
-test(List<String> args) {
+main(List<String> args) {
   // Make sure the precise runtime-type of C is not known below.
   C c = args.length == 0 ? C<int>() : C<String>();
 
diff --git a/runtime/tests/vm/dart/entrypoints/super_test.dart b/runtime/tests/vm/dart/entrypoints/super_test.dart
new file mode 100644
index 0000000..2a17e61
--- /dev/null
+++ b/runtime/tests/vm/dart/entrypoints/super_test.dart
@@ -0,0 +1,64 @@
+// 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.
+//
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
+
+// Test that 'StaticCall's against "super" go through the unchecked entrypoint.
+
+import "common.dart";
+import "package:expect/expect.dart";
+
+abstract class C<T> {
+  @NeverInline
+  @pragma("vm:testing.unsafe.trace-entrypoints-fn", validate)
+  void target1(T x) {
+    Expect.notEquals(x, -1);
+  }
+}
+
+class D<T> extends C<T> {
+  @NeverInline
+  void target1(T x) {
+    super.target1(x);
+  }
+}
+
+class E<T> extends C<T> {
+  @NeverInline
+  void target1(T x) {
+    super.target1(x);
+  }
+}
+
+int j = 0;
+
+C getC() {
+  if (j % 2 == 0) {
+    ++j;
+    return new D<int>();
+  } else {
+    ++j;
+    return new E<int>();
+  }
+}
+
+// This works around issues with OSR not totally respecting the optimization
+// counter threshold.
+void testOneC(C x, int i) => x.target1(i);
+
+main(List<String> args) {
+  expectedEntryPoint = -1;
+  for (int i = 0; i < 100; ++i) {
+    testOneC(getC(), i);
+  }
+
+  expectedEntryPoint = 1;
+  const int iterations = benchmarkMode ? 200000000 : 100;
+  for (int i = 0; i < iterations; ++i) {
+    testOneC(getC(), i);
+  }
+
+  Expect.isTrue(validateRan);
+}
diff --git a/runtime/tests/vm/dart/entrypoints/tearoff_inline_test.dart b/runtime/tests/vm/dart/entrypoints/tearoff_inline_test.dart
deleted file mode 100644
index 843324a..0000000
--- a/runtime/tests/vm/dart/entrypoints/tearoff_inline_test.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
-
-import "tearoff.dart";
-
-main(args) => test(args);
diff --git a/runtime/tests/vm/dart/entrypoints/tearoff_noinline_test.dart b/runtime/tests/vm/dart/entrypoints/tearoff_noinline_test.dart
deleted file mode 100644
index aac3f75..0000000
--- a/runtime/tests/vm/dart/entrypoints/tearoff_noinline_test.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
-
-import "tearoff.dart";
-
-main(args) => test(args);
diff --git a/runtime/tests/vm/dart/entrypoints/tearoff_prologue.dart b/runtime/tests/vm/dart/entrypoints/tearoff_prologue.dart
deleted file mode 100644
index 8ce9916..0000000
--- a/runtime/tests/vm/dart/entrypoints/tearoff_prologue.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-// No type checks are removed here, but we can skip the argument count check.
-
-import "package:expect/expect.dart";
-import "common.dart";
-
-class C<T> {
-  @NeverInline
-  @pragma("vm:testing.unsafe.trace-entrypoints-fn", validateTearoff)
-  void samir1(T x) {
-    if (x == -1) {
-      throw "oh no";
-    }
-  }
-}
-
-test(List<String> args) {
-  var c = new C<int>();
-  var f = c.samir1;
-
-  // Warmup.
-  expectedEntryPoint = -1;
-  expectedTearoffEntryPoint = -1;
-  for (int i = 0; i < 100; ++i) {
-    f(i);
-  }
-
-  expectedEntryPoint = 0;
-  expectedTearoffEntryPoint = 1;
-  int iterations = benchmarkMode ? 100000000 : 100;
-  for (int i = 0; i < iterations; ++i) {
-    f(i);
-  }
-
-  Expect.isTrue(validateRan);
-}
diff --git a/runtime/tests/vm/dart/entrypoints/tearoff_prologue_inline_test.dart b/runtime/tests/vm/dart/entrypoints/tearoff_prologue_inline_test.dart
deleted file mode 100644
index 3ccf462..0000000
--- a/runtime/tests/vm/dart/entrypoints/tearoff_prologue_inline_test.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
-
-import "tearoff_prologue.dart";
-
-main(args) => test(args);
diff --git a/runtime/tests/vm/dart/entrypoints/tearoff_prologue_noinline_test.dart b/runtime/tests/vm/dart/entrypoints/tearoff_prologue_noinline_test.dart
deleted file mode 100644
index 4f1bbcd..0000000
--- a/runtime/tests/vm/dart/entrypoints/tearoff_prologue_noinline_test.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
-
-import "tearoff_prologue.dart";
-
-main(args) => test(args);
diff --git a/runtime/tests/vm/dart/entrypoints/tearoff_prologue_test.dart b/runtime/tests/vm/dart/entrypoints/tearoff_prologue_test.dart
new file mode 100644
index 0000000..47d1c89
--- /dev/null
+++ b/runtime/tests/vm/dart/entrypoints/tearoff_prologue_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// No type checks are removed here, but we can skip the argument count check.
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
+
+import "package:expect/expect.dart";
+import "common.dart";
+
+class C<T> {
+  @NeverInline
+  @pragma("vm:testing.unsafe.trace-entrypoints-fn", validateTearoff)
+  void samir1(T x) {
+    if (x == -1) {
+      throw "oh no";
+    }
+  }
+}
+
+main(List<String> args) {
+  var c = new C<int>();
+  var f = c.samir1;
+
+  // Warmup.
+  expectedEntryPoint = -1;
+  expectedTearoffEntryPoint = -1;
+  for (int i = 0; i < 100; ++i) {
+    f(i);
+  }
+
+  expectedEntryPoint = 0;
+  expectedTearoffEntryPoint = 1;
+  int iterations = benchmarkMode ? 100000000 : 100;
+  for (int i = 0; i < iterations; ++i) {
+    f(i);
+  }
+
+  Expect.isTrue(validateRan);
+}
diff --git a/runtime/tests/vm/dart/entrypoints/tearoff.dart b/runtime/tests/vm/dart/entrypoints/tearoff_test.dart
similarity index 74%
rename from runtime/tests/vm/dart/entrypoints/tearoff.dart
rename to runtime/tests/vm/dart/entrypoints/tearoff_test.dart
index cdebd3a..356a819 100644
--- a/runtime/tests/vm/dart/entrypoints/tearoff.dart
+++ b/runtime/tests/vm/dart/entrypoints/tearoff_test.dart
@@ -1,6 +1,9 @@
 // Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
 
 // Test that typed calls against tearoffs go into the unchecked entrypoint.
 
@@ -16,7 +19,7 @@
   }
 }
 
-test(List<String> args) {
+main(List<String> args) {
   var f = (new C<int>()).target1;
 
   // Warmup.
diff --git a/runtime/tests/vm/dart/kernel_determinism_test.dart b/runtime/tests/vm/dart/kernel_determinism_test.dart
new file mode 100644
index 0000000..ed3ab3d
--- /dev/null
+++ b/runtime/tests/vm/dart/kernel_determinism_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify creating an incremental kernel file twice generates the same bits.
+
+import 'dart:async';
+import 'snapshot_test_helper.dart';
+
+int fib(int n) {
+  if (n <= 1) return 1;
+  return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main(List<String> args) async {
+  if (args.contains('--child')) {
+    print(fib(35));
+    return;
+  }
+
+  await checkDeterministicSnapshot("kernel", "");
+}
diff --git a/runtime/tests/vm/dart/regress_34755_test.dart b/runtime/tests/vm/dart/regress_34755_test.dart
new file mode 100644
index 0000000..c13cfcf
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_34755_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test checking that null is handled correctly at the call-sites that
+// are tracking static type exactness.
+
+import 'package:expect/expect.dart';
+
+void invokeAdd(List<int> l) {
+  l.add(10);
+}
+
+void main() {
+  Expect.throws(() => invokeAdd(null), (error) => error is NoSuchMethodError);
+}
diff --git a/runtime/tests/vm/dart/snapshot_test_helper.dart b/runtime/tests/vm/dart/snapshot_test_helper.dart
index ef65c1f..6c0cd2f 100644
--- a/runtime/tests/vm/dart/snapshot_test_helper.dart
+++ b/runtime/tests/vm/dart/snapshot_test_helper.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 import 'dart:io';
+import 'dart:math';
 
 import 'package:expect/expect.dart';
 import 'package:path/path.dart' as p;
@@ -63,6 +64,8 @@
   final snapshot2Path = p.join(temp.path, 'snapshot2');
 
   try {
+    print("Version ${Platform.version}");
+
     final generate1Result = await runDartBinary('GENERATE SNAPSHOT 1', [
       '--deterministic',
       '--snapshot=$snapshot1Path',
@@ -84,12 +87,13 @@
     var snapshot1Bytes = await new File(snapshot1Path).readAsBytes();
     var snapshot2Bytes = await new File(snapshot2Path).readAsBytes();
 
-    Expect.equals(snapshot1Bytes.length, snapshot2Bytes.length);
-    for (var i = 0; i < snapshot1Bytes.length; i++) {
+    var minLength = min(snapshot1Bytes.length, snapshot2Bytes.length);
+    for (var i = 0; i < minLength; i++) {
       if (snapshot1Bytes[i] != snapshot2Bytes[i]) {
-        Expect.fail("Snapshots are not bitwise equal!");
+        Expect.fail("Snapshots differ at byte $i");
       }
     }
+    Expect.equals(snapshot1Bytes.length, snapshot2Bytes.length);
   } finally {
     await temp.delete(recursive: true);
   }
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index cfd49dc..2187ffd 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -17,19 +17,21 @@
 cc/IsolateReload_PendingUnqualifiedCall_InstanceToStatic: Fail # Issue 32981
 cc/IsolateReload_PendingUnqualifiedCall_StaticToInstance: Fail # Issue 32981
 cc/IsolateReload_RunNewFieldInitializersWithGenerics: Fail # Issue 32299
-cc/Profiler_FunctionInline: Pass, Fail # Flaky failure.
-cc/Profiler_InliningIntervalBoundry: Skip # Differences in ia32, debug, release
 cc/SNPrint_BadArgs: Crash, Fail # These tests are expected to crash on all platforms.
 dart/data_uri_import_test/none: SkipByDesign
 dart/snapshot_version_test: Skip # This test is a Dart1 test (script snapshot)
 dart/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
 dart/stack_overflow_shared_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
 
+[ $mode == debug ]
+dart/appjit_cha_deopt_test: Pass, Slow # Quite slow in debug mode, uses --optimization-counter-threshold=100
+
 [ $builder_tag == asan ]
 cc/CodeImmutability: Fail, OK # Address Sanitizer turns a crash into a failure.
 
 [ $builder_tag == optimization_counter_threshold ]
 dart/appjit*: SkipByDesign # Test needs to a particular opt-counter value
+dart/kernel_determinism_test: SkipSlow
 
 [ $compiler == app_jitk ]
 dart/data_uri_import_test/utf16: MissingRuntimeError
@@ -104,8 +106,6 @@
 
 [ $system == windows ]
 cc/CorelibCompilerStats: Skip
-cc/Profiler_ContextAllocation: Fail, Pass # Flaky on Windows --- sometimes give "profiler_test.cc: 1107: error: expected: !walker.Down()"
-cc/Service_Profile: Skip
 cc/GenKernelKernelLoadKernel: Skip  # Issue 34542.
 cc/GenKernelKernelReadAllBytecode: Skip  # Issue 34393.
 cc/GenKernelKernelCombined: Skip  # Issue 34393.
@@ -118,29 +118,6 @@
 [ !$checked && !$strong && $runtime == vm ]
 dart/redirection_type_shuffling_test/00: MissingCompileTimeError
 
-# Following tests are failing in a weird way on macos/ia32/debug builds
-# need to investigate.
-[ $runtime == vm && $system == macos ]
-cc/Profiler_ArrayAllocation: Skip # Issue 34493
-cc/Profiler_BasicSourcePosition: Skip # Issue 34493
-cc/Profiler_BasicSourcePositionOptimized: Skip # Issue 34493
-cc/Profiler_BinaryOperatorSourcePosition: Skip # Issue 34493
-cc/Profiler_BinaryOperatorSourcePositionOptimized: Skip # Issue 34493
-cc/Profiler_ChainedSamples: Skip # Issue 34493
-cc/Profiler_ClosureAllocation: Skip # Issue 34493
-cc/Profiler_CodeTicks: Skip # Issue 34493
-cc/Profiler_ContextAllocation: Skip # Issue 34493
-cc/Profiler_FunctionInline: Skip # Issue 34493
-cc/Profiler_FunctionTicks: Skip # Issue 34493
-cc/Profiler_IntrinsicAllocation: Skip # Issue 34493
-cc/Profiler_SourcePosition: Skip # Issue 34493
-cc/Profiler_SourcePositionOptimized: Skip # Issue 34493
-cc/Profiler_StringAllocation: Skip # Issue 34493
-cc/Profiler_StringInterpolation: Skip # Issue 34493
-cc/Profiler_ToggleRecordAllocation: Skip # Issue 34493
-cc/Profiler_TrivialRecordAllocation: Skip # Issue 34493
-cc/Profiler_TypedArrayAllocation: Skip # Issue 34493
-
 [ $arch != simarm && $arch != simarm64 && $arch != simdbc64 && ($compiler == dartk || $compiler == dartkb) && $hot_reload ]
 dart/data_uri_import_test/base64: Crash
 dart/data_uri_import_test/nocharset: Crash
@@ -149,18 +126,6 @@
 dart/data_uri_import_test/utf16: Crash
 dart/data_uri_import_test/wrongmime: Crash
 
-[ $arch == x64 && ($compiler == dartk || $compiler == dartkb) && $system == windows && $strong && $mode == release ]
-cc/Profiler_BasicSourcePosition: Fail # http://dartbug.com/33224
-cc/Profiler_CodeTicks: Fail # dartbug.com/33337
-
-[ $arch == x64 && $system == windows ]
-cc/Profiler_BinaryOperatorSourcePositionOptimized: Pass, Fail # Issue 31137
-cc/Profiler_ClosureAllocation: Pass, Fail # Issue 31137
-cc/Profiler_IntrinsicAllocation: Pass, Fail # Issue 31137
-cc/Profiler_SourcePositionOptimized: Pass, Fail # Issue 31137
-cc/Profiler_StringAllocation: Pass, Fail # Issue 31137
-cc/Profiler_TypedArrayAllocation: Pass, Fail # Issue 31137
-
 [ $builder_tag == asan && $mode == debug && ($runtime == dart_precompiled || $runtime == vm) ]
 cc/Dart2JSCompileAll: SkipSlow # Timeout.
 
@@ -195,11 +160,6 @@
 cc/Debugger_SetBreakpointInPartOfLibrary: Crash
 cc/IsolateReload_NotTypedefToTypedef: Fail
 cc/IsolateReload_TypedefToNotTypedef: Fail
-cc/Profiler_BasicSourcePositionOptimized: Skip
-cc/Profiler_BinaryOperatorSourcePositionOptimized: Skip
-cc/Profiler_GetSourceReport: Fail
-cc/Profiler_SourcePositionOptimized: Fail
-cc/Profiler_SourcePositionOptimized: Skip
 cc/SourceReport_CallSites_PolymorphicCall: Fail
 cc/SourceReport_CallSites_SimpleCall: Fail
 cc/SourceReport_Coverage_AllFunctions: Fail
@@ -226,9 +186,6 @@
 
 [ ($compiler == dartk || $compiler == dartkb) && $system == windows ]
 cc/IsolateReload_LibraryLookup: Fail, Crash
-cc/Profiler_FunctionTicks: Fail, Pass
-cc/Profiler_ToggleRecordAllocation: Fail, Pass
-cc/Profiler_TrivialRecordAllocation: Fail, Pass
 
 [ $arch == x64 && ($compiler == dartk || $compiler == dartkb) && $system == windows && $mode == release ]
 cc/Service_Address: Fail
@@ -257,9 +214,11 @@
 
 [ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
 dart/data_uri_spawn_test: Skip # Timeout
+dart/kernel_determinism_test: SkipSlow
 
 [ $compiler != dartk && $compiler != dartkb && $compiler != none ]
 dart/appjit*: SkipByDesign # Test needs to run from source
+dart/kernel_determinism_test: SkipByDesign # Test needs to run from source
 
 [ $compiler == dartkp && ($runtime == dart_precompiled || $runtime == vm) ]
 dart/data_uri_import_test/utf16: MissingRuntimeError # UTF-16 data URIs work in dartk
diff --git a/runtime/tools/dartfuzz/README.md b/runtime/tools/dartfuzz/README.md
index ca5d676..b4909ed 100644
--- a/runtime/tools/dartfuzz/README.md
+++ b/runtime/tools/dartfuzz/README.md
@@ -34,6 +34,7 @@
     run_dartfuzz_test.py  [--help]
                           [--isolates ISOLATES ]
                           [--repeat REPEAT]
+                          [--time TIME]
                           [--true_divergence]
                           [--mode1 MODE]
                           [--mode2 MODE]
@@ -43,23 +44,24 @@
     --help            : prints help and exits
     --isolates        : number of isolates in the session (1 by default)
     --repeat          : number of tests to run (1000 by default)
+    --time            : time limit in seconds (none by default)
     --show-stats      : show statistics during session (true by default)
     --true-divergence : only report true divergences (true by default)
     --dart-top        : sets DART_TOP explicitly through command line
     --mode1           : m1
     --mode2           : m2, and values one of
-        jit-[debug-]ia32    = Dart JIT (ia32)
-        jit-[debug-]x64     = Dart JIT (x64)
-        jit-[debug-]arm32   = Dart JIT (simarm)
-        jit-[debug-]arm64   = Dart JIT (simarm64)
-        jit-[debug-]dbc     = Dart JIT (simdbc)
-        jit-[debug-]dbc64   = Dart JIT (simdbc64)
-        aot-[debug-]x64     = Dart AOT (x64)
-        aot-[debug-]arm64   = Dart AOT (simarm64)
-        kbc-int-[debug-]x64 = Dart KBC (interpreted bytecode)
-        kbc-mix-[debug-]x64 = Dart KBC (mixed-mode bytecode)
-        kbc-cmp-[debug-]x64 = Dart KBC (compiled bytecode)
-        js                  = dart2js + JS
+        jit-[opt-][debug-]ia32  = Dart JIT (ia32)
+        jit-[opt-][debug-]x64   = Dart JIT (x64)
+        jit-[opt-][debug-]arm32 = Dart JIT (simarm)
+        jit-[opt-][debug-]arm64 = Dart JIT (simarm64)
+        jit-[opt-][debug-]dbc   = Dart JIT (simdbc)
+        jit-[opt-][debug-]dbc64 = Dart JIT (simdbc64)
+        aot-[debug-]x64         = Dart AOT (x64)
+        aot-[debug-]arm64       = Dart AOT (simarm64)
+        kbc-int-[debug-]x64     = Dart KBC (interpreted bytecode)
+        kbc-mix-[debug-]x64     = Dart KBC (mixed-mode bytecode)
+        kbc-cmp-[debug-]x64     = Dart KBC (compiled bytecode)
+        js                      = dart2js + JS
 
 If no modes are given, a random JIT and/or AOT combination is used.
 
diff --git a/runtime/tools/dartfuzz/dartfuzz_test.dart b/runtime/tools/dartfuzz/dartfuzz_test.dart
index 417c937..f1b9132 100644
--- a/runtime/tools/dartfuzz/dartfuzz_test.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_test.dart
@@ -13,7 +13,7 @@
 
 const debug = false;
 const sigkill = 9;
-const timeout = 30; // in seconds
+const timeout = 60; // in seconds
 
 // Exit code of running a test.
 enum ResultCode { success, timeout, error }
@@ -51,8 +51,11 @@
   // Factory.
   static TestRunner getTestRunner(
       String mode, String top, String tmp, Map<String, String> env) {
+    if (mode.startsWith('jit-opt'))
+      return new TestRunnerJIT(
+          getTag(mode), top, tmp, env, ['--optimization_counter_threshold=1']);
     if (mode.startsWith('jit'))
-      return new TestRunnerJIT(getTag(mode), top, tmp, env);
+      return new TestRunnerJIT(getTag(mode), top, tmp, env, []);
     if (mode.startsWith('aot'))
       return new TestRunnerAOT(getTag(mode), top, tmp, env);
     if (mode.startsWith('kbc'))
@@ -81,21 +84,24 @@
 
 /// Concrete test runner of Dart JIT.
 class TestRunnerJIT implements TestRunner {
-  TestRunnerJIT(String tag, String top, String tmp, Map<String, String> e) {
-    description = 'JIT-${tag}';
+  TestRunnerJIT(String tag, String top, String tmp, Map<String, String> e,
+      List<String> extra_flags) {
+    description = extra_flags.length == 0 ? 'JIT-${tag}' : 'JIT-OPT-${tag}';
     dart = '$top/out/$tag/dart';
     fileName = '$tmp/fuzz.dart';
     env = e;
+    cmd = [dart] + extra_flags + [fileName];
   }
 
   TestResult run() {
-    return runCommand([dart, fileName], env);
+    return runCommand(cmd, env);
   }
 
   String description;
   String dart;
   String fileName;
   Map<String, String> env;
+  List<String> cmd;
 }
 
 /// Concrete test runner of Dart AOT.
@@ -167,8 +173,8 @@
   String dill;
   String dart;
   String fileName;
-  List<String> cmd;
   Map<String, String> env;
+  List<String> cmd;
 }
 
 /// Concrete test runner of Dart2JS.
@@ -198,8 +204,8 @@
 
 /// Class to run fuzz testing.
 class DartFuzzTest {
-  DartFuzzTest(this.env, this.repeat, this.trueDivergence, this.showStats,
-      this.top, this.mode1, this.mode2);
+  DartFuzzTest(this.env, this.repeat, this.time, this.trueDivergence,
+      this.showStats, this.top, this.mode1, this.mode2);
 
   int run() {
     setup();
@@ -216,8 +222,10 @@
       runTest();
       if (showStats) {
         showStatistics();
-      } else if ((i & 31) == 31) {
-        print('\n${isolate}: busy @${numTests}....');
+      }
+      // Timeout?
+      if (timeIsUp()) {
+        break;
       }
     }
 
@@ -238,6 +246,11 @@
     isolate = 'Isolate (${tmpDir.path}) '
         '${runner1.description} - ${runner2.description}';
 
+    start_time = new DateTime.now().millisecondsSinceEpoch;
+    current_time = start_time;
+    report_time = start_time;
+    end_time = start_time + max(0, time - timeout) * 1000;
+
     numTests = 0;
     numSuccess = 0;
     numNotRun = 0;
@@ -245,6 +258,22 @@
     numDivergences = 0;
   }
 
+  bool timeIsUp() {
+    if (time > 0) {
+      current_time = new DateTime.now().millisecondsSinceEpoch;
+      if (current_time > end_time) {
+        return true;
+      }
+      // Report every 10 minutes.
+      if ((current_time - report_time) > (10 * 60 * 1000)) {
+        print(
+            '\n${isolate}: busy @${numTests} ${current_time - start_time} seconds....');
+        report_time = current_time;
+      }
+    }
+    return false;
+  }
+
   void cleanup() {
     tmpDir.delete(recursive: true);
   }
@@ -315,6 +344,7 @@
   // Context.
   final Map<String, String> env;
   final int repeat;
+  final int time;
   final bool trueDivergence;
   final bool showStats;
   final String top;
@@ -330,6 +360,12 @@
   String isolate;
   int seed;
 
+  // Timing
+  int start_time;
+  int current_time;
+  int report_time;
+  int end_time;
+
   // Stats.
   int numTests;
   int numSuccess;
@@ -340,8 +376,8 @@
 
 /// Class to start fuzz testing session.
 class DartFuzzTestSession {
-  DartFuzzTestSession(this.isolates, this.repeat, this.trueDivergence,
-      this.showStats, String tp, this.mode1, this.mode2)
+  DartFuzzTestSession(this.isolates, this.repeat, this.time,
+      this.trueDivergence, this.showStats, String tp, this.mode1, this.mode2)
       : top = getTop(tp) {}
 
   start() async {
@@ -349,6 +385,11 @@
     print('Fuzz Version    : ${version}');
     print('Isolates        : ${isolates}');
     print('Tests           : ${repeat}');
+    if (time > 0) {
+      print('Time            : ${time} seconds');
+    } else {
+      print('Time            : unlimited');
+    }
     print('True Divergence : ${trueDivergence}');
     print('Show Stats      : ${showStats}');
     print('Dart Dev        : ${top}');
@@ -379,8 +420,15 @@
     try {
       final m1 = getMode(session.mode1, null);
       final m2 = getMode(session.mode2, m1);
-      final fuzz = new DartFuzzTest(Platform.environment, session.repeat,
-          session.trueDivergence, session.showStats, session.top, m1, m2);
+      final fuzz = new DartFuzzTest(
+          Platform.environment,
+          session.repeat,
+          session.time,
+          session.trueDivergence,
+          session.showStats,
+          session.top,
+          m1,
+          m2);
       divergences = fuzz.run();
     } catch (e) {
       print('Isolate: $e');
@@ -404,7 +452,7 @@
     // Random when not set.
     if (mode == null || mode == '') {
       // Pick a mode at random (cluster), different from other.
-      const cluster_modes = 20;
+      int cluster_modes = modes.length - 3;
       Random rand = new Random();
       do {
         mode = modes[rand.nextInt(cluster_modes)];
@@ -420,6 +468,7 @@
   // Context.
   final int isolates;
   final int repeat;
+  final int time;
   final bool trueDivergence;
   final bool showStats;
   final String top;
@@ -432,6 +481,18 @@
   // Supported modes.
   static const List<String> modes = [
     // Cluster options:
+    'jit-opt-debug-ia32',
+    'jit-opt-debug-x64',
+    'jit-opt-debug-arm32',
+    'jit-opt-debug-arm64',
+    'jit-opt-debug-dbc',
+    'jit-opt-debug-dbc64',
+    'jit-opt-ia32',
+    'jit-opt-x64',
+    'jit-opt-arm32',
+    'jit-opt-arm64',
+    'jit-opt-dbc',
+    'jit-opt-dbc64',
     'jit-debug-ia32',
     'jit-debug-x64',
     'jit-debug-arm32',
@@ -453,8 +514,8 @@
     'kbc-cmp-x64',
     'kbc-mix-x64',
     // Times out often:
-    'aot-arm64',
     'aot-debug-arm64',
+    'aot-arm64',
     // Too many divergences (due to arithmetic):
     'js'
   ];
@@ -466,6 +527,7 @@
   final parser = new ArgParser()
     ..addOption('isolates', help: 'number of isolates to use', defaultsTo: '1')
     ..addOption('repeat', help: 'number of tests to run', defaultsTo: '1000')
+    ..addOption('time', help: 'time limit in seconds', defaultsTo: '0')
     ..addFlag('true-divergence',
         negatable: true, help: 'only report true divergences', defaultsTo: true)
     ..addFlag('show-stats',
@@ -476,7 +538,9 @@
     // Undocumented options for cluster runs.
     ..addOption('shards',
         help: 'number of shards used in cluster run', defaultsTo: '1')
-    ..addOption('shard', help: 'shard id in cluster run', defaultsTo: '1');
+    ..addOption('shard', help: 'shard id in cluster run', defaultsTo: '1')
+    ..addOption('output_directory',
+        help: 'path to output (ignored)', defaultsTo: null);
 
   // Starts fuzz testing session.
   try {
@@ -489,6 +553,7 @@
     new DartFuzzTestSession(
             int.parse(results['isolates']),
             int.parse(results['repeat']),
+            int.parse(results['time']),
             results['true-divergence'],
             results['show-stats'],
             results['dart-top'],
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index c2f3f55..60078c6 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -99,6 +99,8 @@
   bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
   bin::Builtin::SetNativeResolver(bin::Builtin::kCLILibrary);
   TransitionNativeToVM transition(thread);
+  StackZone zone(thread);
+  HANDLESCOPE(thread);
   Timer timer(true, "Compile all of Core lib benchmark");
   timer.Start();
   const Error& error =
@@ -423,24 +425,33 @@
 // Measure frame lookup during stack traversal.
 //
 static void StackFrame_accessFrame(Dart_NativeArguments args) {
-  const int kNumIterations = 100;
-  Code& code = Code::Handle();
   Timer timer(true, "LookupDartCode benchmark");
   timer.Start();
-  for (int i = 0; i < kNumIterations; i++) {
-    StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
-                              Thread::Current(),
-                              StackFrameIterator::kNoCrossThreadIteration);
-    StackFrame* frame = frames.NextFrame();
-    while (frame != NULL) {
-      if (frame->IsStubFrame()) {
-        code = frame->LookupDartCode();
-        EXPECT(code.function() == Function::null());
-      } else if (frame->IsDartFrame()) {
-        code = frame->LookupDartCode();
-        EXPECT(code.function() != Function::null());
+  {
+    Thread* thread = Thread::Current();
+    TransitionNativeToVM transition(thread);
+    const int kNumIterations = 100;
+    Code& code = Code::Handle(thread->zone());
+    Bytecode& bytecode = Bytecode::Handle(thread->zone());
+    for (int i = 0; i < kNumIterations; i++) {
+      StackFrameIterator frames(ValidationPolicy::kDontValidateFrames, thread,
+                                StackFrameIterator::kNoCrossThreadIteration);
+      StackFrame* frame = frames.NextFrame();
+      while (frame != NULL) {
+        if (frame->IsStubFrame()) {
+          code = frame->LookupDartCode();
+          EXPECT(code.function() == Function::null());
+        } else if (frame->IsDartFrame()) {
+          if (frame->is_interpreted()) {
+            bytecode = frame->LookupDartBytecode();
+            EXPECT(bytecode.function() != Function::null());
+          } else {
+            code = frame->LookupDartCode();
+            EXPECT(code.function() != Function::null());
+          }
+        }
+        frame = frames.NextFrame();
       }
-      frame = frames.NextFrame();
     }
   }
   timer.Stop();
@@ -532,9 +543,13 @@
   // Need to load the script into the dart: core library due to
   // the import of dart:_internal.
   TestCase::LoadCoreTestScript(kScriptChars, NULL);
-  Api::CheckAndFinalizePendingClasses(thread);
 
   TransitionNativeToVM transition(thread);
+  StackZone zone(thread);
+  HANDLESCOPE(thread);
+
+  Api::CheckAndFinalizePendingClasses(thread);
+
   // Write snapshot with object content.
   FullSnapshotWriter writer(Snapshot::kFull, &vm_snapshot_data_buffer,
                             &isolate_snapshot_data_buffer, &malloc_allocator,
@@ -569,9 +584,13 @@
   // Need to load the script into the dart: core library due to
   // the import of dart:_internal.
   TestCase::LoadCoreTestScript(kScriptChars, NULL);
-  Api::CheckAndFinalizePendingClasses(thread);
 
   TransitionNativeToVM transition(thread);
+  StackZone zone(thread);
+  HANDLESCOPE(thread);
+
+  Api::CheckAndFinalizePendingClasses(thread);
+
   // Write snapshot with object content.
   FullSnapshotWriter writer(Snapshot::kFull, &vm_snapshot_data_buffer,
                             &isolate_snapshot_data_buffer, &malloc_allocator,
@@ -611,7 +630,12 @@
       "\n";
   const intptr_t kLoopCount = 1000000;
   TestCase::LoadTestScript(kScriptChars, NULL);
-  Api::CheckAndFinalizePendingClasses(thread);
+  {
+    TransitionNativeToVM transition(thread);
+    StackZone zone(thread);
+    HANDLESCOPE(thread);
+    Api::CheckAndFinalizePendingClasses(thread);
+  }
   Dart_Isolate isolate = Dart_CurrentIsolate();
   Timer timer(true, "Enter and Exit isolate");
   timer.Start();
@@ -626,6 +650,8 @@
 
 BENCHMARK(SerializeNull) {
   TransitionNativeToVM transition(thread);
+  StackZone zone(thread);
+  HANDLESCOPE(thread);
   const Object& null_object = Object::Handle();
   const intptr_t kLoopCount = 1000000;
   Timer timer(true, "Serialize Null");
@@ -648,6 +674,8 @@
 
 BENCHMARK(SerializeSmi) {
   TransitionNativeToVM transition(thread);
+  StackZone zone(thread);
+  HANDLESCOPE(thread);
   const Integer& smi_object = Integer::Handle(Smi::New(42));
   const intptr_t kLoopCount = 1000000;
   Timer timer(true, "Serialize Smi");
@@ -670,6 +698,8 @@
 
 BENCHMARK(SimpleMessage) {
   TransitionNativeToVM transition(thread);
+  StackZone zone(thread);
+  HANDLESCOPE(thread);
   const Array& array_object = Array::Handle(Array::New(2));
   array_object.SetAt(0, Integer::Handle(Smi::New(42)));
   array_object.SetAt(1, Object::Handle());
@@ -704,6 +734,8 @@
   Dart_Handle h_result = Dart_Invoke(h_lib, NewString("makeMap"), 0, NULL);
   EXPECT_VALID(h_result);
   TransitionNativeToVM transition(thread);
+  StackZone zone(thread);
+  HANDLESCOPE(thread);
   Instance& map = Instance::Handle();
   map ^= Api::UnwrapHandle(h_result);
   const intptr_t kLoopCount = 100;
diff --git a/runtime/vm/benchmark_test.h b/runtime/vm/benchmark_test.h
index eb08041..64962b9 100644
--- a/runtime/vm/benchmark_test.h
+++ b/runtime/vm/benchmark_test.h
@@ -43,8 +43,6 @@
     BenchmarkIsolateScope __isolate__(benchmark);                              \
     Thread* __thread__ = Thread::Current();                                    \
     ASSERT(__thread__->isolate() == benchmark->isolate());                     \
-    StackZone __zone__(__thread__);                                            \
-    HandleScope __hs__(__thread__);                                            \
     Dart_BenchmarkHelper##name(benchmark, __thread__);                         \
     MallocHooks::set_stack_trace_collection_enabled(                           \
         __stack_trace_collection_enabled__);                                   \
diff --git a/runtime/vm/bootstrap_natives.cc b/runtime/vm/bootstrap_natives.cc
index fb3d08b..e02c6fa 100644
--- a/runtime/vm/bootstrap_natives.cc
+++ b/runtime/vm/bootstrap_natives.cc
@@ -34,7 +34,9 @@
 Dart_NativeFunction BootstrapNatives::Lookup(Dart_Handle name,
                                              int argument_count,
                                              bool* auto_setup_scope) {
-  const Object& obj = Object::Handle(Api::UnwrapHandle(name));
+  Thread* thread = Thread::Current();
+  TransitionNativeToVM transition(thread);
+  const Object& obj = Object::Handle(thread->zone(), Api::UnwrapHandle(name));
   if (!obj.IsString()) {
     return NULL;
   }
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 04fb131..3d717b7 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -58,7 +58,7 @@
 
 void AddSuperType(const AbstractType& type,
                   GrowableArray<intptr_t>* finalized_super_classes) {
-  ASSERT(type.HasResolvedTypeClass());
+  ASSERT(type.HasTypeClass());
   ASSERT(!type.IsDynamicType());
   if (type.IsObjectType()) {
     return;
@@ -86,7 +86,7 @@
   AbstractType& super_type = Type::Handle();
   super_type = cls.super_type();
   if (!super_type.IsNull()) {
-    if (!super_type.IsMalformed() && super_type.HasResolvedTypeClass()) {
+    if (!super_type.IsMalformed() && super_type.HasTypeClass()) {
       cls ^= super_type.type_class();
       if (cls.is_finalized()) {
         AddSuperType(super_type, finalized_super_classes);
@@ -157,7 +157,7 @@
   for (intptr_t i = 0; i < interfaces.Length(); ++i) {
     type ^= interfaces.At(i);
     if (type.IsMalformed()) continue;
-    if (!type.HasResolvedTypeClass()) continue;
+    if (!type.HasTypeClass()) continue;
     ifc ^= type.type_class();
     for (intptr_t j = 0; j < cids->length(); ++j) {
       if ((*cids)[j] == ifc.id()) {
@@ -309,53 +309,12 @@
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-static bool IsLoaded(const Type& type) {
-  if (type.HasResolvedTypeClass()) {
-    return true;
-  }
-  const UnresolvedClass& unresolved_class =
-      UnresolvedClass::Handle(type.unresolved_class());
-  const Object& prefix =
-      Object::Handle(unresolved_class.library_or_library_prefix());
-  if (prefix.IsNull()) {
-    return true;
-  } else if (prefix.IsLibraryPrefix()) {
-    return LibraryPrefix::Cast(prefix).is_loaded();
-  } else {
-    return true;
-  }
-}
-
-// Resolve unresolved_class in the library of cls, or return null.
-RawClass* ClassFinalizer::ResolveClass(
-    const Class& cls,
-    const UnresolvedClass& unresolved_class) {
-  const String& class_name = String::Handle(unresolved_class.ident());
-  Library& lib = Library::Handle();
-  Class& resolved_class = Class::Handle();
-  if (unresolved_class.library_or_library_prefix() == Object::null()) {
-    lib = cls.library();
-    ASSERT(!lib.IsNull());
-    resolved_class = lib.LookupClass(class_name);
-  } else {
-    const Object& prefix =
-        Object::Handle(unresolved_class.library_or_library_prefix());
-
-    if (prefix.IsLibraryPrefix()) {
-      resolved_class = LibraryPrefix::Cast(prefix).LookupClass(class_name);
-    } else {
-      resolved_class = Library::Cast(prefix).LookupClass(class_name);
-    }
-  }
-  return resolved_class.raw();
-}
-
 void ClassFinalizer::ResolveRedirectingFactory(const Class& cls,
                                                const Function& factory) {
   const Function& target = Function::Handle(factory.RedirectionTarget());
   if (target.IsNull()) {
     Type& type = Type::Handle(factory.RedirectionType());
-    if (!type.IsMalformed() && IsLoaded(type)) {
+    if (!type.IsMalformed()) {
       const GrowableObjectArray& visited_factories =
           GrowableObjectArray::Handle(GrowableObjectArray::New());
       ResolveRedirectingFactoryTarget(cls, factory, visited_factories);
@@ -516,25 +475,7 @@
   // unresolved is the correct thing to do.
 
   // Lookup the type class if necessary.
-  Class& type_class = Class::Handle();
-  if (type.HasResolvedTypeClass()) {
-    type_class = type.type_class();
-  } else {
-    const UnresolvedClass& unresolved_class =
-        UnresolvedClass::Handle(type.unresolved_class());
-    type_class = ResolveClass(cls, unresolved_class);
-    if (type_class.IsNull()) {
-      // The type class could not be resolved. The type is malformed.
-      FinalizeMalformedType(Error::Handle(),  // No previous error.
-                            Script::Handle(cls.script()), type,
-                            "cannot resolve class '%s' from '%s'",
-                            String::Handle(unresolved_class.Name()).ToCString(),
-                            String::Handle(cls.Name()).ToCString());
-      return;
-    }
-    // Replace unresolved class with resolved type class.
-    type.set_type_class(type_class);
-  }
+  Class& type_class = Class::Handle(type.type_class());
   // Promote the type to a function type in case its type class is a typedef.
   // Note that the type may already be a function type if it was parsed as a
   // formal parameter function type.
@@ -1596,10 +1537,8 @@
         // If the redirection type is from a deferred library and is not
         // yet loaded, do not attempt to resolve.
         Type& type = Type::Handle(zone, function.RedirectionType());
-        if (IsLoaded(type)) {
-          type ^= FinalizeType(cls, type);
-          function.SetRedirectionType(type);
-        }
+        type ^= FinalizeType(cls, type);
+        function.SetRedirectionType(type);
       }
     }
   }
@@ -2072,7 +2011,7 @@
   }
   Type& mixin_type = Type::Handle(mixin_app_class.mixin());
   ASSERT(!mixin_type.IsNull());
-  ASSERT(mixin_type.HasResolvedTypeClass());
+  ASSERT(mixin_type.HasTypeClass());
   const Class& mixin_class = Class::Handle(mixin_type.type_class());
 
   if (FLAG_trace_class_finalization) {
@@ -2189,7 +2128,7 @@
   Zone* zone = Thread::Current()->zone();
   const Type& mixin_type = Type::Handle(zone, cls.mixin());
   ASSERT(!mixin_type.IsNull());
-  ASSERT(mixin_type.HasResolvedTypeClass());
+  ASSERT(mixin_type.HasTypeClass());
   const Class& mixin_cls = Class::Handle(zone, mixin_type.type_class());
   FinalizeClass(mixin_cls);
   // If the mixin is a mixin application alias class, there are no members to
@@ -2775,7 +2714,7 @@
     if (super_class.IsMixinApplication()) {
       const Type& mixin_type = Type::Handle(super_class.mixin());
       ASSERT(!mixin_type.IsNull());
-      ASSERT(mixin_type.HasResolvedTypeClass());
+      ASSERT(mixin_type.HasTypeClass());
       const Class& mixin_class = Class::Handle(mixin_type.type_class());
       if (!IsMixinCycleFree(mixin_class, visited)) {
         return false;
@@ -2791,7 +2730,7 @@
     const Class& cls,
     const Type& type,
     const GrowableObjectArray& collected_args) {
-  ASSERT(type.HasResolvedTypeClass());
+  ASSERT(type.HasTypeClass());
   Class& type_class = Class::Handle(type.type_class());
   TypeArguments& type_args = TypeArguments::Handle(type.arguments());
   const intptr_t num_type_parameters = type_class.NumTypeParameters();
@@ -2839,7 +2778,7 @@
   AbstractType& mixin_super_type =
       AbstractType::Handle(zone, mixin_app_type.super_type());
   ResolveType(cls, mixin_super_type);
-  ASSERT(mixin_super_type.HasResolvedTypeClass());  // Even if malformed.
+  ASSERT(mixin_super_type.HasTypeClass());  // Even if malformed.
   if (mixin_super_type.IsMalformedOrMalbounded()) {
     ReportError(Error::Handle(zone, mixin_super_type.error()));
   }
@@ -2867,7 +2806,7 @@
     mixin_type = mixin_app_type.MixinTypeAt(i);
     ASSERT(!mixin_type.IsNull());
     ResolveType(cls, mixin_type);
-    ASSERT(mixin_type.HasResolvedTypeClass());  // Even if malformed.
+    ASSERT(mixin_type.HasTypeClass());  // Even if malformed.
     ASSERT(mixin_type.IsType());
     if (mixin_type.IsMalformedOrMalbounded()) {
       ReportError(Error::Handle(zone, mixin_type.error()));
@@ -3302,11 +3241,10 @@
                                                    ...) {
   va_list args;
   va_start(args, format);
-  const UnresolvedClass& unresolved_class =
-      UnresolvedClass::Handle(UnresolvedClass::New(LibraryPrefix::Handle(),
-                                                   Symbols::Empty(), type_pos));
-  const Type& type = Type::Handle(
-      Type::New(unresolved_class, Object::null_type_arguments(), type_pos));
+  // TODO(regis): Are malformed types still used in strong mode? Probably not.
+  const Type& type =
+      Type::Handle(Type::New(Class::Handle(Object::dynamic_class()),
+                             Object::null_type_arguments(), type_pos));
   MarkTypeMalformed(prev_error, script, type, format, args);
   va_end(args);
   ASSERT(type.IsMalformed());
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index e8d70ac..3b36a23 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -118,8 +118,6 @@
   static bool IsMixinCycleFree(const Class& cls,
                                GrowableArray<intptr_t>* visited);
   static void CheckForLegalConstClass(const Class& cls);
-  static RawClass* ResolveClass(const Class& cls,
-                                const UnresolvedClass& unresolved_class);
   static void ResolveType(const Class& cls, const AbstractType& type);
   static void ResolveRedirectingFactoryTarget(
       const Class& cls,
diff --git a/runtime/vm/class_finalizer_test.cc b/runtime/vm/class_finalizer_test.cc
index 4ea8c25..42fee86 100644
--- a/runtime/vm/class_finalizer_test.cc
+++ b/runtime/vm/class_finalizer_test.cc
@@ -70,33 +70,4 @@
   EXPECT(!ClassFinalizer::ProcessPendingClasses());
 }
 
-static RawLibrary* NewLib(const char* url_chars) {
-  String& url = String::ZoneHandle(Symbols::New(Thread::Current(), url_chars));
-  return Library::New(url);
-}
-
-ISOLATE_UNIT_TEST_CASE(ClassFinalize_Resolve) {
-  Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  ObjectStore* object_store = isolate->object_store();
-  const GrowableObjectArray& pending_classes =
-      GrowableObjectArray::Handle(zone, object_store->pending_classes());
-  Class& rhb = Class::Handle(CreateTestClass("RhB"));
-  pending_classes.Add(rhb);
-  Class& sbb = Class::Handle(CreateTestClass("SBB"));
-  pending_classes.Add(sbb);
-  Library& lib = Library::Handle(NewLib("TestLib"));
-  lib.AddClass(rhb);
-  lib.AddClass(sbb);
-  const String& superclass_name = String::Handle(sbb.Name());
-  const UnresolvedClass& unresolved =
-      UnresolvedClass::Handle(UnresolvedClass::New(
-          LibraryPrefix::Handle(), superclass_name, TokenPosition::kNoSource));
-  const TypeArguments& type_arguments = TypeArguments::Handle();
-  rhb.set_super_type(
-      Type::Handle(Type::New(Object::Handle(unresolved.raw()), type_arguments,
-                             TokenPosition::kNoSource)));
-  EXPECT(ClassFinalizer::ProcessPendingClasses());
-}
-
 }  // namespace dart
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 69082af..f9f3441 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -90,7 +90,7 @@
       : SerializationCluster("Class"),
         predefined_(kNumPredefinedCids),
         objects_(num_cids) {}
-  virtual ~ClassSerializationCluster() {}
+  ~ClassSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawClass* cls = Class::RawCast(object);
@@ -175,7 +175,7 @@
 class ClassDeserializationCluster : public DeserializationCluster {
  public:
   ClassDeserializationCluster() {}
-  virtual ~ClassDeserializationCluster() {}
+  ~ClassDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     predefined_start_index_ = d->next_index();
@@ -280,91 +280,10 @@
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-class UnresolvedClassSerializationCluster : public SerializationCluster {
- public:
-  UnresolvedClassSerializationCluster()
-      : SerializationCluster("UnresolvedClass") {}
-  virtual ~UnresolvedClassSerializationCluster() {}
-
-  void Trace(Serializer* s, RawObject* object) {
-    RawUnresolvedClass* cls = UnresolvedClass::RawCast(object);
-    objects_.Add(cls);
-
-    RawObject** from = cls->from();
-    RawObject** to = cls->to();
-    for (RawObject** p = from; p <= to; p++) {
-      s->Push(*p);
-    }
-  }
-
-  void WriteAlloc(Serializer* s) {
-    s->WriteCid(kUnresolvedClassCid);
-    intptr_t count = objects_.length();
-    s->WriteUnsigned(count);
-    for (intptr_t i = 0; i < count; i++) {
-      RawUnresolvedClass* cls = objects_[i];
-      s->AssignRef(cls);
-    }
-  }
-
-  void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
-    for (intptr_t i = 0; i < count; i++) {
-      RawUnresolvedClass* cls = objects_[i];
-      RawObject** from = cls->from();
-      RawObject** to = cls->to();
-      for (RawObject** p = from; p <= to; p++) {
-        s->WriteRef(*p);
-      }
-      s->WriteTokenPosition(cls->ptr()->token_pos_);
-    }
-  }
-
- private:
-  GrowableArray<RawUnresolvedClass*> objects_;
-};
-#endif  // !DART_PRECOMPILED_RUNTIME
-
-class UnresolvedClassDeserializationCluster : public DeserializationCluster {
- public:
-  UnresolvedClassDeserializationCluster() {}
-  virtual ~UnresolvedClassDeserializationCluster() {}
-
-  void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, UnresolvedClass::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
-  }
-
-  void ReadFill(Deserializer* d) {
-    bool is_vm_object = d->isolate() == Dart::vm_isolate();
-
-    for (intptr_t id = start_index_; id < stop_index_; id++) {
-      RawUnresolvedClass* cls =
-          reinterpret_cast<RawUnresolvedClass*>(d->Ref(id));
-      Deserializer::InitializeHeader(cls, kUnresolvedClassCid,
-                                     UnresolvedClass::InstanceSize(),
-                                     is_vm_object);
-      RawObject** from = cls->from();
-      RawObject** to = cls->to();
-      for (RawObject** p = from; p <= to; p++) {
-        *p = d->ReadRef();
-      }
-      cls->ptr()->token_pos_ = d->ReadTokenPosition();
-    }
-  }
-};
-
-#if !defined(DART_PRECOMPILED_RUNTIME)
 class TypeArgumentsSerializationCluster : public SerializationCluster {
  public:
   TypeArgumentsSerializationCluster() : SerializationCluster("TypeArguments") {}
-  virtual ~TypeArgumentsSerializationCluster() {}
+  ~TypeArgumentsSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawTypeArguments* type_args = TypeArguments::RawCast(object);
@@ -413,7 +332,7 @@
 class TypeArgumentsDeserializationCluster : public DeserializationCluster {
  public:
   TypeArgumentsDeserializationCluster() {}
-  virtual ~TypeArgumentsDeserializationCluster() {}
+  ~TypeArgumentsDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -454,7 +373,7 @@
 class PatchClassSerializationCluster : public SerializationCluster {
  public:
   PatchClassSerializationCluster() : SerializationCluster("PatchClass") {}
-  virtual ~PatchClassSerializationCluster() {}
+  ~PatchClassSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawPatchClass* cls = PatchClass::RawCast(object);
@@ -501,7 +420,7 @@
 class PatchClassDeserializationCluster : public DeserializationCluster {
  public:
   PatchClassDeserializationCluster() {}
-  virtual ~PatchClassDeserializationCluster() {}
+  ~PatchClassDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -543,9 +462,10 @@
 class FunctionSerializationCluster : public SerializationCluster {
  public:
   FunctionSerializationCluster() : SerializationCluster("Function") {}
-  virtual ~FunctionSerializationCluster() {}
+  ~FunctionSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
+    Snapshot::Kind kind = s->kind();
     RawFunction* func = Function::RawCast(object);
     objects_.Add(func);
 
@@ -554,9 +474,11 @@
     for (RawObject** p = from; p <= to; p++) {
       s->Push(*p);
     }
-    if (s->kind() == Snapshot::kFullAOT) {
+    if (kind == Snapshot::kFull) {
+      NOT_IN_PRECOMPILED(s->Push(func->ptr()->bytecode_));
+    } else if (kind == Snapshot::kFullAOT) {
       s->Push(func->ptr()->code_);
-    } else if (s->kind() == Snapshot::kFullJIT) {
+    } else if (kind == Snapshot::kFullJIT) {
       NOT_IN_PRECOMPILED(s->Push(func->ptr()->unoptimized_code_));
       NOT_IN_PRECOMPILED(s->Push(func->ptr()->bytecode_));
       s->Push(func->ptr()->code_);
@@ -584,7 +506,9 @@
       for (RawObject** p = from; p <= to; p++) {
         s->WriteRef(*p);
       }
-      if (kind == Snapshot::kFullAOT) {
+      if (kind == Snapshot::kFull) {
+        NOT_IN_PRECOMPILED(s->WriteRef(func->ptr()->bytecode_));
+      } else if (kind == Snapshot::kFullAOT) {
         s->WriteRef(func->ptr()->code_);
       } else if (s->kind() == Snapshot::kFullJIT) {
         NOT_IN_PRECOMPILED(s->WriteRef(func->ptr()->unoptimized_code_));
@@ -613,7 +537,7 @@
 class FunctionDeserializationCluster : public DeserializationCluster {
  public:
   FunctionDeserializationCluster() {}
-  virtual ~FunctionDeserializationCluster() {}
+  ~FunctionDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -643,13 +567,16 @@
         *p = Object::null();
       }
 
-      if (kind == Snapshot::kFullAOT) {
+      if (kind == Snapshot::kFull) {
+        NOT_IN_PRECOMPILED(func->ptr()->bytecode_ =
+                               reinterpret_cast<RawBytecode*>(d->ReadRef()));
+      } else if (kind == Snapshot::kFullAOT) {
         func->ptr()->code_ = reinterpret_cast<RawCode*>(d->ReadRef());
       } else if (kind == Snapshot::kFullJIT) {
         NOT_IN_PRECOMPILED(func->ptr()->unoptimized_code_ =
                                reinterpret_cast<RawCode*>(d->ReadRef()));
         NOT_IN_PRECOMPILED(func->ptr()->bytecode_ =
-                               reinterpret_cast<RawCode*>(d->ReadRef()));
+                               reinterpret_cast<RawBytecode*>(d->ReadRef()));
         func->ptr()->code_ = reinterpret_cast<RawCode*>(d->ReadRef());
         func->ptr()->ic_data_array_ = reinterpret_cast<RawArray*>(d->ReadRef());
       }
@@ -736,7 +663,7 @@
 class ClosureDataSerializationCluster : public SerializationCluster {
  public:
   ClosureDataSerializationCluster() : SerializationCluster("ClosureData") {}
-  virtual ~ClosureDataSerializationCluster() {}
+  ~ClosureDataSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawClosureData* data = ClosureData::RawCast(object);
@@ -781,7 +708,7 @@
 class ClosureDataDeserializationCluster : public DeserializationCluster {
  public:
   ClosureDataDeserializationCluster() {}
-  virtual ~ClosureDataDeserializationCluster() {}
+  ~ClosureDataDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -818,7 +745,7 @@
 class SignatureDataSerializationCluster : public SerializationCluster {
  public:
   SignatureDataSerializationCluster() : SerializationCluster("SignatureData") {}
-  virtual ~SignatureDataSerializationCluster() {}
+  ~SignatureDataSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawSignatureData* data = SignatureData::RawCast(object);
@@ -861,7 +788,7 @@
 class SignatureDataDeserializationCluster : public DeserializationCluster {
  public:
   SignatureDataDeserializationCluster() {}
-  virtual ~SignatureDataDeserializationCluster() {}
+  ~SignatureDataDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -895,7 +822,7 @@
  public:
   RedirectionDataSerializationCluster()
       : SerializationCluster("RedirectionData") {}
-  virtual ~RedirectionDataSerializationCluster() {}
+  ~RedirectionDataSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawRedirectionData* data = RedirectionData::RawCast(object);
@@ -938,7 +865,7 @@
 class RedirectionDataDeserializationCluster : public DeserializationCluster {
  public:
   RedirectionDataDeserializationCluster() {}
-  virtual ~RedirectionDataDeserializationCluster() {}
+  ~RedirectionDataDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -973,7 +900,7 @@
 class FieldSerializationCluster : public SerializationCluster {
  public:
   FieldSerializationCluster() : SerializationCluster("Field") {}
-  virtual ~FieldSerializationCluster() {}
+  ~FieldSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawField* field = Field::RawCast(object);
@@ -1086,7 +1013,7 @@
 class FieldDeserializationCluster : public DeserializationCluster {
  public:
   FieldDeserializationCluster() {}
-  virtual ~FieldDeserializationCluster() {}
+  ~FieldDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -1159,7 +1086,7 @@
 class ScriptSerializationCluster : public SerializationCluster {
  public:
   ScriptSerializationCluster() : SerializationCluster("Script") {}
-  virtual ~ScriptSerializationCluster() {}
+  ~ScriptSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawScript* script = Script::RawCast(object);
@@ -1208,7 +1135,7 @@
 class ScriptDeserializationCluster : public DeserializationCluster {
  public:
   ScriptDeserializationCluster() {}
-  virtual ~ScriptDeserializationCluster() {}
+  ~ScriptDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -1251,7 +1178,7 @@
 class LibrarySerializationCluster : public SerializationCluster {
  public:
   LibrarySerializationCluster() : SerializationCluster("Library") {}
-  virtual ~LibrarySerializationCluster() {}
+  ~LibrarySerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawLibrary* lib = Library::RawCast(object);
@@ -1304,7 +1231,7 @@
 class LibraryDeserializationCluster : public DeserializationCluster {
  public:
   LibraryDeserializationCluster() {}
-  virtual ~LibraryDeserializationCluster() {}
+  ~LibraryDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -1355,7 +1282,7 @@
 class NamespaceSerializationCluster : public SerializationCluster {
  public:
   NamespaceSerializationCluster() : SerializationCluster("Namespace") {}
-  virtual ~NamespaceSerializationCluster() {}
+  ~NamespaceSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawNamespace* ns = Namespace::RawCast(object);
@@ -1398,7 +1325,7 @@
 class NamespaceDeserializationCluster : public DeserializationCluster {
  public:
   NamespaceDeserializationCluster() {}
-  virtual ~NamespaceDeserializationCluster() {}
+  ~NamespaceDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -1432,7 +1359,7 @@
  public:
   KernelProgramInfoSerializationCluster()
       : SerializationCluster("KernelProgramInfo") {}
-  virtual ~KernelProgramInfoSerializationCluster() {}
+  ~KernelProgramInfoSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawKernelProgramInfo* info = KernelProgramInfo::RawCast(object);
@@ -1476,7 +1403,7 @@
 class KernelProgramInfoDeserializationCluster : public DeserializationCluster {
  public:
   KernelProgramInfoDeserializationCluster() {}
-  virtual ~KernelProgramInfoDeserializationCluster() {}
+  ~KernelProgramInfoDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -1526,7 +1453,7 @@
 class CodeSerializationCluster : public SerializationCluster {
  public:
   CodeSerializationCluster() : SerializationCluster("Code") {}
-  virtual ~CodeSerializationCluster() {}
+  ~CodeSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawCode* code = Code::RawCast(object);
@@ -1583,7 +1510,7 @@
       }
 
       s->WriteInstructions(code->ptr()->instructions_, code);
-      if (s->kind() == Snapshot::kFullJIT) {
+      if (kind == Snapshot::kFullJIT) {
         // TODO(rmacnak): Fix references to disabled code before serializing.
         // For now, we may write the FixCallersTarget or equivalent stub. This
         // will cause a fixup if this code is called.
@@ -1607,7 +1534,7 @@
         s->WriteRef(code->ptr()->inlined_id_to_function_);
         s->WriteRef(code->ptr()->code_source_map_);
       }
-      if (s->kind() == Snapshot::kFullJIT) {
+      if (kind == Snapshot::kFullJIT) {
         s->WriteRef(code->ptr()->deopt_info_array_);
         s->WriteRef(code->ptr()->static_calls_target_table_);
       }
@@ -1626,7 +1553,7 @@
 class CodeDeserializationCluster : public DeserializationCluster {
  public:
   CodeDeserializationCluster() {}
-  virtual ~CodeDeserializationCluster() {}
+  ~CodeDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -1712,10 +1639,87 @@
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
+class BytecodeSerializationCluster : public SerializationCluster {
+ public:
+  BytecodeSerializationCluster() : SerializationCluster("Bytecode") {}
+  virtual ~BytecodeSerializationCluster() {}
+
+  void Trace(Serializer* s, RawObject* object) {
+    RawBytecode* bytecode = Bytecode::RawCast(object);
+    objects_.Add(bytecode);
+
+    RawObject** from = bytecode->from();
+    RawObject** to = bytecode->to();
+    for (RawObject** p = from; p <= to; p++) {
+      s->Push(*p);
+    }
+  }
+
+  void WriteAlloc(Serializer* s) {
+    s->WriteCid(kBytecodeCid);
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      RawBytecode* bytecode = objects_[i];
+      s->AssignRef(bytecode);
+    }
+  }
+
+  void WriteFill(Serializer* s) {
+    ASSERT(s->kind() == Snapshot::kFullJIT);
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      RawBytecode* bytecode = objects_[i];
+      RawObject** from = bytecode->from();
+      RawObject** to = bytecode->to();
+      for (RawObject** p = from; p <= to; p++) {
+        s->WriteRef(*p);
+      }
+      s->Write<int32_t>(bytecode->ptr()->source_positions_binary_offset_);
+    }
+  }
+
+ private:
+  GrowableArray<RawBytecode*> objects_;
+};
+
+class BytecodeDeserializationCluster : public DeserializationCluster {
+ public:
+  BytecodeDeserializationCluster() {}
+  virtual ~BytecodeDeserializationCluster() {}
+
+  void ReadAlloc(Deserializer* d) {
+    start_index_ = d->next_index();
+    PageSpace* old_space = d->heap()->old_space();
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(AllocateUninitialized(old_space, Bytecode::InstanceSize()));
+    }
+    stop_index_ = d->next_index();
+  }
+
+  void ReadFill(Deserializer* d) {
+    ASSERT(d->kind() == Snapshot::kFullJIT);
+    bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      RawBytecode* bytecode = reinterpret_cast<RawBytecode*>(d->Ref(id));
+      Deserializer::InitializeHeader(bytecode, kBytecodeCid,
+                                     Bytecode::InstanceSize(), is_vm_object);
+      RawObject** from = bytecode->from();
+      RawObject** to = bytecode->to();
+      for (RawObject** p = from; p <= to; p++) {
+        *p = d->ReadRef();
+      }
+      bytecode->ptr()->source_positions_binary_offset_ = d->Read<int32_t>();
+    }
+  }
+};
+
 class ObjectPoolSerializationCluster : public SerializationCluster {
  public:
   ObjectPoolSerializationCluster() : SerializationCluster("ObjectPool") {}
-  virtual ~ObjectPoolSerializationCluster() {}
+  ~ObjectPoolSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawObjectPool* pool = ObjectPool::RawCast(object);
@@ -1811,7 +1815,7 @@
 class ObjectPoolDeserializationCluster : public DeserializationCluster {
  public:
   ObjectPoolDeserializationCluster() {}
-  virtual ~ObjectPoolDeserializationCluster() {}
+  ~ObjectPoolDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -1873,7 +1877,7 @@
  public:
   RODataSerializationCluster(const char* name, intptr_t cid)
       : SerializationCluster(name), cid_(cid) {}
-  virtual ~RODataSerializationCluster() {}
+  ~RODataSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     // A string's hash must already be computed when we write it because it
@@ -1936,7 +1940,7 @@
 class RODataDeserializationCluster : public DeserializationCluster {
  public:
   RODataDeserializationCluster() {}
-  virtual ~RODataDeserializationCluster() {}
+  ~RODataDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     intptr_t count = d->ReadUnsigned();
@@ -1963,7 +1967,7 @@
  public:
   ExceptionHandlersSerializationCluster()
       : SerializationCluster("ExceptionHandlers") {}
-  virtual ~ExceptionHandlersSerializationCluster() {}
+  ~ExceptionHandlersSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawExceptionHandlers* handlers = ExceptionHandlers::RawCast(object);
@@ -2010,7 +2014,7 @@
 class ExceptionHandlersDeserializationCluster : public DeserializationCluster {
  public:
   ExceptionHandlersDeserializationCluster() {}
-  virtual ~ExceptionHandlersDeserializationCluster() {}
+  ~ExceptionHandlersDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -2053,7 +2057,7 @@
 class ContextSerializationCluster : public SerializationCluster {
  public:
   ContextSerializationCluster() : SerializationCluster("Context") {}
-  virtual ~ContextSerializationCluster() {}
+  ~ContextSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawContext* context = Context::RawCast(object);
@@ -2099,7 +2103,7 @@
 class ContextDeserializationCluster : public DeserializationCluster {
  public:
   ContextDeserializationCluster() {}
-  virtual ~ContextDeserializationCluster() {}
+  ~ContextDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -2134,7 +2138,7 @@
 class ContextScopeSerializationCluster : public SerializationCluster {
  public:
   ContextScopeSerializationCluster() : SerializationCluster("ContextScope") {}
-  virtual ~ContextScopeSerializationCluster() {}
+  ~ContextScopeSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawContextScope* scope = ContextScope::RawCast(object);
@@ -2183,7 +2187,7 @@
 class ContextScopeDeserializationCluster : public DeserializationCluster {
  public:
   ContextScopeDeserializationCluster() {}
-  virtual ~ContextScopeDeserializationCluster() {}
+  ~ContextScopeDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -2221,7 +2225,7 @@
 class UnlinkedCallSerializationCluster : public SerializationCluster {
  public:
   UnlinkedCallSerializationCluster() : SerializationCluster("UnlinkedCall") {}
-  virtual ~UnlinkedCallSerializationCluster() {}
+  ~UnlinkedCallSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawUnlinkedCall* unlinked = UnlinkedCall::RawCast(object);
@@ -2264,7 +2268,7 @@
 class UnlinkedCallDeserializationCluster : public DeserializationCluster {
  public:
   UnlinkedCallDeserializationCluster() {}
-  virtual ~UnlinkedCallDeserializationCluster() {}
+  ~UnlinkedCallDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -2299,7 +2303,7 @@
 class ICDataSerializationCluster : public SerializationCluster {
  public:
   ICDataSerializationCluster() : SerializationCluster("ICData") {}
-  virtual ~ICDataSerializationCluster() {}
+  ~ICDataSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawICData* ic = ICData::RawCast(object);
@@ -2350,7 +2354,7 @@
 class ICDataDeserializationCluster : public DeserializationCluster {
  public:
   ICDataDeserializationCluster() {}
-  virtual ~ICDataDeserializationCluster() {}
+  ~ICDataDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -2393,7 +2397,7 @@
  public:
   MegamorphicCacheSerializationCluster()
       : SerializationCluster("MegamorphicCache") {}
-  virtual ~MegamorphicCacheSerializationCluster() {}
+  ~MegamorphicCacheSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawMegamorphicCache* cache = MegamorphicCache::RawCast(object);
@@ -2437,7 +2441,7 @@
 class MegamorphicCacheDeserializationCluster : public DeserializationCluster {
  public:
   MegamorphicCacheDeserializationCluster() {}
-  virtual ~MegamorphicCacheDeserializationCluster() {}
+  ~MegamorphicCacheDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -2474,7 +2478,7 @@
  public:
   SubtypeTestCacheSerializationCluster()
       : SerializationCluster("SubtypeTestCache") {}
-  virtual ~SubtypeTestCacheSerializationCluster() {}
+  ~SubtypeTestCacheSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawSubtypeTestCache* cache = SubtypeTestCache::RawCast(object);
@@ -2508,7 +2512,7 @@
 class SubtypeTestCacheDeserializationCluster : public DeserializationCluster {
  public:
   SubtypeTestCacheDeserializationCluster() {}
-  virtual ~SubtypeTestCacheDeserializationCluster() {}
+  ~SubtypeTestCacheDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -2539,7 +2543,7 @@
 class LanguageErrorSerializationCluster : public SerializationCluster {
  public:
   LanguageErrorSerializationCluster() : SerializationCluster("LanguageError") {}
-  virtual ~LanguageErrorSerializationCluster() {}
+  ~LanguageErrorSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawLanguageError* error = LanguageError::RawCast(object);
@@ -2585,7 +2589,7 @@
 class LanguageErrorDeserializationCluster : public DeserializationCluster {
  public:
   LanguageErrorDeserializationCluster() {}
-  virtual ~LanguageErrorDeserializationCluster() {}
+  ~LanguageErrorDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -2623,7 +2627,7 @@
  public:
   UnhandledExceptionSerializationCluster()
       : SerializationCluster("UnhandledException") {}
-  virtual ~UnhandledExceptionSerializationCluster() {}
+  ~UnhandledExceptionSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawUnhandledException* exception = UnhandledException::RawCast(object);
@@ -2666,7 +2670,7 @@
 class UnhandledExceptionDeserializationCluster : public DeserializationCluster {
  public:
   UnhandledExceptionDeserializationCluster() {}
-  virtual ~UnhandledExceptionDeserializationCluster() {}
+  ~UnhandledExceptionDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -2708,7 +2712,7 @@
     ASSERT(next_field_offset_in_words_ > 0);
     ASSERT(instance_size_in_words_ > 0);
   }
-  virtual ~InstanceSerializationCluster() {}
+  ~InstanceSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawInstance* instance = Instance::RawCast(object);
@@ -2765,7 +2769,7 @@
 class InstanceDeserializationCluster : public DeserializationCluster {
  public:
   explicit InstanceDeserializationCluster(intptr_t cid) : cid_(cid) {}
-  virtual ~InstanceDeserializationCluster() {}
+  ~InstanceDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -2819,7 +2823,7 @@
 class LibraryPrefixSerializationCluster : public SerializationCluster {
  public:
   LibraryPrefixSerializationCluster() : SerializationCluster("LibraryPrefix") {}
-  virtual ~LibraryPrefixSerializationCluster() {}
+  ~LibraryPrefixSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawLibraryPrefix* prefix = LibraryPrefix::RawCast(object);
@@ -2865,7 +2869,7 @@
 class LibraryPrefixDeserializationCluster : public DeserializationCluster {
  public:
   LibraryPrefixDeserializationCluster() {}
-  virtual ~LibraryPrefixDeserializationCluster() {}
+  ~LibraryPrefixDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -2910,7 +2914,7 @@
  public:
   explicit TypeSerializationCluster(const TypeTestingStubFinder& ttsf)
       : SerializationCluster("Type"), type_testing_stubs_(ttsf) {}
-  virtual ~TypeSerializationCluster() {}
+  ~TypeSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawType* type = Type::RawCast(object);
@@ -3015,7 +3019,7 @@
  public:
   TypeDeserializationCluster()
       : type_(AbstractType::Handle()), instr_(Instructions::Handle()) {}
-  virtual ~TypeDeserializationCluster() {}
+  ~TypeDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     canonical_start_index_ = d->next_index();
@@ -3114,7 +3118,7 @@
  public:
   explicit TypeRefSerializationCluster(const TypeTestingStubFinder& ttsf)
       : SerializationCluster("TypeRef"), type_testing_stubs_(ttsf) {}
-  virtual ~TypeRefSerializationCluster() {}
+  ~TypeRefSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawTypeRef* type = TypeRef::RawCast(object);
@@ -3167,7 +3171,7 @@
  public:
   TypeRefDeserializationCluster()
       : type_(AbstractType::Handle()), instr_(Instructions::Handle()) {}
-  virtual ~TypeRefDeserializationCluster() {}
+  ~TypeRefDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -3222,7 +3226,7 @@
   explicit TypeParameterSerializationCluster(const TypeTestingStubFinder& ttsf)
       : SerializationCluster("TypeParameter"), type_testing_stubs_(ttsf) {}
 
-  virtual ~TypeParameterSerializationCluster() {}
+  ~TypeParameterSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawTypeParameter* type = TypeParameter::RawCast(object);
@@ -3280,7 +3284,7 @@
  public:
   TypeParameterDeserializationCluster()
       : type_(AbstractType::Handle()), instr_(Instructions::Handle()) {}
-  virtual ~TypeParameterDeserializationCluster() {}
+  ~TypeParameterDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -3338,7 +3342,7 @@
 class BoundedTypeSerializationCluster : public SerializationCluster {
  public:
   BoundedTypeSerializationCluster() : SerializationCluster("BoundedType") {}
-  virtual ~BoundedTypeSerializationCluster() {}
+  ~BoundedTypeSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawBoundedType* type = BoundedType::RawCast(object);
@@ -3381,7 +3385,7 @@
 class BoundedTypeDeserializationCluster : public DeserializationCluster {
  public:
   BoundedTypeDeserializationCluster() {}
-  virtual ~BoundedTypeDeserializationCluster() {}
+  ~BoundedTypeDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -3414,7 +3418,7 @@
 class ClosureSerializationCluster : public SerializationCluster {
  public:
   ClosureSerializationCluster() : SerializationCluster("Closure") {}
-  virtual ~ClosureSerializationCluster() {}
+  ~ClosureSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawClosure* closure = Closure::RawCast(object);
@@ -3458,7 +3462,7 @@
 class ClosureDeserializationCluster : public DeserializationCluster {
  public:
   ClosureDeserializationCluster() {}
-  virtual ~ClosureDeserializationCluster() {}
+  ~ClosureDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -3492,7 +3496,7 @@
 class MintSerializationCluster : public SerializationCluster {
  public:
   MintSerializationCluster() : SerializationCluster("Mint") {}
-  virtual ~MintSerializationCluster() {}
+  ~MintSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     if (!object->IsHeapObject()) {
@@ -3533,7 +3537,7 @@
 class MintDeserializationCluster : public DeserializationCluster {
  public:
   MintDeserializationCluster() {}
-  virtual ~MintDeserializationCluster() {}
+  ~MintDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     PageSpace* old_space = d->heap()->old_space();
@@ -3581,7 +3585,7 @@
 class DoubleSerializationCluster : public SerializationCluster {
  public:
   DoubleSerializationCluster() : SerializationCluster("Double") {}
-  virtual ~DoubleSerializationCluster() {}
+  ~DoubleSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawDouble* dbl = Double::RawCast(object);
@@ -3615,7 +3619,7 @@
 class DoubleDeserializationCluster : public DeserializationCluster {
  public:
   DoubleDeserializationCluster() {}
-  virtual ~DoubleDeserializationCluster() {}
+  ~DoubleDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -3645,7 +3649,7 @@
  public:
   GrowableObjectArraySerializationCluster()
       : SerializationCluster("GrowableObjectArray") {}
-  virtual ~GrowableObjectArraySerializationCluster() {}
+  ~GrowableObjectArraySerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawGrowableObjectArray* array = GrowableObjectArray::RawCast(object);
@@ -3690,7 +3694,7 @@
     : public DeserializationCluster {
  public:
   GrowableObjectArrayDeserializationCluster() {}
-  virtual ~GrowableObjectArrayDeserializationCluster() {}
+  ~GrowableObjectArrayDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -3727,7 +3731,7 @@
  public:
   explicit TypedDataSerializationCluster(intptr_t cid)
       : SerializationCluster("TypedData"), cid_(cid) {}
-  virtual ~TypedDataSerializationCluster() {}
+  ~TypedDataSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawTypedData* data = TypedData::RawCast(object);
@@ -3768,7 +3772,7 @@
 class TypedDataDeserializationCluster : public DeserializationCluster {
  public:
   explicit TypedDataDeserializationCluster(intptr_t cid) : cid_(cid) {}
-  virtual ~TypedDataDeserializationCluster() {}
+  ~TypedDataDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -3810,7 +3814,7 @@
  public:
   explicit ExternalTypedDataSerializationCluster(intptr_t cid)
       : SerializationCluster("ExternalTypedData"), cid_(cid) {}
-  virtual ~ExternalTypedDataSerializationCluster() {}
+  ~ExternalTypedDataSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawExternalTypedData* data = ExternalTypedData::RawCast(object);
@@ -3836,6 +3840,7 @@
       intptr_t length = Smi::Value(data->ptr()->length_);
       s->WriteUnsigned(length);
       uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data_);
+      s->Align(ExternalTypedData::kDataSerializationAlignment);
       s->WriteBytes(cdata, length * element_size);
     }
   }
@@ -3849,7 +3854,7 @@
 class ExternalTypedDataDeserializationCluster : public DeserializationCluster {
  public:
   explicit ExternalTypedDataDeserializationCluster(intptr_t cid) : cid_(cid) {}
-  virtual ~ExternalTypedDataDeserializationCluster() {}
+  ~ExternalTypedDataDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -3873,6 +3878,7 @@
       Deserializer::InitializeHeader(
           data, cid_, ExternalTypedData::InstanceSize(), is_vm_object);
       data->ptr()->length_ = Smi::New(length);
+      d->Align(ExternalTypedData::kDataSerializationAlignment);
       data->ptr()->data_ = const_cast<uint8_t*>(d->CurrentBufferAddress());
       d->Advance(length * element_size);
       // No finalizer / external size 0.
@@ -3887,7 +3893,7 @@
 class StackTraceSerializationCluster : public SerializationCluster {
  public:
   StackTraceSerializationCluster() : SerializationCluster("StackTrace") {}
-  virtual ~StackTraceSerializationCluster() {}
+  ~StackTraceSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawStackTrace* trace = StackTrace::RawCast(object);
@@ -3930,7 +3936,7 @@
 class StackTraceDeserializationCluster : public DeserializationCluster {
  public:
   StackTraceDeserializationCluster() {}
-  virtual ~StackTraceDeserializationCluster() {}
+  ~StackTraceDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -3963,7 +3969,7 @@
 class RegExpSerializationCluster : public SerializationCluster {
  public:
   RegExpSerializationCluster() : SerializationCluster("RegExp") {}
-  virtual ~RegExpSerializationCluster() {}
+  ~RegExpSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawRegExp* regexp = RegExp::RawCast(object);
@@ -4009,7 +4015,7 @@
 class RegExpDeserializationCluster : public DeserializationCluster {
  public:
   RegExpDeserializationCluster() {}
-  virtual ~RegExpDeserializationCluster() {}
+  ~RegExpDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -4044,7 +4050,7 @@
 class WeakPropertySerializationCluster : public SerializationCluster {
  public:
   WeakPropertySerializationCluster() : SerializationCluster("WeakProperty") {}
-  virtual ~WeakPropertySerializationCluster() {}
+  ~WeakPropertySerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawWeakProperty* property = WeakProperty::RawCast(object);
@@ -4087,7 +4093,7 @@
 class WeakPropertyDeserializationCluster : public DeserializationCluster {
  public:
   WeakPropertyDeserializationCluster() {}
-  virtual ~WeakPropertyDeserializationCluster() {}
+  ~WeakPropertyDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -4122,7 +4128,7 @@
 class LinkedHashMapSerializationCluster : public SerializationCluster {
  public:
   LinkedHashMapSerializationCluster() : SerializationCluster("LinkedHashMap") {}
-  virtual ~LinkedHashMapSerializationCluster() {}
+  ~LinkedHashMapSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawLinkedHashMap* map = LinkedHashMap::RawCast(object);
@@ -4189,7 +4195,7 @@
 class LinkedHashMapDeserializationCluster : public DeserializationCluster {
  public:
   LinkedHashMapDeserializationCluster() {}
-  virtual ~LinkedHashMapDeserializationCluster() {}
+  ~LinkedHashMapDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -4249,7 +4255,7 @@
  public:
   explicit ArraySerializationCluster(intptr_t cid)
       : SerializationCluster("Array"), cid_(cid) {}
-  virtual ~ArraySerializationCluster() {}
+  ~ArraySerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawArray* array = Array::RawCast(object);
@@ -4297,7 +4303,7 @@
 class ArrayDeserializationCluster : public DeserializationCluster {
  public:
   explicit ArrayDeserializationCluster(intptr_t cid) : cid_(cid) {}
-  virtual ~ArrayDeserializationCluster() {}
+  ~ArrayDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -4337,7 +4343,7 @@
 class OneByteStringSerializationCluster : public SerializationCluster {
  public:
   OneByteStringSerializationCluster() : SerializationCluster("OneByteString") {}
-  virtual ~OneByteStringSerializationCluster() {}
+  ~OneByteStringSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawOneByteString* str = reinterpret_cast<RawOneByteString*>(object);
@@ -4377,7 +4383,7 @@
 class OneByteStringDeserializationCluster : public DeserializationCluster {
  public:
   OneByteStringDeserializationCluster() {}
-  virtual ~OneByteStringDeserializationCluster() {}
+  ~OneByteStringDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -4414,7 +4420,7 @@
 class TwoByteStringSerializationCluster : public SerializationCluster {
  public:
   TwoByteStringSerializationCluster() : SerializationCluster("TwoByteString") {}
-  virtual ~TwoByteStringSerializationCluster() {}
+  ~TwoByteStringSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
     RawTwoByteString* str = reinterpret_cast<RawTwoByteString*>(object);
@@ -4454,7 +4460,7 @@
 class TwoByteStringDeserializationCluster : public DeserializationCluster {
  public:
   TwoByteStringDeserializationCluster() {}
-  virtual ~TwoByteStringDeserializationCluster() {}
+  ~TwoByteStringDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
@@ -4489,11 +4495,11 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
 class FakeSerializationCluster : public SerializationCluster {
  public:
-  explicit FakeSerializationCluster(const char* name, intptr_t size)
+  FakeSerializationCluster(const char* name, intptr_t size)
       : SerializationCluster(name) {
     size_ = size;
   }
-  virtual ~FakeSerializationCluster() {}
+  ~FakeSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) { UNREACHABLE(); }
   void WriteAlloc(Serializer* s) { UNREACHABLE(); }
@@ -4557,8 +4563,6 @@
   switch (cid) {
     case kClassCid:
       return new (Z) ClassSerializationCluster(num_cids_);
-    case kUnresolvedClassCid:
-      return new (Z) UnresolvedClassSerializationCluster();
     case kTypeArgumentsCid:
       return new (Z) TypeArgumentsSerializationCluster();
     case kPatchClassCid:
@@ -4583,6 +4587,10 @@
       return new (Z) KernelProgramInfoSerializationCluster();
     case kCodeCid:
       return new (Z) CodeSerializationCluster();
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    case kBytecodeCid:
+      return new (Z) BytecodeSerializationCluster();
+#endif  // !DART_PRECOMPILED_RUNTIME
     case kObjectPoolCid:
       return new (Z) ObjectPoolSerializationCluster();
     case kPcDescriptorsCid:
@@ -4668,12 +4676,8 @@
 }
 
 void Serializer::WriteInstructions(RawInstructions* instr, RawCode* code) {
-  intptr_t offset = heap_->GetObjectId(instr);
-  if (offset == 0) {
-    offset = image_writer_->GetTextOffsetFor(instr, code);
-    ASSERT(offset != 0);
-    heap_->SetObjectId(instr, offset);
-  }
+  const intptr_t offset = image_writer_->GetTextOffsetFor(instr, code);
+  ASSERT(offset != 0);
   Write<int32_t>(offset);
 }
 
@@ -4717,6 +4721,11 @@
   if (object->IsCode() && !Snapshot::IncludesCode(kind_)) {
     return;  // Do not trace, will write null.
   }
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  if (object->IsBytecode() && !Snapshot::IncludesBytecode(kind_)) {
+    return;  // Do not trace, will write null.
+  }
+#endif  // !DART_PRECOMPILED_RUNTIME
 
   if (object->IsSendPort()) {
     // TODO(rmacnak): Do a better job of resetting fields in precompilation
@@ -4726,6 +4735,12 @@
 
   intptr_t id = heap_->GetObjectId(object);
   if (id == 0) {
+    // When discovering the transitive closure of objects reachable from the
+    // roots we do not trace references, e.g. inside [RawCode], to
+    // [RawInstructions], since [RawInstructions] doesn't contain any references
+    // and the serialization code uses an [ImageWriter] for those.
+    ASSERT(object->GetClassId() != kInstructionsCid);
+
     heap_->SetObjectId(object, 1);
     ASSERT(heap_->GetObjectId(object) != 0);
     stack_.Add(object);
@@ -5078,8 +5093,6 @@
   switch (cid) {
     case kClassCid:
       return new (Z) ClassDeserializationCluster();
-    case kUnresolvedClassCid:
-      return new (Z) UnresolvedClassDeserializationCluster();
     case kTypeArgumentsCid:
       return new (Z) TypeArgumentsDeserializationCluster();
     case kPatchClassCid:
@@ -5106,6 +5119,10 @@
 #endif  // !DART_PRECOMPILED_RUNTIME
     case kCodeCid:
       return new (Z) CodeDeserializationCluster();
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    case kBytecodeCid:
+      return new (Z) BytecodeDeserializationCluster();
+#endif  // !DART_PRECOMPILED_RUNTIME
     case kObjectPoolCid:
       return new (Z) ObjectPoolDeserializationCluster();
     case kPcDescriptorsCid:
@@ -5722,7 +5739,7 @@
                                        Thread* thread)
     : kind_(snapshot->kind()),
       thread_(thread),
-      buffer_(snapshot->content()),
+      buffer_(snapshot->Addr()),
       size_(snapshot->length()),
       data_image_(snapshot->DataImage()),
       instructions_image_(instructions_buffer) {
@@ -5740,6 +5757,8 @@
   Deserializer deserializer(thread_, kind_, buffer_, size_, data_image_,
                             instructions_image_, NULL, NULL);
 
+  deserializer.SkipHeader();
+
   RawApiError* error = deserializer.VerifyVersionAndFeatures(/*isolate=*/NULL);
   if (error != ApiError::null()) {
     return error;
@@ -5764,6 +5783,8 @@
                             instructions_image_, shared_data_image_,
                             shared_instructions_image_);
 
+  deserializer.SkipHeader();
+
   RawApiError* error =
       deserializer.VerifyVersionAndFeatures(thread_->isolate());
   if (error != ApiError::null()) {
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index 7c64239..1f64d11 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -212,6 +212,7 @@
   void WriteBytes(const uint8_t* addr, intptr_t len) {
     stream_.WriteBytes(addr, len);
   }
+  void Align(intptr_t alignment) { stream_.Align(alignment); }
 
   void WriteRef(RawObject* object) {
     if (!object->IsHeapObject()) {
@@ -233,6 +234,12 @@
         WriteRef(Object::null());
         return;
       }
+#if !defined(DART_PRECOMPILED_RUNTIME)
+      if (object->IsBytecode() && !Snapshot::IncludesBytecode(kind_)) {
+        WriteRef(Object::null());
+        return;
+      }
+#endif  // !DART_PRECOMPILED_RUNTIME
       if (object->IsSendPort()) {
         // TODO(rmacnak): Do a better job of resetting fields in precompilation
         // and assert this is unreachable.
@@ -324,6 +331,7 @@
   }
 
   void Advance(intptr_t value) { stream_.Advance(value); }
+  void Align(intptr_t alignment) { stream_.Align(alignment); }
 
   intptr_t PendingBytes() const { return stream_.PendingBytes(); }
 
@@ -356,6 +364,8 @@
   RawObject* GetObjectAt(uint32_t offset) const;
   RawObject* GetSharedObjectAt(uint32_t offset) const;
 
+  void SkipHeader() { stream_.SetPosition(Snapshot::kHeaderSize); }
+
   RawApiError* VerifyVersionAndFeatures(Isolate* isolate);
 
   void Prepare();
diff --git a/runtime/vm/code_patcher.h b/runtime/vm/code_patcher.h
index 82668c5..8b69986 100644
--- a/runtime/vm/code_patcher.h
+++ b/runtime/vm/code_patcher.h
@@ -113,11 +113,11 @@
 class KBCPatcher : public AllStatic {
  public:
   static NativeFunctionWrapper GetNativeCallAt(uword return_address,
-                                               const Code& bytecode,
+                                               const Bytecode& bytecode,
                                                NativeFunction* function);
 
   static void PatchNativeCallAt(uword return_address,
-                                const Code& bytecode,
+                                const Bytecode& bytecode,
                                 NativeFunction function,
                                 NativeFunctionWrapper trampoline);
 };
diff --git a/runtime/vm/code_patcher_kbc.cc b/runtime/vm/code_patcher_kbc.cc
index de7cac4..2dd74bd 100644
--- a/runtime/vm/code_patcher_kbc.cc
+++ b/runtime/vm/code_patcher_kbc.cc
@@ -13,7 +13,7 @@
 namespace dart {
 
 void KBCPatcher::PatchNativeCallAt(uword return_address,
-                                   const Code& bytecode,
+                                   const Bytecode& bytecode,
                                    NativeFunction function,
                                    NativeFunctionWrapper trampoline) {
   ASSERT(bytecode.ContainsInstructionAt(return_address));
@@ -24,7 +24,7 @@
 }
 
 NativeFunctionWrapper KBCPatcher::GetNativeCallAt(uword return_address,
-                                                  const Code& bytecode,
+                                                  const Bytecode& bytecode,
                                                   NativeFunction* function) {
   ASSERT(bytecode.ContainsInstructionAt(return_address));
   NativeEntryData native_entry_data(TypedData::Handle(
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index 0ff81a0..571be51 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -287,16 +287,17 @@
   ASSERT(I->can_use_strong_mode_types());
   ASSERT((cid == kDoubleCid) || (cid == kMintCid));
 
-  const String& function_name =
-      (call->IsInstanceCall()
-           ? call->AsInstanceCall()->function_name()
-           : String::ZoneHandle(Z, call->AsStaticCall()->function().name()));
-
-  AddCheckNull(input, function_name, call->deopt_id(), call->env(), call);
+  if (input->Type()->is_nullable()) {
+    const String& function_name =
+        (call->IsInstanceCall()
+             ? call->AsInstanceCall()->function_name()
+             : String::ZoneHandle(Z, call->AsStaticCall()->function().name()));
+    AddCheckNull(input, function_name, call->deopt_id(), call->env(), call);
+  }
 
   input = input->CopyWithType(Z);
 
-  if ((cid == kDoubleCid) && input->Type()->IsNullableInt()) {
+  if (cid == kDoubleCid && input->Type()->IsNullableInt()) {
     Definition* conversion = NULL;
 
     if (input->Type()->ToNullableCid() == kSmiCid) {
@@ -319,25 +320,30 @@
   return input;
 }
 
-Value* AotCallSpecializer::PrepareReceiverOfDevirtualizedCall(Value* input,
+CompileType AotCallSpecializer::BuildStrengthenedReceiverType(Value* input,
                                                               intptr_t cid) {
-  ASSERT(I->can_use_strong_mode_types());
-  ASSERT((cid == kDoubleCid) || (cid == kMintCid));
+  CompileType* old_type = input->Type();
+  CompileType* refined_type = old_type;
 
-  // Can't assert !input->Type()->is_nullable() here as PushArgument receives
-  // value prior to a CheckNull in case of devirtualized call.
-
-  input = input->CopyWithType(Z);
-
-  // Correct type of input if necessary.
-  // This correction is needed as VM may not be able to infer receiver type.
-  if ((cid == kIntegerCid) && !input->Type()->IsNullableInt()) {
-    input->SetReachingType(new (Z) CompileType(CompileType::Int()));
-  } else if ((cid == kDoubleCid) && !input->Type()->IsNullableDouble()) {
-    input->SetReachingType(new (Z) CompileType(CompileType::Double()));
+  CompileType type = CompileType::None();
+  if (cid == kSmiCid) {
+    type = CompileType::NullableSmi();
+    refined_type = CompileType::ComputeRefinedType(old_type, &type);
+  } else if (cid == kMintCid) {
+    type = CompileType::NullableMint();
+    refined_type = CompileType::ComputeRefinedType(old_type, &type);
+  } else if (cid == kIntegerCid && !input->Type()->IsNullableInt()) {
+    type = CompileType::NullableInt();
+    refined_type = CompileType::ComputeRefinedType(old_type, &type);
+  } else if (cid == kDoubleCid && !input->Type()->IsNullableDouble()) {
+    type = CompileType::NullableDouble();
+    refined_type = CompileType::ComputeRefinedType(old_type, &type);
   }
 
-  return input;
+  if (refined_type != old_type) {
+    return *refined_type;
+  }
+  return CompileType::None();
 }
 
 // After replacing a call with a specialized instruction, make sure to
@@ -354,137 +360,209 @@
     InstanceCallInstr* instr) {
   ASSERT(I->can_use_strong_mode_types());
 
-  const intptr_t receiver_index = instr->FirstArgIndex();
   const Token::Kind op_kind = instr->token_kind();
-  Definition* replacement = NULL;
 
-  switch (op_kind) {
-    case Token::kEQ:
-    case Token::kNE:
-    case Token::kLT:
-    case Token::kLTE:
-    case Token::kGT:
-    case Token::kGTE: {
-      Value* left_value = instr->PushArgumentAt(receiver_index)->value();
-      Value* right_value = instr->PushArgumentAt(receiver_index + 1)->value();
-      CompileType* left_type = left_value->Type();
-      CompileType* right_type = right_value->Type();
-      if (left_type->IsNullableInt() && right_type->IsNullableInt()) {
-        if (FlowGraphCompiler::SupportsUnboxedInt64()) {
-          if (Token::IsRelationalOperator(op_kind)) {
+  return TryOptimizeIntegerOperation(instr, op_kind) ||
+         TryOptimizeDoubleOperation(instr, op_kind);
+}
+
+bool AotCallSpecializer::TryOptimizeStaticCallUsingStaticTypes(
+    StaticCallInstr* instr) {
+  ASSERT(I->can_use_strong_mode_types());
+
+  const String& name = String::Handle(Z, instr->function().name());
+  const Token::Kind op_kind = MethodTokenRecognizer::RecognizeTokenKind(name);
+
+  if (op_kind == Token::kEQ && TryReplaceWithHaveSameRuntimeType(instr)) {
+    return true;
+  }
+
+  // We only specialize instance methods for int/double operations.
+  const auto& target = instr->function();
+  if (!target.IsDynamicFunction()) {
+    return false;
+  }
+
+  // For de-virtualized instance calls, we strengthen the type here manually
+  // because it might not be attached to the receiver.
+  // See http://dartbug.com/35179 for preserving the receiver type information.
+  const Class& owner = Class::Handle(Z, target.Owner());
+  const intptr_t cid = owner.id();
+  if (cid == kSmiCid || cid == kMintCid || cid == kIntegerCid ||
+      cid == kDoubleCid) {
+    // Sometimes TFA de-virtualizes instance calls to static calls.  In such
+    // cases the VM might have a looser type on the receiver, so we explicitly
+    // tighten it (this is safe since it was proven that te receiver is either
+    // null or will end up with that target).
+    const intptr_t receiver_index = instr->FirstArgIndex();
+    const intptr_t argument_count = instr->ArgumentCountWithoutTypeArgs();
+    if (argument_count >= 1) {
+      auto push_receiver = instr->PushArgumentAt(receiver_index);
+      auto receiver_value = push_receiver->value();
+      auto receiver = receiver_value->definition();
+      auto type = BuildStrengthenedReceiverType(receiver_value, cid);
+      if (!type.IsNone()) {
+        auto redefinition = flow_graph()->EnsureRedefinition(
+            push_receiver->previous(), receiver, type);
+        if (redefinition != nullptr) {
+          RefineUseTypes(redefinition);
+        }
+      }
+    }
+  }
+
+  return TryOptimizeIntegerOperation(instr, op_kind) ||
+         TryOptimizeDoubleOperation(instr, op_kind);
+}
+
+bool AotCallSpecializer::TryOptimizeIntegerOperation(TemplateDartCall<0>* instr,
+                                                     Token::Kind op_kind) {
+  if (instr->type_args_len() != 0) {
+    // Arithmetic operations don't have type arguments.
+    return false;
+  }
+
+  ASSERT(I->can_use_strong_mode_types());
+
+  Definition* replacement = NULL;
+  if (instr->ArgumentCount() == 2) {
+    Value* left_value = instr->PushArgumentAt(0)->value();
+    Value* right_value = instr->PushArgumentAt(1)->value();
+    CompileType* left_type = left_value->Type();
+    CompileType* right_type = right_value->Type();
+
+    const bool is_equality_op = Token::IsEqualityOperator(op_kind);
+    const bool has_nullable_int_args =
+        left_type->IsNullableInt() && right_type->IsNullableInt();
+
+    // NOTE: We cannot use strict comparisons if the receiver has an overridden
+    // == operator or if either side can be a double, since 1.0 == 1.
+    const bool can_use_strict_compare =
+        is_equality_op && has_nullable_int_args &&
+        (left_type->IsNullableSmi() || right_type->IsNullableSmi());
+
+    // We only support binary operations if both operands are nullable integers
+    // or when we can use a cheap strict comparison operation.
+    if (!has_nullable_int_args) {
+      return false;
+    }
+
+    switch (op_kind) {
+      case Token::kEQ:
+      case Token::kNE:
+      case Token::kLT:
+      case Token::kLTE:
+      case Token::kGT:
+      case Token::kGTE: {
+        const bool supports_unboxed_int =
+            FlowGraphCompiler::SupportsUnboxedInt64();
+        const bool can_use_equality_compare =
+            supports_unboxed_int && is_equality_op && left_type->IsInt() &&
+            right_type->IsInt();
+
+        // We prefer equality compare, since it doesn't require boxing.
+        if (!can_use_equality_compare && can_use_strict_compare) {
+          replacement = new (Z) StrictCompareInstr(
+              instr->token_pos(),
+              (op_kind == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT,
+              left_value->CopyWithType(Z), right_value->CopyWithType(Z),
+              /*needs_number_check=*/false, DeoptId::kNone);
+          break;
+        }
+
+        if (supports_unboxed_int) {
+          if (can_use_equality_compare) {
+            replacement = new (Z) EqualityCompareInstr(
+                instr->token_pos(), op_kind, left_value->CopyWithType(Z),
+                right_value->CopyWithType(Z), kMintCid, DeoptId::kNone,
+                Instruction::kNotSpeculative);
+            break;
+          } else if (Token::IsRelationalOperator(op_kind)) {
             left_value = PrepareStaticOpInput(left_value, kMintCid, instr);
             right_value = PrepareStaticOpInput(right_value, kMintCid, instr);
             replacement = new (Z) RelationalOpInstr(
                 instr->token_pos(), op_kind, left_value, right_value, kMintCid,
                 DeoptId::kNone, Instruction::kNotSpeculative);
-
+            break;
           } else {
             // TODO(dartbug.com/30480): Figure out how to handle null in
             // equality comparisons.
-            // replacement = new (Z) EqualityCompareInstr(
-            //     instr->token_pos(), op_kind, left_value->CopyWithType(Z),
-            //     right_value->CopyWithType(Z), kMintCid, DeoptId::kNone);
-            replacement = new (Z) CheckedSmiComparisonInstr(
-                instr->token_kind(), left_value->CopyWithType(Z),
-                right_value->CopyWithType(Z), instr);
-          }
-          // TODO(dartbug.com/30480): Enable comparisons with Smi.
-        } else if (false &&
-                   ((op_kind == Token::kEQ) || (op_kind == Token::kNE)) &&
-                   ((left_type->ToCid() == kSmiCid) ||
-                    (right_type->ToCid() == kSmiCid))) {
-          replacement = new (Z) StrictCompareInstr(
-              instr->token_pos(),
-              (op_kind == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT,
-              left_value->CopyWithType(Z), right_value->CopyWithType(Z),
-              /* number_check = */ false, DeoptId::kNone);
-        } else {
-          replacement = new (Z) CheckedSmiComparisonInstr(
-              instr->token_kind(), left_value->CopyWithType(Z),
-              right_value->CopyWithType(Z), instr);
-        }
-      } else if (FlowGraphCompiler::SupportsUnboxedDoubles() &&
-                 (left_type->IsNullableDouble() ||
-                  IsSupportedIntOperandForStaticDoubleOp(left_type)) &&
-                 (right_type->IsNullableDouble() ||
-                  IsSupportedIntOperandForStaticDoubleOp(right_type))) {
-        ASSERT(left_type->IsNullableDouble() || right_type->IsNullableDouble());
-        // TODO(dartbug.com/30480): Support == and != for doubles.
-        if ((op_kind == Token::kLT) || (op_kind == Token::kLTE) ||
-            (op_kind == Token::kGT) || (op_kind == Token::kGTE)) {
-          left_value = PrepareStaticOpInput(left_value, kDoubleCid, instr);
-          right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
-          replacement = new (Z) RelationalOpInstr(
-              instr->token_pos(), op_kind, left_value, right_value, kDoubleCid,
-              DeoptId::kNone, Instruction::kNotSpeculative);
-        }
-      }
-      break;
-    }
-    case Token::kSHL:
-    case Token::kSHR:
-    case Token::kBIT_OR:
-    case Token::kBIT_XOR:
-    case Token::kBIT_AND:
-    case Token::kADD:
-    case Token::kSUB:
-    case Token::kMUL:
-    case Token::kDIV: {
-      if ((op_kind == Token::kDIV) &&
-          !FlowGraphCompiler::SupportsHardwareDivision()) {
-        return false;
-      }
-      Value* left_value = instr->PushArgumentAt(receiver_index)->value();
-      Value* right_value = instr->PushArgumentAt(receiver_index + 1)->value();
-      CompileType* left_type = left_value->Type();
-      CompileType* right_type = right_value->Type();
-      if (left_type->IsNullableInt() && right_type->IsNullableInt() &&
-          (op_kind != Token::kDIV)) {
-        if (FlowGraphCompiler::SupportsUnboxedInt64()) {
-          if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) {
-            // TODO(dartbug.com/30480): Enable 64-bit integer shifts.
-            // replacement = new ShiftInt64OpInstr(
-            //     op_kind, left_value->CopyWithType(Z),
-            //     right_value->CopyWithType(Z), DeoptId::kNone);
-            replacement =
-                new (Z) CheckedSmiOpInstr(op_kind, left_value->CopyWithType(Z),
+            replacement = new (Z)
+                CheckedSmiComparisonInstr(op_kind, left_value->CopyWithType(Z),
                                           right_value->CopyWithType(Z), instr);
+            break;
+          }
+        } else {
+          replacement = new (Z)
+              CheckedSmiComparisonInstr(op_kind, left_value->CopyWithType(Z),
+                                        right_value->CopyWithType(Z), instr);
+          break;
+        }
+        break;
+      }
+#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
+        // TODO(ajcbik): 32-bit archs too?
+      case Token::kMOD:
+      case Token::kTRUNCDIV:
+#endif
+      case Token::kSHL:
+      case Token::kSHR:
+      case Token::kBIT_OR:
+      case Token::kBIT_XOR:
+      case Token::kBIT_AND:
+      case Token::kADD:
+      case Token::kSUB:
+      case Token::kMUL: {
+        if (FlowGraphCompiler::SupportsUnboxedInt64()) {
+          if (op_kind == Token::kSHR || op_kind == Token::kSHL) {
+            left_value = PrepareStaticOpInput(left_value, kMintCid, instr);
+            right_value = PrepareStaticOpInput(right_value, kMintCid, instr);
+            replacement = new (Z) ShiftInt64OpInstr(
+                op_kind, left_value, right_value, DeoptId::kNone);
+            break;
           } else {
             left_value = PrepareStaticOpInput(left_value, kMintCid, instr);
             right_value = PrepareStaticOpInput(right_value, kMintCid, instr);
             replacement = new (Z) BinaryInt64OpInstr(
                 op_kind, left_value, right_value, DeoptId::kNone,
                 Instruction::kNotSpeculative);
+            break;
           }
-        } else {
+        }
+        if (op_kind != Token::kMOD && op_kind != Token::kTRUNCDIV) {
           replacement =
               new (Z) CheckedSmiOpInstr(op_kind, left_value->CopyWithType(Z),
                                         right_value->CopyWithType(Z), instr);
+          break;
         }
-      } else if (FlowGraphCompiler::SupportsUnboxedDoubles() &&
-                 (left_type->IsNullableDouble() ||
-                  IsSupportedIntOperandForStaticDoubleOp(left_type)) &&
-                 (right_type->IsNullableDouble() ||
-                  IsSupportedIntOperandForStaticDoubleOp(right_type))) {
-        if ((op_kind == Token::kADD) || (op_kind == Token::kSUB) ||
-            (op_kind == Token::kMUL) || (op_kind == Token::kDIV)) {
-          ASSERT(left_type->IsNullableDouble() ||
-                 right_type->IsNullableDouble() || (op_kind == Token::kDIV));
-          left_value = PrepareStaticOpInput(left_value, kDoubleCid, instr);
-          right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
-          replacement = new (Z) BinaryDoubleOpInstr(
-              op_kind, left_value, right_value, DeoptId::kNone,
-              instr->token_pos(), Instruction::kNotSpeculative);
-        }
+        break;
       }
-      break;
+
+      default:
+        break;
+    }
+  } else if (instr->ArgumentCount() == 1) {
+    Value* left_value = instr->PushArgumentAt(0)->value();
+    CompileType* left_type = left_value->Type();
+
+    // We only support unary operations on nullable integers.
+    if (!left_type->IsNullableInt()) {
+      return false;
     }
 
-    default:
-      break;
+    // Issue http://dartbug.com/35180 for adding support for Token::kBIT_NOT
+    // here.
+#ifndef TARGET_ARCH_DBC
+    if (op_kind == Token::kNEGATE) {
+      left_value = PrepareStaticOpInput(left_value, kMintCid, instr);
+      replacement =
+          new (Z) UnaryInt64OpInstr(Token::kNEGATE, left_value, DeoptId::kNone,
+                                    Instruction::kNotSpeculative);
+    }
+#endif
   }
 
-  if (replacement != NULL && !replacement->ComputeCanDeoptimize()) {
+  if (replacement != nullptr && !replacement->ComputeCanDeoptimize()) {
     if (FLAG_trace_strong_mode_types) {
       THR_Print("[Strong mode] Optimization: replacing %s with %s\n",
                 instr->ToCString(), replacement->ToCString());
@@ -497,47 +575,46 @@
   return false;
 }
 
-bool AotCallSpecializer::TryOptimizeStaticCallUsingStaticTypes(
-    StaticCallInstr* instr) {
-  ASSERT(I->can_use_strong_mode_types());
-  Definition* replacement = NULL;
-
-  const String& name = String::Handle(Z, instr->function().name());
-  const Token::Kind op_kind = MethodTokenRecognizer::RecognizeTokenKind(name);
-
-  if ((op_kind == Token::kEQ) && TryReplaceWithHaveSameRuntimeType(instr)) {
-    return true;
-  }
-
-  const Class& owner = Class::Handle(Z, instr->function().Owner());
-  if ((owner.id() != kIntegerCid) && (owner.id() != kDoubleCid)) {
+bool AotCallSpecializer::TryOptimizeDoubleOperation(TemplateDartCall<0>* instr,
+                                                    Token::Kind op_kind) {
+  if (instr->type_args_len() != 0) {
+    // Arithmetic operations don't have type arguments.
     return false;
   }
 
-  const intptr_t receiver_index = instr->FirstArgIndex();
+  Definition* replacement = NULL;
 
-  // Recognize double and int operators here as devirtualization can convert
-  // instance calls of these operators into static calls.
+  if (instr->ArgumentCount() == 2) {
+    if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {
+      return false;
+    }
 
-  if (owner.id() == kIntegerCid) {
-    if (!FlowGraphCompiler::SupportsUnboxedInt64()) {
+    Value* left_value = instr->PushArgumentAt(0)->value();
+    Value* right_value = instr->PushArgumentAt(1)->value();
+    CompileType* left_type = left_value->Type();
+    CompileType* right_type = right_value->Type();
+
+    if (!left_type->IsNullableDouble() &&
+        !IsSupportedIntOperandForStaticDoubleOp(left_type)) {
+      return false;
+    }
+    if (!right_type->IsNullableDouble() &&
+        !IsSupportedIntOperandForStaticDoubleOp(right_type)) {
       return false;
     }
 
     switch (op_kind) {
       case Token::kEQ:
       case Token::kNE: {
-        Value* left_value = instr->PushArgumentAt(receiver_index)->value();
-        Value* right_value = instr->PushArgumentAt(receiver_index + 1)->value();
-        CompileType* right_type = right_value->Type();
-        // TODO(dartbug.com/32166): Support EQ, NE for nullable ints.
+        // TODO(dartbug.com/32166): Support EQ, NE for nullable doubles.
         // (requires null-aware comparison instruction).
-        if (right_type->IsNullableInt() && !right_type->is_nullable()) {
-          left_value = PrepareReceiverOfDevirtualizedCall(left_value, kMintCid);
-          right_value = PrepareStaticOpInput(right_value, kMintCid, instr);
+        if (right_type->IsDouble()) {
+          left_value = PrepareStaticOpInput(left_value, kDoubleCid, instr);
+          right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
           replacement = new (Z) EqualityCompareInstr(
-              instr->token_pos(), op_kind, left_value, right_value, kMintCid,
+              instr->token_pos(), op_kind, left_value, right_value, kDoubleCid,
               DeoptId::kNone, Instruction::kNotSpeculative);
+          break;
         }
         break;
       }
@@ -545,164 +622,55 @@
       case Token::kLTE:
       case Token::kGT:
       case Token::kGTE: {
-        Value* left_value = instr->PushArgumentAt(receiver_index)->value();
-        Value* right_value = instr->PushArgumentAt(receiver_index + 1)->value();
-        CompileType* left_type = left_value->Type();
-        CompileType* right_type = right_value->Type();
-        if (right_type->IsNullableInt()) {
-          left_value = PrepareReceiverOfDevirtualizedCall(left_value, kMintCid);
-          right_value = PrepareStaticOpInput(right_value, kMintCid, instr);
-          replacement = new (Z) RelationalOpInstr(
-              instr->token_pos(), op_kind, left_value, right_value, kMintCid,
-              DeoptId::kNone, Instruction::kNotSpeculative);
-        } else if (FlowGraphCompiler::SupportsUnboxedDoubles() &&
-                   right_type->IsNullableDouble() &&
-                   IsSupportedIntOperandForStaticDoubleOp(left_type)) {
-          left_value = PrepareStaticOpInput(left_value, kDoubleCid, instr);
-          right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
-          replacement = new (Z) RelationalOpInstr(
-              instr->token_pos(), op_kind, left_value, right_value, kDoubleCid,
-              DeoptId::kNone, Instruction::kNotSpeculative);
-        }
+        left_value = PrepareStaticOpInput(left_value, kDoubleCid, instr);
+        right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
+        replacement = new (Z) RelationalOpInstr(
+            instr->token_pos(), op_kind, left_value, right_value, kDoubleCid,
+            DeoptId::kNone, Instruction::kNotSpeculative);
         break;
       }
-      case Token::kBIT_OR:
-      case Token::kBIT_XOR:
-      case Token::kBIT_AND:
       case Token::kADD:
       case Token::kSUB:
       case Token::kMUL:
-#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
-      // TODO(ajcbik): 32-bit archs too?
-      case Token::kMOD:
-      case Token::kTRUNCDIV:
-#endif
       case Token::kDIV: {
-        if ((op_kind == Token::kDIV) &&
+        if (op_kind == Token::kDIV &&
             !FlowGraphCompiler::SupportsHardwareDivision()) {
           return false;
         }
-        Value* left_value = instr->PushArgumentAt(receiver_index)->value();
-        Value* right_value = instr->PushArgumentAt(receiver_index + 1)->value();
-        CompileType* left_type = left_value->Type();
-        CompileType* right_type = right_value->Type();
-        if (right_type->IsNullableInt() && (op_kind != Token::kDIV)) {
-          left_value = PrepareReceiverOfDevirtualizedCall(left_value, kMintCid);
-          right_value = PrepareStaticOpInput(right_value, kMintCid, instr);
-          replacement = new (Z)
-              BinaryInt64OpInstr(op_kind, left_value, right_value,
-                                 DeoptId::kNone, Instruction::kNotSpeculative);
-        } else if (FlowGraphCompiler::SupportsUnboxedDoubles() &&
-                   right_type->IsNullableDouble() &&
-                   IsSupportedIntOperandForStaticDoubleOp(left_type)) {
-          if ((op_kind == Token::kADD) || (op_kind == Token::kSUB) ||
-              (op_kind == Token::kMUL) || (op_kind == Token::kDIV)) {
-            ASSERT(left_type->IsNullableDouble() ||
-                   right_type->IsNullableDouble() || (op_kind == Token::kDIV));
-            left_value = PrepareStaticOpInput(left_value, kDoubleCid, instr);
-            right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
-            replacement = new (Z) BinaryDoubleOpInstr(
-                op_kind, left_value, right_value, DeoptId::kNone,
-                instr->token_pos(), Instruction::kNotSpeculative);
-          }
-        }
+        left_value = PrepareStaticOpInput(left_value, kDoubleCid, instr);
+        right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
+        replacement = new (Z) BinaryDoubleOpInstr(
+            op_kind, left_value, right_value, DeoptId::kNone,
+            instr->token_pos(), Instruction::kNotSpeculative);
         break;
       }
-#ifndef TARGET_ARCH_DBC
-      case Token::kNEGATE: {
-        Value* left_value = instr->PushArgumentAt(receiver_index)->value();
-        left_value = PrepareReceiverOfDevirtualizedCall(left_value, kMintCid);
-        replacement = new (Z)
-            UnaryInt64OpInstr(Token::kNEGATE, left_value, DeoptId::kNone,
-                              Instruction::kNotSpeculative);
-        break;
-      }
-#endif
-      case Token::kSHL:
-      case Token::kSHR: {
-        Value* left_value = instr->PushArgumentAt(receiver_index)->value();
-        Value* right_value = instr->PushArgumentAt(receiver_index + 1)->value();
-        CompileType* right_type = right_value->Type();
-        if (right_type->IsNullableInt()) {
-          left_value = PrepareReceiverOfDevirtualizedCall(left_value, kMintCid);
-          right_value = PrepareStaticOpInput(right_value, kMintCid, instr);
-          replacement = new (Z) ShiftInt64OpInstr(op_kind, left_value,
-                                                  right_value, DeoptId::kNone);
-        }
-        break;
-      }
+
+      case Token::kBIT_OR:
+      case Token::kBIT_XOR:
+      case Token::kBIT_AND:
+      case Token::kMOD:
+      case Token::kTRUNCDIV:
       default:
         break;
     }
-  } else if ((owner.id() == kDoubleCid) &&
-             FlowGraphCompiler::SupportsUnboxedDoubles()) {
-    // TODO(dartbug.com/30480): Handle more double operations.
-    switch (op_kind) {
-      case Token::kEQ:
-      case Token::kNE: {
-        Value* left_value = instr->PushArgumentAt(receiver_index)->value();
-        Value* right_value = instr->PushArgumentAt(receiver_index + 1)->value();
-        CompileType* right_type = right_value->Type();
-        // TODO(dartbug.com/32166): Support EQ, NE for nullable doubles.
-        // (requires null-aware comparison instruction).
-        if (right_type->IsNullableDouble() && !right_type->is_nullable()) {
-          left_value =
-              PrepareReceiverOfDevirtualizedCall(left_value, kDoubleCid);
-          right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
-          replacement = new (Z) EqualityCompareInstr(
-              instr->token_pos(), op_kind, left_value, right_value, kDoubleCid,
-              DeoptId::kNone, Instruction::kNotSpeculative);
-        }
-        break;
-      }
-      case Token::kLT:
-      case Token::kLTE:
-      case Token::kGT:
-      case Token::kGTE: {
-        Value* left_value = instr->PushArgumentAt(receiver_index)->value();
-        Value* right_value = instr->PushArgumentAt(receiver_index + 1)->value();
-        if (right_value->Type()->IsNullableDouble() ||
-            IsSupportedIntOperandForStaticDoubleOp(right_value->Type())) {
-          left_value =
-              PrepareReceiverOfDevirtualizedCall(left_value, kDoubleCid);
-          right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
-          replacement = new (Z) RelationalOpInstr(
-              instr->token_pos(), op_kind, left_value, right_value, kDoubleCid,
-              DeoptId::kNone, Instruction::kNotSpeculative);
-        }
-        break;
-      }
-      case Token::kADD:
-      case Token::kSUB:
-      case Token::kMUL:
-      case Token::kDIV: {
-        Value* left_value = instr->PushArgumentAt(receiver_index)->value();
-        Value* right_value = instr->PushArgumentAt(receiver_index + 1)->value();
-        if (right_value->Type()->IsNullableDouble() ||
-            IsSupportedIntOperandForStaticDoubleOp(right_value->Type())) {
-          left_value =
-              PrepareReceiverOfDevirtualizedCall(left_value, kDoubleCid);
-          right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
-          replacement = new (Z) BinaryDoubleOpInstr(
-              op_kind, left_value, right_value, DeoptId::kNone,
-              instr->token_pos(), Instruction::kNotSpeculative);
-        }
-        break;
-      }
-      case Token::kNEGATE: {
-        Value* left_value = instr->PushArgumentAt(receiver_index)->value();
-        left_value = PrepareReceiverOfDevirtualizedCall(left_value, kDoubleCid);
-        replacement = new (Z)
-            UnaryDoubleOpInstr(Token::kNEGATE, left_value, instr->deopt_id(),
-                               Instruction::kNotSpeculative);
-        break;
-      }
-      default:
-        break;
+  } else if (instr->ArgumentCount() == 1) {
+    Value* left_value = instr->PushArgumentAt(0)->value();
+    CompileType* left_type = left_value->Type();
+
+    // We only support unary operations on nullable doubles.
+    if (!left_type->IsNullableDouble()) {
+      return false;
+    }
+
+    if (op_kind == Token::kNEGATE) {
+      left_value = PrepareStaticOpInput(left_value, kDoubleCid, instr);
+      replacement = new (Z)
+          UnaryDoubleOpInstr(Token::kNEGATE, left_value, instr->deopt_id(),
+                             Instruction::kNotSpeculative);
     }
   }
 
-  if ((replacement != NULL) && !replacement->ComputeCanDeoptimize()) {
+  if (replacement != NULL && !replacement->ComputeCanDeoptimize()) {
     if (FLAG_trace_strong_mode_types) {
       THR_Print("[Strong mode] Optimization: replacing %s with %s\n",
                 instr->ToCString(), replacement->ToCString());
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.h b/runtime/vm/compiler/aot/aot_call_specializer.h
index 5ffbea1..a18b78c 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.h
+++ b/runtime/vm/compiler/aot/aot_call_specializer.h
@@ -48,12 +48,22 @@
   bool IsSupportedIntOperandForStaticDoubleOp(CompileType* operand_type);
   Value* PrepareStaticOpInput(Value* input, intptr_t cid, Instruction* call);
 
-  Value* PrepareReceiverOfDevirtualizedCall(Value* input, intptr_t cid);
+  CompileType BuildStrengthenedReceiverType(Value* input, intptr_t cid);
 
   bool TryOptimizeInstanceCallUsingStaticTypes(InstanceCallInstr* instr);
 
   virtual bool TryOptimizeStaticCallUsingStaticTypes(StaticCallInstr* call);
 
+  // Try to replace a call with a more specialized instruction working on
+  // integers (e.g. BinaryInt64OpInstr, CheckedSmiComparisonInstr,
+  // RelationalOpInstr)
+  bool TryOptimizeIntegerOperation(TemplateDartCall<0>* call, Token::Kind kind);
+
+  // Try to replace a call with a more specialized instruction working on
+  // doubles (e.g. BinaryDoubleOpInstr, CheckedSmiComparisonInstr,
+  // RelationalOpInstr)
+  bool TryOptimizeDoubleOperation(TemplateDartCall<0>* call, Token::Kind kind);
+
   // Check if o.m(...) [call] is actually an invocation through a getter
   // o.get:m().call(...) given that the receiver of the call is a subclass
   // of the [receiver_class]. If it is - then expand it into
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index c272742..216bdb5 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -369,9 +369,6 @@
     }
 
     CheckForNewDynamicFunctions();
-    if (!changed_) {
-      TraceConstFunctions();
-    }
     CollectCallbackFields();
   }
 }
@@ -477,14 +474,21 @@
 
   const Code& code = Code::Handle(Z, function.CurrentCode());
 
-  const Array& table = Array::Handle(Z, code.static_calls_target_table());
   Object& entry = Object::Handle(Z);
+  Class& cls = Class::Handle(Z);
   Function& target = Function::Handle(Z);
-  for (intptr_t i = 0; i < table.Length(); i++) {
-    entry = table.At(i);
+
+  const Array& table = Array::Handle(Z, code.static_calls_target_table());
+  StaticCallsTable static_calls(table);
+  for (auto& view : static_calls) {
+    entry = view.Get<Code::kSCallTableFunctionTarget>();
     if (entry.IsFunction()) {
-      target ^= entry.raw();
-      AddFunction(target);
+      AddFunction(Function::Cast(entry));
+    }
+    entry = view.Get<Code::kSCallTableCodeTarget>();
+    if (entry.IsCode() && Code::Cast(entry).IsAllocationStubCode()) {
+      cls ^= Code::Cast(entry).owner();
+      AddInstantiatedClass(cls);
     }
   }
 
@@ -493,58 +497,11 @@
 #endif
 
   const ObjectPool& pool = ObjectPool::Handle(Z, code.GetObjectPool());
-  ICData& call_site = ICData::Handle(Z);
-  MegamorphicCache& cache = MegamorphicCache::Handle(Z);
   String& selector = String::Handle(Z);
-  Field& field = Field::Handle(Z);
-  Class& cls = Class::Handle(Z);
-  Instance& instance = Instance::Handle(Z);
-  Code& target_code = Code::Handle(Z);
   for (intptr_t i = 0; i < pool.Length(); i++) {
     if (pool.TypeAt(i) == ObjectPool::kTaggedObject) {
       entry = pool.ObjectAt(i);
-      if (entry.IsICData()) {
-        // A dynamic call.
-        call_site ^= entry.raw();
-        ASSERT(!call_site.is_static_call());
-        selector = call_site.target_name();
-        AddSelector(selector);
-        if (selector.raw() == Symbols::Call().raw()) {
-          // Potential closure call.
-          const Array& arguments_descriptor =
-              Array::Handle(Z, call_site.arguments_descriptor());
-          AddClosureCall(arguments_descriptor);
-        }
-      } else if (entry.IsMegamorphicCache()) {
-        // A dynamic call.
-        cache ^= entry.raw();
-        selector = cache.target_name();
-        AddSelector(selector);
-        if (selector.raw() == Symbols::Call().raw()) {
-          // Potential closure call.
-          const Array& arguments_descriptor =
-              Array::Handle(Z, cache.arguments_descriptor());
-          AddClosureCall(arguments_descriptor);
-        }
-      } else if (entry.IsField()) {
-        // Potential need for field initializer.
-        field ^= entry.raw();
-        AddField(field);
-      } else if (entry.IsInstance()) {
-        // Const object, literal or args descriptor.
-        instance ^= entry.raw();
-        AddConstObject(instance);
-      } else if (entry.IsFunction()) {
-        // Local closure function.
-        target ^= entry.raw();
-        AddFunction(target);
-      } else if (entry.IsCode()) {
-        target_code ^= entry.raw();
-        if (target_code.IsAllocationStubCode()) {
-          cls ^= target_code.owner();
-          AddInstantiatedClass(cls);
-        }
-      }
+      AddCalleesOfHelper(entry, &selector, &cls);
     }
   }
 
@@ -556,6 +513,53 @@
   }
 }
 
+void Precompiler::AddCalleesOfHelper(const Object& entry,
+                                     String* temp_selector,
+                                     Class* temp_cls) {
+  if (entry.IsICData()) {
+    const auto& call_site = ICData::Cast(entry);
+    // A dynamic call.
+    ASSERT(!call_site.is_static_call());
+    *temp_selector = call_site.target_name();
+    AddSelector(*temp_selector);
+    if (temp_selector->raw() == Symbols::Call().raw()) {
+      // Potential closure call.
+      const Array& arguments_descriptor =
+          Array::Handle(Z, call_site.arguments_descriptor());
+      AddClosureCall(arguments_descriptor);
+    }
+  } else if (entry.IsMegamorphicCache()) {
+    // A dynamic call.
+    const auto& cache = MegamorphicCache::Cast(entry);
+    *temp_selector = cache.target_name();
+    AddSelector(*temp_selector);
+    if (temp_selector->raw() == Symbols::Call().raw()) {
+      // Potential closure call.
+      const Array& arguments_descriptor =
+          Array::Handle(Z, cache.arguments_descriptor());
+      AddClosureCall(arguments_descriptor);
+    }
+  } else if (entry.IsField()) {
+    // Potential need for field initializer.
+    const auto& field = Field::Cast(entry);
+    AddField(field);
+  } else if (entry.IsInstance()) {
+    // Const object, literal or args descriptor.
+    const auto& instance = Instance::Cast(entry);
+    AddConstObject(instance);
+  } else if (entry.IsFunction()) {
+    // Local closure function.
+    const auto& target = Function::Cast(entry);
+    AddFunction(target);
+  } else if (entry.IsCode()) {
+    const auto& target_code = Code::Cast(entry);
+    if (target_code.IsAllocationStubCode()) {
+      *temp_cls ^= target_code.owner();
+      AddInstantiatedClass(*temp_cls);
+    }
+  }
+}
+
 void Precompiler::AddTypesOf(const Class& cls) {
   if (cls.IsNull()) return;
   if (classes_to_retain_.HasKey(&cls)) return;
@@ -1304,35 +1308,6 @@
   table.Release();
 }
 
-void Precompiler::TraceConstFunctions() {
-  // Compilation of const accessors happens outside of the treeshakers
-  // queue, so we haven't previously scanned its literal pool.
-
-  Library& lib = Library::Handle(Z);
-  Class& cls = Class::Handle(Z);
-  Array& functions = Array::Handle(Z);
-  Function& function = Function::Handle(Z);
-
-  for (intptr_t i = 0; i < libraries_.Length(); i++) {
-    lib ^= libraries_.At(i);
-    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
-    while (it.HasNext()) {
-      cls = it.GetNextClass();
-      if (cls.IsDynamicClass()) {
-        continue;  // class 'dynamic' is in the read-only VM isolate.
-      }
-
-      functions = cls.functions();
-      for (intptr_t j = 0; j < functions.Length(); j++) {
-        function ^= functions.At(j);
-        if (function.is_const() && function.HasCode()) {
-          AddCalleesOf(function);
-        }
-      }
-    }
-  }
-}
-
 void Precompiler::TraceForRetainedFunctions() {
   Library& lib = Library::Handle(Z);
   Class& cls = Class::Handle(Z);
@@ -1954,8 +1929,8 @@
     explicit BindStaticCallsVisitor(Zone* zone)
         : code_(Code::Handle(zone)),
           table_(Array::Handle(zone)),
-          pc_offset_(Smi::Handle(zone)),
-          target_(Function::Handle(zone)),
+          kind_and_offset_(Smi::Handle(zone)),
+          target_(Object::Handle(zone)),
           target_code_(Code::Handle(zone)) {}
 
     void Visit(const Function& function) {
@@ -1964,15 +1939,16 @@
       }
       code_ = function.CurrentCode();
       table_ = code_.static_calls_target_table();
-
-      for (intptr_t i = 0; i < table_.Length();
-           i += Code::kSCallTableEntryLength) {
-        pc_offset_ ^= table_.At(i + Code::kSCallTableOffsetEntry);
-        target_ ^= table_.At(i + Code::kSCallTableFunctionEntry);
+      StaticCallsTable static_calls(table_);
+      for (auto& view : static_calls) {
+        kind_and_offset_ = view.Get<Code::kSCallTableKindAndOffset>();
+        auto kind = Code::KindField::decode(kind_and_offset_.Value());
+        ASSERT(kind == Code::kCallViaCode);
+        auto pc_offset = Code::OffsetField::decode(kind_and_offset_.Value());
+        target_ = view.Get<Code::kSCallTableFunctionTarget>();
         if (target_.IsNull()) {
-          target_code_ ^= table_.At(i + Code::kSCallTableCodeEntry);
-          ASSERT(!target_code_.IsNull());
-          ASSERT(!target_code_.IsFunctionCode());
+          target_ = view.Get<Code::kSCallTableCodeTarget>();
+          ASSERT(!Code::Cast(target_).IsFunctionCode());
           // Allocation stub or AllocateContext or AllocateArray or ...
         } else {
           // Static calls initially call the CallStaticFunction stub because
@@ -1980,9 +1956,10 @@
           // static call targets are compiled.
           // Cf. runtime entry PatchStaticCall called from CallStaticFunction
           // stub.
-          ASSERT(target_.HasCode());
-          target_code_ ^= target_.CurrentCode();
-          uword pc = pc_offset_.Value() + code_.PayloadStart();
+          const auto& fun = Function::Cast(target_);
+          ASSERT(fun.HasCode());
+          target_code_ ^= fun.CurrentCode();
+          uword pc = pc_offset + code_.PayloadStart();
           CodePatcher::PatchStaticCallAt(pc, code_, target_code_);
         }
       }
@@ -1995,8 +1972,8 @@
    private:
     Code& code_;
     Array& table_;
-    Smi& pc_offset_;
-    Function& target_;
+    Smi& kind_and_offset_;
+    Object& target_;
     Code& target_code_;
   };
 
@@ -2022,13 +1999,10 @@
   // array. Iterate all the object pools and rewrite the ic data from
   // (cid, target function, count) to (cid, target code, entry point), and
   // replace the ICCallThroughFunction stub with ICCallThroughCode.
-
-  class SwitchICCallsVisitor : public FunctionVisitor {
+  class ICCallSwitcher {
    public:
-    explicit SwitchICCallsVisitor(Zone* zone)
+    explicit ICCallSwitcher(Zone* zone)
         : zone_(zone),
-          code_(Code::Handle(zone)),
-          pool_(ObjectPool::Handle(zone)),
           entry_(Object::Handle(zone)),
           ic_(ICData::Handle(zone)),
           target_name_(String::Handle(zone)),
@@ -2037,16 +2011,10 @@
           target_code_(Code::Handle(zone)),
           canonical_unlinked_calls_() {}
 
-    void Visit(const Function& function) {
-      if (!function.HasCode()) {
-        return;
-      }
-
-      code_ = function.CurrentCode();
-      pool_ = code_.object_pool();
-      for (intptr_t i = 0; i < pool_.Length(); i++) {
-        if (pool_.TypeAt(i) != ObjectPool::kTaggedObject) continue;
-        entry_ = pool_.ObjectAt(i);
+    void SwitchPool(const ObjectPool& pool) {
+      for (intptr_t i = 0; i < pool.Length(); i++) {
+        if (pool.TypeAt(i) != ObjectPool::kTaggedObject) continue;
+        entry_ = pool.ObjectAt(i);
         if (entry_.IsICData()) {
           // The only IC calls generated by precompilation are for switchable
           // calls.
@@ -2059,11 +2027,11 @@
           args_descriptor_ = ic_.arguments_descriptor();
           unlinked_.set_args_descriptor(args_descriptor_);
           unlinked_ = DedupUnlinkedCall(unlinked_);
-          pool_.SetObjectAt(i, unlinked_);
+          pool.SetObjectAt(i, unlinked_);
         } else if (entry_.raw() ==
                    StubCode::ICCallThroughFunction_entry()->code()) {
           target_code_ = StubCode::UnlinkedCall_entry()->code();
-          pool_.SetObjectAt(i, target_code_);
+          pool.SetObjectAt(i, target_code_);
         }
       }
     }
@@ -2082,8 +2050,6 @@
 
    private:
     Zone* zone_;
-    Code& code_;
-    ObjectPool& pool_;
     Object& entry_;
     ICData& ic_;
     String& target_name_;
@@ -2093,8 +2059,30 @@
     UnlinkedCallSet canonical_unlinked_calls_;
   };
 
-  ASSERT(!I->compilation_allowed());
-  SwitchICCallsVisitor visitor(Z);
+  class SwitchICCallsVisitor : public FunctionVisitor {
+   public:
+    SwitchICCallsVisitor(ICCallSwitcher* ic_call_switcher, Zone* zone)
+        : ic_call_switcher_(*ic_call_switcher),
+          code_(Code::Handle(zone)),
+          pool_(ObjectPool::Handle(zone)) {}
+
+    void Visit(const Function& function) {
+      if (!function.HasCode()) {
+        return;
+      }
+      code_ = function.CurrentCode();
+      pool_ = code_.object_pool();
+      ic_call_switcher_.SwitchPool(pool_);
+    }
+
+   private:
+    ICCallSwitcher& ic_call_switcher_;
+    Code& code_;
+    ObjectPool& pool_;
+  };
+
+  ICCallSwitcher switcher(Z);
+  SwitchICCallsVisitor visitor(&switcher, Z);
 
   // We need both iterations to ensure we visit all the functions that might end
   // up in the snapshot. The ProgramVisitor will miss closures from duplicated
@@ -2232,7 +2220,8 @@
   // Allocates instruction object. Since this occurs only at safepoint,
   // there can be no concurrent access to the instruction page.
   const Code& code = Code::Handle(Code::FinalizeCode(
-      function, graph_compiler, assembler, optimized(), stats));
+      function, graph_compiler, assembler, Code::PoolAttachment::kAttachPool,
+      optimized(), stats));
   code.set_is_optimized(optimized());
   code.set_owner(function);
   if (!function.IsOptimizable()) {
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index a884b26..47ac594 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -262,6 +262,9 @@
   void AddTypesOf(const Function& function);
   void AddTypeArguments(const TypeArguments& args);
   void AddCalleesOf(const Function& function);
+  void AddCalleesOfHelper(const Object& entry,
+                          String* temp_selector,
+                          Class* temp_cls);
   void AddConstObject(const Instance& instance);
   void AddClosureCall(const Array& arguments_descriptor);
   void AddField(const Field& field);
@@ -272,7 +275,6 @@
 
   void ProcessFunction(const Function& function);
   void CheckForNewDynamicFunctions();
-  void TraceConstFunctions();
   void CollectCallbackFields();
 
   void AttachOptimizedTypeTestingStub();
diff --git a/runtime/vm/compiler/assembler/assembler.cc b/runtime/vm/compiler/assembler/assembler.cc
index 8c94874..af83190 100644
--- a/runtime/vm/compiler/assembler/assembler.cc
+++ b/runtime/vm/compiler/assembler/assembler.cc
@@ -173,7 +173,7 @@
 }
 
 // Shared macros are implemented here.
-void Assembler::Unimplemented(const char* message) {
+void AssemblerBase::Unimplemented(const char* message) {
   const char* format = "Unimplemented: %s";
   const intptr_t len = Utils::SNPrint(NULL, 0, format, message);
   char* buffer = reinterpret_cast<char*>(malloc(len + 1));
@@ -181,7 +181,7 @@
   Stop(buffer);
 }
 
-void Assembler::Untested(const char* message) {
+void AssemblerBase::Untested(const char* message) {
   const char* format = "Untested: %s";
   const intptr_t len = Utils::SNPrint(NULL, 0, format, message);
   char* buffer = reinterpret_cast<char*>(malloc(len + 1));
@@ -189,7 +189,7 @@
   Stop(buffer);
 }
 
-void Assembler::Unreachable(const char* message) {
+void AssemblerBase::Unreachable(const char* message) {
   const char* format = "Unreachable: %s";
   const intptr_t len = Utils::SNPrint(NULL, 0, format, message);
   char* buffer = reinterpret_cast<char*>(malloc(len + 1));
@@ -197,7 +197,7 @@
   Stop(buffer);
 }
 
-void Assembler::Comment(const char* format, ...) {
+void AssemblerBase::Comment(const char* format, ...) {
   if (EmittingComments()) {
     char buffer[1024];
 
@@ -212,11 +212,11 @@
   }
 }
 
-bool Assembler::EmittingComments() {
+bool AssemblerBase::EmittingComments() {
   return FLAG_code_comments || FLAG_disassemble || FLAG_disassemble_optimized;
 }
 
-const Code::Comments& Assembler::GetCodeComments() const {
+const Code::Comments& AssemblerBase::GetCodeComments() const {
   Code::Comments& comments = Code::Comments::New(comments_.length());
 
   for (intptr_t i = 0; i < comments_.length(); i++) {
diff --git a/runtime/vm/compiler/assembler/assembler.h b/runtime/vm/compiler/assembler/assembler.h
index 90d106d..b411ed3 100644
--- a/runtime/vm/compiler/assembler/assembler.h
+++ b/runtime/vm/compiler/assembler/assembler.h
@@ -412,6 +412,77 @@
 
 enum RestorePP { kRestoreCallerPP, kKeepCalleePP };
 
+class AssemblerBase : public ValueObject {
+ public:
+  explicit AssemblerBase(ObjectPoolWrapper* object_pool_wrapper)
+      : prologue_offset_(-1),
+        has_single_entry_point_(true),
+        object_pool_wrapper_(object_pool_wrapper) {}
+  virtual ~AssemblerBase() {}
+
+  intptr_t CodeSize() const { return buffer_.Size(); }
+
+  uword CodeAddress(intptr_t offset) { return buffer_.Address(offset); }
+
+  ObjectPoolWrapper& object_pool_wrapper() { return *object_pool_wrapper_; }
+
+  intptr_t prologue_offset() const { return prologue_offset_; }
+  bool has_single_entry_point() const { return has_single_entry_point_; }
+
+  void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
+  static bool EmittingComments();
+
+  const Code::Comments& GetCodeComments() const;
+
+  void Unimplemented(const char* message);
+  void Untested(const char* message);
+  void Unreachable(const char* message);
+  virtual void Stop(const char* message) = 0;
+
+  void FinalizeInstructions(const MemoryRegion& region) {
+    buffer_.FinalizeInstructions(region);
+  }
+
+  // Count the fixups that produce a pointer offset, without processing
+  // the fixups.
+  intptr_t CountPointerOffsets() const { return buffer_.CountPointerOffsets(); }
+
+  const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
+    return buffer_.pointer_offsets();
+  }
+
+  RawObjectPool* MakeObjectPool() {
+    if (object_pool_wrapper_ != nullptr) {
+      return object_pool_wrapper_->MakeObjectPool();
+    }
+    return ObjectPool::null();
+  }
+
+ protected:
+  AssemblerBuffer buffer_;  // Contains position independent code.
+  int32_t prologue_offset_;
+  bool has_single_entry_point_;
+
+ private:
+  class CodeComment : public ZoneAllocated {
+   public:
+    CodeComment(intptr_t pc_offset, const String& comment)
+        : pc_offset_(pc_offset), comment_(comment) {}
+
+    intptr_t pc_offset() const { return pc_offset_; }
+    const String& comment() const { return comment_; }
+
+   private:
+    intptr_t pc_offset_;
+    const String& comment_;
+
+    DISALLOW_COPY_AND_ASSIGN(CodeComment);
+  };
+
+  GrowableArray<CodeComment*> comments_;
+  ObjectPoolWrapper* object_pool_wrapper_;
+};
+
 }  // namespace dart
 
 #if defined(TARGET_ARCH_IA32)
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index e35c3c1..320d6e3 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -1591,8 +1591,6 @@
   ASSERT(object != value);
   ASSERT(object != LR);
   ASSERT(value != LR);
-
-#if defined(CONCURRENT_MARKING)
   ASSERT(object != TMP);
   ASSERT(value != TMP);
 
@@ -1645,31 +1643,55 @@
   }
   if (!lr_reserved) Pop(LR);
   Bind(&done);
-#else
-  str(value, dest);
-  // A store buffer update is required.
-  if (lr_reserved) {
-    StoreIntoObjectFilter(object, value, nullptr, can_be_smi, kNoJump);
-    ldr(LR, Address(THR, Thread::write_barrier_wrappers_offset(object)), NE);
-    blx(LR, NE);
-  } else {
-    Label done;
-    StoreIntoObjectFilter(object, value, &done, can_be_smi, kJumpToNoUpdate);
-    RegList regs = 0;
-    regs |= (1 << LR);
-    if (value != kWriteBarrierObjectReg) {
-      regs |= (1 << kWriteBarrierObjectReg);
-    }
-    PushList(regs);
-    if (object != kWriteBarrierObjectReg) {
-      mov(kWriteBarrierObjectReg, Operand(object));
-    }
-    ldr(LR, Address(THR, Thread::write_barrier_entry_point_offset()));
-    blx(LR);
-    PopList(regs);
-    Bind(&done);
+}
+
+void Assembler::StoreIntoArray(Register object,
+                               Register slot,
+                               Register value,
+                               CanBeSmi can_be_smi,
+                               bool lr_reserved) {
+  // x.slot = x. Barrier should have be removed at the IL level.
+  ASSERT(object != value);
+  ASSERT(object != LR);
+  ASSERT(value != LR);
+  ASSERT(slot != LR);
+  ASSERT(object != TMP);
+  ASSERT(value != TMP);
+  ASSERT(slot != TMP);
+
+  str(value, Address(slot, 0));
+
+  // In parallel, test whether
+  //  - object is old and not remembered and value is new, or
+  //  - object is old and value is old and not marked and concurrent marking is
+  //    in progress
+  // If so, call the WriteBarrier stub, which will either add object to the
+  // store buffer (case 1) or add value to the marking stack (case 2).
+  // Compare RawObject::StorePointer.
+  Label done;
+  if (can_be_smi == kValueCanBeSmi) {
+    BranchIfSmi(value, &done);
   }
-#endif
+  if (!lr_reserved) Push(LR);
+  ldrb(TMP, FieldAddress(object, Object::tags_offset()));
+  ldrb(LR, FieldAddress(value, Object::tags_offset()));
+  and_(TMP, LR, Operand(TMP, LSR, RawObject::kBarrierOverlapShift));
+  ldr(LR, Address(THR, Thread::write_barrier_mask_offset()));
+  tst(TMP, Operand(LR));
+
+  if ((object != kWriteBarrierObjectReg) || (value != kWriteBarrierValueReg) ||
+      (slot != kWriteBarrierSlotReg)) {
+    // Spill and shuffle unimplemented. Currently StoreIntoArray is only used
+    // from StoreIndexInstr, which gets these exact registers from the register
+    // allocator.
+    UNIMPLEMENTED();
+  }
+
+  ldr(LR, Address(THR, Thread::array_write_barrier_entry_point_offset()), NE);
+  blx(LR, NE);
+
+  if (!lr_reserved) Pop(LR);
+  Bind(&done);
 }
 
 void Assembler::StoreIntoObjectOffset(Register object,
@@ -3386,6 +3408,11 @@
   }
 }
 
+void Assembler::GenerateUnRelocatedPcRelativeCall() {
+  // Emit "blr <offset>".
+  EmitType5(AL, 0x686868, /*link=*/true);
+}
+
 void Assembler::Stop(const char* message) {
   if (FLAG_print_stop_message) {
     PushList((1 << R0) | (1 << IP) | (1 << LR));  // Preserve R0, IP, LR.
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 93da8c4..801f1c3 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -336,16 +336,12 @@
   }
 };
 
-class Assembler : public ValueObject {
+class Assembler : public AssemblerBase {
  public:
   explicit Assembler(ObjectPoolWrapper* object_pool_wrapper,
                      bool use_far_branches = false)
-      : buffer_(),
-        object_pool_wrapper_(object_pool_wrapper),
-        prologue_offset_(-1),
-        has_single_entry_point_(true),
+      : AssemblerBase(object_pool_wrapper),
         use_far_branches_(use_far_branches),
-        comments_(),
         constant_pool_allowed_(false) {}
 
   ~Assembler() {}
@@ -364,25 +360,6 @@
   }
 
   // Misc. functionality
-  intptr_t CodeSize() const { return buffer_.Size(); }
-  intptr_t prologue_offset() const { return prologue_offset_; }
-  bool has_single_entry_point() const { return has_single_entry_point_; }
-
-  // Count the fixups that produce a pointer offset, without processing
-  // the fixups.  On ARM there are no pointers in code.
-  intptr_t CountPointerOffsets() const { return 0; }
-
-  const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
-    ASSERT(buffer_.pointer_offsets().length() == 0);  // No pointers in code.
-    return buffer_.pointer_offsets();
-  }
-
-  ObjectPoolWrapper& object_pool_wrapper() { return *object_pool_wrapper_; }
-
-  RawObjectPool* MakeObjectPool() {
-    return object_pool_wrapper_->MakeObjectPool();
-  }
-
   bool use_far_branches() const {
     return FLAG_use_far_branches || use_far_branches_;
   }
@@ -393,24 +370,12 @@
   void set_use_far_branches(bool b) { use_far_branches_ = b; }
 #endif  // TESTING || DEBUG
 
-  void FinalizeInstructions(const MemoryRegion& region) {
-    buffer_.FinalizeInstructions(region);
-  }
-
   // Debugging and bringup support.
   void Breakpoint() { bkpt(0); }
-  void Stop(const char* message);
-  void Unimplemented(const char* message);
-  void Untested(const char* message);
-  void Unreachable(const char* message);
+  void Stop(const char* message) override;
 
   static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
 
-  void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
-  static bool EmittingComments();
-
-  const Code::Comments& GetCodeComments() const;
-
   static const char* RegisterName(Register reg);
 
   static const char* FpuRegisterName(FpuRegister reg);
@@ -818,6 +783,11 @@
                        Register value,       // Value we are storing.
                        CanBeSmi can_value_be_smi = kValueCanBeSmi,
                        bool lr_reserved = false);
+  void StoreIntoArray(Register object,
+                      Register slot,
+                      Register value,
+                      CanBeSmi can_value_be_smi = kValueCanBeSmi,
+                      bool lr_reserved = false);
   void StoreIntoObjectOffset(Register object,
                              int32_t offset,
                              Register value,
@@ -1132,6 +1102,19 @@
                         Register temp1,
                         Register temp2);
 
+  // This emits an PC-relative call of the form "blr <offset>".  The offset
+  // is not yet known and needs therefore relocation to the right place before
+  // the code can be used.
+  //
+  // The neccessary information for the "linker" (i.e. the relocation
+  // information) is stored in [RawCode::static_calls_target_table_]: an entry
+  // of the form
+  //
+  //   (Code::kPcRelativeCall & pc_offset, <target-code>, <target-function>)
+  //
+  // will be used during relocation to fix the offset.
+  void GenerateUnRelocatedPcRelativeCall();
+
   // Emit data (e.g encoded instruction or immediate) in instruction stream.
   void Emit(int32_t value);
 
@@ -1160,10 +1143,6 @@
   static int32_t DecodeBranchOffset(int32_t inst);
 
  private:
-  AssemblerBuffer buffer_;  // Contains position independent code.
-  ObjectPoolWrapper* object_pool_wrapper_;
-  int32_t prologue_offset_;
-  bool has_single_entry_point_;
   bool use_far_branches_;
 
   // If you are thinking of using one or both of these instructions directly,
@@ -1176,23 +1155,6 @@
 
   void BranchLink(const ExternalLabel* label);
 
-  class CodeComment : public ZoneAllocated {
-   public:
-    CodeComment(intptr_t pc_offset, const String& comment)
-        : pc_offset_(pc_offset), comment_(comment) {}
-
-    intptr_t pc_offset() const { return pc_offset_; }
-    const String& comment() const { return comment_; }
-
-   private:
-    intptr_t pc_offset_;
-    const String& comment_;
-
-    DISALLOW_COPY_AND_ASSIGN(CodeComment);
-  };
-
-  GrowableArray<CodeComment*> comments_;
-
   bool constant_pool_allowed_;
 
   void LoadObjectHelper(Register rd,
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index c258d9a..5780bbd 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -23,12 +23,8 @@
 
 Assembler::Assembler(ObjectPoolWrapper* object_pool_wrapper,
                      bool use_far_branches)
-    : buffer_(),
-      object_pool_wrapper_(object_pool_wrapper),
-      prologue_offset_(-1),
-      has_single_entry_point_(true),
+    : AssemblerBase(object_pool_wrapper),
       use_far_branches_(use_far_branches),
-      comments_(),
       constant_pool_allowed_(false) {}
 
 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) {
@@ -979,8 +975,6 @@
   ASSERT(object != value);
   ASSERT(object != LR);
   ASSERT(value != LR);
-
-#if defined(CONCURRENT_MARKING)
   ASSERT(object != TMP);
   ASSERT(object != TMP2);
   ASSERT(value != TMP);
@@ -1032,20 +1026,53 @@
   }
   if (!lr_reserved) Pop(LR);
   Bind(&done);
-#else
-  ASSERT(object != value);
-  ASSERT(object != LR);
-  ASSERT(value != LR);
+}
 
-  str(value, dest);
+void Assembler::StoreIntoArray(Register object,
+                               Register slot,
+                               Register value,
+                               CanBeSmi can_be_smi,
+                               bool lr_reserved) {
+  ASSERT(object != TMP);
+  ASSERT(object != TMP2);
+  ASSERT(value != TMP);
+  ASSERT(value != TMP2);
+  ASSERT(slot != TMP);
+  ASSERT(slot != TMP2);
+
+  str(value, Address(slot, 0));
+
+  // In parallel, test whether
+  //  - object is old and not remembered and value is new, or
+  //  - object is old and value is old and not marked and concurrent marking is
+  //    in progress
+  // If so, call the WriteBarrier stub, which will either add object to the
+  // store buffer (case 1) or add value to the marking stack (case 2).
+  // Compare RawObject::StorePointer.
   Label done;
-  StoreIntoObjectFilter(object, value, &done, can_be_smi, kJumpToNoUpdate);
+  if (can_be_smi == kValueCanBeSmi) {
+    BranchIfSmi(value, &done);
+  }
+  ldr(TMP, FieldAddress(object, Object::tags_offset()), kUnsignedByte);
+  ldr(TMP2, FieldAddress(value, Object::tags_offset()), kUnsignedByte);
+  and_(TMP, TMP2, Operand(TMP, LSR, RawObject::kBarrierOverlapShift));
+  tst(TMP, Operand(BARRIER_MASK));
+  b(&done, ZERO);
   if (!lr_reserved) Push(LR);
-  ldr(LR, Address(THR, Thread::write_barrier_wrappers_offset(object)));
+
+  if ((object != kWriteBarrierObjectReg) || (value != kWriteBarrierValueReg) ||
+      (slot != kWriteBarrierSlotReg)) {
+    // Spill and shuffle unimplemented. Currently StoreIntoArray is only used
+    // from StoreIndexInstr, which gets these exact registers from the register
+    // allocator.
+    UNIMPLEMENTED();
+  }
+
+  ldr(LR, Address(THR, Thread::array_write_barrier_entry_point_offset()));
   blr(LR);
+
   if (!lr_reserved) Pop(LR);
   Bind(&done);
-#endif
 }
 
 void Assembler::StoreIntoObjectNoBarrier(Register object,
@@ -1519,6 +1546,11 @@
   }
 }
 
+void Assembler::GenerateUnRelocatedPcRelativeCall() {
+  // Emit "bl <offset>".
+  EmitUnconditionalBranchOp(BL, 0x686868);
+}
+
 Address Assembler::ElementAddressForIntIndex(bool is_external,
                                              intptr_t cid,
                                              intptr_t index_scale,
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 7807f87..761ec23 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -423,7 +423,7 @@
   friend class Assembler;
 };
 
-class Assembler : public ValueObject {
+class Assembler : public AssemblerBase {
  public:
   explicit Assembler(ObjectPoolWrapper* object_pool_wrapper,
                      bool use_far_branches = false);
@@ -458,50 +458,18 @@
     cmp(value, Operand(TMP));
   }
 
-  // Misc. functionality
-  intptr_t CodeSize() const { return buffer_.Size(); }
-  intptr_t prologue_offset() const { return prologue_offset_; }
-  bool has_single_entry_point() const { return has_single_entry_point_; }
-
-  // Count the fixups that produce a pointer offset, without processing
-  // the fixups.  On ARM64 there are no pointers in code.
-  intptr_t CountPointerOffsets() const { return 0; }
-
-  const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
-    ASSERT(buffer_.pointer_offsets().length() == 0);  // No pointers in code.
-    return buffer_.pointer_offsets();
-  }
-
-  ObjectPoolWrapper& object_pool_wrapper() { return *object_pool_wrapper_; }
-
-  RawObjectPool* MakeObjectPool() {
-    return object_pool_wrapper_->MakeObjectPool();
-  }
-
   bool use_far_branches() const {
     return FLAG_use_far_branches || use_far_branches_;
   }
 
   void set_use_far_branches(bool b) { use_far_branches_ = b; }
 
-  void FinalizeInstructions(const MemoryRegion& region) {
-    buffer_.FinalizeInstructions(region);
-  }
-
   // Debugging and bringup support.
   void Breakpoint() { brk(0); }
-  void Stop(const char* message);
-  void Unimplemented(const char* message);
-  void Untested(const char* message);
-  void Unreachable(const char* message);
+  void Stop(const char* message) override;
 
   static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
 
-  void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
-  static bool EmittingComments();
-
-  const Code::Comments& GetCodeComments() const;
-
   static const char* RegisterName(Register reg);
 
   static const char* FpuRegisterName(FpuRegister reg);
@@ -1477,6 +1445,12 @@
                        Register value,
                        CanBeSmi can_value_be_smi = kValueCanBeSmi,
                        bool lr_reserved = false);
+  void StoreIntoArray(Register object,
+                      Register slot,
+                      Register value,
+                      CanBeSmi can_value_be_smi = kValueCanBeSmi,
+                      bool lr_reserved = false);
+
   void StoreIntoObjectOffset(Register object,
                              int32_t offset,
                              Register value,
@@ -1593,6 +1567,19 @@
                         Register temp1,
                         Register temp2);
 
+  // This emits an PC-relative call of the form "bl <offset>".  The offset
+  // is not yet known and needs therefore relocation to the right place before
+  // the code can be used.
+  //
+  // The neccessary information for the "linker" (i.e. the relocation
+  // information) is stored in [RawCode::static_calls_target_table_]: an entry
+  // of the form
+  //
+  //   (Code::kPcRelativeCall & pc_offset, <target-code>, <target-function>)
+  //
+  // will be used during relocation to fix the offset.
+  void GenerateUnRelocatedPcRelativeCall();
+
   Address ElementAddressForIntIndex(bool is_external,
                                     intptr_t cid,
                                     intptr_t index_scale,
@@ -1624,30 +1611,20 @@
                       Register tmp,
                       OperandSize sz);
 
+  static int32_t EncodeImm26BranchOffset(int64_t imm, int32_t instr) {
+    const int32_t imm32 = static_cast<int32_t>(imm);
+    const int32_t off = (((imm32 >> 2) << kImm26Shift) & kImm26Mask);
+    return (instr & ~kImm26Mask) | off;
+  }
+
+  static int64_t DecodeImm26BranchOffset(int32_t instr) {
+    const int32_t off = (((instr & kImm26Mask) >> kImm26Shift) << 6) >> 4;
+    return static_cast<int64_t>(off);
+  }
+
  private:
-  AssemblerBuffer buffer_;  // Contains position independent code.
-  ObjectPoolWrapper* object_pool_wrapper_;
-  int32_t prologue_offset_;
-  bool has_single_entry_point_;
   bool use_far_branches_;
 
-  class CodeComment : public ZoneAllocated {
-   public:
-    CodeComment(intptr_t pc_offset, const String& comment)
-        : pc_offset_(pc_offset), comment_(comment) {}
-
-    intptr_t pc_offset() const { return pc_offset_; }
-    const String& comment() const { return comment_; }
-
-   private:
-    intptr_t pc_offset_;
-    const String& comment_;
-
-    DISALLOW_COPY_AND_ASSIGN(CodeComment);
-  };
-
-  GrowableArray<CodeComment*> comments_;
-
   bool constant_pool_allowed_;
 
   void LoadWordFromPoolOffsetFixed(Register dst, uint32_t offset);
@@ -1849,17 +1826,6 @@
     return (instr & ~B24) | (cond == EQ ? B24 : 0);  // tbz : tbnz
   }
 
-  int32_t EncodeImm26BranchOffset(int64_t imm, int32_t instr) {
-    const int32_t imm32 = static_cast<int32_t>(imm);
-    const int32_t off = (((imm32 >> 2) << kImm26Shift) & kImm26Mask);
-    return (instr & ~kImm26Mask) | off;
-  }
-
-  int64_t DecodeImm26BranchOffset(int32_t instr) {
-    const int32_t off = (((instr & kImm26Mask) >> kImm26Shift) << 6) >> 4;
-    return static_cast<int64_t>(off);
-  }
-
   void EmitCompareAndBranchOp(CompareAndBranchOp op,
                               Register rt,
                               int64_t imm,
diff --git a/runtime/vm/compiler/assembler/assembler_dbc.cc b/runtime/vm/compiler/assembler/assembler_dbc.cc
index e52eaa8..3465c38 100644
--- a/runtime/vm/compiler/assembler/assembler_dbc.cc
+++ b/runtime/vm/compiler/assembler/assembler_dbc.cc
@@ -21,14 +21,15 @@
 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) {
   const uword end = data + length;
   while (data < end) {
-    *reinterpret_cast<int32_t*>(data) = Bytecode::kTrap;
+    *reinterpret_cast<int32_t*>(data) = SimulatorBytecode::kTrap;
     data += sizeof(int32_t);
   }
 }
 
 #define DEFINE_EMIT(Name, Signature, Fmt0, Fmt1, Fmt2)                         \
   void Assembler::Name(PARAMS_##Signature) {                                   \
-    Emit(Bytecode::FENCODE_##Signature(Bytecode::k##Name ENCODE_##Signature)); \
+    Emit(SimulatorBytecode::FENCODE_##Signature(                               \
+        SimulatorBytecode::k##Name ENCODE_##Signature));                       \
   }
 
 #define PARAMS_0
@@ -75,7 +76,7 @@
 }
 
 static int32_t EncodeJump(int32_t relative_pc) {
-  return Bytecode::kJump | (relative_pc << 8);
+  return SimulatorBytecode::kJump | (relative_pc << 8);
 }
 
 static int32_t OffsetToPC(int32_t offset) {
@@ -108,7 +109,7 @@
 
 void Assembler::Stop(const char* message) {
   // TODO(vegorov) support passing a message to the bytecode.
-  Emit(Bytecode::kTrap);
+  Emit(SimulatorBytecode::kTrap);
 }
 
 void Assembler::PushConstant(const Object& obj) {
diff --git a/runtime/vm/compiler/assembler/assembler_dbc.h b/runtime/vm/compiler/assembler/assembler_dbc.h
index 7642b4b7..09a5aa1 100644
--- a/runtime/vm/compiler/assembler/assembler_dbc.h
+++ b/runtime/vm/compiler/assembler/assembler_dbc.h
@@ -25,59 +25,29 @@
   Address();
 };
 
-class Assembler : public ValueObject {
+class Assembler : public AssemblerBase {
  public:
   explicit Assembler(ObjectPoolWrapper* object_pool_wrapper,
                      bool use_far_branches = false)
-      : buffer_(), object_pool_wrapper_(object_pool_wrapper), comments_() {}
-
+      : AssemblerBase(object_pool_wrapper) {}
   ~Assembler() {}
 
   void Bind(Label* label);
   void Jump(Label* label);
 
   // Misc. functionality
-  intptr_t CodeSize() const { return buffer_.Size(); }
   intptr_t prologue_offset() const { return 0; }
-  bool has_single_entry_point() const { return true; }
-
-  // Count the fixups that produce a pointer offset, without processing
-  // the fixups.
-  intptr_t CountPointerOffsets() const { return 0; }
-
-  const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
-    ASSERT(buffer_.pointer_offsets().length() == 0);  // No pointers in code.
-    return buffer_.pointer_offsets();
-  }
-
-  ObjectPoolWrapper& object_pool_wrapper() { return *object_pool_wrapper_; }
-
-  RawObjectPool* MakeObjectPool() {
-    return object_pool_wrapper_->MakeObjectPool();
-  }
-
-  void FinalizeInstructions(const MemoryRegion& region) {
-    buffer_.FinalizeInstructions(region);
-  }
 
   // Debugging and bringup support.
-  void Stop(const char* message);
-  void Unimplemented(const char* message);
-  void Untested(const char* message);
-  void Unreachable(const char* message);
+  void Stop(const char* message) override;
 
   static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
 
-  void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
-  static bool EmittingComments();
-
-  const Code::Comments& GetCodeComments() const;
-
   static const char* RegisterName(Register reg);
 
   static const char* FpuRegisterName(FpuRegister reg) { return "?"; }
 
-  static uword GetBreakInstructionFiller() { return Bytecode::kTrap; }
+  static uword GetBreakInstructionFiller() { return SimulatorBytecode::kTrap; }
 
   static bool IsSafe(const Object& value) { return true; }
   static bool IsSafeSmi(const Object& value) { return false; }
@@ -125,26 +95,6 @@
   void Nop(intptr_t d) { Nop(0, d); }
 
  private:
-  AssemblerBuffer buffer_;  // Contains position independent code.
-  ObjectPoolWrapper* object_pool_wrapper_;
-
-  class CodeComment : public ZoneAllocated {
-   public:
-    CodeComment(intptr_t pc_offset, const String& comment)
-        : pc_offset_(pc_offset), comment_(comment) {}
-
-    intptr_t pc_offset() const { return pc_offset_; }
-    const String& comment() const { return comment_; }
-
-   private:
-    intptr_t pc_offset_;
-    const String& comment_;
-
-    DISALLOW_COPY_AND_ASSIGN(CodeComment);
-  };
-
-  GrowableArray<CodeComment*> comments_;
-
   DISALLOW_ALLOCATION();
   DISALLOW_COPY_AND_ASSIGN(Assembler);
 };
diff --git a/runtime/vm/compiler/assembler/assembler_dbc_test.cc b/runtime/vm/compiler/assembler/assembler_dbc_test.cc
index 6f2417a..7652b45 100644
--- a/runtime/vm/compiler/assembler/assembler_dbc_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_dbc_test.cc
@@ -75,7 +75,8 @@
   const Function& dummy_instance_function =
       Function::Handle(CreateFunction(dummy_function_name));
   Code& code = Code::Handle(
-      Code::FinalizeCode(dummy_instance_function, nullptr, &_assembler_));
+      Code::FinalizeCode(dummy_instance_function, nullptr, &_assembler_,
+                         Code::PoolAttachment::kAttachPool));
   dummy_instance_function.AttachCode(code);
 
   // Make a dummy ICData.
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index e2074e5..a936849 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -1909,6 +1909,48 @@
   // No store buffer update.
 }
 
+// Destroys the value register.
+void Assembler::StoreIntoArray(Register object,
+                               Register slot,
+                               Register value,
+                               CanBeSmi can_be_smi) {
+  ASSERT(object != value);
+  movl(Address(slot, 0), value);
+
+  Label done;
+  StoreIntoObjectFilter(object, value, &done, can_be_smi, kJumpToNoUpdate);
+  // A store buffer update is required.
+  if (value != kWriteBarrierObjectReg) {
+    pushl(kWriteBarrierObjectReg);  // Preserve kWriteBarrierObjectReg.
+  }
+  if (value != kWriteBarrierSlotReg && slot != kWriteBarrierSlotReg) {
+    pushl(kWriteBarrierSlotReg);  // Preserve kWriteBarrierSlotReg.
+  }
+  if (object != kWriteBarrierObjectReg && slot != kWriteBarrierSlotReg) {
+    if (slot == kWriteBarrierObjectReg && object == kWriteBarrierSlotReg) {
+      xchgl(slot, object);
+    } else if (slot == kWriteBarrierObjectReg) {
+      movl(kWriteBarrierSlotReg, slot);
+      movl(kWriteBarrierObjectReg, object);
+    } else {
+      movl(kWriteBarrierObjectReg, object);
+      movl(kWriteBarrierSlotReg, slot);
+    }
+  } else if (object != kWriteBarrierObjectReg) {
+    movl(kWriteBarrierObjectReg, object);
+  } else if (slot != kWriteBarrierSlotReg) {
+    movl(kWriteBarrierSlotReg, slot);
+  }
+  call(Address(THR, Thread::array_write_barrier_entry_point_offset()));
+  if (value != kWriteBarrierSlotReg && slot != kWriteBarrierSlotReg) {
+    popl(kWriteBarrierSlotReg);  // Restore kWriteBarrierSlotReg.
+  }
+  if (value != kWriteBarrierObjectReg) {
+    popl(kWriteBarrierObjectReg);  // Restore kWriteBarrierObjectReg.
+  }
+  Bind(&done);
+}
+
 void Assembler::UnverifiedStoreOldObject(const Address& dest,
                                          const Object& value) {
   ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index cb75d28..4c4854c 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -221,18 +221,13 @@
   }
 };
 
-class Assembler : public ValueObject {
+class Assembler : public AssemblerBase {
  public:
   explicit Assembler(ObjectPoolWrapper* object_pool_wrapper,
                      bool use_far_branches = false)
-      : buffer_(),
-        prologue_offset_(-1),
+      : AssemblerBase(object_pool_wrapper),
         jit_cookie_(0),
-        comments_(),
         code_(Code::ZoneHandle()) {
-    // On ia32 we don't use object pools.
-    USE(object_pool_wrapper);
-
     // This mode is only needed and implemented for ARM.
     ASSERT(!use_far_branches);
   }
@@ -615,6 +610,10 @@
                        const Address& dest,  // Where we are storing into.
                        Register value,       // Value we are storing.
                        CanBeSmi can_value_be_smi = kValueCanBeSmi);
+  void StoreIntoArray(Register object,  // Object we are storing into.
+                      Register slot,    // Where we are storing into.
+                      Register value,   // Value we are storing.
+                      CanBeSmi can_value_be_smi = kValueCanBeSmi);
 
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
@@ -715,30 +714,8 @@
   void Bind(Label* label);
   void Jump(Label* label) { jmp(label); }
 
-  // Address of code at offset.
-  uword CodeAddress(intptr_t offset) { return buffer_.Address(offset); }
-
-  intptr_t CodeSize() const { return buffer_.Size(); }
-  intptr_t prologue_offset() const { return prologue_offset_; }
   bool has_single_entry_point() const { return true; }
 
-  // Count the fixups that produce a pointer offset, without processing
-  // the fixups.
-  intptr_t CountPointerOffsets() const { return buffer_.CountPointerOffsets(); }
-  const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
-    return buffer_.pointer_offsets();
-  }
-
-  ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; }
-
-  RawObjectPool* MakeObjectPool() {
-    return object_pool_wrapper_.MakeObjectPool();
-  }
-
-  void FinalizeInstructions(const MemoryRegion& region) {
-    buffer_.FinalizeInstructions(region);
-  }
-
   // Set up a Dart frame on entry with a frame pointer and PC information to
   // enable easy access to the RawInstruction object of code corresponding
   // to this frame.
@@ -831,18 +808,10 @@
 
   // Debugging and bringup support.
   void Breakpoint() { int3(); }
-  void Stop(const char* message);
-  void Unimplemented(const char* message);
-  void Untested(const char* message);
-  void Unreachable(const char* message);
+  void Stop(const char* message) override;
 
   static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
 
-  void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
-  static bool EmittingComments();
-
-  const Code::Comments& GetCodeComments() const;
-
   static const char* RegisterName(Register reg);
   static const char* FpuRegisterName(FpuRegister reg);
 
@@ -873,21 +842,6 @@
   void PushCodeObject();
 
  private:
-  class CodeComment : public ZoneAllocated {
-   public:
-    CodeComment(intptr_t pc_offset, const String& comment)
-        : pc_offset_(pc_offset), comment_(comment) {}
-
-    intptr_t pc_offset() const { return pc_offset_; }
-    const String& comment() const { return comment_; }
-
-   private:
-    intptr_t pc_offset_;
-    const String& comment_;
-
-    DISALLOW_COPY_AND_ASSIGN(CodeComment);
-  };
-
   void Alu(int bytes, uint8_t opcode, Register dst, Register src);
   void Alu(uint8_t modrm_opcode, Register dst, const Immediate& imm);
   void Alu(int bytes, uint8_t opcode, Register dst, const Address& src);
@@ -931,11 +885,7 @@
 
   int32_t jit_cookie();
 
-  AssemblerBuffer buffer_;
-  ObjectPoolWrapper object_pool_wrapper_;
-  intptr_t prologue_offset_;
   int32_t jit_cookie_;
-  GrowableArray<CodeComment*> comments_;
   Code& code_;
 
   DISALLOW_ALLOCATION();
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index c91098b..26a220a 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -24,12 +24,7 @@
 
 Assembler::Assembler(ObjectPoolWrapper* object_pool_wrapper,
                      bool use_far_branches)
-    : buffer_(),
-      object_pool_wrapper_(object_pool_wrapper),
-      prologue_offset_(-1),
-      has_single_entry_point_(true),
-      comments_(),
-      constant_pool_allowed_(false) {
+    : AssemblerBase(object_pool_wrapper), constant_pool_allowed_(false) {
   // Far branching mode is only needed and implemented for ARM.
   ASSERT(!use_far_branches);
 }
@@ -1266,8 +1261,6 @@
                                 CanBeSmi can_be_smi) {
   // x.slot = x. Barrier should have be removed at the IL level.
   ASSERT(object != value);
-
-#if defined(CONCURRENT_MARKING)
   ASSERT(object != TMP);
   ASSERT(value != TMP);
 
@@ -1313,14 +1306,47 @@
     popq(kWriteBarrierValueReg);
   }
   Bind(&done);
-#else
-  movq(dest, value);
+}
+
+void Assembler::StoreIntoArray(Register object,
+                               Register slot,
+                               Register value,
+                               CanBeSmi can_be_smi) {
+  ASSERT(object != TMP);
+  ASSERT(value != TMP);
+  ASSERT(slot != TMP);
+
+  movq(Address(slot, 0), value);
+
+  // In parallel, test whether
+  //  - object is old and not remembered and value is new, or
+  //  - object is old and value is old and not marked and concurrent marking is
+  //    in progress
+  // If so, call the WriteBarrier stub, which will either add object to the
+  // store buffer (case 1) or add value to the marking stack (case 2).
+  // Compare RawObject::StorePointer.
   Label done;
-  StoreIntoObjectFilter(object, value, &done, can_be_smi, kJumpToNoUpdate);
-  // A store buffer update is required.
-  call(Address(THR, Thread::write_barrier_wrappers_offset(object)));
+  if (can_be_smi == kValueCanBeSmi) {
+    testq(value, Immediate(kSmiTagMask));
+    j(ZERO, &done, kNearJump);
+  }
+  movb(TMP, FieldAddress(object, Object::tags_offset()));
+  shrl(TMP, Immediate(RawObject::kBarrierOverlapShift));
+  andl(TMP, Address(THR, Thread::write_barrier_mask_offset()));
+  testb(FieldAddress(value, Object::tags_offset()), TMP);
+  j(ZERO, &done, kNearJump);
+
+  if ((object != kWriteBarrierObjectReg) || (value != kWriteBarrierValueReg) ||
+      (slot != kWriteBarrierSlotReg)) {
+    // Spill and shuffle unimplemented. Currently StoreIntoArray is only used
+    // from StoreIndexInstr, which gets these exact registers from the register
+    // allocator.
+    UNIMPLEMENTED();
+  }
+
+  call(Address(THR, Thread::array_write_barrier_entry_point_offset()));
+
   Bind(&done);
-#endif
 }
 
 void Assembler::StoreIntoObjectNoBarrier(Register object,
@@ -1369,19 +1395,12 @@
   addq(dest, inc_imm);
 }
 
-void Assembler::Stop(const char* message, bool fixed_length_encoding) {
+void Assembler::Stop(const char* message) {
   if (FLAG_print_stop_message) {
     int64_t message_address = reinterpret_cast<int64_t>(message);
     pushq(TMP);  // Preserve TMP register.
     pushq(RDI);  // Preserve RDI register.
-    if (fixed_length_encoding) {
-      AssemblerBuffer::EnsureCapacity ensured(&buffer_);
-      EmitRegisterREX(RDI, REX_W);
-      EmitUint8(0xB8 | (RDI & 7));
-      EmitInt64(message_address);
-    } else {
-      LoadImmediate(RDI, Immediate(message_address));
-    }
+    LoadImmediate(RDI, Immediate(message_address));
     call(&StubCode::PrintStopMessage_entry()->label());
     popq(RDI);  // Restore RDI register.
     popq(TMP);  // Restore TMP register.
@@ -1803,6 +1822,12 @@
   }
 }
 
+void Assembler::GenerateUnRelocatedPcRelativeCall() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  buffer_.Emit<uint8_t>(0xe8);
+  buffer_.Emit<int32_t>(0x68686868);
+}
+
 void Assembler::Align(int alignment, intptr_t offset) {
   ASSERT(Utils::IsPowerOfTwo(alignment));
   intptr_t pos = offset + buffer_.GetPosition();
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 6090c76..0d6e3cf 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -275,7 +275,7 @@
   }
 };
 
-class Assembler : public ValueObject {
+class Assembler : public AssemblerBase {
  public:
   explicit Assembler(ObjectPoolWrapper* object_pool_wrapper,
                      bool use_far_branches = false);
@@ -726,6 +726,10 @@
                        const Address& dest,  // Where we are storing into.
                        Register value,       // Value we are storing.
                        CanBeSmi can_be_smi = kValueCanBeSmi);
+  void StoreIntoArray(Register object,  // Object we are storing into.
+                      Register slot,    // Where we are storing into.
+                      Register value,   // Value we are storing.
+                      CanBeSmi can_be_smi = kValueCanBeSmi);
 
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
@@ -818,36 +822,6 @@
     cmpq(value, address);
   }
 
-  void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
-  static bool EmittingComments();
-
-  const Code::Comments& GetCodeComments() const;
-
-  // Address of code at offset.
-  uword CodeAddress(intptr_t offset) { return buffer_.Address(offset); }
-
-  intptr_t CodeSize() const { return buffer_.Size(); }
-  intptr_t prologue_offset() const { return prologue_offset_; }
-  bool has_single_entry_point() const { return has_single_entry_point_; }
-
-  // Count the fixups that produce a pointer offset, without processing
-  // the fixups.
-  intptr_t CountPointerOffsets() const { return buffer_.CountPointerOffsets(); }
-
-  const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
-    return buffer_.pointer_offsets();
-  }
-
-  ObjectPoolWrapper& object_pool_wrapper() { return *object_pool_wrapper_; }
-
-  RawObjectPool* MakeObjectPool() {
-    return object_pool_wrapper_->MakeObjectPool();
-  }
-
-  void FinalizeInstructions(const MemoryRegion& region) {
-    buffer_.FinalizeInstructions(region);
-  }
-
   void RestoreCodePointer();
   void LoadPoolPointer(Register pp = PP);
 
@@ -927,12 +901,22 @@
                         Register end_address,
                         Register temp);
 
+  // This emits an PC-relative call of the form "callq *[rip+<offset>]".  The
+  // offset is not yet known and needs therefore relocation to the right place
+  // before the code can be used.
+  //
+  // The neccessary information for the "linker" (i.e. the relocation
+  // information) is stored in [RawCode::static_calls_target_table_]: an entry
+  // of the form
+  //
+  //   (Code::kPcRelativeCall & pc_offset, <target-code>, <target-function>)
+  //
+  // will be used during relocation to fix the offset.
+  void GenerateUnRelocatedPcRelativeCall();
+
   // Debugging and bringup support.
   void Breakpoint() { int3(); }
-  void Stop(const char* message, bool fixed_length_encoding = false);
-  void Unimplemented(const char* message);
-  void Untested(const char* message);
-  void Unreachable(const char* message);
+  void Stop(const char* message) override;
 
   static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
 
@@ -961,29 +945,6 @@
   static bool IsSafeSmi(const Object& object) { return object.IsSmi(); }
 
  private:
-  AssemblerBuffer buffer_;
-
-  ObjectPoolWrapper* object_pool_wrapper_;
-
-  intptr_t prologue_offset_;
-  bool has_single_entry_point_;
-
-  class CodeComment : public ZoneAllocated {
-   public:
-    CodeComment(intptr_t pc_offset, const String& comment)
-        : pc_offset_(pc_offset), comment_(comment) {}
-
-    intptr_t pc_offset() const { return pc_offset_; }
-    const String& comment() const { return comment_; }
-
-   private:
-    intptr_t pc_offset_;
-    const String& comment_;
-
-    DISALLOW_COPY_AND_ASSIGN(CodeComment);
-  };
-
-  GrowableArray<CodeComment*> comments_;
   bool constant_pool_allowed_;
 
   intptr_t FindImmediate(int64_t imm);
diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc
index 01312ca..11138e6 100644
--- a/runtime/vm/compiler/assembler/disassembler.cc
+++ b/runtime/vm/compiler/assembler/disassembler.cc
@@ -16,13 +16,12 @@
 
 namespace dart {
 
-#ifndef PRODUCT
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 
 DECLARE_FLAG(bool, trace_inlining_intervals);
 DEFINE_FLAG(bool, trace_source_positions, false, "Source position diagnostics");
 
-void DisassembleToStdout::ConsumeInstruction(const Code& code,
-                                             char* hex_buffer,
+void DisassembleToStdout::ConsumeInstruction(char* hex_buffer,
                                              intptr_t hex_size,
                                              char* human_buffer,
                                              intptr_t human_size,
@@ -51,8 +50,7 @@
   va_end(args);
 }
 
-void DisassembleToJSONStream::ConsumeInstruction(const Code& code,
-                                                 char* hex_buffer,
+void DisassembleToJSONStream::ConsumeInstruction(char* hex_buffer,
                                                  intptr_t hex_size,
                                                  char* human_buffer,
                                                  intptr_t human_size,
@@ -97,9 +95,7 @@
   free(p);
 }
 
-#if !defined(PRODUCT)
-void DisassembleToMemory::ConsumeInstruction(const Code& code,
-                                             char* hex_buffer,
+void DisassembleToMemory::ConsumeInstruction(char* hex_buffer,
                                              intptr_t hex_size,
                                              char* human_buffer,
                                              intptr_t human_size,
@@ -154,8 +150,6 @@
   *buffer_ = '\0';
 }
 
-#endif
-
 void Disassembler::Disassemble(uword start,
                                uword end,
                                DisassemblyFormatter* formatter,
@@ -206,9 +200,8 @@
     DecodeInstruction(hex_buffer, sizeof(hex_buffer), human_buffer,
                       sizeof(human_buffer), &instruction_length, code, &object,
                       pc);
-    formatter->ConsumeInstruction(code, hex_buffer, sizeof(hex_buffer),
-                                  human_buffer, sizeof(human_buffer), object,
-                                  pc);
+    formatter->ConsumeInstruction(hex_buffer, sizeof(hex_buffer), human_buffer,
+                                  sizeof(human_buffer), object, pc);
     pc += instruction_length;
   }
 }
@@ -243,7 +236,9 @@
 
   const ObjectPool& object_pool =
       ObjectPool::Handle(zone, code.GetObjectPool());
-  object_pool.DebugPrint();
+  if (!object_pool.IsNull()) {
+    object_pool.DebugPrint();
+  }
 
   THR_Print("PC Descriptors for function '%s' {\n", function_fullname);
   PcDescriptors::PrintHeaderString();
@@ -332,32 +327,53 @@
 
   {
     THR_Print("Static call target functions {\n");
-    const Array& table = Array::Handle(zone, code.static_calls_target_table());
-    Smi& offset = Smi::Handle(zone);
-    Function& function = Function::Handle(zone);
-    Code& code = Code::Handle(zone);
-    for (intptr_t i = 0; i < table.Length();
-         i += Code::kSCallTableEntryLength) {
-      offset ^= table.At(i + Code::kSCallTableOffsetEntry);
-      function ^= table.At(i + Code::kSCallTableFunctionEntry);
-      code ^= table.At(i + Code::kSCallTableCodeEntry);
-      if (function.IsNull()) {
-        Class& cls = Class::Handle(zone);
-        cls ^= code.owner();
-        if (cls.IsNull()) {
-          THR_Print("  0x%" Px ": %s, %p\n", start + offset.Value(),
-                    code.QualifiedName(), code.raw());
-        } else {
-          THR_Print("  0x%" Px ": allocation stub for %s, %p\n",
-                    start + offset.Value(), cls.ToCString(), code.raw());
+    const auto& table = Array::Handle(zone, code.static_calls_target_table());
+    auto& cls = Class::Handle(zone);
+    auto& kind_and_offset = Smi::Handle(zone);
+    auto& function = Function::Handle(zone);
+    auto& code = Code::Handle(zone);
+    if (!table.IsNull()) {
+      StaticCallsTable static_calls(table);
+      for (auto& call : static_calls) {
+        kind_and_offset = call.Get<Code::kSCallTableKindAndOffset>();
+        function = call.Get<Code::kSCallTableFunctionTarget>();
+        code = call.Get<Code::kSCallTableCodeTarget>();
+
+        auto kind = Code::KindField::decode(kind_and_offset.Value());
+        auto offset = Code::OffsetField::decode(kind_and_offset.Value());
+
+        const char* skind = nullptr;
+        switch (kind) {
+          case Code::kPcRelativeCall:
+            skind = "pc-relative-call";
+            break;
+          case Code::kPcRelativeTailCall:
+            skind = "pc-relative-tail-call";
+            break;
+          case Code::kCallViaCode:
+            skind = "call-via-code";
+            break;
+          default:
+            UNREACHABLE();
         }
-      } else {
-        THR_Print("  0x%" Px ": %s, %p\n", start + offset.Value(),
-                  function.ToFullyQualifiedCString(), code.raw());
+        if (function.IsNull()) {
+          cls ^= code.owner();
+          if (cls.IsNull()) {
+            THR_Print("  0x%" Px ": %s, %p (%s)\n", start + offset,
+                      code.QualifiedName(), code.raw(), skind);
+          } else {
+            THR_Print("  0x%" Px ": allocation stub for %s, %p (%s)\n",
+                      start + offset, cls.ToCString(), code.raw(), skind);
+          }
+        } else {
+          THR_Print("  0x%" Px ": %s, %p (%s)\n", start + offset,
+                    function.ToFullyQualifiedCString(), code.raw(), skind);
+        }
       }
     }
-    THR_Print("}\n");
   }
+  THR_Print("}\n");
+
   if (optimized && FLAG_trace_inlining_intervals) {
     code.DumpInlineIntervals();
   }
@@ -373,6 +389,6 @@
   DisassembleCodeHelper(function_fullname, code, optimized);
 }
 
-#endif  // !PRODUCT
+#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/assembler/disassembler.h b/runtime/vm/compiler/assembler/disassembler.h
index b43f894..f23f08c 100644
--- a/runtime/vm/compiler/assembler/disassembler.h
+++ b/runtime/vm/compiler/assembler/disassembler.h
@@ -24,8 +24,7 @@
   virtual ~DisassemblyFormatter() {}
 
   // Consume the decoded instruction at the given pc.
-  virtual void ConsumeInstruction(const Code& code,
-                                  char* hex_buffer,
+  virtual void ConsumeInstruction(char* hex_buffer,
                                   intptr_t hex_size,
                                   char* human_buffer,
                                   intptr_t human_size,
@@ -43,8 +42,7 @@
   DisassembleToStdout() : DisassemblyFormatter() {}
   ~DisassembleToStdout() {}
 
-  virtual void ConsumeInstruction(const Code& code,
-                                  char* hex_buffer,
+  virtual void ConsumeInstruction(char* hex_buffer,
                                   intptr_t hex_size,
                                   char* human_buffer,
                                   intptr_t human_size,
@@ -65,8 +63,7 @@
       : DisassemblyFormatter(), jsarr_(jsarr) {}
   ~DisassembleToJSONStream() {}
 
-  virtual void ConsumeInstruction(const Code& code,
-                                  char* hex_buffer,
+  virtual void ConsumeInstruction(char* hex_buffer,
                                   intptr_t hex_size,
                                   char* human_buffer,
                                   intptr_t human_size,
@@ -81,7 +78,7 @@
   DISALLOW_COPY_AND_ASSIGN(DisassembleToJSONStream);
 };
 
-#if !defined(PRODUCT)
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 // Basic disassembly formatter that outputs the disassembled instruction
 // to a memory buffer. This is only intended for test writing.
 class DisassembleToMemory : public DisassemblyFormatter {
@@ -93,8 +90,7 @@
         overflowed_(false) {}
   ~DisassembleToMemory() {}
 
-  virtual void ConsumeInstruction(const Code& code,
-                                  char* hex_buffer,
+  virtual void ConsumeInstruction(char* hex_buffer,
                                   intptr_t hex_size,
                                   char* human_buffer,
                                   intptr_t human_size,
@@ -130,7 +126,7 @@
   }
 
   static void Disassemble(uword start, uword end, const Code& code) {
-#if !defined(PRODUCT)
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
     DisassembleToStdout stdout_formatter;
     LogBlock lb;
     Disassemble(start, end, &stdout_formatter, code);
@@ -140,7 +136,7 @@
   }
 
   static void Disassemble(uword start, uword end) {
-#if !defined(PRODUCT)
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
     DisassembleToStdout stdout_formatter;
     LogBlock lb;
     Disassemble(start, end, &stdout_formatter);
@@ -153,7 +149,7 @@
                           uword end,
                           char* buffer,
                           uintptr_t buffer_size) {
-#if !defined(PRODUCT)
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
     DisassembleToMemory memory_formatter(buffer, buffer_size);
     LogBlock lb;
     Disassemble(start, end, &memory_formatter);
diff --git a/runtime/vm/compiler/assembler/disassembler_arm.cc b/runtime/vm/compiler/assembler/disassembler_arm.cc
index 491a2b4..d3880c0 100644
--- a/runtime/vm/compiler/assembler/disassembler_arm.cc
+++ b/runtime/vm/compiler/assembler/disassembler_arm.cc
@@ -13,7 +13,7 @@
 
 namespace dart {
 
-#ifndef PRODUCT
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 
 class ARMDecoder : public ValueObject {
  public:
@@ -1512,7 +1512,7 @@
   }
 }
 
-#endif  // !PRODUCT
+#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/assembler/disassembler_arm64.cc b/runtime/vm/compiler/assembler/disassembler_arm64.cc
index 14fb8a6..2abe750 100644
--- a/runtime/vm/compiler/assembler/disassembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/disassembler_arm64.cc
@@ -12,7 +12,7 @@
 
 namespace dart {
 
-#ifndef PRODUCT
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 
 class ARM64Decoder : public ValueObject {
  public:
@@ -1574,7 +1574,7 @@
   }
 }
 
-#endif  // !PRODUCT
+#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/assembler/disassembler_kbc.cc b/runtime/vm/compiler/assembler/disassembler_kbc.cc
index 0899494..9102f84 100644
--- a/runtime/vm/compiler/assembler/disassembler_kbc.cc
+++ b/runtime/vm/compiler/assembler/disassembler_kbc.cc
@@ -128,21 +128,18 @@
   Apply(&buf, &size, pc, op2, bc, "");
 }
 
-// TODO(alexmarkov) This format is currently unused. Restore it if needed, or
-// remove it once bytecode instruction set is finalized.
-//
-// static void FormatA_X(char* buf,
-//                      intptr_t size,
-//                      uword pc,
-//                      uint32_t op,
-//                      Fmt op1,
-//                      Fmt op2,
-//                      Fmt op3) {
-//  const int32_t a = (op & 0xFF00) >> 8;
-//  const int32_t bc = static_cast<int32_t>(op) >> 16;
-//  Apply(&buf, &size, pc, op1, a, ", ");
-//  Apply(&buf, &size, pc, op2, bc, "");
-// }
+static void FormatA_X(char* buf,
+                      intptr_t size,
+                      uword pc,
+                      uint32_t op,
+                      Fmt op1,
+                      Fmt op2,
+                      Fmt op3) {
+  const int32_t a = (op & 0xFF00) >> 8;
+  const int32_t bc = static_cast<int32_t>(op) >> 16;
+  Apply(&buf, &size, pc, op1, a, ", ");
+  Apply(&buf, &size, pc, op2, bc, "");
+}
 
 static void FormatX(char* buf,
                     intptr_t size,
@@ -249,7 +246,7 @@
                                                    char* human_buffer,
                                                    intptr_t human_size,
                                                    int* out_instr_size,
-                                                   const Code& bytecode,
+                                                   const Bytecode& bytecode,
                                                    Object** object,
                                                    uword pc) {
   const uint32_t instr = *reinterpret_cast<uint32_t*>(pc);
@@ -280,57 +277,22 @@
 void KernelBytecodeDisassembler::Disassemble(uword start,
                                              uword end,
                                              DisassemblyFormatter* formatter,
-                                             const Code& bytecode) {
+                                             const Bytecode& bytecode) {
 #if !defined(PRODUCT)
-  const Code::Comments& comments =
-      bytecode.IsNull() ? Code::Comments::New(0) : bytecode.comments();
   ASSERT(formatter != NULL);
   char hex_buffer[kHexadecimalBufferSize];  // Instruction in hexadecimal form.
   char human_buffer[kUserReadableBufferSize];  // Human-readable instruction.
   uword pc = start;
-  intptr_t comment_finger = 0;
   GrowableArray<const Function*> inlined_functions;
   GrowableArray<TokenPosition> token_positions;
   while (pc < end) {
-    const intptr_t offset = pc - start;
-    const intptr_t old_comment_finger = comment_finger;
-    while (comment_finger < comments.Length() &&
-           comments.PCOffsetAt(comment_finger) <= offset) {
-      formatter->Print(
-          "        ;; %s\n",
-          String::Handle(comments.CommentAt(comment_finger)).ToCString());
-      comment_finger++;
-    }
-    if (old_comment_finger != comment_finger) {
-      char str[4000];
-      BufferFormatter f(str, sizeof(str));
-      // Comment emitted, emit inlining information.
-      bytecode.GetInlinedFunctionsAtInstruction(offset, &inlined_functions,
-                                                &token_positions);
-      // Skip top scope function printing (last entry in 'inlined_functions').
-      bool first = true;
-      for (intptr_t i = 1; i < inlined_functions.length(); i++) {
-        const char* name = inlined_functions[i]->ToQualifiedCString();
-        if (first) {
-          f.Print("        ;; Inlined [%s", name);
-          first = false;
-        } else {
-          f.Print(" -> %s", name);
-        }
-      }
-      if (!first) {
-        f.Print("]\n");
-        formatter->Print("%s", str);
-      }
-    }
     int instruction_length;
     Object* object;
     DecodeInstruction(hex_buffer, sizeof(hex_buffer), human_buffer,
                       sizeof(human_buffer), &instruction_length, bytecode,
                       &object, pc);
-    formatter->ConsumeInstruction(bytecode, hex_buffer, sizeof(hex_buffer),
-                                  human_buffer, sizeof(human_buffer), object,
-                                  pc);
+    formatter->ConsumeInstruction(hex_buffer, sizeof(hex_buffer), human_buffer,
+                                  sizeof(human_buffer), object, pc);
     pc += instruction_length;
   }
 #else
@@ -343,17 +305,16 @@
   ASSERT(function.HasBytecode());
   const char* function_fullname = function.ToFullyQualifiedCString();
   Zone* zone = Thread::Current()->zone();
-  const Code& bytecode = Code::Handle(zone, function.Bytecode());
+  const Bytecode& bytecode = Bytecode::Handle(zone, function.bytecode());
   THR_Print("Bytecode for function '%s' {\n", function_fullname);
-  const Instructions& instr = Instructions::Handle(bytecode.instructions());
-  uword start = instr.PayloadStart();
+  uword start = bytecode.PayloadStart();
   DisassembleToStdout stdout_formatter;
   LogBlock lb;
-  Disassemble(start, start + instr.Size(), &stdout_formatter, bytecode);
+  Disassemble(start, start + bytecode.Size(), &stdout_formatter, bytecode);
   THR_Print("}\n");
 
   const ObjectPool& object_pool =
-      ObjectPool::Handle(zone, bytecode.GetObjectPool());
+      ObjectPool::Handle(zone, bytecode.object_pool());
   object_pool.DebugPrint();
 
   THR_Print("PC Descriptors for function '%s' {\n", function_fullname);
diff --git a/runtime/vm/compiler/assembler/disassembler_kbc.h b/runtime/vm/compiler/assembler/disassembler_kbc.h
index 3512779..89bbc18 100644
--- a/runtime/vm/compiler/assembler/disassembler_kbc.h
+++ b/runtime/vm/compiler/assembler/disassembler_kbc.h
@@ -21,15 +21,15 @@
   static void Disassemble(uword start,
                           uword end,
                           DisassemblyFormatter* formatter,
-                          const Code& bytecode);
+                          const Bytecode& bytecode);
 
   static void Disassemble(uword start,
                           uword end,
                           DisassemblyFormatter* formatter) {
-    Disassemble(start, end, formatter, Code::Handle());
+    Disassemble(start, end, formatter, Bytecode::Handle());
   }
 
-  static void Disassemble(uword start, uword end, const Code& bytecode) {
+  static void Disassemble(uword start, uword end, const Bytecode& bytecode) {
 #if !defined(PRODUCT)
     DisassembleToStdout stdout_formatter;
     LogBlock lb;
@@ -71,7 +71,7 @@
                                 char* human_buffer,
                                 intptr_t human_size,
                                 int* out_instr_len,
-                                const Code& bytecode,
+                                const Bytecode& bytecode,
                                 Object** object,
                                 uword pc);
 
diff --git a/runtime/vm/compiler/assembler/disassembler_x86.cc b/runtime/vm/compiler/assembler/disassembler_x86.cc
index b6c2324..01e0c0c 100644
--- a/runtime/vm/compiler/assembler/disassembler_x86.cc
+++ b/runtime/vm/compiler/assembler/disassembler_x86.cc
@@ -19,7 +19,7 @@
 
 namespace dart {
 
-#ifndef PRODUCT
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 
 enum OperandType {
   UNSET_OP_ORDER = 0,
@@ -1991,7 +1991,7 @@
 #endif
 }
 
-#endif  // !PRODUCT
+#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/backend/compile_type.h b/runtime/vm/compiler/backend/compile_type.h
new file mode 100644
index 0000000..86f148a
--- /dev/null
+++ b/runtime/vm/compiler/backend/compile_type.h
@@ -0,0 +1,215 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_COMPILER_BACKEND_COMPILE_TYPE_H_
+#define RUNTIME_VM_COMPILER_BACKEND_COMPILE_TYPE_H_
+
+#include "vm/object.h"
+#include "vm/thread.h"
+
+namespace dart {
+
+class BufferFormatter;
+
+// CompileType describes type of a value produced by a definition.
+//
+// It captures the following properties:
+//    - whether the value can potentially be null or if it is definitely not
+//      null;
+//    - concrete class id of the value or kDynamicCid if unknown statically;
+//    - abstract super type of the value, concrete type of the value in runtime
+//      is guaranteed to be sub type of this type.
+//
+// Values of CompileType form a lattice with a None type as a bottom and a
+// nullable Dynamic type as a top element. Method Union provides a join
+// operation for the lattice.
+class CompileType : public ZoneAllocated {
+ public:
+  static const bool kNullable = true;
+  static const bool kNonNullable = false;
+
+  CompileType(bool is_nullable, intptr_t cid, const AbstractType* type)
+      : is_nullable_(is_nullable), cid_(cid), type_(type) {}
+
+  CompileType(const CompileType& other)
+      : ZoneAllocated(),
+        is_nullable_(other.is_nullable_),
+        cid_(other.cid_),
+        type_(other.type_) {}
+
+  CompileType& operator=(const CompileType& other) {
+    is_nullable_ = other.is_nullable_;
+    cid_ = other.cid_;
+    type_ = other.type_;
+    return *this;
+  }
+
+  bool is_nullable() const { return is_nullable_; }
+
+  // Return type such that concrete value's type in runtime is guaranteed to
+  // be subtype of it.
+  const AbstractType* ToAbstractType();
+
+  // Return class id such that it is either kDynamicCid or in runtime
+  // value is guaranteed to have an equal class id.
+  intptr_t ToCid();
+
+  // Return class id such that it is either kDynamicCid or in runtime
+  // value is guaranteed to be either null or have an equal class id.
+  intptr_t ToNullableCid();
+
+  // Return true if the value is guaranteed to be not-null or is known to be
+  // always null.
+  bool HasDecidableNullability();
+
+  // Return true if the value is known to be always null.
+  bool IsNull();
+
+  // Return true if this type is more specific than given type.
+  bool IsMoreSpecificThan(const AbstractType& other);
+
+  // Return true if value of this type is assignable to a location of the
+  // given type.
+  bool IsAssignableTo(const AbstractType& type) {
+    bool is_instance;
+    return CanComputeIsInstanceOf(type, kNullable, &is_instance) && is_instance;
+  }
+
+  // Create a new CompileType representing given combination of class id and
+  // abstract type. The pair is assumed to be coherent.
+  static CompileType Create(intptr_t cid, const AbstractType& type);
+
+  CompileType CopyNonNullable() const {
+    return CompileType(kNonNullable, kIllegalCid, type_);
+  }
+
+  static CompileType CreateNullable(bool is_nullable, intptr_t cid) {
+    return CompileType(is_nullable, cid, NULL);
+  }
+
+  // Create a new CompileType representing given abstract type. By default
+  // values as assumed to be nullable.
+  static CompileType FromAbstractType(const AbstractType& type,
+                                      bool is_nullable = kNullable);
+
+  // Create a new CompileType representing a value with the given class id.
+  // Resulting CompileType is nullable only if cid is kDynamicCid or kNullCid.
+  static CompileType FromCid(intptr_t cid);
+
+  // Create None CompileType. It is the bottom of the lattice and is used to
+  // represent type of the phi that was not yet inferred.
+  static CompileType None() {
+    return CompileType(kNullable, kIllegalCid, NULL);
+  }
+
+  // Create Dynamic CompileType. It is the top of the lattice and is used to
+  // represent unknown type.
+  static CompileType Dynamic();
+
+  static CompileType Null();
+
+  // Create non-nullable Bool type.
+  static CompileType Bool();
+
+  // Create non-nullable Int type.
+  static CompileType Int();
+
+  // Create nullable Int type.
+  static CompileType NullableInt();
+
+  // Create non-nullable Smi type.
+  static CompileType Smi();
+
+  // Create nullable Smi type.
+  static CompileType NullableSmi() {
+    return CreateNullable(kNullable, kSmiCid);
+  }
+
+  // Create nullable Mint type.
+  static CompileType NullableMint() {
+    return CreateNullable(kNullable, kMintCid);
+  }
+
+  // Create non-nullable Double type.
+  static CompileType Double();
+
+  // Create nullable Double type.
+  static CompileType NullableDouble();
+
+  // Create non-nullable String type.
+  static CompileType String();
+
+  // Perform a join operation over the type lattice.
+  void Union(CompileType* other);
+
+  // Refine old type with newly inferred type (it could be more or less
+  // specific, or even unrelated to an old type in case of unreachable code).
+  // May return 'old_type', 'new_type' or create a new CompileType instance.
+  static CompileType* ComputeRefinedType(CompileType* old_type,
+                                         CompileType* new_type);
+
+  // Return true if this and other types are the same.
+  bool IsEqualTo(CompileType* other) {
+    return (is_nullable_ == other->is_nullable_) &&
+           (ToNullableCid() == other->ToNullableCid()) &&
+           (ToAbstractType()->Equals(*other->ToAbstractType()));
+  }
+
+  bool IsNone() const { return (cid_ == kIllegalCid) && (type_ == NULL); }
+
+  // Return true if value of this type is a non-nullable int.
+  bool IsInt() { return !is_nullable() && IsNullableInt(); }
+
+  // Return true if value of this type is a non-nullable double.
+  bool IsDouble() { return !is_nullable() && IsNullableDouble(); }
+
+  // Return true if value of this type is either int or null.
+  bool IsNullableInt() {
+    if ((cid_ == kSmiCid) || (cid_ == kMintCid)) {
+      return true;
+    }
+    if ((cid_ == kIllegalCid) || (cid_ == kDynamicCid)) {
+      return (type_ != NULL) && ((type_->IsIntType() || type_->IsSmiType()));
+    }
+    return false;
+  }
+
+  // Returns true if value of this type is either Smi or null.
+  bool IsNullableSmi() {
+    if (cid_ == kSmiCid) {
+      return true;
+    }
+    if ((cid_ == kIllegalCid) || (cid_ == kDynamicCid)) {
+      return type_ != nullptr && type_->IsSmiType();
+    }
+    return false;
+  }
+
+  // Return true if value of this type is either double or null.
+  bool IsNullableDouble() {
+    if (cid_ == kDoubleCid) {
+      return true;
+    }
+    if ((cid_ == kIllegalCid) || (cid_ == kDynamicCid)) {
+      return (type_ != NULL) && type_->IsDoubleType();
+    }
+    return false;
+  }
+
+  void PrintTo(BufferFormatter* f) const;
+  const char* ToCString() const;
+
+ private:
+  bool CanComputeIsInstanceOf(const AbstractType& type,
+                              bool is_nullable,
+                              bool* is_instance);
+
+  bool is_nullable_;
+  intptr_t cid_;
+  const AbstractType* type_;
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_COMPILER_BACKEND_COMPILE_TYPE_H_
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 8811240..9342167 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -796,8 +796,7 @@
 
 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) {
   Value* instance = instr->instance();
-  if ((instr->native_field() != nullptr) &&
-      (instr->native_field()->kind() == NativeFieldDesc::kArray_length) &&
+  if ((instr->slot().kind() == Slot::Kind::kArray_length) &&
       instance->definition()->OriginalDefinition()->IsCreateArray()) {
     Value* num_elements = instance->definition()
                               ->OriginalDefinition()
@@ -885,12 +884,16 @@
         return;
       }
     }
-    if (instr->type_arguments().IsUninstantiatedIdentity() ||
-        instr->type_arguments().CanShareInstantiatorTypeArguments(
+    if (instr->type_arguments().CanShareInstantiatorTypeArguments(
             instr->instantiator_class())) {
       SetValue(instr, instantiator_type_args);
       return;
     }
+    if (instr->type_arguments().CanShareFunctionTypeArguments(
+            instr->function())) {
+      SetValue(instr, function_type_args);
+      return;
+    }
     SetValue(instr, non_constant_);
   }
   // TODO(regis): If both instantiator type arguments and function type
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index cd8350c..1be6986 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -450,7 +450,7 @@
     // a null check rather than the more elaborate class check
     CompileType* type = receiver->Type();
     const AbstractType* atype = type->ToAbstractType();
-    if (atype->IsInstantiated() && atype->HasResolvedTypeClass() &&
+    if (atype->IsInstantiated() && atype->HasTypeClass() &&
         !atype->IsDynamicType()) {
       if (type->is_nullable()) {
         receiver_maybe_null = true;
@@ -549,10 +549,9 @@
   const Class& cls = Class::Handle(
       zone(), Isolate::Current()->class_table()->At(receiver_cid));
 
-  Definition* load_type_args = new (zone())
-      LoadFieldInstr(call->Receiver()->CopyWithType(),
-                     NativeFieldDesc::GetTypeArgumentsFieldFor(zone(), cls),
-                     call->token_pos());
+  Definition* load_type_args = new (zone()) LoadFieldInstr(
+      call->Receiver()->CopyWithType(),
+      Slot::GetTypeArgumentsSlotFor(thread(), cls), call->token_pos());
   InsertBefore(call, load_type_args, call->env(), FlowGraph::kValue);
 
   const AbstractType& type =
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 6d25b3e..01b1cc8 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -2,9 +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 "vm/globals.h"  // Needed here to get TARGET_ARCH_XXX.
-
 #include "vm/compiler/backend/flow_graph_compiler.h"
+#include "vm/globals.h"  // Needed here to get TARGET_ARCH_XXX.
 
 #include "platform/utils.h"
 #include "vm/bit_vector.h"
@@ -700,16 +699,29 @@
                                           null_check_name_idx);
 }
 
+void FlowGraphCompiler::AddPcRelativeCallTarget(const Function& function) {
+  ASSERT(function.IsZoneHandle());
+  static_calls_target_table_.Add(new (zone()) StaticCallsStruct(
+      Code::kPcRelativeCall, assembler()->CodeSize(), &function, NULL));
+}
+
+void FlowGraphCompiler::AddPcRelativeCallStubTarget(const Code& stub_code) {
+  ASSERT(stub_code.IsZoneHandle());
+  ASSERT(!stub_code.IsNull());
+  static_calls_target_table_.Add(new (zone()) StaticCallsStruct(
+      Code::kPcRelativeCall, assembler()->CodeSize(), NULL, &stub_code));
+}
+
 void FlowGraphCompiler::AddStaticCallTarget(const Function& func) {
   ASSERT(func.IsZoneHandle());
-  static_calls_target_table_.Add(
-      new (zone()) StaticCallsStruct(assembler()->CodeSize(), &func, NULL));
+  static_calls_target_table_.Add(new (zone()) StaticCallsStruct(
+      Code::kCallViaCode, assembler()->CodeSize(), &func, NULL));
 }
 
 void FlowGraphCompiler::AddStubCallTarget(const Code& code) {
   ASSERT(code.IsZoneHandle());
-  static_calls_target_table_.Add(
-      new (zone()) StaticCallsStruct(assembler()->CodeSize(), NULL, &code));
+  static_calls_target_table_.Add(new (zone()) StaticCallsStruct(
+      Code::kCallViaCode, assembler()->CodeSize(), NULL, &code));
 }
 
 CompilerDeoptInfo* FlowGraphCompiler::AddDeoptIndexAtCall(intptr_t deopt_id) {
@@ -1063,22 +1075,26 @@
 
 void FlowGraphCompiler::FinalizeStaticCallTargetsTable(const Code& code) {
   ASSERT(code.static_calls_target_table() == Array::null());
-  const Array& targets =
-      Array::Handle(zone(), Array::New((static_calls_target_table_.length() *
-                                        Code::kSCallTableEntryLength),
-                                       Heap::kOld));
-  Smi& smi_offset = Smi::Handle(zone());
-  for (intptr_t i = 0; i < static_calls_target_table_.length(); i++) {
-    const intptr_t target_ix = Code::kSCallTableEntryLength * i;
-    smi_offset = Smi::New(static_calls_target_table_[i]->offset);
-    targets.SetAt(target_ix + Code::kSCallTableOffsetEntry, smi_offset);
-    if (static_calls_target_table_[i]->function != NULL) {
-      targets.SetAt(target_ix + Code::kSCallTableFunctionEntry,
-                    *static_calls_target_table_[i]->function);
+  const auto& calls = static_calls_target_table_;
+  const intptr_t array_length = calls.length() * Code::kSCallTableEntryLength;
+  const auto& targets =
+      Array::Handle(zone(), Array::New(array_length, Heap::kOld));
+
+  StaticCallsTable entries(targets);
+  auto& kind_and_offset = Smi::Handle(zone());
+  for (intptr_t i = 0; i < calls.length(); i++) {
+    auto entry = calls[i];
+    kind_and_offset = Smi::New(Code::KindField::encode(entry->call_kind) |
+                               Code::OffsetField::encode(entry->offset));
+    auto view = entries[i];
+    view.Set<Code::kSCallTableKindAndOffset>(kind_and_offset);
+    const Object* target = nullptr;
+    if (entry->function != nullptr) {
+      view.Set<Code::kSCallTableFunctionTarget>(*calls[i]->function);
     }
-    if (static_calls_target_table_[i]->code != NULL) {
-      targets.SetAt(target_ix + Code::kSCallTableCodeEntry,
-                    *static_calls_target_table_[i]->code);
+    if (entry->code != NULL) {
+      ASSERT(target == nullptr);
+      view.Set<Code::kSCallTableCodeTarget>(*calls[i]->code);
     }
   }
   code.set_static_calls_target_table(targets);
@@ -1948,9 +1964,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.
     const Function& function = *targets.TargetAt(smi_case)->target;
-    GenerateStaticDartCall(
-        deopt_id, token_index, *StubCode::CallStaticFunction_entry(),
-        RawPcDescriptors::kOther, locs, function, entry_kind);
+    GenerateStaticDartCall(deopt_id, token_index, RawPcDescriptors::kOther,
+                           locs, function, entry_kind);
     __ Drop(args_info.count_with_type_args);
     if (match_found != NULL) {
       __ Jump(match_found);
@@ -1999,9 +2014,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.
     const Function& function = *targets.TargetAt(i)->target;
-    GenerateStaticDartCall(
-        deopt_id, token_index, *StubCode::CallStaticFunction_entry(),
-        RawPcDescriptors::kOther, locs, function, entry_kind);
+    GenerateStaticDartCall(deopt_id, token_index, RawPcDescriptors::kOther,
+                           locs, function, entry_kind);
     __ Drop(args_info.count_with_type_args);
     if (!is_last_check || add_megamorphic_call) {
       __ Jump(match_found);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 4c84b7b..e7deb03 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -469,7 +469,6 @@
   void GenerateStaticDartCall(
       intptr_t deopt_id,
       TokenPosition token_pos,
-      const StubEntry& stub_entry,
       RawPcDescriptors::Kind kind,
       LocationSummary* locs,
       const Function& target,
@@ -772,6 +771,8 @@
 
   void EmitFrameEntry();
 
+  void AddPcRelativeCallTarget(const Function& function);
+  void AddPcRelativeCallStubTarget(const Code& stub_code);
   void AddStaticCallTarget(const Function& function);
 
   void GenerateDeferredCode();
@@ -923,13 +924,18 @@
   // This struct contains either function or code, the other one being NULL.
   class StaticCallsStruct : public ZoneAllocated {
    public:
+    Code::CallKind call_kind;
     const intptr_t offset;
     const Function* function;  // Can be NULL.
     const Code* code;          // Can be NULL.
-    StaticCallsStruct(intptr_t offset_arg,
+    StaticCallsStruct(Code::CallKind call_kind,
+                      intptr_t offset_arg,
                       const Function* function_arg,
                       const Code* code_arg)
-        : offset(offset_arg), function(function_arg), code(code_arg) {
+        : call_kind(call_kind),
+          offset(offset_arg),
+          function(function_arg),
+          code(code_arg) {
       ASSERT((function == NULL) || function->IsZoneHandle());
       ASSERT((code == NULL) || code->IsZoneHandle());
     }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 729d9ff..3b082be 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -286,7 +286,7 @@
         AbstractType::ZoneHandle(zone(), type_arguments.TypeAt(0));
     ASSERT(!tp_argument.IsMalformed());
     if (tp_argument.IsType()) {
-      ASSERT(tp_argument.HasResolvedTypeClass());
+      ASSERT(tp_argument.HasTypeClass());
       // Check if type argument is dynamic, Object, or void.
       const Type& object_type = Type::Handle(zone(), Type::ObjectType());
       if (object_type.IsSubtypeOf(tp_argument, NULL, NULL, Heap::kOld)) {
@@ -988,7 +988,6 @@
 
 void FlowGraphCompiler::GenerateStaticDartCall(intptr_t deopt_id,
                                                TokenPosition token_pos,
-                                               const StubEntry& stub_entry,
                                                RawPcDescriptors::Kind kind,
                                                LocationSummary* locs,
                                                const Function& target,
@@ -997,6 +996,7 @@
   // call sites are never patched for breakpoints: the function is deoptimized
   // and the unoptimized code with IC calls for static calls is patched instead.
   ASSERT(is_optimizing());
+  const auto& stub_entry = *StubCode::CallStaticFunction_entry();
   __ BranchLinkWithEquivalence(stub_entry, target, entry_kind);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
   AddStaticCallTarget(target);
@@ -1163,7 +1163,6 @@
   // 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,
-                         *StubCode::CallStaticFunction_entry(),
                          RawPcDescriptors::kOther, locs, function, entry_kind);
   __ Drop(count_with_type_args);
 }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 4812ac4..c62d083 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -278,7 +278,6 @@
         AbstractType::ZoneHandle(zone(), type_arguments.TypeAt(0));
     ASSERT(!tp_argument.IsMalformed());
     if (tp_argument.IsType()) {
-      ASSERT(tp_argument.HasResolvedTypeClass());
       // Check if type argument is dynamic, Object, or void.
       const Type& object_type = Type::Handle(zone(), Type::ObjectType());
       if (object_type.IsSubtypeOf(tp_argument, NULL, NULL, Heap::kOld)) {
@@ -966,7 +965,6 @@
 
 void FlowGraphCompiler::GenerateStaticDartCall(intptr_t deopt_id,
                                                TokenPosition token_pos,
-                                               const StubEntry& stub_entry,
                                                RawPcDescriptors::Kind kind,
                                                LocationSummary* locs,
                                                const Function& target,
@@ -976,6 +974,7 @@
   // call sites are never patched for breakpoints: the function is deoptimized
   // and the unoptimized code with IC calls for static calls is patched instead.
   ASSERT(is_optimizing());
+  const auto& stub_entry = *StubCode::CallStaticFunction_entry();
   __ BranchLinkWithEquivalence(stub_entry, target);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
   AddStaticCallTarget(target);
@@ -1146,7 +1145,6 @@
   // 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,
-                         *StubCode::CallStaticFunction_entry(),
                          RawPcDescriptors::kOther, locs, function);
   __ Drop(count_with_type_args);
 }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index f6dc95a..859e772 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -294,7 +294,6 @@
         AbstractType::ZoneHandle(zone(), type_arguments.TypeAt(0));
     ASSERT(!tp_argument.IsMalformed());
     if (tp_argument.IsType()) {
-      ASSERT(tp_argument.HasResolvedTypeClass());
       // Check if type argument is dynamic, Object, or void.
       const Type& object_type = Type::Handle(zone(), Type::ObjectType());
       if (object_type.IsSubtypeOf(tp_argument, NULL, NULL, Heap::kOld)) {
@@ -877,12 +876,12 @@
 
 void FlowGraphCompiler::GenerateStaticDartCall(intptr_t deopt_id,
                                                TokenPosition token_pos,
-                                               const StubEntry& stub_entry,
                                                RawPcDescriptors::Kind kind,
                                                LocationSummary* locs,
                                                const Function& target,
                                                Code::EntryKind entry_kind) {
   // TODO(sjindel/entrypoints): Support multiple entrypoints on IA32.
+  const auto& stub_entry = *StubCode::CallStaticFunction_entry();
   __ Call(stub_entry, true /* movable_target */);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
   AddStaticCallTarget(target);
@@ -1018,7 +1017,6 @@
   // 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,
-                         *StubCode::CallStaticFunction_entry(),
                          RawPcDescriptors::kOther, locs, function);
   __ Drop(count_with_type_args);
 }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 2471b4e..fa8c99b 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -287,7 +287,7 @@
         AbstractType::ZoneHandle(zone(), type_arguments.TypeAt(0));
     ASSERT(!tp_argument.IsMalformed());
     if (tp_argument.IsType()) {
-      ASSERT(tp_argument.HasResolvedTypeClass());
+      ASSERT(tp_argument.HasTypeClass());
       // Check if type argument is dynamic, Object, or void.
       const Type& object_type = Type::Handle(zone(), Type::ObjectType());
       if (object_type.IsSubtypeOf(tp_argument, NULL, NULL, Heap::kOld)) {
@@ -979,7 +979,6 @@
 
 void FlowGraphCompiler::GenerateStaticDartCall(intptr_t deopt_id,
                                                TokenPosition token_pos,
-                                               const StubEntry& stub_entry,
                                                RawPcDescriptors::Kind kind,
                                                LocationSummary* locs,
                                                const Function& target,
@@ -988,6 +987,7 @@
   // call sites are never patched for breakpoints: the function is deoptimized
   // and the unoptimized code with IC calls for static calls is patched instead.
   ASSERT(is_optimizing());
+  const auto& stub_entry = *StubCode::CallStaticFunction_entry();
   __ CallWithEquivalence(stub_entry, target, entry_kind);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
   AddStaticCallTarget(target);
@@ -1140,7 +1140,6 @@
   // 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,
-                         *StubCode::CallStaticFunction_entry(),
                          RawPcDescriptors::kOther, locs, function, entry_kind);
   __ Drop(count_with_type_args, RCX);
 }
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 9688cae..d7f3af6 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -735,103 +735,19 @@
   return mask;
 }
 
-const NativeFieldDesc* NativeFieldDesc::Get(Kind kind) {
-  static const NativeFieldDesc fields[] = {
-#define IMMUTABLE true
-#define MUTABLE false
-#define DEFINE_NATIVE_FIELD(ClassName, FieldName, cid, mutability)             \
-  NativeFieldDesc(k##ClassName##_##FieldName, ClassName::FieldName##_offset(), \
-                  k##cid##Cid, mutability),
-
-      NATIVE_FIELDS_LIST(DEFINE_NATIVE_FIELD)
-
-#undef DEFINE_FIELD
-#undef MUTABLE
-#undef IMMUTABLE
-  };
-
-  return &fields[kind];
-}
-
-const NativeFieldDesc* NativeFieldDesc::GetLengthFieldForArrayCid(
-    intptr_t array_cid) {
-  if (RawObject::IsExternalTypedDataClassId(array_cid) ||
-      RawObject::IsTypedDataClassId(array_cid)) {
-    return Get(kTypedData_length);
-  }
-
-  switch (array_cid) {
-    case kGrowableObjectArrayCid:
-      return Get(kGrowableObjectArray_length);
-
-    case kOneByteStringCid:
-    case kTwoByteStringCid:
-    case kExternalOneByteStringCid:
-    case kExternalTwoByteStringCid:
-      return Get(kString_length);
-
-    case kArrayCid:
-    case kImmutableArrayCid:
-      return Get(kArray_length);
-
-    default:
-      UNREACHABLE();
-      return nullptr;
-  }
-}
-
-const NativeFieldDesc* NativeFieldDesc::GetTypeArgumentsField(Zone* zone,
-                                                              intptr_t offset) {
-  // TODO(vegorov) consider caching type arguments fields for specific classes
-  // in some sort of a flow-graph specific cache.
-  ASSERT(offset != Class::kNoTypeArguments);
-  return new (zone) NativeFieldDesc(kTypeArguments, offset, kDynamicCid,
-                                    /*immutable=*/true);
-}
-
-const NativeFieldDesc* NativeFieldDesc::GetTypeArgumentsFieldFor(
-    Zone* zone,
-    const Class& cls) {
-  return GetTypeArgumentsField(zone, cls.type_arguments_field_offset());
-}
-
-RawAbstractType* NativeFieldDesc::type() const {
-  if (cid() == kSmiCid) {
-    return Type::SmiType();
-  }
-
-  return Type::DynamicType();
-}
-
-const char* NativeFieldDesc::name() const {
-  switch (kind()) {
-#define HANDLE_CASE(ClassName, FieldName, cid, mutability)                     \
-  case k##ClassName##_##FieldName:                                             \
-    return #ClassName "." #FieldName;
-
-    NATIVE_FIELDS_LIST(HANDLE_CASE)
-
-#undef HANDLE_CASE
-    case kTypeArguments:
-      return ":type_arguments";
-  }
-  UNREACHABLE();
-  return nullptr;
-}
-
 bool LoadFieldInstr::IsUnboxedLoad() const {
-  return FLAG_unbox_numeric_fields && (field() != NULL) &&
-         FlowGraphCompiler::IsUnboxedField(*field());
+  return FLAG_unbox_numeric_fields && slot().IsDartField() &&
+         FlowGraphCompiler::IsUnboxedField(slot().field());
 }
 
 bool LoadFieldInstr::IsPotentialUnboxedLoad() const {
-  return FLAG_unbox_numeric_fields && (field() != NULL) &&
-         FlowGraphCompiler::IsPotentialUnboxedField(*field());
+  return FLAG_unbox_numeric_fields && slot().IsDartField() &&
+         FlowGraphCompiler::IsPotentialUnboxedField(slot().field());
 }
 
 Representation LoadFieldInstr::representation() const {
   if (IsUnboxedLoad()) {
-    const intptr_t cid = field()->UnboxedFieldCid();
+    const intptr_t cid = slot().field().UnboxedFieldCid();
     switch (cid) {
       case kDoubleCid:
         return kUnboxedDouble;
@@ -847,20 +763,20 @@
 }
 
 bool StoreInstanceFieldInstr::IsUnboxedStore() const {
-  return FLAG_unbox_numeric_fields && !field().IsNull() &&
-         FlowGraphCompiler::IsUnboxedField(field());
+  return FLAG_unbox_numeric_fields && slot().IsDartField() &&
+         FlowGraphCompiler::IsUnboxedField(slot().field());
 }
 
 bool StoreInstanceFieldInstr::IsPotentialUnboxedStore() const {
-  return FLAG_unbox_numeric_fields && !field().IsNull() &&
-         FlowGraphCompiler::IsPotentialUnboxedField(field());
+  return FLAG_unbox_numeric_fields && slot().IsDartField() &&
+         FlowGraphCompiler::IsPotentialUnboxedField(slot().field());
 }
 
 Representation StoreInstanceFieldInstr::RequiredInputRepresentation(
     intptr_t index) const {
   ASSERT((index == 0) || (index == 1));
   if ((index == 1) && IsUnboxedStore()) {
-    const intptr_t cid = field().UnboxedFieldCid();
+    const intptr_t cid = slot().field().UnboxedFieldCid();
     switch (cid) {
       case kDoubleCid:
         return kUnboxedDouble;
@@ -963,12 +879,7 @@
 bool LoadFieldInstr::AttributesEqual(Instruction* other) const {
   LoadFieldInstr* other_load = other->AsLoadField();
   ASSERT(other_load != NULL);
-  if (field() != NULL) {
-    return (other_load->field() != NULL) &&
-           (field()->raw() == other_load->field()->raw());
-  }
-  return (other_load->field() == NULL) &&
-         (offset_in_bytes() == other_load->offset_in_bytes());
+  return &this->slot_ == &other_load->slot_;
 }
 
 Instruction* InitStaticFieldInstr::Canonicalize(FlowGraph* flow_graph) {
@@ -1600,6 +1511,10 @@
   return loop_info_ != nullptr && loop_info_->header() == this;
 }
 
+intptr_t BlockEntryInstr::NestingDepth() const {
+  return loop_info_ == nullptr ? 0 : loop_info_->NestingDepth();
+}
+
 // Helper to mutate the graph during inlining. This block should be
 // replaced with new_block as a predecessor of all of this block's
 // successors.  For each successor, the predecessors will be reordered
@@ -2569,26 +2484,37 @@
 }
 
 bool LoadFieldInstr::IsImmutableLengthLoad() const {
-  if (native_field() != nullptr) {
-    switch (native_field()->kind()) {
-      case NativeFieldDesc::kArray_length:
-      case NativeFieldDesc::kTypedData_length:
-      case NativeFieldDesc::kString_length:
-        return true;
-      case NativeFieldDesc::kGrowableObjectArray_length:
-        return false;
+  switch (slot().kind()) {
+    case Slot::Kind::kArray_length:
+    case Slot::Kind::kTypedData_length:
+    case Slot::Kind::kString_length:
+      return true;
+    case Slot::Kind::kGrowableObjectArray_length:
+      return false;
 
-      // Not length loads.
-      case NativeFieldDesc::kLinkedHashMap_index:
-      case NativeFieldDesc::kLinkedHashMap_data:
-      case NativeFieldDesc::kLinkedHashMap_hash_mask:
-      case NativeFieldDesc::kLinkedHashMap_used_data:
-      case NativeFieldDesc::kLinkedHashMap_deleted_keys:
-      case NativeFieldDesc::kArgumentsDescriptor_type_args_len:
-      case NativeFieldDesc::kTypeArguments:
-        return false;
-    }
+    // Not length loads.
+    case Slot::Kind::kLinkedHashMap_index:
+    case Slot::Kind::kLinkedHashMap_data:
+    case Slot::Kind::kLinkedHashMap_hash_mask:
+    case Slot::Kind::kLinkedHashMap_used_data:
+    case Slot::Kind::kLinkedHashMap_deleted_keys:
+    case Slot::Kind::kArgumentsDescriptor_type_args_len:
+    case Slot::Kind::kArgumentsDescriptor_positional_count:
+    case Slot::Kind::kArgumentsDescriptor_count:
+    case Slot::Kind::kTypeArguments:
+    case Slot::Kind::kGrowableObjectArray_data:
+    case Slot::Kind::kContext_parent:
+    case Slot::Kind::kClosure_context:
+    case Slot::Kind::kClosure_delayed_type_arguments:
+    case Slot::Kind::kClosure_function:
+    case Slot::Kind::kClosure_function_type_arguments:
+    case Slot::Kind::kClosure_instantiator_type_arguments:
+    case Slot::Kind::kClosure_hash:
+    case Slot::Kind::kCapturedVariable:
+    case Slot::Kind::kDartField:
+      return false;
   }
+  UNREACHABLE();
   return false;
 }
 
@@ -2618,42 +2544,54 @@
   return this;
 }
 
-bool LoadFieldInstr::Evaluate(const Object& instance, Object* result) {
-  if (native_field() != nullptr) {
-    switch (native_field()->kind()) {
-      case NativeFieldDesc::kArgumentsDescriptor_type_args_len:
-        if (instance.IsArray() && Array::Cast(instance).IsImmutable()) {
-          ArgumentsDescriptor desc(Array::Cast(instance));
-          *result = Smi::New(desc.TypeArgsLen());
-          return true;
-        }
-        return false;
+bool LoadFieldInstr::TryEvaluateLoad(const Object& instance,
+                                     const Slot& field,
+                                     Object* result) {
+  switch (field.kind()) {
+    case Slot::Kind::kDartField:
+      return TryEvaluateLoad(instance, field.field(), result);
 
-      default:
-        break;
-    }
+    case Slot::Kind::kArgumentsDescriptor_type_args_len:
+      if (instance.IsArray() && Array::Cast(instance).IsImmutable()) {
+        ArgumentsDescriptor desc(Array::Cast(instance));
+        *result = Smi::New(desc.TypeArgsLen());
+        return true;
+      }
+      return false;
+
+    default:
+      break;
   }
+  return false;
+}
 
-  if (field() == nullptr || !field()->is_final() || !instance.IsInstance()) {
+bool LoadFieldInstr::TryEvaluateLoad(const Object& instance,
+                                     const Field& field,
+                                     Object* result) {
+  if (!field.is_final() || !instance.IsInstance()) {
     return false;
   }
 
   // Check that instance really has the field which we
   // are trying to load from.
   Class& cls = Class::Handle(instance.clazz());
-  while (cls.raw() != Class::null() && cls.raw() != field()->Owner()) {
+  while (cls.raw() != Class::null() && cls.raw() != field.Owner()) {
     cls = cls.SuperClass();
   }
-  if (cls.raw() != field()->Owner()) {
+  if (cls.raw() != field.Owner()) {
     // Failed to find the field in class or its superclasses.
     return false;
   }
 
   // Object has the field: execute the load.
-  *result = Instance::Cast(instance).GetField(*field());
+  *result = Instance::Cast(instance).GetField(field);
   return true;
 }
 
+bool LoadFieldInstr::Evaluate(const Object& instance, Object* result) {
+  return TryEvaluateLoad(instance, slot(), result);
+}
+
 Definition* LoadFieldInstr::Canonicalize(FlowGraph* flow_graph) {
   if (!HasUses()) return nullptr;
 
@@ -2668,21 +2606,21 @@
         return call->ArgumentAt(1);
       }
     } else if (CreateArrayInstr* create_array = array->AsCreateArray()) {
-      if (native_field() == NativeFieldDesc::Array_length()) {
+      if (slot().kind() == Slot::Kind::kArray_length) {
         return create_array->num_elements()->definition();
       }
     } else if (LoadFieldInstr* load_array = array->AsLoadField()) {
       // For arrays with guarded lengths, replace the length load
       // with a constant.
-      if (const Field* field = load_array->field()) {
-        if (field->guarded_list_length() >= 0) {
+      const Slot& slot = load_array->slot();
+      if (slot.IsDartField()) {
+        if (slot.field().guarded_list_length() >= 0) {
           return flow_graph->GetConstant(
-              Smi::Handle(Smi::New(field->guarded_list_length())));
+              Smi::Handle(Smi::New(slot.field().guarded_list_length())));
         }
       }
     }
-  } else if (native_field() != nullptr &&
-             native_field()->kind() == NativeFieldDesc::kTypeArguments) {
+  } else if (slot().IsTypeArguments()) {
     Definition* array = instance()->definition()->OriginalDefinition();
     if (StaticCallInstr* call = array->AsStaticCall()) {
       if (call->is_known_list_constructor()) {
@@ -2694,18 +2632,24 @@
     } else if (CreateArrayInstr* create_array = array->AsCreateArray()) {
       return create_array->element_type()->definition();
     } else if (LoadFieldInstr* load_array = array->AsLoadField()) {
-      const Field* field = load_array->field();
-      // For trivially exact fields we know that type arguments match
-      // static type arguments exactly.
-      if ((field != nullptr) &&
-          field->static_type_exactness_state().IsTriviallyExact()) {
-        return flow_graph->GetConstant(TypeArguments::Handle(
-            AbstractType::Handle(field->type()).arguments()));
-      } else if (const NativeFieldDesc* native_field =
-                     load_array->native_field()) {
-        if (native_field == NativeFieldDesc::LinkedHashMap_data()) {
-          return flow_graph->constant_null();
+      const Slot& slot = load_array->slot();
+      switch (slot.kind()) {
+        case Slot::Kind::kDartField: {
+          // For trivially exact fields we know that type arguments match
+          // static type arguments exactly.
+          const Field& field = slot.field();
+          if (field.static_type_exactness_state().IsTriviallyExact()) {
+            return flow_graph->GetConstant(TypeArguments::Handle(
+                AbstractType::Handle(field.type()).arguments()));
+          }
+          break;
         }
+
+        case Slot::Kind::kLinkedHashMap_data:
+          return flow_graph->constant_null();
+
+        default:
+          break;
       }
     }
   }
@@ -2786,19 +2730,18 @@
   if (instantiator_type_args == nullptr) {
     if (LoadFieldInstr* load_type_args =
             instantiator_type_arguments()->definition()->AsLoadField()) {
-      if (load_type_args->native_field() != nullptr &&
-          load_type_args->native_field()->kind() ==
-              NativeFieldDesc::kTypeArguments) {
+      if (load_type_args->slot().IsTypeArguments()) {
         if (LoadFieldInstr* load_field = load_type_args->instance()
                                              ->definition()
                                              ->OriginalDefinition()
                                              ->AsLoadField()) {
-          if (load_field->field() != nullptr &&
-              load_field->field()
-                  ->static_type_exactness_state()
+          if (load_field->slot().IsDartField() &&
+              load_field->slot()
+                  .field()
+                  .static_type_exactness_state()
                   .IsHasExactSuperClass()) {
             instantiator_type_args = &TypeArguments::Handle(
-                Z, AbstractType::Handle(Z, load_field->field()->type())
+                Z, AbstractType::Handle(Z, load_field->slot().field().type())
                        .arguments());
           }
         }
@@ -2820,17 +2763,19 @@
       new_dst_type = TypeRef::Cast(new_dst_type).type();
     }
     new_dst_type = new_dst_type.Canonicalize();
+
+    // Successfully instantiated destination type: update the type attached
+    // to this instruction and set type arguments to null because we no
+    // longer need them (the type was instantiated).
     set_dst_type(new_dst_type);
+    instantiator_type_arguments()->BindTo(flow_graph->constant_null());
+    function_type_arguments()->BindTo(flow_graph->constant_null());
 
     if (new_dst_type.IsDynamicType() || new_dst_type.IsObjectType() ||
         (FLAG_eliminate_type_checks &&
          value()->Type()->IsAssignableTo(new_dst_type))) {
       return value()->definition();
     }
-
-    ConstantInstr* null_constant = flow_graph->constant_null();
-    instantiator_type_arguments()->BindTo(null_constant);
-    function_type_arguments()->BindTo(null_constant);
   }
   return this;
 }
@@ -4056,7 +4001,7 @@
     // static receiver type on the ICData.
     if (checked_argument_count() == 1) {
       if (static_receiver_type_ != nullptr &&
-          static_receiver_type_->HasResolvedTypeClass()) {
+          static_receiver_type_->HasTypeClass()) {
         const Class& cls =
             Class::Handle(zone, static_receiver_type_->type_class());
         if (cls.IsGeneric() && !cls.IsFutureOrClass()) {
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 33d1434..05bab1d 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -7,7 +7,9 @@
 
 #include "vm/allocation.h"
 #include "vm/code_descriptors.h"
+#include "vm/compiler/backend/compile_type.h"
 #include "vm/compiler/backend/locations.h"
+#include "vm/compiler/backend/slot.h"
 #include "vm/compiler/compiler_state.h"
 #include "vm/compiler/method_recognizer.h"
 #include "vm/flags.h"
@@ -42,178 +44,6 @@
 class UnboxIntegerInstr;
 class TypeUsageInfo;
 
-// CompileType describes type of the value produced by the definition.
-//
-// It captures the following properties:
-//    - whether value can potentially be null or it is definitely not null;
-//    - concrete class id of the value or kDynamicCid if unknown statically;
-//    - abstract super type of the value, concrete type of the value in runtime
-//      is guaranteed to be sub type of this type.
-//
-// Values of CompileType form a lattice with a None type as a bottom and a
-// nullable Dynamic type as a top element. Method Union provides a join
-// operation for the lattice.
-class CompileType : public ZoneAllocated {
- public:
-  static const bool kNullable = true;
-  static const bool kNonNullable = false;
-
-  CompileType(bool is_nullable, intptr_t cid, const AbstractType* type)
-      : is_nullable_(is_nullable), cid_(cid), type_(type) {}
-
-  CompileType(const CompileType& other)
-      : ZoneAllocated(),
-        is_nullable_(other.is_nullable_),
-        cid_(other.cid_),
-        type_(other.type_) {}
-
-  CompileType& operator=(const CompileType& other) {
-    is_nullable_ = other.is_nullable_;
-    cid_ = other.cid_;
-    type_ = other.type_;
-    return *this;
-  }
-
-  bool is_nullable() const { return is_nullable_; }
-
-  // Return type such that concrete value's type in runtime is guaranteed to
-  // be subtype of it.
-  const AbstractType* ToAbstractType();
-
-  // Return class id such that it is either kDynamicCid or in runtime
-  // value is guaranteed to have an equal class id.
-  intptr_t ToCid();
-
-  // Return class id such that it is either kDynamicCid or in runtime
-  // value is guaranteed to be either null or have an equal class id.
-  intptr_t ToNullableCid();
-
-  // Returns true if the value is guaranteed to be not-null or is known to be
-  // always null.
-  bool HasDecidableNullability();
-
-  // Returns true if the value is known to be always null.
-  bool IsNull();
-
-  // Returns true if this type is more specific than given type.
-  bool IsMoreSpecificThan(const AbstractType& other);
-
-  // Returns true if value of this type is assignable to a location of the
-  // given type.
-  bool IsAssignableTo(const AbstractType& type) {
-    bool is_instance;
-    return CanComputeIsInstanceOf(type, kNullable, &is_instance) && is_instance;
-  }
-
-  // Create a new CompileType representing given combination of class id and
-  // abstract type. The pair is assumed to be coherent.
-  static CompileType Create(intptr_t cid, const AbstractType& type);
-
-  CompileType CopyNonNullable() const {
-    return CompileType(kNonNullable, kIllegalCid, type_);
-  }
-
-  static CompileType CreateNullable(bool is_nullable, intptr_t cid) {
-    return CompileType(is_nullable, cid, NULL);
-  }
-
-  // Create a new CompileType representing given abstract type. By default
-  // values as assumed to be nullable.
-  static CompileType FromAbstractType(const AbstractType& type,
-                                      bool is_nullable = kNullable);
-
-  // Create a new CompileType representing a value with the given class id.
-  // Resulting CompileType is nullable only if cid is kDynamicCid or kNullCid.
-  static CompileType FromCid(intptr_t cid);
-
-  // Create None CompileType. It is the bottom of the lattice and is used to
-  // represent type of the phi that was not yet inferred.
-  static CompileType None() {
-    return CompileType(kNullable, kIllegalCid, NULL);
-  }
-
-  // Create Dynamic CompileType. It is the top of the lattice and is used to
-  // represent unknown type.
-  static CompileType Dynamic();
-
-  static CompileType Null();
-
-  // Create non-nullable Bool type.
-  static CompileType Bool();
-
-  // Create non-nullable Int type.
-  static CompileType Int();
-
-  // Create non-nullable Smi type.
-  static CompileType Smi();
-
-  // Create non-nullable Double type.
-  static CompileType Double();
-
-  // Create non-nullable String type.
-  static CompileType String();
-
-  // Perform a join operation over the type lattice.
-  void Union(CompileType* other);
-
-  // Refine old type with newly inferred type (it could be more or less
-  // specific, or even unrelated to an old type in case of unreachable code).
-  // May return 'old_type', 'new_type' or create a new CompileType instance.
-  static CompileType* ComputeRefinedType(CompileType* old_type,
-                                         CompileType* new_type);
-
-  // Returns true if this and other types are the same.
-  bool IsEqualTo(CompileType* other) {
-    return (is_nullable_ == other->is_nullable_) &&
-           (ToNullableCid() == other->ToNullableCid()) &&
-           (ToAbstractType()->Equals(*other->ToAbstractType()));
-  }
-
-  bool IsNone() const { return (cid_ == kIllegalCid) && (type_ == NULL); }
-
-  bool IsInt() {
-    return !is_nullable() &&
-           ((ToCid() == kSmiCid) || (ToCid() == kMintCid) ||
-            ((type_ != NULL) &&
-             (type_->Equals(Type::Handle(Type::Int64Type())))));
-  }
-
-  // Returns true if value of this type is either int or null.
-  bool IsNullableInt() {
-    if ((cid_ == kSmiCid) || (cid_ == kMintCid)) {
-      return true;
-    }
-    if ((cid_ == kIllegalCid) || (cid_ == kDynamicCid)) {
-      return (type_ != NULL) && ((type_->IsIntType() || type_->IsInt64Type() ||
-                                  type_->IsSmiType()));
-    }
-    return false;
-  }
-
-  // Returns true if value of this type is either double or null.
-  bool IsNullableDouble() {
-    if (cid_ == kDoubleCid) {
-      return true;
-    }
-    if ((cid_ == kIllegalCid) || (cid_ == kDynamicCid)) {
-      return (type_ != NULL) && type_->IsDoubleType();
-    }
-    return false;
-  }
-
-  void PrintTo(BufferFormatter* f) const;
-  const char* ToCString() const;
-
- private:
-  bool CanComputeIsInstanceOf(const AbstractType& type,
-                              bool is_nullable,
-                              bool* is_instance);
-
-  bool is_nullable_;
-  intptr_t cid_;
-  const AbstractType* type_;
-};
-
 class Value : public ZoneAllocated {
  public:
   // A forward iterator that allows removing the current value from the
@@ -660,18 +490,18 @@
   DECLARE_INSTRUCTION_NO_BACKEND(type)                                         \
   DECLARE_COMPARISON_METHODS
 
-#ifndef PRODUCT
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 #define PRINT_TO_SUPPORT virtual void PrintTo(BufferFormatter* f) const;
 #else
 #define PRINT_TO_SUPPORT
-#endif  // !PRODUCT
+#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 
-#ifndef PRODUCT
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 #define PRINT_OPERANDS_TO_SUPPORT                                              \
   virtual void PrintOperandsTo(BufferFormatter* f) const;
 #else
 #define PRINT_OPERANDS_TO_SUPPORT
-#endif  // !PRODUCT
+#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 
 // Together with CidRange, this represents a mapping from a range of class-ids
 // to a method for a given selector (method name).  Also can contain an
@@ -894,7 +724,7 @@
 
   // Printing support.
   const char* ToCString() const;
-#ifndef PRODUCT
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
   virtual void PrintTo(BufferFormatter* f) const;
   virtual void PrintOperandsTo(BufferFormatter* f) const;
 #endif
@@ -1360,6 +1190,7 @@
   LoopInfo* loop_info() const { return loop_info_; }
   void set_loop_info(LoopInfo* loop_info) { loop_info_ = loop_info; }
   bool IsLoopHeader() const;
+  intptr_t NestingDepth() const;
 
   virtual BlockEntryInstr* GetBlock() { return this; }
 
@@ -2293,7 +2124,7 @@
   DISALLOW_COPY_AND_ASSIGN(ParameterInstr);
 };
 
-// Stores a tagged pointer to a slot accessable from a fixed register.  It has
+// Stores a tagged pointer to a slot accessible from a fixed register.  It has
 // the form:
 //
 //     base_reg[index + #constant] = value
@@ -2304,7 +2135,7 @@
 //
 // Currently this instruction uses pinpoints the register to be FP.
 //
-// This lowlevel instruction is non-inlinable since it makes assumptons about
+// This low-level instruction is non-inlinable since it makes assumptions about
 // the frame.  This is asserted via `inliner.cc::CalleeGraphValidator`.
 class StoreIndexedUnsafeInstr : public TemplateDefinition<2, NoThrow> {
  public:
@@ -3270,6 +3101,18 @@
     ASSERT(argument_names.IsZoneHandle() || argument_names.InVMHeap());
   }
 
+  RawString* Selector() {
+    // The Token::Kind we have does unfortunately not encode whether the call is
+    // a dyn: call or not.
+    if (auto static_call = this->AsStaticCall()) {
+      return static_call->ic_data()->target_name();
+    } else if (auto instance_call = this->AsInstanceCall()) {
+      return instance_call->ic_data()->target_name();
+    } else {
+      UNREACHABLE();
+    }
+  }
+
   intptr_t FirstArgIndex() const { return type_args_len_ > 0 ? 1 : 0; }
   Value* Receiver() const {
     return this->PushArgumentAt(FirstArgIndex())->value();
@@ -4259,51 +4102,76 @@
 
 enum StoreBarrierType { kNoStoreBarrier, kEmitStoreBarrier };
 
+// StoreInstanceField instruction represents a store of the given [value] into
+// the specified [slot] on the [instance] object. [emit_store_barrier] allows to
+// specify whether the store should omit the write barrier. [kind] specifies
+// whether this store is an initializing store, i.e. the first store into a
+// field after the allocation.
+//
+// In JIT mode a slot might be a subject to the field unboxing optimization:
+// if field type profiling shows that this slot always contains a double or SIMD
+// value then this field becomes "unboxed" - in this case when storing into
+// such field we update the payload of the box referenced by the field, rather
+// than updating the field itself.
+//
+// Note: even if [emit_store_barrier] is set to [kEmitStoreBarrier] the store
+// can still omit the barrier if it establishes that it is not needed.
+//
+// Note: stores generated from the constructor initializer list and from
+// field initializers *must* be marked as initializing. Initializing stores
+// into unboxed fields are responsible for allocating the mutable box which
+// would be mutated by subsequent stores.
 class StoreInstanceFieldInstr : public TemplateDefinition<2, NoThrow> {
  public:
+  enum class Kind {
+    // Store is known to be the first store into a slot of an object after
+    // object was allocated and before it escapes (e.g. stores in constructor
+    // initializer list).
+    kInitializing,
+
+    // All other stores.
+    kOther,
+  };
+
+  StoreInstanceFieldInstr(const Slot& slot,
+                          Value* instance,
+                          Value* value,
+                          StoreBarrierType emit_store_barrier,
+                          TokenPosition token_pos,
+                          Kind kind = Kind::kOther)
+      : slot_(slot),
+        emit_store_barrier_(emit_store_barrier),
+        token_pos_(token_pos),
+        is_initialization_(kind == Kind::kInitializing) {
+    SetInputAt(kInstancePos, instance);
+    SetInputAt(kValuePos, value);
+  }
+
+  // Convenience constructor that looks up an IL Slot for the given [field].
   StoreInstanceFieldInstr(const Field& field,
                           Value* instance,
                           Value* value,
                           StoreBarrierType emit_store_barrier,
-                          TokenPosition token_pos)
-      : field_(field),
-        offset_in_bytes_(field.Offset()),
-        emit_store_barrier_(emit_store_barrier),
-        token_pos_(token_pos),
-        is_initialization_(false) {
-    SetInputAt(kInstancePos, instance);
-    SetInputAt(kValuePos, value);
-    CheckField(field);
-  }
-
-  StoreInstanceFieldInstr(intptr_t offset_in_bytes,
-                          Value* instance,
-                          Value* value,
-                          StoreBarrierType emit_store_barrier,
-                          TokenPosition token_pos)
-      : field_(Field::ZoneHandle()),
-        offset_in_bytes_(offset_in_bytes),
-        emit_store_barrier_(emit_store_barrier),
-        token_pos_(token_pos),
-        is_initialization_(false) {
-    SetInputAt(kInstancePos, instance);
-    SetInputAt(kValuePos, value);
-  }
+                          TokenPosition token_pos,
+                          const ParsedFunction* parsed_function,
+                          Kind kind = Kind::kOther)
+      : StoreInstanceFieldInstr(Slot::Get(field, parsed_function),
+                                instance,
+                                value,
+                                emit_store_barrier,
+                                token_pos,
+                                kind) {}
 
   DECLARE_INSTRUCTION(StoreInstanceField)
 
-  void set_is_initialization(bool value) { is_initialization_ = value; }
-
   enum { kInstancePos = 0, kValuePos = 1 };
 
   Value* instance() const { return inputs_[kInstancePos]; }
+  const Slot& slot() const { return slot_; }
   Value* value() const { return inputs_[kValuePos]; }
-  bool is_initialization() const { return is_initialization_; }
 
   virtual TokenPosition token_pos() const { return token_pos_; }
-
-  const Field& field() const { return field_; }
-  intptr_t offset_in_bytes() const { return offset_in_bytes_; }
+  bool is_initialization() const { return is_initialization_; }
 
   bool ShouldEmitStoreBarrier() const {
     if (instance()->definition() == value()->definition()) {
@@ -4335,7 +4203,6 @@
   virtual bool HasUnknownSideEffects() const { return false; }
 
   bool IsUnboxedStore() const;
-
   bool IsPotentialUnboxedStore() const;
 
   virtual Representation RequiredInputRepresentation(intptr_t index) const;
@@ -4345,6 +4212,8 @@
  private:
   friend class JitCallSpecializer;  // For ASSERT(initialization_).
 
+  intptr_t OffsetInBytes() const { return slot().offset_in_bytes(); }
+
   Assembler::CanBeSmi CanValueBeSmi() const {
     Isolate* isolate = Isolate::Current();
     if (isolate->type_checks() && !FLAG_strong) {
@@ -4360,12 +4229,11 @@
                               : Assembler::kValueIsNotSmi;
   }
 
-  const Field& field_;
-  intptr_t offset_in_bytes_;
+  const Slot& slot_;
   StoreBarrierType emit_store_barrier_;
   const TokenPosition token_pos_;
   // Marks initializing stores. E.g. in the constructor.
-  bool is_initialization_;
+  const bool is_initialization_;
 
   DISALLOW_COPY_AND_ASSIGN(StoreInstanceFieldInstr);
 };
@@ -4955,6 +4823,9 @@
   DISALLOW_COPY_AND_ASSIGN(AllocateObjectInstr);
 };
 
+// TODO(vegorov) the name of the instruction is confusing. At some point
+// it used to allocate uninitialized storage, but this is no longer true.
+// These days it allocates null initialized storage.
 class AllocateUninitializedContextInstr
     : public TemplateAllocation<0, NoThrow> {
  public:
@@ -4998,7 +4869,7 @@
 class MaterializeObjectInstr : public Definition {
  public:
   MaterializeObjectInstr(AllocateObjectInstr* allocation,
-                         const ZoneGrowableArray<const Object*>& slots,
+                         const ZoneGrowableArray<const Slot*>& slots,
                          ZoneGrowableArray<Value*>* values)
       : allocation_(allocation),
         cls_(allocation->cls()),
@@ -5016,7 +4887,7 @@
   }
 
   MaterializeObjectInstr(AllocateUninitializedContextInstr* allocation,
-                         const ZoneGrowableArray<const Object*>& slots,
+                         const ZoneGrowableArray<const Slot*>& slots,
                          ZoneGrowableArray<Value*>* values)
       : allocation_(allocation),
         cls_(Class::ZoneHandle(Object::context_class())),
@@ -5039,8 +4910,7 @@
   intptr_t num_variables() const { return num_variables_; }
 
   intptr_t FieldOffsetAt(intptr_t i) const {
-    return slots_[i]->IsField() ? Field::Cast(*slots_[i]).Offset()
-                                : Smi::Cast(*slots_[i]).Value();
+    return slots_[i]->offset_in_bytes();
   }
 
   const Location& LocationAt(intptr_t i) { return locations_[i]; }
@@ -5084,7 +4954,7 @@
   Definition* allocation_;
   const Class& cls_;
   intptr_t num_variables_;
-  const ZoneGrowableArray<const Object*>& slots_;
+  const ZoneGrowableArray<const Slot*>& slots_;
   ZoneGrowableArray<Value*>* values_;
   Location* locations_;
 
@@ -5125,7 +4995,15 @@
   virtual AliasIdentity Identity() const { return identity_; }
   virtual void SetIdentity(AliasIdentity identity) { identity_ = identity; }
 
-  virtual bool WillAllocateNewOrRemembered() const { return true; }
+  virtual bool WillAllocateNewOrRemembered() const {
+    // Large arrays will use cards instead; cannot skip write barrier.
+    if (!num_elements()->BindsToConstant()) return false;
+    const Object& length = num_elements()->BoundConstant();
+    if (!length.IsSmi()) return false;
+    intptr_t raw_length = Smi::Cast(length).Value();
+    // Compare Array::New.
+    return (raw_length >= 0) && (raw_length < Array::kMaxNewSpaceElements);
+  }
 
  private:
   const TokenPosition token_pos_;
@@ -5187,160 +5065,29 @@
   DISALLOW_COPY_AND_ASSIGN(LoadClassIdInstr);
 };
 
-#define NATIVE_FIELDS_LIST(V)                                                  \
-  V(Array, length, Smi, IMMUTABLE)                                             \
-  V(GrowableObjectArray, length, Smi, MUTABLE)                                 \
-  V(TypedData, length, Smi, IMMUTABLE)                                         \
-  V(String, length, Smi, IMMUTABLE)                                            \
-  V(LinkedHashMap, index, TypedDataUint32Array, MUTABLE)                       \
-  V(LinkedHashMap, data, Array, MUTABLE)                                       \
-  V(LinkedHashMap, hash_mask, Smi, MUTABLE)                                    \
-  V(LinkedHashMap, used_data, Smi, MUTABLE)                                    \
-  V(LinkedHashMap, deleted_keys, Smi, MUTABLE)                                 \
-  V(ArgumentsDescriptor, type_args_len, Smi, IMMUTABLE)
-
-class NativeFieldDesc : public ZoneAllocated {
- public:
-  // clang-format off
-  enum Kind {
-#define DECLARE_KIND(ClassName, FieldName, cid, mutability)                    \
-  k##ClassName##_##FieldName,
-    NATIVE_FIELDS_LIST(DECLARE_KIND)
-#undef DECLARE_KIND
-    kTypeArguments,
-  };
-  // clang-format on
-
-#define DEFINE_GETTER(ClassName, FieldName, cid, mutability)                   \
-  static const NativeFieldDesc* ClassName##_##FieldName() {                    \
-    return Get(k##ClassName##_##FieldName);                                    \
-  }
-
-  NATIVE_FIELDS_LIST(DEFINE_GETTER)
-#undef DEFINE_GETTER
-
-  static const NativeFieldDesc* Get(Kind kind);
-  static const NativeFieldDesc* GetLengthFieldForArrayCid(intptr_t array_cid);
-  static const NativeFieldDesc* GetTypeArgumentsField(Zone* zone,
-                                                      intptr_t offset);
-  static const NativeFieldDesc* GetTypeArgumentsFieldFor(Zone* zone,
-                                                         const Class& cls);
-
-  const char* name() const;
-
-  Kind kind() const { return kind_; }
-
-  intptr_t offset_in_bytes() const { return offset_in_bytes_; }
-
-  bool is_immutable() const { return immutable_; }
-
-  intptr_t cid() const { return cid_; }
-
-  RawAbstractType* type() const;
-
- private:
-  NativeFieldDesc(Kind kind,
-                  intptr_t offset_in_bytes,
-                  intptr_t cid,
-                  bool immutable)
-      : kind_(kind),
-        offset_in_bytes_(offset_in_bytes),
-        immutable_(immutable),
-        cid_(cid) {}
-
-  NativeFieldDesc(const NativeFieldDesc& other)
-      : NativeFieldDesc(other.kind_,
-                        other.offset_in_bytes_,
-                        other.immutable_,
-                        other.cid_) {}
-
-  const Kind kind_;
-  const intptr_t offset_in_bytes_;
-  const bool immutable_;
-
-  const intptr_t cid_;
-};
-
+// LoadFieldInstr represents a load from the given [slot] in the given
+// [instance].
+//
+// Note: if slot was a subject of the field unboxing optimization then this load
+// would both load the box stored in the field and then load the content of
+// the box.
 class LoadFieldInstr : public TemplateDefinition<1, NoThrow> {
  public:
-  LoadFieldInstr(Value* instance,
-                 intptr_t offset_in_bytes,
-                 const AbstractType& type,
-                 TokenPosition token_pos)
-      : offset_in_bytes_(offset_in_bytes),
-        type_(type),
-        result_cid_(kDynamicCid),
-        immutable_(false),
-        native_field_(nullptr),
-        field_(nullptr),
-        token_pos_(token_pos) {
-    ASSERT(offset_in_bytes >= 0);
-    // May be null if field is not an instance.
-    ASSERT(type_.IsZoneHandle() || type_.IsReadOnlyHandle());
+  LoadFieldInstr(Value* instance, const Slot& slot, TokenPosition token_pos)
+      : slot_(slot), token_pos_(token_pos) {
     SetInputAt(0, instance);
   }
 
-  LoadFieldInstr(Value* instance,
-                 const NativeFieldDesc* native_field,
-                 TokenPosition token_pos)
-      : offset_in_bytes_(native_field->offset_in_bytes()),
-        type_(AbstractType::ZoneHandle(native_field->type())),
-        result_cid_(native_field->cid()),
-        immutable_(native_field->is_immutable()),
-        native_field_(native_field),
-        field_(nullptr),
-        token_pos_(token_pos) {
-    ASSERT(offset_in_bytes_ >= 0);
-    // May be null if field is not an instance.
-    ASSERT(type_.IsZoneHandle() || type_.IsReadOnlyHandle());
-    SetInputAt(0, instance);
-  }
-
-  LoadFieldInstr(Value* instance,
-                 const Field* field,
-                 const AbstractType& type,
-                 TokenPosition token_pos,
-                 const ParsedFunction* parsed_function)
-      : offset_in_bytes_(field->Offset()),
-        type_(type),
-        result_cid_(kDynamicCid),
-        immutable_(false),
-        native_field_(nullptr),
-        field_(field),
-        token_pos_(token_pos) {
-    ASSERT(Class::Handle(field->Owner()).is_finalized());
-    ASSERT(field->IsZoneHandle());
-    // May be null if field is not an instance.
-    ASSERT(type.IsZoneHandle() || type.IsReadOnlyHandle());
-    SetInputAt(0, instance);
-
-    if (parsed_function != nullptr && field->guarded_cid() != kIllegalCid) {
-      if (!field->is_nullable() || (field->guarded_cid() == kNullCid)) {
-        set_result_cid(field->guarded_cid());
-      }
-      parsed_function->AddToGuardedFields(field);
-    }
-  }
-
-  void set_is_immutable(bool value) { immutable_ = value; }
-
   Value* instance() const { return inputs_[0]; }
-  intptr_t offset_in_bytes() const { return offset_in_bytes_; }
-  const AbstractType& type() const { return type_; }
-  void set_result_cid(intptr_t value) { result_cid_ = value; }
-  intptr_t result_cid() const { return result_cid_; }
-  virtual TokenPosition token_pos() const { return token_pos_; }
+  const Slot& slot() const { return slot_; }
 
-  const Field* field() const { return field_; }
+  virtual TokenPosition token_pos() const { return token_pos_; }
 
   virtual Representation representation() const;
 
   bool IsUnboxedLoad() const;
-
   bool IsPotentialUnboxedLoad() const;
 
-  const NativeFieldDesc* native_field() const { return native_field_; }
-
   DECLARE_INSTRUCTION(LoadField)
   virtual CompileType ComputeType() const;
 
@@ -5357,11 +5104,19 @@
   // instance has the field.
   bool Evaluate(const Object& instance_value, Object* result);
 
+  static bool TryEvaluateLoad(const Object& instance,
+                              const Field& field,
+                              Object* result);
+
+  static bool TryEvaluateLoad(const Object& instance,
+                              const Slot& field,
+                              Object* result);
+
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
 
   static bool IsFixedLengthArrayCid(intptr_t cid);
 
-  virtual bool AllowsCSE() const { return immutable_; }
+  virtual bool AllowsCSE() const { return slot_.is_immutable(); }
   virtual bool HasUnknownSideEffects() const { return false; }
 
   virtual bool AttributesEqual(Instruction* other) const;
@@ -5369,13 +5124,9 @@
   PRINT_OPERANDS_TO_SUPPORT
 
  private:
-  const intptr_t offset_in_bytes_;
-  const AbstractType& type_;
-  intptr_t result_cid_;
-  bool immutable_;
+  intptr_t OffsetInBytes() const { return slot().offset_in_bytes(); }
 
-  const NativeFieldDesc* native_field_;
-  const Field* field_;
+  const Slot& slot_;
   const TokenPosition token_pos_;
 
   DISALLOW_COPY_AND_ASSIGN(LoadFieldInstr);
@@ -5419,14 +5170,18 @@
   InstantiateTypeArgumentsInstr(TokenPosition token_pos,
                                 const TypeArguments& type_arguments,
                                 const Class& instantiator_class,
+                                const Function& function,
                                 Value* instantiator_type_arguments,
                                 Value* function_type_arguments,
                                 intptr_t deopt_id)
       : TemplateDefinition(deopt_id),
         token_pos_(token_pos),
         type_arguments_(type_arguments),
-        instantiator_class_(instantiator_class) {
+        instantiator_class_(instantiator_class),
+        function_(function) {
     ASSERT(type_arguments.IsZoneHandle());
+    ASSERT(instantiator_class.IsZoneHandle());
+    ASSERT(function.IsZoneHandle());
     SetInputAt(0, instantiator_type_arguments);
     SetInputAt(1, function_type_arguments);
   }
@@ -5437,6 +5192,7 @@
   Value* function_type_arguments() const { return inputs_[1]; }
   const TypeArguments& type_arguments() const { return type_arguments_; }
   const Class& instantiator_class() const { return instantiator_class_; }
+  const Function& function() const { return function_; }
   virtual TokenPosition token_pos() const { return token_pos_; }
 
   virtual bool ComputeCanDeoptimize() const { return true; }
@@ -5451,20 +5207,30 @@
   const TokenPosition token_pos_;
   const TypeArguments& type_arguments_;
   const Class& instantiator_class_;
+  const Function& function_;
 
   DISALLOW_COPY_AND_ASSIGN(InstantiateTypeArgumentsInstr);
 };
 
+// [AllocateContext] instruction allocates a new Context object with the space
+// for the given [context_variables].
 class AllocateContextInstr : public TemplateAllocation<0, NoThrow> {
  public:
-  AllocateContextInstr(TokenPosition token_pos, intptr_t num_context_variables)
-      : token_pos_(token_pos), num_context_variables_(num_context_variables) {}
+  AllocateContextInstr(TokenPosition token_pos,
+                       const GrowableArray<LocalVariable*>& context_variables)
+      : token_pos_(token_pos), context_variables_(context_variables) {}
 
   DECLARE_INSTRUCTION(AllocateContext)
   virtual CompileType ComputeType() const;
 
   virtual TokenPosition token_pos() const { return token_pos_; }
-  intptr_t num_context_variables() const { return num_context_variables_; }
+  const GrowableArray<LocalVariable*>& context_variables() const {
+    return context_variables_;
+  }
+
+  intptr_t num_context_variables() const {
+    return context_variables().length();
+  }
 
   virtual bool ComputeCanDeoptimize() const { return false; }
 
@@ -5472,14 +5238,14 @@
 
   virtual bool WillAllocateNewOrRemembered() const {
     return Heap::IsAllocatableInNewSpace(
-        Context::InstanceSize(num_context_variables_));
+        Context::InstanceSize(context_variables().length()));
   }
 
   PRINT_OPERANDS_TO_SUPPORT
 
  private:
   const TokenPosition token_pos_;
-  const intptr_t num_context_variables_;
+  const GrowableArray<LocalVariable*>& context_variables_;
 
   DISALLOW_COPY_AND_ASSIGN(AllocateContextInstr);
 };
@@ -5507,23 +5273,26 @@
   DISALLOW_COPY_AND_ASSIGN(InitStaticFieldInstr);
 };
 
+// [CloneContext] instruction clones the given Context object assuming that
+// it contains exactly the provided [context_variables].
 class CloneContextInstr : public TemplateDefinition<1, NoThrow> {
  public:
   CloneContextInstr(TokenPosition token_pos,
                     Value* context_value,
-                    intptr_t num_context_variables,
+                    const GrowableArray<LocalVariable*>& context_variables,
                     intptr_t deopt_id)
       : TemplateDefinition(deopt_id),
         token_pos_(token_pos),
-        num_context_variables_(num_context_variables) {
+        context_variables_(context_variables) {
     SetInputAt(0, context_value);
   }
 
-  static const intptr_t kUnknownContextSize = -1;
-
   virtual TokenPosition token_pos() const { return token_pos_; }
   Value* context_value() const { return inputs_[0]; }
-  intptr_t num_context_variables() const { return num_context_variables_; }
+
+  const GrowableArray<LocalVariable*>& context_variables() const {
+    return context_variables_;
+  }
 
   DECLARE_INSTRUCTION(CloneContext)
   virtual CompileType ComputeType() const;
@@ -5534,7 +5303,7 @@
 
  private:
   const TokenPosition token_pos_;
-  const intptr_t num_context_variables_;
+  const GrowableArray<LocalVariable*>& context_variables_;
 
   DISALLOW_COPY_AND_ASSIGN(CloneContextInstr);
 };
@@ -6319,14 +6088,14 @@
   CheckedSmiOpInstr(Token::Kind op_kind,
                     Value* left,
                     Value* right,
-                    InstanceCallInstr* call)
+                    TemplateDartCall<0>* call)
       : TemplateDefinition(call->deopt_id()), call_(call), op_kind_(op_kind) {
     ASSERT(call->type_args_len() == 0);
     SetInputAt(0, left);
     SetInputAt(1, right);
   }
 
-  InstanceCallInstr* call() const { return call_; }
+  TemplateDartCall<0>* call() const { return call_; }
   Token::Kind op_kind() const { return op_kind_; }
   Value* left() const { return inputs_[0]; }
   Value* right() const { return inputs_[1]; }
@@ -6344,7 +6113,7 @@
   DECLARE_INSTRUCTION(CheckedSmiOp)
 
  private:
-  InstanceCallInstr* call_;
+  TemplateDartCall<0>* call_;
   const Token::Kind op_kind_;
   DISALLOW_COPY_AND_ASSIGN(CheckedSmiOpInstr);
 };
@@ -6354,7 +6123,7 @@
   CheckedSmiComparisonInstr(Token::Kind op_kind,
                             Value* left,
                             Value* right,
-                            InstanceCallInstr* call)
+                            TemplateDartCall<0>* call)
       : TemplateComparison(call->token_pos(), op_kind, call->deopt_id()),
         call_(call),
         is_negated_(false) {
@@ -6363,7 +6132,7 @@
     SetInputAt(1, right);
   }
 
-  InstanceCallInstr* call() const { return call_; }
+  TemplateDartCall<0>* call() const { return call_; }
 
   virtual bool ComputeCanDeoptimize() const { return false; }
 
@@ -6400,7 +6169,7 @@
   virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
 
  private:
-  InstanceCallInstr* call_;
+  TemplateDartCall<0>* call_;
   bool is_negated_;
   DISALLOW_COPY_AND_ASSIGN(CheckedSmiComparisonInstr);
 };
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 05dc2cd..ccd7847 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -1484,9 +1484,9 @@
 
 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
-  const bool directly_addressable = aligned() &&
-                                    class_id() != kTypedDataInt64ArrayCid &&
-                                    class_id() != kTypedDataUint64ArrayCid;
+  const bool directly_addressable =
+      aligned() && class_id() != kTypedDataInt64ArrayCid &&
+      class_id() != kTypedDataUint64ArrayCid && class_id() != kArrayCid;
   const intptr_t kNumInputs = 3;
   LocationSummary* locs;
 
@@ -1523,15 +1523,13 @@
 
   switch (class_id()) {
     case kArrayCid:
-#if defined(CONCURRENT_MARKING)
       locs->set_in(2, ShouldEmitStoreBarrier()
                           ? Location::RegisterLocation(kWriteBarrierValueReg)
                           : Location::RegisterOrConstant(value()));
-#else
-      locs->set_in(2, ShouldEmitStoreBarrier()
-                          ? Location::WritableRegister()
-                          : Location::RegisterOrConstant(value()));
-#endif
+      if (ShouldEmitStoreBarrier()) {
+        locs->set_in(0, Location::RegisterLocation(kWriteBarrierObjectReg));
+        locs->set_temp(0, Location::RegisterLocation(kWriteBarrierSlotReg));
+      }
       break;
     case kExternalTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid:
@@ -1569,9 +1567,9 @@
 }
 
 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const bool directly_addressable = aligned() &&
-                                    class_id() != kTypedDataInt64ArrayCid &&
-                                    class_id() != kTypedDataUint64ArrayCid;
+  const bool directly_addressable =
+      aligned() && class_id() != kTypedDataInt64ArrayCid &&
+      class_id() != kTypedDataUint64ArrayCid && class_id() != kArrayCid;
   // The array register points to the backing store for external arrays.
   const Register array = locs()->in(0).reg();
   const Location index = locs()->in(1);
@@ -1610,14 +1608,14 @@
     case kArrayCid:
       if (ShouldEmitStoreBarrier()) {
         const Register value = locs()->in(2).reg();
-        __ StoreIntoObject(array, element_address, value, CanValueBeSmi(),
-                           /*lr_reserved=*/!compiler->intrinsic_mode());
+        __ StoreIntoArray(array, temp, value, CanValueBeSmi(),
+                          /*lr_reserved=*/!compiler->intrinsic_mode());
       } else if (locs()->in(2).IsConstant()) {
         const Object& constant = locs()->in(2).constant();
-        __ StoreIntoObjectNoBarrier(array, element_address, constant);
+        __ StoreIntoObjectNoBarrier(array, Address(temp), constant);
       } else {
         const Register value = locs()->in(2).reg();
-        __ StoreIntoObjectNoBarrier(array, element_address, value);
+        __ StoreIntoObjectNoBarrier(array, Address(temp), value);
       }
       break;
     case kTypedDataInt8ArrayCid:
@@ -2216,15 +2214,9 @@
     summary->set_temp(2, opt ? Location::RequiresFpuRegister()
                              : Location::FpuRegisterLocation(Q1));
   } else {
-#if defined(CONCURRENT_MARKING)
     summary->set_in(1, ShouldEmitStoreBarrier()
                            ? Location::RegisterLocation(kWriteBarrierValueReg)
                            : Location::RegisterOrConstant(value()));
-#else
-    summary->set_in(1, ShouldEmitStoreBarrier()
-                           ? Location::WritableRegister()
-                           : Location::RegisterOrConstant(value()));
-#endif
   }
   return summary;
 }
@@ -2255,12 +2247,13 @@
   Label skip_store;
 
   const Register instance_reg = locs()->in(0).reg();
+  const intptr_t offset_in_bytes = OffsetInBytes();
 
   if (IsUnboxedStore() && compiler->is_optimizing()) {
     const DRegister value = EvenDRegisterOf(locs()->in(1).fpu_reg());
     const Register temp = locs()->temp(0).reg();
     const Register temp2 = locs()->temp(1).reg();
-    const intptr_t cid = field().UnboxedFieldCid();
+    const intptr_t cid = slot().field().UnboxedFieldCid();
 
     if (is_initialization()) {
       const Class* cls = NULL;
@@ -2280,10 +2273,10 @@
 
       BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2);
       __ MoveRegister(temp2, temp);
-      __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2,
+      __ StoreIntoObjectOffset(instance_reg, offset_in_bytes, temp2,
                                Assembler::kValueIsNotSmi);
     } else {
-      __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes_));
+      __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes));
     }
     switch (cid) {
       case kDoubleCid:
@@ -2324,7 +2317,7 @@
     Label store_float32x4;
     Label store_float64x2;
 
-    __ LoadObject(temp, Field::ZoneHandle(Z, field().Original()));
+    __ LoadObject(temp, Field::ZoneHandle(Z, slot().field().Original()));
 
     __ ldrh(temp2, FieldAddress(temp, Field::is_nullable_offset()));
     __ CompareImmediate(temp2, kNullCid);
@@ -2357,7 +2350,7 @@
     {
       __ Bind(&store_double);
       EnsureMutableBox(compiler, this, temp, compiler->double_class(),
-                       instance_reg, offset_in_bytes_, temp2);
+                       instance_reg, offset_in_bytes, temp2);
       __ CopyDoubleField(temp, value_reg, TMP, temp2, fpu_temp);
       __ b(&skip_store);
     }
@@ -2365,7 +2358,7 @@
     {
       __ Bind(&store_float32x4);
       EnsureMutableBox(compiler, this, temp, compiler->float32x4_class(),
-                       instance_reg, offset_in_bytes_, temp2);
+                       instance_reg, offset_in_bytes, temp2);
       __ CopyFloat32x4Field(temp, value_reg, TMP, temp2, fpu_temp);
       __ b(&skip_store);
     }
@@ -2373,7 +2366,7 @@
     {
       __ Bind(&store_float64x2);
       EnsureMutableBox(compiler, this, temp, compiler->float64x2_class(),
-                       instance_reg, offset_in_bytes_, temp2);
+                       instance_reg, offset_in_bytes, temp2);
       __ CopyFloat64x2Field(temp, value_reg, TMP, temp2, fpu_temp);
       __ b(&skip_store);
     }
@@ -2387,16 +2380,16 @@
     // by executing 'ret LR' directly. Therefore we cannot overwrite LR. (see
     // ReturnInstr::EmitNativeCode).
     ASSERT(!locs()->live_registers()->Contains(Location::RegisterLocation(LR)));
-    __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, value_reg,
+    __ StoreIntoObjectOffset(instance_reg, offset_in_bytes, value_reg,
                              CanValueBeSmi(),
                              /*lr_reserved=*/!compiler->intrinsic_mode());
   } else {
     if (locs()->in(1).IsConstant()) {
-      __ StoreIntoObjectNoBarrierOffset(instance_reg, offset_in_bytes_,
+      __ StoreIntoObjectNoBarrierOffset(instance_reg, offset_in_bytes,
                                         locs()->in(1).constant());
     } else {
       const Register value_reg = locs()->in(1).reg();
-      __ StoreIntoObjectNoBarrierOffset(instance_reg, offset_in_bytes_,
+      __ StoreIntoObjectNoBarrierOffset(instance_reg, offset_in_bytes,
                                         value_reg);
     }
   }
@@ -2431,12 +2424,7 @@
   const intptr_t kNumTemps = 1;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-#if defined(CONCURRENT_MARKING)
   locs->set_in(0, Location::RegisterLocation(kWriteBarrierValueReg));
-#else
-  locs->set_in(0, value()->NeedsWriteBarrier() ? Location::WritableRegister()
-                                               : Location::RequiresRegister());
-#endif
   locs->set_temp(0, Location::RequiresRegister());
   return locs;
 }
@@ -2616,8 +2604,8 @@
   if (IsUnboxedLoad() && compiler->is_optimizing()) {
     const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
     const Register temp = locs()->temp(0).reg();
-    __ LoadFieldFromOffset(kWord, temp, instance_reg, offset_in_bytes());
-    const intptr_t cid = field()->UnboxedFieldCid();
+    __ LoadFieldFromOffset(kWord, temp, instance_reg, OffsetInBytes());
+    const intptr_t cid = slot().field().UnboxedFieldCid();
     switch (cid) {
       case kDoubleCid:
         __ Comment("UnboxedDoubleLoadFieldInstr");
@@ -2652,7 +2640,7 @@
     Label load_float32x4;
     Label load_float64x2;
 
-    __ LoadObject(result_reg, Field::ZoneHandle(field()->Original()));
+    __ LoadObject(result_reg, Field::ZoneHandle(slot().field().Original()));
 
     FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset());
     FieldAddress field_nullability_operand(result_reg,
@@ -2685,7 +2673,7 @@
       __ Bind(&load_double);
       BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(),
                                       result_reg, temp);
-      __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ ldr(temp, FieldAddress(instance_reg, OffsetInBytes()));
       __ CopyDoubleField(result_reg, temp, TMP, temp2, value);
       __ b(&done);
     }
@@ -2694,7 +2682,7 @@
       __ Bind(&load_float32x4);
       BoxAllocationSlowPath::Allocate(
           compiler, this, compiler->float32x4_class(), result_reg, temp);
-      __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ ldr(temp, FieldAddress(instance_reg, OffsetInBytes()));
       __ CopyFloat32x4Field(result_reg, temp, TMP, temp2, value);
       __ b(&done);
     }
@@ -2703,14 +2691,14 @@
       __ Bind(&load_float64x2);
       BoxAllocationSlowPath::Allocate(
           compiler, this, compiler->float64x2_class(), result_reg, temp);
-      __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ ldr(temp, FieldAddress(instance_reg, OffsetInBytes()));
       __ CopyFloat64x2Field(result_reg, temp, TMP, temp2, value);
       __ b(&done);
     }
 
     __ Bind(&load_pointer);
   }
-  __ LoadFieldFromOffset(kWord, result_reg, instance_reg, offset_in_bytes());
+  __ LoadFieldFromOffset(kWord, result_reg, instance_reg, OffsetInBytes());
   __ Bind(&done);
 }
 
@@ -2767,9 +2755,10 @@
 
   // 'instantiator_type_args_reg' is a TypeArguments object (or null).
   // 'function_type_args_reg' is a TypeArguments object (or null).
-  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
-         !type_arguments().CanShareInstantiatorTypeArguments(
-             instantiator_class()));
+  ASSERT(!type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()) &&
+         !type_arguments().CanShareFunctionTypeArguments(
+             compiler->parsed_function().function()));
   // If both the instantiator and function type arguments are null and if the
   // type argument vector instantiated from null becomes a vector of dynamic,
   // then use null as the type arguments.
@@ -3233,13 +3222,12 @@
     }
     __ Push(locs->in(0).reg());
     __ Push(locs->in(1).reg());
-    const String& selector =
-        String::Handle(instruction()->call()->ic_data()->target_name());
-    const Array& arguments_descriptor =
-        Array::Handle(instruction()->call()->ic_data()->arguments_descriptor());
+    const auto& selector = String::Handle(instruction()->call()->Selector());
+    const auto& arguments_descriptor = Array::Handle(
+        ArgumentsDescriptor::New(/*type_args_len=*/0, /*num_arguments=*/2));
     compiler->EmitMegamorphicInstanceCall(
         selector, arguments_descriptor, instruction()->call()->deopt_id(),
-        instruction()->call()->token_pos(), locs, try_index_, kNumSlowPathArgs);
+        instruction()->token_pos(), locs, try_index_, kNumSlowPathArgs);
     __ mov(result, Operand(R0));
     compiler->RestoreLiveRegisters(locs);
     __ b(exit_label());
@@ -3374,13 +3362,12 @@
     }
     __ Push(locs->in(0).reg());
     __ Push(locs->in(1).reg());
-    String& selector =
-        String::Handle(instruction()->call()->ic_data()->target_name());
-    const Array& arguments_descriptor =
-        Array::Handle(instruction()->call()->ic_data()->arguments_descriptor());
+    const auto& selector = String::Handle(instruction()->call()->Selector());
+    const auto& arguments_descriptor = Array::Handle(
+        ArgumentsDescriptor::New(/*type_args_len=*/0, /*num_arguments=*/2));
     compiler->EmitMegamorphicInstanceCall(
         selector, arguments_descriptor, instruction()->call()->deopt_id(),
-        instruction()->call()->token_pos(), locs, try_index_, kNumSlowPathArgs);
+        instruction()->token_pos(), locs, try_index_, kNumSlowPathArgs);
     __ mov(result, Operand(R0));
     compiler->RestoreLiveRegisters(locs);
     compiler->pending_deoptimization_env_ = NULL;
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index f3d72fb..c8b80a1 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -1357,7 +1357,7 @@
 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
   const intptr_t kNumInputs = 3;
-  const intptr_t kNumTemps = aligned() ? 0 : 2;
+  const intptr_t kNumTemps = aligned() ? 1 : 2;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   locs->set_in(0, Location::RequiresRegister());
@@ -1366,17 +1366,19 @@
   } else {
     locs->set_in(1, Location::WritableRegister());
   }
+  for (intptr_t i = 0; i < kNumTemps; i++) {
+    locs->set_temp(i, Location::RequiresRegister());
+  }
+
   switch (class_id()) {
     case kArrayCid:
-#if defined(CONCURRENT_MARKING)
       locs->set_in(2, ShouldEmitStoreBarrier()
                           ? Location::RegisterLocation(kWriteBarrierValueReg)
                           : Location::RegisterOrConstant(value()));
-#else
-      locs->set_in(2, ShouldEmitStoreBarrier()
-                          ? Location::WritableRegister()
-                          : Location::RegisterOrConstant(value()));
-#endif
+      if (ShouldEmitStoreBarrier()) {
+        locs->set_in(0, Location::RegisterLocation(kWriteBarrierObjectReg));
+        locs->set_temp(0, Location::RegisterLocation(kWriteBarrierSlotReg));
+      }
       break;
     case kExternalTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid:
@@ -1405,10 +1407,6 @@
       UNREACHABLE();
       return NULL;
   }
-  if (!aligned()) {
-    locs->set_temp(0, Location::RequiresRegister());
-    locs->set_temp(1, Location::RequiresRegister());
-  }
   return locs;
 }
 
@@ -1416,30 +1414,18 @@
   // The array register points to the backing store for external arrays.
   const Register array = locs()->in(0).reg();
   const Location index = locs()->in(1);
-  const Register address = aligned() ? kNoRegister : locs()->temp(0).reg();
+  const Register address = locs()->temp(0).reg();
   const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg();
 
-  Address element_address(TMP);  // Bad address.
-  if (aligned()) {
-    element_address =
-        index.IsRegister()
-            ? __ ElementAddressForRegIndex(false,  // Store.
-                                           IsExternal(), class_id(),
-                                           index_scale(), array, index.reg())
-            : __ ElementAddressForIntIndex(IsExternal(), class_id(),
-                                           index_scale(), array,
-                                           Smi::Cast(index.constant()).Value());
+  if (index.IsRegister()) {
+    __ LoadElementAddressForRegIndex(address,
+                                     false,  // Store.
+                                     IsExternal(), class_id(), index_scale(),
+                                     array, index.reg());
   } else {
-    if (index.IsRegister()) {
-      __ LoadElementAddressForRegIndex(address,
-                                       false,  // Store.
-                                       IsExternal(), class_id(), index_scale(),
-                                       array, index.reg());
-    } else {
-      __ LoadElementAddressForIntIndex(address, IsExternal(), class_id(),
-                                       index_scale(), array,
-                                       Smi::Cast(index.constant()).Value());
-    }
+    __ LoadElementAddressForIntIndex(address, IsExternal(), class_id(),
+                                     index_scale(), array,
+                                     Smi::Cast(index.constant()).Value());
   }
 
   switch (class_id()) {
@@ -1447,14 +1433,14 @@
       ASSERT(aligned());
       if (ShouldEmitStoreBarrier()) {
         const Register value = locs()->in(2).reg();
-        __ StoreIntoObject(array, element_address, value, CanValueBeSmi(),
-                           /*lr_reserved=*/!compiler->intrinsic_mode());
+        __ StoreIntoArray(array, address, value, CanValueBeSmi(),
+                          /*lr_reserved=*/!compiler->intrinsic_mode());
       } else if (locs()->in(2).IsConstant()) {
         const Object& constant = locs()->in(2).constant();
-        __ StoreIntoObjectNoBarrier(array, element_address, constant);
+        __ StoreIntoObjectNoBarrier(array, Address(address), constant);
       } else {
         const Register value = locs()->in(2).reg();
-        __ StoreIntoObjectNoBarrier(array, element_address, value);
+        __ StoreIntoObjectNoBarrier(array, Address(address), value);
       }
       break;
     case kTypedDataInt8ArrayCid:
@@ -1465,11 +1451,11 @@
       if (locs()->in(2).IsConstant()) {
         const Smi& constant = Smi::Cast(locs()->in(2).constant());
         __ LoadImmediate(TMP, static_cast<int8_t>(constant.Value()));
-        __ str(TMP, element_address, kUnsignedByte);
+        __ str(TMP, Address(address), kUnsignedByte);
       } else {
         const Register value = locs()->in(2).reg();
         __ SmiUntag(TMP, value);
-        __ str(TMP, element_address, kUnsignedByte);
+        __ str(TMP, Address(address), kUnsignedByte);
       }
       break;
     }
@@ -1486,7 +1472,7 @@
           value = 0;
         }
         __ LoadImmediate(TMP, static_cast<int8_t>(value));
-        __ str(TMP, element_address, kUnsignedByte);
+        __ str(TMP, Address(address), kUnsignedByte);
       } else {
         const Register value = locs()->in(2).reg();
         __ CompareImmediate(value, 0x1FE);  // Smi value and smi 0xFF.
@@ -1494,7 +1480,7 @@
         __ csetm(TMP, GT);             // TMP = value > 0x1FE ? -1 : 0.
         __ csel(TMP, value, TMP, LS);  // TMP = value in range ? value : TMP.
         __ SmiUntag(TMP);
-        __ str(TMP, element_address, kUnsignedByte);
+        __ str(TMP, Address(address), kUnsignedByte);
       }
       break;
     }
@@ -1503,7 +1489,7 @@
       const Register value = locs()->in(2).reg();
       __ SmiUntag(TMP, value);
       if (aligned()) {
-        __ str(TMP, element_address, kUnsignedHalfword);
+        __ str(TMP, Address(address), kUnsignedHalfword);
       } else {
         __ StoreUnaligned(TMP, address, scratch, kUnsignedHalfword);
       }
@@ -1513,7 +1499,7 @@
     case kTypedDataUint32ArrayCid: {
       const Register value = locs()->in(2).reg();
       if (aligned()) {
-        __ str(value, element_address, kUnsignedWord);
+        __ str(value, Address(address), kUnsignedWord);
       } else {
         __ StoreUnaligned(value, address, scratch, kUnsignedWord);
       }
@@ -1523,7 +1509,7 @@
     case kTypedDataUint64ArrayCid: {
       const Register value = locs()->in(2).reg();
       if (aligned()) {
-        __ str(value, element_address, kDoubleWord);
+        __ str(value, Address(address), kDoubleWord);
       } else {
         __ StoreUnaligned(value, address, scratch, kDoubleWord);
       }
@@ -1532,7 +1518,7 @@
     case kTypedDataFloat32ArrayCid: {
       const VRegister value_reg = locs()->in(2).fpu_reg();
       if (aligned()) {
-        __ fstrs(value_reg, element_address);
+        __ fstrs(value_reg, Address(address));
       } else {
         __ fmovrs(TMP, value_reg);
         __ StoreUnaligned(TMP, address, scratch, kWord);
@@ -1542,7 +1528,7 @@
     case kTypedDataFloat64ArrayCid: {
       const VRegister value_reg = locs()->in(2).fpu_reg();
       if (aligned()) {
-        __ fstrd(value_reg, element_address);
+        __ fstrd(value_reg, Address(address));
       } else {
         __ fmovrd(TMP, value_reg);
         __ StoreUnaligned(TMP, address, scratch, kDoubleWord);
@@ -1554,7 +1540,7 @@
     case kTypedDataFloat32x4ArrayCid: {
       ASSERT(aligned());
       const VRegister value_reg = locs()->in(2).fpu_reg();
-      __ fstrq(value_reg, element_address);
+      __ fstrq(value_reg, Address(address));
       break;
     }
     default:
@@ -1655,7 +1641,7 @@
   Label* fail = (deopt != NULL) ? deopt : &fail_label;
 
   if (emit_full_guard) {
-    __ LoadObject(field_reg, Field::ZoneHandle(field().Original()));
+    __ LoadObject(field_reg, Field::ZoneHandle((field().Original())));
 
     FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset(),
                                    kUnsignedHalfword);
@@ -1938,15 +1924,9 @@
     summary->set_temp(0, Location::RequiresRegister());
     summary->set_temp(1, Location::RequiresRegister());
   } else {
-#if defined(CONCURRENT_MARKING)
     summary->set_in(1, ShouldEmitStoreBarrier()
                            ? Location::RegisterLocation(kWriteBarrierValueReg)
                            : Location::RegisterOrConstant(value()));
-#else
-    summary->set_in(1, ShouldEmitStoreBarrier()
-                           ? Location::WritableRegister()
-                           : Location::RegisterOrConstant(value()));
-#endif
   }
   return summary;
 }
@@ -1956,12 +1936,13 @@
   Label skip_store;
 
   const Register instance_reg = locs()->in(0).reg();
+  const intptr_t offset_in_bytes = OffsetInBytes();
 
   if (IsUnboxedStore() && compiler->is_optimizing()) {
     const VRegister value = locs()->in(1).fpu_reg();
     const Register temp = locs()->temp(0).reg();
     const Register temp2 = locs()->temp(1).reg();
-    const intptr_t cid = field().UnboxedFieldCid();
+    const intptr_t cid = slot().field().UnboxedFieldCid();
 
     if (is_initialization()) {
       const Class* cls = NULL;
@@ -1981,11 +1962,11 @@
 
       BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2);
       __ MoveRegister(temp2, temp);
-      __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2,
+      __ StoreIntoObjectOffset(instance_reg, offset_in_bytes, temp2,
                                Assembler::kValueIsNotSmi,
                                /*lr_reserved=*/!compiler->intrinsic_mode());
     } else {
-      __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes_);
+      __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes);
     }
     switch (cid) {
       case kDoubleCid:
@@ -2023,7 +2004,7 @@
     Label store_float32x4;
     Label store_float64x2;
 
-    __ LoadObject(temp, Field::ZoneHandle(Z, field().Original()));
+    __ LoadObject(temp, Field::ZoneHandle(Z, slot().field().Original()));
 
     __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(),
                            kUnsignedHalfword);
@@ -2061,7 +2042,7 @@
     {
       __ Bind(&store_double);
       EnsureMutableBox(compiler, this, temp, compiler->double_class(),
-                       instance_reg, offset_in_bytes_, temp2);
+                       instance_reg, offset_in_bytes, temp2);
       __ LoadDFieldFromOffset(VTMP, value_reg, Double::value_offset());
       __ StoreDFieldToOffset(VTMP, temp, Double::value_offset());
       __ b(&skip_store);
@@ -2070,7 +2051,7 @@
     {
       __ Bind(&store_float32x4);
       EnsureMutableBox(compiler, this, temp, compiler->float32x4_class(),
-                       instance_reg, offset_in_bytes_, temp2);
+                       instance_reg, offset_in_bytes, temp2);
       __ LoadQFieldFromOffset(VTMP, value_reg, Float32x4::value_offset());
       __ StoreQFieldToOffset(VTMP, temp, Float32x4::value_offset());
       __ b(&skip_store);
@@ -2079,7 +2060,7 @@
     {
       __ Bind(&store_float64x2);
       EnsureMutableBox(compiler, this, temp, compiler->float64x2_class(),
-                       instance_reg, offset_in_bytes_, temp2);
+                       instance_reg, offset_in_bytes, temp2);
       __ LoadQFieldFromOffset(VTMP, value_reg, Float64x2::value_offset());
       __ StoreQFieldToOffset(VTMP, temp, Float64x2::value_offset());
       __ b(&skip_store);
@@ -2094,16 +2075,16 @@
     // by executing 'ret LR' directly. Therefore we cannot overwrite LR. (see
     // ReturnInstr::EmitNativeCode).
     ASSERT((kDartAvailableCpuRegs & (1 << LR)) == 0);
-    __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, value_reg,
+    __ StoreIntoObjectOffset(instance_reg, offset_in_bytes, value_reg,
                              CanValueBeSmi(),
                              /*lr_reserved=*/!compiler->intrinsic_mode());
   } else {
     if (locs()->in(1).IsConstant()) {
-      __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes_,
+      __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes,
                                         locs()->in(1).constant());
     } else {
       const Register value_reg = locs()->in(1).reg();
-      __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes_,
+      __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes,
                                         value_reg);
     }
   }
@@ -2136,12 +2117,7 @@
                                                             bool opt) const {
   LocationSummary* locs =
       new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall);
-#if defined(CONCURRENT_MARKING)
   locs->set_in(0, Location::RegisterLocation(kWriteBarrierValueReg));
-#else
-  locs->set_in(0, value()->NeedsWriteBarrier() ? Location::WritableRegister()
-                                               : Location::RequiresRegister());
-#endif
   locs->set_temp(0, Location::RequiresRegister());
   return locs;
 }
@@ -2319,8 +2295,8 @@
   if (IsUnboxedLoad() && compiler->is_optimizing()) {
     const VRegister result = locs()->out(0).fpu_reg();
     const Register temp = locs()->temp(0).reg();
-    __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes());
-    const intptr_t cid = field()->UnboxedFieldCid();
+    __ LoadFieldFromOffset(temp, instance_reg, OffsetInBytes());
+    const intptr_t cid = slot().field().UnboxedFieldCid();
     switch (cid) {
       case kDoubleCid:
         __ Comment("UnboxedDoubleLoadFieldInstr");
@@ -2348,7 +2324,7 @@
     Label load_float32x4;
     Label load_float64x2;
 
-    __ LoadObject(result_reg, Field::ZoneHandle(field()->Original()));
+    __ LoadObject(result_reg, Field::ZoneHandle(slot().field().Original()));
 
     FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset(),
                                    kUnsignedHalfword);
@@ -2382,7 +2358,7 @@
       __ Bind(&load_double);
       BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(),
                                       result_reg, temp);
-      __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes());
+      __ LoadFieldFromOffset(temp, instance_reg, OffsetInBytes());
       __ LoadDFieldFromOffset(VTMP, temp, Double::value_offset());
       __ StoreDFieldToOffset(VTMP, result_reg, Double::value_offset());
       __ b(&done);
@@ -2392,7 +2368,7 @@
       __ Bind(&load_float32x4);
       BoxAllocationSlowPath::Allocate(
           compiler, this, compiler->float32x4_class(), result_reg, temp);
-      __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes());
+      __ LoadFieldFromOffset(temp, instance_reg, OffsetInBytes());
       __ LoadQFieldFromOffset(VTMP, temp, Float32x4::value_offset());
       __ StoreQFieldToOffset(VTMP, result_reg, Float32x4::value_offset());
       __ b(&done);
@@ -2402,7 +2378,7 @@
       __ Bind(&load_float64x2);
       BoxAllocationSlowPath::Allocate(
           compiler, this, compiler->float64x2_class(), result_reg, temp);
-      __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes());
+      __ LoadFieldFromOffset(temp, instance_reg, OffsetInBytes());
       __ LoadQFieldFromOffset(VTMP, temp, Float64x2::value_offset());
       __ StoreQFieldToOffset(VTMP, result_reg, Float64x2::value_offset());
       __ b(&done);
@@ -2410,7 +2386,7 @@
 
     __ Bind(&load_pointer);
   }
-  __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes());
+  __ LoadFieldFromOffset(result_reg, instance_reg, OffsetInBytes());
   __ Bind(&done);
 }
 
@@ -2467,9 +2443,10 @@
 
   // 'instantiator_type_args_reg' is a TypeArguments object (or null).
   // 'function_type_args_reg' is a TypeArguments object (or null).
-  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
-         !type_arguments().CanShareInstantiatorTypeArguments(
-             instantiator_class()));
+  ASSERT(!type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()) &&
+         !type_arguments().CanShareFunctionTypeArguments(
+             compiler->parsed_function().function()));
   // If both the instantiator and function type arguments are null and if the
   // type argument vector instantiated from null becomes a vector of dynamic,
   // then use null as the type arguments.
@@ -2941,13 +2918,12 @@
     }
     __ Push(locs->in(0).reg());
     __ Push(locs->in(1).reg());
-    const String& selector =
-        String::Handle(instruction()->call()->ic_data()->target_name());
-    const Array& arguments_descriptor =
-        Array::Handle(instruction()->call()->ic_data()->arguments_descriptor());
+    const auto& selector = String::Handle(instruction()->call()->Selector());
+    const auto& arguments_descriptor = Array::Handle(
+        ArgumentsDescriptor::New(/*type_args_len=*/0, /*num_arguments=*/2));
     compiler->EmitMegamorphicInstanceCall(
         selector, arguments_descriptor, instruction()->call()->deopt_id(),
-        instruction()->call()->token_pos(), locs, try_index_, kNumSlowPathArgs);
+        instruction()->token_pos(), locs, try_index_, kNumSlowPathArgs);
     __ mov(result, R0);
     compiler->RestoreLiveRegisters(locs);
     __ b(exit_label());
@@ -3084,13 +3060,12 @@
     }
     __ Push(locs->in(0).reg());
     __ Push(locs->in(1).reg());
-    String& selector =
-        String::Handle(instruction()->call()->ic_data()->target_name());
-    const Array& arguments_descriptor =
-        Array::Handle(instruction()->call()->ic_data()->arguments_descriptor());
+    const auto& selector = String::Handle(instruction()->call()->Selector());
+    const auto& arguments_descriptor = Array::Handle(
+        ArgumentsDescriptor::New(/*type_args_len=*/0, /*num_arguments=*/2));
     compiler->EmitMegamorphicInstanceCall(
         selector, arguments_descriptor, instruction()->call()->deopt_id(),
-        instruction()->call()->token_pos(), locs, try_index_, kNumSlowPathArgs);
+        instruction()->token_pos(), locs, try_index_, kNumSlowPathArgs);
     __ mov(result, R0);
     compiler->RestoreLiveRegisters(locs);
     compiler->pending_deoptimization_env_ = NULL;
diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc
index 71c3db4..4e5509f 100644
--- a/runtime/vm/compiler/backend/il_dbc.cc
+++ b/runtime/vm/compiler/backend/il_dbc.cc
@@ -516,20 +516,23 @@
   }
 
   if (!compiler->is_optimizing()) {
-    const Bytecode::Opcode eq_op = needs_number_check()
-                                       ? Bytecode::kIfEqStrictNumTOS
-                                       : Bytecode::kIfEqStrictTOS;
-    const Bytecode::Opcode ne_op = needs_number_check()
-                                       ? Bytecode::kIfNeStrictNumTOS
-                                       : Bytecode::kIfNeStrictTOS;
+    const SimulatorBytecode::Opcode eq_op =
+        needs_number_check() ? SimulatorBytecode::kIfEqStrictNumTOS
+                             : SimulatorBytecode::kIfEqStrictTOS;
+    const SimulatorBytecode::Opcode ne_op =
+        needs_number_check() ? SimulatorBytecode::kIfNeStrictNumTOS
+                             : SimulatorBytecode::kIfNeStrictTOS;
     __ Emit(comparison == Token::kEQ_STRICT ? eq_op : ne_op);
   } else {
-    const Bytecode::Opcode eq_op =
-        needs_number_check() ? Bytecode::kIfEqStrictNum : Bytecode::kIfEqStrict;
-    const Bytecode::Opcode ne_op =
-        needs_number_check() ? Bytecode::kIfNeStrictNum : Bytecode::kIfNeStrict;
-    __ Emit(Bytecode::Encode((comparison == Token::kEQ_STRICT) ? eq_op : ne_op,
-                             locs()->in(0).reg(), locs()->in(1).reg()));
+    const SimulatorBytecode::Opcode eq_op =
+        needs_number_check() ? SimulatorBytecode::kIfEqStrictNum
+                             : SimulatorBytecode::kIfEqStrict;
+    const SimulatorBytecode::Opcode ne_op =
+        needs_number_check() ? SimulatorBytecode::kIfNeStrictNum
+                             : SimulatorBytecode::kIfNeStrict;
+    __ Emit(SimulatorBytecode::Encode(
+        (comparison == Token::kEQ_STRICT) ? eq_op : ne_op, locs()->in(0).reg(),
+        locs()->in(1).reg()));
   }
 
   if (needs_number_check() && token_pos().IsReal()) {
@@ -1084,34 +1087,34 @@
 
 EMIT_NATIVE_CODE(StoreInstanceField, 2) {
   ASSERT(!HasTemp());
-  ASSERT(offset_in_bytes() % kWordSize == 0);
+  ASSERT(OffsetInBytes() % kWordSize == 0);
   if (compiler->is_optimizing()) {
     const Register value = locs()->in(1).reg();
     const Register instance = locs()->in(0).reg();
-    if (Utils::IsInt(8, offset_in_bytes() / kWordSize)) {
-      __ StoreField(instance, offset_in_bytes() / kWordSize, value);
+    if (Utils::IsInt(8, OffsetInBytes() / kWordSize)) {
+      __ StoreField(instance, OffsetInBytes() / kWordSize, value);
     } else {
       __ StoreFieldExt(instance, value);
-      __ Nop(offset_in_bytes() / kWordSize);
+      __ Nop(OffsetInBytes() / kWordSize);
     }
   } else {
-    __ StoreFieldTOS(offset_in_bytes() / kWordSize);
+    __ StoreFieldTOS(OffsetInBytes() / kWordSize);
   }
 }
 
 EMIT_NATIVE_CODE(LoadField, 1, Location::RequiresRegister()) {
-  ASSERT(offset_in_bytes() % kWordSize == 0);
+  ASSERT(OffsetInBytes() % kWordSize == 0);
   if (compiler->is_optimizing()) {
     const Register result = locs()->out(0).reg();
     const Register instance = locs()->in(0).reg();
-    if (Utils::IsInt(8, offset_in_bytes() / kWordSize)) {
-      __ LoadField(result, instance, offset_in_bytes() / kWordSize);
+    if (Utils::IsInt(8, OffsetInBytes() / kWordSize)) {
+      __ LoadField(result, instance, OffsetInBytes() / kWordSize);
     } else {
       __ LoadFieldExt(result, instance);
-      __ Nop(offset_in_bytes() / kWordSize);
+      __ Nop(OffsetInBytes() / kWordSize);
     }
   } else {
-    __ LoadFieldTOS(offset_in_bytes() / kWordSize);
+    __ LoadFieldTOS(OffsetInBytes() / kWordSize);
   }
 }
 
@@ -1868,43 +1871,43 @@
   }
 }
 
-static Bytecode::Opcode OpcodeForSmiCondition(Token::Kind kind) {
+static SimulatorBytecode::Opcode OpcodeForSmiCondition(Token::Kind kind) {
   switch (kind) {
     case Token::kEQ:
-      return Bytecode::kIfEqStrict;
+      return SimulatorBytecode::kIfEqStrict;
     case Token::kNE:
-      return Bytecode::kIfNeStrict;
+      return SimulatorBytecode::kIfNeStrict;
     case Token::kLT:
-      return Bytecode::kIfLt;
+      return SimulatorBytecode::kIfLt;
     case Token::kGT:
-      return Bytecode::kIfGt;
+      return SimulatorBytecode::kIfGt;
     case Token::kLTE:
-      return Bytecode::kIfLe;
+      return SimulatorBytecode::kIfLe;
     case Token::kGTE:
-      return Bytecode::kIfGe;
+      return SimulatorBytecode::kIfGe;
     default:
       UNREACHABLE();
-      return Bytecode::kTrap;
+      return SimulatorBytecode::kTrap;
   }
 }
 
-static Bytecode::Opcode OpcodeForDoubleCondition(Token::Kind kind) {
+static SimulatorBytecode::Opcode OpcodeForDoubleCondition(Token::Kind kind) {
   switch (kind) {
     case Token::kEQ:
-      return Bytecode::kIfDEq;
+      return SimulatorBytecode::kIfDEq;
     case Token::kNE:
-      return Bytecode::kIfDNe;
+      return SimulatorBytecode::kIfDNe;
     case Token::kLT:
-      return Bytecode::kIfDLt;
+      return SimulatorBytecode::kIfDLt;
     case Token::kGT:
-      return Bytecode::kIfDGt;
+      return SimulatorBytecode::kIfDGt;
     case Token::kLTE:
-      return Bytecode::kIfDLe;
+      return SimulatorBytecode::kIfDLe;
     case Token::kGTE:
-      return Bytecode::kIfDGe;
+      return SimulatorBytecode::kIfDGe;
     default:
       UNREACHABLE();
-      return Bytecode::kTrap;
+      return SimulatorBytecode::kTrap;
   }
 }
 
@@ -1926,7 +1929,8 @@
   if (compiler->is_optimizing()) {
     const Register left = locs->in(0).reg();
     const Register right = locs->in(1).reg();
-    __ Emit(Bytecode::Encode(OpcodeForSmiCondition(comparison), left, right));
+    __ Emit(SimulatorBytecode::Encode(OpcodeForSmiCondition(comparison), left,
+                                      right));
     return condition;
   } else {
     switch (kind) {
@@ -1967,7 +1971,8 @@
   // TODO(fschneider): Change the block order instead in DBC so that the
   // false block in always the fall-through block.
   Condition condition = NEXT_IS_TRUE;
-  __ Emit(Bytecode::Encode(OpcodeForDoubleCondition(comparison), left, right));
+  __ Emit(SimulatorBytecode::Encode(OpcodeForDoubleCondition(comparison), left,
+                                    right));
   return condition;
 }
 
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 182ddd3..e28e999 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -1265,7 +1265,8 @@
 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
   const intptr_t kNumInputs = 3;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      class_id() == kArrayCid && ShouldEmitStoreBarrier() ? 1 : 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   locs->set_in(0, Location::RequiresRegister());
@@ -1283,6 +1284,10 @@
       locs->set_in(2, ShouldEmitStoreBarrier()
                           ? Location::WritableRegister()
                           : Location::RegisterOrConstant(value()));
+      if (ShouldEmitStoreBarrier()) {
+        locs->set_in(0, Location::RegisterLocation(kWriteBarrierObjectReg));
+        locs->set_temp(0, Location::RegisterLocation(kWriteBarrierSlotReg));
+      }
       break;
     case kExternalTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid:
@@ -1345,7 +1350,9 @@
     case kArrayCid:
       if (ShouldEmitStoreBarrier()) {
         Register value = locs()->in(2).reg();
-        __ StoreIntoObject(array, element_address, value, CanValueBeSmi());
+        Register slot = locs()->temp(0).reg();
+        __ leal(slot, element_address);
+        __ StoreIntoArray(array, slot, value, CanValueBeSmi());
       } else if (locs()->in(2).IsConstant()) {
         const Object& constant = locs()->in(2).constant();
         __ StoreIntoObjectNoBarrier(array, element_address, constant);
@@ -1823,13 +1830,14 @@
   ASSERT(sizeof(classid_t) == kInt16Size);
   Label skip_store;
 
-  Register instance_reg = locs()->in(0).reg();
+  const Register instance_reg = locs()->in(0).reg();
+  const intptr_t offset_in_bytes = OffsetInBytes();
 
   if (IsUnboxedStore() && compiler->is_optimizing()) {
     XmmRegister value = locs()->in(1).fpu_reg();
     Register temp = locs()->temp(0).reg();
     Register temp2 = locs()->temp(1).reg();
-    const intptr_t cid = field().UnboxedFieldCid();
+    const intptr_t cid = slot().field().UnboxedFieldCid();
 
     if (is_initialization()) {
       const Class* cls = NULL;
@@ -1850,10 +1858,10 @@
       BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2);
       __ movl(temp2, temp);
       __ StoreIntoObject(instance_reg,
-                         FieldAddress(instance_reg, offset_in_bytes_), temp2,
+                         FieldAddress(instance_reg, offset_in_bytes), temp2,
                          Assembler::kValueIsNotSmi);
     } else {
-      __ movl(temp, FieldAddress(instance_reg, offset_in_bytes_));
+      __ movl(temp, FieldAddress(instance_reg, offset_in_bytes));
     }
     switch (cid) {
       case kDoubleCid:
@@ -1893,7 +1901,7 @@
     Label store_float32x4;
     Label store_float64x2;
 
-    __ LoadObject(temp, Field::ZoneHandle(Z, field().Original()));
+    __ LoadObject(temp, Field::ZoneHandle(Z, slot().field().Original()));
 
     __ cmpw(FieldAddress(temp, Field::is_nullable_offset()),
             Immediate(kNullCid));
@@ -1926,7 +1934,7 @@
     {
       __ Bind(&store_double);
       EnsureMutableBox(compiler, this, temp, compiler->double_class(),
-                       instance_reg, offset_in_bytes_, temp2);
+                       instance_reg, offset_in_bytes, temp2);
       __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset()));
       __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp);
       __ jmp(&skip_store);
@@ -1935,7 +1943,7 @@
     {
       __ Bind(&store_float32x4);
       EnsureMutableBox(compiler, this, temp, compiler->float32x4_class(),
-                       instance_reg, offset_in_bytes_, temp2);
+                       instance_reg, offset_in_bytes, temp2);
       __ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset()));
       __ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp);
       __ jmp(&skip_store);
@@ -1944,7 +1952,7 @@
     {
       __ Bind(&store_float64x2);
       EnsureMutableBox(compiler, this, temp, compiler->float64x2_class(),
-                       instance_reg, offset_in_bytes_, temp2);
+                       instance_reg, offset_in_bytes, temp2);
       __ movups(fpu_temp, FieldAddress(value_reg, Float64x2::value_offset()));
       __ movups(FieldAddress(temp, Float64x2::value_offset()), fpu_temp);
       __ jmp(&skip_store);
@@ -1956,18 +1964,17 @@
   if (ShouldEmitStoreBarrier()) {
     Register value_reg = locs()->in(1).reg();
     __ StoreIntoObject(instance_reg,
-                       FieldAddress(instance_reg, offset_in_bytes_), value_reg,
+                       FieldAddress(instance_reg, offset_in_bytes), value_reg,
                        CanValueBeSmi());
   } else {
     if (locs()->in(1).IsConstant()) {
       __ StoreIntoObjectNoBarrier(instance_reg,
-                                  FieldAddress(instance_reg, offset_in_bytes_),
+                                  FieldAddress(instance_reg, offset_in_bytes),
                                   locs()->in(1).constant());
     } else {
       Register value_reg = locs()->in(1).reg();
-      __ StoreIntoObjectNoBarrier(instance_reg,
-                                  FieldAddress(instance_reg, offset_in_bytes_),
-                                  value_reg);
+      __ StoreIntoObjectNoBarrier(
+          instance_reg, FieldAddress(instance_reg, offset_in_bytes), value_reg);
     }
   }
   __ Bind(&skip_store);
@@ -2178,8 +2185,8 @@
   if (IsUnboxedLoad() && compiler->is_optimizing()) {
     XmmRegister result = locs()->out(0).fpu_reg();
     Register temp = locs()->temp(0).reg();
-    __ movl(temp, FieldAddress(instance_reg, offset_in_bytes()));
-    const intptr_t cid = field()->UnboxedFieldCid();
+    __ movl(temp, FieldAddress(instance_reg, OffsetInBytes()));
+    const intptr_t cid = slot().field().UnboxedFieldCid();
     switch (cid) {
       case kDoubleCid:
         __ Comment("UnboxedDoubleLoadFieldInstr");
@@ -2210,7 +2217,7 @@
     Label load_float32x4;
     Label load_float64x2;
 
-    __ LoadObject(result, Field::ZoneHandle(field()->Original()));
+    __ LoadObject(result, Field::ZoneHandle(slot().field().Original()));
 
     FieldAddress field_cid_operand(result, Field::guarded_cid_offset());
     FieldAddress field_nullability_operand(result, Field::is_nullable_offset());
@@ -2238,7 +2245,7 @@
       __ Bind(&load_double);
       BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(),
                                       result, temp);
-      __ movl(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ movl(temp, FieldAddress(instance_reg, OffsetInBytes()));
       __ movsd(value, FieldAddress(temp, Double::value_offset()));
       __ movsd(FieldAddress(result, Double::value_offset()), value);
       __ jmp(&done);
@@ -2248,7 +2255,7 @@
       __ Bind(&load_float32x4);
       BoxAllocationSlowPath::Allocate(
           compiler, this, compiler->float32x4_class(), result, temp);
-      __ movl(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ movl(temp, FieldAddress(instance_reg, OffsetInBytes()));
       __ movups(value, FieldAddress(temp, Float32x4::value_offset()));
       __ movups(FieldAddress(result, Float32x4::value_offset()), value);
       __ jmp(&done);
@@ -2258,7 +2265,7 @@
       __ Bind(&load_float64x2);
       BoxAllocationSlowPath::Allocate(
           compiler, this, compiler->float64x2_class(), result, temp);
-      __ movl(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ movl(temp, FieldAddress(instance_reg, OffsetInBytes()));
       __ movups(value, FieldAddress(temp, Float64x2::value_offset()));
       __ movups(FieldAddress(result, Float64x2::value_offset()), value);
       __ jmp(&done);
@@ -2266,7 +2273,7 @@
 
     __ Bind(&load_pointer);
   }
-  __ movl(result, FieldAddress(instance_reg, offset_in_bytes()));
+  __ movl(result, FieldAddress(instance_reg, OffsetInBytes()));
   __ Bind(&done);
 }
 
@@ -2324,9 +2331,10 @@
 
   // 'instantiator_type_args_reg' is a TypeArguments object (or null).
   // 'function_type_args_reg' is a TypeArguments object (or null).
-  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
-         !type_arguments().CanShareInstantiatorTypeArguments(
-             instantiator_class()));
+  ASSERT(!type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()) &&
+         !type_arguments().CanShareFunctionTypeArguments(
+             compiler->parsed_function().function()));
   // If both the instantiator and function type arguments are null and if the
   // type argument vector instantiated from null becomes a vector of dynamic,
   // then use null as the type arguments.
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index d18ee6f..a2a26ea 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -13,7 +13,7 @@
 
 namespace dart {
 
-#ifndef PRODUCT
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 
 DEFINE_FLAG(bool,
             display_sorted_ic_data,
@@ -612,14 +612,8 @@
 }
 
 void StoreInstanceFieldInstr::PrintOperandsTo(BufferFormatter* f) const {
-  if (field().IsNull()) {
-    f->Print("{%" Pd "}, ", offset_in_bytes());
-  } else {
-    f->Print("%s {%" Pd "}, ", String::Handle(field().name()).ToCString(),
-             field().Offset());
-  }
   instance()->PrintTo(f);
-  f->Print(", ");
+  f->Print(" . %s = ", slot().Name());
   value()->PrintTo(f);
   if (!ShouldEmitStoreBarrier()) f->Print(", barrier removed");
 }
@@ -671,27 +665,14 @@
   f->Print("%s", String::Handle(cls_.ScrubbedName()).ToCString());
   for (intptr_t i = 0; i < InputCount(); i++) {
     f->Print(", ");
-    f->Print("%s: ", slots_[i]->ToCString());
+    f->Print("%s: ", slots_[i]->Name());
     InputAt(i)->PrintTo(f);
   }
 }
 
 void LoadFieldInstr::PrintOperandsTo(BufferFormatter* f) const {
   instance()->PrintTo(f);
-  f->Print(", %" Pd, offset_in_bytes());
-
-  if (field() != nullptr) {
-    f->Print(" {%s} %s", String::Handle(field()->name()).ToCString(),
-             field()->GuardedPropertiesAsCString());
-  }
-
-  if (native_field() != nullptr) {
-    f->Print(" {%s}", native_field()->name());
-  }
-
-  if (immutable_) {
-    f->Print(", immutable");
-  }
+  f->Print(" . %s%s", slot().Name(), slot().is_immutable() ? " {final}" : "");
 }
 
 void InstantiateTypeInstr::PrintOperandsTo(BufferFormatter* f) const {
@@ -1158,7 +1139,7 @@
   return Thread::Current()->zone()->MakeCopyOfString(buffer);
 }
 
-#else  // PRODUCT
+#else  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 
 const char* Instruction::ToCString() const {
   return DebugName();
@@ -1196,7 +1177,7 @@
   return false;
 }
 
-#endif  // !PRODUCT
+#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/backend/il_test.cc b/runtime/vm/compiler/backend/il_test.cc
index 9c3f88c..388136c 100644
--- a/runtime/vm/compiler/backend/il_test.cc
+++ b/runtime/vm/compiler/backend/il_test.cc
@@ -7,7 +7,7 @@
 
 namespace dart {
 
-TEST_CASE(InstructionTests) {
+ISOLATE_UNIT_TEST_CASE(InstructionTests) {
   TargetEntryInstr* target_instr =
       new TargetEntryInstr(1, kInvalidTryIndex, DeoptId::kNone);
   EXPECT(target_instr->IsBlockEntry());
@@ -19,7 +19,7 @@
   EXPECT(context->GetBlock() == target_instr);
 }
 
-TEST_CASE(OptimizationTests) {
+ISOLATE_UNIT_TEST_CASE(OptimizationTests) {
   JoinEntryInstr* join =
       new JoinEntryInstr(1, kInvalidTryIndex, DeoptId::kNone);
 
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index a4709d6..64ed573 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -1387,7 +1387,8 @@
 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
   const intptr_t kNumInputs = 3;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      class_id() == kArrayCid && ShouldEmitStoreBarrier() ? 1 : 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   locs->set_in(0, Location::RequiresRegister());
@@ -1406,15 +1407,13 @@
   }
   switch (class_id()) {
     case kArrayCid:
-#if defined(CONCURRENT_MARKING)
       locs->set_in(2, ShouldEmitStoreBarrier()
                           ? Location::RegisterLocation(kWriteBarrierValueReg)
                           : Location::RegisterOrConstant(value()));
-#else
-      locs->set_in(2, ShouldEmitStoreBarrier()
-                          ? Location::WritableRegister()
-                          : Location::RegisterOrConstant(value()));
-#endif
+      if (ShouldEmitStoreBarrier()) {
+        locs->set_in(0, Location::RegisterLocation(kWriteBarrierObjectReg));
+        locs->set_temp(0, Location::RegisterLocation(kWriteBarrierSlotReg));
+      }
       break;
     case kExternalTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid:
@@ -1474,7 +1473,9 @@
     case kArrayCid:
       if (ShouldEmitStoreBarrier()) {
         Register value = locs()->in(2).reg();
-        __ StoreIntoObject(array, element_address, value, CanValueBeSmi());
+        Register slot = locs()->temp(0).reg();
+        __ leaq(slot, element_address);
+        __ StoreIntoArray(array, slot, value, CanValueBeSmi());
       } else if (locs()->in(2).IsConstant()) {
         const Object& constant = locs()->in(2).constant();
         __ StoreIntoObjectNoBarrier(array, element_address, constant);
@@ -1926,15 +1927,9 @@
     summary->set_temp(2, opt ? Location::RequiresFpuRegister()
                              : Location::FpuRegisterLocation(XMM1));
   } else {
-#if defined(CONCURRENT_MARKING)
     summary->set_in(1, ShouldEmitStoreBarrier()
                            ? Location::RegisterLocation(kWriteBarrierValueReg)
                            : Location::RegisterOrConstant(value()));
-#else
-    summary->set_in(1, ShouldEmitStoreBarrier()
-                           ? Location::WritableRegister()
-                           : Location::RegisterOrConstant(value()));
-#endif
   }
   return summary;
 }
@@ -1962,13 +1957,14 @@
   ASSERT(sizeof(classid_t) == kInt16Size);
   Label skip_store;
 
-  Register instance_reg = locs()->in(0).reg();
+  const Register instance_reg = locs()->in(0).reg();
+  const intptr_t offset_in_bytes = OffsetInBytes();
 
   if (IsUnboxedStore() && compiler->is_optimizing()) {
     XmmRegister value = locs()->in(1).fpu_reg();
     Register temp = locs()->temp(0).reg();
     Register temp2 = locs()->temp(1).reg();
-    const intptr_t cid = field().UnboxedFieldCid();
+    const intptr_t cid = slot().field().UnboxedFieldCid();
 
     if (is_initialization()) {
       const Class* cls = NULL;
@@ -1989,10 +1985,10 @@
       BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2);
       __ movq(temp2, temp);
       __ StoreIntoObject(instance_reg,
-                         FieldAddress(instance_reg, offset_in_bytes_), temp2,
+                         FieldAddress(instance_reg, offset_in_bytes), temp2,
                          Assembler::kValueIsNotSmi);
     } else {
-      __ movq(temp, FieldAddress(instance_reg, offset_in_bytes_));
+      __ movq(temp, FieldAddress(instance_reg, offset_in_bytes));
     }
     switch (cid) {
       case kDoubleCid:
@@ -2030,7 +2026,7 @@
     Label store_float32x4;
     Label store_float64x2;
 
-    __ LoadObject(temp, Field::ZoneHandle(Z, field().Original()));
+    __ LoadObject(temp, Field::ZoneHandle(Z, slot().field().Original()));
 
     __ cmpw(FieldAddress(temp, Field::is_nullable_offset()),
             Immediate(kNullCid));
@@ -2063,7 +2059,7 @@
     {
       __ Bind(&store_double);
       EnsureMutableBox(compiler, this, temp, compiler->double_class(),
-                       instance_reg, offset_in_bytes_, temp2);
+                       instance_reg, offset_in_bytes, temp2);
       __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset()));
       __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp);
       __ jmp(&skip_store);
@@ -2072,7 +2068,7 @@
     {
       __ Bind(&store_float32x4);
       EnsureMutableBox(compiler, this, temp, compiler->float32x4_class(),
-                       instance_reg, offset_in_bytes_, temp2);
+                       instance_reg, offset_in_bytes, temp2);
       __ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset()));
       __ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp);
       __ jmp(&skip_store);
@@ -2081,7 +2077,7 @@
     {
       __ Bind(&store_float64x2);
       EnsureMutableBox(compiler, this, temp, compiler->float64x2_class(),
-                       instance_reg, offset_in_bytes_, temp2);
+                       instance_reg, offset_in_bytes, temp2);
       __ movups(fpu_temp, FieldAddress(value_reg, Float64x2::value_offset()));
       __ movups(FieldAddress(temp, Float64x2::value_offset()), fpu_temp);
       __ jmp(&skip_store);
@@ -2093,18 +2089,17 @@
   if (ShouldEmitStoreBarrier()) {
     Register value_reg = locs()->in(1).reg();
     __ StoreIntoObject(instance_reg,
-                       FieldAddress(instance_reg, offset_in_bytes_), value_reg,
+                       FieldAddress(instance_reg, offset_in_bytes), value_reg,
                        CanValueBeSmi());
   } else {
     if (locs()->in(1).IsConstant()) {
       __ StoreIntoObjectNoBarrier(instance_reg,
-                                  FieldAddress(instance_reg, offset_in_bytes_),
+                                  FieldAddress(instance_reg, offset_in_bytes),
                                   locs()->in(1).constant());
     } else {
       Register value_reg = locs()->in(1).reg();
-      __ StoreIntoObjectNoBarrier(instance_reg,
-                                  FieldAddress(instance_reg, offset_in_bytes_),
-                                  value_reg);
+      __ StoreIntoObjectNoBarrier(
+          instance_reg, FieldAddress(instance_reg, offset_in_bytes), value_reg);
     }
   }
   __ Bind(&skip_store);
@@ -2136,12 +2131,7 @@
                                                             bool opt) const {
   LocationSummary* locs =
       new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall);
-#if defined(CONCURRENT_MARKING)
   locs->set_in(0, Location::RegisterLocation(kWriteBarrierValueReg));
-#else
-  locs->set_in(0, value()->NeedsWriteBarrier() ? Location::WritableRegister()
-                                               : Location::RequiresRegister());
-#endif
   locs->set_temp(0, Location::RequiresRegister());
   return locs;
 }
@@ -2321,8 +2311,8 @@
   if (IsUnboxedLoad() && compiler->is_optimizing()) {
     XmmRegister result = locs()->out(0).fpu_reg();
     Register temp = locs()->temp(0).reg();
-    __ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
-    intptr_t cid = field()->UnboxedFieldCid();
+    __ movq(temp, FieldAddress(instance_reg, OffsetInBytes()));
+    intptr_t cid = slot().field().UnboxedFieldCid();
     switch (cid) {
       case kDoubleCid:
         __ Comment("UnboxedDoubleLoadFieldInstr");
@@ -2353,7 +2343,7 @@
     Label load_float32x4;
     Label load_float64x2;
 
-    __ LoadObject(result, Field::ZoneHandle(field()->Original()));
+    __ LoadObject(result, Field::ZoneHandle(slot().field().Original()));
 
     FieldAddress field_cid_operand(result, Field::guarded_cid_offset());
     FieldAddress field_nullability_operand(result, Field::is_nullable_offset());
@@ -2381,7 +2371,7 @@
       __ Bind(&load_double);
       BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(),
                                       result, temp);
-      __ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ movq(temp, FieldAddress(instance_reg, OffsetInBytes()));
       __ movsd(value, FieldAddress(temp, Double::value_offset()));
       __ movsd(FieldAddress(result, Double::value_offset()), value);
       __ jmp(&done);
@@ -2391,7 +2381,7 @@
       __ Bind(&load_float32x4);
       BoxAllocationSlowPath::Allocate(
           compiler, this, compiler->float32x4_class(), result, temp);
-      __ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ movq(temp, FieldAddress(instance_reg, OffsetInBytes()));
       __ movups(value, FieldAddress(temp, Float32x4::value_offset()));
       __ movups(FieldAddress(result, Float32x4::value_offset()), value);
       __ jmp(&done);
@@ -2401,7 +2391,7 @@
       __ Bind(&load_float64x2);
       BoxAllocationSlowPath::Allocate(
           compiler, this, compiler->float64x2_class(), result, temp);
-      __ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ movq(temp, FieldAddress(instance_reg, OffsetInBytes()));
       __ movups(value, FieldAddress(temp, Float64x2::value_offset()));
       __ movups(FieldAddress(result, Float64x2::value_offset()), value);
       __ jmp(&done);
@@ -2409,7 +2399,7 @@
 
     __ Bind(&load_pointer);
   }
-  __ movq(result, FieldAddress(instance_reg, offset_in_bytes()));
+  __ movq(result, FieldAddress(instance_reg, OffsetInBytes()));
   __ Bind(&done);
 }
 
@@ -2466,9 +2456,10 @@
 
   // 'instantiator_type_args_reg' is a TypeArguments object (or null).
   // 'function_type_args_reg' is a TypeArguments object (or null).
-  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
-         !type_arguments().CanShareInstantiatorTypeArguments(
-             instantiator_class()));
+  ASSERT(!type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()) &&
+         !type_arguments().CanShareFunctionTypeArguments(
+             compiler->parsed_function().function()));
   // If both the instantiator and function type arguments are null and if the
   // type argument vector instantiated from null becomes a vector of dynamic,
   // then use null as the type arguments.
@@ -2955,13 +2946,12 @@
     }
     __ pushq(locs->in(0).reg());
     __ pushq(locs->in(1).reg());
-    const String& selector =
-        String::Handle(instruction()->call()->ic_data()->target_name());
-    const Array& arguments_descriptor =
-        Array::Handle(instruction()->call()->ic_data()->arguments_descriptor());
+    const auto& selector = String::Handle(instruction()->call()->Selector());
+    const auto& arguments_descriptor = Array::Handle(
+        ArgumentsDescriptor::New(/*type_args_len=*/0, /*num_arguments=*/2));
     compiler->EmitMegamorphicInstanceCall(
         selector, arguments_descriptor, instruction()->call()->deopt_id(),
-        instruction()->call()->token_pos(), locs, try_index_, kNumSlowPathArgs);
+        instruction()->token_pos(), locs, try_index_, kNumSlowPathArgs);
     __ MoveRegister(result, RAX);
     compiler->RestoreLiveRegisters(locs);
     __ jmp(exit_label());
@@ -3122,13 +3112,14 @@
     }
     __ pushq(locs->in(0).reg());
     __ pushq(locs->in(1).reg());
-    String& selector =
-        String::Handle(instruction()->call()->ic_data()->target_name());
-    const Array& arguments_descriptor =
-        Array::Handle(instruction()->call()->ic_data()->arguments_descriptor());
+
+    const auto& selector = String::Handle(instruction()->call()->Selector());
+    const auto& arguments_descriptor = Array::Handle(
+        ArgumentsDescriptor::New(/*type_args_len=*/0, /*num_arguments=*/2));
+
     compiler->EmitMegamorphicInstanceCall(
         selector, arguments_descriptor, instruction()->call()->deopt_id(),
-        instruction()->call()->token_pos(), locs, try_index_, kNumSlowPathArgs);
+        instruction()->token_pos(), locs, try_index_, kNumSlowPathArgs);
     __ MoveRegister(result, RAX);
     compiler->RestoreLiveRegisters(locs);
     compiler->pending_deoptimization_env_ = NULL;
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index bdbf35a..1398af1 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -254,7 +254,7 @@
 // A collection of call sites to consider for inlining.
 class CallSites : public ValueObject {
  public:
-  explicit CallSites(FlowGraph* flow_graph, intptr_t threshold)
+  explicit CallSites(intptr_t threshold)
       : inlining_depth_threshold_(threshold),
         static_calls_(),
         closure_calls_(),
@@ -264,9 +264,14 @@
     PolymorphicInstanceCallInstr* call;
     double ratio;
     const FlowGraph* caller_graph;
+    intptr_t nesting_depth;
     InstanceCallInfo(PolymorphicInstanceCallInstr* call_arg,
-                     FlowGraph* flow_graph)
-        : call(call_arg), ratio(0.0), caller_graph(flow_graph) {}
+                     FlowGraph* flow_graph,
+                     intptr_t depth)
+        : call(call_arg),
+          ratio(0.0),
+          caller_graph(flow_graph),
+          nesting_depth(depth) {}
     const Function& caller() const { return caller_graph->function(); }
   };
 
@@ -274,8 +279,14 @@
     StaticCallInstr* call;
     double ratio;
     FlowGraph* caller_graph;
-    StaticCallInfo(StaticCallInstr* value, FlowGraph* flow_graph)
-        : call(value), ratio(0.0), caller_graph(flow_graph) {}
+    intptr_t nesting_depth;
+    StaticCallInfo(StaticCallInstr* value,
+                   FlowGraph* flow_graph,
+                   intptr_t depth)
+        : call(value),
+          ratio(0.0),
+          caller_graph(flow_graph),
+          nesting_depth(depth) {}
     const Function& caller() const { return caller_graph->function(); }
   };
 
@@ -315,6 +326,32 @@
     instance_calls_.Clear();
   }
 
+  // Heuristic that maps the loop nesting depth to a static estimate of number
+  // of times code at that depth is executed (code at each higher nesting
+  // depth is assumed to execute 10x more often up to depth 3).
+  static intptr_t AotCallCountApproximation(intptr_t nesting_depth) {
+    switch (nesting_depth) {
+      case 0:
+        // Note that we use value 0, and not 1, i.e. any straightline code
+        // outside a loop is assumed to be very cold. With value 1, inlining
+        // inside loops is still favored over inlining inside straightline
+        // code, but for a method without loops, *all* call sites are inlined
+        // (potentially more performance, at the expense of larger code size).
+        // TODO(ajcbik): use 1 and fine tune other heuristics
+        return 0;
+      case 1:
+        return 10;
+      case 2:
+        return 100;
+      default:
+        return 1000;
+    }
+  }
+
+  // Computes the ratio for each call site in a method, defined as the
+  // number of times a call site is executed over the maximum number of
+  // times any call site is executed in the method. JIT uses actual call
+  // counts whereas AOT uses a static estimate based on nesting depth.
   void ComputeCallSiteRatio(intptr_t static_call_start_ix,
                             intptr_t instance_call_start_ix) {
     const intptr_t num_static_calls =
@@ -325,21 +362,26 @@
     intptr_t max_count = 0;
     GrowableArray<intptr_t> instance_call_counts(num_instance_calls);
     for (intptr_t i = 0; i < num_instance_calls; ++i) {
-      const intptr_t aggregate_count =
-          instance_calls_[i + instance_call_start_ix].call->CallCount();
+      const InstanceCallInfo& info =
+          instance_calls_[i + instance_call_start_ix];
+      intptr_t aggregate_count =
+          FLAG_precompiled_mode ? AotCallCountApproximation(info.nesting_depth)
+                                : info.call->CallCount();
       instance_call_counts.Add(aggregate_count);
       if (aggregate_count > max_count) max_count = aggregate_count;
     }
 
     GrowableArray<intptr_t> static_call_counts(num_static_calls);
     for (intptr_t i = 0; i < num_static_calls; ++i) {
+      const StaticCallInfo& info = static_calls_[i + static_call_start_ix];
       intptr_t aggregate_count =
-          static_calls_[i + static_call_start_ix].call->CallCount();
+          FLAG_precompiled_mode ? AotCallCountApproximation(info.nesting_depth)
+                                : info.call->CallCount();
       static_call_counts.Add(aggregate_count);
       if (aggregate_count > max_count) max_count = aggregate_count;
     }
 
-    // max_count can be 0 if none of the calls was executed.
+    // Note that max_count can be 0 if none of the calls was executed.
     for (intptr_t i = 0; i < num_instance_calls; ++i) {
       const double ratio =
           (max_count == 0)
@@ -404,12 +446,18 @@
     const bool inline_only_recognized_methods =
         (depth == inlining_depth_threshold_);
 
+    // In AOT, compute loop hierarchy.
+    if (FLAG_precompiled_mode) {
+      graph->GetLoopHierarchy();
+    }
+
     const intptr_t instance_call_start_ix = instance_calls_.length();
     const intptr_t static_call_start_ix = static_calls_.length();
     for (BlockIterator block_it = graph->postorder_iterator(); !block_it.Done();
          block_it.Advance()) {
-      for (ForwardInstructionIterator it(block_it.Current()); !it.Done();
-           it.Advance()) {
+      BlockEntryInstr* entry = block_it.Current();
+      const intptr_t depth = entry->NestingDepth();
+      for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
         Instruction* current = it.Current();
         if (current->IsPolymorphicInstanceCall()) {
           PolymorphicInstanceCallInstr* instance_call =
@@ -417,7 +465,7 @@
           if (!inline_only_recognized_methods ||
               instance_call->IsSureToCallSingleRecognizedTarget() ||
               instance_call->HasOnlyDispatcherOrImplicitAccessorTargets()) {
-            instance_calls_.Add(InstanceCallInfo(instance_call, graph));
+            instance_calls_.Add(InstanceCallInfo(instance_call, graph, depth));
           } else {
             // Method not inlined because inlining too deep and method
             // not recognized.
@@ -433,7 +481,7 @@
           if (!inline_only_recognized_methods ||
               static_call->function().IsRecognized() ||
               static_call->function().IsDispatcherOrImplicitAccessor()) {
-            static_calls_.Add(StaticCallInfo(static_call, graph));
+            static_calls_.Add(StaticCallInfo(static_call, graph, depth));
           } else {
             // Method not inlined because inlining too deep and method
             // not recognized.
@@ -626,10 +674,7 @@
           ASSERT(call_data->call->IsClosureCall());
           LoadFieldInstr* context_load = new (zone) LoadFieldInstr(
               new Value((*arguments)[first_arg_index]->definition()),
-              Closure::context_offset(),
-              AbstractType::ZoneHandle(zone, AbstractType::null()),
-              call_data->call->token_pos());
-          context_load->set_is_immutable(true);
+              Slot::Closure_context(), call_data->call->token_pos());
           context_load->set_ssa_temp_index(
               caller_graph->alloc_ssa_temp_index());
           context_load->InsertBefore(callee_entry->next());
@@ -751,8 +796,8 @@
       return;
     }
     // Create two call site collections to swap between.
-    CallSites sites1(caller_graph_, inlining_depth_threshold_);
-    CallSites sites2(caller_graph_, inlining_depth_threshold_);
+    CallSites sites1(inlining_depth_threshold_);
+    CallSites sites2(inlining_depth_threshold_);
     CallSites* call_sites_temp = NULL;
     collected_call_sites_ = &sites1;
     inlining_call_sites_ = &sites2;
@@ -924,8 +969,7 @@
             isolate->loading_invalidation_gen();
 
         if (Compiler::IsBackgroundCompilation()) {
-          if (isolate->IsTopLevelParsing() ||
-              (loading_invalidation_gen_at_start !=
+          if ((loading_invalidation_gen_at_start !=
                isolate->loading_invalidation_gen())) {
             // Loading occured while parsing. We need to abort here because
             // state changed while compiling.
@@ -2319,8 +2363,8 @@
                                        bool can_speculate) {
   // Insert array length load and bounds check.
   LoadFieldInstr* length = new (Z) LoadFieldInstr(
-      new (Z) Value(*array),
-      NativeFieldDesc::GetLengthFieldForArrayCid(array_cid), call->token_pos());
+      new (Z) Value(*array), Slot::GetLengthFieldForArrayCid(array_cid),
+      call->token_pos());
   *cursor = flow_graph->AppendTo(*cursor, length, NULL, FlowGraph::kValue);
 
   Instruction* bounds_check = NULL;
@@ -2336,10 +2380,9 @@
 
   if (array_cid == kGrowableObjectArrayCid) {
     // Insert data elements load.
-    LoadFieldInstr* elements = new (Z) LoadFieldInstr(
-        new (Z) Value(*array), GrowableObjectArray::data_offset(),
-        Object::dynamic_type(), call->token_pos());
-    elements->set_result_cid(kArrayCid);
+    LoadFieldInstr* elements = new (Z)
+        LoadFieldInstr(new (Z) Value(*array), Slot::GrowableObjectArray_data(),
+                       call->token_pos());
     *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
     // Load from the data from backing store which is a fixed-length array.
     *array = elements;
@@ -2435,10 +2478,11 @@
       case kArrayCid:
       case kGrowableObjectArrayCid: {
         const Class& instantiator_class = Class::Handle(Z, target.Owner());
-        LoadFieldInstr* load_type_args = new (Z) LoadFieldInstr(
-            new (Z) Value(array),
-            NativeFieldDesc::GetTypeArgumentsFieldFor(Z, instantiator_class),
-            call->token_pos());
+        LoadFieldInstr* load_type_args = new (Z)
+            LoadFieldInstr(new (Z) Value(array),
+                           Slot::GetTypeArgumentsSlotFor(flow_graph->thread(),
+                                                         instantiator_class),
+                           call->token_pos());
         cursor = flow_graph->AppendTo(cursor, load_type_args, NULL,
                                       FlowGraph::kValue);
         type_args = load_type_args;
@@ -2624,7 +2668,7 @@
 }
 
 static bool InlineGrowableArraySetter(FlowGraph* flow_graph,
-                                      intptr_t offset,
+                                      const Slot& field,
                                       StoreBarrierType store_barrier_type,
                                       Instruction* call,
                                       Definition* receiver,
@@ -2640,9 +2684,9 @@
   (*entry)->InheritDeoptTarget(Z, call);
 
   // This is an internal method, no need to check argument types.
-  StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
-      offset, new (Z) Value(array), new (Z) Value(value), store_barrier_type,
-      call->token_pos());
+  StoreInstanceFieldInstr* store = new (Z)
+      StoreInstanceFieldInstr(field, new (Z) Value(array), new (Z) Value(value),
+                              store_barrier_type, call->token_pos());
   flow_graph->AppendTo(*entry, store, call->env(), FlowGraph::kEffect);
   *last = store;
 
@@ -2660,8 +2704,8 @@
   ASSERT(array_cid != kDynamicCid);
 
   LoadFieldInstr* length = new (Z) LoadFieldInstr(
-      new (Z) Value(array),
-      NativeFieldDesc::GetLengthFieldForArrayCid(array_cid), call->token_pos());
+      new (Z) Value(array), Slot::GetLengthFieldForArrayCid(array_cid),
+      call->token_pos());
   *cursor = flow_graph->AppendTo(*cursor, length, NULL, FlowGraph::kValue);
 
   intptr_t element_size = Instance::ElementSizeFor(array_cid);
@@ -3072,9 +3116,9 @@
                                               Definition* str,
                                               Definition* index,
                                               Instruction* cursor) {
-  LoadFieldInstr* length = new (Z) LoadFieldInstr(
-      new (Z) Value(str), NativeFieldDesc::GetLengthFieldForArrayCid(cid),
-      str->token_pos());
+  LoadFieldInstr* length = new (Z)
+      LoadFieldInstr(new (Z) Value(str), Slot::GetLengthFieldForArrayCid(cid),
+                     str->token_pos());
   cursor = flow_graph->AppendTo(cursor, length, NULL, FlowGraph::kValue);
 
   // Bounds check.
@@ -3811,16 +3855,16 @@
       ASSERT(call->IsStaticCall() ||
              (ic_data == NULL || ic_data->NumberOfChecksIs(1)));
       return InlineGrowableArraySetter(
-          flow_graph, GrowableObjectArray::data_offset(), kEmitStoreBarrier,
-          call, receiver, graph_entry, entry, last);
+          flow_graph, Slot::GrowableObjectArray_data(), kEmitStoreBarrier, call,
+          receiver, graph_entry, entry, last);
     case MethodRecognizer::kGrowableArraySetLength:
       ASSERT((receiver_cid == kGrowableObjectArrayCid) ||
              ((receiver_cid == kDynamicCid) && call->IsStaticCall()));
       ASSERT(call->IsStaticCall() ||
              (ic_data == NULL || ic_data->NumberOfChecksIs(1)));
       return InlineGrowableArraySetter(
-          flow_graph, GrowableObjectArray::length_offset(), kNoStoreBarrier,
-          call, receiver, graph_entry, entry, last);
+          flow_graph, Slot::GrowableObjectArray_length(), kNoStoreBarrier, call,
+          receiver, graph_entry, entry, last);
     case MethodRecognizer::kSmi_bitAndFromSmi:
       return InlineSmiBitAndFromSmi(flow_graph, call, receiver, graph_entry,
                                     entry, last);
diff --git a/runtime/vm/compiler/backend/inliner.h b/runtime/vm/compiler/backend/inliner.h
index 1ca172f..a516847 100644
--- a/runtime/vm/compiler/backend/inliner.h
+++ b/runtime/vm/compiler/backend/inliner.h
@@ -68,7 +68,7 @@
  private:
   bool IsBlacklisted(intptr_t id) const {
     for (intptr_t i = 0; i < inlining_blacklist_.length(); ++i) {
-      if (inlining_blacklist_[i] != id) return true;
+      if (inlining_blacklist_[i] == id) return true;
     }
     return false;
   }
diff --git a/runtime/vm/compiler/backend/loops.cc b/runtime/vm/compiler/backend/loops.cc
index 42e656e..394da9e 100644
--- a/runtime/vm/compiler/backend/loops.cc
+++ b/runtime/vm/compiler/backend/loops.cc
@@ -11,11 +11,624 @@
 
 namespace dart {
 
+// Private class to perform induction variable analysis on a single loop
+// or a full loop hierarchy. The analysis implementation is based on the
+// paper by M. Gerlek et al. "Beyond Induction Variables: Detecting and
+// Classifying Sequences Using a Demand-Driven SSA Form" (ACM Transactions
+// on Programming Languages and Systems, Volume 17 Issue 1, Jan. 1995).
+//
+// The algorithm discovers and classifies definitions within loops that
+// behave like induction variables, and attaches an InductionVar record
+// to it (this mapping is stored in the loop data structure). The algorithm
+// first finds strongly connected components in the flow graph and classifies
+// each component as an induction when possible. Due to the descendant-first
+// nature, classification happens "on-demand" (e.g. basic induction is
+// classified before derived induction).
+class InductionVarAnalysis : public ValueObject {
+ public:
+  // Constructor to set up analysis phase.
+  explicit InductionVarAnalysis(const GrowableArray<BlockEntryInstr*>& preorder)
+      : preorder_(preorder),
+        stack_(),
+        scc_(),
+        cycle_(),
+        map_(),
+        current_index_(0),
+        zone_(Thread::Current()->zone()) {}
+
+  // Detects induction variables on the full loop hierarchy.
+  void VisitHierarchy(LoopInfo* loop);
+
+  // Detects induction variables on a single loop.
+  void VisitLoop(LoopInfo* loop);
+
+ private:
+  // An information node needed during SCC traversal that can
+  // reside in a map without any explicit memory allocation.
+  struct SCCInfo {
+    SCCInfo() : depth(-1), done(false) {}
+    explicit SCCInfo(intptr_t d) : depth(d), done(false) {}
+    intptr_t depth;
+    bool done;
+    bool operator!=(const SCCInfo& other) const {
+      return depth != other.depth || done != other.done;
+    }
+    bool operator==(const SCCInfo& other) const {
+      return depth == other.depth && done == other.done;
+    }
+  };
+  typedef RawPointerKeyValueTrait<Definition, SCCInfo> VisitKV;
+
+  // Traversal methods.
+  bool Visit(LoopInfo* loop, Definition* def);
+  intptr_t VisitDescendant(LoopInfo* loop, Definition* def);
+  void Classify(LoopInfo* loop, Definition* def);
+  void ClassifySCC(LoopInfo* loop);
+
+  // Transfer methods. Computes how induction of the operands, if any,
+  // tranfers over the operation performed by the given definition.
+  InductionVar* TransferPhi(LoopInfo* loop, Definition* def, intptr_t idx = -1);
+  InductionVar* TransferBinary(LoopInfo* loop, Definition* def);
+  InductionVar* TransferUnary(LoopInfo* loop, Definition* def);
+
+  // Solver methods. Computes how temporary meaning given to the
+  // definitions in a cycle transfer over the operation performed
+  // by the given definition.
+  InductionVar* SolvePhi(LoopInfo* loop, Definition* def, intptr_t idx = -1);
+  InductionVar* SolveBinary(LoopInfo* loop,
+                            Definition* def,
+                            InductionVar* init);
+  InductionVar* SolveUnary(LoopInfo* loop, Definition* def, InductionVar* init);
+
+  // Lookup.
+  InductionVar* Lookup(LoopInfo* loop, Definition* def);
+  InductionVar* LookupCycle(Definition* def);
+
+  // Arithmetic.
+  InductionVar* Add(InductionVar* x, InductionVar* y);
+  InductionVar* Sub(InductionVar* x, InductionVar* y);
+  InductionVar* Mul(InductionVar* x, InductionVar* y);
+
+  // Bookkeeping data (released when analysis goes out of scope).
+  const GrowableArray<BlockEntryInstr*>& preorder_;
+  GrowableArray<Definition*> stack_;
+  GrowableArray<Definition*> scc_;
+  DirectChainedHashMap<LoopInfo::InductionKV> cycle_;
+  DirectChainedHashMap<VisitKV> map_;
+  intptr_t current_index_;
+  Zone* zone_;
+
+  DISALLOW_COPY_AND_ASSIGN(InductionVarAnalysis);
+};
+
+// Helper method that finds phi-index of the initial value
+// that comes from a block outside the loop. Note that the
+// algorithm still works if there are several of these.
+static intptr_t InitIndex(LoopInfo* loop) {
+  BlockEntryInstr* header = loop->header();
+  for (intptr_t i = 0; i < header->PredecessorCount(); ++i) {
+    if (!loop->Contains(header->PredecessorAt(i))) {  // pick first
+      return i;
+    }
+  }
+  UNREACHABLE();
+  return -1;
+}
+
+// Helper method that determines if a definition is a constant.
+static bool IsConstant(Definition* def, int64_t* val) {
+  if (def->IsConstant()) {
+    const Object& value = def->AsConstant()->value();
+    if (value.IsInteger()) {
+      *val = Integer::Cast(value).AsInt64Value();  // smi and mint
+      return true;
+    }
+  }
+  return false;
+}
+
+void InductionVarAnalysis::VisitHierarchy(LoopInfo* loop) {
+  for (; loop != nullptr; loop = loop->next_) {
+    VisitLoop(loop);
+    VisitHierarchy(loop->inner_);
+  }
+}
+
+void InductionVarAnalysis::VisitLoop(LoopInfo* loop) {
+  loop->ResetInduction();
+  // Find strongly connected components (SSCs) in the SSA graph of this
+  // loop using Tarjan's algorithm. Due to the descendant-first nature,
+  // classification happens "on-demand".
+  current_index_ = 0;
+  ASSERT(stack_.is_empty());
+  ASSERT(map_.IsEmpty());
+  for (BitVector::Iterator it(loop->blocks_); !it.Done(); it.Advance()) {
+    BlockEntryInstr* block = preorder_[it.Current()];
+    ASSERT(block->loop_info() != nullptr);
+    if (block->loop_info() != loop) {
+      continue;  // inner loop
+    }
+    // Visit phi-operations.
+    if (block->IsJoinEntry()) {
+      for (PhiIterator it(block->AsJoinEntry()); !it.Done(); it.Advance()) {
+        Visit(loop, it.Current());
+      }
+    }
+    // Visit instructions.
+    for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
+      Visit(loop, it.Current()->AsDefinition());
+    }
+  }
+  ASSERT(stack_.is_empty());
+  map_.Clear();
+}
+
+bool InductionVarAnalysis::Visit(LoopInfo* loop, Definition* def) {
+  if (def == nullptr || map_.HasKey(def)) {
+    return false;  // no def, or already visited
+  }
+  intptr_t d = ++current_index_;
+  map_.Insert(VisitKV::Pair(def, SCCInfo(d)));
+  stack_.Add(def);
+
+  // Visit all descendants.
+  intptr_t low = d;
+  for (intptr_t i = 0, n = def->InputCount(); i < n; i++) {
+    Value* input = def->InputAt(i);
+    if (input != nullptr) {
+      low = Utils::Minimum(low, VisitDescendant(loop, input->definition()));
+    }
+  }
+
+  // Lower or found SCC?
+  if (low < d) {
+    map_.Lookup(def)->value.depth = low;
+  } else {
+    // Pop the stack to build the SCC for classification.
+    ASSERT(scc_.is_empty());
+    while (!stack_.is_empty()) {
+      Definition* top = stack_.RemoveLast();
+      scc_.Add(top);
+      map_.Lookup(top)->value.done = true;
+      if (top == def) {
+        break;
+      }
+    }
+    // Classify.
+    if (scc_.length() == 1) {
+      Classify(loop, scc_[0]);
+    } else {
+      ASSERT(scc_.length() > 1);
+      ASSERT(cycle_.IsEmpty());
+      ClassifySCC(loop);
+      cycle_.Clear();
+    }
+    scc_.Clear();
+  }
+  return true;
+}
+
+intptr_t InductionVarAnalysis::VisitDescendant(LoopInfo* loop,
+                                               Definition* def) {
+  // The traversal stops at anything not defined in this loop
+  // (either a loop invariant entry value defined outside the
+  // loop or an inner exit value defined by an inner loop).
+  if (def->GetBlock()->loop_info() != loop) {
+    return current_index_;
+  }
+  // Inspect descendant node.
+  if (!Visit(loop, def) && map_.Lookup(def)->value.done) {
+    return current_index_;
+  }
+  return map_.Lookup(def)->value.depth;
+}
+
+void InductionVarAnalysis::Classify(LoopInfo* loop, Definition* def) {
+  // Classify different kind of instructions.
+  InductionVar* induc = nullptr;
+  if (loop->IsHeaderPhi(def)) {
+    intptr_t idx = InitIndex(loop);
+    induc = TransferPhi(loop, def, idx);
+    if (induc != nullptr) {
+      InductionVar* init = Lookup(loop, def->InputAt(idx)->definition());
+      // Wrap-around (except for unusual header phi(x,..,x) = x).
+      if (!init->IsEqual(induc)) {
+        induc =
+            new (zone_) InductionVar(InductionVar::kWrapAround, init, induc);
+      }
+    }
+  } else if (def->IsPhi()) {
+    induc = TransferPhi(loop, def);
+  } else if (def->IsRedefinition() || def->IsConstraint() || def->IsBox() ||
+             def->IsUnbox()) {
+    induc = Lookup(loop, def->InputAt(0)->definition());  // pass-through
+  } else if (def->IsBinaryIntegerOp()) {
+    induc = TransferBinary(loop, def);
+  } else if (def->IsUnaryIntegerOp()) {
+    induc = TransferUnary(loop, def);
+  }
+  // Successfully classified?
+  if (induc != nullptr) {
+    loop->AddInduction(def, induc);
+  }
+}
+
+void InductionVarAnalysis::ClassifySCC(LoopInfo* loop) {
+  intptr_t size = scc_.length();
+  // Find a header phi, usually at the end.
+  intptr_t p = -1;
+  for (intptr_t i = size - 1; i >= 0; i--) {
+    if (loop->IsHeaderPhi(scc_[i])) {
+      p = i;
+      break;
+    }
+  }
+  // Rotate header phi up front.
+  if (p >= 0) {
+    Definition* phi = scc_[p];
+    intptr_t idx = InitIndex(loop);
+    InductionVar* init = Lookup(loop, phi->InputAt(idx)->definition());
+    // Inspect remainder of the cycle. The cycle mapping assigns temporary
+    // meaning to instructions, seeded from the phi instruction and back.
+    // The init of the phi is passed as marker token to detect first use.
+    cycle_.Insert(LoopInfo::InductionKV::Pair(phi, init));
+    for (intptr_t i = 1, j = p; i < size; i++) {
+      if (++j >= size) j = 0;
+      Definition* def = scc_[j];
+      InductionVar* update = nullptr;
+      if (def->IsPhi()) {
+        update = SolvePhi(loop, def);
+      } else if (def->IsRedefinition() || def->IsConstraint() || def->IsBox() ||
+                 def->IsUnbox()) {
+        update = LookupCycle(def->InputAt(0)->definition());  // pass-through
+      } else if (def->IsBinaryIntegerOp()) {
+        update = SolveBinary(loop, def, init);
+      } else if (def->IsUnaryIntegerOp()) {
+        update = SolveUnary(loop, def, init);
+      }
+      // Continue cycle?
+      if (update == nullptr) {
+        return;
+      }
+      cycle_.Insert(LoopInfo::InductionKV::Pair(def, update));
+    }
+    // Success if all internal links (inputs to the phi that are along
+    // back-edges) received the same temporary meaning. The external
+    // link (initial value coming from outside the loop) is excluded
+    // while taking this join.
+    InductionVar* induc = SolvePhi(loop, phi, idx);
+    if (induc != nullptr) {
+      // Invariant means linear induction.
+      if (induc->kind_ == InductionVar::kInvariant) {
+        induc = new (zone_) InductionVar(InductionVar::kLinear, init, induc);
+      } else {
+        ASSERT(induc->kind_ == InductionVar::kPeriodic);
+      }
+      // Classify first phi and then the rest of the cycle "on-demand".
+      loop->AddInduction(phi, induc);
+      for (intptr_t i = 1, j = p; i < size; i++) {
+        if (++j >= size) j = 0;
+        Classify(loop, scc_[j]);
+      }
+    }
+  }
+}
+
+InductionVar* InductionVarAnalysis::TransferPhi(LoopInfo* loop,
+                                                Definition* def,
+                                                intptr_t idx) {
+  InductionVar* induc = nullptr;
+  for (intptr_t i = 0, n = def->InputCount(); i < n; i++) {
+    if (i != idx) {
+      InductionVar* x = Lookup(loop, def->InputAt(i)->definition());
+      if (x == nullptr) {
+        return nullptr;
+      } else if (induc == nullptr) {
+        induc = x;
+      } else if (!induc->IsEqual(x)) {
+        return nullptr;
+      }
+    }
+  }
+  return induc;
+}
+
+InductionVar* InductionVarAnalysis::TransferBinary(LoopInfo* loop,
+                                                   Definition* def) {
+  InductionVar* x = Lookup(loop, def->InputAt(0)->definition());
+  InductionVar* y = Lookup(loop, def->InputAt(1)->definition());
+  switch (def->AsBinaryIntegerOp()->op_kind()) {
+    case Token::kADD:
+      return Add(x, y);
+    case Token::kSUB:
+      return Sub(x, y);
+    case Token::kMUL:
+      return Mul(x, y);
+    default:
+      return nullptr;
+  }
+}
+
+InductionVar* InductionVarAnalysis::TransferUnary(LoopInfo* loop,
+                                                  Definition* def) {
+  InductionVar* x = Lookup(loop, def->InputAt(0)->definition());
+  switch (def->AsUnaryIntegerOp()->op_kind()) {
+    case Token::kNEGATE: {
+      InductionVar* zero = new (zone_) InductionVar(0);
+      return Sub(zero, x);
+    }
+    default:
+      return nullptr;
+  }
+}
+
+InductionVar* InductionVarAnalysis::SolvePhi(LoopInfo* loop,
+                                             Definition* def,
+                                             intptr_t idx) {
+  InductionVar* induc = nullptr;
+  for (intptr_t i = 0, n = def->InputCount(); i < n; i++) {
+    if (i != idx) {
+      InductionVar* c = LookupCycle(def->InputAt(i)->definition());
+      if (c == nullptr) {
+        return nullptr;
+      } else if (induc == nullptr) {
+        induc = c;
+      } else if (!induc->IsEqual(c)) {
+        return nullptr;
+      }
+    }
+  }
+  return induc;
+}
+
+InductionVar* InductionVarAnalysis::SolveBinary(LoopInfo* loop,
+                                                Definition* def,
+                                                InductionVar* init) {
+  InductionVar* x = Lookup(loop, def->InputAt(0)->definition());
+  InductionVar* y = Lookup(loop, def->InputAt(1)->definition());
+  switch (def->AsBinaryIntegerOp()->op_kind()) {
+    case Token::kADD:
+      if (InductionVar::IsInvariant(x)) {
+        InductionVar* c = LookupCycle(def->InputAt(1)->definition());
+        // The init marker denotes first use, otherwise aggregate.
+        if (c == init) {
+          return x;
+        } else if (InductionVar::IsInvariant(c)) {
+          return Add(x, c);
+        }
+      }
+      if (InductionVar::IsInvariant(y)) {
+        InductionVar* c = LookupCycle(def->InputAt(0)->definition());
+        // The init marker denotes first use, otherwise aggregate.
+        if (c == init) {
+          return y;
+        } else if (InductionVar::IsInvariant(c)) {
+          return Add(c, y);
+        }
+      }
+      break;
+    case Token::kSUB:
+      if (InductionVar::IsInvariant(x)) {
+        InductionVar* c = LookupCycle(def->InputAt(1)->definition());
+        // Note that i = x - i is periodic. The temporary
+        // meaning is expressed in terms of the header phi.
+        if (c == init) {
+          InductionVar* next = Sub(x, init);
+          if (InductionVar::IsInvariant(next)) {
+            return new (zone_)
+                InductionVar(InductionVar::kPeriodic, init, next);
+          }
+        }
+      }
+      if (InductionVar::IsInvariant(y)) {
+        InductionVar* c = LookupCycle(def->InputAt(0)->definition());
+        // The init marker denotes first use, otherwise aggregate.
+        if (c == init) {
+          InductionVar* zero = new (zone_) InductionVar(0);
+          return Sub(zero, y);
+        } else if (InductionVar::IsInvariant(c)) {
+          return Sub(c, y);
+        }
+      }
+      break;
+    default:
+      break;
+  }
+  return nullptr;
+}
+
+InductionVar* InductionVarAnalysis::SolveUnary(LoopInfo* loop,
+                                               Definition* def,
+                                               InductionVar* init) {
+  switch (def->AsUnaryIntegerOp()->op_kind()) {
+    case Token::kNEGATE: {
+      InductionVar* c = LookupCycle(def->InputAt(0)->definition());
+      // Note that i = - i is periodic. The temporary
+      // meaning is expressed in terms of the header phi.
+      if (c == init) {
+        InductionVar* zero = new (zone_) InductionVar(0);
+        InductionVar* next = Sub(zero, init);
+        if (InductionVar::IsInvariant(next)) {
+          return new (zone_) InductionVar(InductionVar::kPeriodic, init, next);
+        }
+      }
+      return nullptr;
+    }
+    default:
+      return nullptr;
+  }
+}
+
+InductionVar* InductionVarAnalysis::Lookup(LoopInfo* loop, Definition* def) {
+  InductionVar* induc = loop->LookupInduction(def);
+  if (induc == nullptr) {
+    // Loop-invariants are added lazily.
+    if (!loop->Contains(def->GetBlock())) {
+      int64_t val = 0;
+      if (IsConstant(def, &val)) {
+        induc = new (zone_) InductionVar(val);
+      } else {
+        induc = new (zone_) InductionVar(0, 1, def);
+      }
+      loop->AddInduction(def, induc);
+    }
+  }
+  return induc;
+}
+
+InductionVar* InductionVarAnalysis::LookupCycle(Definition* def) {
+  LoopInfo::InductionKV::Pair* pair = cycle_.Lookup(def);
+  if (pair != nullptr) {
+    return pair->value;
+  }
+  return nullptr;
+}
+
+InductionVar* InductionVarAnalysis::Add(InductionVar* x, InductionVar* y) {
+  if (InductionVar::IsInvariant(x)) {
+    if (InductionVar::IsInvariant(y)) {
+      // Invariant + Invariant : only for same or just one instruction.
+      if (x->def_ == y->def_) {
+        return new (zone_)
+            InductionVar(x->offset_ + y->offset_, x->mult_ + y->mult_, x->def_);
+      } else if (y->mult_ == 0) {
+        return new (zone_)
+            InductionVar(x->offset_ + y->offset_, x->mult_, x->def_);
+      } else if (x->mult_ == 0) {
+        return new (zone_)
+            InductionVar(x->offset_ + y->offset_, y->mult_, y->def_);
+      }
+    } else if (y != nullptr) {
+      // Invariant + Induction.
+      InductionVar* i = Add(x, y->initial_);
+      InductionVar* n =
+          y->kind_ == InductionVar::kLinear ? y->next_ : Add(x, y->next_);
+      if (i != nullptr && n != nullptr) {
+        return new (zone_) InductionVar(y->kind_, i, n);
+      }
+    }
+  } else if (InductionVar::IsInvariant(y)) {
+    if (x != nullptr) {
+      // Induction + Invariant.
+      ASSERT(!InductionVar::IsInvariant(x));
+      InductionVar* i = Add(x->initial_, y);
+      InductionVar* n =
+          x->kind_ == InductionVar::kLinear ? x->next_ : Add(x->next_, y);
+      if (i != nullptr && n != nullptr) {
+        return new (zone_) InductionVar(x->kind_, i, n);
+      }
+    }
+  } else if (InductionVar::IsLinear(x) && InductionVar::IsLinear(y)) {
+    // Linear + Linear.
+    InductionVar* i = Add(x->initial_, y->initial_);
+    InductionVar* n = Add(x->next_, y->next_);
+    if (i != nullptr && n != nullptr) {
+      return new (zone_) InductionVar(InductionVar::kLinear, i, n);
+    }
+  }
+  return nullptr;
+}
+
+InductionVar* InductionVarAnalysis::Sub(InductionVar* x, InductionVar* y) {
+  if (InductionVar::IsInvariant(x)) {
+    if (InductionVar::IsInvariant(y)) {
+      // Invariant + Invariant : only for same or just one instruction.
+      if (x->def_ == y->def_) {
+        return new (zone_)
+            InductionVar(x->offset_ - y->offset_, x->mult_ - y->mult_, x->def_);
+      } else if (y->mult_ == 0) {
+        return new (zone_)
+            InductionVar(x->offset_ - y->offset_, x->mult_, x->def_);
+      } else if (x->mult_ == 0) {
+        return new (zone_)
+            InductionVar(x->offset_ - y->offset_, -y->mult_, y->def_);
+      }
+    } else if (y != nullptr) {
+      // Invariant - Induction.
+      InductionVar* i = Sub(x, y->initial_);
+      InductionVar* n;
+      if (y->kind_ == InductionVar::kLinear) {
+        InductionVar* zero = new (zone_) InductionVar(0, 0, nullptr);
+        n = Sub(zero, y->next_);
+      } else {
+        n = Sub(x, y->next_);
+      }
+      if (i != nullptr && n != nullptr) {
+        return new (zone_) InductionVar(y->kind_, i, n);
+      }
+    }
+  } else if (InductionVar::IsInvariant(y)) {
+    if (x != nullptr) {
+      // Induction - Invariant.
+      ASSERT(!InductionVar::IsInvariant(x));
+      InductionVar* i = Sub(x->initial_, y);
+      InductionVar* n =
+          x->kind_ == InductionVar::kLinear ? x->next_ : Sub(x->next_, y);
+      if (i != nullptr && n != nullptr) {
+        return new (zone_) InductionVar(x->kind_, i, n);
+      }
+    }
+  } else if (InductionVar::IsLinear(x) && InductionVar::IsLinear(y)) {
+    // Linear - Linear.
+    InductionVar* i = Sub(x->initial_, y->initial_);
+    InductionVar* n = Sub(x->next_, y->next_);
+    if (i != nullptr && n != nullptr) {
+      return new (zone_) InductionVar(InductionVar::kLinear, i, n);
+    }
+  }
+  return nullptr;
+}
+
+InductionVar* InductionVarAnalysis::Mul(InductionVar* x, InductionVar* y) {
+  // Swap constant left.
+  if (!InductionVar::IsConstant(x)) {
+    InductionVar* tmp = x;
+    x = y;
+    y = tmp;
+  }
+  // Apply constant to any induction.
+  if (InductionVar::IsConstant(x) && y != nullptr) {
+    if (y->kind_ == InductionVar::kInvariant) {
+      return new (zone_)
+          InductionVar(x->offset_ * y->offset_, x->offset_ * y->mult_, y->def_);
+    }
+    return new (zone_)
+        InductionVar(y->kind_, Mul(x, y->initial_), Mul(x, y->next_));
+  }
+  return nullptr;
+}
+
+const char* InductionVar::ToCString() const {
+  char buffer[1024];
+  BufferFormatter f(buffer, sizeof(buffer));
+  switch (kind_) {
+    case kInvariant:
+      if (mult_ != 0) {
+        f.Print("(%" Pd64 " + %" Pd64 " x %.4s)", offset_, mult_,
+                def_->ToCString());
+      } else {
+        f.Print("%" Pd64, offset_);
+      }
+      break;
+    case kLinear:
+      f.Print("LIN(%s + %s * i)", initial_->ToCString(), next_->ToCString());
+      break;
+    case kWrapAround:
+      f.Print("WRAP(%s, %s)", initial_->ToCString(), next_->ToCString());
+      break;
+    case kPeriodic:
+      f.Print("PERIOD(%s, %s)", initial_->ToCString(), next_->ToCString());
+      break;
+  }
+  return Thread::Current()->zone()->MakeCopyOfString(buffer);
+}
+
 LoopInfo::LoopInfo(intptr_t id, BlockEntryInstr* header, BitVector* blocks)
     : id_(id),
       header_(header),
       blocks_(blocks),
       back_edges_(),
+      induction_(),
       outer_(nullptr),
       inner_(nullptr),
       next_(nullptr) {}
@@ -37,13 +650,22 @@
   return false;
 }
 
-bool LoopInfo::IsIn(LoopInfo* other) const {
-  if (other != nullptr) {
-    return other->blocks_->Contains(header_->preorder_number());
+bool LoopInfo::IsHeaderPhi(Instruction* instr) const {
+  return instr->IsPhi() && instr->GetBlock() == header_ &&
+         !instr->AsPhi()->IsRedundant();  // phi(x,..,x) = x
+}
+
+bool LoopInfo::IsIn(LoopInfo* loop) const {
+  if (loop != nullptr) {
+    return loop->Contains(header_);
   }
   return false;
 }
 
+bool LoopInfo::Contains(BlockEntryInstr* block) const {
+  return blocks_->Contains(block->preorder_number());
+}
+
 intptr_t LoopInfo::NestingDepth() const {
   intptr_t nesting_depth = 1;
   for (LoopInfo* o = outer_; o != nullptr; o = o->outer()) {
@@ -52,6 +674,22 @@
   return nesting_depth;
 }
 
+void LoopInfo::ResetInduction() {
+  induction_.Clear();
+}
+
+void LoopInfo::AddInduction(Definition* def, InductionVar* induc) {
+  induction_.Insert(InductionKV::Pair(def, induc));
+}
+
+InductionVar* LoopInfo::LookupInduction(Definition* def) const {
+  InductionKV::Pair* pair = induction_.Lookup(def);
+  if (pair != nullptr) {
+    return pair->value;
+  }
+  return nullptr;
+}
+
 const char* LoopInfo::ToCString() const {
   char buffer[1024];
   BufferFormatter f(buffer, sizeof(buffer));
@@ -83,7 +721,7 @@
   // Link every entry block to the closest enveloping loop.
   for (intptr_t i = 0, n = headers_->length(); i < n; ++i) {
     LoopInfo* loop = (*headers_)[i]->loop_info();
-    for (BitVector::Iterator it(loop->blocks()); !it.Done(); it.Advance()) {
+    for (BitVector::Iterator it(loop->blocks_); !it.Done(); it.Advance()) {
       BlockEntryInstr* block = preorder_[it.Current()];
       if (block->loop_info() == nullptr) {
         block->set_loop_info(loop);
@@ -110,14 +748,14 @@
   }
   // If tracing is requested, print the loop hierarchy.
   if (FLAG_trace_optimization) {
-    Print(top());
+    Print(top_);
   }
 }
 
 void LoopHierarchy::Print(LoopInfo* loop) {
   for (; loop != nullptr; loop = loop->next_) {
     THR_Print("%s {", loop->ToCString());
-    for (BitVector::Iterator it(loop->blocks()); !it.Done(); it.Advance()) {
+    for (BitVector::Iterator it(loop->blocks_); !it.Done(); it.Advance()) {
       THR_Print(" B%" Pd, preorder_[it.Current()]->block_id());
     }
     THR_Print(" }\n");
@@ -125,6 +763,10 @@
   }
 }
 
+void LoopHierarchy::ComputeInduction() const {
+  InductionVarAnalysis(preorder_).VisitHierarchy(top_);
+}
+
 }  // namespace dart
 
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/backend/loops.h b/runtime/vm/compiler/backend/loops.h
index 555f69f..1d5b45a 100644
--- a/runtime/vm/compiler/backend/loops.h
+++ b/runtime/vm/compiler/backend/loops.h
@@ -10,6 +10,116 @@
 
 namespace dart {
 
+// Information on an induction variable in a particular loop.
+//
+// Invariant:
+//     offset + mult * def
+// Linear:
+//     initial + next * i, for invariant initial and next,
+//                       and a "normalized" loop index i
+// Wrap-around:
+//     initial then next, for invariant initial and any next
+// Periodic:
+//     alternate initial and next, for invariant initial and next
+//
+class InductionVar : public ZoneAllocated {
+ public:
+  enum Kind {
+    kInvariant,
+    kLinear,
+    kWrapAround,
+    kPeriodic,
+  };
+
+  // Constructor for an invariant.
+  InductionVar(int64_t offset, int64_t mult, Definition* def)
+      : kind_(kInvariant), offset_(offset), mult_(mult), def_(def) {}
+
+  // Constructor for a constant.
+  explicit InductionVar(int64_t offset) : InductionVar(offset, 0, nullptr) {}
+
+  // Constructor for induction.
+  InductionVar(Kind kind, InductionVar* initial, InductionVar* next)
+      : kind_(kind), initial_(initial), next_(next) {
+    ASSERT(IsInvariant(initial));
+    switch (kind) {
+      case kLinear:
+      case kPeriodic:
+        ASSERT(IsInvariant(next));
+        break;
+      case kWrapAround:
+        ASSERT(next != nullptr);
+        break;
+      default:
+        UNREACHABLE();
+    }
+  }
+
+  // Returns true if the other induction is structually equivalent.
+  bool IsEqual(InductionVar* other) const {
+    ASSERT(other != nullptr);
+    if (kind_ == other->kind_) {
+      switch (kind_) {
+        case kInvariant:
+          return offset_ == other->offset_ && mult_ == other->mult_ &&
+                 (mult_ == 0 || def_ == other->def_);
+        case kLinear:
+        case kWrapAround:
+        case kPeriodic:
+          return initial_->IsEqual(other->initial_) &&
+                 next_->IsEqual(other->next_);
+      }
+    }
+    return false;
+  }
+
+  // For debugging.
+  const char* ToCString() const;
+
+  // Returns true if x is invariant.
+  static bool IsInvariant(InductionVar* x) {
+    return x != nullptr && x->kind_ == kInvariant;
+  }
+
+  // Returns true if x is a constant (and invariant).
+  static bool IsConstant(InductionVar* x) {
+    return x != nullptr && x->kind_ == kInvariant && x->mult_ == 0;
+  }
+
+  // Returns true if x is linear.
+  static bool IsLinear(InductionVar* x) {
+    return x != nullptr && x->kind_ == kLinear;
+  }
+
+  // Returns true if x is wrap-around.
+  static bool IsWrapAround(InductionVar* x) {
+    return x != nullptr && x->kind_ == kWrapAround;
+  }
+
+  // Returns true if x is periodic.
+  static bool IsPeriodic(InductionVar* x) {
+    return x != nullptr && x->kind_ == kPeriodic;
+  }
+
+ private:
+  friend class InductionVarAnalysis;
+
+  const Kind kind_;
+  union {
+    struct {
+      int64_t offset_;
+      int64_t mult_;
+      Definition* def_;
+    };
+    struct {
+      InductionVar* initial_;
+      InductionVar* next_;
+    };
+  };
+
+  DISALLOW_COPY_AND_ASSIGN(InductionVar);
+};
+
 // Information on a "natural loop" in the flow graph.
 class LoopInfo : public ZoneAllocated {
  public:
@@ -24,12 +134,27 @@
   // Returns true if given block is backedge of this loop.
   bool IsBackEdge(BlockEntryInstr* block) const;
 
-  // Returns true if this loop is nested inside other loop.
-  bool IsIn(LoopInfo* other) const;
+  // Returns true if given instruction is a header phi for this loop.
+  bool IsHeaderPhi(Instruction* instr) const;
+
+  // Returns true if this loop is nested inside given loop.
+  bool IsIn(LoopInfo* loop) const;
+
+  // Returns true if this loop contains given block.
+  bool Contains(BlockEntryInstr* block) const;
 
   // Returns the nesting depth of this loop.
   intptr_t NestingDepth() const;
 
+  // Resets induction.
+  void ResetInduction();
+
+  // Assigns induction to a definition.
+  void AddInduction(Definition* def, InductionVar* induc);
+
+  // Looks up induction.
+  InductionVar* LookupInduction(Definition* def) const;
+
   // Getters.
   intptr_t id() const { return id_; }
   BlockEntryInstr* header() const { return header_; }
@@ -43,8 +168,11 @@
   const char* ToCString() const;
 
  private:
+  friend class InductionVarAnalysis;
   friend class LoopHierarchy;
 
+  typedef RawPointerKeyValueTrait<Definition, InductionVar*> InductionKV;
+
   // Unique id of loop. We use its index in the
   // loop header array for this.
   const intptr_t id_;
@@ -59,6 +187,9 @@
   // Back edges of loop (usually one).
   GrowableArray<BlockEntryInstr*> back_edges_;
 
+  // Map instruction -> induction for this loop.
+  DirectChainedHashMap<InductionKV> induction_;
+
   // Loop hierarchy.
   LoopInfo* outer_;
   LoopInfo* inner_;
@@ -82,6 +213,9 @@
   // Returns total number of loops in the hierarchy.
   intptr_t num_loops() const { return headers_->length(); }
 
+  // Performs induction variable analysis on all loops.
+  void ComputeInduction() const;
+
  private:
   void Build();
   void Print(LoopInfo* loop);
diff --git a/runtime/vm/compiler/backend/loops_test.cc b/runtime/vm/compiler/backend/loops_test.cc
new file mode 100644
index 0000000..8b27faa
--- /dev/null
+++ b/runtime/vm/compiler/backend/loops_test.cc
@@ -0,0 +1,323 @@
+// 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.
+//
+// Unit tests specific to loops and induction variables.
+// Note, try to avoid relying on information that is subject
+// to change (block ids, variable numbers, etc.) in order
+// to make this test less sensitive to unrelated changes.
+
+#include "vm/compiler/backend/loops.h"
+#include "vm/compiler/backend/il_printer.h"
+#include "vm/compiler/backend/inliner.h"
+#include "vm/compiler/backend/type_propagator.h"
+#include "vm/compiler/compiler_pass.h"
+#include "vm/compiler/frontend/kernel_to_il.h"
+#include "vm/compiler/jit/jit_call_specializer.h"
+#include "vm/log.h"
+#include "vm/object.h"
+#include "vm/parser.h"
+#include "vm/symbols.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+// Helper method to construct an induction debug string for loop hierarchy.
+void TestString(BufferFormatter* f,
+                LoopInfo* loop,
+                const GrowableArray<BlockEntryInstr*>& preorder) {
+  for (; loop != nullptr; loop = loop->next()) {
+    intptr_t depth = loop->NestingDepth();
+    f->Print("%*c[%" Pd "\n", static_cast<int>(2 * depth), ' ', loop->id());
+    for (BitVector::Iterator block_it(loop->blocks()); !block_it.Done();
+         block_it.Advance()) {
+      BlockEntryInstr* block = preorder[block_it.Current()];
+      if (block->IsJoinEntry()) {
+        for (PhiIterator it(block->AsJoinEntry()); !it.Done(); it.Advance()) {
+          InductionVar* induc = loop->LookupInduction(it.Current());
+          if (induc != nullptr) {
+            f->Print("%*c%s\n", static_cast<int>(2 * depth), ' ',
+                     induc->ToCString());
+          }
+        }
+      }
+      for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
+        InductionVar* induc =
+            loop->LookupInduction(it.Current()->AsDefinition());
+        if (induc != nullptr) {
+          f->Print("%*c%s\n", static_cast<int>(2 * depth), ' ',
+                   induc->ToCString());
+        }
+      }
+    }
+    TestString(f, loop->inner(), preorder);
+    f->Print("%*c]\n", static_cast<int>(2 * depth), ' ');
+  }
+}
+
+// Helper method to build CFG and compute induction.
+static const char* ComputeInduction(Thread* thread, const char* script_chars) {
+  // Invoke the script.
+  Dart_Handle script = TestCase::LoadTestScript(script_chars, NULL);
+  Dart_Handle result = Dart_Invoke(script, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+
+  // Find parsed function "foo".
+  TransitionNativeToVM transition(thread);
+  Zone* zone = thread->zone();
+  Library& lib =
+      Library::ZoneHandle(Library::RawCast(Api::UnwrapHandle(script)));
+  RawFunction* raw_func =
+      lib.LookupLocalFunction(String::Handle(Symbols::New(thread, "foo")));
+  ParsedFunction* parsed_function =
+      new (zone) ParsedFunction(thread, Function::ZoneHandle(zone, raw_func));
+  EXPECT(parsed_function != nullptr);
+
+  // Build flow graph.
+  CompilerState state(thread);
+  ZoneGrowableArray<const ICData*>* ic_data_array =
+      new (zone) ZoneGrowableArray<const ICData*>();
+  parsed_function->function().RestoreICDataMap(ic_data_array, true);
+  kernel::FlowGraphBuilder builder(parsed_function, ic_data_array, nullptr,
+                                   nullptr, true, DeoptId::kNone);
+  FlowGraph* flow_graph = builder.BuildGraph();
+  EXPECT(flow_graph != nullptr);
+
+  // Setup some pass data structures and perform minimum passes.
+  SpeculativeInliningPolicy speculative_policy(/*enable_blacklist*/ false);
+  CompilerPassState pass_state(thread, flow_graph, &speculative_policy);
+  JitCallSpecializer call_specializer(flow_graph, &speculative_policy);
+  pass_state.call_specializer = &call_specializer;
+  flow_graph->ComputeSSA(0, nullptr);
+  FlowGraphTypePropagator::Propagate(flow_graph);
+  call_specializer.ApplyICData();
+
+  // Build loop hierarchy and find induction.
+  const LoopHierarchy& hierarchy = flow_graph->GetLoopHierarchy();
+  hierarchy.ComputeInduction();
+  flow_graph->RemoveRedefinitions();  // don't query later
+
+  // Construct and return a debug string for testing.
+  char buffer[1024];
+  BufferFormatter f(buffer, sizeof(buffer));
+  TestString(&f, hierarchy.top(), flow_graph->preorder());
+  return Thread::Current()->zone()->MakeCopyOfString(buffer);
+}
+
+TEST_CASE(BasicInduction) {
+  const char* script_chars =
+      "foo() {\n"
+      "  for (int i = 0; i < 100; i++) {\n"
+      "  }\n"
+      "}\n"
+      "main() {\n"
+      "  foo();\n"
+      "}\n";
+  const char* expected =
+      "  [0\n"
+      "  LIN(0 + 1 * i)\n"  // phi
+      "  LIN(1 + 1 * i)\n"  // add
+      "  ]\n";
+  EXPECT_STREQ(expected, ComputeInduction(thread, script_chars));
+}
+
+TEST_CASE(BasicInductionStepUp) {
+  const char* script_chars =
+      "foo() {\n"
+      "  for (int i = 10; i < 100; i += 2) {\n"
+      "  }\n"
+      "}\n"
+      "main() {\n"
+      "  foo();\n"
+      "}\n";
+  const char* expected =
+      "  [0\n"
+      "  LIN(10 + 2 * i)\n"  // phi
+      "  LIN(12 + 2 * i)\n"  // add
+      "  ]\n";
+  EXPECT_STREQ(expected, ComputeInduction(thread, script_chars));
+}
+
+TEST_CASE(BasicInductionStepDown) {
+  const char* script_chars =
+      "foo() {\n"
+      "  for (int i = 100; i >= 0; i -= 7) {\n"
+      "  }\n"
+      "}\n"
+      "main() {\n"
+      "  foo();\n"
+      "}\n";
+  const char* expected =
+      "  [0\n"
+      "  LIN(100 + -7 * i)\n"  // phi
+      "  LIN(93 + -7 * i)\n"   // add
+      "  ]\n";
+  EXPECT_STREQ(expected, ComputeInduction(thread, script_chars));
+}
+
+TEST_CASE(BasicInductionLoopNest) {
+  const char* script_chars =
+      "foo() {\n"
+      "  for (int i = 0; i < 100; i++) {\n"
+      "    for (int j = 1; j < 100; j++) {\n"
+      "      for (int k = 2; k < 100; k++) {\n"
+      "      }\n"
+      "    }\n"
+      "  }\n"
+      "}\n"
+      "main() {\n"
+      "  foo();\n"
+      "}\n";
+  const char* expected =
+      "  [2\n"
+      "  LIN(0 + 1 * i)\n"  // i
+      "  LIN(1 + 1 * i)\n"
+      "    [1\n"
+      "    LIN(1 + 1 * i)\n"  // j
+      "    LIN(2 + 1 * i)\n"
+      "      [0\n"
+      "      LIN(2 + 1 * i)\n"  // k
+      "      LIN(3 + 1 * i)\n"
+      "      ]\n"
+      "    ]\n"
+      "  ]\n";
+  EXPECT_STREQ(expected, ComputeInduction(thread, script_chars));
+}
+
+TEST_CASE(ChainInduction) {
+  const char* script_chars =
+      "foo() {\n"
+      "  int j = 1;\n"
+      "  for (int i = 0; i < 100; i++) {\n"
+      "    j += 5;\n"
+      "    j += 7;\n"
+      "  }\n"
+      "}\n"
+      "main() {\n"
+      "  foo();\n"
+      "}\n";
+  const char* expected =
+      "  [0\n"
+      "  LIN(1 + 12 * i)\n"   // phi (j)
+      "  LIN(0 + 1 * i)\n"    // phi
+      "  LIN(6 + 12 * i)\n"   // j-add
+      "  LIN(13 + 12 * i)\n"  // j-add
+      "  LIN(1 + 1 * i)\n"    // add
+      "  ]\n";
+  EXPECT_STREQ(expected, ComputeInduction(thread, script_chars));
+}
+
+TEST_CASE(TwoWayInduction) {
+  const char* script_chars =
+      "foo() {\n"
+      "  int j = 123;\n"
+      "  for (int i = 0; i < 100; i++) {\n"
+      "     if (i == 10) {\n"
+      "       j += 3;\n"
+      "     } else {\n"
+      "       j += 3;\n"
+      "     }\n"
+      "  }\n"
+      "}\n"
+      "main() {\n"
+      "  foo();\n"
+      "}\n";
+  const char* expected =
+      "  [0\n"
+      "  LIN(123 + 3 * i)\n"  // phi (j)
+      "  LIN(0 + 1 * i)\n"    // phi
+      "  LIN(126 + 3 * i)\n"  // j-true
+      "  LIN(126 + 3 * i)\n"  // j-false
+      "  LIN(1 + 1 * i)\n"    // add
+      "  LIN(126 + 3 * i)\n"  // phi (j)
+      "  ]\n";
+  EXPECT_STREQ(expected, ComputeInduction(thread, script_chars));
+}
+
+TEST_CASE(DerivedInduction) {
+  const char* script_chars =
+      "foo() {\n"
+      "  for (int i = 1; i < 100; i++) {\n"
+      "    int a = i + 3;\n"
+      "    int b = i - 5;\n"
+      "    int c = i * 7;\n"
+      "    int d = - i;\n"
+      "  }\n"
+      "}\n"
+      "main() {\n"
+      "  foo();\n"
+      "}\n";
+  const char* expected =
+      "  [0\n"
+      "  LIN(1 + 1 * i)\n"    // phi
+      "  LIN(4 + 1 * i)\n"    // a
+      "  LIN(-4 + 1 * i)\n"   // b
+      "  LIN(7 + 7 * i)\n"    // c
+      "  LIN(-1 + -1 * i)\n"  // d
+      "  LIN(2 + 1 * i)\n"    // add
+      "  ]\n";
+  EXPECT_STREQ(expected, ComputeInduction(thread, script_chars));
+}
+
+TEST_CASE(WrapAroundAndDerived) {
+  const char* script_chars =
+      "foo() {\n"
+      "  int w = 99;\n"
+      "  for (int i = 0; i < 100; i++) {\n"
+      "    int a = w + 3;\n"
+      "    int b = w - 5;\n"
+      "    int c = w * 7;\n"
+      "    int d = - w;\n"
+      "    w = i;\n"
+      "  }\n"
+      "}\n"
+      "main() {\n"
+      "  foo();\n"
+      "}\n";
+  const char* expected =
+      "  [0\n"
+      "  WRAP(99, LIN(0 + 1 * i))\n"    // phi (w)
+      "  LIN(0 + 1 * i)\n"              // phi
+      "  WRAP(102, LIN(3 + 1 * i))\n"   // a
+      "  WRAP(94, LIN(-5 + 1 * i))\n"   // b
+      "  WRAP(693, LIN(0 + 7 * i))\n"   // c
+      "  WRAP(-99, LIN(0 + -1 * i))\n"  // d
+      "  LIN(1 + 1 * i)\n"              // add
+      "  ]\n";
+  EXPECT_STREQ(ComputeInduction(thread, script_chars), expected);
+}
+
+TEST_CASE(PeriodicAndDerived) {
+  const char* script_chars =
+      "foo() {\n"
+      "  int p1 = 3;\n"
+      "  int p2 = 5;\n"
+      "  for (int i = 0; i < 100; i++) {\n"
+      "    int a = p1 + 3;\n"
+      "    int b = p1 - 5;\n"
+      "    int c = p1 * 7;\n"
+      "    int d = - p1;\n"
+      "    p1 = - p1;\n"
+      "    p2 = 100 - p2;\n"
+      "  }\n"
+      "}\n"
+      "main() {\n"
+      "  foo();\n"
+      "}\n";
+  const char* expected =
+      "  [0\n"
+      "  PERIOD(3, -3)\n"    // phi(p1)
+      "  PERIOD(5, 95)\n"    // phi(p2)
+      "  LIN(0 + 1 * i)\n"   // phi
+      "  PERIOD(6, 0)\n"     // a
+      "  PERIOD(-2, -8)\n"   // b
+      "  PERIOD(21, -21)\n"  // c
+      "  PERIOD(-3, 3)\n"    // d
+      "  PERIOD(-3, 3)\n"    // p1
+      "  PERIOD(95, 5)\n"    // p2
+      "  LIN(1 + 1 * i)\n"   // add
+      "  ]\n";
+  EXPECT_STREQ(ComputeInduction(thread, script_chars), expected);
+}
+
+}  // namespace dart
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index c2a4bef..5b50229 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2707,43 +2707,55 @@
 }
 
 void LoadFieldInstr::InferRange(RangeAnalysis* analysis, Range* range) {
-  if (native_field() != nullptr) {
-    switch (native_field()->kind()) {
-      case NativeFieldDesc::kArray_length:
-      case NativeFieldDesc::kGrowableObjectArray_length:
-        *range = Range(RangeBoundary::FromConstant(0),
-                       RangeBoundary::FromConstant(Array::kMaxElements));
-        break;
+  switch (slot().kind()) {
+    case Slot::Kind::kArray_length:
+    case Slot::Kind::kGrowableObjectArray_length:
+      *range = Range(RangeBoundary::FromConstant(0),
+                     RangeBoundary::FromConstant(Array::kMaxElements));
+      break;
 
-      case NativeFieldDesc::kTypedData_length:
-        *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
-        break;
+    case Slot::Kind::kTypedData_length:
+      *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
+      break;
 
-      case NativeFieldDesc::kString_length:
-        *range = Range(RangeBoundary::FromConstant(0),
-                       RangeBoundary::FromConstant(String::kMaxElements));
-        break;
+    case Slot::Kind::kString_length:
+      *range = Range(RangeBoundary::FromConstant(0),
+                     RangeBoundary::FromConstant(String::kMaxElements));
+      break;
 
-      case NativeFieldDesc::kLinkedHashMap_index:
-      case NativeFieldDesc::kLinkedHashMap_data:
-      case NativeFieldDesc::kTypeArguments:
-        // Not an integer valued field.
-        UNREACHABLE();
-        break;
+    case Slot::Kind::kDartField:
+    case Slot::Kind::kCapturedVariable:
+      // Use default value.
+      Definition::InferRange(analysis, range);
+      break;
 
-      case NativeFieldDesc::kLinkedHashMap_hash_mask:
-      case NativeFieldDesc::kLinkedHashMap_used_data:
-      case NativeFieldDesc::kLinkedHashMap_deleted_keys:
-        *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
-        break;
+    case Slot::Kind::kLinkedHashMap_index:
+    case Slot::Kind::kLinkedHashMap_data:
+    case Slot::Kind::kGrowableObjectArray_data:
+    case Slot::Kind::kContext_parent:
+    case Slot::Kind::kTypeArguments:
+    case Slot::Kind::kClosure_context:
+    case Slot::Kind::kClosure_delayed_type_arguments:
+    case Slot::Kind::kClosure_function:
+    case Slot::Kind::kClosure_function_type_arguments:
+    case Slot::Kind::kClosure_instantiator_type_arguments:
+      // Not an integer valued field.
+      UNREACHABLE();
+      break;
 
-      case NativeFieldDesc::kArgumentsDescriptor_type_args_len:
-        *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
-        break;
-    }
-    return;
+    case Slot::Kind::kClosure_hash:
+    case Slot::Kind::kLinkedHashMap_hash_mask:
+    case Slot::Kind::kLinkedHashMap_used_data:
+    case Slot::Kind::kLinkedHashMap_deleted_keys:
+      *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
+      break;
+
+    case Slot::Kind::kArgumentsDescriptor_type_args_len:
+    case Slot::Kind::kArgumentsDescriptor_positional_count:
+    case Slot::Kind::kArgumentsDescriptor_count:
+      *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
+      break;
   }
-  Definition::InferRange(analysis, range);
 }
 
 void LoadIndexedInstr::InferRange(RangeAnalysis* analysis, Range* range) {
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index f8f5ec8..f3d89f5 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -58,8 +58,10 @@
 // We distinguish the following aliases:
 //
 //   - for fields
-//     - *.f, *.@offs - field inside some object;
-//     - X.f, X.@offs - field inside an allocated object X;
+//     - *.f - field inside some object;
+//     - X.f - field inside an allocated object X;
+//     -   f - static fields
+//
 //   - for indexed accesses
 //     - *[*] - non-constant index inside some object;
 //     - *[C] - constant index inside some object;
@@ -103,14 +105,13 @@
   enum Kind {
     kNone,
 
-    // Field location. For instance fields is represented as a pair of a Field
-    // object and an instance (SSA definition) that is being accessed.
-    // For static fields instance is NULL.
-    kField,
+    // Static field location. Is represented as a Field object with a
+    // nullptr instance.
+    kStaticField,
 
-    // VMField location. Represented as a pair of an instance (SSA definition)
-    // being accessed and offset to the field.
-    kVMField,
+    // Instance field location. It is reprensented by a pair of instance
+    // and a Slot.
+    kInstanceField,
 
     // Indexed location with a non-constant index.
     kIndexed,
@@ -158,19 +159,14 @@
   // Construct a place from instruction if instruction accesses any place.
   // Otherwise constructs kNone place.
   Place(Instruction* instr, bool* is_load, bool* is_store)
-      : flags_(0), instance_(NULL), raw_selector_(0), id_(0) {
+      : flags_(0), instance_(nullptr), raw_selector_(0), id_(0) {
     switch (instr->tag()) {
       case Instruction::kLoadField: {
         LoadFieldInstr* load_field = instr->AsLoadField();
         set_representation(load_field->representation());
         instance_ = load_field->instance()->definition()->OriginalDefinition();
-        if (load_field->field() != NULL) {
-          set_kind(kField);
-          field_ = load_field->field();
-        } else {
-          set_kind(kVMField);
-          offset_in_bytes_ = load_field->offset_in_bytes();
-        }
+        set_kind(kInstanceField);
+        instance_field_ = &load_field->slot();
         *is_load = true;
         break;
       }
@@ -180,30 +176,25 @@
         set_representation(store->RequiredInputRepresentation(
             StoreInstanceFieldInstr::kValuePos));
         instance_ = store->instance()->definition()->OriginalDefinition();
-        if (!store->field().IsNull()) {
-          set_kind(kField);
-          field_ = &store->field();
-        } else {
-          set_kind(kVMField);
-          offset_in_bytes_ = store->offset_in_bytes();
-        }
+        set_kind(kInstanceField);
+        instance_field_ = &store->slot();
         *is_store = true;
         break;
       }
 
       case Instruction::kLoadStaticField:
-        set_kind(kField);
+        set_kind(kStaticField);
         set_representation(instr->AsLoadStaticField()->representation());
-        field_ = &instr->AsLoadStaticField()->StaticField();
+        static_field_ = &instr->AsLoadStaticField()->StaticField();
         *is_load = true;
         break;
 
       case Instruction::kStoreStaticField:
-        set_kind(kField);
+        set_kind(kStaticField);
         set_representation(
             instr->AsStoreStaticField()->RequiredInputRepresentation(
                 StoreStaticFieldInstr::kValuePos));
-        field_ = &instr->AsStoreStaticField()->field();
+        static_field_ = &instr->AsStoreStaticField()->field();
         *is_store = true;
         break;
 
@@ -233,6 +224,18 @@
     }
   }
 
+  bool IsConstant(Object* value) const {
+    switch (kind()) {
+      case kInstanceField:
+        return (instance() != nullptr) && instance()->IsConstant() &&
+               LoadFieldInstr::TryEvaluateLoad(
+                   instance()->AsConstant()->constant_value(), instance_field(),
+                   value);
+      default:
+        return false;
+    }
+  }
+
   // Create object representing *[*] alias.
   static Place* CreateAnyInstanceAnyIndexAlias(Zone* zone, intptr_t id) {
     return Wrap(
@@ -264,12 +267,12 @@
 
   bool DependsOnInstance() const {
     switch (kind()) {
-      case kField:
-      case kVMField:
+      case kInstanceField:
       case kIndexed:
       case kConstantIndexed:
         return true;
 
+      case kStaticField:
       case kNone:
         return false;
     }
@@ -325,14 +328,15 @@
     instance_ = def->OriginalDefinition();
   }
 
-  const Field& field() const {
-    ASSERT(kind() == kField);
-    return *field_;
+  const Field& static_field() const {
+    ASSERT(kind() == kStaticField);
+    ASSERT(static_field_->is_static());
+    return *static_field_;
   }
 
-  intptr_t offset_in_bytes() const {
-    ASSERT(kind() == kVMField);
-    return offset_in_bytes_;
+  const Slot& instance_field() const {
+    ASSERT(kind() == kInstanceField);
+    return *instance_field_;
   }
 
   Definition* index() const {
@@ -361,19 +365,16 @@
       case kNone:
         return "<none>";
 
-      case kField: {
-        const char* field_name = String::Handle(field().name()).ToCString();
-        if (field().is_static()) {
-          return Thread::Current()->zone()->PrintToString("<%s>", field_name);
-        } else {
-          return Thread::Current()->zone()->PrintToString(
-              "<%s.%s>", DefinitionName(instance()), field_name);
-        }
+      case kStaticField: {
+        const char* field_name =
+            String::Handle(static_field().name()).ToCString();
+        return Thread::Current()->zone()->PrintToString("<%s>", field_name);
       }
 
-      case kVMField:
+      case kInstanceField:
         return Thread::Current()->zone()->PrintToString(
-            "<%s.@%" Pd ">", DefinitionName(instance()), offset_in_bytes());
+            "<%s.%s[%p]>", DefinitionName(instance()), instance_field().Name(),
+            &instance_field());
 
       case kIndexed:
         return Thread::Current()->zone()->PrintToString(
@@ -397,8 +398,14 @@
   // Handle static finals as non-final with precompilation because
   // they may be reset to uninitialized after compilation.
   bool IsImmutableField() const {
-    return (kind() == kField) && field().is_final() &&
-           (!field().is_static() || !FLAG_fields_may_be_reset);
+    switch (kind()) {
+      case kInstanceField:
+        return instance_field().is_immutable();
+      case kStaticField:
+        return static_field().is_final() && !FLAG_fields_may_be_reset;
+      default:
+        return false;
+    }
   }
 
   intptr_t Hashcode() const {
@@ -427,14 +434,16 @@
       : flags_(flags), instance_(instance), raw_selector_(selector), id_(0) {}
 
   bool SameField(const Place* other) const {
-    return (kind() == kField)
-               ? (field().Original() == other->field().Original())
-               : (offset_in_bytes_ == other->offset_in_bytes_);
+    return (kind() == kStaticField)
+               ? (static_field().Original() == other->static_field().Original())
+               : (raw_selector_ == other->raw_selector_);
   }
 
   intptr_t FieldHashcode() const {
-    return (kind() == kField) ? reinterpret_cast<intptr_t>(field().Original())
-                              : offset_in_bytes_;
+    return (kind() == kStaticField)
+               ? String::Handle(Field::Handle(static_field().Original()).name())
+                     .Hash()
+               : raw_selector_;
   }
 
   void set_representation(Representation rep) {
@@ -549,8 +558,8 @@
   Definition* instance_;
   union {
     intptr_t raw_selector_;
-    const Field* field_;
-    intptr_t offset_in_bytes_;
+    const Field* static_field_;
+    const Slot* instance_field_;
     intptr_t index_constant_;
     Definition* index_;
   };
@@ -907,10 +916,13 @@
         }
         break;
 
-      case Place::kField:
-      case Place::kVMField:
+      case Place::kStaticField:
+        // Nothing to do.
+        break;
+
+      case Place::kInstanceField:
         if (CanBeAliased(alias->instance())) {
-          // X.f or X.@offs alias with *.f and *.@offs respectively.
+          // X.f alias with *.f.
           CrossAlias(alias, alias->CopyWithoutInstance());
         }
         break;
@@ -925,30 +937,16 @@
   // occur in other functions.
   bool IsIndependentFromEffects(Place* place) {
     if (place->IsImmutableField()) {
-      // Note that we can't use LoadField's is_immutable attribute here because
-      // some VM-fields (those that have no corresponding Field object and
-      // accessed through offset alone) can share offset but have different
-      // immutability properties.
-      // One example is the length property of growable and fixed size list. If
-      // loads of these two properties occur in the same function for the same
-      // receiver then they will get the same expression number. However
-      // immutability of the length of fixed size list does not mean that
-      // growable list also has immutable property. Thus we will make a
-      // conservative assumption for the VM-properties.
-      // TODO(vegorov): disambiguate immutable and non-immutable VM-fields with
-      // the same offset e.g. through recognized kind.
       return true;
     }
 
-    return ((place->kind() == Place::kField) ||
-            (place->kind() == Place::kVMField)) &&
+    return (place->kind() == Place::kInstanceField) &&
            !CanBeAliased(place->instance());
   }
 
   // Returns true if there are direct loads from the given place.
   bool HasLoadsFromPlace(Definition* defn, const Place* place) {
-    ASSERT((place->kind() == Place::kField) ||
-           (place->kind() == Place::kVMField));
+    ASSERT(place->kind() == Place::kInstanceField);
 
     for (Value* use = defn->input_use_list(); use != NULL;
          use = use->next_use()) {
@@ -1127,8 +1125,7 @@
 }
 
 static bool IsPhiDependentPlace(Place* place) {
-  return ((place->kind() == Place::kField) ||
-          (place->kind() == Place::kVMField)) &&
+  return (place->kind() == Place::kInstanceField) &&
          (place->instance() != NULL) && place->instance()->IsPhi();
 }
 
@@ -1589,13 +1586,13 @@
         }
 
         // For object allocation forward initial values of the fields to
-        // subsequent loads. For skip final fields.  Final fields are
-        // initialized in constructor that potentially can be not inlined into
-        // the function that we are currently optimizing. However at the same
-        // time we assume that values of the final fields can be forwarded
-        // across side-effects. If we add 'null' as known values for these
-        // fields here we will incorrectly propagate this null across
-        // constructor invocation.
+        // subsequent loads except for final fields of escaping objects.
+        // Final fields are initialized in constructor which potentially was
+        // not inlined into the function that we are currently optimizing.
+        // However at the same time we assume that values of the final fields
+        // can be forwarded across side-effects. If we add 'null' as known
+        // values for these fields here we will incorrectly propagate this
+        // null across constructor invocation.
         AllocateObjectInstr* alloc = instr->AsAllocateObject();
         if ((alloc != NULL)) {
           for (Value* use = alloc->input_use_list(); use != NULL;
@@ -1610,10 +1607,10 @@
               // Found a load. Initialize current value of the field to null for
               // normal fields, or with type arguments.
 
-              // Forward for all fields for non-escaping objects and only
-              // non-final fields and type arguments for escaping ones.
+              // If the object escapes then don't forward final fields - see
+              // the comment above for explanation.
               if (aliased_set_->CanBeAliased(alloc) &&
-                  (load->field() != NULL) && load->field()->is_final()) {
+                  load->slot().IsDartField() && load->slot().is_immutable()) {
                 continue;
               }
 
@@ -1622,7 +1619,8 @@
                 ASSERT(alloc->ArgumentCount() == 1);
                 intptr_t type_args_offset =
                     alloc->cls().type_arguments_field_offset();
-                if (load->offset_in_bytes() == type_args_offset) {
+                if (load->slot().IsTypeArguments() &&
+                    load->slot().offset_in_bytes() == type_args_offset) {
                   forward_def = alloc->PushArgumentAt(0)->value()->definition();
                 }
               }
@@ -2937,12 +2935,9 @@
 }
 
 // Add a field/offset to the list of fields if it is not yet present there.
-static bool AddSlot(ZoneGrowableArray<const Object*>* slots,
-                    const Object& slot) {
-  ASSERT(slot.IsSmi() || slot.IsField());
-  ASSERT(!slot.IsField() || Field::Cast(slot).IsOriginal());
-  for (intptr_t i = 0; i < slots->length(); i++) {
-    if ((*slots)[i]->raw() == slot.raw()) {
+static bool AddSlot(ZoneGrowableArray<const Slot*>* slots, const Slot& slot) {
+  for (auto s : *slots) {
+    if (s == &slot) {
       return false;
     }
   }
@@ -2993,7 +2988,7 @@
 void AllocationSinking::CreateMaterializationAt(
     Instruction* exit,
     Definition* alloc,
-    const ZoneGrowableArray<const Object*>& slots) {
+    const ZoneGrowableArray<const Slot*>& slots) {
   ZoneGrowableArray<Value*>* values =
       new (Z) ZoneGrowableArray<Value*>(slots.length());
 
@@ -3003,20 +2998,14 @@
   Instruction* load_point = FirstMaterializationAt(exit);
 
   // Insert load instruction for every field.
-  for (intptr_t i = 0; i < slots.length(); i++) {
+  for (auto slot : slots) {
     LoadFieldInstr* load =
-        slots[i]->IsField()
-            ? new (Z) LoadFieldInstr(
-                  new (Z) Value(alloc), &Field::Cast(*slots[i]),
-                  AbstractType::ZoneHandle(Z), alloc->token_pos(), NULL)
-            : new (Z) LoadFieldInstr(
-                  new (Z) Value(alloc), Smi::Cast(*slots[i]).Value(),
-                  AbstractType::ZoneHandle(Z), alloc->token_pos());
-    flow_graph_->InsertBefore(load_point, load, NULL, FlowGraph::kValue);
+        new (Z) LoadFieldInstr(new (Z) Value(alloc), *slot, alloc->token_pos());
+    flow_graph_->InsertBefore(load_point, load, nullptr, FlowGraph::kValue);
     values->Add(new (Z) Value(load));
   }
 
-  MaterializeObjectInstr* mat = NULL;
+  MaterializeObjectInstr* mat = nullptr;
   if (alloc->IsAllocateObject()) {
     mat = new (Z)
         MaterializeObjectInstr(alloc->AsAllocateObject(), slots, values);
@@ -3026,7 +3015,7 @@
         alloc->AsAllocateUninitializedContext(), slots, values);
   }
 
-  flow_graph_->InsertBefore(exit, mat, NULL, FlowGraph::kValue);
+  flow_graph_->InsertBefore(exit, mat, nullptr, FlowGraph::kValue);
 
   // Replace all mentions of this allocation with a newly inserted
   // MaterializeObject instruction.
@@ -3112,27 +3101,21 @@
 
 void AllocationSinking::InsertMaterializations(Definition* alloc) {
   // Collect all fields that are written for this instance.
-  ZoneGrowableArray<const Object*>* slots =
-      new (Z) ZoneGrowableArray<const Object*>(5);
+  auto slots = new (Z) ZoneGrowableArray<const Slot*>(5);
 
   for (Value* use = alloc->input_use_list(); use != NULL;
        use = use->next_use()) {
     StoreInstanceFieldInstr* store = use->instruction()->AsStoreInstanceField();
     if ((store != NULL) && (store->instance()->definition() == alloc)) {
-      if (!store->field().IsNull()) {
-        AddSlot(slots, Field::ZoneHandle(Z, store->field().Original()));
-      } else {
-        AddSlot(slots, Smi::ZoneHandle(Z, Smi::New(store->offset_in_bytes())));
-      }
+      AddSlot(slots, store->slot());
     }
   }
 
   if (alloc->ArgumentCount() > 0) {
     AllocateObjectInstr* alloc_object = alloc->AsAllocateObject();
     ASSERT(alloc_object->ArgumentCount() == 1);
-    intptr_t type_args_offset =
-        alloc_object->cls().type_arguments_field_offset();
-    AddSlot(slots, Smi::ZoneHandle(Z, Smi::New(type_args_offset)));
+    AddSlot(slots, Slot::GetTypeArgumentsSlotFor(flow_graph_->thread(),
+                                                 alloc_object->cls()));
   }
 
   // Collect all instructions that mention this object in the environment.
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.h b/runtime/vm/compiler/backend/redundancy_elimination.h
index 0e9e1dd..f759073 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.h
+++ b/runtime/vm/compiler/backend/redundancy_elimination.h
@@ -64,7 +64,7 @@
 
   void CreateMaterializationAt(Instruction* exit,
                                Definition* alloc,
-                               const ZoneGrowableArray<const Object*>& fields);
+                               const ZoneGrowableArray<const Slot*>& fields);
 
   void EliminateAllocation(Definition* alloc);
 
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
new file mode 100644
index 0000000..ebc0c53
--- /dev/null
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -0,0 +1,201 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/compiler/backend/slot.h"
+
+#ifndef DART_PRECOMPILED_RUNTIME
+
+#include "vm/compiler/compiler_state.h"
+#include "vm/hash_map.h"
+#include "vm/parser.h"
+#include "vm/scopes.h"
+
+namespace dart {
+
+// Canonicalization cache for Slot objects.
+//
+// This cache is attached to the CompilerState to ensure that we preserve
+// identity of Slot objects during each individual compilation.
+class SlotCache : public ZoneAllocated {
+ public:
+  // Returns an instance of SlotCache for the current compilation.
+  static SlotCache& Instance(Thread* thread) {
+    auto result = thread->compiler_state().slot_cache();
+    if (result == nullptr) {
+      result = new (thread->zone()) SlotCache(thread);
+      thread->compiler_state().set_slot_cache(result);
+    }
+    return *result;
+  }
+
+  const Slot& Canonicalize(const Slot& value) {
+    auto result = fields_.LookupValue(&value);
+    if (result == nullptr) {
+      result = new (zone_) Slot(value);
+      fields_.Insert(result);
+    }
+    return *result;
+  }
+
+ private:
+  explicit SlotCache(Thread* thread)
+      : zone_(thread->zone()), fields_(thread->zone()) {}
+
+  Zone* const zone_;
+  DirectChainedHashMap<PointerKeyValueTrait<const Slot> > fields_;
+};
+
+const Slot& Slot::GetNativeSlot(Kind kind) {
+  // There is a fixed statically known number of native slots so we cache
+  // them statically.
+  static const Slot fields[] = {
+#define FIELD_FINAL (IsImmutableBit::encode(true))
+#define FIELD_VAR (0)
+#define DEFINE_NATIVE_FIELD(ClassName, FieldName, cid, mutability)             \
+  Slot(Kind::k##ClassName##_##FieldName, FIELD_##mutability, k##cid##Cid,      \
+       ClassName::FieldName##_offset(), #ClassName "." #FieldName, nullptr),
+
+      NATIVE_SLOTS_LIST(DEFINE_NATIVE_FIELD)
+
+#undef DEFINE_FIELD
+#undef FIELD_VAR
+#undef FIELD_FINAL
+  };
+
+  ASSERT(static_cast<uint8_t>(kind) < ARRAY_SIZE(fields));
+  return fields[static_cast<uint8_t>(kind)];
+}
+
+// Note: should only be called with cids of array-like classes.
+const Slot& Slot::GetLengthFieldForArrayCid(intptr_t array_cid) {
+  if (RawObject::IsExternalTypedDataClassId(array_cid) ||
+      RawObject::IsTypedDataClassId(array_cid)) {
+    return GetNativeSlot(Kind::kTypedData_length);
+  }
+
+  switch (array_cid) {
+    case kGrowableObjectArrayCid:
+      return GetNativeSlot(Kind::kGrowableObjectArray_length);
+
+    case kOneByteStringCid:
+    case kTwoByteStringCid:
+    case kExternalOneByteStringCid:
+    case kExternalTwoByteStringCid:
+      return GetNativeSlot(Kind::kString_length);
+
+    case kArrayCid:
+    case kImmutableArrayCid:
+      return GetNativeSlot(Kind::kArray_length);
+
+    default:
+      UNREACHABLE();
+      return GetNativeSlot(Kind::kArray_length);
+  }
+}
+
+const Slot& Slot::GetTypeArgumentsSlotAt(Thread* thread, intptr_t offset) {
+  ASSERT(offset != Class::kNoTypeArguments);
+  return SlotCache::Instance(thread).Canonicalize(Slot(
+      Kind::kTypeArguments, IsImmutableBit::encode(true), kTypeArgumentsCid,
+      offset, ":type_arguments", /*static_type=*/nullptr));
+}
+
+const Slot& Slot::GetTypeArgumentsSlotFor(Thread* thread, const Class& cls) {
+  return GetTypeArgumentsSlotAt(thread, cls.type_arguments_field_offset());
+}
+
+const Slot& Slot::GetContextVariableSlotFor(Thread* thread,
+                                            const LocalVariable& variable) {
+  ASSERT(variable.is_captured());
+  // TODO(vegorov) Can't assign static type to local variables because
+  // for captured parameters we generate the code that first stores a
+  // variable into the context and then loads it from the context to perform
+  // the type check.
+  return SlotCache::Instance(thread).Canonicalize(Slot(
+      Kind::kCapturedVariable,
+      IsImmutableBit::encode(variable.is_final()) | IsNullableBit::encode(true),
+      kDynamicCid, Context::variable_offset(variable.index().value()),
+      &variable.name(), /*static_type=*/nullptr));
+}
+
+const Slot& Slot::Get(const Field& field,
+                      const ParsedFunction* parsed_function) {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  intptr_t nullable_cid = kDynamicCid;
+  bool is_nullable = true;
+
+  if (thread->isolate()->use_field_guards() &&
+      field.guarded_cid() != kIllegalCid) {
+    ASSERT(parsed_function != nullptr);  // Need to record dependency.
+    nullable_cid = field.guarded_cid();
+    is_nullable = field.is_nullable();
+    parsed_function->AddToGuardedFields(&field);
+  }
+
+  return SlotCache::Instance(thread).Canonicalize(
+      Slot(Kind::kDartField,
+           IsImmutableBit::encode(field.is_final() || field.is_const()) |
+               IsNullableBit::encode(is_nullable),
+           nullable_cid, field.Offset(), &field,
+           &AbstractType::ZoneHandle(zone, field.type())));
+}
+
+CompileType Slot::ComputeCompileType() const {
+  return CompileType::CreateNullable(is_nullable(), nullable_cid());
+}
+
+const AbstractType& Slot::static_type() const {
+  return static_type_ != nullptr ? *static_type_ : Object::null_abstract_type();
+}
+
+const char* Slot::Name() const {
+  if (IsLocalVariable()) {
+    return DataAs<const String>()->ToCString();
+  } else if (IsDartField()) {
+    return String::Handle(field().name()).ToCString();
+  } else {
+    return DataAs<const char>();
+  }
+}
+
+bool Slot::Equals(const Slot* other) const {
+  if (kind_ != other->kind_) {
+    return false;
+  }
+
+  switch (kind_) {
+    case Kind::kTypeArguments:
+      return (offset_in_bytes_ == other->offset_in_bytes_);
+
+    case Kind::kCapturedVariable:
+      return (offset_in_bytes_ == other->offset_in_bytes_) &&
+             (flags_ == other->flags_) &&
+             (DataAs<const String>()->raw() ==
+              other->DataAs<const String>()->raw());
+
+    case Kind::kDartField:
+      return (offset_in_bytes_ == other->offset_in_bytes_) &&
+             other->DataAs<const Field>()->Original() ==
+                 DataAs<const Field>()->Original();
+
+    default:
+      UNREACHABLE();
+      return false;
+  }
+}
+
+intptr_t Slot::Hashcode() const {
+  intptr_t result = (static_cast<int8_t>(kind_) * 63 + offset_in_bytes_) * 31;
+  if (IsDartField()) {
+    result += String::Handle(DataAs<const Field>()->name()).Hash();
+  } else if (IsLocalVariable()) {
+    result += DataAs<const String>()->Hash();
+  }
+  return result;
+}
+
+}  // namespace dart
+
+#endif  // DART_PRECOMPILED_RUNTIME
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
new file mode 100644
index 0000000..aef5482
--- /dev/null
+++ b/runtime/vm/compiler/backend/slot.h
@@ -0,0 +1,214 @@
+// 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.
+
+// Slot is an abstraction that describes an readable (and possibly writeable)
+// location within an object.
+//
+// In general slots follow the memory model for normal Dart fields - but can
+// also be used to describe locations that don't have corresponding Field
+// object, i.e. fields within native objects like arrays or contexts.
+//
+// Slot objects created by the compiler have an identity. If two slots F and G
+// are different then compiler assumes that store into F can't alias a load
+// from G and vice versa.
+//
+// All slots can be split into 4 categories:
+//
+//   - slots for fields of native classes (Array, Closure, etc);
+//   - slots for type arguments;
+//   - slots for captured variable;
+//   - slots for normal Dart fields (e.g. those that Field object).
+//
+
+#ifndef RUNTIME_VM_COMPILER_BACKEND_SLOT_H_
+#define RUNTIME_VM_COMPILER_BACKEND_SLOT_H_
+
+#include "vm/compiler/backend/compile_type.h"
+#include "vm/thread.h"
+
+namespace dart {
+
+class LocalScope;
+class LocalVariable;
+class ParsedFunction;
+
+// List of slots that correspond to fields of native objects in the following
+// format:
+//
+//     V(class_name, field_name, exact_type, FINAL|VAR)
+//
+// - class_name and field_name specify the name of the host class and the name
+//   of the field respectively;
+// - exact_type specifies exact type of the field (any load from this field
+//   would only yield instances of this type);
+// - the last component specifies whether field behaves like a final field
+//   (i.e. initialized once at construction time and does not change after
+//   that) or like a non-final field.
+//
+// Note: native slots are expected to be non-nullable.
+#define NATIVE_SLOTS_LIST(V)                                                   \
+  V(Array, length, Smi, FINAL)                                                 \
+  V(Context, parent, Context, FINAL)                                           \
+  V(Closure, instantiator_type_arguments, TypeArguments, FINAL)                \
+  V(Closure, delayed_type_arguments, TypeArguments, FINAL)                     \
+  V(Closure, function_type_arguments, TypeArguments, FINAL)                    \
+  V(Closure, function, Function, FINAL)                                        \
+  V(Closure, context, Context, FINAL)                                          \
+  V(Closure, hash, Context, VAR)                                               \
+  V(GrowableObjectArray, length, Smi, VAR)                                     \
+  V(GrowableObjectArray, data, Array, VAR)                                     \
+  V(TypedData, length, Smi, FINAL)                                             \
+  V(String, length, Smi, FINAL)                                                \
+  V(LinkedHashMap, index, TypedDataUint32Array, VAR)                           \
+  V(LinkedHashMap, data, Array, VAR)                                           \
+  V(LinkedHashMap, hash_mask, Smi, VAR)                                        \
+  V(LinkedHashMap, used_data, Smi, VAR)                                        \
+  V(LinkedHashMap, deleted_keys, Smi, VAR)                                     \
+  V(ArgumentsDescriptor, type_args_len, Smi, FINAL)                            \
+  V(ArgumentsDescriptor, positional_count, Smi, FINAL)                         \
+  V(ArgumentsDescriptor, count, Smi, FINAL)
+
+// Slot is an abstraction that describes an readable (and possibly writeable)
+// location within an object.
+//
+// Slot objects returned by Slot::Get* methods have identity and can be
+// compared by pointer. If two slots are different they must not alias.
+// If two slots can alias - they must be represented by identical
+// slot object.
+class Slot : public ZoneAllocated {
+ public:
+  // clang-format off
+  enum class Kind : uint8_t {
+    // Native slots are identified by their kind - each native slot has its own.
+#define DECLARE_KIND(ClassName, FieldName, cid, mutability)                    \
+  k##ClassName##_##FieldName,
+    NATIVE_SLOTS_LIST(DECLARE_KIND)
+#undef DECLARE_KIND
+
+    // A slot used to store type arguments.
+    kTypeArguments,
+
+    // A slot within a Context object that contains a value of a captured
+    // local variable.
+    kCapturedVariable,
+
+    // A slot that corresponds to a Dart field (has corresponding Field object).
+    kDartField,
+  };
+  // clang-format on
+
+  // Returns a slot that represents length field for the given [array_cid].
+  static const Slot& GetLengthFieldForArrayCid(intptr_t array_cid);
+
+  // Return a slot that represents type arguments field at the given offset
+  // or for the given class.
+  //
+  // We do not distinguish type argument fields within disjoint
+  // class hierarchies: type argument fields at the same offset would be
+  // represented by the same Slot object. Type argument slots are final
+  // so disambiguating type arguments fields does not improve alias analysis.
+  static const Slot& GetTypeArgumentsSlotAt(Thread* thread, intptr_t offset);
+  static const Slot& GetTypeArgumentsSlotFor(Thread* thread, const Class& cls);
+
+  // Returns a slot that represents the given captured local variable.
+  static const Slot& GetContextVariableSlotFor(Thread* thread,
+                                               const LocalVariable& var);
+
+  // Returns a slot that represents the given Dart field.
+  static const Slot& Get(const Field& field,
+                         const ParsedFunction* parsed_function);
+
+  // Convenience getters for native slots.
+#define DEFINE_GETTER(ClassName, FieldName, cid, mutability)                   \
+  static const Slot& ClassName##_##FieldName() {                               \
+    return GetNativeSlot(Kind::k##ClassName##_##FieldName);                    \
+  }
+
+  NATIVE_SLOTS_LIST(DEFINE_GETTER)
+#undef DEFINE_GETTER
+
+  Kind kind() const { return kind_; }
+  bool IsDartField() const { return kind() == Kind::kDartField; }
+  bool IsLocalVariable() const { return kind() == Kind::kCapturedVariable; }
+  bool IsTypeArguments() const { return kind() == Kind::kTypeArguments; }
+
+  const char* Name() const;
+
+  intptr_t offset_in_bytes() const { return offset_in_bytes_; }
+
+  bool is_immutable() const { return IsImmutableBit::decode(flags_); }
+
+  intptr_t nullable_cid() const { return cid_; }
+  intptr_t is_nullable() const { return IsNullableBit::decode(flags_); }
+
+  // Static type of the slots if any.
+  //
+  // A value that is read from the slot is guaranteed to be assignable to its
+  // static type.
+  const AbstractType& static_type() const;
+
+  // More precise type information about values that can be read from this slot.
+  CompileType ComputeCompileType() const;
+
+  const Field& field() const {
+    ASSERT(IsDartField());
+    ASSERT(data_ != nullptr);
+    return *DataAs<const Field>();
+  }
+
+  bool Equals(const Slot* other) const;
+  intptr_t Hashcode() const;
+
+ private:
+  Slot(Kind kind,
+       int8_t bits,
+       int16_t cid,
+       intptr_t offset_in_bytes,
+       const void* data,
+       const AbstractType* static_type)
+      : kind_(kind),
+        flags_(bits),
+        cid_(cid),
+        offset_in_bytes_(offset_in_bytes),
+        data_(data),
+        static_type_(static_type) {}
+
+  Slot(const Slot& other)
+      : Slot(other.kind_,
+             other.flags_,
+             other.cid_,
+             other.offset_in_bytes_,
+             other.data_,
+             other.static_type_) {}
+
+  using IsImmutableBit = BitField<int8_t, bool, 0, 1>;
+  using IsNullableBit = BitField<int8_t, bool, 1, 1>;
+
+  template <typename T>
+  const T* DataAs() const {
+    return static_cast<const T*>(data_);
+  }
+
+  static const Slot& GetNativeSlot(Kind kind);
+
+  const Kind kind_;
+  const int8_t flags_;  // is_immutable, is_nullable
+  const int16_t cid_;   // Concrete cid of a value or kDynamicCid.
+
+  const intptr_t offset_in_bytes_;
+
+  // Kind dependent data:
+  //   - name as a Dart String object for local variables;
+  //   - name as a C string for native slots;
+  //   - Field object for Dart fields;
+  const void* data_;
+
+  const AbstractType* static_type_;
+
+  friend class SlotCache;
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_COMPILER_BACKEND_SLOT_H_
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 45f0f84..ed928f7 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -648,7 +648,11 @@
 }
 
 CompileType CompileType::Int() {
-  return FromAbstractType(Type::ZoneHandle(Type::Int64Type()), kNonNullable);
+  return FromAbstractType(Type::ZoneHandle(Type::IntType()), kNonNullable);
+}
+
+CompileType CompileType::NullableInt() {
+  return FromAbstractType(Type::ZoneHandle(Type::IntType()), kNullable);
 }
 
 CompileType CompileType::Smi() {
@@ -659,6 +663,10 @@
   return Create(kDoubleCid, Type::ZoneHandle(Type::Double()));
 }
 
+CompileType CompileType::NullableDouble() {
+  return FromAbstractType(Type::ZoneHandle(Type::Double()), kNullable);
+}
+
 CompileType CompileType::String() {
   return FromAbstractType(Type::ZoneHandle(Type::StringType()), kNonNullable);
 }
@@ -692,7 +700,7 @@
       cid_ = kNullCid;
     } else if (type_->IsFunctionType() || type_->IsDartFunctionType()) {
       cid_ = kClosureCid;
-    } else if (type_->HasResolvedTypeClass()) {
+    } else if (type_->type_class_id() != kIllegalCid) {
       const Class& type_class = Class::Handle(type_->type_class());
       Thread* thread = Thread::Current();
       CHA& cha = thread->compiler_state().cha();
@@ -965,7 +973,7 @@
     // Receiver can't be null but can be an instance of a subclass.
     intptr_t cid = kDynamicCid;
 
-    if (type.HasResolvedTypeClass()) {
+    if (type.type_class_id() != kIllegalCid) {
       Thread* thread = Thread::Current();
       const Class& type_class = Class::Handle(type.type_class());
       if (!CHA::HasSubclasses(type_class)) {
@@ -995,6 +1003,9 @@
     return CompileType(CompileType::kNonNullable, cid, &type);
   }
 
+  const bool is_unchecked_entry_param =
+      graph_entry->unchecked_entry() == block_;
+
   if (Isolate::Current()->can_use_strong_mode_types()) {
     LocalScope* scope = graph_entry->parsed_function().node_sequence()->scope();
     // Note: in catch-blocks we have ParameterInstr for each local variable
@@ -1014,7 +1025,9 @@
       }
       // If parameter type was checked by caller, then use Dart type annotation,
       // plus non-nullability from inferred type if known.
-      if (param->was_type_checked_by_caller()) {
+      if (param->was_type_checked_by_caller() ||
+          (is_unchecked_entry_param &&
+           !param->is_explicit_covariant_parameter())) {
         const bool is_nullable =
             (inferred_type == NULL) || inferred_type->is_nullable();
         TraceStrongModeType(this, param->type());
@@ -1306,36 +1319,29 @@
 }
 
 CompileType LoadFieldInstr::ComputeType() const {
-  // Type may be null if the field is a VM field, e.g. context parent.
-  // Keep it as null for debug purposes and do not return dynamic in production
-  // mode, since misuse of the type would remain undetected.
-  if (type().IsNull()) {
-    return CompileType::Dynamic();
+  const AbstractType& field_type = slot().static_type();
+  CompileType compile_type_cid = slot().ComputeCompileType();
+  if (field_type.raw() == AbstractType::null()) {
+    return compile_type_cid;
   }
 
   const Isolate* isolate = Isolate::Current();
-  bool is_nullable = CompileType::kNullable;
   intptr_t cid = kDynamicCid;
   const AbstractType* abstract_type = NULL;
   if (isolate->can_use_strong_mode_types() ||
       (isolate->type_checks() &&
-       (type().IsFunctionType() || type().HasResolvedTypeClass()))) {
+       (field_type.IsFunctionType() || field_type.HasTypeClass()))) {
     cid = kIllegalCid;  // Abstract type is known, calculate cid lazily.
-    abstract_type = &type();
+    abstract_type = &field_type;
     TraceStrongModeType(this, *abstract_type);
   }
-  if ((field_ != NULL) && (field_->guarded_cid() != kIllegalCid) &&
-      (field_->guarded_cid() != kDynamicCid)) {
-    cid = field_->guarded_cid();
-    is_nullable = field_->is_nullable();
-    abstract_type = nullptr;  // Cid is known, calculate abstract type lazily.
-  } else {
-    cid = result_cid_;
-    if ((cid != kIllegalCid) && (cid != kDynamicCid)) {
-      abstract_type = nullptr;  // Cid is known, calculate abstract type lazily.
-    }
+
+  if (compile_type_cid.ToNullableCid() != kDynamicCid) {
+    abstract_type = nullptr;
   }
-  return CompileType(is_nullable, cid, abstract_type);
+
+  return CompileType(compile_type_cid.is_nullable(),
+                     compile_type_cid.ToNullableCid(), abstract_type);
 }
 
 CompileType LoadCodeUnitsInstr::ComputeType() const {
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index c07b6f4..577b3af 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -894,19 +894,17 @@
 
 void CallSpecializer::InlineImplicitInstanceGetter(Definition* call,
                                                    const Field& field) {
+  const Slot& slot = Slot::Get(field, &flow_graph()->parsed_function());
   LoadFieldInstr* load = new (Z) LoadFieldInstr(
-      new (Z) Value(call->ArgumentAt(0)), &field,
-      AbstractType::ZoneHandle(Z, field.type()), call->token_pos(),
-      isolate()->use_field_guards() ? &flow_graph()->parsed_function() : NULL);
-  load->set_is_immutable(field.is_final());
+      new (Z) Value(call->ArgumentAt(0)), slot, call->token_pos());
 
   // Discard the environment from the original instruction because the load
   // can't deoptimize.
   call->RemoveEnvironment();
   ReplaceCall(call, load);
 
-  if (load->result_cid() != kDynamicCid) {
-    // Reset value types if guarded_cid was used.
+  if (load->slot().nullable_cid() != kDynamicCid) {
+    // Reset value types if we know concrete cid.
     for (Value::Iterator it(load->input_use_list()); !it.Done(); it.Advance()) {
       it.Current()->SetReachingType(NULL);
     }
@@ -1034,10 +1032,10 @@
       if (!dst_type.IsInstantiated()) {
         const Class& owner = Class::Handle(Z, field.Owner());
         if (owner.NumTypeArguments() > 0) {
-          instantiator_type_args = new (Z) LoadFieldInstr(
-              new (Z) Value(instr->ArgumentAt(0)),
-              NativeFieldDesc::GetTypeArgumentsFieldFor(zone(), owner),
-              instr->token_pos());
+          instantiator_type_args = new (Z)
+              LoadFieldInstr(new (Z) Value(instr->ArgumentAt(0)),
+                             Slot::GetTypeArgumentsSlotFor(thread(), owner),
+                             instr->token_pos());
           InsertBefore(instr, instantiator_type_args, instr->env(),
                        FlowGraph::kValue);
         }
@@ -1056,15 +1054,10 @@
 
   // Field guard was detached.
   ASSERT(instr->FirstArgIndex() == 0);
-  StoreInstanceFieldInstr* store = new (Z)
-      StoreInstanceFieldInstr(field, new (Z) Value(instr->ArgumentAt(0)),
-                              new (Z) Value(instr->ArgumentAt(1)),
-                              kEmitStoreBarrier, instr->token_pos());
-
-  ASSERT(I->use_field_guards() || !store->IsUnboxedStore());
-  if (I->use_field_guards() && store->IsUnboxedStore()) {
-    flow_graph()->parsed_function().AddToGuardedFields(&field);
-  }
+  StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
+      field, new (Z) Value(instr->ArgumentAt(0)),
+      new (Z) Value(instr->ArgumentAt(1)), kEmitStoreBarrier,
+      instr->token_pos(), &flow_graph()->parsed_function());
 
   // Discard the environment from the original instruction because the store
   // can't deoptimize.
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index c771039..afc73c3 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -37,6 +37,7 @@
   "backend/code_statistics.h",
   "backend/constant_propagator.cc",
   "backend/constant_propagator.h",
+  "backend/compile_type.h",
   "backend/flow_graph.cc",
   "backend/flow_graph.h",
   "backend/flow_graph_compiler.cc",
@@ -69,6 +70,8 @@
   "backend/range_analysis.h",
   "backend/redundancy_elimination.cc",
   "backend/redundancy_elimination.h",
+  "backend/slot.cc",
+  "backend/slot.h",
   "backend/type_propagator.cc",
   "backend/type_propagator.h",
   "call_specializer.cc",
@@ -77,6 +80,7 @@
   "cha.h",
   "compiler_pass.cc",
   "compiler_pass.h",
+  "compiler_state.cc",
   "compiler_state.h",
   "frontend/base_flow_graph_builder.cc",
   "frontend/base_flow_graph_builder.h",
@@ -125,6 +129,7 @@
   "assembler/disassembler_test.cc",
   "backend/il_test.cc",
   "backend/locations_helpers_test.cc",
+  "backend/loops_test.cc",
   "backend/range_analysis_test.cc",
   "cha_test.cc",
 ]
diff --git a/runtime/vm/compiler/compiler_state.cc b/runtime/vm/compiler/compiler_state.cc
new file mode 100644
index 0000000..4e05c0d
--- /dev/null
+++ b/runtime/vm/compiler/compiler_state.cc
@@ -0,0 +1,80 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/compiler/compiler_state.h"
+
+#ifndef DART_PRECOMPILED_RUNTIME
+
+#include <functional>
+
+#include "vm/scopes.h"
+
+namespace dart {
+
+template <typename T>
+T* PutIfAbsent(Thread* thread,
+               ZoneGrowableArray<T*>** array_slot,
+               intptr_t index,
+               std::function<T*()> create) {
+  auto array = *array_slot;
+
+  if (array == nullptr) {
+    Zone* const Z = thread->zone();
+    *array_slot = array = new (Z) ZoneGrowableArray<T*>(Z, index + 1);
+  }
+
+  while (array->length() <= index) {
+    array->Add(nullptr);
+  }
+
+  if (array->At(index) == nullptr) {
+    (*array)[index] = create();
+  }
+  return array->At(index);
+}
+
+LocalVariable* CompilerState::GetDummyCapturedVariable(intptr_t context_id,
+                                                       intptr_t index) {
+  return PutIfAbsent<LocalVariable>(
+      thread(), &dummy_captured_vars_, index, [&]() {
+        Zone* const Z = thread()->zone();
+        const AbstractType& dynamic_type =
+            AbstractType::ZoneHandle(Z, Type::DynamicType());
+        const String& name = String::ZoneHandle(
+            Z, Symbols::NewFormatted(thread(), ":context_var%" Pd, index));
+        LocalVariable* var = new (Z)
+            LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
+                          name, dynamic_type, /*param_type=*/nullptr);
+        var->set_is_captured();
+        var->set_index(VariableIndex(index));
+        return var;
+      });
+}
+
+const GrowableArray<LocalVariable*>& CompilerState::GetDummyContextVariables(
+    intptr_t context_id,
+    intptr_t num_context_variables) {
+  return PutIfAbsent<LocalScope>(
+             thread(), &dummy_scopes_, num_context_variables,
+             [&]() {
+               Zone* const Z = thread()->zone();
+
+               LocalScope* scope = new (Z) LocalScope(
+                   /*parent=*/NULL, /*function_level=*/0, /*loop_level=*/0);
+               scope->set_context_level(0);
+
+               for (intptr_t i = 0; i < num_context_variables; i++) {
+                 LocalVariable* var = GetDummyCapturedVariable(context_id, i);
+                 scope->AddVariable(var);
+                 scope->AddContextVariable(var);
+               }
+
+               return scope;
+             })
+      ->context_variables();
+}
+
+}  // namespace dart
+
+#endif  // DART_PRECOMPILED_RUNTIME
diff --git a/runtime/vm/compiler/compiler_state.h b/runtime/vm/compiler/compiler_state.h
index 320a174..e9bc675 100644
--- a/runtime/vm/compiler/compiler_state.h
+++ b/runtime/vm/compiler/compiler_state.h
@@ -10,6 +10,10 @@
 
 namespace dart {
 
+class LocalScope;
+class LocalVariable;
+class SlotCache;
+
 // Deoptimization Id logic.
 //
 // Deoptimization ids are used to refer to deoptimization points, at which
@@ -79,10 +83,47 @@
     return Thread::Current()->compiler_state();
   }
 
+  SlotCache* slot_cache() const { return slot_cache_; }
+  void set_slot_cache(SlotCache* cache) { slot_cache_ = cache; }
+
+  // Create a dummy list of local variables representing a context object
+  // with the given number of captured variables and given ID.
+  //
+  // Used during bytecode to IL translation because AllocateContext and
+  // CloneContext IL instructions need a list of local varaibles and bytecode
+  // does not record this information.
+  //
+  // TODO(vegorov): create context classes for distinct context IDs and
+  // populate them with slots without creating variables.
+  const GrowableArray<LocalVariable*>& GetDummyContextVariables(
+      intptr_t context_id,
+      intptr_t num_context_variables);
+
+  // Create a dummy LocalVariable that represents a captured local variable
+  // at the given index in the context with given ID.
+  //
+  // Used during bytecode to IL translation because StoreInstanceField and
+  // LoadField IL instructions need Slot, which can only be created from a
+  // LocalVariable.
+  //
+  // This function returns the same variable when it is called with the
+  // same index.
+  //
+  // TODO(vegorov): disambiguate slots for different context IDs.
+  LocalVariable* GetDummyCapturedVariable(intptr_t context_id, intptr_t index);
+
  private:
   CHA cha_;
   intptr_t deopt_id_ = 0;
 
+  // Cache for Slot objects created during compilation (see slot.h).
+  SlotCache* slot_cache_ = nullptr;
+
+  // Caches for dummy LocalVariables and LocalScopes created during
+  // bytecode to IL translation.
+  ZoneGrowableArray<LocalScope*>* dummy_scopes_ = nullptr;
+  ZoneGrowableArray<LocalVariable*>* dummy_captured_vars_ = nullptr;
+
   CompilerState* previous_;
 };
 
@@ -102,6 +143,24 @@
   DISALLOW_COPY_AND_ASSIGN(DeoptIdScope);
 };
 
+/// Ensures that there were no deopt id allocations during the lifetime of this
+/// object.
+class AssertNoDeoptIdsAllocatedScope : public StackResource {
+ public:
+  explicit AssertNoDeoptIdsAllocatedScope(Thread* thread)
+      : StackResource(thread),
+        prev_deopt_id_(thread->compiler_state().deopt_id()) {}
+
+  ~AssertNoDeoptIdsAllocatedScope() {
+    ASSERT(thread()->compiler_state().deopt_id() == prev_deopt_id_);
+  }
+
+ private:
+  const intptr_t prev_deopt_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(AssertNoDeoptIdsAllocatedScope);
+};
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_COMPILER_COMPILER_STATE_H_
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index b122dab..4e54a2b 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -114,7 +114,7 @@
   ASSERT(delta >= 0);
   Fragment instructions = LoadLocal(parsed_function_->current_context_var());
   while (delta-- > 0) {
-    instructions += LoadField(Context::parent_offset());
+    instructions += LoadNativeField(Slot::Context_parent());
   }
   return instructions;
 }
@@ -187,9 +187,10 @@
   return instructions.closed();
 }
 
-Fragment BaseFlowGraphBuilder::CheckStackOverflow(TokenPosition position) {
+Fragment BaseFlowGraphBuilder::CheckStackOverflow(TokenPosition position,
+                                                  intptr_t loop_depth) {
   return Fragment(
-      new (Z) CheckStackOverflowInstr(position, loop_depth_, GetNextDeoptId()));
+      new (Z) CheckStackOverflowInstr(position, loop_depth, GetNextDeoptId()));
 }
 
 Fragment BaseFlowGraphBuilder::Constant(const Object& value) {
@@ -243,7 +244,7 @@
   TargetEntryInstr* neq_entry;
 
   test += LoadArgDescriptor();
-  test += LoadNativeField(NativeFieldDesc::ArgumentsDescriptor_type_args_len());
+  test += LoadNativeField(Slot::ArgumentsDescriptor_type_args_len());
   test += IntConstant(num_type_args);
   test += BranchIfEqual(&eq_entry, &neq_entry);
 
@@ -266,7 +267,7 @@
   TargetEntryInstr* present_entry;
 
   test += LoadLocal(closure);
-  test += LoadField(Closure::delayed_type_arguments_offset());
+  test += LoadNativeField(Slot::Closure_delayed_type_arguments());
   test += Constant(Object::empty_type_arguments());
   test += BranchIfEqual(&absent_entry, &present_entry);
 
@@ -302,22 +303,6 @@
   }
 }
 
-Fragment BaseFlowGraphBuilder::LoadField(const Field& field) {
-  LoadFieldInstr* load = new (Z) LoadFieldInstr(
-      Pop(), &MayCloneField(field), AbstractType::ZoneHandle(Z, field.type()),
-      TokenPosition::kNoSource, parsed_function_);
-  Push(load);
-  return Fragment(load);
-}
-
-Fragment BaseFlowGraphBuilder::LoadField(intptr_t offset, intptr_t class_id) {
-  LoadFieldInstr* load = new (Z) LoadFieldInstr(
-      Pop(), offset, AbstractType::ZoneHandle(Z), TokenPosition::kNoSource);
-  load->set_result_cid(class_id);
-  Push(load);
-  return Fragment(load);
-}
-
 Fragment BaseFlowGraphBuilder::LoadIndexed(intptr_t index_scale) {
   Value* index = Pop();
   Value* array = Pop();
@@ -328,8 +313,11 @@
   return Fragment(instr);
 }
 
-Fragment BaseFlowGraphBuilder::LoadNativeField(
-    const NativeFieldDesc* native_field) {
+Fragment BaseFlowGraphBuilder::LoadField(const Field& field) {
+  return LoadNativeField(Slot::Get(MayCloneField(field), parsed_function_));
+}
+
+Fragment BaseFlowGraphBuilder::LoadNativeField(const Slot& native_field) {
   LoadFieldInstr* load =
       new (Z) LoadFieldInstr(Pop(), native_field, TokenPosition::kNoSource);
   Push(load);
@@ -380,14 +368,14 @@
 
 Fragment BaseFlowGraphBuilder::StoreInstanceField(
     TokenPosition position,
-    intptr_t offset,
+    const Slot& field,
     StoreBarrierType emit_store_barrier) {
   Value* value = Pop();
   if (value->BindsToConstant()) {
     emit_store_barrier = kNoStoreBarrier;
   }
   StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
-      offset, Pop(), value, emit_store_barrier, position);
+      field, Pop(), value, emit_store_barrier, position);
   return Fragment(store);
 }
 
@@ -400,10 +388,11 @@
     emit_store_barrier = kNoStoreBarrier;
   }
 
-  StoreInstanceFieldInstr* store = new (Z)
-      StoreInstanceFieldInstr(MayCloneField(field), Pop(), value,
-                              emit_store_barrier, TokenPosition::kNoSource);
-  store->set_is_initialization(is_initialization_store);
+  StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
+      MayCloneField(field), Pop(), value, emit_store_barrier,
+      TokenPosition::kNoSource, parsed_function_,
+      is_initialization_store ? StoreInstanceFieldInstr::Kind::kInitializing
+                              : StoreInstanceFieldInstr::Kind::kOther);
 
   return Fragment(store);
 }
@@ -439,6 +428,14 @@
   return Fragment(load);
 }
 
+Fragment BaseFlowGraphBuilder::RedefinitionWithType(const AbstractType& type) {
+  auto redefinition = new (Z) RedefinitionInstr(Pop());
+  redefinition->set_constrained_type(
+      new (Z) CompileType(CompileType::FromAbstractType(type)));
+  Push(redefinition);
+  return Fragment(redefinition);
+}
+
 Fragment BaseFlowGraphBuilder::StoreStaticField(TokenPosition position,
                                                 const Field& field) {
   return Fragment(
@@ -466,7 +463,7 @@
     instructions += LoadContextAt(variable->owner()->context_level());
     instructions += LoadLocal(value);
     instructions += StoreInstanceField(
-        position, Context::variable_offset(variable->index().value()));
+        position, Slot::GetContextVariableSlotFor(thread_, *variable));
     return instructions;
   }
   return StoreLocalRaw(position, variable);
@@ -667,9 +664,10 @@
   return Fragment(negate);
 }
 
-Fragment BaseFlowGraphBuilder::AllocateContext(intptr_t size) {
+Fragment BaseFlowGraphBuilder::AllocateContext(
+    const GrowableArray<LocalVariable*>& context_variables) {
   AllocateContextInstr* allocate =
-      new (Z) AllocateContextInstr(TokenPosition::kNoSource, size);
+      new (Z) AllocateContextInstr(TokenPosition::kNoSource, context_variables);
   Push(allocate);
   return Fragment(allocate);
 }
@@ -700,7 +698,7 @@
   Value* instantiator_type_args = Pop();
   const Class& instantiator_class = Class::ZoneHandle(Z, function_.Owner());
   InstantiateTypeArgumentsInstr* instr = new (Z) InstantiateTypeArgumentsInstr(
-      TokenPosition::kNoSource, type_arguments, instantiator_class,
+      TokenPosition::kNoSource, type_arguments, instantiator_class, function_,
       instantiator_type_args, function_type_args, GetNextDeoptId());
   Push(instr);
   return Fragment(instr);
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index b37c2db..69ff503 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -129,13 +129,11 @@
         next_used_try_index_(0),
         stack_(NULL),
         pending_argument_count_(0),
-        loop_depth_(0),
         exit_collector_(exit_collector),
         inlining_unchecked_entry_(inlining_unchecked_entry) {}
 
   Fragment LoadField(const Field& field);
-  Fragment LoadField(intptr_t offset, intptr_t class_id = kDynamicCid);
-  Fragment LoadNativeField(const NativeFieldDesc* native_field);
+  Fragment LoadNativeField(const Slot& native_field);
   Fragment LoadIndexed(intptr_t index_scale);
 
   void SetTempIndex(Definition* definition);
@@ -149,7 +147,7 @@
   const Field& MayCloneField(const Field& field);
   Fragment StoreInstanceField(
       TokenPosition position,
-      intptr_t offset,
+      const Slot& field,
       StoreBarrierType emit_store_barrier = kEmitStoreBarrier);
   Fragment StoreInstanceField(
       const Field& field,
@@ -158,6 +156,7 @@
   Fragment StoreInstanceFieldGuarded(const Field& field,
                                      bool is_initialization_store);
   Fragment LoadStaticField();
+  Fragment RedefinitionWithType(const AbstractType& type);
   Fragment StoreStaticField(TokenPosition position, const Field& field);
   Fragment StoreIndexed(intptr_t class_id);
 
@@ -219,7 +218,7 @@
   Fragment BranchIfStrictEqual(TargetEntryInstr** then_entry,
                                TargetEntryInstr** otherwise_entry);
   Fragment Return(TokenPosition position);
-  Fragment CheckStackOverflow(TokenPosition position);
+  Fragment CheckStackOverflow(TokenPosition position, intptr_t loop_depth);
   Fragment ThrowException(TokenPosition position);
   Fragment TailCall(const Code& code);
 
@@ -262,7 +261,7 @@
 
   Fragment AssertBool(TokenPosition position);
   Fragment BooleanNegate();
-  Fragment AllocateContext(intptr_t size);
+  Fragment AllocateContext(const GrowableArray<LocalVariable*>& scope);
   Fragment CreateArray();
   Fragment InstantiateType(const AbstractType& type);
   Fragment InstantiateTypeArguments(const TypeArguments& type_arguments);
@@ -289,7 +288,6 @@
 
   Value* stack_;
   intptr_t pending_argument_count_;
-  intptr_t loop_depth_;
   InlineExitCollector* exit_collector_;
 
   const bool inlining_unchecked_entry_;
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index 6d48c90..20cb6a0 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -5,6 +5,7 @@
 #include "vm/compiler/frontend/bytecode_flow_graph_builder.h"
 
 #include "vm/compiler/backend/il_printer.h"
+#include "vm/compiler/frontend/bytecode_reader.h"
 #include "vm/compiler/frontend/prologue_builder.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/object_store.h"
@@ -373,14 +374,15 @@
   throw_no_such_method_ = B->BuildThrowNoSuchMethod();
 
   check_args += B->LoadArgDescriptor();
-  check_args += B->LoadField(ArgumentsDescriptor::positional_count_offset());
+  check_args +=
+      B->LoadNativeField(Slot::ArgumentsDescriptor_positional_count());
   check_args += B->IntConstant(num_fixed_params);
   TargetEntryInstr *success1, *fail1;
   check_args += B->BranchIfEqual(&success1, &fail1);
   check_args = Fragment(check_args.entry, success1);
 
   check_args += B->LoadArgDescriptor();
-  check_args += B->LoadField(ArgumentsDescriptor::count_offset());
+  check_args += B->LoadNativeField(Slot::ArgumentsDescriptor_count());
   check_args += B->IntConstant(num_fixed_params);
   TargetEntryInstr *success2, *fail2;
   check_args += B->BranchIfEqual(&success2, &fail2);
@@ -566,8 +568,8 @@
   // If expect_type_args, a non-zero length must match the declaration length.
   TargetEntryInstr *then, *fail;
   setup_type_args += B->LoadArgDescriptor();
-  setup_type_args += B->LoadNativeField(NativeFieldDesc::Get(
-      NativeFieldDesc::kArgumentsDescriptor_type_args_len));
+  setup_type_args +=
+      B->LoadNativeField(Slot::ArgumentsDescriptor_type_args_len());
 
   if (expected_num_type_args != 0) {
     JoinEntryInstr* join2 = B->BuildJoinEntry();
@@ -593,7 +595,7 @@
 
     Fragment store_type_args(then2);
     store_type_args += B->LoadArgDescriptor();
-    store_type_args += B->LoadField(ArgumentsDescriptor::count_offset());
+    store_type_args += B->LoadNativeField(Slot::ArgumentsDescriptor_count());
     store_type_args += B->LoadFpRelativeSlot(
         kWordSize * (1 + compiler_frame_layout.param_end_from_fp));
     store_type_args +=
@@ -624,8 +626,10 @@
 }
 
 void BytecodeFlowGraphBuilder::BuildCheckStack() {
-  // TODO(alexmarkov): update B->loop_depth_
-  code_ += B->CheckStackOverflow(position_);
+  if (is_generating_interpreter()) {
+    UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
+  }
+  code_ += B->CheckStackOverflow(position_, DecodeOperandA().value());
   ASSERT(B->stack_ == nullptr);
 }
 
@@ -777,15 +781,27 @@
     UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
   }
 
-  code_ += B->AllocateContext(DecodeOperandD().value());
+  const intptr_t context_id = DecodeOperandA().value();
+  const intptr_t num_context_vars = DecodeOperandD().value();
+
+  auto& context_variables = CompilerState::Current().GetDummyContextVariables(
+      context_id, num_context_vars);
+  code_ += B->AllocateContext(context_variables);
 }
 
 void BytecodeFlowGraphBuilder::BuildCloneContext() {
+  if (is_generating_interpreter()) {
+    UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
+  }
+
   LoadStackSlots(1);
-  // TODO(alexmarkov): Pass context_size and use it in compiled mode.
+  const intptr_t context_id = DecodeOperandA().value();
+  const intptr_t num_context_vars = DecodeOperandD().value();
+
+  auto& context_variables = CompilerState::Current().GetDummyContextVariables(
+      context_id, num_context_vars);
   CloneContextInstr* clone_instruction = new (Z) CloneContextInstr(
-      TokenPosition::kNoSource, Pop(), CloneContextInstr::kUnknownContextSize,
-      B->GetNextDeoptId());
+      TokenPosition::kNoSource, Pop(), context_variables, B->GetNextDeoptId());
   code_ <<= clone_instruction;
   B->Push(clone_instruction);
 }
@@ -795,6 +811,24 @@
   code_ += B->CreateArray();
 }
 
+const Slot& ClosureSlotByField(const Field& field) {
+  const intptr_t offset = field.Offset();
+  if (offset == Closure::instantiator_type_arguments_offset()) {
+    return Slot::Closure_instantiator_type_arguments();
+  } else if (offset == Closure::function_type_arguments_offset()) {
+    return Slot::Closure_function_type_arguments();
+  } else if (offset == Closure::delayed_type_arguments_offset()) {
+    return Slot::Closure_delayed_type_arguments();
+  } else if (offset == Closure::function_offset()) {
+    return Slot::Closure_function();
+  } else if (offset == Closure::context_offset()) {
+    return Slot::Closure_context();
+  } else {
+    RELEASE_ASSERT(offset == Closure::hash_offset());
+    return Slot::Closure_hash();
+  }
+}
+
 void BytecodeFlowGraphBuilder::BuildStoreFieldTOS() {
   if (is_generating_interpreter()) {
     UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
@@ -809,8 +843,7 @@
 
   if (field.Owner() == isolate()->object_store()->closure_class()) {
     // Stores to _Closure fields are lower-level.
-    // TODO(alexmarkov): use NativeFieldDesc
-    code_ += B->StoreInstanceField(position_, field.Offset());
+    code_ += B->StoreInstanceField(position_, ClosureSlotByField(field));
   } else {
     // The rest of the StoreFieldTOS are for field initializers.
     // TODO(alexmarkov): Consider adding a flag to StoreFieldTOS or even
@@ -834,8 +867,7 @@
 
   if (field.Owner() == isolate()->object_store()->closure_class()) {
     // Loads from _Closure fields are lower-level.
-    // TODO(alexmarkov): use NativeFieldDesc
-    code_ += B->LoadField(field.Offset());
+    code_ += B->LoadNativeField(ClosureSlotByField(field));
   } else {
     code_ += B->LoadField(field);
   }
@@ -844,15 +876,13 @@
 void BytecodeFlowGraphBuilder::BuildStoreContextParent() {
   LoadStackSlots(2);
 
-  // TODO(alexmarkov): use NativeFieldDesc
-  code_ += B->StoreInstanceField(position_, Context::parent_offset());
+  code_ += B->StoreInstanceField(position_, Slot::Context_parent());
 }
 
 void BytecodeFlowGraphBuilder::BuildLoadContextParent() {
   LoadStackSlots(1);
 
-  // TODO(alexmarkov): use NativeFieldDesc
-  code_ += B->LoadField(Context::parent_offset());
+  code_ += B->LoadNativeField(Slot::Context_parent());
 }
 
 void BytecodeFlowGraphBuilder::BuildStoreContextVar() {
@@ -861,11 +891,13 @@
   }
 
   LoadStackSlots(2);
-  Operand var_index = DecodeOperandD();
+  const intptr_t context_id = DecodeOperandA().value();
+  const intptr_t var_index = DecodeOperandD().value();
 
-  // TODO(alexmarkov): use NativeFieldDesc
-  code_ += B->StoreInstanceField(position_,
-                                 Context::variable_offset(var_index.value()));
+  auto var =
+      CompilerState::Current().GetDummyCapturedVariable(context_id, var_index);
+  code_ += B->StoreInstanceField(
+      position_, Slot::GetContextVariableSlotFor(thread(), *var));
 }
 
 void BytecodeFlowGraphBuilder::BuildLoadContextVar() {
@@ -874,10 +906,12 @@
   }
 
   LoadStackSlots(1);
-  Operand var_index = DecodeOperandD();
+  const intptr_t context_id = DecodeOperandA().value();
+  const intptr_t var_index = DecodeOperandD().value();
 
-  // TODO(alexmarkov): use NativeFieldDesc
-  code_ += B->LoadField(Context::variable_offset(var_index.value()));
+  auto var =
+      CompilerState::Current().GetDummyCapturedVariable(context_id, var_index);
+  code_ += B->LoadNativeField(Slot::GetContextVariableSlotFor(thread(), *var));
 }
 
 void BytecodeFlowGraphBuilder::BuildLoadTypeArgumentsField() {
@@ -889,8 +923,7 @@
   const intptr_t offset =
       Smi::Cast(ConstantAt(DecodeOperandD()).value()).Value() * kWordSize;
 
-  code_ +=
-      B->LoadNativeField(NativeFieldDesc::GetTypeArgumentsField(Z, offset));
+  code_ += B->LoadNativeField(Slot::GetTypeArgumentsSlotAt(thread(), offset));
 }
 
 void BytecodeFlowGraphBuilder::BuildStoreStaticTOS() {
@@ -1032,8 +1065,7 @@
 
   TargetEntryInstr *is_zero, *is_not_zero;
   code_ += B->LoadArgDescriptor();
-  code_ += B->LoadNativeField(NativeFieldDesc::Get(
-      NativeFieldDesc::kArgumentsDescriptor_type_args_len));
+  code_ += B->LoadNativeField(Slot::ArgumentsDescriptor_type_args_len());
   code_ += B->IntConstant(0);
   code_ += B->BranchIfEqual(&is_zero, &is_not_zero);
 
@@ -1156,8 +1188,7 @@
   }
 
   LocalVariable* special_var = nullptr;
-  switch (DecodeOperandD().value()) {
-    // TODO(alexmarkov): Move these constants to constants_kbc.h
+  switch (DecodeOperandA().value()) {
     case KernelBytecode::kExceptionSpecialIndex:
       ASSERT(exception_var_ != nullptr);
       special_var = exception_var_;
@@ -1171,7 +1202,7 @@
   }
 
   code_ += B->LoadLocal(special_var);
-  StoreLocal(DecodeOperandA());
+  StoreLocal(DecodeOperandX());
   code_ += B->Drop();
 }
 
@@ -1451,10 +1482,10 @@
   // Use default flow graph builder for native methods.
   ASSERT(!function().is_native());
 
-  const Code& bytecode = Code::Handle(Z, function().Bytecode());
+  const Bytecode& bytecode = Bytecode::Handle(Z, function().bytecode());
 
   object_pool_ = bytecode.object_pool();
-  raw_bytecode_ = reinterpret_cast<KBCInstr*>(bytecode.EntryPoint());
+  raw_bytecode_ = reinterpret_cast<KBCInstr*>(bytecode.PayloadStart());
   bytecode_length_ = bytecode.Size() / sizeof(KBCInstr);
 
   ProcessICDataInObjectPool(object_pool_);
@@ -1472,6 +1503,9 @@
 
   CollectControlFlow(descriptors, handlers, graph_entry);
 
+  kernel::BytecodeSourcePositionsIterator source_pos_iter(Z, bytecode);
+  bool update_position = source_pos_iter.MoveNext();
+
   code_ = Fragment(normal_entry);
 
   for (pc_ = 0; pc_ < bytecode_length_; ++pc_) {
@@ -1494,6 +1528,12 @@
       ASSERT(!code_.is_closed());
     }
 
+    while (update_position &&
+           pc_ >= source_pos_iter.BytecodeInstructionIndex()) {
+      position_ = source_pos_iter.TokenPos();
+      update_position = source_pos_iter.MoveNext();
+    }
+
     BuildInstruction(KernelBytecode::DecodeOpcode(bytecode_instr_));
 
     if (code_.is_closed()) {
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 49dec04..b5f2acc 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -74,11 +74,13 @@
   }
 
   const int kHasExceptionsTableFlag = 1 << 0;
-  const int kHasNullableFieldsFlag = 1 << 1;
-  const int kHasClosuresFlag = 1 << 2;
+  const int kHasSourcePositionsFlag = 1 << 1;
+  const int kHasNullableFieldsFlag = 1 << 2;
+  const int kHasClosuresFlag = 1 << 3;
 
   const intptr_t flags = helper_->reader_.ReadUInt();
   const bool has_exceptions_table = (flags & kHasExceptionsTableFlag) != 0;
+  const bool has_source_positions = (flags & kHasSourcePositionsFlag) != 0;
   const bool has_nullable_fields = (flags & kHasNullableFieldsFlag) != 0;
   const bool has_closures = (flags & kHasClosuresFlag) != 0;
 
@@ -98,12 +100,16 @@
   }
 
   // Read bytecode and attach to function.
-  const Code& bytecode = Code::Handle(helper_->zone_, ReadBytecode(pool));
+  const Bytecode& bytecode =
+      Bytecode::Handle(helper_->zone_, ReadBytecode(pool));
   function.AttachBytecode(bytecode);
+  ASSERT(bytecode.GetBinary(helper_->zone_) ==
+         helper_->reader_.typed_data()->raw());
 
-  // Read exceptions table.
   ReadExceptionsTable(bytecode, has_exceptions_table);
 
+  ReadSourcePositions(bytecode, has_source_positions);
+
   if (FLAG_dump_kernel_bytecode) {
     KernelBytecodeDisassembler::Disassemble(function);
   }
@@ -130,19 +136,26 @@
   // Read closures.
   if (has_closures) {
     Function& closure = Function::Handle(helper_->zone_);
-    Code& closure_bytecode = Code::Handle(helper_->zone_);
+    Bytecode& closure_bytecode = Bytecode::Handle(helper_->zone_);
     const intptr_t num_closures = helper_->ReadListLength();
     for (intptr_t i = 0; i < num_closures; i++) {
       intptr_t closure_index = helper_->ReadUInt();
       ASSERT(closure_index < obj_count);
       closure ^= pool.ObjectAt(closure_index);
 
+      const intptr_t flags = helper_->reader_.ReadUInt();
+      const bool has_exceptions_table = (flags & kHasExceptionsTableFlag) != 0;
+      const bool has_source_positions = (flags & kHasSourcePositionsFlag) != 0;
+
       // Read closure bytecode and attach to closure function.
       closure_bytecode = ReadBytecode(pool);
       closure.AttachBytecode(closure_bytecode);
+      ASSERT(bytecode.GetBinary(helper_->zone_) ==
+             helper_->reader_.typed_data()->raw());
 
-      // Read closure exceptions table.
-      ReadExceptionsTable(closure_bytecode);
+      ReadExceptionsTable(closure_bytecode, has_exceptions_table);
+
+      ReadSourcePositions(closure_bytecode, has_source_positions);
 
       if (FLAG_dump_kernel_bytecode) {
         KernelBytecodeDisassembler::Disassemble(closure);
@@ -628,23 +641,29 @@
   return obj_count - 1;
 }
 
-RawCode* BytecodeMetadataHelper::ReadBytecode(const ObjectPool& pool) {
+RawBytecode* BytecodeMetadataHelper::ReadBytecode(const ObjectPool& pool) {
 #if !defined(PRODUCT)
   TimelineDurationScope tds(Thread::Current(), Timeline::GetCompilerStream(),
                             "BytecodeMetadataHelper::ReadBytecode");
 #endif  // !defined(PRODUCT)
-
-  intptr_t size = helper_->reader_.ReadUInt();
+  intptr_t size = helper_->ReadUInt();
+  helper_->SkipBytes(helper_->ReadByte());
   intptr_t offset = helper_->reader_.offset();
+  ASSERT(Utils::IsAligned(offset, sizeof(KBCInstr)));
   const uint8_t* data = helper_->reader_.BufferAt(offset);
+  ASSERT(Utils::IsAligned(data, sizeof(KBCInstr)));
   helper_->reader_.set_offset(offset + size);
 
-  // Create and return code object.
-  return Code::FinalizeBytecode(reinterpret_cast<const void*>(data), size,
-                                pool);
+  const ExternalTypedData& instructions = ExternalTypedData::Handle(
+      helper_->zone_,
+      ExternalTypedData::New(kExternalTypedDataInt8ArrayCid,
+                             const_cast<uint8_t*>(data), size, Heap::kOld));
+
+  // Create and return bytecode object.
+  return Bytecode::New(instructions, pool);
 }
 
-void BytecodeMetadataHelper::ReadExceptionsTable(const Code& bytecode,
+void BytecodeMetadataHelper::ReadExceptionsTable(const Bytecode& bytecode,
                                                  bool has_exceptions_table) {
 #if !defined(PRODUCT)
   TimelineDurationScope tds(Thread::Current(), Timeline::GetCompilerStream(),
@@ -714,6 +733,17 @@
   }
 }
 
+void BytecodeMetadataHelper::ReadSourcePositions(const Bytecode& bytecode,
+                                                 bool has_source_positions) {
+  if (!has_source_positions) {
+    return;
+  }
+
+  intptr_t length = helper_->reader_.ReadUInt();
+  bytecode.set_source_positions_binary_offset(helper_->reader_.offset());
+  helper_->SkipBytes(length);
+}
+
 RawTypedData* BytecodeMetadataHelper::NativeEntry(const Function& function,
                                                   const String& external_name) {
   Zone* zone = helper_->zone_;
@@ -781,6 +811,8 @@
   ASSERT(thread->sticky_error() == Error::null());
   ASSERT(Thread::Current()->IsMutatorThread());
 
+  VMTagScope tagScope(thread, VMTag::kLoadBytecodeTagId);
+
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
     StackZone stack_zone(thread);
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.h b/runtime/vm/compiler/frontend/bytecode_reader.h
index bbde906..079316c 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.h
+++ b/runtime/vm/compiler/frontend/bytecode_reader.h
@@ -6,6 +6,7 @@
 #define RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_READER_H_
 
 #include "vm/compiler/frontend/kernel_translation_helper.h"
+#include "vm/constants_kbc.h"
 #include "vm/object.h"
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -32,9 +33,9 @@
                            const Function& inner_function,
                            const ObjectPool& pool,
                            intptr_t from_index);
-  RawCode* ReadBytecode(const ObjectPool& pool);
-  void ReadExceptionsTable(const Code& bytecode,
-                           bool has_exceptions_table = true);
+  RawBytecode* ReadBytecode(const ObjectPool& pool);
+  void ReadExceptionsTable(const Bytecode& bytecode, bool has_exceptions_table);
+  void ReadSourcePositions(const Bytecode& bytecode, bool has_source_positions);
   RawTypedData* NativeEntry(const Function& function,
                             const String& external_name);
 
@@ -52,6 +53,46 @@
                                         const Function& function);
 };
 
+class BytecodeSourcePositionsIterator : ValueObject {
+ public:
+  BytecodeSourcePositionsIterator(Zone* zone, const Bytecode& bytecode)
+      : reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))),
+        pairs_remaining_(0),
+        cur_bci_(0),
+        cur_token_pos_(TokenPosition::kNoSource.value()) {
+    if (bytecode.HasSourcePositions()) {
+      reader_.set_offset(bytecode.source_positions_binary_offset());
+      pairs_remaining_ = reader_.ReadUInt();
+    }
+  }
+
+  bool MoveNext() {
+    if (pairs_remaining_ == 0) {
+      return false;
+    }
+    ASSERT(pairs_remaining_ > 0);
+    --pairs_remaining_;
+    cur_bci_ += reader_.ReadUInt();
+    cur_token_pos_ += reader_.ReadSLEB128();
+    return true;
+  }
+
+  intptr_t BytecodeInstructionIndex() const { return cur_bci_; }
+
+  uword PcOffset() const {
+    return KernelBytecode::BytecodePcToOffset(BytecodeInstructionIndex(),
+                                              /* is_return_address = */ true);
+  }
+
+  TokenPosition TokenPos() const { return TokenPosition(cur_token_pos_); }
+
+ private:
+  Reader reader_;
+  intptr_t pairs_remaining_;
+  intptr_t cur_bci_;
+  intptr_t cur_token_pos_;
+};
+
 }  // namespace kernel
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/frontend/constant_evaluator.cc b/runtime/vm/compiler/frontend/constant_evaluator.cc
index a59c3a0..ba83f35 100644
--- a/runtime/vm/compiler/frontend/constant_evaluator.cc
+++ b/runtime/vm/compiler/frontend/constant_evaluator.cc
@@ -43,6 +43,8 @@
                                                    bool reset_position) {
   ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
   if (!GetCachedConstant(offset, &result_)) {
+    BailoutIfBackgroundCompilation();
+
     ASSERT(IsAllowedToEvaluate());
     intptr_t original_offset = helper_->ReaderOffset();
     helper_->SetOffset(offset);
@@ -164,6 +166,8 @@
 Instance& ConstantEvaluator::EvaluateListLiteral(intptr_t offset,
                                                  bool reset_position) {
   if (!GetCachedConstant(offset, &result_)) {
+    BailoutIfBackgroundCompilation();
+
     ASSERT(IsAllowedToEvaluate());
     intptr_t original_offset = helper_->ReaderOffset();
     helper_->SetOffset(offset);
@@ -181,6 +185,8 @@
 Instance& ConstantEvaluator::EvaluateMapLiteral(intptr_t offset,
                                                 bool reset_position) {
   if (!GetCachedConstant(offset, &result_)) {
+    BailoutIfBackgroundCompilation();
+
     ASSERT(IsAllowedToEvaluate());
     intptr_t original_offset = helper_->ReaderOffset();
     helper_->SetOffset(offset);
@@ -199,6 +205,8 @@
     intptr_t offset,
     bool reset_position) {
   if (!GetCachedConstant(offset, &result_)) {
+    BailoutIfBackgroundCompilation();
+
     ASSERT(IsAllowedToEvaluate());
     intptr_t original_offset = helper_->ReaderOffset();
     helper_->SetOffset(offset);
@@ -216,6 +224,8 @@
 Instance& ConstantEvaluator::EvaluateStaticInvocation(intptr_t offset,
                                                       bool reset_position) {
   if (!GetCachedConstant(offset, &result_)) {
+    BailoutIfBackgroundCompilation();
+
     ASSERT(IsAllowedToEvaluate());
     intptr_t original_offset = helper_->ReaderOffset();
     helper_->SetOffset(offset);
@@ -244,6 +254,8 @@
 }
 
 RawObject* ConstantEvaluator::EvaluateAnnotations() {
+  BailoutIfBackgroundCompilation();
+
   intptr_t list_length = helper_->ReadListLength();  // read list length.
   const Array& metadata_values =
       Array::Handle(Z, Array::New(list_length, H.allocation_space()));
@@ -257,6 +269,13 @@
   return metadata_values.raw();
 }
 
+void ConstantEvaluator::BailoutIfBackgroundCompilation() {
+  if (Compiler::IsBackgroundCompilation()) {
+    Compiler::AbortBackgroundCompilation(
+        DeoptId::kNone, "Cannot evaluate annotations in background compiler.");
+  }
+}
+
 bool ConstantEvaluator::IsBuildingFlowGraph() const {
   return flow_graph_builder_ != nullptr;
 }
@@ -777,6 +796,12 @@
   // read type arguments.
   intptr_t num_type_args = helper_->ReadListLength();
   const TypeArguments* type_args = &T.BuildTypeArguments(num_type_args);
+  if (!type_args->IsNull() && !type_args->IsInstantiated()) {
+    H.ReportError(
+        script_, TokenPosition::kNoSource,
+        "Type arguments in partial instantiations must be instantiated and are "
+        "therefore not allowed to depend on type parameters.");
+  }
 
   // Create new closure with the type arguments inserted, and other things
   // copied over.
diff --git a/runtime/vm/compiler/frontend/constant_evaluator.h b/runtime/vm/compiler/frontend/constant_evaluator.h
index 6ce86bc..f5fe543 100644
--- a/runtime/vm/compiler/frontend/constant_evaluator.h
+++ b/runtime/vm/compiler/frontend/constant_evaluator.h
@@ -57,6 +57,8 @@
   RawObject* EvaluateAnnotations();
 
  private:
+  void BailoutIfBackgroundCompilation();
+
   bool IsBuildingFlowGraph() const;
   bool IsAllowedToEvaluate() const;
   void EvaluateAsExpression();
diff --git a/runtime/vm/compiler/frontend/entrypoints_pragma.md b/runtime/vm/compiler/frontend/entrypoints_pragma.md
deleted file mode 100644
index 3fcb451..0000000
--- a/runtime/vm/compiler/frontend/entrypoints_pragma.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# Pragma for testing multiple entrypoints
-
-Example:
-
-```dart
-void hook(String functionName, int entryPointId) {
-  // ...
-}
-
-class C<T> {
-  @pragma("vm:testing.unsafe.trace-entrypoints-fn", hook)
-  void foo(T x) {
-    // ...
-  }
-}
-```
-
-When `foo` is invoked, `hook` will be called in `foo`'s prologue if `foo` was
-compiled with multiple entrypoints. `hook` will be passed the name of the
-function it was called for and the ID of the entrypoint used for the invocation:
-
-- 0: Normal entry.
-
-- 1: Unchecked entry: prologue was short so separate prologues for normal and
-  unchecked entry were compiled.
-
-- 2: Unchecked shared entry: prologue was long, so normal and unchecked entry
-  set a temporary and type-checks are predicated on the temporary.
diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.cc b/runtime/vm/compiler/frontend/flow_graph_builder.cc
index 2f04698..3d14de6 100644
--- a/runtime/vm/compiler/frontend/flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/flow_graph_builder.cc
@@ -356,7 +356,7 @@
   // Bail if the type is a function or a Dart Function type.
   if (type.IsFunctionType() || type.IsDartFunctionType()) return false;
 
-  ASSERT(type.HasResolvedTypeClass());
+  ASSERT(type.HasTypeClass());
   const Class& type_class = Class::Handle(type.type_class());
   // Bail if the type has any type parameters.
   if (type_class.IsGeneric()) return false;
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 4835b6a..61d755e 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -530,7 +530,8 @@
       // static methods they forward to don't do it themselves.
       AlternativeReadingScope _(&reader_);
       BuildArgumentTypeChecks(kCheckAllTypeParameterBounds,
-                              &explicit_checks_unused, &implicit_checks);
+                              &explicit_checks_unused, &implicit_checks,
+                              nullptr);
     } else {
       // Check if parent function was annotated with no-dynamic-invocations.
       const ProcedureAttributesMetadata attrs =
@@ -541,7 +542,8 @@
         // tear-off.
         AlternativeReadingScope _(&reader_);
         BuildArgumentTypeChecks(kCheckNonCovariantTypeParameterBounds,
-                                &explicit_checks_unused, &implicit_checks);
+                                &explicit_checks_unused, &implicit_checks,
+                                nullptr);
       }
     }
   }
@@ -565,8 +567,9 @@
     // closed-over receiver.
     body +=
         LoadLocal(parsed_function()->node_sequence()->scope()->VariableAt(0));
-    body += LoadField(Closure::context_offset());
-    body += flow_graph_builder_->LoadField(Context::variable_offset(0));
+    body += LoadNativeField(Slot::Closure_context());
+    body += LoadNativeField(
+        Slot::GetContextVariableSlotFor(thread(), *scopes()->this_variable));
     body += PushArgument();
   }
 
@@ -633,6 +636,7 @@
       extra_entry = BuildSharedUncheckedEntryPoint(
           /*shared_prologue_linked_in=*/shared_prologue,
           /*skippable_checks=*/default_type_handling + implicit_checks,
+          /*redefinitions_if_skipped=*/Fragment(),
           /*body=*/body);
     }
     RecordUncheckedEntryPoint(extra_entry);
@@ -678,15 +682,17 @@
   if (is_implicit_closure_function && !function.is_static()) {
     if (parsed_function()->has_arg_desc_var()) {
       body += B->LoadArgDescriptor();
-      body += LoadField(ArgumentsDescriptor::count_offset());
+      body += LoadNativeField(Slot::ArgumentsDescriptor_count());
       body += LoadLocal(parsed_function()->current_context_var());
-      body += B->LoadField(Context::variable_offset(0));
+      body += B->LoadNativeField(
+          Slot::GetContextVariableSlotFor(thread(), *scopes()->this_variable));
       body += B->StoreFpRelativeSlot(kWordSize *
                                      compiler_frame_layout.param_end_from_fp);
       body += Drop();
     } else {
       body += LoadLocal(parsed_function()->current_context_var());
-      body += B->LoadField(Context::variable_offset(0));
+      body += B->LoadNativeField(
+          Slot::GetContextVariableSlotFor(thread(), *scopes()->this_variable));
       body += B->StoreFpRelativeSlot(
           kWordSize *
           (compiler_frame_layout.param_end_from_fp + function.NumParameters()));
@@ -699,7 +705,8 @@
 
   if (function.NeedsArgumentTypeChecks(I)) {
     AlternativeReadingScope _(&reader_);
-    BuildArgumentTypeChecks(kCheckAllTypeParameterBounds, &body, &body);
+    BuildArgumentTypeChecks(kCheckAllTypeParameterBounds, &body, &body,
+                            nullptr);
   }
 
   function_node_helper.ReadUntilExcluding(
@@ -724,7 +731,7 @@
 
   if (function.HasOptionalParameters()) {
     body += B->LoadArgDescriptor();
-    body += LoadField(ArgumentsDescriptor::count_offset());
+    body += LoadNativeField(Slot::ArgumentsDescriptor_count());
   } else {
     body += IntConstant(function.NumParameters());
   }
@@ -837,7 +844,8 @@
       body += Constant(type);
     } else {
       body += LoadLocal(parsed_function()->current_context_var());
-      body += B->LoadField(Context::variable_offset(0));
+      body += B->LoadNativeField(
+          Slot::GetContextVariableSlotFor(thread(), *scopes()->this_variable));
     }
   } else {
     LocalScope* scope = parsed_function()->node_sequence()->scope();
@@ -949,7 +957,8 @@
 void StreamingFlowGraphBuilder::BuildArgumentTypeChecks(
     TypeChecksToBuild mode,
     Fragment* explicit_checks,
-    Fragment* implicit_checks) {
+    Fragment* implicit_checks,
+    Fragment* implicit_redefinitions) {
   if (!I->should_emit_strong_mode_checks()) return;
 
   FunctionNodeHelper function_node_helper(this);
@@ -1071,6 +1080,18 @@
     *checks += LoadLocal(param);
     *checks += CheckArgumentType(param, *target_type);
     *checks += Drop();
+
+    if (!helper.IsCovariant() && implicit_redefinitions != nullptr &&
+        B->optimizing_) {
+      // We generate slightly different code in optimized vs. un-optimized code,
+      // which is ok since we don't allocate any deopt ids.
+      AssertNoDeoptIdsAllocatedScope no_deopt_allocation(H.thread());
+
+      *implicit_redefinitions += LoadLocal(param);
+      *implicit_redefinitions += RedefinitionWithType(*target_type);
+      *implicit_redefinitions += StoreLocal(TokenPosition::kNoSource, param);
+      *implicit_redefinitions += Drop();
+    }
   }
 
   // Named.
@@ -1100,6 +1121,18 @@
     *checks += LoadLocal(param);
     *checks += CheckArgumentType(param, *target_type);
     *checks += Drop();
+
+    if (!helper.IsCovariant() && implicit_redefinitions != nullptr &&
+        B->optimizing_) {
+      // We generate slightly different code in optimized vs. un-optimized code,
+      // which is ok since we don't allocate any deopt ids.
+      AssertNoDeoptIdsAllocatedScope no_deopt_allocation(H.thread());
+
+      *implicit_redefinitions += LoadLocal(param);
+      *implicit_redefinitions += RedefinitionWithType(*target_type);
+      *implicit_redefinitions += StoreLocal(TokenPosition::kNoSource, param);
+      *implicit_redefinitions += Drop();
+    }
   }
 }
 
@@ -1222,8 +1255,8 @@
   {
     AlternativeReadingScope alt(&reader_);
     SetOffset(type_parameters_offset);
-    BuildArgumentTypeChecks(kCheckNonCovariantTypeParameterBounds, &body,
-                            &body);
+    BuildArgumentTypeChecks(kCheckNonCovariantTypeParameterBounds, &body, &body,
+                            nullptr);
   }
 
   // Push all arguments and invoke the original method.
@@ -1343,7 +1376,7 @@
       prologue += LoadLocal(fn_type_args);
       prologue += PushArgument();
       prologue += LoadLocal(closure);
-      prologue += LoadField(Closure::function_type_arguments_offset());
+      prologue += LoadNativeField(Slot::Closure_function_type_arguments());
       prologue += PushArgument();
       prologue += IntConstant(dart_function.NumParentTypeParameters());
       prologue += PushArgument();
@@ -1364,7 +1397,7 @@
       prologue += Drop();
     } else {
       prologue += LoadLocal(closure);
-      prologue += LoadField(Closure::function_type_arguments_offset());
+      prologue += LoadNativeField(Slot::Closure_function_type_arguments());
       prologue += StoreLocal(TokenPosition::kNoSource, fn_type_args);
       prologue += Drop();
     }
@@ -1448,10 +1481,9 @@
 Fragment StreamingFlowGraphBuilder::SetupCapturedParameters(
     const Function& dart_function) {
   Fragment body;
-  intptr_t context_size =
-      parsed_function()->node_sequence()->scope()->num_context_variables();
-  if (context_size > 0) {
-    body += flow_graph_builder_->PushContext(context_size);
+  const LocalScope* scope = parsed_function()->node_sequence()->scope();
+  if (scope->num_context_variables() > 0) {
+    body += flow_graph_builder_->PushContext(scope);
     LocalVariable* context = MakeTemporary();
 
     // Copy captured parameters from the stack into the context.
@@ -1477,7 +1509,7 @@
         body += LoadLocal(&raw_parameter);
         body += flow_graph_builder_->StoreInstanceField(
             TokenPosition::kNoSource,
-            Context::variable_offset(variable->index().value()));
+            Slot::GetContextVariableSlotFor(thread(), *variable));
         body += NullConstant();
         body += StoreLocal(TokenPosition::kNoSource, &raw_parameter);
         body += Drop();
@@ -1498,7 +1530,8 @@
     const Function& dart_function,
     intptr_t type_parameters_offset,
     Fragment* explicit_checks,
-    Fragment* implicit_checks) {
+    Fragment* implicit_checks,
+    Fragment* implicit_redefinitions) {
   if (!dart_function.NeedsArgumentTypeChecks(I)) return;
 
   // Check if parent function was annotated with no-dynamic-invocations.
@@ -1512,7 +1545,7 @@
       MethodCanSkipTypeChecksForNonCovariantArguments(dart_function, attrs)
           ? kCheckCovariantTypeParameterBounds
           : kCheckAllTypeParameterBounds,
-      explicit_checks, implicit_checks);
+      explicit_checks, implicit_checks, implicit_redefinitions);
 }
 
 Fragment StreamingFlowGraphBuilder::ShortcutForUserDefinedEquals(
@@ -1657,6 +1690,7 @@
 FunctionEntryInstr* StreamingFlowGraphBuilder::BuildSharedUncheckedEntryPoint(
     Fragment shared_prologue_linked_in,
     Fragment skippable_checks,
+    Fragment redefinitions_if_skipped,
     Fragment body) {
   ASSERT(shared_prologue_linked_in.entry == B->graph_entry_->normal_entry());
   ASSERT(parsed_function()->has_entry_points_temp_var());
@@ -1695,7 +1729,7 @@
   JoinEntryInstr* rest_entry = B->BuildJoinEntry();
 
   Fragment(do_checks) + skippable_checks + Goto(rest_entry);
-  Fragment(skip_checks) + Goto(rest_entry);
+  Fragment(skip_checks) + redefinitions_if_skipped + Goto(rest_entry);
   Fragment(rest_entry) + body;
 
   return extra_target_entry;
@@ -1815,8 +1849,10 @@
 
   Fragment explicit_type_checks;
   Fragment implicit_type_checks;
+  Fragment implicit_redefinitions;
   CheckArgumentTypesAsNecessary(dart_function, type_parameters_offset,
-                                &explicit_type_checks, &implicit_type_checks);
+                                &explicit_type_checks, &implicit_type_checks,
+                                &implicit_redefinitions);
 
   const Fragment body =
       BuildFunctionBody(dart_function, first_parameter, is_constructor);
@@ -1860,6 +1896,7 @@
         extra_entry = BuildSharedUncheckedEntryPoint(
             /*shared_prologue_linked_in=*/prologue,
             /*skippable_checks=*/implicit_type_checks,
+            /*redefinitions_if_skipped=*/implicit_redefinitions,
             /*body=*/body);
         break;
       }
@@ -2418,6 +2455,11 @@
   return flow_graph_builder_->LoadStaticField();
 }
 
+Fragment StreamingFlowGraphBuilder::RedefinitionWithType(
+    const AbstractType& type) {
+  return flow_graph_builder_->RedefinitionWithType(type);
+}
+
 Fragment StreamingFlowGraphBuilder::CheckNull(
     TokenPosition position,
     LocalVariable* receiver,
@@ -2442,10 +2484,11 @@
     const Array& argument_names,
     ICData::RebindRule rebind_rule,
     const InferredTypeMetadata* result_type,
-    intptr_t type_args_count) {
-  return flow_graph_builder_->StaticCall(position, target, argument_count,
-                                         argument_names, rebind_rule,
-                                         result_type, type_args_count);
+    intptr_t type_args_count,
+    bool use_unchecked_entry) {
+  return flow_graph_builder_->StaticCall(
+      position, target, argument_count, argument_names, rebind_rule,
+      result_type, type_args_count, use_unchecked_entry);
 }
 
 Fragment StreamingFlowGraphBuilder::InstanceCall(
@@ -2509,12 +2552,13 @@
   return flow_graph_builder_->AllocateObject(klass, closure_function);
 }
 
-Fragment StreamingFlowGraphBuilder::AllocateContext(intptr_t size) {
-  return flow_graph_builder_->AllocateContext(size);
+Fragment StreamingFlowGraphBuilder::AllocateContext(
+    const GrowableArray<LocalVariable*>& context_variables) {
+  return flow_graph_builder_->AllocateContext(context_variables);
 }
 
-Fragment StreamingFlowGraphBuilder::LoadField(intptr_t offset) {
-  return flow_graph_builder_->LoadField(offset);
+Fragment StreamingFlowGraphBuilder::LoadNativeField(const Slot& field) {
+  return flow_graph_builder_->LoadNativeField(field);
 }
 
 Fragment StreamingFlowGraphBuilder::StoreLocal(TokenPosition position,
@@ -2527,11 +2571,6 @@
   return flow_graph_builder_->StoreStaticField(position, field);
 }
 
-Fragment StreamingFlowGraphBuilder::StoreInstanceField(TokenPosition position,
-                                                       intptr_t offset) {
-  return flow_graph_builder_->StoreInstanceField(position, offset);
-}
-
 Fragment StreamingFlowGraphBuilder::StringInterpolate(TokenPosition position) {
   return flow_graph_builder_->StringInterpolate(position);
 }
@@ -2566,12 +2605,13 @@
 }
 
 Fragment StreamingFlowGraphBuilder::CheckStackOverflow(TokenPosition position) {
-  return flow_graph_builder_->CheckStackOverflow(position);
+  return flow_graph_builder_->CheckStackOverflow(
+      position, flow_graph_builder_->loop_depth_);
 }
 
 Fragment StreamingFlowGraphBuilder::CloneContext(
-    intptr_t num_context_variables) {
-  return flow_graph_builder_->CloneContext(num_context_variables);
+    const GrowableArray<LocalVariable*>& context_variables) {
+  return flow_graph_builder_->CloneContext(context_variables);
 }
 
 Fragment StreamingFlowGraphBuilder::TranslateFinallyFinalizers(
@@ -2752,8 +2792,8 @@
 
 Fragment StreamingFlowGraphBuilder::EnterScope(
     intptr_t kernel_offset,
-    intptr_t* num_context_variables) {
-  return flow_graph_builder_->EnterScope(kernel_offset, num_context_variables);
+    const LocalScope** scope /* = nullptr */) {
+  return flow_graph_builder_->EnterScope(kernel_offset, scope);
 }
 
 Fragment StreamingFlowGraphBuilder::ExitScope(intptr_t kernel_offset) {
@@ -3027,7 +3067,7 @@
   bool is_unchecked_call = false;
 #ifndef TARGET_ARCH_DBC
   if (call_site_attributes.receiver_type != nullptr &&
-      call_site_attributes.receiver_type->HasResolvedTypeClass() &&
+      call_site_attributes.receiver_type->HasTypeClass() &&
       !Class::Handle(call_site_attributes.receiver_type->type_class())
            .IsGeneric()) {
     is_unchecked_call = true;
@@ -3317,9 +3357,11 @@
 
     SkipCanonicalNameReference();  // skip target_reference.
 
-    instructions +=
-        StaticCall(position, Function::ZoneHandle(Z, function.raw()),
-                   /* argument_count = */ 2, ICData::kSuper);
+    instructions += StaticCall(
+        position, Function::ZoneHandle(Z, function.raw()),
+        /* argument_count = */ 2, Array::null_array(), ICData::kSuper,
+        /*result_type=*/nullptr, /*type_args_len=*/0,
+        /*use_unchecked_entry=*/!FLAG_precompiled_mode);
     instructions += Drop();  // Drop result of the setter invocation.
   }
 
@@ -3565,7 +3607,7 @@
       SkipExpression();  // skip receiver
       is_unchecked_closure_call =
           ReadNameAsMethodName().Equals(Symbols::Call());
-    } else if (call_site_attributes.receiver_type->HasResolvedTypeClass() &&
+    } else if (call_site_attributes.receiver_type->HasTypeClass() &&
                !Class::Handle(call_site_attributes.receiver_type->type_class())
                     .IsGeneric()) {
       is_unchecked_call = true;
@@ -3703,7 +3745,7 @@
   if (is_unchecked_closure_call) {
     // Lookup the function in the closure.
     instructions += LoadLocal(receiver_temp);
-    instructions += LoadField(Closure::function_offset());
+    instructions += LoadNativeField(Slot::Closure_function());
     if (parsed_function()->function().is_debuggable()) {
       ASSERT(!parsed_function()->function().is_native());
       instructions += DebugStepCheck(position);
@@ -3961,7 +4003,8 @@
     return instructions +
            StaticCall(position, Function::ZoneHandle(Z, function.raw()),
                       argument_count, argument_names, ICData::kSuper,
-                      &result_type, type_args_len);
+                      &result_type, type_args_len,
+                      /*use_unchecked_entry_point=*/!FLAG_precompiled_mode);
   }
 }
 
@@ -4802,38 +4845,40 @@
 
   instructions += LoadLocal(new_closure);
   instructions += LoadLocal(type_args_vec);
-  instructions += StoreInstanceField(TokenPosition::kNoSource,
-                                     Closure::delayed_type_arguments_offset());
-
+  instructions += flow_graph_builder_->StoreInstanceField(
+      TokenPosition::kNoSource, Slot::Closure_delayed_type_arguments());
   instructions += Drop();  // Drop type args.
 
   // Copy over the target function.
   instructions += LoadLocal(new_closure);
   instructions += LoadLocal(original_closure);
-  instructions += LoadField(Closure::function_offset());
   instructions +=
-      StoreInstanceField(TokenPosition::kNoSource, Closure::function_offset());
+      flow_graph_builder_->LoadNativeField(Slot::Closure_function());
+  instructions += flow_graph_builder_->StoreInstanceField(
+      TokenPosition::kNoSource, Slot::Closure_function());
 
   // Copy over the instantiator type arguments.
   instructions += LoadLocal(new_closure);
   instructions += LoadLocal(original_closure);
-  instructions += LoadField(Closure::instantiator_type_arguments_offset());
-  instructions += StoreInstanceField(
-      TokenPosition::kNoSource, Closure::instantiator_type_arguments_offset());
+  instructions += flow_graph_builder_->LoadNativeField(
+      Slot::Closure_instantiator_type_arguments());
+  instructions += flow_graph_builder_->StoreInstanceField(
+      TokenPosition::kNoSource, Slot::Closure_instantiator_type_arguments());
 
   // Copy over the function type arguments.
   instructions += LoadLocal(new_closure);
   instructions += LoadLocal(original_closure);
-  instructions += LoadField(Closure::function_type_arguments_offset());
-  instructions += StoreInstanceField(TokenPosition::kNoSource,
-                                     Closure::function_type_arguments_offset());
+  instructions += flow_graph_builder_->LoadNativeField(
+      Slot::Closure_function_type_arguments());
+  instructions += flow_graph_builder_->StoreInstanceField(
+      TokenPosition::kNoSource, Slot::Closure_function_type_arguments());
 
   // Copy over the context.
   instructions += LoadLocal(new_closure);
   instructions += LoadLocal(original_closure);
-  instructions += LoadField(Closure::context_offset());
-  instructions +=
-      StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset());
+  instructions += flow_graph_builder_->LoadNativeField(Slot::Closure_context());
+  instructions += flow_graph_builder_->StoreInstanceField(
+      TokenPosition::kNoSource, Slot::Closure_context());
 
   instructions += DropTempsPreserveTop(1);  // Drop old closure.
 
@@ -5068,8 +5113,8 @@
 
   loop_depth_inc();
 
-  intptr_t num_context_variables = 0;
-  declarations += EnterScope(offset, &num_context_variables);
+  const LocalScope* context_scope = nullptr;
+  declarations += EnterScope(offset, &context_scope);
 
   intptr_t list_length = ReadListLength();  // read number of variables.
   for (intptr_t i = 0; i < list_length; ++i) {
@@ -5105,7 +5150,9 @@
     // the context object (at same depth) which ensures the next iteration of
     // the body gets a fresh set of [ForStatement] variables (with the old
     // (possibly updated) values).
-    if (num_context_variables > 0) body += CloneContext(num_context_variables);
+    if (context_scope->num_context_variables() > 0) {
+      body += CloneContext(context_scope->context_variables());
+    }
 
     body += updates;
     JoinEntryInstr* join = BuildJoinEntry();
@@ -5946,8 +5993,7 @@
     instructions += LoadLocal(closure);
     instructions += LoadInstantiatorTypeArguments();
     instructions += flow_graph_builder_->StoreInstanceField(
-        TokenPosition::kNoSource,
-        Closure::instantiator_type_arguments_offset());
+        TokenPosition::kNoSource, Slot::Closure_instantiator_type_arguments());
   }
 
   // TODO(30455): We only need to save these if the closure uses any captured
@@ -5955,23 +6001,23 @@
   instructions += LoadLocal(closure);
   instructions += LoadFunctionTypeArguments();
   instructions += flow_graph_builder_->StoreInstanceField(
-      TokenPosition::kNoSource, Closure::function_type_arguments_offset());
+      TokenPosition::kNoSource, Slot::Closure_function_type_arguments());
 
   instructions += LoadLocal(closure);
   instructions += Constant(Object::empty_type_arguments());
   instructions += flow_graph_builder_->StoreInstanceField(
-      TokenPosition::kNoSource, Closure::delayed_type_arguments_offset());
+      TokenPosition::kNoSource, Slot::Closure_delayed_type_arguments());
 
   // Store the function and the context in the closure.
   instructions += LoadLocal(closure);
   instructions += Constant(function);
   instructions += flow_graph_builder_->StoreInstanceField(
-      TokenPosition::kNoSource, Closure::function_offset());
+      TokenPosition::kNoSource, Slot::Closure_function());
 
   instructions += LoadLocal(closure);
   instructions += LoadLocal(parsed_function()->current_context_var());
   instructions += flow_graph_builder_->StoreInstanceField(
-      TokenPosition::kNoSource, Closure::context_offset());
+      TokenPosition::kNoSource, Slot::Closure_context());
 
   return instructions;
 }
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index d5a388b..644ab79 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -43,8 +43,7 @@
         direct_call_metadata_helper_(this),
         inferred_type_metadata_helper_(this),
         procedure_attributes_metadata_helper_(this),
-        call_site_attributes_metadata_helper_(this, &type_translator_) {
-  }
+        call_site_attributes_metadata_helper_(this, &type_translator_) {}
 
   virtual ~StreamingFlowGraphBuilder() {}
 
@@ -57,6 +56,8 @@
  private:
   bool optimizing();
 
+  Thread* thread() const { return flow_graph_builder_->thread_; }
+
   FlowGraph* BuildGraphOfFieldInitializer();
   FlowGraph* BuildGraphOfFieldAccessor(LocalVariable* setter_value);
   void SetupDefaultParameterValues();
@@ -127,7 +128,8 @@
   void CheckArgumentTypesAsNecessary(const Function& dart_function,
                                      intptr_t type_parameters_offset,
                                      Fragment* explicit_checks,
-                                     Fragment* implicit_checks);
+                                     Fragment* implicit_checks,
+                                     Fragment* implicit_redefinitions);
   Fragment CompleteBodyWithYieldContinuations(Fragment body);
   FunctionEntryInstr* BuildSeparateUncheckedEntryPoint(
       BlockEntryInstr* normal_entry,
@@ -138,6 +140,7 @@
   FunctionEntryInstr* BuildSharedUncheckedEntryPoint(
       Fragment prologue_from_normal_entry,
       Fragment skippable_checks,
+      Fragment redefinitions_if_skipped,
       Fragment body);
 
   Fragment BuildEntryPointsIntrospection();
@@ -206,6 +209,7 @@
   Fragment Constant(const Object& value);
   Fragment IntConstant(int64_t value);
   Fragment LoadStaticField();
+  Fragment RedefinitionWithType(const AbstractType& type);
   Fragment CheckNull(TokenPosition position,
                      LocalVariable* receiver,
                      const String& function_name,
@@ -220,7 +224,8 @@
                       const Array& argument_names,
                       ICData::RebindRule rebind_rule,
                       const InferredTypeMetadata* result_type = NULL,
-                      intptr_t type_args_len = 0);
+                      intptr_t type_args_len = 0,
+                      bool use_unchecked_entry = false);
   Fragment InstanceCall(TokenPosition position,
                         const String& name,
                         Token::Kind kind,
@@ -258,7 +263,8 @@
 
   void BuildArgumentTypeChecks(TypeChecksToBuild mode,
                                Fragment* explicit_checks,
-                               Fragment* implicit_checks);
+                               Fragment* implicit_checks,
+                               Fragment* implicit_redefinitions);
 
   Fragment ThrowException(TokenPosition position);
   Fragment BooleanNegate();
@@ -269,11 +275,11 @@
                           const Class& klass,
                           intptr_t argument_count);
   Fragment AllocateObject(const Class& klass, const Function& closure_function);
-  Fragment AllocateContext(intptr_t size);
-  Fragment LoadField(intptr_t offset);
+  Fragment AllocateContext(
+      const GrowableArray<LocalVariable*>& context_variables);
+  Fragment LoadNativeField(const Slot& field);
   Fragment StoreLocal(TokenPosition position, LocalVariable* variable);
   Fragment StoreStaticField(TokenPosition position, const Field& field);
-  Fragment StoreInstanceField(TokenPosition position, intptr_t offset);
   Fragment StringInterpolate(TokenPosition position);
   Fragment StringInterpolateSingle(TokenPosition position);
   Fragment ThrowTypeError();
@@ -283,7 +289,7 @@
   Fragment CreateArray();
   Fragment StoreIndexed(intptr_t class_id);
   Fragment CheckStackOverflow(TokenPosition position);
-  Fragment CloneContext(intptr_t num_context_variables);
+  Fragment CloneContext(const GrowableArray<LocalVariable*>& context_variables);
   Fragment TranslateFinallyFinalizers(TryFinallyBlock* outer_finally,
                                       intptr_t target_context_depth);
   Fragment BranchIfTrue(TargetEntryInstr** then_entry,
@@ -322,7 +328,7 @@
   Fragment CheckVariableTypeInCheckedMode(const AbstractType& dst_type,
                                           const String& name_symbol);
   Fragment EnterScope(intptr_t kernel_offset,
-                      intptr_t* num_context_variables = NULL);
+                      const LocalScope** scope = nullptr);
   Fragment ExitScope(intptr_t kernel_offset);
 
   TestFragment TranslateConditionForControl();
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index 1df89e8..005a1c5 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -289,7 +289,7 @@
 
   if (!simple) {
     // TODO(bkonyi): include in hash.
-    SkipCanonicalNameReference();  // read typedef reference.
+    SkipOptionalDartType();  // read typedef type.
   }
 
   CalculateDartTypeFingerprint();  // read return type.
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 88dbd35..e0420dc 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORp 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.
 
@@ -50,6 +50,7 @@
       optimizing_(optimizing),
       ic_data_array_(*ic_data_array),
       next_function_id_(0),
+      loop_depth_(0),
       try_depth_(0),
       catch_depth_(0),
       for_in_depth_(0),
@@ -67,17 +68,17 @@
 
 FlowGraphBuilder::~FlowGraphBuilder() {}
 
-Fragment FlowGraphBuilder::EnterScope(intptr_t kernel_offset,
-                                      intptr_t* num_context_variables) {
+Fragment FlowGraphBuilder::EnterScope(
+    intptr_t kernel_offset,
+    const LocalScope** context_scope /* = nullptr */) {
   Fragment instructions;
-  const intptr_t context_size =
-      scopes_->scopes.Lookup(kernel_offset)->num_context_variables();
-  if (context_size > 0) {
-    instructions += PushContext(context_size);
+  const LocalScope* scope = scopes_->scopes.Lookup(kernel_offset);
+  if (scope->num_context_variables() > 0) {
+    instructions += PushContext(scope);
     instructions += Drop();
   }
-  if (num_context_variables != NULL) {
-    *num_context_variables = context_size;
+  if (context_scope != nullptr) {
+    *context_scope = scope;
   }
   return instructions;
 }
@@ -105,14 +106,14 @@
   return instructions;
 }
 
-Fragment FlowGraphBuilder::PushContext(int size) {
-  ASSERT(size > 0);
-  Fragment instructions = AllocateContext(size);
+Fragment FlowGraphBuilder::PushContext(const LocalScope* scope) {
+  ASSERT(scope->num_context_variables() > 0);
+  Fragment instructions = AllocateContext(scope->context_variables());
   LocalVariable* context = MakeTemporary();
   instructions += LoadLocal(context);
   instructions += LoadLocal(parsed_function_->current_context_var());
   instructions +=
-      StoreInstanceField(TokenPosition::kNoSource, Context::parent_offset());
+      StoreInstanceField(TokenPosition::kNoSource, Slot::Context_parent());
   instructions += StoreLocal(TokenPosition::kNoSource,
                              parsed_function_->current_context_var());
   ++context_depth_;
@@ -141,7 +142,7 @@
     ASSERT(!parsed_function_->function().IsFactory());
     instructions += LoadLocal(scopes_->this_variable);
     instructions += LoadNativeField(
-        NativeFieldDesc::GetTypeArgumentsFieldFor(Z, *active_class_.klass));
+        Slot::GetTypeArgumentsSlotFor(thread_, *active_class_.klass));
   } else {
     instructions += NullConstant();
   }
@@ -180,10 +181,8 @@
   } else {
     // The [type_arguments] vector contains a type reference to a type
     // parameter we need to resolve it.
-    const bool use_instantiator =
-        type_arguments.IsUninstantiatedIdentity() ||
-        type_arguments.CanShareInstantiatorTypeArguments(*active_class_.klass);
-    if (use_instantiator) {
+    if (type_arguments.CanShareInstantiatorTypeArguments(
+            *active_class_.klass)) {
       // If the instantiator type arguments are just passed on, we don't need to
       // resolve the type parameters.
       //
@@ -194,6 +193,9 @@
       // We just use the type argument vector from the [Foo] object and pass it
       // directly to the `new List<T>()` factory constructor.
       instructions += LoadInstantiatorTypeArguments();
+    } else if (type_arguments.CanShareFunctionTypeArguments(
+                   parsed_function_->function())) {
+      instructions += LoadFunctionTypeArguments();
     } else {
       // Otherwise we need to resolve [TypeParameterType]s in the type
       // expression based on the current instantiator type argument vector.
@@ -265,7 +267,7 @@
     LocalVariable* closure_parameter = scope->VariableAt(0);
     ASSERT(!closure_parameter->is_captured());
     instructions += LoadLocal(closure_parameter);
-    instructions += LoadField(Closure::context_offset());
+    instructions += LoadNativeField(Slot::Closure_context());
     instructions += StoreLocal(TokenPosition::kNoSource, context_variable);
     instructions += Drop();
   }
@@ -275,14 +277,14 @@
     instructions += LoadLocal(raw_exception_var);
     instructions += StoreInstanceField(
         TokenPosition::kNoSource,
-        Context::variable_offset(exception_var->index().value()));
+        Slot::GetContextVariableSlotFor(thread_, *exception_var));
   }
   if (stacktrace_var->is_captured()) {
     instructions += LoadLocal(context_variable);
     instructions += LoadLocal(raw_stacktrace_var);
     instructions += StoreInstanceField(
         TokenPosition::kNoSource,
-        Context::variable_offset(stacktrace_var->index().value()));
+        Slot::GetContextVariableSlotFor(thread_, *stacktrace_var));
   }
 
   // :saved_try_context_var can be captured in the context of
@@ -324,19 +326,20 @@
   if (IsInlining()) {
     // If we are inlining don't actually attach the stack check.  We must still
     // create the stack check in order to allocate a deopt id.
-    CheckStackOverflow(position);
+    CheckStackOverflow(position, loop_depth_);
     return Fragment();
   }
-  return CheckStackOverflow(position);
+  return CheckStackOverflow(position, loop_depth_);
 }
 
-Fragment FlowGraphBuilder::CloneContext(intptr_t num_context_variables) {
+Fragment FlowGraphBuilder::CloneContext(
+    const GrowableArray<LocalVariable*>& context_variables) {
   LocalVariable* context_variable = parsed_function_->current_context_var();
 
   Fragment instructions = LoadLocal(context_variable);
 
   CloneContextInstr* clone_instruction = new (Z) CloneContextInstr(
-      TokenPosition::kNoSource, Pop(), num_context_variables, GetNextDeoptId());
+      TokenPosition::kNoSource, Pop(), context_variables, GetNextDeoptId());
   instructions <<= clone_instruction;
   Push(clone_instruction);
 
@@ -422,7 +425,7 @@
     Fragment instructions;
     instructions += LoadContextAt(variable->owner()->context_level());
     instructions +=
-        LoadField(Context::variable_offset(variable->index().value()));
+        LoadNativeField(Slot::GetContextVariableSlotFor(thread_, *variable));
     return instructions;
   } else {
     return BaseFlowGraphBuilder::LoadLocal(variable);
@@ -569,13 +572,17 @@
                                       const Array& argument_names,
                                       ICData::RebindRule rebind_rule,
                                       const InferredTypeMetadata* result_type,
-                                      intptr_t type_args_count) {
+                                      intptr_t type_args_count,
+                                      bool use_unchecked_entry) {
   const intptr_t total_count = argument_count + (type_args_count > 0 ? 1 : 0);
   ArgumentArray arguments = GetArguments(total_count);
   StaticCallInstr* call = new (Z)
       StaticCallInstr(position, target, type_args_count, argument_names,
                       arguments, ic_data_array_, GetNextDeoptId(), rebind_rule);
   SetResultTypeForStaticCall(call, target, argument_count, result_type);
+  if (use_unchecked_entry) {
+    call->set_entry_kind(Code::EntryKind::kUnchecked);
+  }
   Push(call);
   return Fragment(call);
 }
@@ -757,7 +764,7 @@
     case MethodRecognizer::kStringBaseLength:
     case MethodRecognizer::kStringBaseIsEmpty:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadNativeField(NativeFieldDesc::String_length());
+      body += LoadNativeField(Slot::String_length());
       if (kind == MethodRecognizer::kStringBaseIsEmpty) {
         body += IntConstant(0);
         body += StrictCompare(Token::kEQ_STRICT);
@@ -765,16 +772,16 @@
       break;
     case MethodRecognizer::kGrowableArrayLength:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadNativeField(NativeFieldDesc::GrowableObjectArray_length());
+      body += LoadNativeField(Slot::GrowableObjectArray_length());
       break;
     case MethodRecognizer::kObjectArrayLength:
     case MethodRecognizer::kImmutableArrayLength:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadNativeField(NativeFieldDesc::Array_length());
+      body += LoadNativeField(Slot::Array_length());
       break;
     case MethodRecognizer::kTypedDataLength:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadNativeField(NativeFieldDesc::TypedData_length());
+      body += LoadNativeField(Slot::TypedData_length());
       break;
     case MethodRecognizer::kClassIDgetID:
       body += LoadLocal(first_parameter);
@@ -782,8 +789,8 @@
       break;
     case MethodRecognizer::kGrowableArrayCapacity:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadField(GrowableObjectArray::data_offset(), kArrayCid);
-      body += LoadNativeField(NativeFieldDesc::Array_length());
+      body += LoadNativeField(Slot::GrowableObjectArray_data());
+      body += LoadNativeField(Slot::Array_length());
       break;
     case MethodRecognizer::kListFactory: {
       // factory List<E>([int length]) {
@@ -795,8 +802,7 @@
       TargetEntryInstr *allocate_non_growable, *allocate_growable;
 
       body += LoadArgDescriptor();
-      body +=
-          LoadField(ArgumentsDescriptor::positional_count_offset(), kSmiCid);
+      body += LoadNativeField(Slot::ArgumentsDescriptor_positional_count());
       body += IntConstant(2);
       body += BranchIfStrictEqual(&allocate_non_growable, &allocate_growable);
 
@@ -857,59 +863,59 @@
       break;
     case MethodRecognizer::kLinkedHashMap_getIndex:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadNativeField(NativeFieldDesc::LinkedHashMap_index());
+      body += LoadNativeField(Slot::LinkedHashMap_index());
       break;
     case MethodRecognizer::kLinkedHashMap_setIndex:
       body += LoadLocal(scopes_->this_variable);
       body += LoadLocal(first_parameter);
       body += StoreInstanceField(TokenPosition::kNoSource,
-                                 LinkedHashMap::index_offset());
+                                 Slot::LinkedHashMap_index());
       body += NullConstant();
       break;
     case MethodRecognizer::kLinkedHashMap_getData:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadNativeField(NativeFieldDesc::LinkedHashMap_data());
+      body += LoadNativeField(Slot::LinkedHashMap_data());
       break;
     case MethodRecognizer::kLinkedHashMap_setData:
       body += LoadLocal(scopes_->this_variable);
       body += LoadLocal(first_parameter);
       body += StoreInstanceField(TokenPosition::kNoSource,
-                                 LinkedHashMap::data_offset());
+                                 Slot::LinkedHashMap_data());
       body += NullConstant();
       break;
     case MethodRecognizer::kLinkedHashMap_getHashMask:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadNativeField(NativeFieldDesc::LinkedHashMap_hash_mask());
+      body += LoadNativeField(Slot::LinkedHashMap_hash_mask());
       break;
     case MethodRecognizer::kLinkedHashMap_setHashMask:
       body += LoadLocal(scopes_->this_variable);
       body += LoadLocal(first_parameter);
-      body += StoreInstanceField(TokenPosition::kNoSource,
-                                 LinkedHashMap::hash_mask_offset(),
-                                 kNoStoreBarrier);
+      body +=
+          StoreInstanceField(TokenPosition::kNoSource,
+                             Slot::LinkedHashMap_hash_mask(), kNoStoreBarrier);
       body += NullConstant();
       break;
     case MethodRecognizer::kLinkedHashMap_getUsedData:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadNativeField(NativeFieldDesc::LinkedHashMap_used_data());
+      body += LoadNativeField(Slot::LinkedHashMap_used_data());
       break;
     case MethodRecognizer::kLinkedHashMap_setUsedData:
       body += LoadLocal(scopes_->this_variable);
       body += LoadLocal(first_parameter);
-      body += StoreInstanceField(TokenPosition::kNoSource,
-                                 LinkedHashMap::used_data_offset(),
-                                 kNoStoreBarrier);
+      body +=
+          StoreInstanceField(TokenPosition::kNoSource,
+                             Slot::LinkedHashMap_used_data(), kNoStoreBarrier);
       body += NullConstant();
       break;
     case MethodRecognizer::kLinkedHashMap_getDeletedKeys:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadNativeField(NativeFieldDesc::LinkedHashMap_deleted_keys());
+      body += LoadNativeField(Slot::LinkedHashMap_deleted_keys());
       break;
     case MethodRecognizer::kLinkedHashMap_setDeletedKeys:
       body += LoadLocal(scopes_->this_variable);
       body += LoadLocal(first_parameter);
       body += StoreInstanceField(TokenPosition::kNoSource,
-                                 LinkedHashMap::deleted_keys_offset(),
+                                 Slot::LinkedHashMap_deleted_keys(),
                                  kNoStoreBarrier);
       body += NullConstant();
       break;
@@ -932,6 +938,42 @@
   return body + Return(TokenPosition::kNoSource, omit_result_type_check);
 }
 
+static Type& GetCanonicalType(Zone* Z, const Class& klass) {
+  ASSERT(!klass.IsNull());
+  // Note that if cls is _Closure, the returned type will be _Closure,
+  // and not the signature type.
+  Type& type = Type::ZoneHandle(Z, klass.CanonicalType());
+  if (!type.IsNull()) {
+    return type;
+  }
+  type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()),
+                   klass.token_pos());
+  if (klass.is_type_finalized()) {
+    type ^= ClassFinalizer::FinalizeType(klass, type);
+    // Note that the receiver type may now be a malbounded type.
+    klass.SetCanonicalType(type);
+  }
+  return type;
+}
+
+static const LocalScope* MakeImplicitClosureScope(Zone* Z,
+                                                  const Function& function) {
+  Class& klass = Class::Handle(Z, function.Owner());
+  Type& klass_type = GetCanonicalType(Z, klass);
+
+  LocalVariable* this_variable = new (Z)
+      LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
+                    Symbols::This(), klass_type, /*param_type=*/nullptr);
+
+  this_variable->set_is_captured();
+  //  this_variable->set_is_final();
+  LocalScope* scope = new (Z) LocalScope(NULL, 0, 0);
+  scope->set_context_level(0);
+  scope->AddVariable(this_variable);
+  scope->AddContextVariable(this_variable);
+  return scope;
+}
+
 Fragment FlowGraphBuilder::BuildImplicitClosureCreation(
     const Function& target) {
   Fragment fragment;
@@ -944,9 +986,8 @@
   if (!target.HasInstantiatedSignature(kCurrentClass)) {
     fragment += LoadLocal(closure);
     fragment += LoadInstantiatorTypeArguments();
-    fragment +=
-        StoreInstanceField(TokenPosition::kNoSource,
-                           Closure::instantiator_type_arguments_offset());
+    fragment += StoreInstanceField(TokenPosition::kNoSource,
+                                   Slot::Closure_instantiator_type_arguments());
   }
 
   // The function signature cannot have uninstantiated function type parameters,
@@ -954,31 +995,36 @@
   ASSERT(target.HasInstantiatedSignature(kFunctions));
 
   // Allocate a context that closes over `this`.
-  fragment += AllocateContext(1);
+  // Note: this must be kept in sync with ScopeBuilder::BuildScopes.
+  const LocalScope* implicit_closure_scope =
+      MakeImplicitClosureScope(Z, target);
+  fragment += AllocateContext(implicit_closure_scope->context_variables());
   LocalVariable* context = MakeTemporary();
 
   // Store the function and the context in the closure.
   fragment += LoadLocal(closure);
   fragment += Constant(target);
   fragment +=
-      StoreInstanceField(TokenPosition::kNoSource, Closure::function_offset());
+      StoreInstanceField(TokenPosition::kNoSource, Slot::Closure_function());
 
   fragment += LoadLocal(closure);
   fragment += LoadLocal(context);
   fragment +=
-      StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset());
+      StoreInstanceField(TokenPosition::kNoSource, Slot::Closure_context());
 
   fragment += LoadLocal(closure);
   fragment += Constant(Object::empty_type_arguments());
   fragment += StoreInstanceField(TokenPosition::kNoSource,
-                                 Closure::delayed_type_arguments_offset());
+                                 Slot::Closure_delayed_type_arguments());
 
   // The context is on top of the operand stack.  Store `this`.  The context
   // doesn't need a parent pointer because it doesn't close over anything
   // else.
   fragment += LoadLocal(scopes_->this_variable);
-  fragment +=
-      StoreInstanceField(TokenPosition::kNoSource, Context::variable_offset(0));
+  fragment += StoreInstanceField(
+      TokenPosition::kNoSource,
+      Slot::GetContextVariableSlotFor(
+          thread_, *implicit_closure_scope->context_variables()[0]));
 
   return fragment;
 }
@@ -1361,7 +1407,7 @@
   if (is_closure_call) {
     // Lookup the function in the closure.
     body += LoadLocal(closure);
-    body += LoadField(Closure::function_offset());
+    body += LoadNativeField(Slot::Closure_function());
 
     body += ClosureCall(TokenPosition::kNoSource, descriptor.TypeArgsLen(),
                         descriptor.Count(), argument_names);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 7607105..4a95aa3 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -67,12 +67,12 @@
                               LocalVariable* first_parameter);
 
   Fragment EnterScope(intptr_t kernel_offset,
-                      intptr_t* num_context_variables = NULL);
+                      const LocalScope** scope = nullptr);
   Fragment ExitScope(intptr_t kernel_offset);
 
   Fragment AdjustContextTo(int depth);
 
-  Fragment PushContext(int size);
+  Fragment PushContext(const LocalScope* scope);
   Fragment PopContext();
 
   Fragment LoadInstantiatorTypeArguments();
@@ -90,7 +90,7 @@
                            bool is_synthesized);
   Fragment TryCatch(int try_handler_index);
   Fragment CheckStackOverflowInPrologue(TokenPosition position);
-  Fragment CloneContext(intptr_t num_context_variables);
+  Fragment CloneContext(const GrowableArray<LocalVariable*>& context_variables);
 
   Fragment InstanceCall(
       TokenPosition position,
@@ -135,7 +135,8 @@
                       const Array& argument_names,
                       ICData::RebindRule rebind_rule,
                       const InferredTypeMetadata* result_type = NULL,
-                      intptr_t type_args_len = 0);
+                      intptr_t type_args_len = 0,
+                      bool use_unchecked_entry = false);
   Fragment StoreInstanceFieldGuarded(const Field& field,
                                      bool is_initialization_store);
   Fragment StringInterpolate(TokenPosition position);
@@ -180,6 +181,7 @@
   intptr_t next_function_id_;
   intptr_t AllocateFunctionId() { return next_function_id_++; }
 
+  intptr_t loop_depth_;
   intptr_t try_depth_;
   intptr_t catch_depth_;
   intptr_t for_in_depth_;
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index df8096b..3f7837b 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -100,6 +100,7 @@
 void TranslationHelper::SetMetadataPayloads(
     const ExternalTypedData& metadata_payloads) {
   ASSERT(metadata_payloads_.IsNull());
+  ASSERT(Utils::IsAligned(metadata_payloads.DataAddr(0), kWordSize));
   metadata_payloads_ = metadata_payloads.raw();
 }
 
@@ -1937,6 +1938,10 @@
     case kSimpleFunctionType:
       SkipFunctionType(true);
       return;
+    case kTypedefType:
+      ReadUInt();             // read index for canonical name.
+      SkipListOfDartTypes();  // read list of types.
+      return;
     case kTypeParameterType:
       ReadUInt();              // read index for parameter.
       SkipOptionalDartType();  // read bound bound.
@@ -1984,7 +1989,7 @@
   }
 
   if (!simple) {
-    SkipCanonicalNameReference();  // read typedef reference.
+    SkipOptionalDartType();  // read typedef type.
   }
 
   SkipDartType();  // read return type.
@@ -2868,7 +2873,7 @@
   }
 
   if (!simple) {
-    helper_->SkipCanonicalNameReference();  // read typedef reference.
+    helper_->SkipOptionalDartType();  // read typedef type.
   }
 
   BuildTypeInternal();  // read return type.
diff --git a/runtime/vm/compiler/frontend/prologue_builder.cc b/runtime/vm/compiler/frontend/prologue_builder.cc
index a63ae30..a08c6db 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.cc
+++ b/runtime/vm/compiler/frontend/prologue_builder.cc
@@ -95,8 +95,7 @@
   // If expect_type_args, a non-zero length must match the declaration length.
   TargetEntryInstr *then, *fail;
   check_type_args += LoadArgDescriptor();
-  check_type_args += LoadNativeField(NativeFieldDesc::Get(
-      NativeFieldDesc::kArgumentsDescriptor_type_args_len));
+  check_type_args += LoadNativeField(Slot::ArgumentsDescriptor_type_args_len());
   if (expect_type_args) {
     JoinEntryInstr* join2 = BuildJoinEntry();
 
@@ -146,11 +145,11 @@
 
   copy_args_prologue += LoadArgDescriptor();
   copy_args_prologue +=
-      LoadField(ArgumentsDescriptor::positional_count_offset());
+      LoadNativeField(Slot::ArgumentsDescriptor_positional_count());
   LocalVariable* positional_count_var = MakeTemporary();
 
   copy_args_prologue += LoadArgDescriptor();
-  copy_args_prologue += LoadField(ArgumentsDescriptor::count_offset());
+  copy_args_prologue += LoadNativeField(Slot::ArgumentsDescriptor_count());
   LocalVariable* count_var = MakeTemporary();
 
   // Ensure the caller provided at least [min_num_pos_args] arguments.
@@ -363,7 +362,7 @@
   JoinEntryInstr* done = BuildJoinEntry();
 
   check_args += LoadArgDescriptor();
-  check_args += LoadField(ArgumentsDescriptor::count_offset());
+  check_args += LoadNativeField(Slot::ArgumentsDescriptor_count());
   LocalVariable* count = MakeTemporary();
 
   TargetEntryInstr *then, *fail;
@@ -374,7 +373,7 @@
   TargetEntryInstr *then2, *fail2;
   Fragment check_len(then);
   check_len += LoadArgDescriptor();
-  check_len += LoadField(ArgumentsDescriptor::positional_count_offset());
+  check_len += LoadNativeField(Slot::ArgumentsDescriptor_positional_count());
   check_len += BranchIfEqual(&then2, &fail2);
 
   Fragment(fail) + Goto(nsm);
@@ -394,7 +393,7 @@
   // (both load/store happen on the copyied-down places).
   Fragment populate_context;
   populate_context += LoadLocal(closure_parameter);
-  populate_context += LoadField(Closure::context_offset());
+  populate_context += LoadNativeField(Slot::Closure_context());
   populate_context += StoreLocal(TokenPosition::kNoSource, context);
   populate_context += Drop();
   return populate_context;
@@ -407,7 +406,7 @@
 
   Fragment store_type_args;
   store_type_args += LoadArgDescriptor();
-  store_type_args += LoadField(ArgumentsDescriptor::count_offset());
+  store_type_args += LoadNativeField(Slot::ArgumentsDescriptor_count());
   store_type_args += LoadFpRelativeSlot(
       kWordSize * (1 + compiler_frame_layout.param_end_from_fp));
   store_type_args += StoreLocal(TokenPosition::kNoSource, type_args_var);
@@ -430,7 +429,7 @@
     Fragment use_delayed_type_args;
     use_delayed_type_args += LoadLocal(closure);
     use_delayed_type_args +=
-        LoadField(Closure::delayed_type_arguments_offset());
+        LoadNativeField(Slot::Closure_delayed_type_arguments());
     use_delayed_type_args +=
         StoreLocal(TokenPosition::kNoSource, type_args_var);
     use_delayed_type_args += Drop();
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index 09b239b..410e903 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -99,11 +99,11 @@
     result_->this_variable =
         MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                      Symbols::This(), klass_type);
-    result_->this_variable->set_index(VariableIndex(0));
     result_->this_variable->set_is_captured();
     enclosing_scope = new (Z) LocalScope(NULL, 0, 0);
     enclosing_scope->set_context_level(0);
     enclosing_scope->AddVariable(result_->this_variable);
+    enclosing_scope->AddContextVariable(result_->this_variable);
   } else if (function.IsLocalFunction()) {
     enclosing_scope = LocalScope::RestoreOuterScope(
         ContextScope::Handle(Z, function.context_scope()));
@@ -299,9 +299,10 @@
           FieldHelper field_helper(&helper_);
           field_helper.ReadUntilIncluding(FieldHelper::kFlags);
 
-          if (!field_helper.IsCovariant() &&
-              (!field_helper.IsGenericCovariantImpl() ||
-               (!attrs.has_non_this_uses && !attrs.has_tearoff_uses))) {
+          if (field_helper.IsCovariant()) {
+            result_->setter_value->set_is_explicit_covariant_parameter();
+          } else if (!field_helper.IsGenericCovariantImpl() ||
+                     (!attrs.has_non_this_uses && !attrs.has_tearoff_uses)) {
             result_->setter_value->set_type_check_mode(
                 LocalVariable::kTypeCheckedByCaller);
           }
@@ -1292,7 +1293,7 @@
   }
 
   if (!simple) {
-    helper_.SkipCanonicalNameReference();  // read typedef reference.
+    helper_.SkipOptionalDartType();  // read typedef reference.
   }
 
   VisitDartType();  // read return type.
@@ -1428,6 +1429,9 @@
   if (helper.IsFinal()) {
     variable->set_is_final();
   }
+  if (helper.IsCovariant()) {
+    variable->set_is_explicit_covariant_parameter();
+  }
   if (variable->name().raw() == Symbols::IteratorParameter().raw()) {
     variable->set_is_forced_stack();
   }
diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc
index 7537204..bf445f5 100644
--- a/runtime/vm/compiler/intrinsifier.cc
+++ b/runtime/vm/compiler/intrinsifier.cc
@@ -480,10 +480,9 @@
 static void PrepareIndexedOp(BlockBuilder* builder,
                              Definition* array,
                              Definition* index,
-                             intptr_t length_offset) {
+                             const Slot& length_field) {
   Definition* length = builder->AddDefinition(new LoadFieldInstr(
-      new Value(array), length_offset, Type::ZoneHandle(Type::SmiType()),
-      TokenPosition::kNoSource));
+      new Value(array), length_field, TokenPosition::kNoSource));
   builder->AddInstruction(new CheckArrayBoundInstr(
       new Value(length), new Value(index), DeoptId::kNone));
 }
@@ -497,14 +496,8 @@
   Definition* index = builder.AddParameter(1);
   Definition* array = builder.AddParameter(2);
 
-  intptr_t length_offset = Array::length_offset();
-  if (RawObject::IsTypedDataClassId(array_cid)) {
-    length_offset = TypedData::length_offset();
-  } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
-    length_offset = ExternalTypedData::length_offset();
-  }
-
-  PrepareIndexedOp(&builder, array, index, length_offset);
+  PrepareIndexedOp(&builder, array, index,
+                   Slot::GetLengthFieldForArrayCid(array_cid));
 
   if (RawObject::IsExternalTypedDataClassId(array_cid)) {
     array = builder.AddDefinition(new LoadUntaggedInstr(
@@ -581,14 +574,8 @@
   Definition* index = builder.AddParameter(2);
   Definition* array = builder.AddParameter(3);
 
-  intptr_t length_offset = Array::length_offset();
-  if (RawObject::IsTypedDataClassId(array_cid)) {
-    length_offset = TypedData::length_offset();
-  } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
-    length_offset = ExternalTypedData::length_offset();
-  }
-
-  PrepareIndexedOp(&builder, array, index, length_offset);
+  PrepareIndexedOp(&builder, array, index,
+                   Slot::GetLengthFieldForArrayCid(array_cid));
 
   // Value check/conversion.
   switch (array_cid) {
@@ -689,7 +676,7 @@
                         MethodRecognizer::k##enum_name##SetIndexed));          \
   }
 
-DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray)  // Setter in intrinsifier_<arch>.cc.
+DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray)
 DEFINE_ARRAY_GETTER_INTRINSIC(ImmutableArray)
 
 #define DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(enum_name)                       \
@@ -782,7 +769,7 @@
 
   Definition* index = builder.AddParameter(1);
   Definition* str = builder.AddParameter(2);
-  PrepareIndexedOp(&builder, str, index, String::length_offset());
+  PrepareIndexedOp(&builder, str, index, Slot::String_length());
 
   // For external strings: Load external data.
   if (cid == kExternalOneByteStringCid) {
@@ -907,37 +894,37 @@
                                MethodRecognizer::kFloat32x4ShuffleW);
 }
 
-static bool BuildLoadField(FlowGraph* flow_graph, intptr_t offset) {
+static bool BuildLoadField(FlowGraph* flow_graph, const Slot& field) {
   GraphEntryInstr* graph_entry = flow_graph->graph_entry();
   auto normal_entry = graph_entry->normal_entry();
   BlockBuilder builder(flow_graph, normal_entry);
 
   Definition* array = builder.AddParameter(1);
 
-  Definition* length = builder.AddDefinition(new LoadFieldInstr(
-      new Value(array), offset, Type::ZoneHandle(), builder.TokenPos()));
+  Definition* length = builder.AddDefinition(
+      new LoadFieldInstr(new Value(array), field, builder.TokenPos()));
   builder.AddIntrinsicReturn(new Value(length));
   return true;
 }
 
 bool Intrinsifier::Build_ObjectArrayLength(FlowGraph* flow_graph) {
-  return BuildLoadField(flow_graph, Array::length_offset());
+  return BuildLoadField(flow_graph, Slot::Array_length());
 }
 
 bool Intrinsifier::Build_ImmutableArrayLength(FlowGraph* flow_graph) {
-  return BuildLoadField(flow_graph, Array::length_offset());
+  return BuildLoadField(flow_graph, Slot::Array_length());
 }
 
 bool Intrinsifier::Build_GrowableArrayLength(FlowGraph* flow_graph) {
-  return BuildLoadField(flow_graph, GrowableObjectArray::length_offset());
+  return BuildLoadField(flow_graph, Slot::GrowableObjectArray_length());
 }
 
 bool Intrinsifier::Build_StringBaseLength(FlowGraph* flow_graph) {
-  return BuildLoadField(flow_graph, String::length_offset());
+  return BuildLoadField(flow_graph, Slot::String_length());
 }
 
 bool Intrinsifier::Build_TypedDataLength(FlowGraph* flow_graph) {
-  return BuildLoadField(flow_graph, TypedData::length_offset());
+  return BuildLoadField(flow_graph, Slot::TypedData_length());
 }
 
 bool Intrinsifier::Build_GrowableArrayCapacity(FlowGraph* flow_graph) {
@@ -947,12 +934,10 @@
 
   Definition* array = builder.AddParameter(1);
 
-  Definition* backing_store = builder.AddDefinition(
-      new LoadFieldInstr(new Value(array), GrowableObjectArray::data_offset(),
-                         Type::ZoneHandle(), builder.TokenPos()));
-  Definition* capacity = builder.AddDefinition(
-      new LoadFieldInstr(new Value(backing_store), Array::length_offset(),
-                         Type::ZoneHandle(), builder.TokenPos()));
+  Definition* backing_store = builder.AddDefinition(new LoadFieldInstr(
+      new Value(array), Slot::GrowableObjectArray_data(), builder.TokenPos()));
+  Definition* capacity = builder.AddDefinition(new LoadFieldInstr(
+      new Value(backing_store), Slot::Array_length(), builder.TokenPos()));
   builder.AddIntrinsicReturn(new Value(capacity));
   return true;
 }
@@ -966,11 +951,11 @@
   Definition* growable_array = builder.AddParameter(2);
 
   PrepareIndexedOp(&builder, growable_array, index,
-                   GrowableObjectArray::length_offset());
+                   Slot::GrowableObjectArray_length());
 
-  Definition* backing_store = builder.AddDefinition(new LoadFieldInstr(
-      new Value(growable_array), GrowableObjectArray::data_offset(),
-      Type::ZoneHandle(), builder.TokenPos()));
+  Definition* backing_store = builder.AddDefinition(
+      new LoadFieldInstr(new Value(growable_array),
+                         Slot::GrowableObjectArray_data(), builder.TokenPos()));
   Definition* result = builder.AddDefinition(new LoadIndexedInstr(
       new Value(backing_store), new Value(index),
       Instance::ElementSizeFor(kArrayCid),  // index scale
@@ -979,13 +964,33 @@
   return true;
 }
 
-void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler,
-                                         Label* normal_ir_body) {
+bool Intrinsifier::Build_ObjectArraySetIndexed(FlowGraph* flow_graph) {
   if (Isolate::Current()->argument_type_checks()) {
-    return;
+    return false;
   }
 
-  ObjectArraySetIndexedUnchecked(assembler, normal_ir_body);
+  return Build_ObjectArraySetIndexedUnchecked(flow_graph);
+}
+
+bool Intrinsifier::Build_ObjectArraySetIndexedUnchecked(FlowGraph* flow_graph) {
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* value = builder.AddParameter(1);
+  Definition* index = builder.AddParameter(2);
+  Definition* array = builder.AddParameter(3);
+
+  PrepareIndexedOp(&builder, array, index, Slot::Array_length());
+
+  builder.AddInstruction(new StoreIndexedInstr(
+      new Value(array), new Value(index), new Value(value), kEmitStoreBarrier,
+      Instance::ElementSizeFor(kArrayCid),  // index scale
+      kArrayCid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+  // Return null.
+  Definition* null_def = builder.AddNullDefinition();
+  builder.AddIntrinsicReturn(new Value(null_def));
+  return true;
 }
 
 bool Intrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) {
@@ -1006,12 +1011,10 @@
   Definition* index = builder.AddParameter(2);
   Definition* array = builder.AddParameter(3);
 
-  PrepareIndexedOp(&builder, array, index,
-                   GrowableObjectArray::length_offset());
+  PrepareIndexedOp(&builder, array, index, Slot::GrowableObjectArray_length());
 
-  Definition* backing_store = builder.AddDefinition(
-      new LoadFieldInstr(new Value(array), GrowableObjectArray::data_offset(),
-                         Type::ZoneHandle(), builder.TokenPos()));
+  Definition* backing_store = builder.AddDefinition(new LoadFieldInstr(
+      new Value(array), Slot::GrowableObjectArray_data(), builder.TokenPos()));
 
   builder.AddInstruction(new StoreIndexedInstr(
       new Value(backing_store), new Value(index), new Value(value),
@@ -1038,7 +1041,7 @@
                                              *value_check, builder.TokenPos()));
 
   builder.AddInstruction(new StoreInstanceFieldInstr(
-      GrowableObjectArray::data_offset(), new Value(growable_array),
+      Slot::GrowableObjectArray_data(), new Value(growable_array),
       new Value(data), kEmitStoreBarrier, builder.TokenPos()));
   // Return null.
   Definition* null_def = builder.AddNullDefinition();
@@ -1057,7 +1060,7 @@
   builder.AddInstruction(
       new CheckSmiInstr(new Value(length), DeoptId::kNone, builder.TokenPos()));
   builder.AddInstruction(new StoreInstanceFieldInstr(
-      GrowableObjectArray::length_offset(), new Value(growable_array),
+      Slot::GrowableObjectArray_length(), new Value(growable_array),
       new Value(length), kNoStoreBarrier, builder.TokenPos()));
   Definition* null_def = builder.AddNullDefinition();
   builder.AddIntrinsicReturn(new Value(null_def));
diff --git a/runtime/vm/compiler/intrinsifier_arm.cc b/runtime/vm/compiler/intrinsifier_arm.cc
index 920b211..bd5a15d 100644
--- a/runtime/vm/compiler/intrinsifier_arm.cc
+++ b/runtime/vm/compiler/intrinsifier_arm.cc
@@ -53,31 +53,6 @@
   assembler->mov(LR, Operand(CALLEE_SAVED_TEMP));
 }
 
-// Intrinsify only for Smi index.
-void Intrinsifier::ObjectArraySetIndexedUnchecked(Assembler* assembler,
-                                                  Label* normal_ir_body) {
-  __ ldr(R1, Address(SP, 1 * kWordSize));  // Index.
-  __ tst(R1, Operand(kSmiTagMask));
-  // Index not Smi.
-  __ b(normal_ir_body, NE);
-  __ ldr(R0, Address(SP, 2 * kWordSize));  // Array.
-
-  // Range check.
-  __ ldr(R3, FieldAddress(R0, Array::length_offset()));  // Array length.
-  __ cmp(R1, Operand(R3));
-  // Runtime throws exception.
-  __ b(normal_ir_body, CS);
-
-  // Note that R1 is Smi, i.e, times 2.
-  ASSERT(kSmiTagShift == 1);
-  __ ldr(R2, Address(SP, 0 * kWordSize));  // Value.
-  __ add(R1, R0, Operand(R1, LSL, 1));     // R1 is Smi.
-  __ StoreIntoObject(R0, FieldAddress(R1, Array::data_offset()), R2);
-  // Caller is responsible for preserving the value if necessary.
-  __ Ret();
-  __ Bind(normal_ir_body);
-}
-
 // Allocate a GrowableObjectArray using the backing array specified.
 // On stack: type argument (+1), data (+0).
 void Intrinsifier::GrowableArray_Allocate(Assembler* assembler,
@@ -112,40 +87,6 @@
   __ Bind(normal_ir_body);
 }
 
-// Add an element to growable array if it doesn't need to grow, otherwise
-// call into regular code.
-// On stack: growable array (+1), value (+0).
-void Intrinsifier::GrowableArray_add(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  // In checked mode we need to type-check the incoming argument.
-  if (Isolate::Current()->argument_type_checks()) {
-    return;
-  }
-  // R0: Array.
-  __ ldr(R0, Address(SP, 1 * kWordSize));
-  // R1: length.
-  __ ldr(R1, FieldAddress(R0, GrowableObjectArray::length_offset()));
-  // R2: data.
-  __ ldr(R2, FieldAddress(R0, GrowableObjectArray::data_offset()));
-  // R3: capacity.
-  __ ldr(R3, FieldAddress(R2, Array::length_offset()));
-  // Compare length with capacity.
-  __ cmp(R1, Operand(R3));
-  __ b(normal_ir_body, EQ);  // Must grow data.
-  const int32_t value_one = reinterpret_cast<int32_t>(Smi::New(1));
-  // len = len + 1;
-  __ add(R3, R1, Operand(value_one));
-  __ StoreIntoSmiField(FieldAddress(R0, GrowableObjectArray::length_offset()),
-                       R3);
-  __ ldr(R0, Address(SP, 0 * kWordSize));  // Value.
-  ASSERT(kSmiTagShift == 1);
-  __ add(R1, R2, Operand(R1, LSL, 1));
-  __ StoreIntoObject(R2, FieldAddress(R1, Array::data_offset()), R0);
-  __ LoadObject(R0, Object::null_object());
-  __ Ret();
-  __ Bind(normal_ir_body);
-}
-
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \
diff --git a/runtime/vm/compiler/intrinsifier_arm64.cc b/runtime/vm/compiler/intrinsifier_arm64.cc
index 96773e5..e8f925b 100644
--- a/runtime/vm/compiler/intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/intrinsifier_arm64.cc
@@ -57,29 +57,6 @@
   assembler->mov(ARGS_DESC_REG, CALLEE_SAVED_TEMP2);
 }
 
-// Intrinsify only for Smi index.
-void Intrinsifier::ObjectArraySetIndexedUnchecked(Assembler* assembler,
-                                                  Label* normal_ir_body) {
-  __ ldr(R1, Address(SP, 1 * kWordSize));  // Index.
-  __ BranchIfNotSmi(R1, normal_ir_body);
-  __ ldr(R0, Address(SP, 2 * kWordSize));  // Array.
-
-  // Range check.
-  __ ldr(R3, FieldAddress(R0, Array::length_offset()));  // Array length.
-  __ cmp(R1, Operand(R3));
-  // Runtime throws exception.
-  __ b(normal_ir_body, CS);
-
-  // Note that R1 is Smi, i.e, times 2.
-  ASSERT(kSmiTagShift == 1);
-  __ ldr(R2, Address(SP, 0 * kWordSize));  // Value.
-  __ add(R1, R0, Operand(R1, LSL, 2));     // R1 is Smi.
-  __ StoreIntoObject(R0, FieldAddress(R1, Array::data_offset()), R2);
-  // Caller is responsible for preserving the value if necessary.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
 // Allocate a GrowableObjectArray using the backing array specified.
 // On stack: type argument (+1), data (+0).
 void Intrinsifier::GrowableArray_Allocate(Assembler* assembler,
@@ -113,39 +90,6 @@
   __ Bind(normal_ir_body);
 }
 
-// Add an element to growable array if it doesn't need to grow, otherwise
-// call into regular code.
-// On stack: growable array (+1), value (+0).
-void Intrinsifier::GrowableArray_add(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  // In checked mode we need to type-check the incoming argument.
-  if (Isolate::Current()->argument_type_checks()) {
-    return;
-  }
-  // R0: Array.
-  __ ldr(R0, Address(SP, 1 * kWordSize));
-  // R1: length.
-  __ ldr(R1, FieldAddress(R0, GrowableObjectArray::length_offset()));
-  // R2: data.
-  __ ldr(R2, FieldAddress(R0, GrowableObjectArray::data_offset()));
-  // R3: capacity.
-  __ ldr(R3, FieldAddress(R2, Array::length_offset()));
-  // Compare length with capacity.
-  __ cmp(R1, Operand(R3));
-  __ b(normal_ir_body, EQ);  // Must grow data.
-  const int64_t value_one = reinterpret_cast<int64_t>(Smi::New(1));
-  // len = len + 1;
-  __ add(R3, R1, Operand(value_one));
-  __ str(R3, FieldAddress(R0, GrowableObjectArray::length_offset()));
-  __ ldr(R0, Address(SP, 0 * kWordSize));  // Value.
-  ASSERT(kSmiTagShift == 1);
-  __ add(R1, R2, Operand(R1, LSL, 2));
-  __ StoreIntoObject(R2, FieldAddress(R1, Array::data_offset()), R0);
-  __ LoadObject(R0, Object::null_object());
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
 static int GetScaleFactor(intptr_t size) {
   switch (size) {
     case 1:
diff --git a/runtime/vm/compiler/intrinsifier_ia32.cc b/runtime/vm/compiler/intrinsifier_ia32.cc
index c97906c..395c165 100644
--- a/runtime/vm/compiler/intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/intrinsifier_ia32.cc
@@ -52,29 +52,6 @@
   assembler->movl(ARGS_DESC_REG, CALLEE_SAVED_TEMP);
 }
 
-// Intrinsify only for Smi index.
-void Intrinsifier::ObjectArraySetIndexedUnchecked(Assembler* assembler,
-                                                  Label* normal_ir_body) {
-  __ movl(EBX, Address(ESP, +2 * kWordSize));  // Index.
-  __ testl(EBX, Immediate(kSmiTagMask));
-  // Index not Smi.
-  __ j(NOT_ZERO, normal_ir_body);
-  __ movl(EAX, Address(ESP, +3 * kWordSize));  // Array.
-  // Range check.
-  __ cmpl(EBX, FieldAddress(EAX, Array::length_offset()));
-  // Runtime throws exception.
-  __ j(ABOVE_EQUAL, normal_ir_body);
-  // Note that EBX is Smi, i.e, times 2.
-  ASSERT(kSmiTagShift == 1);
-  // Destroy ECX (ic data) as we will not continue in the function.
-  __ movl(ECX, Address(ESP, +1 * kWordSize));  // Value.
-  __ StoreIntoObject(EAX, FieldAddress(EAX, EBX, TIMES_2, Array::data_offset()),
-                     ECX);
-  // Caller is responsible of preserving the value if necessary.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
 // Allocate a GrowableObjectArray using the backing array specified.
 // On stack: type argument (+2), data (+1), return-address (+0).
 void Intrinsifier::GrowableArray_Allocate(Assembler* assembler,
@@ -110,35 +87,6 @@
   __ Bind(normal_ir_body);
 }
 
-// Add an element to growable array if it doesn't need to grow, otherwise
-// call into regular code.
-// On stack: growable array (+2), value (+1), return-address (+0).
-void Intrinsifier::GrowableArray_add(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  // In checked mode we need to type-check the incoming argument.
-  if (Isolate::Current()->argument_type_checks()) return;
-
-  __ movl(EAX, Address(ESP, +2 * kWordSize));  // Array.
-  __ movl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset()));
-  // EBX: length.
-  __ movl(EDI, FieldAddress(EAX, GrowableObjectArray::data_offset()));
-  // EDI: data.
-  // Compare length with capacity.
-  __ cmpl(EBX, FieldAddress(EDI, Array::length_offset()));
-  __ j(EQUAL, normal_ir_body);  // Must grow data.
-  __ IncrementSmiField(FieldAddress(EAX, GrowableObjectArray::length_offset()),
-                       1);
-  __ movl(EAX, Address(ESP, +1 * kWordSize));  // Value
-  ASSERT(kSmiTagShift == 1);
-  __ StoreIntoObject(EDI, FieldAddress(EDI, EBX, TIMES_2, Array::data_offset()),
-                     EAX);
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<int32_t>(Object::null()));
-  __ movl(EAX, raw_null);
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor)          \
   const intptr_t kArrayLengthStackOffset = 1 * kWordSize;                      \
   NOT_IN_PRODUCT(__ MaybeTraceAllocation(cid, EDI, normal_ir_body, false));    \
diff --git a/runtime/vm/compiler/intrinsifier_x64.cc b/runtime/vm/compiler/intrinsifier_x64.cc
index 57975e5..91b1cc8 100644
--- a/runtime/vm/compiler/intrinsifier_x64.cc
+++ b/runtime/vm/compiler/intrinsifier_x64.cc
@@ -52,27 +52,6 @@
   assembler->movq(ARGS_DESC_REG, CALLEE_SAVED_TEMP);
 }
 
-void Intrinsifier::ObjectArraySetIndexedUnchecked(Assembler* assembler,
-                                                  Label* normal_ir_body) {
-  __ movq(RDX, Address(RSP, +1 * kWordSize));  // Value.
-  __ movq(RCX, Address(RSP, +2 * kWordSize));  // Index.
-  __ movq(RAX, Address(RSP, +3 * kWordSize));  // Array.
-  __ testq(RCX, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, normal_ir_body);
-  // Range check.
-  __ cmpq(RCX, FieldAddress(RAX, Array::length_offset()));
-  // Runtime throws exception.
-  __ j(ABOVE_EQUAL, normal_ir_body);
-  // Note that RBX is Smi, i.e, times 2.
-  ASSERT(kSmiTagShift == 1);
-  // Destroy RCX (ic data) as we will not continue in the function.
-  __ StoreIntoObject(RAX, FieldAddress(RAX, RCX, TIMES_4, Array::data_offset()),
-                     RDX);
-  // Caller is responsible of preserving the value if necessary.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
 // Allocate a GrowableObjectArray using the backing array specified.
 // On stack: type argument (+2), data (+1), return-address (+0).
 void Intrinsifier::GrowableArray_Allocate(Assembler* assembler,
@@ -108,34 +87,6 @@
   __ Bind(normal_ir_body);
 }
 
-// Add an element to growable array if it doesn't need to grow, otherwise
-// call into regular code.
-// On stack: growable array (+2), value (+1), return-address (+0).
-void Intrinsifier::GrowableArray_add(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  // In checked mode we need to check the incoming argument.
-  if (Isolate::Current()->argument_type_checks()) return;
-
-  __ movq(RAX, Address(RSP, +2 * kWordSize));  // Array.
-  __ movq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset()));
-  // RCX: length.
-  __ movq(RDX, FieldAddress(RAX, GrowableObjectArray::data_offset()));
-  // RDX: data.
-  // Compare length with capacity.
-  __ cmpq(RCX, FieldAddress(RDX, Array::length_offset()));
-  __ j(EQUAL, normal_ir_body);  // Must grow data.
-  // len = len + 1;
-  __ IncrementSmiField(FieldAddress(RAX, GrowableObjectArray::length_offset()),
-                       1);
-  __ movq(RAX, Address(RSP, +1 * kWordSize));  // Value
-  ASSERT(kSmiTagShift == 1);
-  __ StoreIntoObject(RDX, FieldAddress(RDX, RCX, TIMES_4, Array::data_offset()),
-                     RAX);
-  __ LoadObject(RAX, Object::null_object());
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor)          \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 1 * kWordSize;                      \
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index f3c1792..972285d 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -229,7 +229,7 @@
 //   Arg0: function object.
 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) {
   ASSERT(thread->IsMutatorThread());
-  const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
+  const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(0));
   Object& result = Object::Handle(zone);
 
   if (FLAG_enable_interpreter && function.IsBytecodeAllowed(zone)) {
@@ -541,7 +541,8 @@
   // Allocates instruction object. Since this occurs only at safepoint,
   // there can be no concurrent access to the instruction page.
   Code& code = Code::Handle(Code::FinalizeCode(
-      function, graph_compiler, assembler, optimized(), /*stats=*/nullptr));
+      function, graph_compiler, assembler, Code::PoolAttachment::kAttachPool,
+      optimized(), /*stats=*/nullptr));
   code.set_is_optimized(optimized());
   code.set_owner(function);
 #if !defined(PRODUCT)
@@ -677,6 +678,11 @@
     function.set_unoptimized_code(code);
     function.AttachCode(code);
     function.SetWasCompiled(true);
+    if (function.IsOptimizable() && (function.usage_counter() < 0)) {
+      // While doing compilation in background, usage counter is set
+      // to INT_MIN. Reset counter so that function can be optimized further.
+      function.SetUsageCounter(0);
+    }
   }
   if (parsed_function()->HasDeferredPrefixes()) {
     ASSERT(!FLAG_load_deferred_eagerly);
@@ -936,8 +942,7 @@
 
     if (Compiler::IsBackgroundCompilation()) {
       ASSERT(function.is_background_optimizable());
-      if (isolate->IsTopLevelParsing() ||
-          (loading_invalidation_gen_at_start !=
+      if ((loading_invalidation_gen_at_start !=
            isolate->loading_invalidation_gen())) {
         // Loading occured while parsing. We need to abort here because state
         // changed while compiling.
@@ -1122,12 +1127,6 @@
 #endif
 
   Isolate* isolate = thread->isolate();
-
-#if !defined(PRODUCT)
-  VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId);
-  TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "CompileFunction", function);
-#endif  // !defined(PRODUCT)
-
   if (!isolate->compilation_allowed()) {
     FATAL3("Precompilation missed function %s (%s, %s)\n",
            function.ToLibNamePrefixedQualifiedCString(),
@@ -1135,6 +1134,17 @@
            Function::KindToCString(function.kind()));
   }
 
+#if !defined(PRODUCT)
+  VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId);
+  const char* event_name;
+  if (IsBackgroundCompilation()) {
+    event_name = "CompileFunctionUnoptimizedBackground";
+  } else {
+    event_name = "CompileFunction";
+  }
+  TIMELINE_FUNCTION_COMPILATION_DURATION(thread, event_name, function);
+#endif  // !defined(PRODUCT)
+
   CompilationPipeline* pipeline =
       CompilationPipeline::New(thread->zone(), function);
 
@@ -1207,14 +1217,10 @@
   } else {
     event_name = "CompileFunctionOptimized";
   }
-  // TODO(alexmarkov): Consider adding a separate event for unoptimized
-  // compilation triggered from interpreter
   TIMELINE_FUNCTION_COMPILATION_DURATION(thread, event_name, function);
 #endif  // !defined(PRODUCT)
 
-  // If running with interpreter, do the unoptimized compilation first.
-  const bool optimized = function.ShouldCompilerOptimize();
-  ASSERT(FLAG_enable_interpreter || optimized);
+  ASSERT(function.ShouldCompilerOptimize());
 
   // If we are in the optimizing in the mutator/Dart thread, then
   // this is either an OSR compilation or background compilation is
@@ -1225,7 +1231,8 @@
          !function.is_background_optimizable());
   CompilationPipeline* pipeline =
       CompilationPipeline::New(thread->zone(), function);
-  return CompileFunctionHelper(pipeline, function, optimized, osr_id);
+  return CompileFunctionHelper(pipeline, function, /* optimized = */ true,
+                               osr_id);
 }
 
 // This is only used from unit tests.
@@ -1256,12 +1263,6 @@
 void Compiler::ComputeLocalVarDescriptors(const Code& code) {
   ASSERT(!code.is_optimized());
   const Function& function = Function::Handle(code.function());
-  if (FLAG_enable_interpreter && function.Bytecode() == code.raw()) {
-    // TODO(regis): Kernel bytecode does not yet provide var descriptors.
-    ASSERT(code.var_descriptors() == Object::null());
-    code.set_var_descriptors(Object::empty_var_descriptors());
-    return;
-  }
   ParsedFunction* parsed_function = new ParsedFunction(
       Thread::Current(), Function::ZoneHandle(function.raw()));
   ASSERT(code.var_descriptors() == Object::null());
@@ -1657,14 +1658,17 @@
         MonitorLocker ml(queue_monitor_);
         function = function_queue()->PeekFunction();
       }
-      while (running_ && !function.IsNull() && !isolate_->IsTopLevelParsing()) {
+      while (running_ && !function.IsNull()) {
         // This is false if we are compiling bytecode -> unoptimized code.
         const bool optimizing = function.ShouldCompilerOptimize();
         ASSERT(FLAG_enable_interpreter || optimizing);
 
-        // Check that we have aggregated and cleared the stats.
-        Compiler::CompileOptimizedFunction(thread, function,
-                                           Compiler::kNoOSRDeoptId);
+        if (optimizing) {
+          Compiler::CompileOptimizedFunction(thread, function,
+                                             Compiler::kNoOSRDeoptId);
+        } else {
+          Compiler::CompileFunction(thread, function);
+        }
 
         QueueElement* qelem = NULL;
         {
@@ -1698,8 +1702,7 @@
     {
       // Wait to be notified when the work queue is not empty.
       MonitorLocker ml(queue_monitor_);
-      while ((function_queue()->IsEmpty() || isolate_->IsTopLevelParsing()) &&
-             running_) {
+      while (function_queue()->IsEmpty() && running_) {
         ml.Wait();
       }
     }
@@ -1824,7 +1827,7 @@
 }
 
 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) {
-  const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
+  const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(0));
   FATAL3("Precompilation missed function %s (%" Pd ", %s)\n",
          function.ToLibNamePrefixedQualifiedCString(),
          function.token_pos().value(),
diff --git a/runtime/vm/compiler/jit/compiler.h b/runtime/vm/compiler/jit/compiler.h
index aee82f1..53e41fd 100644
--- a/runtime/vm/compiler/jit/compiler.h
+++ b/runtime/vm/compiler/jit/compiler.h
@@ -110,9 +110,6 @@
                                          const Function& function);
 
   // Generates optimized code for function.
-  // If interpreter is used and function was not compiled yet, then
-  // generates unoptimized code (it's basically the first round of
-  // optimization).
   //
   // Returns the code object if compilation succeeds.  Returns an Error if
   // there is a compilation error.  If optimization fails, but there is no
diff --git a/runtime/vm/compiler/jit/jit_call_specializer.cc b/runtime/vm/compiler/jit/jit_call_specializer.cc
index cbc5395..3b97b71 100644
--- a/runtime/vm/compiler/jit/jit_call_specializer.cc
+++ b/runtime/vm/compiler/jit/jit_call_specializer.cc
@@ -185,7 +185,7 @@
     // usage count of at least 1/kGetterSetterRatio of the getter usage count.
     // This is to avoid unboxing fields where the setter is never or rarely
     // executed.
-    const Field& field = instr->field();
+    const Field& field = instr->slot().field();
     const String& field_name = String::Handle(Z, field.name());
     const Class& owner = Class::Handle(Z, field.Owner());
     const Function& getter =
@@ -233,23 +233,24 @@
 // allocation and explicit initializing stores.
 // If context_value is not NULL then newly allocated context is a populated
 // with values copied from it, otherwise it is initialized with null.
-void JitCallSpecializer::LowerContextAllocation(Definition* alloc,
-                                                intptr_t num_context_variables,
-                                                Value* context_value) {
+void JitCallSpecializer::LowerContextAllocation(
+    Definition* alloc,
+    const GrowableArray<LocalVariable*>& context_variables,
+    Value* context_value) {
   ASSERT(alloc->IsAllocateContext() || alloc->IsCloneContext());
 
   AllocateUninitializedContextInstr* replacement =
       new AllocateUninitializedContextInstr(alloc->token_pos(),
-                                            num_context_variables);
+                                            context_variables.length());
   alloc->ReplaceWith(replacement, current_iterator());
 
   Definition* cursor = replacement;
 
   Value* initial_value;
   if (context_value != NULL) {
-    LoadFieldInstr* load = new (Z)
-        LoadFieldInstr(context_value->CopyWithType(Z), Context::parent_offset(),
-                       AbstractType::ZoneHandle(Z), alloc->token_pos());
+    LoadFieldInstr* load =
+        new (Z) LoadFieldInstr(context_value->CopyWithType(Z),
+                               Slot::Context_parent(), alloc->token_pos());
     flow_graph()->InsertAfter(cursor, load, NULL, FlowGraph::kValue);
     cursor = load;
     initial_value = new (Z) Value(load);
@@ -257,20 +258,18 @@
     initial_value = new (Z) Value(flow_graph()->constant_null());
   }
   StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
-      Context::parent_offset(), new (Z) Value(replacement), initial_value,
-      kNoStoreBarrier, alloc->token_pos());
-  // Storing into uninitialized memory; remember to prevent dead store
-  // elimination and ensure proper GC barrier.
-  store->set_is_initialization(true);
-  flow_graph()->InsertAfter(cursor, store, NULL, FlowGraph::kEffect);
+      Slot::Context_parent(), new (Z) Value(replacement), initial_value,
+      kNoStoreBarrier, alloc->token_pos(),
+      StoreInstanceFieldInstr::Kind::kInitializing);
+  flow_graph()->InsertAfter(cursor, store, nullptr, FlowGraph::kEffect);
   cursor = replacement;
 
-  for (intptr_t i = 0; i < num_context_variables; ++i) {
-    if (context_value != NULL) {
+  for (auto variable : context_variables) {
+    const auto& field = Slot::GetContextVariableSlotFor(thread(), *variable);
+    if (context_value != nullptr) {
       LoadFieldInstr* load = new (Z) LoadFieldInstr(
-          context_value->CopyWithType(Z), Context::variable_offset(i),
-          AbstractType::ZoneHandle(Z), alloc->token_pos());
-      flow_graph()->InsertAfter(cursor, load, NULL, FlowGraph::kValue);
+          context_value->CopyWithType(Z), field, alloc->token_pos());
+      flow_graph()->InsertAfter(cursor, load, nullptr, FlowGraph::kValue);
       cursor = load;
       initial_value = new (Z) Value(load);
     } else {
@@ -278,27 +277,19 @@
     }
 
     store = new (Z) StoreInstanceFieldInstr(
-        Context::variable_offset(i), new (Z) Value(replacement), initial_value,
-        kNoStoreBarrier, alloc->token_pos());
-    // Storing into uninitialized memory; remember to prevent dead store
-    // elimination and ensure proper GC barrier.
-    store->set_is_initialization(true);
-    flow_graph()->InsertAfter(cursor, store, NULL, FlowGraph::kEffect);
+        field, new (Z) Value(replacement), initial_value, kNoStoreBarrier,
+        alloc->token_pos(), StoreInstanceFieldInstr::Kind::kInitializing);
+    flow_graph()->InsertAfter(cursor, store, nullptr, FlowGraph::kEffect);
     cursor = store;
   }
 }
 
 void JitCallSpecializer::VisitAllocateContext(AllocateContextInstr* instr) {
-  LowerContextAllocation(instr, instr->num_context_variables(), NULL);
+  LowerContextAllocation(instr, instr->context_variables(), nullptr);
 }
 
 void JitCallSpecializer::VisitCloneContext(CloneContextInstr* instr) {
-  if (instr->num_context_variables() ==
-      CloneContextInstr::kUnknownContextSize) {
-    return;
-  }
-
-  LowerContextAllocation(instr, instr->num_context_variables(),
+  LowerContextAllocation(instr, instr->context_variables(),
                          instr->context_value());
 }
 
diff --git a/runtime/vm/compiler/jit/jit_call_specializer.h b/runtime/vm/compiler/jit/jit_call_specializer.h
index bbb00e3..77c72bd 100644
--- a/runtime/vm/compiler/jit/jit_call_specializer.h
+++ b/runtime/vm/compiler/jit/jit_call_specializer.h
@@ -30,9 +30,10 @@
 
   virtual bool TryOptimizeStaticCallUsingStaticTypes(StaticCallInstr* call);
 
-  void LowerContextAllocation(Definition* instr,
-                              intptr_t num_context_variables,
-                              Value* context_value);
+  void LowerContextAllocation(
+      Definition* instr,
+      const GrowableArray<LocalVariable*>& context_variables,
+      Value* context_value);
 
   void ReplaceWithStaticCall(InstanceCallInstr* instr,
                              const ICData& unary_checks,
diff --git a/runtime/vm/compiler/method_recognizer.h b/runtime/vm/compiler/method_recognizer.h
index 0c0801c..d53528c 100644
--- a/runtime/vm/compiler/method_recognizer.h
+++ b/runtime/vm/compiler/method_recognizer.h
@@ -14,7 +14,8 @@
 // clang-format off
 // (class-name, function-name, recognized enum, result type, fingerprint).
 // When adding a new function add a 0 as fingerprint, build and run to get the
-// correct fingerprint from the mismatch error.
+// correct fingerprint from the mismatch error (or use Library::GetFunction()
+// and print func.SourceFingerprint()).
 #define OTHER_RECOGNIZED_LIST(V)                                               \
   V(::, identical, ObjectIdentical, Bool, 0x49c6e96a)                          \
   V(ClassID, getID, ClassIDgetID, Smi, 0x7b18b257)                             \
@@ -169,11 +170,8 @@
   V(_Double, get:isNegative, Double_getIsNegative, Bool, 0x3a59e7f4)           \
   V(_Double, _mulFromInteger, Double_mulFromInteger, Double, 0x2017fcf6)       \
   V(_Double, .fromInteger, DoubleFromInteger, Double, 0x6d234f4b)              \
-  V(_List, _setIndexed, ObjectArraySetIndexedUnchecked, Dynamic, 0x50d64c75)   \
-  V(_List, []=, ObjectArraySetIndexed, Dynamic, 0x16b3d2b0)                    \
   V(_GrowableList, .withData, GrowableArray_Allocate, GrowableObjectArray,     \
     0x28b2138e)                                                                \
-  V(_GrowableList, add, GrowableArray_add, Dynamic, 0x40b490b8)                \
   V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, Dynamic, 0x380184b1)          \
   V(_RegExp, _ExecuteMatchSticky, RegExp_ExecuteMatchSticky, Dynamic,          \
     0x79b8f955)                                                                \
@@ -325,6 +323,8 @@
 #define GRAPH_CORE_INTRINSICS_LIST(V)                                          \
   V(_List, get:length, ObjectArrayLength, Smi, 0x25952390)                     \
   V(_List, [], ObjectArrayGetIndexed, Dynamic, 0x653da02e)                     \
+  V(_List, []=, ObjectArraySetIndexed, Dynamic, 0x16b3d2b0)                    \
+  V(_List, _setIndexed, ObjectArraySetIndexedUnchecked, Dynamic, 0x50d64c75)   \
   V(_ImmutableList, get:length, ImmutableArrayLength, Smi, 0x25952390)         \
   V(_ImmutableList, [], ImmutableArrayGetIndexed, Dynamic, 0x653da02e)         \
   V(_GrowableList, get:length, GrowableArrayLength, Smi, 0x18dd86b4)           \
@@ -444,6 +444,9 @@
   V(::, _toUint16, ConvertIntToUint16, 0x6087d1af)                             \
   V(::, _toInt32, ConvertIntToInt32, 0x62b451b9)                               \
   V(::, _toUint32, ConvertIntToUint32, 0x17a8e085)                             \
+  V(::, _byteSwap16, ByteSwap16, 0x44f173be)                                   \
+  V(::, _byteSwap32, ByteSwap32, 0x6219333b)                                   \
+  V(::, _byteSwap64, ByteSwap64, 0x9abe57e0)                                   \
   V(Lists, copy, ListsCopy, 0x40e974f6)                                        \
   V(_HashVMBase, get:_index, LinkedHashMap_getIndex, 0x02477157)               \
   V(_HashVMBase, set:_index, LinkedHashMap_setIndex, 0x4fc8d5e0)               \
diff --git a/runtime/vm/compiler/result_type_pragma.md b/runtime/vm/compiler/result_type_pragma.md
deleted file mode 100644
index debb523..0000000
--- a/runtime/vm/compiler/result_type_pragma.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Result type @pragma annotations
-
-To facilitate type-flow analysis and other optimizations, Dart methods may use the pragma `vm:exact-result-type` to declare an exact return type different than the return type in the signature of the method. There are three limitations on this pragma:
-
-0. The Dart object returned by the method at runtime must have exactly the type specified in the annotation (not a subtype).
-
-1. The exact return type declared in the pragma must be a subtype of the return type declared in the method signature.
-   Note that this restriction is not enforced automatically by the compiler.
-
-2. `vm:exact-result-type` may only be attached to methods in the core library.
-   This pragma can introduce unsafe behavior since it allows the compiler to make stronger assumptions during optimization than what the sound strong-mode type system allows, so it is only allowed in the core library where the Dart VM team can ensure that it is not misused.
-
-If limitations 0 or 1 are violated, undefined behavior may result.
-Note that since `null` is an instance of the `Null` type, which is a subtype of any other, exactness of the annotated result type implies that the result must be non-null.
-
-## Syntax
-
-### Reference to type via type literal
-
-```dart
-class A {}
-class B extends A {}
-
-@pragma("vm:exact-result-type", B)
-A foo() native "foo_impl";
-```
-
-### Reference to type via path
-
-```dart
-@pragma("vm:exact-result-type", "dart:core#_Smi");
-int foo() native "foo_impl";
-```
diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc
index ae91b3e..02a4ed1 100644
--- a/runtime/vm/compiler_test.cc
+++ b/runtime/vm/compiler_test.cc
@@ -110,7 +110,7 @@
   BackgroundCompiler::Stop(isolate);
 }
 
-TEST_CASE(RegenerateAllocStubs) {
+ISOLATE_UNIT_TEST_CASE(RegenerateAllocStubs) {
   const char* kScriptChars =
       "class A {\n"
       "}\n"
@@ -120,29 +120,39 @@
       "  return unOpt();\n"
       "}\n";
 
+  Class& cls = Class::Handle();
+  TransitionVMToNative transition(thread);
+
   Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
   EXPECT_VALID(result);
-  RawLibrary* raw_library = Library::RawCast(Api::UnwrapHandle(lib));
-  Library& lib_handle = Library::ZoneHandle(raw_library);
-  Class& cls = Class::Handle(
-      lib_handle.LookupClass(String::Handle(Symbols::New(thread, "A"))));
-  EXPECT(!cls.IsNull());
 
-  Zone* zone = thread->zone();
-  const Code& stub =
-      Code::Handle(zone, StubCode::GetAllocationStubForClass(cls));
-  Class& owner = Class::Handle();
-  owner ^= stub.owner();
-  owner.DisableAllocationStub();
+  {
+    TransitionNativeToVM transition(thread);
+    Library& lib_handle =
+        Library::Handle(Library::RawCast(Api::UnwrapHandle(lib)));
+    cls = lib_handle.LookupClass(String::Handle(Symbols::New(thread, "A")));
+    EXPECT(!cls.IsNull());
+  }
+
+  {
+    TransitionNativeToVM transition(thread);
+    cls.DisableAllocationStub();
+  }
   result = Dart_Invoke(lib, NewString("main"), 0, NULL);
   EXPECT_VALID(result);
 
-  owner.DisableAllocationStub();
+  {
+    TransitionNativeToVM transition(thread);
+    cls.DisableAllocationStub();
+  }
   result = Dart_Invoke(lib, NewString("main"), 0, NULL);
   EXPECT_VALID(result);
 
-  owner.DisableAllocationStub();
+  {
+    TransitionNativeToVM transition(thread);
+    cls.DisableAllocationStub();
+  }
   result = Dart_Invoke(lib, NewString("main"), 0, NULL);
   EXPECT_VALID(result);
 }
@@ -173,20 +183,16 @@
   const Class& receiver_cls = Class::Handle(obj.clazz());
 
   if (!KernelIsolate::IsRunning()) {
-    val = Instance::Cast(obj).Evaluate(
-        receiver_cls, expr_text, Array::empty_array(), Array::empty_array());
+    UNREACHABLE();
   } else {
     RawLibrary* raw_library = Library::RawCast(Api::UnwrapHandle(lib));
     Library& lib_handle = Library::ZoneHandle(raw_library);
 
-    Dart_KernelCompilationResult compilation_result;
-    {
-      TransitionVMToNative transition(thread);
-      compilation_result = KernelIsolate::CompileExpressionToKernel(
-          expr_text.ToCString(), Array::empty_array(), Array::empty_array(),
-          String::Handle(lib_handle.url()).ToCString(), "A",
-          /* is_static= */ false);
-    }
+    Dart_KernelCompilationResult compilation_result =
+        KernelIsolate::CompileExpressionToKernel(
+            expr_text.ToCString(), Array::empty_array(), Array::empty_array(),
+            String::Handle(lib_handle.url()).ToCString(), "A",
+            /* is_static= */ false);
     EXPECT_EQ(Dart_KernelCompilationStatus_Ok, compilation_result.status);
 
     const uint8_t* kernel_bytes = compilation_result.kernel;
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 4092d250..08380f8 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -283,6 +283,7 @@
 // ABI for write barrier stub.
 const Register kWriteBarrierObjectReg = R1;
 const Register kWriteBarrierValueReg = R0;
+const Register kWriteBarrierSlotReg = R9;
 
 // List of registers used in load/store multiple.
 typedef uint16_t RegList;
@@ -308,10 +309,12 @@
 const RegList kReservedCpuRegisters = (1 << SPREG) | (1 << FPREG) | (1 << TMP) |
                                       (1 << PP) | (1 << THR) | (1 << LR) |
                                       (1 << PC);
+constexpr intptr_t kNumberOfReservedCpuRegisters = 7;
 // CPU registers available to Dart allocator.
 constexpr RegList kDartAvailableCpuRegs =
     kAllCpuRegistersList & ~kReservedCpuRegisters;
-constexpr int kNumberOfDartAvailableCpuRegs = kNumberOfCpuRegisters - 7;
+constexpr int kNumberOfDartAvailableCpuRegs =
+    kNumberOfCpuRegisters - kNumberOfReservedCpuRegisters;
 const intptr_t kStoreBufferWrapperSize = 24;
 // Registers available to Dart that are not preserved by runtime calls.
 const RegList kDartVolatileCpuRegs =
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index c456dc7..6067a37 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -125,6 +125,7 @@
 // ABI for write barrier stub.
 const Register kWriteBarrierObjectReg = R1;
 const Register kWriteBarrierValueReg = R0;
+const Register kWriteBarrierSlotReg = R25;
 
 // Masks, sizes, etc.
 const int kXRegSizeInBits = 64;
@@ -134,7 +135,7 @@
 
 // List of registers used in load/store multiple.
 typedef uint32_t RegList;
-const RegList kAllCpuRegistersList = 0xFFFF;
+const RegList kAllCpuRegistersList = 0xFFFFFFFF;
 
 // C++ ABI call registers.
 const RegList kAbiArgumentCpuRegs = (1 << R0) | (1 << R1) | (1 << R2) |
@@ -156,10 +157,12 @@
     (1 << LR) | (1 << BARRIER_MASK) | (1 << R31) |  // C++ SP
     (1 << R18);                                     // iOS platform register.
 // TODO(rmacnak): Only reserve on Mac & iOS.
+constexpr intptr_t kNumberOfReservedCpuRegisters = 10;
 // CPU registers available to Dart allocator.
 const RegList kDartAvailableCpuRegs =
     kAllCpuRegistersList & ~kReservedCpuRegisters;
-constexpr int kNumberOfDartAvailableCpuRegs = kNumberOfCpuRegisters - 9;
+constexpr int kNumberOfDartAvailableCpuRegs =
+    kNumberOfCpuRegisters - kNumberOfReservedCpuRegisters;
 // Registers available to Dart that are not preserved by runtime calls.
 const RegList kDartVolatileCpuRegs =
     kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs;
diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h
index c211898..74e1ac1 100644
--- a/runtime/vm/constants_dbc.h
+++ b/runtime/vm/constants_dbc.h
@@ -12,7 +12,7 @@
 namespace dart {
 
 // clang-format off
-// List of Dart Bytecode instructions.
+// List of Simulator Bytecode instructions.
 //
 // INTERPRETER STATE
 //
@@ -943,7 +943,7 @@
 
 typedef uint32_t Instr;
 
-class Bytecode {
+class SimulatorBytecode {
  public:
   enum Opcode {
 #define DECLARE_BYTECODE(name, encoding, op1, op2, op3) k##name,
@@ -1015,18 +1015,18 @@
   }
 
   DART_FORCE_INLINE static bool IsTrap(Instr instr) {
-    return DecodeOpcode(instr) == Bytecode::kTrap;
+    return DecodeOpcode(instr) == SimulatorBytecode::kTrap;
   }
 
   DART_FORCE_INLINE static bool IsCallOpcode(Instr instr) {
     switch (DecodeOpcode(instr)) {
-      case Bytecode::kStaticCall:
-      case Bytecode::kIndirectStaticCall:
-      case Bytecode::kInstanceCall1:
-      case Bytecode::kInstanceCall2:
-      case Bytecode::kInstanceCall1Opt:
-      case Bytecode::kInstanceCall2Opt:
-      case Bytecode::kDebugBreak:
+      case SimulatorBytecode::kStaticCall:
+      case SimulatorBytecode::kIndirectStaticCall:
+      case SimulatorBytecode::kInstanceCall1:
+      case SimulatorBytecode::kInstanceCall2:
+      case SimulatorBytecode::kInstanceCall1Opt:
+      case SimulatorBytecode::kInstanceCall2Opt:
+      case SimulatorBytecode::kDebugBreak:
         return true;
 
       default:
@@ -1036,14 +1036,14 @@
 
   DART_FORCE_INLINE static bool IsFastSmiOpcode(Instr instr) {
     switch (DecodeOpcode(instr)) {
-      case Bytecode::kAddTOS:
-      case Bytecode::kSubTOS:
-      case Bytecode::kMulTOS:
-      case Bytecode::kBitOrTOS:
-      case Bytecode::kBitAndTOS:
-      case Bytecode::kEqualTOS:
-      case Bytecode::kLessThanTOS:
-      case Bytecode::kGreaterThanTOS:
+      case SimulatorBytecode::kAddTOS:
+      case SimulatorBytecode::kSubTOS:
+      case SimulatorBytecode::kMulTOS:
+      case SimulatorBytecode::kBitOrTOS:
+      case SimulatorBytecode::kBitAndTOS:
+      case SimulatorBytecode::kEqualTOS:
+      case SimulatorBytecode::kLessThanTOS:
+      case SimulatorBytecode::kGreaterThanTOS:
         return true;
 
       default:
@@ -1060,7 +1060,7 @@
 
  private:
   DISALLOW_ALLOCATION();
-  DISALLOW_IMPLICIT_CONSTRUCTORS(Bytecode);
+  DISALLOW_IMPLICIT_CONSTRUCTORS(SimulatorBytecode);
 };
 
 // Various dummy declarations to make shared code compile.
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index 5bd61c4..4e56d03 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -72,6 +72,7 @@
 // ABI for write barrier stub.
 const Register kWriteBarrierObjectReg = EDX;
 const Register kWriteBarrierValueReg = kNoRegister;
+const Register kWriteBarrierSlotReg = EDI;
 
 typedef uint32_t RegList;
 const RegList kAllCpuRegistersList = 0xFF;
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index d61ac75..67772ab 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -137,10 +137,11 @@
 //    Check for a passed-in type argument vector of length A and
 //    store it at FP[D].
 //
-//  - CheckStack
+//  - CheckStack A
 //
 //    Compare SP against isolate stack limit and call StackOverflow handler if
-//    necessary.
+//    necessary. Should be used in prologue (A = 0), or at the beginning of
+//    a loop with depth A.
 //
 //  - Allocate D
 //
@@ -154,13 +155,18 @@
 //
 //    Allocate array of length SP[0] with type arguments SP[-1].
 //
-//  - AllocateContext D
+//  - AllocateContext A, D
 //
-//    Allocate Context object assuming for D context variables.
+//    Allocate Context object holding D context variables.
+//    A is a static ID of the context. Static ID of a context may be used to
+//    disambiguate accesses to different context objects.
+//    Context objects with the same ID should have the same number of
+//    context variables.
 //
-//  - CloneContext
+//  - CloneContext A, D
 //
-//    Clone context stored in TOS.
+//    Clone Context object SP[0] holding D context variables.
+//    A is a static ID of the context. Cloned context has the same ID.
 //
 //  - LoadContextParent
 //
@@ -170,13 +176,15 @@
 //
 //    Store context SP[0] into `parent` field of context SP[-1].
 //
-//  - LoadContextVar D
+//  - LoadContextVar A, D
 //
 //    Load value from context SP[0] at index D.
+//    A is a static ID of the context.
 //
-//  - StoreContextVar D
+//  - StoreContextVar A, D
 //
 //    Store value SP[0] into context SP[-1] at index D.
+//    A is a static ID of the context.
 //
 //  - PushConstant D
 //
@@ -329,10 +337,10 @@
 //    Throw (Rethrow if A != 0) exception. Exception object and stack object
 //    are taken from TOS.
 //
-//  - MoveSpecial rA, D
+//  - MoveSpecial A, rX
 //
-//    Copy special values from inside interpreter to FP[rA]. Currently only
-//    used to pass exception object (D = 0) and stack trace object (D = 1) to
+//    Copy value from special variable to FP[rX]. Currently only
+//    used to pass exception object (A = 0) and stack trace object (A = 1) to
 //    catch handler.
 //
 //  - SetFrame A
@@ -396,13 +404,13 @@
   V(EntryOptional,                     A_B_C, num, num, num)                   \
   V(LoadConstant,                        A_D, reg, lit, ___)                   \
   V(Frame,                                 D, num, ___, ___)                   \
-  V(CheckFunctionTypeArgs,               A_D, num, num, ___)                   \
-  V(CheckStack,                            0, ___, ___, ___)                   \
+  V(CheckFunctionTypeArgs,               A_D, num, reg, ___)                   \
+  V(CheckStack,                            A, num, ___, ___)                   \
   V(Allocate,                              D, lit, ___, ___)                   \
   V(AllocateT,                             0, ___, ___, ___)                   \
   V(CreateArrayTOS,                        0, ___, ___, ___)                   \
   V(AllocateContext,                       D, num, ___, ___)                   \
-  V(CloneContext,                          0, ___, ___, ___)                   \
+  V(CloneContext,                          D, num, ___, ___)                   \
   V(LoadContextParent,                     0, ___, ___, ___)                   \
   V(StoreContextParent,                    0, ___, ___, ___)                   \
   V(LoadContextVar,                        D, num, ___, ___)                   \
@@ -441,7 +449,7 @@
   V(InstantiateType,                       D, lit, ___, ___)                   \
   V(InstantiateTypeArgumentsTOS,         A_D, num, lit, ___)                   \
   V(Throw,                                 A, num, ___, ___)                   \
-  V(MoveSpecial,                         A_D, reg, num, ___)                   \
+  V(MoveSpecial,                         A_X, num, xeg, ___)                   \
   V(SetFrame,                              A, num, ___, num)                   \
   V(BooleanNegateTOS,                      0, ___, ___, ___)                   \
   V(EqualsNull,                            0, ___, ___, ___)                   \
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 055d51b..512ff98 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -115,6 +115,7 @@
 // ABI for write barrier stub.
 const Register kWriteBarrierObjectReg = RDX;
 const Register kWriteBarrierValueReg = RAX;
+const Register kWriteBarrierSlotReg = R13;
 
 typedef uint32_t RegList;
 const RegList kAllCpuRegistersList = 0xFFFF;
@@ -122,10 +123,12 @@
 
 const RegList kReservedCpuRegisters =
     (1 << SPREG) | (1 << FPREG) | (1 << TMP) | (1 << PP) | (1 << THR);
+constexpr intptr_t kNumberOfReservedCpuRegisters = 5;
 // CPU registers available to Dart allocator.
 const RegList kDartAvailableCpuRegs =
     kAllCpuRegistersList & ~kReservedCpuRegisters;
-constexpr int kNumberOfDartAvailableCpuRegs = kNumberOfCpuRegisters - 5;
+constexpr int kNumberOfDartAvailableCpuRegs =
+    kNumberOfCpuRegisters - kNumberOfReservedCpuRegisters;
 constexpr int kStoreBufferWrapperSize = 13;
 
 enum ScaleFactor {
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index ea392ed..e4dfb86 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -42,7 +42,6 @@
 namespace dart {
 
 DECLARE_FLAG(bool, print_class_table);
-DECLARE_FLAG(bool, trace_time_all);
 DEFINE_FLAG(bool, keep_code, false, "Keep deoptimized code for profiling.");
 DEFINE_FLAG(bool, trace_shutdown, false, "Trace VM shutdown on stderr");
 DECLARE_FLAG(bool, strong);
@@ -151,7 +150,6 @@
 #endif  // defined(TARGET_OS_WINDOWS)
 
     FLAG_use_field_guards = false;
-    FLAG_optimization_counter_threshold = -1;
   }
 
   FrameLayout::Init();
@@ -170,7 +168,6 @@
   NOT_IN_PRODUCT(
       TimelineDurationScope tds(Timeline::GetVMStream(), "Dart::Init"));
   Isolate::InitVM();
-  IdleNotifier::Init();
   PortMap::Init();
   FreeListElement::Init();
   ForwardingCorpse::Init();
@@ -300,7 +297,6 @@
     // We need to initialize the constants here for the vm isolate thread due to
     // bootstrapping issues.
     T->InitVMConstants();
-    Scanner::Init();
 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
     // Dart VM requires at least SSE2.
     if (!TargetCPUFeatures::sse2_supported()) {
@@ -441,8 +437,6 @@
   }
   WaitForIsolateShutdown();
 
-  IdleNotifier::Stop();
-
 #if !defined(PRODUCT)
   {
     // IMPORTANT: the code below enters VM isolate so that Metric::Cleanup could
@@ -500,7 +494,6 @@
   vm_isolate_ = NULL;
   ASSERT(Isolate::IsolateListLength() == 0);
   PortMap::Cleanup();
-  IdleNotifier::Cleanup();
   ICData::Cleanup();
   ArgumentsDescriptor::Cleanup();
   TargetCPUFeatures::Cleanup();
@@ -796,11 +789,12 @@
 
 void Dart::RunShutdownCallback() {
   Thread* thread = Thread::Current();
-  ASSERT(thread->execution_state() == Thread::kThreadInNative);
+  ASSERT(thread->execution_state() == Thread::kThreadInVM);
   Isolate* isolate = thread->isolate();
   void* callback_data = isolate->init_callback_data();
   Dart_IsolateShutdownCallback callback = Isolate::ShutdownCallback();
   if (callback != NULL) {
+    TransitionVMToNative transition(thread);
     (callback)(callback_data);
   }
 }
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 92e7895..e3dd575 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -107,15 +107,15 @@
       // Verify that the result type of a function is canonical or a
       // TypeParameter.
       typeHandle_ ^= funcHandle_.result_type();
-      ASSERT(typeHandle_.IsMalformed() || !typeHandle_.IsResolved() ||
-             typeHandle_.IsTypeParameter() || typeHandle_.IsCanonical());
+      ASSERT(typeHandle_.IsMalformed() || typeHandle_.IsTypeParameter() ||
+             typeHandle_.IsCanonical());
       // Verify that the types in the function signature are all canonical or
       // a TypeParameter.
       const intptr_t num_parameters = funcHandle_.NumParameters();
       for (intptr_t i = 0; i < num_parameters; i++) {
         typeHandle_ = funcHandle_.ParameterTypeAt(i);
-        ASSERT(typeHandle_.IsMalformed() || !typeHandle_.IsResolved() ||
-               typeHandle_.IsTypeParameter() || typeHandle_.IsCanonical());
+        ASSERT(typeHandle_.IsMalformed() || typeHandle_.IsTypeParameter() ||
+               typeHandle_.IsCanonical());
       }
     }
   }
@@ -347,6 +347,7 @@
   if (raw == Bool::False().raw()) {
     return False();
   }
+  ASSERT(thread->execution_state() == Thread::kThreadInVM);
   return InitNewHandle(thread, raw);
 }
 
@@ -417,11 +418,11 @@
 Dart_Handle Api::NewError(const char* format, ...) {
   Thread* T = Thread::Current();
   CHECK_API_SCOPE(T);
-  HANDLESCOPE(T);
   CHECK_CALLBACK_STATE(T);
   // Ensure we transition safepoint state to VM if we are not already in
   // that state.
   TransitionToVM transition(T);
+  HANDLESCOPE(T);
 
   va_list args;
   va_start(args, format);
@@ -868,9 +869,10 @@
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
   CHECK_ISOLATE(isolate);
-  NoSafepointScope no_safepoint_scope;
   ApiState* state = isolate->api_state();
   ASSERT(state != NULL);
+  TransitionNativeToVM transition(thread);
+  NoSafepointScope no_safepoint_scope;
   PersistentHandle* ref = PersistentHandle::Cast(object);
   return Api::NewHandle(thread, ref->raw());
 }
@@ -880,9 +882,10 @@
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
   CHECK_ISOLATE(isolate);
-  NoSafepointScope no_safepoint_scope;
   ApiState* state = isolate->api_state();
   ASSERT(state != NULL);
+  TransitionNativeToVM transition(thread);
+  NoSafepointScope no_safepoint_scope;
   FinalizablePersistentHandle* weak_ref =
       FinalizablePersistentHandle::Cast(object);
   return Api::NewHandle(thread, weak_ref->raw());
@@ -1125,7 +1128,7 @@
     // We enter an API scope here as InitializeIsolate could compile some
     // bootstrap library files which call out to a tag handler that may create
     // Api Handles when an error is encountered.
-    Dart_EnterScope();
+    T->EnterApiScope();
     const Error& error_obj = Error::Handle(
         Z,
         Dart::InitializeIsolate(snapshot_data, snapshot_instructions,
@@ -1138,7 +1141,7 @@
       }
 #endif  // defined(DART_NO_SNAPSHOT) && !defined(PRODUCT).
       // We exit the API scope entered above.
-      Dart_ExitScope();
+      T->ExitApiScope();
       // A Thread structure has been associated to the thread, we do the
       // safepoint transition explicitly here instead of using the
       // TransitionXXX scope objects as the reverse transition happens
@@ -1154,7 +1157,7 @@
       *error = strdup(error_obj.ToErrorCString());
     }
     // We exit the API scope entered above.
-    Dart_ExitScope();
+    T->ExitApiScope();
   }
   Dart::ShutdownIsolate();
   return reinterpret_cast<Dart_Isolate>(NULL);
@@ -1197,6 +1200,15 @@
   Thread* T = Thread::Current();
   Isolate* I = T->isolate();
   CHECK_ISOLATE(I);
+
+  // The Thread structure is disassociated from the isolate, we do the
+  // safepoint transition explicitly here instead of using the TransitionXXX
+  // scope objects as the original transition happened outside this scope in
+  // Dart_EnterIsolate/Dart_CreateIsolate.
+  ASSERT(T->execution_state() == Thread::kThreadInNative);
+  T->ExitSafepoint();
+  T->set_execution_state(Thread::kThreadInVM);
+
   I->WaitForOutstandingSpawns();
 
   // Release any remaining API scopes.
@@ -1212,12 +1224,6 @@
     StackZone zone(T);
     HandleScope handle_scope(T);
     Dart::RunShutdownCallback();
-    // The Thread structure is disassociated from the isolate, we do the
-    // safepoint transition explicitly here instead of using the TransitionXXX
-    // scope objects as the original transition happened outside this scope in
-    // Dart_EnterIsolate/Dart_CreateIsolate.
-    T->ExitSafepoint();
-    T->set_execution_state(Thread::kThreadInVM);
   }
   Dart::ShutdownIsolate();
 }
@@ -1419,6 +1425,7 @@
   CHECK_ISOLATE(I);
   NoSafepointScope no_safepoint_scope;
   if (I->sticky_error() != Error::null()) {
+    TransitionNativeToVM transition(T);
     Dart_Handle error = Api::NewHandle(T, I->sticky_error());
     return error;
   }
@@ -1541,8 +1548,23 @@
     Dart_MessageNotifyCallback message_notify_callback) {
   Isolate* isolate = Isolate::Current();
   CHECK_ISOLATE(isolate);
-  NoSafepointScope no_safepoint_scope;
-  isolate->set_message_notify_callback(message_notify_callback);
+
+  {
+    NoSafepointScope no_safepoint_scope;
+    isolate->set_message_notify_callback(message_notify_callback);
+  }
+
+  if (message_notify_callback != nullptr && isolate->HasPendingMessages()) {
+    ::Dart_ExitIsolate();
+
+    // If a new handler gets installed and there are pending messages in the
+    // queue (e.g. OOB messages for doing vm service work) we need to notify
+    // the newly registered callback, otherwise the embedder might never get
+    // notified about the pending messages.
+    message_notify_callback(Api::CastIsolate(isolate));
+
+    ::Dart_EnterIsolate(Api::CastIsolate(isolate));
+  }
 }
 
 DART_EXPORT Dart_MessageNotifyCallback Dart_GetMessageNotifyCallback() {
@@ -1591,7 +1613,9 @@
   }
   ::Dart_EnterIsolate(Api::CastIsolate(I));
   if (I->sticky_error() != Object::null()) {
-    Dart_Handle error = Api::NewHandle(Thread::Current(), I->sticky_error());
+    Thread* T = Thread::Current();
+    TransitionNativeToVM transition(T);
+    Dart_Handle error = Api::NewHandle(T, I->sticky_error());
     I->clear_sticky_error();
     return error;
   }
@@ -1763,34 +1787,15 @@
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
   CHECK_ISOLATE(isolate);
-  NoSafepointScope no_safepoint_scope;
-  ApiLocalScope* new_scope = thread->api_reusable_scope();
-  if (new_scope == NULL) {
-    new_scope = new ApiLocalScope(thread->api_top_scope(),
-                                  thread->top_exit_frame_info());
-    ASSERT(new_scope != NULL);
-  } else {
-    new_scope->Reinit(thread, thread->api_top_scope(),
-                      thread->top_exit_frame_info());
-    thread->set_api_reusable_scope(NULL);
-  }
-  thread->set_api_top_scope(new_scope);  // New scope is now the top scope.
+  TransitionNativeToVM transition(thread);
+  thread->EnterApiScope();
 }
 
 DART_EXPORT void Dart_ExitScope() {
-  Thread* T = Thread::Current();
-  CHECK_API_SCOPE(T);
-  NoSafepointScope no_safepoint_scope;
-  ApiLocalScope* scope = T->api_top_scope();
-  ApiLocalScope* reusable_scope = T->api_reusable_scope();
-  T->set_api_top_scope(scope->previous());  // Reset top scope to previous.
-  if (reusable_scope == NULL) {
-    scope->Reset(T);  // Reset the old scope which we just exited.
-    T->set_api_reusable_scope(scope);
-  } else {
-    ASSERT(reusable_scope != scope);
-    delete scope;
-  }
+  Thread* thread = Thread::Current();
+  CHECK_API_SCOPE(thread);
+  TransitionNativeToVM transition(thread);
+  thread->ExitApiScope();
 }
 
 DART_EXPORT uint8_t* Dart_ScopeAllocate(intptr_t size) {
@@ -2146,11 +2151,6 @@
   Isolate* isolate = thread->isolate();
   CHECK_ISOLATE(isolate);
   API_TIMELINE_DURATION(thread);
-  if (Smi::IsValid(value)) {
-    NOHANDLESCOPE(thread);
-    return Api::NewHandle(thread, Smi::New(static_cast<intptr_t>(value)));
-  }
-  // Slow path for Mints.
   DARTSCOPE(thread);
   CHECK_CALLBACK_STATE(thread);
   return Api::NewHandle(thread, Integer::New(value));
@@ -3691,6 +3691,7 @@
   Zone* zone = thread->zone();
   Isolate* isolate = thread->isolate();
   CHECK_ISOLATE(isolate);
+  TransitionNativeToVM transition(thread);
   intptr_t class_id = Api::ClassId(object);
   if (class_id != kByteBufferCid) {
     RETURN_TYPE_ERROR(zone, object, 'ByteBuffer');
@@ -4503,6 +4504,7 @@
     const Dart_NativeArgument_Descriptor* argument_descriptors,
     Dart_NativeArgument_Value* arg_values) {
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
+  TransitionNativeToVM transition(arguments->thread());
   ASSERT(arguments->thread()->isolate() == Isolate::Current());
   if (arg_values == NULL) {
     RETURN_NULL_ERROR(arg_values);
@@ -4636,6 +4638,7 @@
         "%s: argument 'index' out of range. Expected 0..%d but saw %d.",
         CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
   }
+  TransitionNativeToVM transition(arguments->thread());
   return Api::NewHandle(arguments->thread(), arguments->NativeArgAt(index));
 }
 
@@ -4682,6 +4685,7 @@
                                                      int arg_index,
                                                      void** peer) {
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
+  TransitionNativeToVM transition(arguments->thread());
   Dart_Handle result = Api::Null();
   if (!GetNativeStringArgument(arguments, arg_index, &result, peer)) {
     return Api::NewError(
@@ -4752,6 +4756,7 @@
       !Api::IsError(retval)) {
     // Print the current stack trace to make the problematic caller
     // easier to find.
+    TransitionNativeToVM transition(arguments->thread());
     const StackTrace& stacktrace = GetCurrentStackTrace(0);
     OS::PrintErr("=== Current Trace:\n%s===\n", stacktrace.ToCString());
 
@@ -4831,25 +4836,28 @@
 RawString* Api::CallEnvironmentCallback(Thread* thread, const String& name) {
   Isolate* isolate = thread->isolate();
   Dart_EnvironmentCallback callback = isolate->environment_callback();
-  String& result = String::Handle(thread->zone());
   if (callback != NULL) {
-    TransitionVMToNative transition(thread);
     Scope api_scope(thread);
-    Dart_Handle response = callback(Api::NewHandle(thread, name.raw()));
-    if (::Dart_IsString(response)) {
-      result ^= Api::UnwrapHandle(response);
-    } else if (::Dart_IsError(response)) {
-      const Object& error =
-          Object::Handle(thread->zone(), Api::UnwrapHandle(response));
+    Dart_Handle api_name = Api::NewHandle(thread, name.raw());
+    Dart_Handle api_response;
+    {
+      TransitionVMToNative transition(thread);
+      api_response = callback(api_name);
+    }
+    const Object& response =
+        Object::Handle(thread->zone(), Api::UnwrapHandle(api_response));
+    if (response.IsString()) {
+      return String::Cast(response).raw();
+    } else if (response.IsError()) {
       Exceptions::ThrowArgumentError(
-          String::Handle(String::New(Error::Cast(error).ToErrorCString())));
-    } else if (!::Dart_IsNull(response)) {
+          String::Handle(String::New(Error::Cast(response).ToErrorCString())));
+    } else if (!response.IsNull()) {
       // At this point everything except null are invalid environment values.
       Exceptions::ThrowArgumentError(
           String::Handle(String::New("Illegal environment value")));
     }
   }
-  return result.raw();
+  return String::null();
 }
 
 DART_EXPORT Dart_Handle
@@ -5014,6 +5022,7 @@
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
   CHECK_ISOLATE(isolate);
+  TransitionNativeToVM transition(thread);
   return Api::NewHandle(thread, isolate->object_store()->root_library());
 }
 
@@ -5033,7 +5042,16 @@
 #if defined(DART_PRECOMPILED_RUNTIME)
   // This is not a completely thorough check that the class is an entry-point,
   // but it catches most missing annotations.
-  RELEASE_ASSERT(klass.has_pragma());
+  if (!klass.has_pragma()) {
+    OS::PrintErr(
+        "ERROR: It is illegal to access class %s through Dart C API "
+        "because it was not annotated with @pragma('vm:entry-point').\n"
+        "ERROR: See "
+        "https://github.com/dart-lang/sdk/blob/master/runtime/docs/compiler/"
+        "aot/entry_point_pragma.md",
+        String::Handle(klass.UserVisibleName()).ToCString());
+    UNREACHABLE();
+  }
 #endif
 }
 
@@ -6202,7 +6220,7 @@
 
   NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
                                             "WriteAppAOTSnapshot"));
-  AssemblyImageWriter image_writer(callback, callback_data, NULL, NULL);
+  AssemblyImageWriter image_writer(T, callback, callback_data, NULL, NULL);
   uint8_t* vm_snapshot_data_buffer = NULL;
   uint8_t* isolate_snapshot_data_buffer = NULL;
   FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
@@ -6235,7 +6253,7 @@
 
   NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
                                             "WriteVMAOTSnapshot"));
-  AssemblyImageWriter image_writer(callback, callback_data, NULL, NULL);
+  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);
@@ -6291,12 +6309,15 @@
 
   NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
                                             "WriteAppAOTSnapshot"));
-  BlobImageWriter vm_image_writer(vm_snapshot_instructions_buffer,
+  BlobImageWriter vm_image_writer(T, vm_snapshot_instructions_buffer,
                                   ApiReallocate, 2 * MB /* initial_size */,
-                                  NULL, NULL);
+                                  /*shared_objects=*/nullptr,
+                                  /*shared_instructions=*/nullptr,
+                                  /*reused_objects=*/nullptr);
   BlobImageWriter isolate_image_writer(
-      isolate_snapshot_instructions_buffer, ApiReallocate,
-      2 * MB /* initial_size */, shared_data_image, shared_instructions_image);
+      T, isolate_snapshot_instructions_buffer, ApiReallocate,
+      2 * MB /* initial_size */, shared_data_image, shared_instructions_image,
+      /* reuse_instructions= */ nullptr);
   FullSnapshotWriter writer(Snapshot::kFullAOT, vm_snapshot_data_buffer,
                             isolate_snapshot_data_buffer, ApiReallocate,
                             &vm_image_writer, &isolate_image_writer);
@@ -6312,6 +6333,52 @@
 #endif
 }
 
+#if (!defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME))
+
+// Any flag that affects how we compile code might cause a problem when the
+// snapshot writer generates code with one value of the flag and the snapshot
+// reader expects code to behave according to another value of the flag.
+// Normally, we add these flags to Dart::FeaturesString and refuse to run the
+// snapshot it they don't match, but since --interpret-irregexp affects only
+// 2 functions we choose to remove the code instead. See issue #34422.
+static void DropRegExpMatchCode(Zone* zone) {
+  const String& execute_match_name =
+      String::Handle(zone, String::New("_ExecuteMatch"));
+  const String& execute_match_sticky_name =
+      String::Handle(zone, String::New("_ExecuteMatchSticky"));
+
+  const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
+  const Class& reg_exp_class =
+      Class::Handle(zone, core_lib.LookupClassAllowPrivate(Symbols::_RegExp()));
+  ASSERT(!reg_exp_class.IsNull());
+
+  Function& func = Function::Handle(
+      zone, reg_exp_class.LookupFunctionAllowPrivate(execute_match_name));
+  ASSERT(!func.IsNull());
+  Code& code = Code::Handle(zone);
+  if (func.HasCode()) {
+    code ^= func.CurrentCode();
+    ASSERT(!code.IsNull());
+    code.DisableDartCode();
+  }
+  func.ClearCode();
+  func.ClearICDataArray();
+  ASSERT(!func.HasCode());
+
+  func ^= reg_exp_class.LookupFunctionAllowPrivate(execute_match_sticky_name);
+  ASSERT(!func.IsNull());
+  if (func.HasCode()) {
+    code ^= func.CurrentCode();
+    ASSERT(!code.IsNull());
+    code.DisableDartCode();
+  }
+  func.ClearCode();
+  func.ClearICDataArray();
+  ASSERT(!func.HasCode());
+}
+
+#endif  // (!defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME))
+
 DART_EXPORT Dart_Handle Dart_CreateCoreJITSnapshotAsBlobs(
     uint8_t** vm_snapshot_data_buffer,
     intptr_t* vm_snapshot_data_size,
@@ -6347,18 +6414,23 @@
     return state;
   }
   BackgroundCompiler::Stop(I);
+  DropRegExpMatchCode(Z);
 
   ProgramVisitor::Dedup();
   Symbols::Compact(I);
 
   NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
                                             "WriteCoreJITSnapshot"));
-  BlobImageWriter vm_image_writer(vm_snapshot_instructions_buffer,
+  BlobImageWriter vm_image_writer(T, vm_snapshot_instructions_buffer,
                                   ApiReallocate, 2 * MB /* initial_size */,
-                                  NULL, NULL);
-  BlobImageWriter isolate_image_writer(isolate_snapshot_instructions_buffer,
+                                  /*shared_objects=*/nullptr,
+                                  /*shared_instructions=*/nullptr,
+                                  /*reused_objects=*/nullptr);
+  BlobImageWriter isolate_image_writer(T, isolate_snapshot_instructions_buffer,
                                        ApiReallocate, 2 * MB /* initial_size */,
-                                       NULL, NULL);
+                                       /*shared_objects=*/nullptr,
+                                       /*shared_instructions=*/nullptr,
+                                       /*reused_objects=*/nullptr);
   FullSnapshotWriter writer(Snapshot::kFullJIT, vm_snapshot_data_buffer,
                             isolate_snapshot_data_buffer, ApiReallocate,
                             &vm_image_writer, &isolate_image_writer);
@@ -6402,6 +6474,7 @@
     return state;
   }
   BackgroundCompiler::Stop(I);
+  DropRegExpMatchCode(Z);
 
   if (reused_instructions) {
     DropCodeWithoutReusableInstructions(reused_instructions);
@@ -6411,9 +6484,11 @@
 
   NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
                                             "WriteAppJITSnapshot"));
-  BlobImageWriter isolate_image_writer(isolate_snapshot_instructions_buffer,
+  BlobImageWriter isolate_image_writer(T, isolate_snapshot_instructions_buffer,
                                        ApiReallocate, 2 * MB /* initial_size */,
-                                       NULL, NULL, reused_instructions);
+                                       /*shared_objects=*/nullptr,
+                                       /*shared_instructions=*/nullptr,
+                                       reused_instructions);
   FullSnapshotWriter writer(Snapshot::kFullJIT, NULL,
                             isolate_snapshot_data_buffer, ApiReallocate, NULL,
                             &isolate_image_writer);
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index e6a1361..adb7182 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -134,9 +134,9 @@
   class Scope : public StackResource {
    public:
     explicit Scope(Thread* thread) : StackResource(thread) {
-      Dart_EnterScope();
+      thread->EnterApiScope();
     }
-    ~Scope() { Dart_ExitScope(); }
+    ~Scope() { thread()->ExitApiScope(); }
 
    private:
     DISALLOW_COPY_AND_ASSIGN(Scope);
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 995a437..c77865b 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -671,7 +671,11 @@
 }
 
 TEST_CASE(DartAPI_Error) {
-  Dart_Handle error = Api::NewError("An %s", "error");
+  Dart_Handle error;
+  {
+    TransitionNativeToVM transition(thread);
+    error = Api::NewError("An %s", "error");
+  }
   EXPECT(Dart_IsError(error));
   EXPECT_STREQ("An error", Dart_GetError(error));
 }
@@ -728,7 +732,6 @@
   // Non-instance objects.
   {
     CHECK_API_SCOPE(thread);
-    HANDLESCOPE(thread);
     Dart_Handle lib1 = Dart_LookupLibrary(dart_core);
     Dart_Handle lib2 = Dart_LookupLibrary(dart_mirrors);
 
@@ -780,15 +783,21 @@
   Dart_Handle type = Dart_InstanceGetType(Dart_Null());
   EXPECT_VALID(type);
   EXPECT(Dart_IsType(type));
-  const Type& null_type_obj = Api::UnwrapTypeHandle(zone, type);
-  EXPECT(null_type_obj.raw() == Type::NullType());
+  {
+    TransitionNativeToVM transition(thread);
+    const Type& null_type_obj = Api::UnwrapTypeHandle(zone, type);
+    EXPECT(null_type_obj.raw() == Type::NullType());
+  }
 
   Dart_Handle instance = Dart_True();
   type = Dart_InstanceGetType(instance);
   EXPECT_VALID(type);
   EXPECT(Dart_IsType(type));
-  const Type& bool_type_obj = Api::UnwrapTypeHandle(zone, type);
-  EXPECT(bool_type_obj.raw() == Type::BoolType());
+  {
+    TransitionNativeToVM transition(thread);
+    const Type& bool_type_obj = Api::UnwrapTypeHandle(zone, type);
+    EXPECT(bool_type_obj.raw() == Type::BoolType());
+  }
 
   // Errors propagate.
   Dart_Handle error = Dart_NewApiError("MyError");
@@ -1470,6 +1479,7 @@
     EXPECT_VALID(small16);
     {
       CHECK_API_SCOPE(thread);
+      TransitionNativeToVM transition(thread);
       HANDLESCOPE(thread);
       String& handle = String::Handle();
       handle ^= Api::UnwrapHandle(big8);
@@ -1500,6 +1510,7 @@
     EXPECT_VALID(small);
     {
       CHECK_API_SCOPE(thread);
+      TransitionNativeToVM transition(thread);
       HANDLESCOPE(thread);
       ExternalTypedData& handle = ExternalTypedData::Handle();
       handle ^= Api::UnwrapHandle(big);
@@ -2703,12 +2714,10 @@
   Dart_EnterScope();
   {
     EXPECT(thread->api_top_scope() != NULL);
+    TransitionNativeToVM transition(thread);
     HANDLESCOPE(thread);
     String& str1 = String::Handle();
-    {
-      TransitionNativeToVM transition(thread);
-      str1 = String::New("Test String");
-    }
+    str1 = String::New("Test String");
     Dart_Handle ref = Api::NewHandle(thread, str1.raw());
     String& str2 = String::Handle();
     str2 ^= Api::UnwrapHandle(ref);
@@ -2733,7 +2742,6 @@
   Dart_EnterScope();
   {
     CHECK_API_SCOPE(thread);
-    HANDLESCOPE(thread);
     Dart_Handle ref1 = Dart_NewStringFromCString(kTestString1);
     for (int i = 0; i < 1000; i++) {
       handles[i] = Dart_NewPersistentHandle(ref1);
@@ -2757,6 +2765,7 @@
   }
   Dart_ExitScope();
   {
+    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     for (int i = 0; i < 500; i++) {
@@ -2796,7 +2805,6 @@
   EXPECT(state != NULL);
   Thread* thread = Thread::Current();
   CHECK_API_SCOPE(thread);
-  HANDLESCOPE(thread);
 
   // Start with a known persistent handle.
   Dart_PersistentHandle obj1 = Dart_NewPersistentHandle(Dart_True());
@@ -2824,25 +2832,33 @@
 
   Thread* T = Thread::Current();
   CHECK_API_SCOPE(T);
-  HANDLESCOPE(T);
   Isolate* isolate = T->isolate();
   EXPECT(isolate != NULL);
   ApiState* state = isolate->api_state();
   EXPECT(state != NULL);
-  String& str = String::Handle();
 
   // Start with a known persistent handle.
   Dart_Handle ref1 = Dart_NewStringFromCString(kTestString1);
   Dart_PersistentHandle obj = Dart_NewPersistentHandle(ref1);
   EXPECT(state->IsValidPersistentHandle(obj));
-  str ^= PersistentHandle::Cast(obj)->raw();
-  EXPECT(str.Equals(kTestString1));
+  {
+    TransitionNativeToVM transition(T);
+    HANDLESCOPE(T);
+    String& str = String::Handle();
+    str ^= PersistentHandle::Cast(obj)->raw();
+    EXPECT(str.Equals(kTestString1));
+  }
 
   // Now create another local handle and assign it to the persistent handle.
   Dart_Handle ref2 = Dart_NewStringFromCString(kTestString2);
   Dart_SetPersistentHandle(obj, ref2);
-  str ^= PersistentHandle::Cast(obj)->raw();
-  EXPECT(str.Equals(kTestString2));
+  {
+    TransitionNativeToVM transition(T);
+    HANDLESCOPE(T);
+    String& str = String::Handle();
+    str ^= PersistentHandle::Cast(obj)->raw();
+    EXPECT(str.Equals(kTestString2));
+  }
 
   // Now assign Null to the persistent handle and check.
   Dart_SetPersistentHandle(obj, Dart_Null());
@@ -3168,6 +3184,7 @@
     // external size charged to old space.
     {
       CHECK_API_SCOPE(thread);
+      TransitionNativeToVM transition(thread);
       HANDLESCOPE(thread);
       String& handle = String::Handle(thread->zone());
       handle ^= Api::UnwrapHandle(obj);
@@ -3273,7 +3290,6 @@
   Dart_EnterScope();
   {
     CHECK_API_SCOPE(thread);
-    HANDLESCOPE(thread);
 
     Dart_Handle local = AllocateOldString("strongly reachable");
     strong = Dart_NewPersistentHandle(local);
@@ -3337,7 +3353,6 @@
   Dart_EnterScope();
   {
     CHECK_API_SCOPE(thread);
-    HANDLESCOPE(thread);
 
     Dart_Handle local = AllocateOldString("strongly reachable");
     strong = Dart_NewPersistentHandle(local);
@@ -3405,43 +3420,54 @@
   Dart_Handle handles[300];
   {
     StackZone zone(thread);
+    TransitionNativeToVM transition1(thread);
     HANDLESCOPE(thread);
     Smi& val = Smi::Handle();
+    TransitionVMToNative transition2(thread);
 
     // Start a new scope and allocate some local handles.
     Dart_EnterScope();
-    for (int i = 0; i < 100; i++) {
-      handles[i] = Api::NewHandle(thread, Smi::New(i));
-    }
-    EXPECT_EQ(100, thread->CountLocalHandles());
-    for (int i = 0; i < 100; i++) {
-      val ^= Api::UnwrapHandle(handles[i]);
-      EXPECT_EQ(i, val.Value());
+    {
+      TransitionNativeToVM transition3(thread);
+      for (int i = 0; i < 100; i++) {
+        handles[i] = Api::NewHandle(thread, Smi::New(i));
+      }
+      EXPECT_EQ(100, thread->CountLocalHandles());
+      for (int i = 0; i < 100; i++) {
+        val ^= Api::UnwrapHandle(handles[i]);
+        EXPECT_EQ(i, val.Value());
+      }
     }
     // Start another scope and allocate some more local handles.
     {
       Dart_EnterScope();
-      for (int i = 100; i < 200; i++) {
-        handles[i] = Api::NewHandle(thread, Smi::New(i));
-      }
-      EXPECT_EQ(200, thread->CountLocalHandles());
-      for (int i = 100; i < 200; i++) {
-        val ^= Api::UnwrapHandle(handles[i]);
-        EXPECT_EQ(i, val.Value());
+      {
+        TransitionNativeToVM transition3(thread);
+        for (int i = 100; i < 200; i++) {
+          handles[i] = Api::NewHandle(thread, Smi::New(i));
+        }
+        EXPECT_EQ(200, thread->CountLocalHandles());
+        for (int i = 100; i < 200; i++) {
+          val ^= Api::UnwrapHandle(handles[i]);
+          EXPECT_EQ(i, val.Value());
+        }
       }
 
       // Start another scope and allocate some more local handles.
       {
         Dart_EnterScope();
-        for (int i = 200; i < 300; i++) {
-          handles[i] = Api::NewHandle(thread, Smi::New(i));
+        {
+          TransitionNativeToVM transition3(thread);
+          for (int i = 200; i < 300; i++) {
+            handles[i] = Api::NewHandle(thread, Smi::New(i));
+          }
+          EXPECT_EQ(300, thread->CountLocalHandles());
+          for (int i = 200; i < 300; i++) {
+            val ^= Api::UnwrapHandle(handles[i]);
+            EXPECT_EQ(i, val.Value());
+          }
+          EXPECT_EQ(300, thread->CountLocalHandles());
         }
-        EXPECT_EQ(300, thread->CountLocalHandles());
-        for (int i = 200; i < 300; i++) {
-          val ^= Api::UnwrapHandle(handles[i]);
-          EXPECT_EQ(i, val.Value());
-        }
-        EXPECT_EQ(300, thread->CountLocalHandles());
         VERIFY_ON_TRANSITION;
         Dart_ExitScope();
       }
@@ -4158,6 +4184,16 @@
   EXPECT_STREQ("myerror", Dart_GetError(result));
 }
 
+TEST_CASE(DartAPI_SetField_BadType) {
+  const char* kScriptChars = "int foo;\n";
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  Dart_Handle name = NewString("foo");
+  Dart_Handle result = Dart_SetField(lib, name, Dart_True());
+  EXPECT(Dart_IsError(result));
+  EXPECT_SUBSTRING("type 'bool' is not a subtype of type 'int' of 'foo'",
+                   Dart_GetError(result));
+}
+
 void NativeFieldLookup(Dart_NativeArguments args) {
   UNREACHABLE();
 }
@@ -4221,6 +4257,7 @@
   result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
   EXPECT_VALID(result);
   CHECK_API_SCOPE(thread);
+  TransitionNativeToVM transition(thread);
   HANDLESCOPE(thread);
   Instance& obj = Instance::Handle();
   obj ^= Api::UnwrapHandle(result);
@@ -4302,6 +4339,7 @@
                                                          bool* auto_scope) {
   ASSERT(auto_scope != NULL);
   *auto_scope = true;
+  TransitionNativeToVM transition(Thread::Current());
   const Object& obj = Object::Handle(Api::UnwrapHandle(name));
   if (!obj.IsString()) {
     return NULL;
@@ -4494,7 +4532,6 @@
       "}\n";
   Dart_Handle result;
   CHECK_API_SCOPE(thread);
-  HANDLESCOPE(thread);
 
   // Create a test library and Load up a test script in it.
   Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
@@ -5141,6 +5178,88 @@
   EXPECT_STREQ("myerror", Dart_GetError(result));
 }
 
+TEST_CASE(DartAPI_Invoke_BadArgs) {
+  const char* kScriptChars =
+      "class BaseMethods {\n"
+      "  inheritedMethod(int arg) => 'inherited $arg';\n"
+      "  static nonInheritedMethod(int arg) => 'noninherited $arg';\n"
+      "}\n"
+      "\n"
+      "class Methods extends BaseMethods {\n"
+      "  instanceMethod(int arg) => 'instance $arg';\n"
+      "  _instanceMethod(int arg) => 'hidden instance $arg';\n"
+      "  static staticMethod(int arg) => 'static $arg';\n"
+      "  static _staticMethod(int arg) => 'hidden static $arg';\n"
+      "}\n"
+      "\n"
+      "topMethod(int arg) => 'top $arg';\n"
+      "_topMethod(int arg) => 'hidden top $arg';\n"
+      "\n"
+      "Methods test() {\n"
+      "  return new Methods();\n"
+      "}\n";
+
+#if defined(PRODUCT)
+  const char* error_msg =
+      "type '_OneByteString' is not a subtype of type 'int' of 'arg'";
+#else
+  const char* error_msg =
+      "type 'String' is not a subtype of type 'int' of 'arg'";
+#endif  // defined(PRODUCT)
+
+  // Shared setup.
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  Dart_Handle type = Dart_GetType(lib, NewString("Methods"), 0, NULL);
+  EXPECT_VALID(type);
+  Dart_Handle instance = Dart_Invoke(lib, NewString("test"), 0, NULL);
+  EXPECT_VALID(instance);
+  Dart_Handle args[1];
+  args[0] = NewString("!!!");
+  Dart_Handle result;
+  Dart_Handle name;
+
+  // Instance method.
+  name = NewString("instanceMethod");
+  result = Dart_Invoke(instance, name, 1, args);
+  EXPECT(Dart_IsError(result));
+  EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
+
+  name = PrivateLibName(lib, "_instanceMethod");
+  result = Dart_Invoke(instance, name, 1, args);
+  EXPECT(Dart_IsError(result));
+  EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
+
+  // Inherited method.
+  name = NewString("inheritedMethod");
+  result = Dart_Invoke(instance, name, 1, args);
+  EXPECT(Dart_IsError(result));
+  EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
+
+  // Static method.
+  name = NewString("staticMethod");
+  result = Dart_Invoke(type, name, 1, args);
+  EXPECT(Dart_IsError(result));
+  EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
+
+  // Hidden static method.
+  name = NewString("_staticMethod");
+  result = Dart_Invoke(type, name, 1, args);
+  EXPECT(Dart_IsError(result));
+  EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
+
+  // Top-Level method.
+  name = NewString("topMethod");
+  result = Dart_Invoke(lib, name, 1, args);
+  EXPECT(Dart_IsError(result));
+  EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
+
+  // Hidden top-level method.
+  name = NewString("_topMethod");
+  result = Dart_Invoke(lib, name, 1, args);
+  EXPECT(Dart_IsError(result));
+  EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
+}
+
 TEST_CASE(DartAPI_Invoke_Null) {
   Dart_Handle result = Dart_Invoke(Dart_Null(), NewString("toString"), 0, NULL);
   EXPECT_VALID(result);
@@ -5259,7 +5378,6 @@
       "}\n";
   Dart_Handle result;
   CHECK_API_SCOPE(thread);
-  HANDLESCOPE(thread);
 
   // Create a test library and Load up a test script in it.
   Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
@@ -5464,6 +5582,7 @@
 static Dart_NativeFunction native_args_lookup(Dart_Handle name,
                                               int argument_count,
                                               bool* auto_scope_setup) {
+  TransitionNativeToVM transition(Thread::Current());
   const Object& obj = Object::Handle(Api::UnwrapHandle(name));
   if (!obj.IsString()) {
     return NULL;
@@ -6059,10 +6178,10 @@
       /* multiroot_filepaths= */ "/bar,/baz",
       /* multiroot_scheme= */ "foo");
   EXPECT_VALID(lib);
-  Library& lib_obj = Library::Handle();
-  lib_obj ^= Api::UnwrapHandle(lib);
   {
     TransitionNativeToVM transition(thread);
+    Library& lib_obj = Library::Handle();
+    lib_obj ^= Api::UnwrapHandle(lib);
     EXPECT_STREQ("foo:///main.dart", String::Handle(lib_obj.url()).ToCString());
     const Array& lib_scripts = Array::Handle(lib_obj.LoadedScripts());
     Script& script = Script::Handle();
@@ -6627,6 +6746,7 @@
                                                    bool* auto_setup_scope) {
   ASSERT(auto_setup_scope != NULL);
   *auto_setup_scope = false;
+  TransitionNativeToVM transition(Thread::Current());
   const Object& obj = Object::Handle(Api::UnwrapHandle(name));
   if (!obj.IsString()) {
     return NULL;
@@ -6766,6 +6886,7 @@
     bool* auto_setup_scope) {
   ASSERT(auto_setup_scope != NULL);
   *auto_setup_scope = false;
+  TransitionNativeToVM transition(Thread::Current());
   const Object& obj = Object::Handle(Api::UnwrapHandle(name));
   if (!obj.IsString()) {
     return NULL;
@@ -6972,7 +7093,6 @@
   Dart_EnterScope();
   {
     CHECK_API_SCOPE(thread);
-    HANDLESCOPE(thread);
     Dart_Handle str = NewString("a string");
     EXPECT_VALID(str);
     EXPECT(Dart_IsString(str));
@@ -7050,7 +7170,6 @@
   Dart_EnterScope();
   {
     CHECK_API_SCOPE(thread);
-    HANDLESCOPE(thread);
     Dart_Handle s1 = NewString("s1");
     EXPECT_VALID(s1);
     EXPECT(Dart_IsString(s1));
@@ -7142,6 +7261,7 @@
   }
   {
     CHECK_API_SCOPE(thread);
+    TransitionNativeToVM transition(thread);
     HANDLESCOPE(thread);
     String& handle = String::Handle();
     handle ^= Api::UnwrapHandle(str);
@@ -7198,7 +7318,6 @@
   {
     Thread* T = Thread::Current();
     CHECK_API_SCOPE(T);
-    HANDLESCOPE(T);
     Dart_Handle str = AllocateOldString("str");
     EXPECT_VALID(str);
     EXPECT(Dart_IsString(str));
@@ -7280,7 +7399,6 @@
   {
     Thread* T = Thread::Current();
     CHECK_API_SCOPE(T);
-    HANDLESCOPE(T);
     Dart_Handle s1 = AllocateOldString("s1");
     EXPECT_VALID(s1);
     EXPECT(Dart_IsString(s1));
diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h
index 71e08f4..360585e 100644
--- a/runtime/vm/datastream.h
+++ b/runtime/vm/datastream.h
@@ -80,6 +80,12 @@
     current_ = buffer_ + value;
   }
 
+  void Align(intptr_t alignment) {
+    intptr_t position_before = Position();
+    intptr_t position_after = Utils::RoundUp(position_before, alignment);
+    Advance(position_after - position_before);
+  }
+
   const uint8_t* AddressOfCurrentPosition() const { return current_; }
 
   void Advance(intptr_t value) {
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index bbdd04f..6823611 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -259,17 +259,11 @@
       deopt_frame_(Array::ZoneHandle(deopt_frame.raw())),
       deopt_frame_offset_(deopt_frame_offset),
       kind_(kind),
-#if !defined(DART_PRECOMPILED_RUNTIME)
-      is_interpreted_(FLAG_enable_interpreter &&
-                      function_.Bytecode() == code_.raw()),
-#else
-      is_interpreted_(false),
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+      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()) {}
 
 ActivationFrame::ActivationFrame(Kind kind)
     : pc_(0),
@@ -318,22 +312,8 @@
       pc_desc_(PcDescriptors::ZoneHandle()) {
   // Extract the function and the code from the asynchronous activation.
   function_ = async_activation.function();
-#if !defined(DART_PRECOMPILED_RUNTIME)
-  // TODO(regis): Revise debugger functionality when running a mix of
-  // interpreted and compiled code.
-  if (!FLAG_enable_interpreter || !function_.HasBytecode()) {
-    function_.EnsureHasCompiledUnoptimizedCode();
-  }
-  if (FLAG_enable_interpreter && function_.HasBytecode()) {
-    is_interpreted_ = true;
-    code_ = function_.Bytecode();
-  } else {
-    code_ = function_.unoptimized_code();
-  }
-#else
   function_.EnsureHasCompiledUnoptimizedCode();
   code_ = function_.unoptimized_code();
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
   ctx_ = async_activation.context();
   ASSERT(fp_ == 0);
   ASSERT(!ctx_.IsNull());
@@ -1440,43 +1420,6 @@
   return type_arguments.raw();
 }
 
-RawObject* ActivationFrame::Evaluate(const String& expr,
-                                     const GrowableObjectArray& param_names,
-                                     const GrowableObjectArray& param_values) {
-#if defined(DART_PRECOMPILED_RUNTIME)
-  return Object::null();
-#else
-  Zone* zone = Thread::Current()->zone();
-  const GrowableObjectArray& type_params_names =
-      GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
-  TypeArguments& type_arguments = TypeArguments::Handle(
-      zone, BuildParameters(param_names, param_values, type_params_names));
-
-  if (function().is_static()) {
-    const Class& cls = Class::Handle(function().Owner());
-    return cls.Evaluate(
-        expr, Array::Handle(zone, Array::MakeFixedLength(param_names)),
-        Array::Handle(zone, Array::MakeFixedLength(param_values)),
-        Array::Handle(zone, Array::MakeFixedLength(type_params_names)),
-        type_arguments);
-  } else {
-    const Object& receiver = Object::Handle(GetReceiver());
-    const Class& method_cls = Class::Handle(function().origin());
-    ASSERT(receiver.IsInstance() || receiver.IsNull());
-    if (!(receiver.IsInstance() || receiver.IsNull())) {
-      return Object::null();
-    }
-    const Instance& inst = Instance::Cast(receiver);
-    return inst.Evaluate(
-        method_cls, expr,
-        Array::Handle(zone, Array::MakeFixedLength(param_names)),
-        Array::Handle(zone, Array::MakeFixedLength(param_values)),
-        Array::Handle(zone, Array::MakeFixedLength(type_params_names)),
-        type_arguments);
-  }
-#endif
-}
-
 const char* ActivationFrame::ToCString() {
   const String& url = String::Handle(SourceUrl());
   intptr_t line = LineNumber();
@@ -1634,8 +1577,8 @@
 #if !defined(TARGET_ARCH_DBC)
       saved_value_(Code::null())
 #else
-      saved_value_(Bytecode::kTrap),
-      saved_value_fastsmi_(Bytecode::kTrap)
+      saved_value_(SimulatorBytecode::kTrap),
+      saved_value_fastsmi_(SimulatorBytecode::kTrap)
 #endif
 {
   ASSERT(!code.IsNull());
@@ -1986,6 +1929,12 @@
                    frame->ToCString());
     }
     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;
+      }
       code = frame->LookupDartCode();
       AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
                        &inlined_code, &deopt_frame);
@@ -2067,6 +2016,10 @@
   while (synchronous_stack_trace_length > 0) {
     ASSERT(frame != NULL);
     if (frame->IsDartFrame()) {
+      if (frame->is_interpreted()) {
+        // TODO(regis): Support debugging of interpreted frames.
+        UNIMPLEMENTED();
+      }
       code = frame->LookupDartCode();
       AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
                        &inlined_code, &deopt_frame);
@@ -2162,6 +2115,10 @@
                    frame->ToCString());
     }
     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);
@@ -2331,6 +2288,12 @@
   while ((frame != NULL) && !frame->IsDartFrame()) {
     frame = iterator.NextFrame();
   }
+  ASSERT(frame != NULL);
+  if (frame->is_interpreted()) {
+    // TODO(regis): Support debugging of interpreted frames.
+    UNIMPLEMENTED();
+    return NULL;
+  }
   Code& code = Code::Handle(frame->LookupDartCode());
   ActivationFrame* activation = new ActivationFrame(
       frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0);
@@ -2366,6 +2329,7 @@
 DebuggerStackTrace* Debugger::StackTraceFrom(const class StackTrace& ex_trace) {
   DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
   Function& function = Function::Handle();
+  Object& code_object = Object::Handle();
   Code& code = Code::Handle();
 
   const uword fp = 0;
@@ -2374,17 +2338,21 @@
   const intptr_t deopt_frame_offset = -1;
 
   for (intptr_t i = 0; i < ex_trace.Length(); i++) {
-    code = ex_trace.CodeAtFrame(i);
+    code_object = ex_trace.CodeAtFrame(i);
     // Pre-allocated StackTraces may include empty slots, either (a) to indicate
     // where frames were omitted in the case a stack has more frames than the
     // pre-allocated trace (such as a stack overflow) or (b) because a stack has
     // fewer frames that the pre-allocated trace (such as memory exhaustion with
     // a shallow stack).
-    if (!code.IsNull()) {
+    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()) {
-        code = ex_trace.CodeAtFrame(i);
         ASSERT(function.raw() == code.function());
         uword pc =
             code.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index ee4f234..4bd77a3 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -333,10 +333,6 @@
       const GrowableObjectArray& param_values,
       const GrowableObjectArray& type_params_names);
 
-  RawObject* Evaluate(const String& expr,
-                      const GrowableObjectArray& names,
-                      const GrowableObjectArray& values);
-
   RawObject* EvaluateCompiledExpression(const uint8_t* kernel_bytes,
                                         intptr_t kernel_length,
                                         const Array& arguments,
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc
index 88792e5..bfb94b4 100644
--- a/runtime/vm/debugger_api_impl_test.cc
+++ b/runtime/vm/debugger_api_impl_test.cc
@@ -219,16 +219,20 @@
 
 DART_EXPORT Dart_Handle Dart_SetBreakpoint(Dart_Handle script_url_in,
                                            intptr_t line_number) {
-  DARTSCOPE(Thread::Current());
-  Isolate* I = T->isolate();
-  CHECK_DEBUGGER(I);
-  UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
+  Breakpoint* bpt;
+  {
+    DARTSCOPE(Thread::Current());
+    Isolate* I = T->isolate();
+    CHECK_DEBUGGER(I);
+    UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
 
-  Debugger* debugger = I->debugger();
-  Breakpoint* bpt = debugger->SetBreakpointAtLine(script_url, line_number);
-  if (bpt == NULL) {
-    return Api::NewError("%s: could not set breakpoint at line %" Pd " in '%s'",
-                         CURRENT_FUNC, line_number, script_url.ToCString());
+    Debugger* debugger = I->debugger();
+    bpt = debugger->SetBreakpointAtLine(script_url, line_number);
+    if (bpt == NULL) {
+      return Api::NewError("%s: could not set breakpoint at line %" Pd
+                           " in '%s'",
+                           CURRENT_FUNC, line_number, script_url.ToCString());
+    }
   }
   return Dart_NewInteger(bpt->id());
 }
@@ -248,20 +252,16 @@
   UNWRAP_AND_CHECK_PARAM(String, expr, expr_in);
 
   if (!KernelIsolate::IsRunning()) {
-    return Api::NewHandle(
-        T, lib.Evaluate(expr, Array::empty_array(), Array::empty_array()));
+    UNREACHABLE();
   } else {
-    Dart_KernelCompilationResult compilation_result;
-    {
-      TransitionVMToNative transition(T);
-      compilation_result = KernelIsolate::CompileExpressionToKernel(
-          expr.ToCString(),
-          /* definitions= */ Array::empty_array(),
-          /* type_defintions= */ Array::empty_array(),
-          String::Handle(lib.url()).ToCString(),
-          /* klass= */ nullptr,
-          /* is_static= */ false);
-    }
+    Dart_KernelCompilationResult compilation_result =
+        KernelIsolate::CompileExpressionToKernel(
+            expr.ToCString(),
+            /* definitions= */ Array::empty_array(),
+            /* type_defintions= */ Array::empty_array(),
+            String::Handle(lib.url()).ToCString(),
+            /* klass= */ nullptr,
+            /* is_static= */ false);
     if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
       return Api::NewError("Failed to compile expression.");
     }
diff --git a/runtime/vm/debugger_dbc.cc b/runtime/vm/debugger_dbc.cc
index 8287e2b..c36dddb 100644
--- a/runtime/vm/debugger_dbc.cc
+++ b/runtime/vm/debugger_dbc.cc
@@ -40,13 +40,14 @@
         // DebugBreak has an A operand matching the call it replaces.
         // This ensures that Return instructions continue to work - as they
         // look at calls to figure out how many arguments to drop.
-        *CallInstructionFromReturnAddress(pc_) = Bytecode::Encode(
-            Bytecode::kDebugBreak, Bytecode::DecodeArgc(saved_value_), 0, 0);
+        *CallInstructionFromReturnAddress(pc_) = SimulatorBytecode::Encode(
+            SimulatorBytecode::kDebugBreak,
+            SimulatorBytecode::DecodeArgc(saved_value_), 0, 0);
         break;
       }
 
       case RawPcDescriptors::kRuntimeCall: {
-        *CallInstructionFromReturnAddress(pc_) = Bytecode::kDebugBreak;
+        *CallInstructionFromReturnAddress(pc_) = SimulatorBytecode::kDebugBreak;
         break;
       }
 
@@ -56,13 +57,15 @@
 
     // If this call is the fall-through for a fast Smi op, also disable the fast
     // Smi op.
-    if ((Bytecode::DecodeOpcode(saved_value_) == Bytecode::kInstanceCall2) &&
-        Bytecode::IsFastSmiOpcode(*FastSmiInstructionFromReturnAddress(pc_))) {
+    if ((SimulatorBytecode::DecodeOpcode(saved_value_) ==
+         SimulatorBytecode::kInstanceCall2) &&
+        SimulatorBytecode::IsFastSmiOpcode(
+            *FastSmiInstructionFromReturnAddress(pc_))) {
       saved_value_fastsmi_ = *FastSmiInstructionFromReturnAddress(pc_);
       *FastSmiInstructionFromReturnAddress(pc_) =
-          Bytecode::Encode(Bytecode::kNop, 0, 0, 0);
+          SimulatorBytecode::Encode(SimulatorBytecode::kNop, 0, 0, 0);
     } else {
-      saved_value_fastsmi_ = Bytecode::kTrap;
+      saved_value_fastsmi_ = SimulatorBytecode::kTrap;
     }
   }
   is_enabled_ = true;
@@ -85,9 +88,10 @@
         UNREACHABLE();
     }
 
-    if (saved_value_fastsmi_ != Bytecode::kTrap) {
+    if (saved_value_fastsmi_ != SimulatorBytecode::kTrap) {
       Instr current_instr = *FastSmiInstructionFromReturnAddress(pc_);
-      ASSERT(Bytecode::DecodeOpcode(current_instr) == Bytecode::kNop);
+      ASSERT(SimulatorBytecode::DecodeOpcode(current_instr) ==
+             SimulatorBytecode::kNop);
       *FastSmiInstructionFromReturnAddress(pc_) = saved_value_fastsmi_;
     }
   }
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index ec35ebc8..7d082c7 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -406,6 +406,7 @@
                                StackFrameIterator::kNoCrossThreadIteration);
     StackFrame* top_frame = iterator.NextFrame();
     ASSERT(top_frame != NULL);
+    ASSERT(!top_frame->is_interpreted());
     const Code& code = Code::Handle(top_frame->LookupDartCode());
     const Function& top_function = Function::Handle(code.function());
     const Script& script = Script::Handle(top_function.script());
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 06f5a47..123870a 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -37,7 +37,7 @@
   StackTraceBuilder() {}
   virtual ~StackTraceBuilder() {}
 
-  virtual void AddFrame(const Code& code, const Smi& offset) = 0;
+  virtual void AddFrame(const Object& code, const Smi& offset) = 0;
 };
 
 class RegularStackTraceBuilder : public StackTraceBuilder {
@@ -52,7 +52,7 @@
   const GrowableObjectArray& code_list() const { return code_list_; }
   const GrowableObjectArray& pc_offset_list() const { return pc_offset_list_; }
 
-  virtual void AddFrame(const Code& code, const Smi& offset) {
+  virtual void AddFrame(const Object& code, const Smi& offset) {
     code_list_.Add(code);
     pc_offset_list_.Add(offset);
   }
@@ -75,7 +75,7 @@
   }
   ~PreallocatedStackTraceBuilder() {}
 
-  virtual void AddFrame(const Code& code, const Smi& offset);
+  virtual void AddFrame(const Object& code, const Smi& offset);
 
  private:
   static const int kNumTopframes = StackTrace::kPreallocatedStackdepth / 2;
@@ -87,11 +87,11 @@
   DISALLOW_COPY_AND_ASSIGN(PreallocatedStackTraceBuilder);
 };
 
-void PreallocatedStackTraceBuilder::AddFrame(const Code& code,
+void PreallocatedStackTraceBuilder::AddFrame(const Object& code,
                                              const Smi& offset) {
   if (cur_index_ >= StackTrace::kPreallocatedStackdepth) {
     // The number of frames is overflowing the preallocated stack trace object.
-    Code& frame_code = Code::Handle();
+    Object& frame_code = Object::Handle();
     Smi& frame_offset = Smi::Handle();
     intptr_t start = StackTrace::kPreallocatedStackdepth - (kNumTopframes - 1);
     intptr_t null_slot = start - 2;
@@ -129,13 +129,21 @@
   StackFrame* frame = frames.NextFrame();
   ASSERT(frame != NULL);  // We expect to find a dart invocation frame.
   Code& code = Code::Handle();
+  Bytecode& bytecode = Bytecode::Handle();
   Smi& offset = Smi::Handle();
   while (frame != NULL) {
     if (frame->IsDartFrame()) {
-      code = frame->LookupDartCode();
-      ASSERT(code.ContainsInstructionAt(frame->pc()));
-      offset = Smi::New(frame->pc() - code.PayloadStart());
-      builder->AddFrame(code, offset);
+      if (frame->is_interpreted()) {
+        bytecode = frame->LookupDartBytecode();
+        ASSERT(bytecode.ContainsInstructionAt(frame->pc()));
+        offset = Smi::New(frame->pc() - bytecode.PayloadStart());
+        builder->AddFrame(bytecode, offset);
+      } else {
+        code = frame->LookupDartCode();
+        ASSERT(code.ContainsInstructionAt(frame->pc()));
+        offset = Smi::New(frame->pc() - code.PayloadStart());
+        builder->AddFrame(code, offset);
+      }
     }
     frame = frames.NextFrame();
   }
diff --git a/runtime/vm/exceptions_test.cc b/runtime/vm/exceptions_test.cc
index fcd8869..fe090d6 100644
--- a/runtime/vm/exceptions_test.cc
+++ b/runtime/vm/exceptions_test.cc
@@ -14,8 +14,12 @@
 
 void FUNCTION_NAME(Unhandled_equals)(Dart_NativeArguments args) {
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
-  const Instance& expected = Instance::CheckedHandle(arguments->NativeArgAt(0));
-  const Instance& actual = Instance::CheckedHandle(arguments->NativeArgAt(1));
+  TransitionNativeToVM transition(arguments->thread());
+  Zone* zone = arguments->thread()->zone();
+  const Instance& expected =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
+  const Instance& actual =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
   if (!expected.CanonicalizeEquals(actual)) {
     OS::PrintErr("expected: '%s' actual: '%s'\n", expected.ToCString(),
                  actual.ToCString());
@@ -64,6 +68,7 @@
                                          bool* auto_setup_scope) {
   ASSERT(auto_setup_scope != NULL);
   *auto_setup_scope = true;
+  TransitionNativeToVM transition(Thread::Current());
   const Object& obj = Object::Handle(Api::UnwrapHandle(name));
   ASSERT(obj.IsString());
   const char* function_name = obj.ToCString();
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 531152e..0c9ea3c 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -68,6 +68,8 @@
   P(compilation_counter_threshold, int, 10,                                    \
     "Function's usage-counter value before interpreted function is compiled, " \
     "-1 means never")                                                          \
+  P(concurrent_mark, bool, USING_MULTICORE,                                    \
+    "Concurrent mark for old generation.")                                     \
   P(concurrent_sweep, bool, USING_MULTICORE,                                   \
     "Concurrent sweep for old generation.")                                    \
   R(dedup_instructions, true, bool, false,                                     \
@@ -170,16 +172,27 @@
   R(support_timeline, false, bool, true, "Support timeline.")                  \
   D(trace_cha, bool, false, "Trace CHA operations")                            \
   R(trace_field_guards, false, bool, false, "Trace changes in field's cids.")  \
+  D(trace_ic, bool, false, "Trace IC handling")                                \
+  D(trace_ic_miss_in_optimized, bool, false,                                   \
+    "Trace IC miss in optimized code")                                         \
   C(trace_irregexp, false, false, bool, false, "Trace irregexps.")             \
+  D(trace_intrinsified_natives, bool, false,                                   \
+    "Report if any of the intrinsified natives are called")                    \
   D(trace_isolates, bool, false, "Trace isolate creation and shut down.")      \
   D(trace_handles, bool, false, "Traces allocation of handles.")               \
   D(trace_kernel_binary, bool, false, "Trace Kernel reader/writer.")           \
+  D(trace_natives, bool, false, "Trace invocation of natives")                 \
   D(trace_optimization, bool, false, "Print optimization details.")            \
   R(trace_profiler, false, bool, false, "Profiler trace")                      \
   D(trace_profiler_verbose, bool, false, "Verbose profiler trace")             \
+  D(trace_runtime_calls, bool, false, "Trace runtime calls.")                  \
   D(trace_ssa_allocator, bool, false, "Trace register allocation over SSA.")   \
   P(trace_strong_mode_types, bool, false,                                      \
     "Trace optimizations based on strong mode types.")                         \
+  D(trace_type_checks, bool, false, "Trace runtime type checks.")              \
+  D(trace_patching, bool, false, "Trace patching of code.")                    \
+  D(trace_optimized_ic_calls, bool, false,                                     \
+    "Trace IC calls in optimized code.")                                       \
   D(trace_zones, bool, false, "Traces allocation sizes in the zone.")          \
   P(truncating_left_shift, bool, true,                                         \
     "Optimize left shift to truncate if possible")                             \
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index 82f860c..a261211 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -85,10 +85,6 @@
 #define TAG_IC_DATA
 #endif
 
-#if !defined(TARGET_OS_MACOS_IOS) && !defined(TARGET_OS_ANDROID)
-#define CONCURRENT_MARKING 1
-#endif
-
 // The expression OFFSET_OF(type, field) computes the byte-offset of
 // the specified field relative to the containing type.
 //
diff --git a/runtime/vm/growable_array_test.cc b/runtime/vm/growable_array_test.cc
index 1796f75..2b9b23b 100644
--- a/runtime/vm/growable_array_test.cc
+++ b/runtime/vm/growable_array_test.cc
@@ -92,7 +92,7 @@
   EXPECT_EQ(4, g.Last());
 }
 
-TEST_CASE(GrowableHandlePtr) {
+ISOLATE_UNIT_TEST_CASE(GrowableHandlePtr) {
   Zone* zone = Thread::Current()->zone();
   GrowableHandlePtrArray<const String> test1(zone, 1);
   EXPECT_EQ(0, test1.length());
diff --git a/runtime/vm/handles.cc b/runtime/vm/handles.cc
index 866260a..33e2e70 100644
--- a/runtime/vm/handles.cc
+++ b/runtime/vm/handles.cc
@@ -73,7 +73,7 @@
 }
 
 void HandleScope::Initialize() {
-  ASSERT(thread()->no_handle_scope_depth() == 0);
+  ASSERT(thread()->MayAllocateHandles());
   VMHandles* handles = thread()->zone()->handles();
   ASSERT(handles != NULL);
   saved_handle_block_ = handles->scoped_blocks_;
@@ -102,14 +102,4 @@
 #endif
 }
 
-#if defined(DEBUG)
-NoHandleScope::NoHandleScope(Thread* thread) : StackResource(thread) {
-  thread->IncrementNoHandleScopeDepth();
-}
-
-NoHandleScope::~NoHandleScope() {
-  thread()->DecrementNoHandleScopeDepth();
-}
-#endif  // defined(DEBUG)
-
 }  // namespace dart
diff --git a/runtime/vm/handles.h b/runtime/vm/handles.h
index 374181a..7eaf8a6 100644
--- a/runtime/vm/handles.h
+++ b/runtime/vm/handles.h
@@ -45,15 +45,6 @@
 //   Handles::AllocateZoneHandle() function for creating zone handles.
 //   The ZoneHandle function of the object type is the only way to create
 //   zone handles in the dart VM.
-//
-// There are some critical regions of the Dart VM were we may need to manipulate
-// raw dart objects directly. We use NOHANDLESCOPE to assert that we do not
-// add code that will allocate new handles during this critical area.
-// {
-//   NOHANDLESCOPE(thread);
-//   ....
-//   ....
-// }
 
 // Forward declarations.
 class ObjectPointerVisitor;
@@ -307,43 +298,6 @@
 #define HANDLESCOPE(thread)                                                    \
   dart::HandleScope vm_internal_handles_scope_(thread);
 
-// The class NoHandleScope is used in critical regions of the virtual machine
-// code where raw dart object pointers are directly manipulated.
-// This class asserts that we do not add code that will allocate new handles
-// during this critical area.
-// It is used as follows:
-// {
-//   NOHANDLESCOPE(thread);
-//   ....
-//   .....
-//   critical code that manipulates dart objects directly.
-//   ....
-// }
-#if defined(DEBUG)
-class NoHandleScope : public StackResource {
- public:
-  explicit NoHandleScope(Thread* thread);
-  ~NoHandleScope();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NoHandleScope);
-};
-#else   // defined(DEBUG)
-class NoHandleScope : public ValueObject {
- public:
-  explicit NoHandleScope(Thread* thread) {}
-  NoHandleScope() {}
-  ~NoHandleScope() {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NoHandleScope);
-};
-#endif  // defined(DEBUG)
-
-// Macro to start a no handles scope in the code.
-#define NOHANDLESCOPE(thread)                                                  \
-  dart::NoHandleScope no_vm_internal_handles_scope_(thread);
-
 }  // namespace dart
 
 #endif  // RUNTIME_VM_HANDLES_H_
diff --git a/runtime/vm/handles_impl.h b/runtime/vm/handles_impl.h
index 901a837..3bbd19f 100644
--- a/runtime/vm/handles_impl.h
+++ b/runtime/vm/handles_impl.h
@@ -82,7 +82,7 @@
 #if defined(DEBUG)
   Thread* thread = Thread::Current();
   ASSERT(thread->top_handle_scope() != NULL);
-  ASSERT(thread->no_handle_scope_depth() == 0);
+  ASSERT(thread->MayAllocateHandles());
 #endif  // DEBUG
   Handles* handles = zone->handles();
   ASSERT(handles != NULL);
@@ -97,7 +97,7 @@
 #if defined(DEBUG)
   Thread* thread = Thread::Current();
   ASSERT(zone->ContainsNestedZone(thread->zone()));
-  ASSERT(thread->no_handle_scope_depth() == 0);
+  ASSERT(thread->MayAllocateHandles());
 #endif  // DEBUG
   Handles* handles = zone->handles();
   ASSERT(handles != NULL);
diff --git a/runtime/vm/handles_test.cc b/runtime/vm/handles_test.cc
index 040225e..8dcb1ba 100644
--- a/runtime/vm/handles_test.cc
+++ b/runtime/vm/handles_test.cc
@@ -14,7 +14,7 @@
 namespace dart {
 
 // Unit test for Zone handle allocation.
-TEST_CASE(AllocateZoneHandle) {
+ISOLATE_UNIT_TEST_CASE(AllocateZoneHandle) {
 #if defined(DEBUG)
   FLAG_trace_handles = true;
 #endif
@@ -38,7 +38,7 @@
 }
 
 // Unit test for Scope handle allocation.
-TEST_CASE(AllocateScopeHandle) {
+ISOLATE_UNIT_TEST_CASE(AllocateScopeHandle) {
 #if defined(DEBUG)
   FLAG_trace_handles = true;
 #endif
@@ -86,11 +86,11 @@
 #if defined(DEBUG)
   FLAG_trace_handles = true;
 #endif
-  Thread* current = Thread::Current();
   Dart_Handle handle = NULL;
   // Check validity using zone handles.
   {
-    StackZone sz(current);
+    TransitionNativeToVM transition(thread);
+    StackZone sz(thread);
     handle = reinterpret_cast<Dart_Handle>(&Smi::ZoneHandle(Smi::New(1)));
     EXPECT_VALID(handle);
   }
@@ -98,18 +98,26 @@
 
   // Check validity using scoped handles.
   {
-    HANDLESCOPE(current);
     Dart_EnterScope();
-    handle = reinterpret_cast<Dart_Handle>(&Smi::Handle(Smi::New(1)));
-    EXPECT_VALID(handle);
+    {
+      TransitionNativeToVM transition(thread);
+      HANDLESCOPE(thread);
+      handle = reinterpret_cast<Dart_Handle>(&Smi::Handle(Smi::New(1)));
+      EXPECT_VALID(handle);
+    }
     Dart_ExitScope();
   }
   EXPECT(!Api::IsValid(handle));
 
   // Check validity using persistent handle.
   Isolate* isolate = Isolate::Current();
+  Dart_Handle scoped_handle;
+  {
+    TransitionNativeToVM transition(thread);
+    scoped_handle = Api::NewHandle(thread, Smi::New(1));
+  }
   Dart_PersistentHandle persistent_handle =
-      Dart_NewPersistentHandle(Api::NewHandle(thread, Smi::New(1)));
+      Dart_NewPersistentHandle(scoped_handle);
   EXPECT_VALID(persistent_handle);
 
   Dart_DeletePersistentHandle(persistent_handle);
diff --git a/runtime/vm/heap/become.h b/runtime/vm/heap/become.h
index e962735..20804ea 100644
--- a/runtime/vm/heap/become.h
+++ b/runtime/vm/heap/become.h
@@ -80,17 +80,16 @@
   // Useful for atomically applying behavior and schema changes.
   static void ElementsForwardIdentity(const Array& before, const Array& after);
 
-  // Update any references pointing to forwarding objects to point the
-  // forwarding objects' targets. Used by the implementation of become and the
-  // simplistic compactor.
-  static void FollowForwardingPointers(Thread* thread);
-
   // Convert and instance object into a dummy object,
   // making the instance independent of its class.
   // (used for morphic instances during reload).
   static void MakeDummyObject(const Instance& instance);
 
  private:
+  // Update any references pointing to forwarding objects to point the
+  // forwarding objects' targets.
+  static void FollowForwardingPointers(Thread* thread);
+
   static void CrashDump(RawObject* before_obj, RawObject* after_obj);
 };
 
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index 6f205184..04739b0 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -380,6 +380,7 @@
   friend class Precompiler;  // VisitObjects
   friend class Unmarker;     // VisitObjects
   friend class ServiceEvent;
+  friend class Scavenger;             // VerifyGC
   friend class PageSpace;             // VerifyGC
   friend class IsolateReloadContext;  // VisitObjects
   friend class ClassFinalizer;        // VisitObjects
diff --git a/runtime/vm/heap/heap_test.cc b/runtime/vm/heap/heap_test.cc
index 357b577..c47ff50 100644
--- a/runtime/vm/heap/heap_test.cc
+++ b/runtime/vm/heap/heap_test.cc
@@ -66,12 +66,15 @@
   EXPECT_VALID(result);
   EXPECT(!Dart_IsNull(result));
   EXPECT(Dart_IsList(result));
-  TransitionNativeToVM transition(thread);
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
-  heap->CollectGarbage(Heap::kOld);
+  {
+    TransitionNativeToVM transition(thread);
+    thread->heap()->CollectGarbage(Heap::kOld);
+  }
   Dart_ExitScope();
-  heap->CollectGarbage(Heap::kOld);
+  {
+    TransitionNativeToVM transition(thread);
+    thread->heap()->CollectGarbage(Heap::kOld);
+  }
 }
 
 #ifndef PRODUCT
@@ -118,78 +121,84 @@
   Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
   EXPECT_VALID(result);
   EXPECT(!Dart_IsNull(result));
-  TransitionNativeToVM transition(thread);
-  Library& lib = Library::Handle();
-  lib ^= Api::UnwrapHandle(h_lib);
-  EXPECT(!lib.IsNull());
-  const Class& cls = Class::Handle(GetClass(lib, "A"));
-  ASSERT(!cls.IsNull());
-  intptr_t cid = cls.id();
-  ClassHeapStats* class_stats =
-      ClassHeapStatsTestHelper::GetHeapStatsForCid(class_table, cid);
-  // Verify preconditions:
-  EXPECT_EQ(0, class_stats->pre_gc.old_count);
-  EXPECT_EQ(0, class_stats->post_gc.old_count);
-  EXPECT_EQ(0, class_stats->recent.old_count);
-  EXPECT_EQ(0, class_stats->pre_gc.new_count);
-  EXPECT_EQ(0, class_stats->post_gc.new_count);
-  // Class allocated twice since GC from new space.
-  EXPECT_EQ(2, class_stats->recent.new_count);
-  // Perform GC.
-  heap->CollectGarbage(Heap::kNew);
-  // Verify postconditions:
-  EXPECT_EQ(0, class_stats->pre_gc.old_count);
-  EXPECT_EQ(0, class_stats->post_gc.old_count);
-  EXPECT_EQ(0, class_stats->recent.old_count);
-  // Total allocations before GC.
-  EXPECT_EQ(2, class_stats->pre_gc.new_count);
-  // Only one survived.
-  EXPECT_EQ(1, class_stats->post_gc.new_count);
-  EXPECT_EQ(0, class_stats->recent.new_count);
-  // Perform GC. The following is heavily dependent on the behaviour
-  // of the GC: Retained instance of A will be promoted.
-  heap->CollectGarbage(Heap::kNew);
-  // Verify postconditions:
-  EXPECT_EQ(0, class_stats->pre_gc.old_count);
-  EXPECT_EQ(0, class_stats->post_gc.old_count);
-  // One promoted instance.
-  EXPECT_EQ(1, class_stats->promoted_count);
-  // Promotion counted as an allocation from old space.
-  EXPECT_EQ(1, class_stats->recent.old_count);
-  // There was one instance allocated before GC.
-  EXPECT_EQ(1, class_stats->pre_gc.new_count);
-  // There are no instances allocated in new space after GC.
-  EXPECT_EQ(0, class_stats->post_gc.new_count);
-  // No new allocations.
-  EXPECT_EQ(0, class_stats->recent.new_count);
-  // Perform a GC on new space.
-  heap->CollectGarbage(Heap::kNew);
-  // There were no instances allocated before GC.
-  EXPECT_EQ(0, class_stats->pre_gc.new_count);
-  // There are no instances allocated in new space after GC.
-  EXPECT_EQ(0, class_stats->post_gc.new_count);
-  // No new allocations.
-  EXPECT_EQ(0, class_stats->recent.new_count);
-  // Nothing was promoted.
-  EXPECT_EQ(0, class_stats->promoted_count);
-  heap->CollectGarbage(Heap::kOld);
-  // Verify postconditions:
-  EXPECT_EQ(1, class_stats->pre_gc.old_count);
-  EXPECT_EQ(1, class_stats->post_gc.old_count);
-  EXPECT_EQ(0, class_stats->recent.old_count);
+  ClassHeapStats* class_stats;
+  {
+    TransitionNativeToVM transition(thread);
+    Library& lib = Library::Handle();
+    lib ^= Api::UnwrapHandle(h_lib);
+    EXPECT(!lib.IsNull());
+    const Class& cls = Class::Handle(GetClass(lib, "A"));
+    ASSERT(!cls.IsNull());
+    intptr_t cid = cls.id();
+    class_stats =
+        ClassHeapStatsTestHelper::GetHeapStatsForCid(class_table, cid);
+    // Verify preconditions:
+    EXPECT_EQ(0, class_stats->pre_gc.old_count);
+    EXPECT_EQ(0, class_stats->post_gc.old_count);
+    EXPECT_EQ(0, class_stats->recent.old_count);
+    EXPECT_EQ(0, class_stats->pre_gc.new_count);
+    EXPECT_EQ(0, class_stats->post_gc.new_count);
+    // Class allocated twice since GC from new space.
+    EXPECT_EQ(2, class_stats->recent.new_count);
+    // Perform GC.
+    heap->CollectGarbage(Heap::kNew);
+    // Verify postconditions:
+    EXPECT_EQ(0, class_stats->pre_gc.old_count);
+    EXPECT_EQ(0, class_stats->post_gc.old_count);
+    EXPECT_EQ(0, class_stats->recent.old_count);
+    // Total allocations before GC.
+    EXPECT_EQ(2, class_stats->pre_gc.new_count);
+    // Only one survived.
+    EXPECT_EQ(1, class_stats->post_gc.new_count);
+    EXPECT_EQ(0, class_stats->recent.new_count);
+    // Perform GC. The following is heavily dependent on the behaviour
+    // of the GC: Retained instance of A will be promoted.
+    heap->CollectGarbage(Heap::kNew);
+    // Verify postconditions:
+    EXPECT_EQ(0, class_stats->pre_gc.old_count);
+    EXPECT_EQ(0, class_stats->post_gc.old_count);
+    // One promoted instance.
+    EXPECT_EQ(1, class_stats->promoted_count);
+    // Promotion counted as an allocation from old space.
+    EXPECT_EQ(1, class_stats->recent.old_count);
+    // There was one instance allocated before GC.
+    EXPECT_EQ(1, class_stats->pre_gc.new_count);
+    // There are no instances allocated in new space after GC.
+    EXPECT_EQ(0, class_stats->post_gc.new_count);
+    // No new allocations.
+    EXPECT_EQ(0, class_stats->recent.new_count);
+    // Perform a GC on new space.
+    heap->CollectGarbage(Heap::kNew);
+    // There were no instances allocated before GC.
+    EXPECT_EQ(0, class_stats->pre_gc.new_count);
+    // There are no instances allocated in new space after GC.
+    EXPECT_EQ(0, class_stats->post_gc.new_count);
+    // No new allocations.
+    EXPECT_EQ(0, class_stats->recent.new_count);
+    // Nothing was promoted.
+    EXPECT_EQ(0, class_stats->promoted_count);
+    heap->CollectGarbage(Heap::kOld);
+    // Verify postconditions:
+    EXPECT_EQ(1, class_stats->pre_gc.old_count);
+    EXPECT_EQ(1, class_stats->post_gc.old_count);
+    EXPECT_EQ(0, class_stats->recent.old_count);
+  }
   // Exit scope, freeing instance.
   Dart_ExitScope();
-  // Perform GC.
-  heap->CollectGarbage(Heap::kOld);
-  // Verify postconditions:
-  EXPECT_EQ(1, class_stats->pre_gc.old_count);
-  EXPECT_EQ(0, class_stats->post_gc.old_count);
-  EXPECT_EQ(0, class_stats->recent.old_count);
-  // Perform GC.
-  heap->CollectGarbage(Heap::kOld);
-  EXPECT_EQ(0, class_stats->pre_gc.old_count);
-  EXPECT_EQ(0, class_stats->post_gc.old_count);
-  EXPECT_EQ(0, class_stats->recent.old_count);
+  {
+    TransitionNativeToVM transition(thread);
+    // Perform GC.
+    heap->CollectGarbage(Heap::kOld);
+    // Verify postconditions:
+    EXPECT_EQ(1, class_stats->pre_gc.old_count);
+    EXPECT_EQ(0, class_stats->post_gc.old_count);
+    EXPECT_EQ(0, class_stats->recent.old_count);
+    // Perform GC.
+    heap->CollectGarbage(Heap::kOld);
+    EXPECT_EQ(0, class_stats->pre_gc.old_count);
+    EXPECT_EQ(0, class_stats->post_gc.old_count);
+    EXPECT_EQ(0, class_stats->recent.old_count);
+  }
   FLAG_concurrent_sweep = saved_concurrent_sweep_mode;
 }
 
@@ -214,9 +223,6 @@
   Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
   EXPECT_VALID(result);
   EXPECT(!Dart_IsNull(result));
-  Library& lib = Library::Handle();
-  lib ^= Api::UnwrapHandle(h_lib);
-  EXPECT(!lib.IsNull());
   intptr_t before = class_stats->recent.new_size;
   Dart_Handle result2 = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
   EXPECT_VALID(result2);
@@ -689,4 +695,49 @@
   EXPECT_EQ(size_before, size_after);
 }
 
+ISOLATE_UNIT_TEST_CASE(ArrayTruncationRaces) {
+  // Alternate between allocating new lists and truncating.
+  // For each list, the life cycle is
+  // 1) the list is allocated and filled with some elements
+  // 2) kNumLists other lists are allocated
+  // 3) the list's backing store is truncated; the list becomes unreachable
+  // 4) kNumLists other lists are allocated
+  // 5) the backing store becomes unreachable
+  // The goal is to cause truncation *during* concurrent mark or sweep, by
+  // truncating an array that had been alive for a while and will be visited by
+  // a GC triggering by the allocations in step 2.
+
+  intptr_t kMaxListLength = 100;
+  intptr_t kNumLists = 1000;
+  Array& lists = Array::Handle(Array::New(kNumLists));
+  Array& arrays = Array::Handle(Array::New(kNumLists));
+
+  GrowableObjectArray& list = GrowableObjectArray::Handle();
+  Array& array = Array::Handle();
+  Object& element = Object::Handle();
+
+  for (intptr_t i = 0; i < kNumLists; i++) {
+    list = GrowableObjectArray::New(Heap::kNew);
+    intptr_t length = i % kMaxListLength;
+    for (intptr_t j = 0; j < length; j++) {
+      list.Add(element, Heap::kNew);
+    }
+    lists.SetAt(i, list);
+  }
+
+  intptr_t kTruncations = 100000;
+  for (intptr_t i = 0; i < kTruncations; i++) {
+    list ^= lists.At(i % kNumLists);
+    array = Array::MakeFixedLength(list);
+    arrays.SetAt(i % kNumLists, array);
+
+    list = GrowableObjectArray::New(Heap::kOld);
+    intptr_t length = i % kMaxListLength;
+    for (intptr_t j = 0; j < length; j++) {
+      list.Add(element, Heap::kOld);
+    }
+    lists.SetAt(i % kNumLists, list);
+  }
+}
+
 }  // namespace dart
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index fed194b..18b8fc9 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -53,11 +53,19 @@
         // If the code wasn't strongly visited through other references
         // after skipping the function's code pointer, then we disconnect the
         // code from the function.
-        func->StorePointer(&(func->ptr()->code_),
-                           StubCode::LazyCompile_entry()->code());
-        uword entry_point = StubCode::LazyCompile_entry()->EntryPoint();
-        func->ptr()->entry_point_ = entry_point;
-        func->ptr()->unchecked_entry_point_ = entry_point;
+        if (FLAG_enable_interpreter && Function::HasBytecode(func)) {
+          func->StorePointer(&(func->ptr()->code_),
+                             StubCode::InterpretCall_entry()->code());
+          uword entry_point = StubCode::InterpretCall_entry()->EntryPoint();
+          func->ptr()->entry_point_ = entry_point;
+          func->ptr()->unchecked_entry_point_ = entry_point;
+        } else {
+          func->StorePointer(&(func->ptr()->code_),
+                             StubCode::LazyCompile_entry()->code());
+          uword entry_point = StubCode::LazyCompile_entry()->EntryPoint();
+          func->ptr()->entry_point_ = entry_point;
+          func->ptr()->unchecked_entry_point_ = entry_point;
+        }
         if (FLAG_log_code_drop) {
           // NOTE: This code runs while GC is in progress and runs within
           // a NoHandleScope block. Hence it is not okay to use a regular Zone
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index 7c0392a..e30089a 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -72,6 +72,7 @@
   result->next_ = NULL;
   result->used_in_bytes_ = 0;
   result->forwarding_page_ = NULL;
+  result->card_table_ = NULL;
   result->type_ = type;
 
   LSAN_REGISTER_ROOT_REGION(result, sizeof(*result));
@@ -82,6 +83,11 @@
 void HeapPage::Deallocate() {
   ASSERT(forwarding_page_ == NULL);
 
+  if (card_table_ != NULL) {
+    free(card_table_);
+    card_table_ = NULL;
+  }
+
   bool image_page = is_image_page();
 
   if (!image_page) {
@@ -125,6 +131,66 @@
   ASSERT(obj_addr == end_addr);
 }
 
+void HeapPage::VisitRememberedCards(ObjectPointerVisitor* visitor) {
+  ASSERT(Thread::Current()->IsAtSafepoint());
+  NoSafepointScope no_safepoint;
+
+  if (card_table_ == NULL) {
+    return;
+  }
+
+  bool table_is_empty = false;
+
+  RawArray* obj = static_cast<RawArray*>(RawObject::FromAddr(object_start()));
+  ASSERT(obj->IsArray());
+  ASSERT(obj->IsCardRemembered());
+  RawObject** obj_from = obj->from();
+  RawObject** obj_to = obj->to(Smi::Value(obj->ptr()->length_));
+
+  const intptr_t size = card_table_size();
+  for (intptr_t i = 0; i < size; i++) {
+    if (card_table_[i] != 0) {
+      RawObject** card_from =
+          reinterpret_cast<RawObject**>(this) + (i << kSlotsPerCardLog2);
+      RawObject** card_to = reinterpret_cast<RawObject**>(card_from) +
+                            (1 << kSlotsPerCardLog2) - 1;
+      // Minus 1 because to is inclusive.
+
+      if (card_from < obj_from) {
+        // First card overlaps with header.
+        card_from = obj_from;
+      }
+      if (card_to > obj_to) {
+        // Last card(s) may extend past the object. Array truncation can make
+        // this happen for more than one card.
+        card_to = obj_to;
+      }
+
+      visitor->VisitPointers(card_from, card_to);
+
+      bool has_new_target = false;
+      for (RawObject** slot = card_from; slot <= card_to; slot++) {
+        if ((*slot)->IsNewObjectMayBeSmi()) {
+          has_new_target = true;
+          break;
+        }
+      }
+
+      if (has_new_target) {
+        // Card remains remembered.
+        table_is_empty = false;
+      } else {
+        card_table_[i] = 0;
+      }
+    }
+  }
+
+  if (table_is_empty) {
+    free(card_table_);
+    card_table_ = NULL;
+  }
+}
+
 RawObject* HeapPage::FindObject(FindObjectVisitor* visitor) const {
   uword obj_addr = object_start();
   uword end_addr = object_end();
@@ -694,6 +760,12 @@
   }
 }
 
+void PageSpace::VisitRememberedCards(ObjectPointerVisitor* visitor) const {
+  for (HeapPage* page = large_pages_; page != NULL; page = page->next()) {
+    page->VisitRememberedCards(visitor);
+  }
+}
+
 RawObject* PageSpace::FindObject(FindObjectVisitor* visitor,
                                  HeapPage::PageType type) const {
   if (type == HeapPage::kExecutable) {
@@ -929,10 +1001,9 @@
   if (!finalize) {
 #if defined(TARGET_ARCH_IA32)
     return;  // Barrier not implemented.
-#elif !defined(CONCURRENT_MARKING)
-    return;  // Barrier generation disabled.
 #else
-    if (FLAG_marker_tasks == 0) return;   // Concurrent marking disabled.
+    if (!FLAG_concurrent_mark) return;    // Disabled.
+    if (FLAG_marker_tasks == 0) return;   // Disabled.
     if (FLAG_write_protect_code) return;  // Not implemented.
 #endif
   }
@@ -1280,6 +1351,7 @@
   page->object_end_ = memory->end();
   page->used_in_bytes_ = page->object_end_ - page->object_start();
   page->forwarding_page_ = NULL;
+  page->card_table_ = NULL;
   if (is_executable) {
     ASSERT(Utils::IsAligned(pointer, OS::PreferredCodeAlignment()));
     page->type_ = HeapPage::kExecutable;
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index 047a3b7..95d8f19 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -82,6 +82,32 @@
     return reinterpret_cast<HeapPage*>(addr & kPageMask);
   }
 
+  // 1 card = 128 slots.
+  static const intptr_t kSlotsPerCardLog2 = 7;
+  static const intptr_t kBytesPerCardLog2 = kWordSizeLog2 + kSlotsPerCardLog2;
+
+  intptr_t card_table_size() const {
+    return memory_->size() >> kBytesPerCardLog2;
+  }
+
+  static intptr_t card_table_offset() {
+    return OFFSET_OF(HeapPage, card_table_);
+  }
+
+  void RememberCard(RawObject* const* slot) {
+    ASSERT(Contains(reinterpret_cast<uword>(slot)));
+    if (card_table_ == NULL) {
+      card_table_ = reinterpret_cast<uint8_t*>(
+          calloc(card_table_size(), sizeof(uint8_t)));
+    }
+    intptr_t offset =
+        reinterpret_cast<uword>(slot) - reinterpret_cast<uword>(this);
+    intptr_t index = offset >> kBytesPerCardLog2;
+    ASSERT((index >= 0) && (index < card_table_size()));
+    card_table_[index] = 1;
+  }
+  void VisitRememberedCards(ObjectPointerVisitor* visitor);
+
  private:
   void set_object_end(uword value) {
     ASSERT((value & kObjectAlignmentMask) == kOldObjectAlignmentOffset);
@@ -102,6 +128,7 @@
   uword object_end_;
   uword used_in_bytes_;
   ForwardingPage* forwarding_page_;
+  uint8_t* card_table_;  // Remembered set, not marking.
   PageType type_;
 
   friend class PageSpace;
@@ -277,6 +304,8 @@
   void VisitObjectsImagePages(ObjectVisitor* visitor) const;
   void VisitObjectPointers(ObjectPointerVisitor* visitor) const;
 
+  void VisitRememberedCards(ObjectPointerVisitor* visitor) const;
+
   RawObject* FindObject(FindObjectVisitor* visitor,
                         HeapPage::PageType type) const;
 
diff --git a/runtime/vm/heap/safepoint.cc b/runtime/vm/heap/safepoint.cc
index a80b802..bf5def1 100644
--- a/runtime/vm/heap/safepoint.cc
+++ b/runtime/vm/heap/safepoint.cc
@@ -9,6 +9,8 @@
 
 namespace dart {
 
+DEFINE_FLAG(bool, trace_safepoint, false, "Trace Safepoint logic.");
+
 SafepointOperationScope::SafepointOperationScope(Thread* T) : StackResource(T) {
   ASSERT(T != NULL);
   Isolate* I = T->isolate();
@@ -109,7 +111,7 @@
       Monitor::WaitResult retval = sl.Wait(1000);
       if (retval == Monitor::kTimedOut) {
         num_attempts += 1;
-        if (num_attempts > 10) {
+        if (FLAG_trace_safepoint && num_attempts > 10) {
           // We have been waiting too long, start logging this as we might
           // have an issue where a thread is not checking in for a safepoint.
           OS::PrintErr("Attempt:%" Pd " waiting for %d threads to check in\n",
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index 346ea81..9e3a457 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -90,6 +90,10 @@
   void VisitingOldObject(RawObject* obj) {
     ASSERT((obj == NULL) || obj->IsOldObject());
     visiting_old_object_ = obj;
+    if (obj != NULL) {
+      // Card update happens in HeapPage::VisitRememberedCards.
+      ASSERT(!obj->IsCardRemembered());
+    }
   }
 
   intptr_t bytes_promoted() const { return bytes_promoted_; }
@@ -581,6 +585,10 @@
     isolate->store_buffer()->PushBlock(pending, StoreBuffer::kIgnoreThreshold);
     pending = next;
   }
+
+  visitor->VisitingOldObject(NULL);
+  heap_->old_space()->VisitRememberedCards(visitor);
+
   heap_->RecordData(kStoreBufferEntries, total_count);
   heap_->RecordData(kDataUnused1, 0);
   heap_->RecordData(kDataUnused2, 0);
@@ -918,7 +926,7 @@
   // TODO(koda): Make verification more compatible with concurrent sweep.
   if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) {
     OS::PrintErr("Verifying before Scavenge...");
-    heap_->Verify(kForbidMarked);
+    heap_->VerifyGC(kForbidMarked);
     OS::PrintErr(" done.\n");
   }
 
@@ -963,7 +971,7 @@
   // TODO(koda): Make verification more compatible with concurrent sweep.
   if (FLAG_verify_after_gc && !FLAG_concurrent_sweep) {
     OS::PrintErr("Verifying after Scavenge...");
-    heap_->Verify(kForbidMarked);
+    heap_->VerifyGC(kForbidMarked);
     OS::PrintErr(" done.\n");
   }
 
diff --git a/runtime/vm/heap/weak_code.cc b/runtime/vm/heap/weak_code.cc
index c1a3d53..795eda1a 100644
--- a/runtime/vm/heap/weak_code.cc
+++ b/runtime/vm/heap/weak_code.cc
@@ -76,10 +76,12 @@
                                StackFrameIterator::kNoCrossThreadIteration);
     StackFrame* frame = iterator.NextFrame();
     while (frame != NULL) {
-      code = frame->LookupDartCode();
-      if (IsOptimizedCode(code_objects, code)) {
-        ReportDeoptimization(code);
-        DeoptimizeAt(code, frame);
+      if (!frame->is_interpreted()) {
+        code = frame->LookupDartCode();
+        if (IsOptimizedCode(code_objects, code)) {
+          ReportDeoptimization(code);
+          DeoptimizeAt(code, frame);
+        }
       }
       frame = iterator.NextFrame();
     }
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 14e5a58..5a48fb4 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -78,10 +78,15 @@
                      reinterpret_cast<const void*>(body_b), body_size);
 }
 
-ImageWriter::ImageWriter(const void* shared_objects,
+ImageWriter::ImageWriter(Heap* heap,
+                         const void* shared_objects,
                          const void* shared_instructions,
                          const void* reused_instructions)
-    : next_data_offset_(0), next_text_offset_(0), objects_(), instructions_() {
+    : heap_(heap),
+      next_data_offset_(0),
+      next_text_offset_(0),
+      objects_(),
+      instructions_() {
   ResetOffsets();
   SetupShared(&shared_objects_, shared_objects);
   SetupShared(&shared_instructions_, shared_instructions);
@@ -109,6 +114,11 @@
 
 int32_t ImageWriter::GetTextOffsetFor(RawInstructions* instructions,
                                       RawCode* code) {
+  intptr_t offset = heap_->GetObjectId(instructions);
+  if (offset != 0) {
+    return offset;
+  }
+
   if (!reuse_instructions_.IsEmpty()) {
     ObjectOffsetPair* pair = reuse_instructions_.Lookup(instructions);
     if (pair == NULL) {
@@ -127,7 +137,8 @@
   }
 
   intptr_t heap_size = instructions->Size();
-  intptr_t offset = next_text_offset_;
+  offset = next_text_offset_;
+  heap_->SetObjectId(instructions, offset);
   next_text_offset_ += heap_size;
   instructions_.Add(InstructionsData(instructions, code, offset));
   return offset;
@@ -299,11 +310,12 @@
   }
 }
 
-AssemblyImageWriter::AssemblyImageWriter(Dart_StreamingWriteCallback callback,
+AssemblyImageWriter::AssemblyImageWriter(Thread* thread,
+                                         Dart_StreamingWriteCallback callback,
                                          void* callback_data,
                                          const void* shared_objects,
                                          const void* shared_instructions)
-    : ImageWriter(shared_objects, shared_instructions, NULL),
+    : ImageWriter(thread->heap(), shared_objects, shared_instructions, NULL),
       assembly_stream_(512 * KB, callback, callback_data),
       dwarf_(NULL) {
 #if defined(DART_PRECOMPILER)
@@ -556,13 +568,17 @@
   }
 }
 
-BlobImageWriter::BlobImageWriter(uint8_t** instructions_blob_buffer,
+BlobImageWriter::BlobImageWriter(Thread* thread,
+                                 uint8_t** instructions_blob_buffer,
                                  ReAlloc alloc,
                                  intptr_t initial_size,
                                  const void* shared_objects,
                                  const void* shared_instructions,
                                  const void* reused_instructions)
-    : ImageWriter(shared_objects, shared_instructions, reused_instructions),
+    : ImageWriter(thread->heap(),
+                  shared_objects,
+                  shared_instructions,
+                  reused_instructions),
       instructions_blob_stream_(instructions_blob_buffer, alloc, initial_size) {
 }
 
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index b5ba9dc..16f83f7 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -96,7 +96,8 @@
 
 class ImageWriter : public ValueObject {
  public:
-  ImageWriter(const void* shared_objects,
+  ImageWriter(Heap* heap,
+              const void* shared_objects,
               const void* shared_instructions,
               const void* reused_instructions);
   virtual ~ImageWriter() {}
@@ -152,6 +153,7 @@
     };
   };
 
+  Heap* heap_;  // Used for mapping RawInstructiosn to object ids.
   intptr_t next_data_offset_;
   intptr_t next_text_offset_;
   GrowableArray<ObjectData> objects_;
@@ -166,7 +168,8 @@
 
 class AssemblyImageWriter : public ImageWriter {
  public:
-  AssemblyImageWriter(Dart_StreamingWriteCallback callback,
+  AssemblyImageWriter(Thread* thread,
+                      Dart_StreamingWriteCallback callback,
                       void* callback_data,
                       const void* shared_objects,
                       const void* shared_instructions);
@@ -195,12 +198,13 @@
 
 class BlobImageWriter : public ImageWriter {
  public:
-  BlobImageWriter(uint8_t** instructions_blob_buffer,
+  BlobImageWriter(Thread* thread,
+                  uint8_t** instructions_blob_buffer,
                   ReAlloc alloc,
                   intptr_t initial_size,
                   const void* shared_objects,
                   const void* shared_instructions,
-                  const void* reused_instructions = NULL);
+                  const void* reused_instructions);
 
   virtual void WriteText(WriteStream* clustered_stream, bool vm);
 
diff --git a/runtime/vm/instructions_arm.cc b/runtime/vm/instructions_arm.cc
index 38dbee5..d7cc494 100644
--- a/runtime/vm/instructions_arm.cc
+++ b/runtime/vm/instructions_arm.cc
@@ -199,9 +199,11 @@
   if (IsLoadWithOffset(instr, PP, &offset, &dst)) {
     intptr_t index = ObjectPool::IndexFromOffset(offset);
     const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
-    if (pool.TypeAt(index) == ObjectPool::kTaggedObject) {
-      *obj = pool.ObjectAt(index);
-      return true;
+    if (!pool.IsNull()) {
+      if (pool.TypeAt(index) == ObjectPool::kTaggedObject) {
+        *obj = pool.ObjectAt(index);
+        return true;
+      }
     }
   } else if (IsLoadWithOffset(instr, THR, &offset, &dst)) {
     return Thread::ObjectAtOffset(offset, obj);
@@ -285,6 +287,22 @@
   return false;
 }
 
+bool PcRelativeCallPattern::IsValid() const {
+  // bl <offset>
+  const uint32_t word = *reinterpret_cast<uint32_t*>(pc_);
+  const uint32_t cond_all = 0xe0;
+  const uint32_t branch_link = 0x0b;
+  return (word >> 24) == (cond_all | branch_link);
+}
+
+bool PcRelativeJumpPattern::IsValid() const {
+  // b <offset>
+  const uint32_t word = *reinterpret_cast<uint32_t*>(pc_);
+  const uint32_t cond_all = 0xe0;
+  const uint32_t branch_nolink = 0x0a;
+  return (word >> 24) == (cond_all | branch_nolink);
+}
+
 intptr_t TypeTestingStubCallPattern::GetSubtypeTestCachePoolIndex() {
   // Calls to the type testing stubs look like:
   //   ldr R3, [PP+idx]
diff --git a/runtime/vm/instructions_arm.h b/runtime/vm/instructions_arm.h
index e11c947..ceb65e5 100644
--- a/runtime/vm/instructions_arm.h
+++ b/runtime/vm/instructions_arm.h
@@ -129,6 +129,66 @@
   const uword pc_;
 };
 
+class PcRelativeCallPattern : public ValueObject {
+ public:
+  explicit PcRelativeCallPattern(uword pc) : pc_(pc) {}
+
+  static const int kLengthInBytes = 1 * Instr::kInstrSize;
+
+  int32_t distance() {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    return Assembler::DecodeBranchOffset(*reinterpret_cast<int32_t*>(pc_));
+#else
+    UNREACHABLE();
+    return 0;
+#endif
+  }
+
+  void set_distance(int32_t distance) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    int32_t* word = reinterpret_cast<int32_t*>(pc_);
+    *word = Assembler::EncodeBranchOffset(distance, *word);
+#else
+    UNREACHABLE();
+#endif
+  }
+
+  bool IsValid() const;
+
+ private:
+  uword pc_;
+};
+
+class PcRelativeJumpPattern : public ValueObject {
+ public:
+  explicit PcRelativeJumpPattern(uword pc) : pc_(pc) {}
+
+  static const int kLengthInBytes = 1 * Instr::kInstrSize;
+
+  int32_t distance() {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    return Assembler::DecodeBranchOffset(*reinterpret_cast<int32_t*>(pc_));
+#else
+    UNREACHABLE();
+    return 0;
+#endif
+  }
+
+  void set_distance(int32_t distance) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    int32_t* word = reinterpret_cast<int32_t*>(pc_);
+    *word = Assembler::EncodeBranchOffset(distance, *word);
+#else
+    UNREACHABLE();
+#endif
+  }
+
+  bool IsValid() const;
+
+ private:
+  uword pc_;
+};
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_INSTRUCTIONS_ARM_H_
diff --git a/runtime/vm/instructions_arm64.cc b/runtime/vm/instructions_arm64.cc
index cbb8667..314ee86 100644
--- a/runtime/vm/instructions_arm64.cc
+++ b/runtime/vm/instructions_arm64.cc
@@ -318,9 +318,11 @@
       ASSERT(Utils::IsAligned(offset, 8));
       intptr_t index = ObjectPool::IndexFromOffset(offset - kHeapObjectTag);
       const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
-      if (pool.TypeAt(index) == ObjectPool::kTaggedObject) {
-        *obj = pool.ObjectAt(index);
-        return true;
+      if (!pool.IsNull()) {
+        if (pool.TypeAt(index) == ObjectPool::kTaggedObject) {
+          *obj = pool.ObjectAt(index);
+          return true;
+        }
       }
     } else if (instr->RnField() == THR) {
       return Thread::ObjectAtOffset(offset, obj);
@@ -417,6 +419,20 @@
   return bx_lr->InstructionBits() == instruction;
 }
 
+bool PcRelativeCallPattern::IsValid() const {
+  // bl <offset>
+  const uint32_t word = *reinterpret_cast<uint32_t*>(pc_);
+  const uint32_t branch_link = 0x25;
+  return (word >> 26) == branch_link;
+}
+
+bool PcRelativeJumpPattern::IsValid() const {
+  // b <offset>
+  const uint32_t word = *reinterpret_cast<uint32_t*>(pc_);
+  const uint32_t branch_nolink = 0x5;
+  return (word >> 26) == branch_nolink;
+}
+
 intptr_t TypeTestingStubCallPattern::GetSubtypeTestCachePoolIndex() {
   // Calls to the type testing stubs look like:
   //   ldr R3, [PP+idx]
diff --git a/runtime/vm/instructions_arm64.h b/runtime/vm/instructions_arm64.h
index 5a3936d..3107db6 100644
--- a/runtime/vm/instructions_arm64.h
+++ b/runtime/vm/instructions_arm64.h
@@ -148,6 +148,66 @@
   const uword pc_;
 };
 
+class PcRelativeCallPattern : public ValueObject {
+ public:
+  explicit PcRelativeCallPattern(uword pc) : pc_(pc) {}
+
+  static const int kLengthInBytes = 1 * Instr::kInstrSize;
+
+  int32_t distance() {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    return Assembler::DecodeImm26BranchOffset(*reinterpret_cast<int32_t*>(pc_));
+#else
+    UNREACHABLE();
+    return 0;
+#endif
+  }
+
+  void set_distance(int32_t distance) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    int32_t* word = reinterpret_cast<int32_t*>(pc_);
+    *word = Assembler::EncodeImm26BranchOffset(distance, *word);
+#else
+    UNREACHABLE();
+#endif
+  }
+
+  bool IsValid() const;
+
+ private:
+  uword pc_;
+};
+
+class PcRelativeJumpPattern : public ValueObject {
+ public:
+  explicit PcRelativeJumpPattern(uword pc) : pc_(pc) {}
+
+  static const int kLengthInBytes = 1 * Instr::kInstrSize;
+
+  int32_t distance() {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    return Assembler::DecodeImm26BranchOffset(*reinterpret_cast<int32_t*>(pc_));
+#else
+    UNREACHABLE();
+    return 0;
+#endif
+  }
+
+  void set_distance(int32_t distance) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    int32_t* word = reinterpret_cast<int32_t*>(pc_);
+    *word = Assembler::EncodeImm26BranchOffset(distance, *word);
+#else
+    UNREACHABLE();
+#endif
+  }
+
+  bool IsValid() const;
+
+ private:
+  uword pc_;
+};
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_INSTRUCTIONS_ARM64_H_
diff --git a/runtime/vm/instructions_dbc.cc b/runtime/vm/instructions_dbc.cc
index 697cba5..377343b 100644
--- a/runtime/vm/instructions_dbc.cc
+++ b/runtime/vm/instructions_dbc.cc
@@ -16,21 +16,21 @@
 namespace dart {
 
 static bool HasLoadFromPool(Instr instr) {
-  switch (Bytecode::DecodeOpcode(instr)) {
-    case Bytecode::kLoadConstant:
-    case Bytecode::kPushConstant:
-    case Bytecode::kStaticCall:
-    case Bytecode::kIndirectStaticCall:
-    case Bytecode::kInstanceCall1:
-    case Bytecode::kInstanceCall2:
-    case Bytecode::kInstanceCall1Opt:
-    case Bytecode::kInstanceCall2Opt:
-    case Bytecode::kStoreStaticTOS:
-    case Bytecode::kPushStatic:
-    case Bytecode::kAllocate:
-    case Bytecode::kInstantiateType:
-    case Bytecode::kInstantiateTypeArgumentsTOS:
-    case Bytecode::kAssertAssignable:
+  switch (SimulatorBytecode::DecodeOpcode(instr)) {
+    case SimulatorBytecode::kLoadConstant:
+    case SimulatorBytecode::kPushConstant:
+    case SimulatorBytecode::kStaticCall:
+    case SimulatorBytecode::kIndirectStaticCall:
+    case SimulatorBytecode::kInstanceCall1:
+    case SimulatorBytecode::kInstanceCall2:
+    case SimulatorBytecode::kInstanceCall1Opt:
+    case SimulatorBytecode::kInstanceCall2Opt:
+    case SimulatorBytecode::kStoreStaticTOS:
+    case SimulatorBytecode::kPushStatic:
+    case SimulatorBytecode::kAllocate:
+    case SimulatorBytecode::kInstantiateType:
+    case SimulatorBytecode::kInstantiateTypeArgumentsTOS:
+    case SimulatorBytecode::kAssertAssignable:
       return true;
     default:
       return false;
@@ -40,9 +40,9 @@
 static bool GetLoadedObjectAt(uword pc,
                               const ObjectPool& object_pool,
                               Object* obj) {
-  Instr instr = Bytecode::At(pc);
+  Instr instr = SimulatorBytecode::At(pc);
   if (HasLoadFromPool(instr)) {
-    uint16_t index = Bytecode::DecodeD(instr);
+    uint16_t index = SimulatorBytecode::DecodeD(instr);
     if (object_pool.TypeAt(index) == ObjectPool::kTaggedObject) {
       *obj = object_pool.ObjectAt(index);
       return true;
@@ -59,10 +59,10 @@
       ic_data_(ICData::Handle()) {
   ASSERT(code.ContainsInstructionAt(end_));
   const uword call_pc = end_ - sizeof(Instr);
-  Instr call_instr = Bytecode::At(call_pc);
-  ASSERT(Bytecode::IsCallOpcode(call_instr));
+  Instr call_instr = SimulatorBytecode::At(call_pc);
+  ASSERT(SimulatorBytecode::IsCallOpcode(call_instr));
   ic_data_load_end_ = call_pc;
-  target_code_pool_index_ = Bytecode::DecodeD(call_instr);
+  target_code_pool_index_ = SimulatorBytecode::DecodeD(call_instr);
 }
 
 NativeCallPattern::NativeCallPattern(uword pc, const Code& code)
@@ -72,10 +72,11 @@
       trampoline_pool_index_(-1) {
   ASSERT(code.ContainsInstructionAt(end_));
   const uword call_pc = end_ - sizeof(Instr);
-  Instr call_instr = Bytecode::At(call_pc);
-  ASSERT(Bytecode::DecodeOpcode(call_instr) == Bytecode::kNativeCall);
-  native_function_pool_index_ = Bytecode::DecodeB(call_instr);
-  trampoline_pool_index_ = Bytecode::DecodeA(call_instr);
+  Instr call_instr = SimulatorBytecode::At(call_pc);
+  ASSERT(SimulatorBytecode::DecodeOpcode(call_instr) ==
+         SimulatorBytecode::kNativeCall);
+  native_function_pool_index_ = SimulatorBytecode::DecodeB(call_instr);
+  trampoline_pool_index_ = SimulatorBytecode::DecodeA(call_instr);
 }
 
 NativeFunctionWrapper NativeCallPattern::target() const {
@@ -160,10 +161,12 @@
 }
 
 void CallPattern::InsertDeoptCallAt(uword pc) {
-  const uint8_t argc = Bytecode::IsCallOpcode(Bytecode::At(pc))
-                           ? Bytecode::DecodeArgc(Bytecode::At(pc))
-                           : 0;
-  *reinterpret_cast<Instr*>(pc) = Bytecode::Encode(Bytecode::kDeopt, argc, 0);
+  const uint8_t argc =
+      SimulatorBytecode::IsCallOpcode(SimulatorBytecode::At(pc))
+          ? SimulatorBytecode::DecodeArgc(SimulatorBytecode::At(pc))
+          : 0;
+  *reinterpret_cast<Instr*>(pc) =
+      SimulatorBytecode::Encode(SimulatorBytecode::kDeopt, argc, 0);
 }
 
 SwitchableCallPattern::SwitchableCallPattern(uword pc, const Code& code)
diff --git a/runtime/vm/instructions_kbc.cc b/runtime/vm/instructions_kbc.cc
index e33ff4d..f6d9f61 100644
--- a/runtime/vm/instructions_kbc.cc
+++ b/runtime/vm/instructions_kbc.cc
@@ -13,17 +13,18 @@
 
 namespace dart {
 
-RawTypedData* KBCNativeCallPattern::GetNativeEntryDataAt(uword pc,
-                                                         const Code& bytecode) {
+RawTypedData* KBCNativeCallPattern::GetNativeEntryDataAt(
+    uword pc,
+    const Bytecode& bytecode) {
   ASSERT(bytecode.ContainsInstructionAt(pc));
   const uword call_pc = pc - sizeof(KBCInstr);
   KBCInstr call_instr = KernelBytecode::At(call_pc);
   ASSERT(KernelBytecode::DecodeOpcode(call_instr) ==
          KernelBytecode::kNativeCall);
   intptr_t native_entry_data_pool_index = KernelBytecode::DecodeD(call_instr);
-  const ObjectPool& object_pool = ObjectPool::Handle(bytecode.GetObjectPool());
+  const ObjectPool& obj_pool = ObjectPool::Handle(bytecode.object_pool());
   TypedData& native_entry_data = TypedData::Handle();
-  native_entry_data ^= object_pool.ObjectAt(native_entry_data_pool_index);
+  native_entry_data ^= obj_pool.ObjectAt(native_entry_data_pool_index);
   // Native calls to recognized functions should never be patched.
   ASSERT(NativeEntryData(native_entry_data).kind() ==
          MethodRecognizer::kUnknown);
diff --git a/runtime/vm/instructions_kbc.h b/runtime/vm/instructions_kbc.h
index 11f56fb..d210a28 100644
--- a/runtime/vm/instructions_kbc.h
+++ b/runtime/vm/instructions_kbc.h
@@ -15,7 +15,7 @@
 
 class KBCNativeCallPattern : public AllStatic {
  public:
-  static RawTypedData* GetNativeEntryDataAt(uword pc, const Code& bytecode);
+  static RawTypedData* GetNativeEntryDataAt(uword pc, const Bytecode& bytecode);
 };
 
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/instructions_x64.cc b/runtime/vm/instructions_x64.cc
index 5efb324..d95e027 100644
--- a/runtime/vm/instructions_x64.cc
+++ b/runtime/vm/instructions_x64.cc
@@ -37,17 +37,21 @@
       if ((bytes[2] & 0xc7) == (0x80 | (PP & 7))) {  // [r15+disp32]
         intptr_t index = IndexFromPPLoadDisp32(pc + 3);
         const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
-        if (pool.TypeAt(index) == ObjectPool::kTaggedObject) {
-          *obj = pool.ObjectAt(index);
-          return true;
+        if (!pool.IsNull()) {
+          if (pool.TypeAt(index) == ObjectPool::kTaggedObject) {
+            *obj = pool.ObjectAt(index);
+            return true;
+          }
         }
       }
       if ((bytes[2] & 0xc7) == (0x40 | (PP & 7))) {  // [r15+disp8]
         intptr_t index = IndexFromPPLoadDisp8(pc + 3);
         const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
-        if (pool.TypeAt(index) == ObjectPool::kTaggedObject) {
-          *obj = pool.ObjectAt(index);
-          return true;
+        if (!pool.IsNull()) {
+          if (pool.TypeAt(index) == ObjectPool::kTaggedObject) {
+            *obj = pool.ObjectAt(index);
+            return true;
+          }
         }
       }
     }
diff --git a/runtime/vm/instructions_x64.h b/runtime/vm/instructions_x64.h
index 1df85ab..8258214 100644
--- a/runtime/vm/instructions_x64.h
+++ b/runtime/vm/instructions_x64.h
@@ -112,6 +112,56 @@
   static const int kLengthInBytes = 3;
 };
 
+// callq *[rip+offset]
+class PcRelativeCallPattern : public InstructionPattern<PcRelativeCallPattern> {
+ public:
+  explicit PcRelativeCallPattern(uword pc) : InstructionPattern(pc) {}
+
+  int32_t distance() {
+    return *reinterpret_cast<int32_t*>(start() + 1) + kLengthInBytes;
+  }
+
+  void set_distance(int32_t distance) {
+    // [distance] is relative to the start of the instruction, x64 considers the
+    // offset relative to next PC.
+    *reinterpret_cast<int32_t*>(start() + 1) = distance - kLengthInBytes;
+  }
+
+  static const int* pattern() {
+    static const int kPattern[kLengthInBytes] = {0xe8, -1, -1, -1, -1};
+    return kPattern;
+  }
+
+  static int pattern_length_in_bytes() { return kLengthInBytes; }
+
+  static const int kLengthInBytes = 5;
+};
+
+// jmpq *[rip+offset]
+class PcRelativeJumpPattern : public InstructionPattern<PcRelativeJumpPattern> {
+ public:
+  explicit PcRelativeJumpPattern(uword pc) : InstructionPattern(pc) {}
+
+  int32_t distance() {
+    return *reinterpret_cast<int32_t*>(start() + 2) + kLengthInBytes;
+  }
+
+  void set_distance(int32_t distance) {
+    // [distance] is relative to the start of the instruction, x64 considers the
+    // offset relative to next PC.
+    *reinterpret_cast<int32_t*>(start() + 2) = distance - kLengthInBytes;
+  }
+
+  static const int* pattern() {
+    static const int kPattern[kLengthInBytes] = {0xff, 0x25, -1, -1, -1, -1};
+    return kPattern;
+  }
+
+  static int pattern_length_in_bytes() { return kLengthInBytes; }
+
+  static const int kLengthInBytes = 6;
+};
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_INSTRUCTIONS_X64_H_
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index 3185b93..8455c42 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -32,6 +32,15 @@
             ULLONG_MAX,
             "Trace interpreter execution after instruction count reached.");
 
+DEFINE_FLAG(charp,
+            interpreter_trace_file,
+            NULL,
+            "File to write a dynamic instruction trace to.");
+DEFINE_FLAG(uint64_t,
+            interpreter_trace_file_max_bytes,
+            100 * MB,
+            "Maximum size in bytes of the interpreter trace file");
+
 #define LIKELY(cond) __builtin_expect((cond), 1)
 #define UNLIKELY(cond) __builtin_expect((cond), 0)
 
@@ -467,14 +476,9 @@
     return true;
   }
 
-  DART_FORCE_INLINE static RawCode* FrameCode(RawObject** FP) {
-    ASSERT(GetClassId(FP[kKBCPcMarkerSlotFromFp]) == kCodeCid);
-    return static_cast<RawCode*>(FP[kKBCPcMarkerSlotFromFp]);
-  }
-
-  DART_FORCE_INLINE static void SetFrameCode(RawObject** FP, RawCode* code) {
-    ASSERT(GetClassId(code) == kCodeCid);
-    FP[kKBCPcMarkerSlotFromFp] = code;
+  DART_FORCE_INLINE static RawBytecode* FrameBytecode(RawObject** FP) {
+    ASSERT(GetClassId(FP[kKBCPcMarkerSlotFromFp]) == kBytecodeCid);
+    return static_cast<RawBytecode*>(FP[kKBCPcMarkerSlotFromFp]);
   }
 
   DART_FORCE_INLINE static uint8_t* GetTypedData(RawObject* obj,
@@ -564,10 +568,36 @@
   last_setjmp_buffer_ = NULL;
 
   DEBUG_ONLY(icount_ = 1);  // So that tracing after 0 traces first bytecode.
+
+#if defined(DEBUG)
+  trace_file_bytes_written_ = 0;
+  trace_file_ = NULL;
+  if (FLAG_interpreter_trace_file != NULL) {
+    Dart_FileOpenCallback file_open = Dart::file_open_callback();
+    if (file_open != NULL) {
+      trace_file_ = file_open(FLAG_interpreter_trace_file, /* write */ true);
+      trace_buffer_ = new KBCInstr[kTraceBufferInstrs];
+      trace_buffer_idx_ = 0;
+    }
+  }
+#endif
 }
 
 Interpreter::~Interpreter() {
   delete[] stack_;
+#if defined(DEBUG)
+  if (trace_file_ != NULL) {
+    FlushTraceBuffer();
+    // Close the file.
+    Dart_FileCloseCallback file_close = Dart::file_close_callback();
+    if (file_close != NULL) {
+      file_close(trace_file_);
+      trace_file_ = NULL;
+      delete[] trace_buffer_;
+      trace_buffer_ = NULL;
+    }
+  }
+#endif
 }
 
 // Get the active Interpreter for the current isolate.
@@ -597,6 +627,44 @@
     THR_Print("Disassembler not supported in this mode.\n");
   }
 }
+
+DART_FORCE_INLINE bool Interpreter::IsWritingTraceFile() const {
+  return (trace_file_ != NULL) &&
+         (trace_file_bytes_written_ < FLAG_interpreter_trace_file_max_bytes);
+}
+
+void Interpreter::FlushTraceBuffer() {
+  Dart_FileWriteCallback file_write = Dart::file_write_callback();
+  if (file_write == NULL) {
+    return;
+  }
+  if (trace_file_bytes_written_ >= FLAG_interpreter_trace_file_max_bytes) {
+    return;
+  }
+  const intptr_t bytes_to_write = Utils::Minimum(
+      static_cast<uint64_t>(trace_buffer_idx_ * sizeof(KBCInstr)),
+      FLAG_interpreter_trace_file_max_bytes - trace_file_bytes_written_);
+  if (bytes_to_write == 0) {
+    return;
+  }
+  file_write(trace_buffer_, bytes_to_write, trace_file_);
+  trace_file_bytes_written_ += bytes_to_write;
+  trace_buffer_idx_ = 0;
+}
+
+DART_NOINLINE void Interpreter::WriteInstructionToTrace(uint32_t* pc) {
+  Dart_FileWriteCallback file_write = Dart::file_write_callback();
+  if (file_write == NULL) {
+    return;
+  }
+  if (trace_buffer_idx_ < kTraceBufferInstrs) {
+    trace_buffer_[trace_buffer_idx_++] = static_cast<KBCInstr>(*pc);
+  }
+  if (trace_buffer_idx_ == kTraceBufferInstrs) {
+    FlushTraceBuffer();
+  }
+}
+
 #endif  // defined(DEBUG)
 
 // Calls into the Dart runtime are based on this interface.
@@ -616,7 +684,7 @@
                        RawObject** frame,
                        uint32_t* pc) {
   frame[0] = Function::null();
-  frame[1] = Code::null();
+  frame[1] = Bytecode::null();
   frame[2] = reinterpret_cast<RawObject*>(pc);
   frame[3] = reinterpret_cast<RawObject*>(base);
   fp_ = frame + kKBCDartFrameFixedSize;
@@ -643,24 +711,6 @@
   reinterpret_cast<RuntimeFunction>(target)(native_args);
 }
 
-DART_FORCE_INLINE static void EnterSyntheticFrame(RawObject*** FP,
-                                                  RawObject*** SP,
-                                                  uint32_t* pc) {
-  RawObject** fp = *SP + kKBCDartFrameFixedSize;
-  fp[kKBCPcMarkerSlotFromFp] = 0;
-  fp[kKBCSavedCallerPcSlotFromFp] = reinterpret_cast<RawObject*>(pc);
-  fp[kKBCSavedCallerFpSlotFromFp] = reinterpret_cast<RawObject*>(*FP);
-  *FP = fp;
-  *SP = fp - 1;
-}
-
-DART_FORCE_INLINE static void LeaveSyntheticFrame(RawObject*** FP,
-                                                  RawObject*** SP) {
-  RawObject** fp = *FP;
-  *FP = reinterpret_cast<RawObject**>(fp[kKBCSavedCallerFpSlotFromFp]);
-  *SP = fp - kKBCDartFrameFixedSize;
-}
-
 // Calling into runtime may trigger garbage collection and relocate objects,
 // so all RawObject* pointers become outdated and should not be used across
 // runtime calls.
@@ -675,7 +725,7 @@
   if (!setjmp(buffer.buffer_)) {
     thread->set_vm_tag(reinterpret_cast<uword>(drt));
     drt(args);
-    thread->set_vm_tag(VMTag::kDartTagId);
+    thread->set_vm_tag(VMTag::kDartInterpretedTagId);
     thread->set_top_exit_frame_info(0);
     return true;
   } else {
@@ -692,7 +742,7 @@
   if (!setjmp(buffer.buffer_)) {
     thread->set_vm_tag(reinterpret_cast<uword>(function));
     wrapper(args, function);
-    thread->set_vm_tag(VMTag::kDartTagId);
+    thread->set_vm_tag(VMTag::kDartInterpretedTagId);
     thread->set_top_exit_frame_info(0);
     return true;
   } else {
@@ -731,10 +781,9 @@
   {
     InterpreterSetjmpBuffer buffer(this);
     if (!setjmp(buffer.buffer_)) {
-      thread->set_vm_tag(reinterpret_cast<uword>(entrypoint));
       result = entrypoint(code, argdesc_, call_base, thread);
-      thread->set_vm_tag(VMTag::kDartTagId);
       thread->set_top_exit_frame_info(0);
+      ASSERT(thread->vm_tag() == VMTag::kDartInterpretedTagId);
       ASSERT(thread->execution_state() == Thread::kThreadInGenerated);
     } else {
       return false;
@@ -743,7 +792,7 @@
   // Pop args and push result.
   *SP = call_base;
   **SP = result;
-  pp_ = InterpreterHelpers::FrameCode(*FP)->ptr()->object_pool_;
+  pp_ = InterpreterHelpers::FrameBytecode(*FP)->ptr()->object_pool_;
 
   // If the result is an error (not a Dart instance), it must either be rethrown
   // (in the case of an unhandled exception) or it must be returned to the
@@ -922,7 +971,7 @@
         // Reload objects after the call which may trigger GC.
         function = reinterpret_cast<RawFunction*>(call_top[0]);
         field = reinterpret_cast<RawField*>(function->ptr()->data_);
-        pp_ = InterpreterHelpers::FrameCode(*FP)->ptr()->object_pool_;
+        pp_ = InterpreterHelpers::FrameBytecode(*FP)->ptr()->object_pool_;
         // The field is initialized by the runtime call, but not returned.
         value = field->ptr()->value_.static_value_;
       }
@@ -1034,6 +1083,8 @@
   if (!InvokeRuntime(thread, this, DRT_CompileFunction, native_args)) {
     return false;
   }
+  // Reload objects after the call which may trigger GC.
+  function = Function::RawCast(call_top[2]);
   if (Function::HasCode(function)) {
     *invoked = true;
     return InvokeCompiled(thread, function, call_base, call_top, pc, FP, SP);
@@ -1042,7 +1093,7 @@
   // Bytecode was loaded in the above compilation step.
   // The caller will dispatch to the function's bytecode.
   *invoked = false;
-  ASSERT(thread->vm_tag() == VMTag::kDartTagId);
+  ASSERT(thread->vm_tag() == VMTag::kDartInterpretedTagId);
   ASSERT(thread->top_exit_frame_info() == 0);
   return true;
 }
@@ -1076,14 +1127,16 @@
               Function::Handle(function).ToFullyQualifiedCString());
   }
 #endif
-  RawCode* bytecode = function->ptr()->bytecode_;
+  RawBytecode* bytecode = function->ptr()->bytecode_;
   callee_fp[kKBCPcMarkerSlotFromFp] = bytecode;
   callee_fp[kKBCSavedCallerPcSlotFromFp] = reinterpret_cast<RawObject*>(*pc);
   callee_fp[kKBCSavedCallerFpSlotFromFp] = reinterpret_cast<RawObject*>(*FP);
   pp_ = bytecode->ptr()->object_pool_;
-  *pc = reinterpret_cast<uint32_t*>(bytecode->ptr()->entry_point_);
+  *pc =
+      reinterpret_cast<uint32_t*>(bytecode->ptr()->instructions_->ptr()->data_);
   pc_ = reinterpret_cast<uword>(*pc);  // For the profiler.
   *FP = callee_fp;
+  fp_ = callee_fp;  // For the profiler.
   *SP = *FP - 1;
   return true;
 }
@@ -1216,24 +1269,6 @@
   return Invoke(thread, call_base, top, pc, FP, SP);
 }
 
-DART_FORCE_INLINE void Interpreter::PrepareForTailCall(
-    RawCode* code,
-    RawImmutableArray* args_desc,
-    RawObject** FP,
-    RawObject*** SP,
-    uint32_t** pc) {
-  // Drop all stack locals.
-  *SP = FP - 1;
-
-  // Replace the callee with the new [code].
-  FP[kKBCFunctionSlotFromFp] = Object::null();
-  FP[kKBCPcMarkerSlotFromFp] = code;
-  *pc = reinterpret_cast<uint32_t*>(code->ptr()->entry_point_);
-  pc_ = reinterpret_cast<uword>(pc);  // For the profiler.
-  pp_ = code->ptr()->object_pool_;
-  argdesc_ = args_desc;
-}
-
 // Note:
 // All macro helpers are intended to be used only inside Interpreter::Call.
 
@@ -1243,6 +1278,9 @@
   if (IsTracingExecution()) {                                                  \
     TraceInstruction(pc - 1);                                                  \
   }                                                                            \
+  if (IsWritingTraceFile()) {                                                  \
+    WriteInstructionToTrace(pc - 1);                                           \
+  }                                                                            \
   icount_++;
 #else
 #define TRACE_INSTRUCTION
@@ -1368,7 +1406,8 @@
 
 #define HANDLE_RETURN                                                          \
   do {                                                                         \
-    pp_ = InterpreterHelpers::FrameCode(FP)->ptr()->object_pool_;              \
+    pp_ = InterpreterHelpers::FrameBytecode(FP)->ptr()->object_pool_;          \
+    fp_ = FP; /* For the profiler. */                                          \
   } while (0)
 
 // Runtime call helpers: handle invocation and potential exception after return.
@@ -1411,61 +1450,6 @@
   }                                                                            \
   ASSERT(Integer::GetInt64Value(RAW_CAST(Integer, SP[0])) == result);
 
-// Returns true if deoptimization succeeds.
-DART_FORCE_INLINE bool Interpreter::Deoptimize(Thread* thread,
-                                               uint32_t** pc,
-                                               RawObject*** FP,
-                                               RawObject*** SP,
-                                               bool is_lazy) {
-  // Note: frame translation will take care of preserving result at the
-  // top of the stack. See CompilerDeoptInfo::CreateDeoptInfo.
-
-  // Make sure we preserve SP[0] when entering synthetic frame below.
-  (*SP)++;
-
-  // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame.
-  // The code in this frame may not cause GC.
-  // DeoptimizeCopyFrame and DeoptimizeFillFrame are leaf runtime calls.
-  EnterSyntheticFrame(FP, SP, *pc - (is_lazy ? 1 : 0));
-  const intptr_t frame_size_in_bytes =
-      DLRT_DeoptimizeCopyFrame(reinterpret_cast<uword>(*FP), is_lazy ? 1 : 0);
-  LeaveSyntheticFrame(FP, SP);
-
-  *SP = *FP + (frame_size_in_bytes / kWordSize);
-  EnterSyntheticFrame(FP, SP, *pc - (is_lazy ? 1 : 0));
-  DLRT_DeoptimizeFillFrame(reinterpret_cast<uword>(*FP));
-
-  // We are now inside a valid frame.
-  {
-    *++(*SP) = 0;  // Space for the result: number of materialization args.
-    Exit(thread, *FP, *SP + 1, /*pc=*/0);
-    NativeArguments native_args(thread, 0, *SP, *SP);
-    if (!InvokeRuntime(thread, this, DRT_DeoptimizeMaterialize, native_args)) {
-      return false;
-    }
-  }
-  const intptr_t materialization_arg_count =
-      Smi::Value(RAW_CAST(Smi, *(*SP)--)) / kWordSize;
-
-  // Restore caller PC.
-  *pc = SavedCallerPC(*FP);
-  pc_ = reinterpret_cast<uword>(*pc);  // For the profiler.
-
-  // Check if it is a fake PC marking the entry frame.
-  ASSERT(!IsEntryFrameMarker(reinterpret_cast<uword>(*pc)));
-
-  // Restore SP, FP and PP.
-  // Unoptimized frame SP is one below FrameArguments(...) because
-  // FrameArguments(...) returns a pointer to the first argument.
-  *SP = FrameArguments(*FP, materialization_arg_count) - 1;
-  *FP = SavedCallerFP(*FP);
-
-  // Restore pp.
-  pp_ = InterpreterHelpers::FrameCode(*FP)->ptr()->object_pool_;
-
-  return true;
-}
-
 bool Interpreter::AssertAssignable(Thread* thread,
                                    uint32_t* pc,
                                    RawObject** FP,
@@ -1629,14 +1613,6 @@
   }
 #endif
 
-  // Save current VM tag and mark thread as executing Dart code.
-  const uword vm_tag = thread->vm_tag();
-  thread->set_vm_tag(VMTag::kDartTagId);  // TODO(regis): kDartBytecodeTagId?
-
-  // Save current top stack resource and reset the list.
-  StackResource* top_resource = thread->top_resource();
-  thread->set_top_resource(NULL);
-
   // Setup entry frame:
   //
   //                        ^
@@ -1677,7 +1653,7 @@
     fp_[kKBCEntrySavedSlots + i] = argv[argc < 0 ? -i : i];
   }
 
-  RawCode* bytecode = function->ptr()->bytecode_;
+  RawBytecode* bytecode = function->ptr()->bytecode_;
   FP[kKBCFunctionSlotFromFp] = function;
   FP[kKBCPcMarkerSlotFromFp] = bytecode;
   FP[kKBCSavedCallerPcSlotFromFp] =
@@ -1689,10 +1665,22 @@
 
   // Ready to start executing bytecode. Load entry point and corresponding
   // object pool.
-  pc = reinterpret_cast<uint32_t*>(bytecode->ptr()->entry_point_);
+  pc =
+      reinterpret_cast<uint32_t*>(bytecode->ptr()->instructions_->ptr()->data_);
   pc_ = reinterpret_cast<uword>(pc);  // For the profiler.
+  fp_ = FP;                           // For the profiler.
   pp_ = bytecode->ptr()->object_pool_;
 
+  // Save current VM tag and mark thread as executing Dart code. For the
+  // profiler, do this *after* setting up the entry frame (compare the machine
+  // code entry stubs).
+  const uword vm_tag = thread->vm_tag();
+  thread->set_vm_tag(VMTag::kDartInterpretedTagId);
+
+  // Save current top stack resource and reset the list.
+  StackResource* top_resource = thread->top_resource();
+  thread->set_top_resource(NULL);
+
   // Cache some frequently used values in the frame.
   RawBool* true_value = Bool::True().raw();
   RawBool* false_value = Bool::False().raw();
@@ -2061,8 +2049,9 @@
   }
 
   {
-    BYTECODE(MoveSpecial, A_D);
-    FP[rA] = special_[rD];
+    BYTECODE(MoveSpecial, A_X);
+    ASSERT(rA < KernelBytecode::kSpecialIndexCount);
+    FP[rD] = special_[rA];
     DISPATCH();
   }
 
@@ -2362,7 +2351,8 @@
     // Restore SP, FP and PP. Push result and dispatch.
     SP = FrameArguments(FP, argc);
     FP = SavedCallerFP(FP);
-    pp_ = InterpreterHelpers::FrameCode(FP)->ptr()->object_pool_;
+    fp_ = FP;  // For the profiler.
+    pp_ = InterpreterHelpers::FrameBytecode(FP)->ptr()->object_pool_;
     *SP = result;
     DISPATCH();
   }
@@ -2915,8 +2905,9 @@
     SP = FrameArguments(FP, 0);
     RawObject** args = SP - argc;
     FP = SavedCallerFP(FP);
+    fp_ = FP;  // For the profiler.
     if (has_dart_caller) {
-      pp_ = InterpreterHelpers::FrameCode(FP)->ptr()->object_pool_;
+      pp_ = InterpreterHelpers::FrameBytecode(FP)->ptr()->object_pool_;
     }
 
     *++SP = null_value;
@@ -2988,7 +2979,7 @@
   // Single dispatch point used by exception handling macros.
   {
   DispatchAfterException:
-    pp_ = InterpreterHelpers::FrameCode(FP)->ptr()->object_pool_;
+    pp_ = InterpreterHelpers::FrameBytecode(FP)->ptr()->object_pool_;
     DISPATCH();
   }
 
@@ -3012,7 +3003,7 @@
   StackResource::Unwind(thread);
 
   // Set the tag.
-  thread->set_vm_tag(VMTag::kDartTagId);
+  thread->set_vm_tag(VMTag::kDartInterpretedTagId);
   // Clear top exit frame.
   thread->set_top_exit_frame_info(0);
 
diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h
index 24d66a8..6150561 100644
--- a/runtime/vm/interpreter.h
+++ b/runtime/vm/interpreter.h
@@ -152,12 +152,6 @@
                       RawObject*** FP,
                       RawObject*** SP);
 
-  bool Deoptimize(Thread* thread,
-                  uint32_t** pc,
-                  RawObject*** FP,
-                  RawObject*** SP,
-                  bool is_lazy);
-
   void InlineCacheMiss(int checked_args,
                        Thread* thread,
                        RawICData* icdata,
@@ -185,12 +179,6 @@
                      RawObject*** SP,
                      bool optimized);
 
-  void PrepareForTailCall(RawCode* code,
-                          RawImmutableArray* args_desc,
-                          RawObject** FP,
-                          RawObject*** SP,
-                          uint32_t** pc);
-
   bool AssertAssignable(Thread* thread,
                         uint32_t* pc,
                         RawObject** FP,
@@ -210,6 +198,19 @@
 
   // Prints bytecode instruction at given pc for instruction tracing.
   void TraceInstruction(uint32_t* pc) const;
+
+  bool IsWritingTraceFile() const;
+  void FlushTraceBuffer();
+  void WriteInstructionToTrace(uint32_t* pc);
+
+  void* trace_file_;
+  uint64_t trace_file_bytes_written_;
+
+  static const intptr_t kTraceBufferSizeInBytes = 10 * KB;
+  static const intptr_t kTraceBufferInstrs =
+      kTraceBufferSizeInBytes / sizeof(KBCInstr);
+  KBCInstr* trace_buffer_;
+  intptr_t trace_buffer_idx_;
 #endif  // defined(DEBUG)
 
   // Longjmp support for exceptions.
diff --git a/runtime/vm/interpreter_unsupported.cc b/runtime/vm/interpreter_unsupported.cc
index b12ba4e..757e9b4 100644
--- a/runtime/vm/interpreter_unsupported.cc
+++ b/runtime/vm/interpreter_unsupported.cc
@@ -128,23 +128,6 @@
   return false;
 }
 
-void Interpreter::PrepareForTailCall(RawCode* code,
-                                     RawImmutableArray* args_desc,
-                                     RawObject** FP,
-                                     RawObject*** SP,
-                                     uint32_t** pc) {
-  UNIMPLEMENTED();
-}
-
-bool Interpreter::Deoptimize(Thread* thread,
-                             uint32_t** pc,
-                             RawObject*** FP,
-                             RawObject*** SP,
-                             bool is_lazy) {
-  UNIMPLEMENTED();
-  return false;
-}
-
 bool Interpreter::AssertAssignable(Thread* thread,
                                    uint32_t* pc,
                                    RawObject** FP,
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index e3a60be..d170355 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -82,9 +82,9 @@
 
 static void DeterministicModeHandler(bool value) {
   if (value) {
-    FLAG_marker_tasks = 0;                // Timing dependent.
     FLAG_background_compilation = false;  // Timing dependent.
     FLAG_collect_code = false;            // Timing dependent.
+    FLAG_concurrent_mark = false;         // Timing dependent.
     FLAG_concurrent_sweep = false;        // Timing dependent.
     FLAG_random_seed = 0x44617274;  // "Dart"
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
@@ -484,6 +484,10 @@
   }
 }
 
+bool Isolate::HasPendingMessages() {
+  return message_handler_->HasMessages() || message_handler_->HasOOBMessages();
+}
+
 MessageHandler::MessageStatus IsolateMessageHandler::HandleMessage(
     Message* message) {
   ASSERT(IsCurrentIsolate());
@@ -933,7 +937,6 @@
       reloaded_kernel_blobs_(GrowableObjectArray::null()),
       next_(NULL),
       loading_invalidation_gen_(kInvalidGen),
-      top_level_parsing_count_(0),
       field_list_mutex_(
           new Mutex(NOT_IN_PRODUCT("Isolate::field_list_mutex_"))),
       boxed_field_list_(GrowableObjectArray::null()),
@@ -1166,6 +1169,21 @@
   return thread_registry()->mutator_thread();
 }
 
+RawObject* Isolate::CallTagHandler(Dart_LibraryTag tag,
+                                   const Object& arg1,
+                                   const Object& arg2) {
+  Thread* thread = Thread::Current();
+  Api::Scope api_scope(thread);
+  Dart_Handle api_arg1 = Api::NewHandle(thread, arg1.raw());
+  Dart_Handle api_arg2 = Api::NewHandle(thread, arg2.raw());
+  Dart_Handle api_result;
+  {
+    TransitionVMToNative transition(thread);
+    api_result = library_tag_handler_(tag, api_arg1, api_arg2);
+  }
+  return Api::UnwrapHandle(api_result);
+}
+
 void Isolate::SetupImagePage(const uint8_t* image_buffer, bool is_executable) {
   Image image(image_buffer);
   heap_->SetupImagePage(image.object_start(), image.object_size(),
@@ -1665,7 +1683,6 @@
 #if defined(DEBUG)
     isolate->ValidateConstants();
 #endif  // defined(DEBUG)
-    TransitionVMToNative transition(thread);
     Dart::RunShutdownCallback();
   }
   // Shut the isolate down.
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index dd92e29..e1cf954 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -223,10 +223,13 @@
   Dart_MessageNotifyCallback message_notify_callback() const {
     return message_notify_callback_;
   }
+
   void set_message_notify_callback(Dart_MessageNotifyCallback value) {
     message_notify_callback_ = value;
   }
 
+  bool HasPendingMessages();
+
   Thread* mutator_thread() const;
 
   // Mutator thread is not scheduled if NULL or no heap is attached
@@ -280,9 +283,10 @@
     environment_callback_ = value;
   }
 
-  Dart_LibraryTagHandler library_tag_handler() const {
-    return library_tag_handler_;
-  }
+  bool HasTagHandler() const { return library_tag_handler_ != nullptr; }
+  RawObject* CallTagHandler(Dart_LibraryTag tag,
+                            const Object& arg1,
+                            const Object& arg2);
   void set_library_tag_handler(Dart_LibraryTagHandler value) {
     library_tag_handler_ = value;
   }
@@ -624,20 +628,6 @@
     isolate_flags_ = RemappingCidsBit::update(value, isolate_flags_);
   }
 
-  // True during top level parsing.
-  bool IsTopLevelParsing() {
-    const intptr_t value =
-        AtomicOperations::LoadRelaxed(&top_level_parsing_count_);
-    ASSERT(value >= 0);
-    return value > 0;
-  }
-  void IncrTopLevelParsingCount() {
-    AtomicOperations::IncrementBy(&top_level_parsing_count_, 1);
-  }
-  void DecrTopLevelParsingCount() {
-    AtomicOperations::DecrementBy(&top_level_parsing_count_, 1);
-  }
-
   static const intptr_t kInvalidGen = 0;
 
   void IncrLoadingInvalidationGen() {
@@ -1001,7 +991,6 @@
   // to background compilation. The counters may overflow, which is OK
   // since we check for equality to detect if an event occured.
   intptr_t loading_invalidation_gen_;
-  intptr_t top_level_parsing_count_;
 
   // Protect access to boxed_field_list_.
   Mutex* field_list_mutex_;
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 892a7ed..1beb60b 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -165,10 +165,8 @@
   TIR_Print("Running new field initializers for class: %s\n", to_.ToCString());
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  String& initializing_expression = String::Handle(zone);
   Function& eval_func = Function::Handle(zone);
   Object& result = Object::Handle(zone);
-  Class& owning_class = Class::Handle(zone);
   // For each new field.
   for (intptr_t i = 0; i < new_fields_->length(); i++) {
     // Create a function that returns the expression.
@@ -176,14 +174,7 @@
     if (field->kernel_offset() > 0) {
       eval_func ^= kernel::CreateFieldInitializerFunction(thread, zone, *field);
     } else {
-      owning_class ^= field->Owner();
-      ASSERT(!owning_class.IsNull());
-      // Extract the initializing expression.
-      initializing_expression = field->InitializingExpression();
-      TIR_Print("New `%s` has initializing expression `%s`\n",
-                field->ToCString(), initializing_expression.ToCString());
-      eval_func ^= Function::EvaluateHelper(
-          owning_class, initializing_expression, Array::empty_array(), true);
+      UNREACHABLE();
     }
 
     for (intptr_t j = 0; j < after_->length(); j++) {
@@ -904,12 +895,10 @@
   Function& func = Function::Handle();
   while (it.HasNextFrame()) {
     StackFrame* frame = it.NextFrame();
-    if (frame->IsDartFrame()) {
+    if (frame->IsDartFrame() && !frame->is_interpreted()) {
       func = frame->LookupDartFunction();
       ASSERT(!func.IsNull());
-      if (!frame->is_interpreted()) {
-        func.EnsureHasCompiledUnoptimizedCode();
-      }
+      func.EnsureHasCompiledUnoptimizedCode();
     }
   }
 }
@@ -1843,22 +1832,28 @@
   Zone* zone = stack_zone.GetZone();
 
   Code& code = Code::Handle(zone);
+  Bytecode& bytecode = Bytecode::Handle(zone);
   Function& function = Function::Handle(zone);
   DartFrameIterator iterator(thread,
                              StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = iterator.NextFrame();
   while (frame != NULL) {
-    code = frame->LookupDartCode();
-    if (code.is_optimized()) {
-      // If this code is optimized, we need to reset the ICs in the
-      // corresponding unoptimized code, which will be executed when the stack
-      // unwinds to the optimized code.
-      function = code.function();
-      code = function.unoptimized_code();
-      ASSERT(!code.IsNull());
-      code.ResetICDatas(zone);
+    if (frame->is_interpreted()) {
+      bytecode = frame->LookupDartBytecode();
+      bytecode.ResetICDatas(zone);
     } else {
-      code.ResetICDatas(zone);
+      code = frame->LookupDartCode();
+      if (code.is_optimized()) {
+        // If this code is optimized, we need to reset the ICs in the
+        // corresponding unoptimized code, which will be executed when the stack
+        // unwinds to the optimized code.
+        function = code.function();
+        code = function.unoptimized_code();
+        ASSERT(!code.IsNull());
+        code.ResetICDatas(zone);
+      } else {
+        code.ResetICDatas(zone);
+      }
     }
     frame = iterator.NextFrame();
   }
@@ -1882,6 +1877,7 @@
         owning_class_(Class::Handle(zone)),
         owning_lib_(Library::Handle(zone)),
         code_(Code::Handle(zone)),
+        bytecode_(Bytecode::Handle(zone)),
         reload_context_(reload_context),
         zone_(zone) {}
 
@@ -1903,19 +1899,25 @@
       // Grab the current code.
       code_ = func.CurrentCode();
       ASSERT(!code_.IsNull());
+      bytecode_ = func.bytecode();
       const bool clear_code = IsFromDirtyLibrary(func);
       const bool stub_code = code_.IsStubCode();
 
       // Zero edge counters.
       func.ZeroEdgeCounters();
 
-      if (!stub_code) {
+      if (!stub_code || !bytecode_.IsNull()) {
         if (clear_code) {
-          VTIR_Print("Marking %s for recompilation, clearning code\n",
+          VTIR_Print("Marking %s for recompilation, clearing code\n",
                      func.ToCString());
           ClearAllCode(func);
         } else {
-          PreserveUnoptimizedCode();
+          if (!stub_code) {
+            PreserveUnoptimizedCode();
+          }
+          if (!bytecode_.IsNull()) {
+            PreserveBytecode();
+          }
         }
       }
 
@@ -1942,6 +1944,13 @@
     code_.ResetICDatas(zone_);
   }
 
+  void PreserveBytecode() {
+    ASSERT(!bytecode_.IsNull());
+    // We are preserving the bytecode, fill all ICData arrays with
+    // the sentinel values so that we have no stale type feedback.
+    bytecode_.ResetICDatas(zone_);
+  }
+
   bool IsFromDirtyLibrary(const Function& func) {
     owning_class_ = func.Owner();
     owning_lib_ = owning_class_.library();
@@ -1952,6 +1961,7 @@
   Class& owning_class_;
   Library& owning_lib_;
   Code& code_;
+  Bytecode& bytecode_;
   IsolateReloadContext* reload_context_;
   Zone* zone_;
 };
diff --git a/runtime/vm/json_test.cc b/runtime/vm/json_test.cc
index b53d5f2..c42d2e6 100644
--- a/runtime/vm/json_test.cc
+++ b/runtime/vm/json_test.cc
@@ -161,7 +161,7 @@
   EXPECT_STREQ("{\"key\":\"2 hello\"}", js.ToCString());
 }
 
-TEST_CASE(JSON_JSONStream_DartObject) {
+ISOLATE_UNIT_TEST_CASE(JSON_JSONStream_DartObject) {
   JSONStream js;
   {
     JSONArray jsarr(&js);
@@ -216,7 +216,9 @@
   EXPECT_VALID(lib);
 
   Dart_Handle result;
+  TransitionNativeToVM transition1(thread);
   String& obj = String::Handle();
+  TransitionVMToNative transition2(thread);
 
   {
     result = Dart_GetField(lib, NewString("ascii"));
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
index da74542..517e02c 100644
--- a/runtime/vm/kernel_binary.cc
+++ b/runtime/vm/kernel_binary.cc
@@ -124,12 +124,14 @@
     return NULL;
   }
   kernel::Program* kernel_program = NULL;
+
+  const String& uri = String::Handle(String::New(script_uri));
+  const Object& ret = Object::Handle(thread->isolate()->CallTagHandler(
+      Dart_kKernelTag, Object::null_object(), uri));
+  Api::Scope api_scope(thread);
+  Dart_Handle retval = Api::NewHandle(thread, ret.raw());
   {
-    const String& uri = String::Handle(String::New(script_uri));
     TransitionVMToNative transition(thread);
-    Api::Scope api_scope(thread);
-    Dart_Handle retval = (thread->isolate()->library_tag_handler())(
-        Dart_kKernelTag, Api::Null(), Api::NewHandle(thread, uri.raw()));
     if (!Dart_IsError(retval)) {
       Dart_TypedData_Type data_type;
       uint8_t* data;
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 2ffb315..3b7d847 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -17,7 +17,7 @@
 // package:kernel/binary.md.
 
 static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
-static const uint32_t kBinaryFormatVersion = 12;
+static const uint32_t kBinaryFormatVersion = 13;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
@@ -238,6 +238,11 @@
     }
   }
 
+  intptr_t ReadSLEB128() {
+    const uint8_t* buffer = this->buffer();
+    return Utils::DecodeSLEB128(buffer, size_, &offset_);
+  }
+
   /**
    * Read and return a TokenPosition from this reader.
    */
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index c56df9b..36eef09 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -160,7 +160,6 @@
         OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Error: %s\n",
                      error.ToErrorCString());
       }
-      TransitionVMToNative transition(T);
       Dart::RunShutdownCallback();
     }
 
@@ -376,6 +375,8 @@
       char const* library_uri,
       char const* klass,
       bool is_static) {
+    Thread* thread = Thread::Current();
+    TransitionNativeToVM transition(thread);
     Dart_CObject tag;
     tag.type = Dart_CObject_kInt32;
     tag.value.as_int32 = KernelIsolate::kCompileExpressionTag;
@@ -399,7 +400,7 @@
       definitions_array[i] = new Dart_CObject;
       definitions_array[i]->type = Dart_CObject_kString;
       definitions_array[i]->value.as_string = const_cast<char*>(
-          String::CheckedHandle(definitions.At(i)).ToCString());
+          String::CheckedHandle(thread->zone(), definitions.At(i)).ToCString());
     }
     definitions_object.value.as_array.values = definitions_array;
 
@@ -414,7 +415,8 @@
       type_definitions_array[i] = new Dart_CObject;
       type_definitions_array[i]->type = Dart_CObject_kString;
       type_definitions_array[i]->value.as_string = const_cast<char*>(
-          String::CheckedHandle(type_definitions.At(i)).ToCString());
+          String::CheckedHandle(thread->zone(), type_definitions.At(i))
+              .ToCString());
     }
     type_definitions_object.value.as_array.values = type_definitions_array;
 
@@ -460,13 +462,18 @@
                                    &suppress_warnings};
     message.value.as_array.values = message_arr;
     message.value.as_array.length = ARRAY_SIZE(message_arr);
-    // Send the message.
-    Dart_PostCObject(kernel_port, &message);
 
-    // Wait for reply to arrive.
-    MonitorLocker ml(monitor_);
-    while (result_.status == Dart_KernelCompilationStatus_Unknown) {
-      ml.Wait();
+    {
+      TransitionVMToNative transition(Thread::Current());
+
+      // Send the message.
+      Dart_PostCObject(kernel_port, &message);
+
+      // Wait for reply to arrive.
+      MonitorLocker ml(monitor_);
+      while (result_.status == Dart_KernelCompilationStatus_Unknown) {
+        ml.Wait();
+      }
     }
 
     for (intptr_t i = 0; i < num_definitions; ++i) {
@@ -819,6 +826,7 @@
     return result;
   }
 
+  TransitionVMToNative transition(Thread::Current());
   KernelCompilationRequest request;
   return request.SendAndWaitForResponse(kernel_port, expression, definitions,
                                         type_definitions, library_url, klass,
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index c1c1adf..6a818a9 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -321,6 +321,7 @@
   const ExternalTypedData& metadata_payloads = ExternalTypedData::Handle(
       Z, reader.ExternalDataFromTo(program_->metadata_payloads_offset(),
                                    program_->metadata_mappings_offset()));
+  ASSERT(Utils::IsAligned(metadata_payloads.DataAddr(0), kWordSize));
 
   // Create view of metadata mappings.
   const ExternalTypedData& metadata_mappings = ExternalTypedData::Handle(
@@ -588,20 +589,12 @@
 
       if (uri_path.IsNull()) continue;
 
-      Dart_LibraryTagHandler handler = I->library_tag_handler();
-      if (handler == NULL) {
+      if (!I->HasTagHandler()) {
         H.ReportError("no library handler registered.");
       }
 
       I->BlockClassFinalization();
-      {
-        TransitionVMToNative transition(thread_);
-        Api::Scope api_scope(thread_);
-        Dart_Handle retval = handler(Dart_kImportExtensionTag,
-                                     Api::NewHandle(thread_, library.raw()),
-                                     Api::NewHandle(thread_, uri_path.raw()));
-        result = Api::UnwrapHandle(retval);
-      }
+      result = I->CallTagHandler(Dart_kImportExtensionTag, library, uri_path);
       I->UnblockClassFinalization();
 
       if (result.IsError()) {
@@ -1235,34 +1228,34 @@
 void KernelLoader::LoadClass(const Library& library,
                              const Class& toplevel_class,
                              intptr_t class_end,
-                             Class* klass) {
+                             Class* out_class) {
   intptr_t class_offset = helper_.ReaderOffset();
   ClassIndex class_index(program_->kernel_data(), program_->kernel_data_size(),
                          class_offset, class_end - class_offset);
 
   ClassHelper class_helper(&helper_);
   class_helper.ReadUntilIncluding(ClassHelper::kCanonicalName);
-  *klass = LookupClass(library, class_helper.canonical_name_);
-  klass->set_kernel_offset(class_offset - correction_offset_);
+  *out_class = LookupClass(library, class_helper.canonical_name_);
+  out_class->set_kernel_offset(class_offset - correction_offset_);
 
   // The class needs to have a script because all the functions in the class
   // will inherit it.  The predicate Function::IsOptimizable uses the absence of
   // a script to detect test functions that should not be optimized.
-  if (klass->script() == Script::null()) {
+  if (out_class->script() == Script::null()) {
     class_helper.ReadUntilIncluding(ClassHelper::kSourceUriIndex);
     const Script& script =
         Script::Handle(Z, ScriptAt(class_helper.source_uri_index_));
-    klass->set_script(script);
+    out_class->set_script(script);
     FixCoreLibraryScriptUri(library, script);
   }
-  if (klass->token_pos() == TokenPosition::kNoSource) {
+  if (out_class->token_pos() == TokenPosition::kNoSource) {
     class_helper.ReadUntilIncluding(ClassHelper::kStartPosition);
-    klass->set_token_pos(class_helper.start_position_);
+    out_class->set_token_pos(class_helper.start_position_);
   }
 
   class_helper.ReadUntilIncluding(ClassHelper::kFlags);
   if (class_helper.is_enum_class()) {
-    klass->set_is_enum_class();
+    out_class->set_is_enum_class();
   }
 
   class_helper.ReadUntilExcluding(ClassHelper::kAnnotations);
@@ -1275,26 +1268,25 @@
                       &is_potential_native_unused, &has_pragma_annotation);
   }
   if (has_pragma_annotation) {
-    klass->set_has_pragma(true);
+    out_class->set_has_pragma(true);
   }
   class_helper.SetJustRead(ClassHelper::kAnnotations);
   class_helper.ReadUntilExcluding(ClassHelper::kTypeParameters);
   intptr_t type_parameter_counts =
       helper_.ReadListLength();  // read type_parameters list length.
 
-  ActiveClassScope active_class_scope(&active_class_, klass);
-  if (!klass->is_cycle_free()) {
+  ActiveClassScope active_class_scope(&active_class_, out_class);
+  if (!out_class->is_cycle_free()) {
     LoadPreliminaryClass(&class_helper, type_parameter_counts);
   } else {
-    for (intptr_t i = 0; i < type_parameter_counts; ++i) {
-      helper_.SkipStringReference();  // read ith name index.
-      helper_.SkipDartType();         // read ith bound.
-    }
+    // do not use type parameters with cycle_free
+    ASSERT(type_parameter_counts == 0);
     class_helper.SetJustRead(ClassHelper::kTypeParameters);
   }
 
   if ((FLAG_enable_mirrors || has_pragma_annotation) && annotation_count > 0) {
-    library.AddClassMetadata(*klass, toplevel_class, TokenPosition::kNoSource,
+    library.AddClassMetadata(*out_class, toplevel_class,
+                             TokenPosition::kNoSource,
                              class_offset - correction_offset_);
   }
 
@@ -1305,7 +1297,7 @@
       library.raw() != expression_evaluation_library_.raw();
 
   if (loading_native_wrappers_library_ || !register_class) {
-    FinishClassLoading(*klass, library, toplevel_class, class_offset,
+    FinishClassLoading(*out_class, library, toplevel_class, class_offset,
                        class_index, &class_helper);
   }
 
diff --git a/runtime/vm/kernel_loader.h b/runtime/vm/kernel_loader.h
index b8a99fd..9ad3b0a 100644
--- a/runtime/vm/kernel_loader.h
+++ b/runtime/vm/kernel_loader.h
@@ -255,7 +255,7 @@
   void LoadClass(const Library& library,
                  const Class& toplevel_class,
                  intptr_t class_end,
-                 Class* klass);
+                 Class* out_class);
 
   void FinishClassLoading(const Class& klass,
                           const Library& library,
diff --git a/runtime/vm/megamorphic_cache_table.cc b/runtime/vm/megamorphic_cache_table.cc
index 7d0c165..75d42a5a 100644
--- a/runtime/vm/megamorphic_cache_table.cc
+++ b/runtime/vm/megamorphic_cache_table.cc
@@ -52,8 +52,15 @@
 void MegamorphicCacheTable::InitMissHandler(Isolate* isolate) {
   // The miss handler for a class ID not found in the table is invoked as a
   // normal Dart function.
-  const Code& code = Code::Handle(StubCode::Generate(
-      "_stub_MegamorphicMiss", StubCode::GenerateMegamorphicMissStub));
+  ObjectPoolWrapper object_pool_wrapper;
+  const Code& code = Code::Handle(
+      StubCode::Generate("_stub_MegamorphicMiss", &object_pool_wrapper,
+                         StubCode::GenerateMegamorphicMissStub));
+
+  const auto& object_pool =
+      ObjectPool::Handle(object_pool_wrapper.MakeObjectPool());
+  code.set_object_pool(object_pool.raw());
+
   // When FLAG_lazy_dispatchers=false, this stub can be on the stack during
   // exceptions, but it has a corresponding function so IsStubCode is false and
   // it is considered in the search for an exception handler.
diff --git a/runtime/vm/message_handler.cc b/runtime/vm/message_handler.cc
index 00a2ff3..c1ae538 100644
--- a/runtime/vm/message_handler.cc
+++ b/runtime/vm/message_handler.cc
@@ -76,7 +76,6 @@
 }
 
 MessageHandler::~MessageHandler() {
-  IdleNotifier::Remove(this);
   delete queue_;
   delete oob_queue_;
   queue_ = NULL;
@@ -171,19 +170,6 @@
   MessageNotify(saved_priority);
 }
 
-void MessageHandler::EnsureTaskForIdleCheck() {
-  MonitorLocker ml(&monitor_);
-  if ((pool_ != NULL) && (task_ == NULL)) {
-    task_ = new MessageHandlerTask(this);
-    bool task_running = pool_->Run(task_);
-    if (!task_running) {
-      OS::PrintErr("Failed to start idle wakeup\n");
-      delete task_;
-      task_ = NULL;
-    }
-  }
-}
-
 Message* MessageHandler::DequeueMessage(Message::Priority min_priority) {
   // TODO(turnidge): Add assert that monitor_ is held here.
   Message* message = oob_queue_->Dequeue();
@@ -361,6 +347,11 @@
   return !oob_queue_->IsEmpty();
 }
 
+bool MessageHandler::HasMessages() {
+  MonitorLocker ml(&monitor_);
+  return !queue_->IsEmpty();
+}
+
 void MessageHandler::TaskCallback() {
   ASSERT(Isolate::Current() == NULL);
   MessageStatus status = kOK;
@@ -426,8 +417,8 @@
           status = HandleMessages(&ml, (status == kOK), true);
         }
 
-        if (status == kOK) {
-          handle_messages = CheckAndRunIdleLocked(&ml);
+        if (status == kOK && HasLivePorts()) {
+          handle_messages = CheckIfIdleLocked(&ml);
         }
       }
     }
@@ -501,22 +492,35 @@
   }
 }
 
-bool MessageHandler::CheckAndRunIdleLocked(MonitorLocker* ml) {
+bool MessageHandler::CheckIfIdleLocked(MonitorLocker* ml) {
   if ((isolate() == NULL) || (idle_start_time_ == 0) ||
       (FLAG_idle_timeout_micros == 0)) {
+    // No idle task to schedule.
     return false;
   }
-
   const int64_t now = OS::GetCurrentMonotonicMicros();
   const int64_t idle_expirary = idle_start_time_ + FLAG_idle_timeout_micros;
   if (idle_expirary > now) {
-    IdleNotifier::Update(this, idle_expirary);
-    // No new messages.
-    return false;
+    // We wait here for the scheduled idle time to expire or
+    // new messages or OOB messages to arrive.
+    paused_for_messages_ = true;
+    ml->WaitMicros(idle_expirary - now);
+    paused_for_messages_ = false;
+    // We want to loop back in order to handle the new messages
+    // or run the idle task.
+    return true;
   }
+  // The idle task can be scheduled immediately.
+  RunIdleTaskLocked(ml);
+  // We may have received new messages while running idle task, so return
+  // true so that the handle messages loop is run again.
+  return true;
+}
 
+void MessageHandler::RunIdleTaskLocked(MonitorLocker* ml) {
   // We've been without a message long enough to hope we can do some
   // cleanup before the next message arrives.
+  const int64_t now = OS::GetCurrentMonotonicMicros();
   const int64_t deadline = now + FLAG_idle_duration_micros;
   // Idle tasks may take a while: don't block other isolates sending
   // us messages.
@@ -524,11 +528,9 @@
   {
     StartIsolateScope start_isolate(isolate());
     isolate()->NotifyIdle(deadline);
-    idle_start_time_ = 0;
   }
   ml->Enter();
-  // We may have received new messages while the monitor was released.
-  return true;
+  idle_start_time_ = 0;
 }
 
 void MessageHandler::ClosePort(Dart_Port port) {
@@ -666,124 +668,4 @@
   handler_->oob_message_handling_allowed_ = true;
 }
 
-Monitor* IdleNotifier::monitor_ = NULL;
-bool IdleNotifier::task_running_ = false;
-IdleNotifier::Timer* IdleNotifier::queue_ = NULL;
-
-void IdleNotifier::Init() {
-  ASSERT(monitor_ == NULL);
-  monitor_ = new Monitor();
-}
-
-void IdleNotifier::Stop() {
-  Timer* timer;
-
-  {
-    MonitorLocker ml(monitor_);
-    timer = queue_;
-    queue_ = NULL;
-    ml.Notify();
-    while (task_running_) {
-      ml.Wait();
-    }
-  }
-
-  while (timer != NULL) {
-    Timer* next = timer->next;
-    delete timer;
-    timer = next;
-  }
-}
-
-void IdleNotifier::Cleanup() {
-  ASSERT(queue_ == NULL);
-  ASSERT(!task_running_);
-  ASSERT(monitor_ != NULL);
-  delete monitor_;
-  monitor_ = NULL;
-}
-
-class IdleNotifier::Task : public ThreadPool::Task {
- private:
-  void Run() {
-    MonitorLocker ml(monitor_);
-    while (queue_ != NULL) {
-      Timer* timer = queue_;
-      const int64_t now = OS::GetCurrentMonotonicMicros();
-      if (now >= timer->expirary) {
-        MessageHandler* handler = timer->handler;
-        queue_ = timer->next;
-        delete timer;
-        // A handler may try to update its expirary while we try to start its
-        // task for idle notification.
-        ml.Exit();
-        handler->EnsureTaskForIdleCheck();
-        ml.Enter();
-      } else {
-        ml.WaitMicros(timer->expirary - now);
-      }
-    }
-    task_running_ = false;
-    ml.Notify();
-  }
-};
-
-void IdleNotifier::Update(MessageHandler* handler, int64_t expirary) {
-  MonitorLocker ml(monitor_);
-
-  Timer* prev = NULL;
-  Timer* timer = queue_;
-  while (timer != NULL) {
-    if (timer->handler == handler) {
-      if (prev == NULL) {
-        queue_ = timer->next;
-      } else {
-        prev->next = timer->next;
-      }
-      if (expirary == 0) {
-        delete timer;
-      } else {
-        timer->expirary = expirary;
-      }
-      break;
-    } else {
-      prev = timer;
-      timer = timer->next;
-    }
-  }
-
-  if (expirary != 0) {
-    Timer* insert_timer = timer;
-    if (insert_timer == NULL) {
-      insert_timer = new Timer;
-      insert_timer->handler = handler;
-      insert_timer->expirary = expirary;
-    }
-
-    prev = NULL;
-    timer = queue_;
-    while ((timer != NULL) && (timer->expirary < insert_timer->expirary)) {
-      prev = timer;
-      timer = timer->next;
-    }
-    if (prev == NULL) {
-      queue_ = insert_timer;
-    } else {
-      prev->next = insert_timer;
-    }
-    insert_timer->next = timer;
-  }
-
-  if (task_running_) {
-    ml.Notify();
-  } else if ((queue_ != NULL) && (expirary != 0)) {
-    Task* task = new Task();
-    task_running_ = Dart::thread_pool()->Run(task);
-    if (!task_running_) {
-      OS::PrintErr("Failed to start idle ticker\n");
-      delete task;
-    }
-  }
-}
-
 }  // namespace dart
diff --git a/runtime/vm/message_handler.h b/runtime/vm/message_handler.h
index 1ce64ad..46dd862 100644
--- a/runtime/vm/message_handler.h
+++ b/runtime/vm/message_handler.h
@@ -50,10 +50,6 @@
            EndCallback end_callback,
            CallbackData data);
 
-  // Starts a task for the message handler if it runs on the thread pool and a
-  // task is not already running.
-  void EnsureTaskForIdleCheck();
-
   // Handles the next message for this message handler.  Should only
   // be used when not running the handler on the thread pool (via Run
   // or RunBlocking).
@@ -75,6 +71,10 @@
   // handler.
   bool HasOOBMessages();
 
+  // Returns true if there are pending normal messages for this message
+  // handler.
+  bool HasMessages();
+
   // A message handler tracks how many live ports it has.
   bool HasLivePorts() const { return live_ports_ > 0; }
 
@@ -211,9 +211,16 @@
   // Called by MessageHandlerTask to process our task queue.
   void TaskCallback();
 
-  // Returns true if the monitor was exited and there may be new OOB messages
-  // to process.
-  bool CheckAndRunIdleLocked(MonitorLocker* ml);
+  // Checks if we have a slot for idle task execution, if we have a slot
+  // for idle task execution it is scheduled immediately or we wait for
+  // idle expiration and then attempt to schedule the idle task.
+  // Returns true if their is scope for idle task execution so that we
+  // can loop back to handle more messages or false if idle tasks are not
+  // scheduled.
+  bool CheckIfIdleLocked(MonitorLocker* ml);
+
+  // Triggers a run of the idle task.
+  void RunIdleTaskLocked(MonitorLocker* ml);
 
   // NOTE: These two functions release and reacquire the monitor, you may
   // need to call HandleMessages to ensure all pending messages are handled.
@@ -258,28 +265,6 @@
   DISALLOW_COPY_AND_ASSIGN(MessageHandler);
 };
 
-class IdleNotifier : public AllStatic {
- public:
-  static void Init();
-  static void Stop();
-  static void Cleanup();
-  static void Update(MessageHandler* handler, int64_t expirary);
-  static void Remove(MessageHandler* handler) { Update(handler, 0); }
-
- private:
-  class Task;
-
-  struct Timer {
-    MessageHandler* handler;
-    int64_t expirary;
-    Timer* next;
-  };
-
-  static Monitor* monitor_;
-  static bool task_running_;
-  static Timer* queue_;
-};
-
 }  // namespace dart
 
 #endif  // RUNTIME_VM_MESSAGE_HANDLER_H_
diff --git a/runtime/vm/metrics_test.cc b/runtime/vm/metrics_test.cc
index 8ca4151..6ca6726 100644
--- a/runtime/vm/metrics_test.cc
+++ b/runtime/vm/metrics_test.cc
@@ -48,6 +48,7 @@
   TestCase::CreateTestIsolate();
   {
     Thread* thread = Thread::Current();
+    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     MyMetric metric;
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index 5b06627..805affb 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -13,8 +13,6 @@
 
 namespace dart {
 
-DECLARE_FLAG(bool, trace_natives);
-
 // Forward declarations.
 class BootstrapNatives;
 class Object;
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc
index ee23b12..f6ac51b 100644
--- a/runtime/vm/native_entry.cc
+++ b/runtime/vm/native_entry.cc
@@ -20,11 +20,6 @@
 
 namespace dart {
 
-DEFINE_FLAG(bool,
-            trace_natives,
-            false,
-            "Trace invocation of natives (debug mode only)");
-
 void DartNativeThrowArgumentException(const Instance& instance) {
   const Array& __args__ = Array::Handle(Array::New(1));
   __args__.SetAt(0, instance);
@@ -44,12 +39,14 @@
   Dart_NativeFunction native_function = NULL;
   {
     Thread* T = Thread::Current();
-    TransitionVMToNative transition(T);
-    Dart_EnterScope();  // Enter a new Dart API scope as we invoke API entries.
-    Dart_NativeEntryResolver resolver = library.native_entry_resolver();
-    native_function = resolver(Api::NewHandle(T, function_name.raw()),
-                               number_of_arguments, auto_setup_scope);
-    Dart_ExitScope();  // Exit the Dart API scope.
+    Api::Scope api_scope(T);
+    Dart_Handle api_function_name = Api::NewHandle(T, function_name.raw());
+    {
+      TransitionVMToNative transition(T);
+      Dart_NativeEntryResolver resolver = library.native_entry_resolver();
+      native_function =
+          resolver(api_function_name, number_of_arguments, auto_setup_scope);
+    }
   }
   return reinterpret_cast<NativeFunction>(native_function);
 }
@@ -180,34 +177,16 @@
     Isolate* isolate = thread->isolate();
     ApiState* state = isolate->api_state();
     ASSERT(state != NULL);
-    ApiLocalScope* current_top_scope = thread->api_top_scope();
-    ApiLocalScope* scope = thread->api_reusable_scope();
     TRACE_NATIVE_CALL("0x%" Px "", reinterpret_cast<uintptr_t>(func));
-    TransitionGeneratedToNative transition(thread);
-    if (scope == NULL) {
-      scope =
-          new ApiLocalScope(current_top_scope, thread->top_exit_frame_info());
-      ASSERT(scope != NULL);
-    } else {
-      scope->Reinit(thread, current_top_scope, thread->top_exit_frame_info());
-      thread->set_api_reusable_scope(NULL);
+    thread->EnterApiScope();
+    {
+      TransitionGeneratedToNative transition(thread);
+      func(args);
+      if (ReturnValueIsError(arguments)) {
+        PropagateErrors(arguments);
+      }
     }
-    thread->set_api_top_scope(scope);  // New scope is now the top scope.
-
-    func(args);
-    if (ReturnValueIsError(arguments)) {
-      PropagateErrors(arguments);
-    }
-
-    ASSERT(current_top_scope == scope->previous());
-    thread->set_api_top_scope(current_top_scope);  // Reset top scope to prev.
-    if (thread->api_reusable_scope() == NULL) {
-      scope->Reset(thread);  // Reset the old scope which we just exited.
-      thread->set_api_reusable_scope(scope);
-    } else {
-      ASSERT(thread->api_reusable_scope() != scope);
-      delete scope;
-    }
+    thread->ExitApiScope();
     DEOPTIMIZE_ALOT;
   }
   ASSERT(thread->execution_state() == Thread::kThreadInGenerated);
@@ -268,8 +247,16 @@
                                StackFrameIterator::kNoCrossThreadIteration);
     StackFrame* caller_frame = iterator.NextFrame();
 
-    const Code& code = Code::Handle(zone, caller_frame->LookupDartCode());
-    const Function& func = Function::Handle(zone, code.function());
+    Code& code = Code::Handle(zone);
+    Bytecode& bytecode = Bytecode::Handle(zone);
+    Function& func = Function::Handle(zone);
+    if (caller_frame->is_interpreted()) {
+      bytecode = caller_frame->LookupDartBytecode();
+      func = bytecode.function();
+    } else {
+      code = caller_frame->LookupDartCode();
+      func = code.function();
+    }
 
     if (FLAG_trace_natives) {
       THR_Print("Resolving native target for %s\n", func.ToCString());
@@ -286,7 +273,7 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
       ASSERT(FLAG_enable_interpreter);
       NativeFunctionWrapper current_trampoline = KBCPatcher::GetNativeCallAt(
-          caller_frame->pc(), code, &current_function);
+          caller_frame->pc(), bytecode, &current_function);
       ASSERT(current_function ==
              reinterpret_cast<NativeFunction>(LinkNativeCall));
       ASSERT(current_trampoline == &BootstrapNativeCallWrapper ||
@@ -338,7 +325,7 @@
       } else {
         trampoline = &NoScopeNativeCallWrapper;
       }
-      KBCPatcher::PatchNativeCallAt(caller_frame->pc(), code,
+      KBCPatcher::PatchNativeCallAt(caller_frame->pc(), bytecode,
                                     patch_target_function, trampoline);
 #else
       UNREACHABLE();
diff --git a/runtime/vm/native_entry.h b/runtime/vm/native_entry.h
index c0abf55..0d7a930 100644
--- a/runtime/vm/native_entry.h
+++ b/runtime/vm/native_entry.h
@@ -39,7 +39,7 @@
 typedef void (*NativeFunctionWrapper)(Dart_NativeArguments args,
                                       Dart_NativeFunction func);
 
-#ifndef PRODUCT
+#ifdef DEBUG
 #define TRACE_NATIVE_CALL(format, name)                                        \
   if (FLAG_trace_natives) {                                                    \
     THR_Print("Calling native: " format "\n", name);                           \
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 2e524cc..091451f 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -13,6 +13,7 @@
 #include "vm/compiler/aot/precompiler.h"
 #include "vm/compiler/assembler/assembler.h"
 #include "vm/compiler/assembler/disassembler.h"
+#include "vm/compiler/assembler/disassembler_kbc.h"
 #include "vm/compiler/frontend/bytecode_reader.h"
 #include "vm/compiler/frontend/kernel_fingerprints.h"
 #include "vm/compiler/frontend/kernel_translation_helper.h"
@@ -111,8 +112,6 @@
 RawClass* Object::class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::dynamic_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::void_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
-RawClass* Object::unresolved_class_class_ =
-    reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::type_arguments_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::patch_class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::function_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -127,6 +126,7 @@
 RawClass* Object::kernel_program_info_class_ =
     reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::code_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
+RawClass* Object::bytecode_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::instructions_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::object_pool_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::pc_descriptors_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -555,9 +555,6 @@
   }
 
   // Allocate the remaining VM internal classes.
-  cls = Class::New<UnresolvedClass>();
-  unresolved_class_class_ = cls.raw();
-
   cls = Class::New<TypeArguments>();
   type_arguments_class_ = cls.raw();
 
@@ -594,6 +591,9 @@
   cls = Class::New<Code>();
   code_class_ = cls.raw();
 
+  cls = Class::New<Bytecode>();
+  bytecode_class_ = cls.raw();
+
   cls = Class::New<Instructions>();
   instructions_class_ = cls.raw();
 
@@ -942,7 +942,6 @@
   class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   dynamic_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   void_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
-  unresolved_class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   type_arguments_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   patch_class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   function_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -955,6 +954,7 @@
   namespace_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   kernel_program_info_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   code_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
+  bytecode_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   instructions_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   object_pool_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   pc_descriptors_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -1041,7 +1041,6 @@
   SET_CLASS_NAME(class, Class);
   SET_CLASS_NAME(dynamic, Dynamic);
   SET_CLASS_NAME(void, Void);
-  SET_CLASS_NAME(unresolved_class, UnresolvedClass);
   SET_CLASS_NAME(type_arguments, TypeArguments);
   SET_CLASS_NAME(patch_class, PatchClass);
   SET_CLASS_NAME(function, Function);
@@ -1054,6 +1053,7 @@
   SET_CLASS_NAME(namespace, Namespace);
   SET_CLASS_NAME(kernel_program_info, KernelProgramInfo);
   SET_CLASS_NAME(code, Code);
+  SET_CLASS_NAME(bytecode, Bytecode);
   SET_CLASS_NAME(instructions, Instructions);
   SET_CLASS_NAME(object_pool, ObjectPool);
   SET_CLASS_NAME(code_source_map, CodeSourceMap);
@@ -1406,7 +1406,7 @@
     // declared number of type parameters is still 0. It will become 1 after
     // patching. The array type allocated below represents the raw type _List
     // and not _List<E> as we could expect. Use with caution.
-    type ^= Type::New(Object::Handle(zone, cls.raw()),
+    type ^= Type::New(Class::Handle(zone, cls.raw()),
                       TypeArguments::Handle(zone), TokenPosition::kNoSource);
     type.SetIsFinalized();
     type ^= type.Canonicalize();
@@ -1739,15 +1739,6 @@
     object_store->set_int_type(type);
 
     cls = Class::New<Instance>(kIllegalCid);
-    RegisterPrivateClass(cls, Symbols::Int64(), core_lib);
-    cls.set_num_type_arguments(0);
-    cls.set_num_own_type_arguments(0);
-    cls.set_is_prefinalized();
-    pending_classes.Add(cls);
-    type = Type::NewNonParameterizedType(cls);
-    object_store->set_int64_type(type);
-
-    cls = Class::New<Instance>(kIllegalCid);
     RegisterClass(cls, Symbols::Double(), core_lib);
     cls.set_num_type_arguments(0);
     cls.set_num_own_type_arguments(0);
@@ -1797,33 +1788,33 @@
     type_args = TypeArguments::New(1);
     type = object_store->int_type();
     type_args.SetTypeAt(0, type);
-    type_args.Canonicalize();
+    type_args = type_args.Canonicalize();
     object_store->set_type_argument_int(type_args);
 
     type_args = TypeArguments::New(1);
     type = object_store->double_type();
     type_args.SetTypeAt(0, type);
-    type_args.Canonicalize();
+    type_args = type_args.Canonicalize();
     object_store->set_type_argument_double(type_args);
 
     type_args = TypeArguments::New(1);
     type = object_store->string_type();
     type_args.SetTypeAt(0, type);
-    type_args.Canonicalize();
+    type_args = type_args.Canonicalize();
     object_store->set_type_argument_string(type_args);
 
     type_args = TypeArguments::New(2);
     type = object_store->string_type();
     type_args.SetTypeAt(0, type);
     type_args.SetTypeAt(1, Object::dynamic_type());
-    type_args.Canonicalize();
+    type_args = type_args.Canonicalize();
     object_store->set_type_argument_string_dynamic(type_args);
 
     type_args = TypeArguments::New(2);
     type = object_store->string_type();
     type_args.SetTypeAt(0, type);
     type_args.SetTypeAt(1, type);
-    type_args.Canonicalize();
+    type_args = type_args.Canonicalize();
     object_store->set_type_argument_string_string(type_args);
 
     // Finish the initialization by compiling the bootstrap scripts containing
@@ -2100,10 +2091,19 @@
   }
 
   void VisitPointers(RawObject** from, RawObject** to) {
-    for (RawObject** slot = from; slot <= to; ++slot) {
-      RawObject* value = *slot;
-      if (value->IsHeapObject()) {
-        old_obj_->CheckHeapPointerStore(value, thread_);
+    if (old_obj_->IsArray()) {
+      for (RawObject** slot = from; slot <= to; ++slot) {
+        RawObject* value = *slot;
+        if (value->IsHeapObject()) {
+          old_obj_->CheckHeapPointerStore(value, thread_);
+        }
+      }
+    } else {
+      for (RawObject** slot = from; slot <= to; ++slot) {
+        RawObject* value = *slot;
+        if (value->IsHeapObject()) {
+          old_obj_->CheckArrayPointerStore(slot, value, thread_);
+        }
       }
     }
   }
@@ -2135,6 +2135,7 @@
   memmove(reinterpret_cast<uint8_t*>(clone_addr + kHeaderSizeInBytes),
           reinterpret_cast<uint8_t*>(orig_addr + kHeaderSizeInBytes),
           size - kHeaderSizeInBytes);
+
   // Add clone to store buffer, if needed.
   if (!raw_clone->IsOldObject()) {
     // No need to remember an object in new space.
@@ -3346,14 +3347,6 @@
   return true;
 }
 
-RawFunction* Function::EvaluateHelper(const Class& cls,
-                                      const String& expr,
-                                      const Array& param_names,
-                                      bool is_static) {
-  UNREACHABLE();
-  return Function::null();
-}
-
 // Conventions:
 // * For throwing a NSM in a class klass we use its runtime type as receiver,
 //   i.e., klass.RareType().
@@ -3385,6 +3378,26 @@
   return DartEntry::InvokeFunction(throwNew, args);
 }
 
+static RawObject* ThrowTypeError(const TokenPosition token_pos,
+                                 const Instance& src_value,
+                                 const AbstractType& dst_type,
+                                 const String& dst_name) {
+  const Array& args = Array::Handle(Array::New(5));
+  const Smi& pos = Smi::Handle(Smi::New(token_pos.value()));
+  args.SetAt(0, pos);
+  args.SetAt(1, src_value);
+  args.SetAt(2, dst_type);
+  args.SetAt(3, dst_name);
+  args.SetAt(4, String::Handle());  // bound error message
+
+  const Library& libcore = Library::Handle(Library::CoreLibrary());
+  const Class& TypeError =
+      Class::Handle(libcore.LookupClassAllowPrivate(Symbols::TypeError()));
+  const Function& throwNew = Function::Handle(
+      TypeError.LookupFunctionAllowPrivate(Symbols::ThrowNew()));
+  return DartEntry::InvokeFunction(throwNew, args);
+}
+
 RawObject* Class::InvokeGetter(const String& getter_name,
                                bool throw_nsm_if_absent,
                                bool respect_reflectable) const {
@@ -3449,21 +3462,31 @@
   const String& internal_setter_name =
       String::Handle(zone, Field::SetterName(setter_name));
 
+  AbstractType& parameter_type = AbstractType::Handle(zone);
+  AbstractType& argument_type =
+      AbstractType::Handle(zone, value.GetType(Heap::kOld));
+
   if (field.IsNull()) {
     const Function& setter =
         Function::Handle(zone, LookupStaticFunction(internal_setter_name));
-
     const int kNumArgs = 1;
     const Array& args = Array::Handle(zone, Array::New(kNumArgs));
     args.SetAt(0, value);
-
     if (setter.IsNull() || (respect_reflectable && !setter.is_reflectable())) {
       return ThrowNoSuchMethod(AbstractType::Handle(zone, RareType()),
                                internal_setter_name, args, Object::null_array(),
                                InvocationMirror::kStatic,
                                InvocationMirror::kSetter);
     }
-
+    parameter_type ^= setter.ParameterTypeAt(0);
+    if (!argument_type.IsNullType() && !parameter_type.IsDynamicType() &&
+        !value.IsInstanceOf(parameter_type, Object::null_type_arguments(),
+                            Object::null_type_arguments(), NULL)) {
+      const String& argument_name =
+          String::Handle(zone, setter.ParameterNameAt(0));
+      return ThrowTypeError(setter.token_pos(), value, parameter_type,
+                            argument_name);
+    }
     // Invoke the setter and return the result.
     return DartEntry::InvokeFunction(setter, args);
   }
@@ -3472,13 +3495,20 @@
     const int kNumArgs = 1;
     const Array& args = Array::Handle(zone, Array::New(kNumArgs));
     args.SetAt(0, value);
-
     return ThrowNoSuchMethod(AbstractType::Handle(zone, RareType()),
                              internal_setter_name, args, Object::null_array(),
                              InvocationMirror::kStatic,
                              InvocationMirror::kSetter);
   }
 
+  parameter_type ^= field.type();
+  if (!argument_type.IsNullType() && !parameter_type.IsDynamicType() &&
+      !value.IsInstanceOf(parameter_type, Object::null_type_arguments(),
+                          Object::null_type_arguments(), NULL)) {
+    const String& argument_name = String::Handle(zone, field.name());
+    return ThrowTypeError(field.token_pos(), value, parameter_type,
+                          argument_name);
+  }
   field.SetStaticValue(value);
   return value.raw();
 }
@@ -3528,48 +3558,22 @@
       return DartEntry::InvokeClosure(call_args, call_args_descriptor_array);
     }
   }
-
   const Array& args_descriptor_array = Array::Handle(
       zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length(), arg_names));
-
   ArgumentsDescriptor args_descriptor(args_descriptor_array);
-
+  const TypeArguments& type_args = Object::null_type_arguments();
   if (function.IsNull() || !function.AreValidArguments(args_descriptor, NULL) ||
       (respect_reflectable && !function.is_reflectable())) {
     return ThrowNoSuchMethod(
         AbstractType::Handle(zone, RareType()), function_name, args, arg_names,
         InvocationMirror::kStatic, InvocationMirror::kMethod);
   }
-
-  return DartEntry::InvokeFunction(function, args, args_descriptor_array);
-}
-
-RawObject* Class::Evaluate(const String& expr,
-                           const Array& param_names,
-                           const Array& param_values) const {
-  return Evaluate(expr, param_names, param_values, Object::empty_array(),
-                  Object::null_type_arguments());
-}
-
-RawObject* Class::Evaluate(const String& expr,
-                           const Array& param_names,
-                           const Array& param_values,
-                           const Array& type_param_names,
-                           const TypeArguments& type_param_values) const {
-  ASSERT(Thread::Current()->IsMutatorThread());
-  if (id() < kInstanceCid || id() == kTypeArgumentsCid) {
-    const Instance& exception = Instance::Handle(String::New(
-        "Expressions can be evaluated only with regular Dart instances"));
-    const Instance& stacktrace = Instance::Handle();
-    return UnhandledException::New(exception, stacktrace);
+  RawObject* type_error =
+      function.DoArgumentTypesMatch(args, args_descriptor, type_args);
+  if (type_error != Error::null()) {
+    return type_error;
   }
-
-  ASSERT(Library::Handle(library()).kernel_data() ==
-             ExternalTypedData::null() ||
-         !FLAG_enable_kernel_expression_compilation);
-  const Function& eval_func = Function::Handle(
-      Function::EvaluateHelper(*this, expr, param_names, true));
-  return DartEntry::InvokeFunction(eval_func, param_values);
+  return DartEntry::InvokeFunction(function, args, args_descriptor_array);
 }
 
 static RawObject* EvaluateCompiledExpressionHelper(
@@ -3900,8 +3904,6 @@
       return Symbols::Void().raw();
     case kClassCid:
       return Symbols::Class().raw();
-    case kUnresolvedClassCid:
-      return Symbols::UnresolvedClass().raw();
     case kTypeArgumentsCid:
       return Symbols::TypeArguments().raw();
     case kPatchClassCid:
@@ -3928,6 +3930,8 @@
       return Symbols::KernelProgramInfo().raw();
     case kCodeCid:
       return Symbols::Code().raw();
+    case kBytecodeCid:
+      return Symbols::Bytecode().raw();
     case kInstructionsCid:
       return Symbols::Instructions().raw();
     case kObjectPoolCid:
@@ -4487,7 +4491,7 @@
         return true;
       }
     }
-    if (other_type_arg.HasResolvedTypeClass() &&
+    if (other_type_arg.HasTypeClass() &&
         TypeTest(Class::kIsSubtypeOf, type_arguments,
                  Class::Handle(zone, other_type_arg.type_class()),
                  TypeArguments::Handle(other_type_arg.arguments()), bound_error,
@@ -5090,64 +5094,6 @@
   set.Release();
 }
 
-RawUnresolvedClass* UnresolvedClass::New(const Object& library_prefix,
-                                         const String& ident,
-                                         TokenPosition token_pos) {
-  const UnresolvedClass& type = UnresolvedClass::Handle(UnresolvedClass::New());
-  type.set_library_or_library_prefix(library_prefix);
-  type.set_ident(ident);
-  type.set_token_pos(token_pos);
-  return type.raw();
-}
-
-RawUnresolvedClass* UnresolvedClass::New() {
-  ASSERT(Object::unresolved_class_class() != Class::null());
-  RawObject* raw = Object::Allocate(
-      UnresolvedClass::kClassId, UnresolvedClass::InstanceSize(), Heap::kOld);
-  return reinterpret_cast<RawUnresolvedClass*>(raw);
-}
-
-void UnresolvedClass::set_token_pos(TokenPosition token_pos) const {
-  ASSERT(!token_pos.IsClassifying());
-  StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
-}
-
-void UnresolvedClass::set_ident(const String& ident) const {
-  StorePointer(&raw_ptr()->ident_, ident.raw());
-}
-
-void UnresolvedClass::set_library_or_library_prefix(
-    const Object& library_prefix) const {
-  StorePointer(&raw_ptr()->library_or_library_prefix_, library_prefix.raw());
-}
-
-RawString* UnresolvedClass::Name() const {
-  if (library_or_library_prefix() != Object::null()) {
-    Thread* thread = Thread::Current();
-    Zone* zone = thread->zone();
-    const Object& lib_prefix =
-        Object::Handle(zone, library_or_library_prefix());
-    String& name = String::Handle(zone);  // Qualifier.
-    if (lib_prefix.IsLibraryPrefix()) {
-      name = LibraryPrefix::Cast(lib_prefix).name();
-    } else {
-      name = Library::Cast(lib_prefix).name();
-    }
-    GrowableHandlePtrArray<const String> strs(zone, 3);
-    strs.Add(name);
-    strs.Add(Symbols::Dot());
-    strs.Add(String::Handle(zone, ident()));
-    return Symbols::FromConcatAll(thread, strs);
-  } else {
-    return ident();
-  }
-}
-
-const char* UnresolvedClass::ToCString() const {
-  const char* cname = String::Handle(Name()).ToCString();
-  return OS::SCreate(Thread::Current()->zone(), "unresolved class '%s'", cname);
-}
-
 intptr_t TypeArguments::ComputeHash() const {
   if (IsNull()) return 0;
   const intptr_t num_types = Length();
@@ -5286,7 +5232,7 @@
     if (type.IsNull()) {
       return false;
     }
-    if (!type.HasResolvedTypeClass()) {
+    if (!type.HasTypeClass()) {
       if (raw_instantiated && type.IsTypeParameter()) {
         // An uninstantiated type parameter is equivalent to dynamic (even in
         // the presence of a malformed bound in checked mode).
@@ -5508,6 +5454,7 @@
   const TypeArguments& super_type_args =
       TypeArguments::Handle(super_type.arguments());
   if (super_type_args.IsNull()) {
+    ASSERT(!IsUninstantiatedIdentity());
     return false;
   }
   AbstractType& super_type_arg = AbstractType::Handle();
@@ -5516,6 +5463,36 @@
     type_arg = TypeAt(i);
     super_type_arg = super_type_args.TypeAt(i);
     if (!type_arg.Equals(super_type_arg)) {
+      ASSERT(!IsUninstantiatedIdentity());
+      return false;
+    }
+  }
+  return true;
+}
+
+// Return true if this uninstantiated type argument vector, once instantiated
+// at runtime, is a prefix of the enclosing function type arguments.
+bool TypeArguments::CanShareFunctionTypeArguments(
+    const Function& function) const {
+  ASSERT(!IsInstantiated());
+  const intptr_t num_type_args = Length();
+  const intptr_t num_parent_type_params = function.NumParentTypeParameters();
+  const intptr_t num_function_type_params = function.NumTypeParameters();
+  const intptr_t num_function_type_args =
+      num_parent_type_params + num_function_type_params;
+  if (num_type_args > num_function_type_args) {
+    // This vector cannot be a prefix of a shorter vector.
+    return false;
+  }
+  AbstractType& type_arg = AbstractType::Handle();
+  for (intptr_t i = 0; i < num_type_args; i++) {
+    type_arg = TypeAt(i);
+    if (!type_arg.IsTypeParameter()) {
+      return false;
+    }
+    const TypeParameter& type_param = TypeParameter::Cast(type_arg);
+    ASSERT(type_param.IsFinalized());
+    if ((type_param.index() != i) || !type_param.IsFunctionTypeParameter()) {
       return false;
     }
   }
@@ -5569,8 +5546,9 @@
     TrailPtr bound_trail,
     Heap::Space space) const {
   ASSERT(!IsInstantiated(kAny, num_free_fun_type_params));
-  if (!instantiator_type_arguments.IsNull() && IsUninstantiatedIdentity() &&
-      (instantiator_type_arguments.Length() == Length())) {
+  if ((instantiator_type_arguments.IsNull() ||
+       instantiator_type_arguments.Length() == Length()) &&
+      IsUninstantiatedIdentity()) {
     return instantiator_type_arguments.raw();
   }
   const intptr_t num_types = Length();
@@ -5969,11 +5947,11 @@
   }
 }
 
-void Function::AttachBytecode(const Code& value) const {
+void Function::AttachBytecode(const Bytecode& value) const {
   DEBUG_ASSERT(IsMutatorOrAtSafepoint());
   ASSERT(FLAG_enable_interpreter || FLAG_use_bytecode_compiler);
   // Finish setting up code before activating it.
-  value.set_owner(*this);
+  value.set_function(*this);
   StorePointer(&raw_ptr()->bytecode_, value.raw());
 
   // We should not have loaded the bytecode if the function had code.
@@ -5986,11 +5964,11 @@
 }
 
 bool Function::HasBytecode() const {
-  return raw_ptr()->bytecode_ != Code::null();
+  return raw_ptr()->bytecode_ != Bytecode::null();
 }
 
 bool Function::HasBytecode(RawFunction* function) {
-  return function->ptr()->bytecode_ != Code::null();
+  return function->ptr()->bytecode_ != Bytecode::null();
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
@@ -6012,7 +5990,7 @@
   ASSERT(Thread::Current()->IsMutatorThread());
 
   StorePointer(&raw_ptr()->unoptimized_code_, Code::null());
-  StorePointer(&raw_ptr()->bytecode_, Code::null());
+  StorePointer(&raw_ptr()->bytecode_, Bytecode::null());
 
   SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code()));
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
@@ -6055,6 +6033,9 @@
 }
 
 void Function::SwitchToLazyCompiledUnoptimizedCode() const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  UNREACHABLE();
+#else
   if (!HasOptimizedCode()) {
     return;
   }
@@ -6069,9 +6050,14 @@
 
   const Code& unopt_code = Code::Handle(zone, unoptimized_code());
   if (unopt_code.IsNull()) {
-    // Set the lazy compile code.
-    TIR_Print("Switched to lazy compile stub for %s\n", ToCString());
-    SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code()));
+    // Set the lazy compile or interpreter call stub code.
+    if (FLAG_enable_interpreter && HasBytecode()) {
+      TIR_Print("Switched to interpreter call stub for %s\n", ToCString());
+      SetInstructions(Code::Handle(StubCode::InterpretCall_entry()->code()));
+    } else {
+      TIR_Print("Switched to lazy compile stub for %s\n", ToCString());
+      SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code()));
+    }
     return;
   }
 
@@ -6079,6 +6065,7 @@
 
   AttachCode(unopt_code);
   unopt_code.Enable();
+#endif
 }
 
 void Function::set_unoptimized_code(const Code& value) const {
@@ -6965,6 +6952,87 @@
   return true;
 }
 
+RawObject* Function::DoArgumentTypesMatch(
+    const Array& args,
+    const ArgumentsDescriptor& args_desc,
+    const TypeArguments& instantiator_type_args) const {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  Function& instantiated_func = Function::Handle(zone, raw());
+
+  if (!HasInstantiatedSignature()) {
+    instantiated_func ^= InstantiateSignatureFrom(instantiator_type_args,
+                                                  Object::null_type_arguments(),
+                                                  kAllFree, Heap::kOld);
+  }
+  AbstractType& argument_type = AbstractType::Handle(zone);
+  AbstractType& parameter_type = AbstractType::Handle(zone);
+  Instance& argument = Instance::Handle(zone);
+
+  // Check types of the provided arguments against the expected parameter types.
+  for (intptr_t i = args_desc.FirstArgIndex(); i < args_desc.PositionalCount();
+       ++i) {
+    argument ^= args.At(i);
+    argument_type ^= argument.GetType(Heap::kOld);
+    parameter_type ^= instantiated_func.ParameterTypeAt(i);
+
+    // If the argument type is dynamic or the parameter is null, move on.
+    if (parameter_type.IsDynamicType() || argument_type.IsNullType()) {
+      continue;
+    }
+    if (!argument.IsInstanceOf(parameter_type, instantiator_type_args,
+                               Object::null_type_arguments(), NULL)) {
+      String& argument_name = String::Handle(zone, ParameterNameAt(i));
+      return ThrowTypeError(token_pos(), argument, parameter_type,
+                            argument_name);
+    }
+  }
+
+  const intptr_t num_arguments = args_desc.Count();
+  const intptr_t num_named_arguments = args_desc.NamedCount();
+  if (num_named_arguments == 0) {
+    return Error::null();
+  }
+
+  String& argument_name = String::Handle(zone);
+  String& parameter_name = String::Handle(zone);
+
+  // Check types of named arguments against expected parameter type.
+  for (intptr_t i = 0; i < num_named_arguments; i++) {
+    argument_name ^= args_desc.NameAt(i);
+    ASSERT(argument_name.IsSymbol());
+    bool found = false;
+    const intptr_t num_positional_args = num_arguments - num_named_arguments;
+    const int num_parameters = NumParameters();
+
+    // Try to find the named parameter that matches the provided argument.
+    for (intptr_t j = num_positional_args; !found && (j < num_parameters);
+         j++) {
+      parameter_name = ParameterNameAt(j);
+      ASSERT(argument_name.IsSymbol());
+      if (argument_name.Equals(parameter_name)) {
+        found = true;
+        argument ^= args.At(args_desc.PositionAt(i));
+        argument_type ^= argument.GetType(Heap::kOld);
+        parameter_type ^= instantiated_func.ParameterTypeAt(j);
+
+        // If the argument type is dynamic or the parameter is null, move on.
+        if (parameter_type.IsDynamicType() || argument_type.IsNullType()) {
+          continue;
+        }
+        if (!argument.IsInstanceOf(parameter_type, instantiator_type_args,
+                                   Object::null_type_arguments(), NULL)) {
+          String& argument_name = String::Handle(zone, ParameterNameAt(i));
+          return ThrowTypeError(token_pos(), argument, parameter_type,
+                                argument_name);
+        }
+      }
+    }
+    ASSERT(found);
+  }
+  return Error::null();
+}
+
 // Helper allocating a C string buffer in the zone, printing the fully qualified
 // name of a function in it, and replacing ':' by '_' to make sure the
 // constructed name is a valid C++ identifier for debugging purpose.
@@ -8814,35 +8882,8 @@
     return closure.raw();
   }
 
-  // This is the first time a closure for this field is requested.
-  // Create the closure and a new static field in which it is stored.
-  const char* field_name = String::Handle(zone, name()).ToCString();
-  String& expr_src = String::Handle(zone);
-  if (make_setter) {
-    expr_src = String::NewFormatted("(%s_) { return %s = %s_; }", field_name,
-                                    field_name, field_name);
-  } else {
-    expr_src = String::NewFormatted("() { return %s; }", field_name);
-  }
-  Object& result =
-      Object::Handle(zone, field_owner.Evaluate(expr_src, Object::empty_array(),
-                                                Object::empty_array()));
-  ASSERT(result.IsInstance());
-  // The caller may expect the closure to be allocated in old space. Copy
-  // the result here, since Object::Clone() is a private method.
-  result = Object::Clone(result, Heap::kOld);
-
-  closure_field = Field::New(closure_name,
-                             true,   // is_static
-                             true,   // is_final
-                             true,   // is_const
-                             false,  // is_reflectable
-                             field_owner, Object::dynamic_type(),
-                             this->token_pos(), this->end_token_pos());
-  closure_field.SetStaticValue(Instance::Cast(result), true);
-  field_owner.AddField(closure_field);
-
-  return Instance::RawCast(result.raw());
+  UNREACHABLE();
+  return Instance::null();
 }
 
 RawInstance* Field::GetterClosure() const {
@@ -9181,6 +9222,8 @@
     const Type& static_type,
     const Instance& value,
     bool print_trace /* = false */) {
+  ASSERT(!value.IsNull());  // Should be handled by the caller.
+
   const TypeArguments& static_type_args =
       TypeArguments::Handle(static_type.arguments());
 
@@ -9634,6 +9677,24 @@
   }
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+static bool IsLetter(int32_t c) {
+  return (('A' <= c) && (c <= 'Z')) || (('a' <= c) && (c <= 'z'));
+}
+
+static bool IsDecimalDigit(int32_t c) {
+  return '0' <= c && c <= '9';
+}
+
+static bool IsIdentStartChar(int32_t c) {
+  return IsLetter(c) || (c == '_') || (c == '$');
+}
+
+static bool IsIdentChar(int32_t c) {
+  return IsLetter(c) || IsDecimalDigit(c) || (c == '_') || (c == '$');
+}
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
 void Script::GetTokenLocation(TokenPosition token_pos,
                               intptr_t* line,
                               intptr_t* column,
@@ -9664,11 +9725,9 @@
       const String& source = String::Handle(zone, Source());
       intptr_t offset = token_pos.value();
       *token_len = 1;
-      if (offset < source.Length() &&
-          Scanner::IsIdentStartChar(source.CharAt(offset))) {
+      if (offset < source.Length() && IsIdentStartChar(source.CharAt(offset))) {
         for (intptr_t i = offset + 1;
-             i < source.Length() && Scanner::IsIdentChar(source.CharAt(i));
-             ++i) {
+             i < source.Length() && IsIdentChar(source.CharAt(i)); ++i) {
           ++*token_len;
         }
       }
@@ -9688,17 +9747,26 @@
 
   if (kind() == RawScript::kKernelTag) {
     const TypedData& line_starts_data = TypedData::Handle(line_starts());
-    const String& source = String::Handle(Source());
-    if (line_starts_data.IsNull() || source.IsNull()) {
+    if (line_starts_data.IsNull()) {
       // Scripts in the AOT snapshot do not have a line starts array.
       *first_token_index = TokenPosition::kNoSource;
       *last_token_index = TokenPosition::kNoSource;
       return;
     }
 #if !defined(DART_PRECOMPILED_RUNTIME)
+    const String& source = String::Handle(Source());
+    intptr_t source_length;
+    if (source.IsNull()) {
+      Smi& value = Smi::Handle();
+      const Array& debug_positions_array = Array::Handle(debug_positions());
+      value ^= debug_positions_array.At(debug_positions_array.Length() - 1);
+      source_length = value.Value();
+    } else {
+      source_length = source.Length();
+    }
     kernel::KernelLineStartsReader line_starts_reader(
         line_starts_data, Thread::Current()->zone());
-    line_starts_reader.TokenRangeAtLine(source.Length(), line_number,
+    line_starts_reader.TokenRangeAtLine(source_length, line_number,
                                         first_token_index, last_token_index);
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
     return;
@@ -11152,12 +11220,14 @@
 }
 
 // Invoke the function, or noSuchMethod if it is null.
-static RawObject* InvokeInstanceFunction(const Instance& receiver,
-                                         const Function& function,
-                                         const String& target_name,
-                                         const Array& args,
-                                         const Array& args_descriptor_array,
-                                         bool respect_reflectable) {
+static RawObject* InvokeInstanceFunction(
+    const Instance& receiver,
+    const Function& function,
+    const String& target_name,
+    const Array& args,
+    const Array& args_descriptor_array,
+    bool respect_reflectable,
+    const TypeArguments& instantiator_type_args) {
   // Note "args" is already the internal arguments with the receiver as the
   // first element.
   ArgumentsDescriptor args_descriptor(args_descriptor_array);
@@ -11166,6 +11236,11 @@
     return DartEntry::InvokeNoSuchMethod(receiver, target_name, args,
                                          args_descriptor_array);
   }
+  RawObject* type_error = function.DoArgumentTypesMatch(args, args_descriptor,
+                                                        instantiator_type_args);
+  if (type_error != Error::null()) {
+    return type_error;
+  }
   return DartEntry::InvokeFunction(function, args, args_descriptor_array);
 }
 
@@ -11227,9 +11302,16 @@
   Object& obj = Object::Handle(LookupLocalOrReExportObject(setter_name));
   const String& internal_setter_name =
       String::Handle(Field::SetterName(setter_name));
-
+  AbstractType& setter_type = AbstractType::Handle();
+  AbstractType& argument_type = AbstractType::Handle(value.GetType(Heap::kOld));
   if (obj.IsField()) {
     const Field& field = Field::Cast(obj);
+    setter_type ^= field.type();
+    if (!argument_type.IsNullType() && !setter_type.IsDynamicType() &&
+        !value.IsInstanceOf(setter_type, Object::null_type_arguments(),
+                            Object::null_type_arguments(), NULL)) {
+      return ThrowTypeError(field.token_pos(), value, setter_type, setter_name);
+    }
     if (field.is_final() || (respect_reflectable && !field.is_reflectable())) {
       const int kNumArgs = 1;
       const Array& args = Array::Handle(Array::New(kNumArgs));
@@ -11260,6 +11342,13 @@
         InvocationMirror::kTopLevel, InvocationMirror::kSetter);
   }
 
+  setter_type ^= setter.ParameterTypeAt(0);
+  if (!argument_type.IsNullType() && !setter_type.IsDynamicType() &&
+      !value.IsInstanceOf(setter_type, Object::null_type_arguments(),
+                          Object::null_type_arguments(), NULL)) {
+    return ThrowTypeError(setter.token_pos(), value, setter_type, setter_name);
+  }
+
   return DartEntry::InvokeFunction(setter, args);
 }
 
@@ -11301,7 +11390,7 @@
   const Array& args_descriptor_array = Array::Handle(
       ArgumentsDescriptor::New(kTypeArgsLen, args.Length(), arg_names));
   ArgumentsDescriptor args_descriptor(args_descriptor_array);
-
+  const TypeArguments& type_args = Object::null_type_arguments();
   if (function.IsNull() || !function.AreValidArguments(args_descriptor, NULL) ||
       (respect_reflectable && !function.is_reflectable())) {
     return ThrowNoSuchMethod(
@@ -11309,30 +11398,14 @@
         function_name, args, arg_names, InvocationMirror::kTopLevel,
         InvocationMirror::kMethod);
   }
-
+  RawObject* type_error =
+      function.DoArgumentTypesMatch(args, args_descriptor, type_args);
+  if (type_error != Error::null()) {
+    return type_error;
+  }
   return DartEntry::InvokeFunction(function, args, args_descriptor_array);
 }
 
-RawObject* Library::Evaluate(const String& expr,
-                             const Array& param_names,
-                             const Array& param_values) const {
-  return Evaluate(expr, param_names, param_values, Array::empty_array(),
-                  TypeArguments::null_type_arguments());
-}
-
-RawObject* Library::Evaluate(const String& expr,
-                             const Array& param_names,
-                             const Array& param_values,
-                             const Array& type_param_names,
-                             const TypeArguments& type_param_values) const {
-  ASSERT(kernel_data() == ExternalTypedData::null() ||
-         !FLAG_enable_kernel_expression_compilation);
-  // Evaluate the expression as a static function of the toplevel class.
-  Class& top_level_class = Class::Handle(toplevel_class());
-  ASSERT(top_level_class.is_finalized());
-  return top_level_class.Evaluate(expr, param_names, param_values);
-}
-
 RawObject* Library::EvaluateCompiledExpression(
     const uint8_t* kernel_bytes,
     intptr_t kernel_length,
@@ -11869,15 +11942,9 @@
             isolate->object_store()->pending_deferred_loads());
     pending_deferred_loads.Add(deferred_lib);
     const String& lib_url = String::Handle(zone, deferred_lib.url());
-    Dart_LibraryTagHandler handler = isolate->library_tag_handler();
-    Object& obj = Object::Handle(zone);
-    {
-      TransitionVMToNative transition(thread);
-      Api::Scope api_scope(thread);
-      obj = Api::UnwrapHandle(handler(Dart_kImportTag,
-                                      Api::NewHandle(thread, importer()),
-                                      Api::NewHandle(thread, lib_url.raw())));
-    }
+    const Object& obj = Object::Handle(
+        zone, isolate->CallTagHandler(
+                  Dart_kImportTag, Library::Handle(zone, importer()), lib_url));
     if (obj.IsError()) {
       Exceptions::PropagateError(Error::Cast(obj));
     }
@@ -12245,6 +12312,8 @@
   Object& key = thread->ObjectHandle();
   Smi& value = thread->SmiHandle();
   {
+    Isolate* isolate = thread->isolate();
+    SafepointMutexLocker ml(isolate->kernel_data_lib_cache_mutex());
     data ^= libraries_cache();
     ASSERT(!data.IsNull());
     IntHashMap table(&key, &value, &data);
@@ -12266,13 +12335,6 @@
   Object& key = thread->ObjectHandle();
   Smi& value = thread->SmiHandle();
   {
-    data ^= libraries_cache();
-    ASSERT(!data.IsNull());
-    IntHashMap table(&key, &value, &data);
-    result ^= table.GetOrNull(name_index);
-    table.Release();
-  }
-  if (result.IsNull()) {
     Isolate* isolate = thread->isolate();
     SafepointMutexLocker ml(isolate->kernel_data_lib_cache_mutex());
     data ^= libraries_cache();
@@ -12299,6 +12361,8 @@
   Object& key = thread->ObjectHandle();
   Smi& value = thread->SmiHandle();
   {
+    Isolate* isolate = thread->isolate();
+    SafepointMutexLocker ml(isolate->kernel_data_class_cache_mutex());
     data ^= classes_cache();
     ASSERT(!data.IsNull());
     IntHashMap table(&key, &value, &data);
@@ -12320,13 +12384,6 @@
   Object& key = thread->ObjectHandle();
   Smi& value = thread->SmiHandle();
   {
-    data ^= classes_cache();
-    ASSERT(!data.IsNull());
-    IntHashMap table(&key, &value, &data);
-    result ^= table.GetOrNull(name_index);
-    table.Release();
-  }
-  if (result.IsNull()) {
     Isolate* isolate = thread->isolate();
     SafepointMutexLocker ml(isolate->kernel_data_class_cache_mutex());
     data ^= classes_cache();
@@ -12598,26 +12655,6 @@
   }
 }
 
-// Decode integer in SLEB128 format from |data| and update |byte_index|.
-static intptr_t DecodeSLEB128(const uint8_t* data,
-                              const intptr_t data_length,
-                              intptr_t* byte_index) {
-  ASSERT(*byte_index < data_length);
-  uword shift = 0;
-  intptr_t value = 0;
-  uint8_t part = 0;
-  do {
-    part = data[(*byte_index)++];
-    value |= static_cast<intptr_t>(part & 0x7f) << shift;
-    shift += 7;
-  } while ((part & 0x80) != 0);
-
-  if ((shift < (sizeof(value) * 8)) && ((part & 0x40) != 0)) {
-    value |= static_cast<intptr_t>(kUwordMax << shift);
-  }
-  return value;
-}
-
 // Encode integer in SLEB128 format.
 void PcDescriptors::EncodeInteger(GrowableArray<uint8_t>* data,
                                   intptr_t value) {
@@ -12628,7 +12665,7 @@
 intptr_t PcDescriptors::DecodeInteger(intptr_t* byte_index) const {
   NoSafepointScope no_safepoint;
   const uint8_t* data = raw_ptr()->data();
-  return DecodeSLEB128(data, Length(), byte_index);
+  return Utils::DecodeSLEB128(data, Length(), byte_index);
 }
 
 RawObjectPool* ObjectPool::New(intptr_t len) {
@@ -13404,7 +13441,8 @@
 
 void ICData::set_ic_data_array(const Array& value) const {
   ASSERT(!value.IsNull());
-  StorePointer(&raw_ptr()->ic_data_, value.raw());
+  StorePointer<RawArray*, MemoryOrder::kRelease>(&raw_ptr()->ic_data_,
+                                                 value.raw());
 }
 
 #if defined(TAG_IC_DATA)
@@ -14523,9 +14561,12 @@
   // FlowGraphCompiler::AddStaticCallTarget adds pc-offsets to the table while
   // emitting assembly. This guarantees that every succeeding pc-offset is
   // larger than the previously added one.
-  for (intptr_t i = kSCallTableEntryLength; i < value.Length();
-       i += kSCallTableEntryLength) {
-    ASSERT(value.At(i - kSCallTableEntryLength) < value.At(i));
+  StaticCallsTable entries(value);
+  const intptr_t count = entries.Length();
+  for (intptr_t i = 0; i < count - 1; ++i) {
+    auto left = Smi::Value(entries[i].Get<kSCallTableKindAndOffset>());
+    auto right = Smi::Value(entries[i + 1].Get<kSCallTableKindAndOffset>());
+    ASSERT(OffsetField::decode(left) < OffsetField::decode(right));
   }
 #endif  // DEBUG
 }
@@ -14578,19 +14619,20 @@
 #else
   NoSafepointScope no_safepoint;
   const Array& table = Array::Handle(raw_ptr()->static_calls_target_table_);
-  RawObject* key = reinterpret_cast<RawObject*>(Smi::New(pc - PayloadStart()));
+  StaticCallsTable entries(table);
+  const intptr_t pc_offset = pc - PayloadStart();
   intptr_t imin = 0;
-  intptr_t imax = table.Length() / kSCallTableEntryLength;
+  intptr_t imax = (table.Length() / kSCallTableEntryLength) - 1;
   while (imax >= imin) {
-    const intptr_t imid = ((imax - imin) / 2) + imin;
-    const intptr_t real_index = imid * kSCallTableEntryLength;
-    RawObject* key_in_table = table.At(real_index);
-    if (key_in_table < key) {
+    const intptr_t imid = imin + (imax - imin) / 2;
+    const auto offset = OffsetField::decode(
+        Smi::Value(entries[imid].Get<kSCallTableKindAndOffset>()));
+    if (offset < pc_offset) {
       imin = imid + 1;
-    } else if (key_in_table > key) {
+    } else if (offset > pc_offset) {
       imax = imid - 1;
     } else {
-      return real_index;
+      return imid;
     }
   }
 #endif
@@ -14607,9 +14649,8 @@
     return Function::null();
   }
   const Array& array = Array::Handle(raw_ptr()->static_calls_target_table_);
-  Function& function = Function::Handle();
-  function ^= array.At(i + kSCallTableFunctionEntry);
-  return function.raw();
+  StaticCallsTable entries(array);
+  return entries[i].Get<kSCallTableFunctionTarget>();
 #endif
 }
 
@@ -14623,9 +14664,8 @@
     return Code::null();
   }
   const Array& array = Array::Handle(raw_ptr()->static_calls_target_table_);
-  Code& code = Code::Handle();
-  code ^= array.At(i + kSCallTableCodeEntry);
-  return code.raw();
+  StaticCallsTable entries(array);
+  return entries[i].Get<kSCallTableCodeTarget>();
 #endif
 }
 
@@ -14636,9 +14676,10 @@
   const intptr_t i = BinarySearchInSCallTable(pc);
   ASSERT(i >= 0);
   const Array& array = Array::Handle(raw_ptr()->static_calls_target_table_);
+  StaticCallsTable entries(array);
   ASSERT(code.IsNull() ||
-         (code.function() == array.At(i + kSCallTableFunctionEntry)));
-  array.SetAt(i + kSCallTableCodeEntry, code);
+         (code.function() == entries[i].Get<kSCallTableFunctionTarget>()));
+  return entries[i].Set<kSCallTableCodeTarget>(code);
 #endif
 }
 
@@ -14649,20 +14690,21 @@
   const intptr_t i = BinarySearchInSCallTable(pc);
   ASSERT(i >= 0);
   const Array& array = Array::Handle(raw_ptr()->static_calls_target_table_);
+  StaticCallsTable entries(array);
 #if defined(DEBUG)
-  if (array.At(i + kSCallTableFunctionEntry) == Function::null()) {
+  if (entries[i].Get<kSCallTableFunctionTarget>() == Function::null()) {
     ASSERT(!code.IsNull() && Object::Handle(code.owner()).IsClass());
   } else {
     ASSERT(code.IsNull() ||
-           (code.function() == array.At(i + kSCallTableFunctionEntry)));
+           (code.function() == entries[i].Get<kSCallTableFunctionTarget>()));
   }
 #endif
-  array.SetAt(i + kSCallTableCodeEntry, code);
+  return entries[i].Set<kSCallTableCodeTarget>(code);
 #endif
 }
 
 void Code::Disassemble(DisassemblyFormatter* formatter) const {
-#if !defined(PRODUCT)
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
   if (!FLAG_support_disassembler) {
     return;
   }
@@ -14673,7 +14715,7 @@
   } else {
     Disassembler::Disassemble(start, start + instr.Size(), formatter, *this);
   }
-#endif
+#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 }
 
 const Code::Comments& Code::comments() const {
@@ -14779,6 +14821,7 @@
 RawCode* Code::FinalizeCode(const char* name,
                             FlowGraphCompiler* compiler,
                             Assembler* assembler,
+                            PoolAttachment pool_attachment,
                             bool optimized,
                             CodeStatistics* stats /* = nullptr */) {
   Isolate* isolate = Isolate::Current();
@@ -14787,8 +14830,10 @@
   }
 
   ASSERT(assembler != NULL);
-  const ObjectPool& object_pool =
-      ObjectPool::Handle(assembler->object_pool_wrapper().MakeObjectPool());
+  const auto object_pool =
+      pool_attachment == PoolAttachment::kAttachPool
+          ? &ObjectPool::Handle(assembler->MakeObjectPool())
+          : nullptr;
 
   // Allocate the Code and Instructions objects.  Code is allocated first
   // because a GC during allocation of the code will leave the instruction
@@ -14839,7 +14884,9 @@
     code.set_is_alive(true);
 
     // Set object pool in Instructions object.
-    code.set_object_pool(object_pool.raw());
+    if (pool_attachment == PoolAttachment::kAttachPool) {
+      code.set_object_pool(object_pool->raw());
+    }
 
     if (FLAG_write_protect_code) {
       uword address = RawObject::ToAddr(instrs.raw());
@@ -14879,6 +14926,7 @@
 RawCode* Code::FinalizeCode(const Function& function,
                             FlowGraphCompiler* compiler,
                             Assembler* assembler,
+                            PoolAttachment pool_attachment,
                             bool optimized /* = false */,
                             CodeStatistics* stats /* = nullptr */) {
 // Calling ToLibNamePrefixedQualifiedCString is very expensive,
@@ -14886,64 +14934,11 @@
 #ifndef PRODUCT
   if (CodeObservers::AreActive()) {
     return FinalizeCode(function.ToLibNamePrefixedQualifiedCString(), compiler,
-                        assembler, optimized, stats);
+                        assembler, pool_attachment, optimized, stats);
   }
 #endif  // !PRODUCT
-  return FinalizeCode("", compiler, assembler, optimized, stats);
-}
-
-RawCode* Code::FinalizeBytecode(const void* bytecode_data,
-                                intptr_t bytecode_size,
-                                const ObjectPool& object_pool,
-                                CodeStatistics* stats /* = nullptr */) {
-  // Allocate the Code and Instructions objects.  Code is allocated first
-  // because a GC during allocation of the code will leave the instruction
-  // pages read-only.
-  const intptr_t pointer_offset_count = 0;  // No fixups in bytecode.
-  Code& code = Code::ZoneHandle(Code::New(pointer_offset_count));
-  Instructions& instrs = Instructions::ZoneHandle(
-      Instructions::New(bytecode_size, true /* has_single_entry_point */, 0));
-
-  // Copy the bytecode data into the instruction area. No fixups to apply.
-  MemoryRegion instrs_region(reinterpret_cast<void*>(instrs.PayloadStart()),
-                             instrs.Size());
-  MemoryRegion bytecode_region(const_cast<void*>(bytecode_data), bytecode_size);
-  // TODO(regis): Avoid copying bytecode.
-  instrs_region.CopyFrom(0, bytecode_region);
-
-  // TODO(regis): Keep following lines or not?
-  // TODO(regis): Do we need to notify CodeObservers for bytecode too?
-  // If so, provide a better name using ToLibNamePrefixedQualifiedCString().
-#ifndef PRODUCT
-  code.set_compile_timestamp(OS::GetCurrentMonotonicMicros());
-  CodeObservers::NotifyAll("bytecode", instrs.PayloadStart(),
-                           0 /* prologue_offset */, instrs.Size(),
-                           false /* optimized */, nullptr);
-#endif
-  {
-    NoSafepointScope no_safepoint;
-
-    // Hook up Code and Instructions objects.
-    code.SetActiveInstructions(instrs);
-    code.set_instructions(instrs);
-    code.set_is_alive(true);
-
-    // Set object pool in Instructions object.
-    code.set_object_pool(object_pool.raw());
-
-    if (FLAG_write_protect_code) {
-      uword address = RawObject::ToAddr(instrs.raw());
-      VirtualMemory::Protect(reinterpret_cast<void*>(address),
-                             instrs.raw()->Size(), VirtualMemory::kReadExecute);
-    }
-  }
-#ifndef PRODUCT
-  // No Code::Comments to set. Default is 0 length Comments.
-  // No prologue was ever entered, optimistically assume nothing was ever
-  // pushed onto the stack.
-  code.SetPrologueOffset(bytecode_size);  // TODO(regis): Correct?
-#endif
-  return code.raw();
+  return FinalizeCode("", compiler, assembler, pool_attachment, optimized,
+                      stats);
 }
 
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
@@ -15041,7 +15036,7 @@
     // Regular stub.
     const char* name = StubCode::NameOfStub(EntryPoint());
     if (name == NULL) {
-      return zone->PrintToString("[this stub]");  // Not yet recorded.
+      return zone->PrintToString("[unknown stub]");  // Not yet recorded.
     }
     return zone->PrintToString("[Stub] %s", name);
   } else if (obj.IsClass()) {
@@ -15052,10 +15047,10 @@
   } else {
     ASSERT(obj.IsFunction());
     // Dart function.
-    const char* opt = is_optimized() ? "*" : "";
+    const char* opt = is_optimized() ? "[Optimized]" : "[Unoptimized]";
     const char* function_name =
         String::Handle(zone, Function::Cast(obj).UserVisibleName()).ToCString();
-    return zone->PrintToString("%s%s", opt, function_name);
+    return zone->PrintToString("%s %s", opt, function_name);
   }
 }
 
@@ -15063,11 +15058,11 @@
   Zone* zone = Thread::Current()->zone();
   const Object& obj = Object::Handle(zone, owner());
   if (obj.IsFunction()) {
-    const char* opt = is_optimized() ? "*" : "";
+    const char* opt = is_optimized() ? "[Optimized]" : "[Unoptimized]";
     const char* function_name =
         String::Handle(zone, Function::Cast(obj).QualifiedScrubbedName())
             .ToCString();
-    return zone->PrintToString("%s%s", opt, function_name);
+    return zone->PrintToString("%s %s", opt, function_name);
   }
   return Name();
 }
@@ -15221,6 +15216,134 @@
 #endif
 }
 
+void Bytecode::set_instructions(const ExternalTypedData& instructions) const {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  ASSERT(Thread::Current()->IsMutatorThread());
+  // The interpreter requires the instructions to be aligned.
+  ASSERT(Utils::IsAligned(instructions.DataAddr(0), sizeof(KBCInstr)));
+  StorePointer(&raw_ptr()->instructions_, instructions.raw());
+#else
+  UNREACHABLE();
+#endif
+}
+
+uword Bytecode::PayloadStart() const {
+  const ExternalTypedData& instr = ExternalTypedData::Handle(instructions());
+  return reinterpret_cast<uword>(instr.DataAddr(0));
+}
+
+intptr_t Bytecode::Size() const {
+  const ExternalTypedData& instr = ExternalTypedData::Handle(instructions());
+  return instr.LengthInBytes();
+}
+
+void Bytecode::Disassemble(DisassemblyFormatter* formatter) const {
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  if (!FLAG_support_disassembler) {
+    return;
+  }
+  uword start = PayloadStart();
+  intptr_t size = Size();
+  if (formatter == NULL) {
+    KernelBytecodeDisassembler::Disassemble(start, start + size, *this);
+  } else {
+    KernelBytecodeDisassembler::Disassemble(start, start + size, formatter,
+                                            *this);
+  }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+}
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+RawBytecode* Bytecode::New(const ExternalTypedData& instructions,
+                           const ObjectPool& object_pool) {
+  ASSERT(Object::bytecode_class() != Class::null());
+  Bytecode& result = Bytecode::Handle();
+  {
+    uword size = Bytecode::InstanceSize();
+    RawObject* raw = Object::Allocate(Bytecode::kClassId, size, Heap::kOld);
+    NoSafepointScope no_safepoint;
+    result ^= raw;
+    result.set_pc_descriptors(Object::empty_descriptors());
+    result.set_instructions(instructions);
+    result.set_object_pool(object_pool);
+    result.set_source_positions_binary_offset(0);
+  }
+  return result.raw();
+}
+#endif
+
+RawExternalTypedData* Bytecode::GetBinary(Zone* zone) const {
+  const Function& func = Function::Handle(zone, function());
+  const Script& script = Script::Handle(zone, func.script());
+  const KernelProgramInfo& info =
+      KernelProgramInfo::Handle(zone, script.kernel_program_info());
+  return info.metadata_payloads();
+}
+
+TokenPosition Bytecode::GetTokenIndexOfPC(uword pc) const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  UNREACHABLE();
+#else
+  if (!HasSourcePositions()) {
+    return TokenPosition::kNoSource;
+  }
+  uword pc_offset = pc - PayloadStart();
+  // PC could equal to bytecode size if the last instruction is Throw.
+  ASSERT(pc_offset <= static_cast<uword>(Size()));
+  kernel::BytecodeSourcePositionsIterator iter(Thread::Current()->zone(),
+                                               *this);
+  TokenPosition token_pos = TokenPosition::kNoSource;
+  while (iter.MoveNext()) {
+    if (pc_offset < iter.PcOffset()) {
+      break;
+    }
+    token_pos = iter.TokenPos();
+  }
+  return token_pos;
+#endif
+}
+
+const char* Bytecode::ToCString() const {
+  return Thread::Current()->zone()->PrintToString("Bytecode(%s)",
+                                                  QualifiedName());
+}
+
+const char* Bytecode::Name() const {
+  Zone* zone = Thread::Current()->zone();
+  const Function& fun = Function::Handle(zone, function());
+  ASSERT(!fun.IsNull());
+  const char* function_name =
+      String::Handle(zone, fun.UserVisibleName()).ToCString();
+  return zone->PrintToString("[Bytecode] %s", function_name);
+}
+
+const char* Bytecode::QualifiedName() const {
+  Zone* zone = Thread::Current()->zone();
+  const Function& fun = Function::Handle(zone, function());
+  ASSERT(!fun.IsNull());
+  const char* function_name =
+      String::Handle(zone, fun.QualifiedScrubbedName()).ToCString();
+  return zone->PrintToString("[Bytecode] %s", function_name);
+}
+
+bool Bytecode::SlowFindRawBytecodeVisitor::FindObject(
+    RawObject* raw_obj) const {
+  return RawBytecode::ContainsPC(raw_obj, pc_);
+}
+
+RawBytecode* Bytecode::FindCode(uword pc) {
+  Thread* thread = Thread::Current();
+  HeapIterationScope heap_iteration_scope(thread);
+  SlowFindRawBytecodeVisitor visitor(pc);
+  RawObject* needle = thread->heap()->FindOldObject(&visitor);
+  if (needle != Bytecode::null()) {
+    return static_cast<RawBytecode*>(needle);
+  }
+  return Bytecode::null();
+}
+
 RawContext* Context::New(intptr_t num_variables, Heap::Space space) {
   ASSERT(num_variables >= 0);
   ASSERT(Object::context_class() != Class::null());
@@ -15588,18 +15711,18 @@
   intptr_t new_len = data.Length() + kTestEntryLength;
   data = Array::Grow(data, new_len);
   set_cache(data);
-  intptr_t data_pos = old_num * kTestEntryLength;
-  data.SetAt(data_pos + kInstanceClassIdOrFunction,
-             instance_class_id_or_function);
-  data.SetAt(data_pos + kInstanceTypeArguments, instance_type_arguments);
-  data.SetAt(data_pos + kInstantiatorTypeArguments,
-             instantiator_type_arguments);
-  data.SetAt(data_pos + kFunctionTypeArguments, function_type_arguments);
-  data.SetAt(data_pos + kInstanceParentFunctionTypeArguments,
-             instance_parent_function_type_arguments);
-  data.SetAt(data_pos + kInstanceDelayedFunctionTypeArguments,
-             instance_delayed_type_arguments);
-  data.SetAt(data_pos + kTestResult, test_result);
+
+  SubtypeTestCacheTable entries(data);
+  auto entry = entries[old_num];
+  entry.Set<kInstanceClassIdOrFunction>(instance_class_id_or_function);
+  entry.Set<kInstanceTypeArguments>(instance_type_arguments);
+  entry.Set<kInstantiatorTypeArguments>(instantiator_type_arguments);
+  entry.Set<kFunctionTypeArguments>(function_type_arguments);
+  entry.Set<kInstanceParentFunctionTypeArguments>(
+      instance_parent_function_type_arguments);
+  entry.Set<kInstanceDelayedFunctionTypeArguments>(
+      instance_delayed_type_arguments);
+  entry.Set<kTestResult>(test_result);
 }
 
 void SubtypeTestCache::GetCheck(
@@ -15612,18 +15735,17 @@
     TypeArguments* instance_delayed_type_arguments,
     Bool* test_result) const {
   Array& data = Array::Handle(cache());
-  intptr_t data_pos = ix * kTestEntryLength;
-  *instance_class_id_or_function =
-      data.At(data_pos + kInstanceClassIdOrFunction);
-  *instance_type_arguments ^= data.At(data_pos + kInstanceTypeArguments);
-  *instantiator_type_arguments ^=
-      data.At(data_pos + kInstantiatorTypeArguments);
-  *function_type_arguments ^= data.At(data_pos + kFunctionTypeArguments);
+  SubtypeTestCacheTable entries(data);
+  auto entry = entries[ix];
+  *instance_class_id_or_function = entry.Get<kInstanceClassIdOrFunction>();
+  *instance_type_arguments ^= entry.Get<kInstanceTypeArguments>();
+  *instantiator_type_arguments ^= entry.Get<kInstantiatorTypeArguments>();
+  *function_type_arguments ^= entry.Get<kFunctionTypeArguments>();
   *instance_parent_function_type_arguments ^=
-      data.At(data_pos + kInstanceParentFunctionTypeArguments);
+      entry.Get<kInstanceParentFunctionTypeArguments>();
   *instance_delayed_type_arguments ^=
-      data.At(data_pos + kInstanceDelayedFunctionTypeArguments);
-  *test_result ^= data.At(data_pos + kTestResult);
+      entry.Get<kInstanceDelayedFunctionTypeArguments>();
+  *test_result ^= entry.Get<kTestResult>();
 }
 
 const char* SubtypeTestCache::ToCString() const {
@@ -15922,6 +16044,10 @@
   Zone* zone = Thread::Current()->zone();
 
   Class& klass = Class::Handle(zone, clazz());
+  TypeArguments& type_args = TypeArguments::Handle(zone);
+  if (klass.NumTypeArguments() > 0) {
+    type_args ^= GetTypeArguments();
+  }
 
   const String& internal_getter_name =
       String::Handle(zone, Field::GetterName(getter_name));
@@ -15946,7 +16072,8 @@
       zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length()));
 
   return InvokeInstanceFunction(*this, function, internal_getter_name, args,
-                                args_descriptor, respect_reflectable);
+                                args_descriptor, respect_reflectable,
+                                type_args);
 }
 
 RawObject* Instance::InvokeSetter(const String& setter_name,
@@ -15955,6 +16082,11 @@
   Zone* zone = Thread::Current()->zone();
 
   const Class& klass = Class::Handle(zone, clazz());
+  TypeArguments& type_args = TypeArguments::Handle(zone);
+  if (klass.NumTypeArguments() > 0) {
+    type_args ^= GetTypeArguments();
+  }
+
   const String& internal_setter_name =
       String::Handle(zone, Field::SetterName(setter_name));
   const Function& setter = Function::Handle(
@@ -15969,7 +16101,8 @@
       zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length()));
 
   return InvokeInstanceFunction(*this, setter, internal_setter_name, args,
-                                args_descriptor, respect_reflectable);
+                                args_descriptor, respect_reflectable,
+                                type_args);
 }
 
 RawObject* Instance::Invoke(const String& function_name,
@@ -15986,6 +16119,11 @@
   const Array& args_descriptor = Array::Handle(
       zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length(), arg_names));
 
+  TypeArguments& type_args = TypeArguments::Handle(zone);
+  if (klass.NumTypeArguments() > 0) {
+    type_args ^= GetTypeArguments();
+  }
+
   if (function.IsNull()) {
     // Didn't find a method: try to find a getter and invoke call on its result.
     const String& getter_name =
@@ -16000,9 +16138,9 @@
       const Array& getter_args_descriptor = Array::Handle(
           zone, ArgumentsDescriptor::New(kTypeArgsLen, getter_args.Length()));
       const Object& getter_result = Object::Handle(
-          zone,
-          InvokeInstanceFunction(*this, function, getter_name, getter_args,
-                                 getter_args_descriptor, respect_reflectable));
+          zone, InvokeInstanceFunction(*this, function, getter_name,
+                                       getter_args, getter_args_descriptor,
+                                       respect_reflectable, type_args));
       if (getter_result.IsError()) {
         return getter_result.raw();
       }
@@ -16015,37 +16153,8 @@
 
   // Found an ordinary method.
   return InvokeInstanceFunction(*this, function, function_name, args,
-                                args_descriptor, respect_reflectable);
-}
-
-RawObject* Instance::Evaluate(const Class& method_cls,
-                              const String& expr,
-                              const Array& param_names,
-                              const Array& param_values) const {
-  return Evaluate(method_cls, expr, param_names, param_values,
-                  Object::empty_array(), TypeArguments::null_type_arguments());
-}
-
-RawObject* Instance::Evaluate(const Class& method_cls,
-                              const String& expr,
-                              const Array& param_names,
-                              const Array& param_values,
-                              const Array& type_param_names,
-                              const TypeArguments& type_param_values) const {
-  const Array& args = Array::Handle(Array::New(1 + param_values.Length()));
-  PassiveObject& param = PassiveObject::Handle();
-  args.SetAt(0, *this);
-  for (intptr_t i = 0; i < param_values.Length(); i++) {
-    param = param_values.At(i);
-    args.SetAt(i + 1, param);
-  }
-
-  const Library& library = Library::Handle(method_cls.library());
-  ASSERT(library.kernel_data() == ExternalTypedData::null() ||
-         !FLAG_enable_kernel_expression_compilation);
-  const Function& eval_func = Function::Handle(
-      Function::EvaluateHelper(method_cls, expr, param_names, false));
-  return DartEntry::InvokeFunction(eval_func, args);
+                                args_descriptor, respect_reflectable,
+                                type_args);
 }
 
 RawObject* Instance::EvaluateCompiledExpression(
@@ -16623,14 +16732,9 @@
     if (IsClosure()) {
       return Closure::Cast(*this).ToCString();
     }
-    const Class& cls = Class::Handle(clazz());
-    TypeArguments& type_arguments = TypeArguments::Handle();
-    const intptr_t num_type_arguments = cls.NumTypeArguments();
-    if (num_type_arguments > 0) {
-      type_arguments = GetTypeArguments();
-    }
-    const Type& type =
-        Type::Handle(Type::New(cls, type_arguments, TokenPosition::kNoSource));
+    // Background compiler disassembly of instructions referring to pool objects
+    // calls this function and requires allocation of Type in old space.
+    const AbstractType& type = AbstractType::Handle(GetType(Heap::kOld));
     const String& type_name = String::Handle(type.UserVisibleName());
     return OS::SCreate(Thread::Current()->zone(), "Instance of '%s'",
                        type_name.ToCString());
@@ -16648,12 +16752,6 @@
   UNREACHABLE();
 }
 
-bool AbstractType::HasResolvedTypeClass() const {
-  // AbstractType is an abstract class.
-  UNREACHABLE();
-  return false;
-}
-
 classid_t AbstractType::type_class_id() const {
   // AbstractType is an abstract class.
   UNREACHABLE();
@@ -16666,12 +16764,6 @@
   return Class::null();
 }
 
-RawUnresolvedClass* AbstractType::unresolved_class() const {
-  // AbstractType is an abstract class.
-  UNREACHABLE();
-  return UnresolvedClass::null();
-}
-
 RawTypeArguments* AbstractType::arguments() const {
   // AbstractType is an abstract class.
   UNREACHABLE();
@@ -16960,9 +17052,8 @@
   String& class_name = String::Handle(zone);
   intptr_t first_type_param_index;
   intptr_t num_type_params;  // Number of type parameters to print.
-  Class& cls = Class::Handle(zone);
+  Class& cls = Class::Handle(zone, type_class());
   if (IsFunctionType()) {
-    cls = type_class();
     const Function& signature_function =
         Function::Handle(zone, Type::Cast(*this).signature());
     if (!cls.IsTypedefClass()) {
@@ -16977,10 +17068,7 @@
       return class_name.raw();
     }
     // Print the name of a typedef as a regular, possibly parameterized, class.
-  } else if (HasResolvedTypeClass()) {
-    cls = type_class();
   }
-  if (!cls.IsNull()) {
     if (IsResolved() || !cls.IsMixinApplication()) {
       // Do not print the full vector, but only the declared type parameters.
       num_type_params = cls.NumTypeParameters();
@@ -17017,11 +17105,6 @@
       } else {
         first_type_param_index = num_args - num_type_params;
       }
-    }
-  } else {
-    class_name = UnresolvedClass::Handle(zone, unresolved_class()).Name();
-    num_type_params = num_args;
-    first_type_param_index = 0;
   }
   GrowableHandlePtrArray<const String> pieces(zone, 4);
   pieces.Add(class_name);
@@ -17042,11 +17125,7 @@
 
 RawString* AbstractType::ClassName() const {
   ASSERT(!IsFunctionType());
-  if (HasResolvedTypeClass()) {
-    return Class::Handle(type_class()).Name();
-  } else {
-    return UnresolvedClass::Handle(unresolved_class()).Name();
-  }
+  return Class::Handle(type_class()).Name();
 }
 
 bool AbstractType::IsNullTypeRef() const {
@@ -17057,7 +17136,7 @@
   if (IsCanonical()) {
     return raw() == Object::dynamic_type().raw();
   }
-  return HasResolvedTypeClass() && (type_class_id() == kDynamicCid);
+  return type_class_id() == kDynamicCid;
 }
 
 bool AbstractType::IsVoidType() const {
@@ -17066,17 +17145,17 @@
 }
 
 bool AbstractType::IsObjectType() const {
-  return HasResolvedTypeClass() && (type_class_id() == kInstanceCid);
+  return type_class_id() == kInstanceCid;
 }
 
 bool AbstractType::IsTopType() const {
   if (IsVoidType()) {
     return true;
   }
-  if (!HasResolvedTypeClass()) {
+  const classid_t cid = type_class_id();
+  if (cid == kIllegalCid) {
     return false;
   }
-  classid_t cid = type_class_id();
   if ((cid == kDynamicCid) || (cid == kInstanceCid)) {
     return true;
   }
@@ -17101,69 +17180,63 @@
 }
 
 bool AbstractType::IsNullType() const {
-  return HasResolvedTypeClass() && (type_class_id() == kNullCid);
+  return type_class_id() == kNullCid;
 }
 
 bool AbstractType::IsBoolType() const {
-  return HasResolvedTypeClass() && (type_class_id() == kBoolCid);
+  return type_class_id() == kBoolCid;
 }
 
 bool AbstractType::IsIntType() const {
-  return HasResolvedTypeClass() &&
+  return HasTypeClass() &&
          (type_class() == Type::Handle(Type::IntType()).type_class());
 }
 
-bool AbstractType::IsInt64Type() const {
-  return HasResolvedTypeClass() &&
-         (type_class() == Type::Handle(Type::Int64Type()).type_class());
-}
-
 bool AbstractType::IsDoubleType() const {
-  return HasResolvedTypeClass() &&
+  return HasTypeClass() &&
          (type_class() == Type::Handle(Type::Double()).type_class());
 }
 
 bool AbstractType::IsFloat32x4Type() const {
   // kFloat32x4Cid refers to the private class and cannot be used here.
-  return HasResolvedTypeClass() &&
+  return HasTypeClass() &&
          (type_class() == Type::Handle(Type::Float32x4()).type_class());
 }
 
 bool AbstractType::IsFloat64x2Type() const {
   // kFloat64x2Cid refers to the private class and cannot be used here.
-  return HasResolvedTypeClass() &&
+  return HasTypeClass() &&
          (type_class() == Type::Handle(Type::Float64x2()).type_class());
 }
 
 bool AbstractType::IsInt32x4Type() const {
   // kInt32x4Cid refers to the private class and cannot be used here.
-  return HasResolvedTypeClass() &&
+  return HasTypeClass() &&
          (type_class() == Type::Handle(Type::Int32x4()).type_class());
 }
 
 bool AbstractType::IsNumberType() const {
-  return HasResolvedTypeClass() && (type_class_id() == kNumberCid);
+  return type_class_id() == kNumberCid;
 }
 
 bool AbstractType::IsSmiType() const {
-  return HasResolvedTypeClass() && (type_class_id() == kSmiCid);
+  return type_class_id() == kSmiCid;
 }
 
 bool AbstractType::IsStringType() const {
-  return HasResolvedTypeClass() &&
+  return HasTypeClass() &&
          (type_class() == Type::Handle(Type::StringType()).type_class());
 }
 
 bool AbstractType::IsDartFunctionType() const {
-  return HasResolvedTypeClass() &&
+  return HasTypeClass() &&
          (type_class() == Type::Handle(Type::DartFunctionType()).type_class());
 }
 
 bool AbstractType::IsDartClosureType() const {
   // Non-typedef function types have '_Closure' class as type class, but are not
   // the Dart '_Closure' type.
-  return !IsFunctionType() && HasResolvedTypeClass() &&
-         (type_class_id() == kClosureCid);
+  return !IsFunctionType() && (type_class_id() == kClosureCid);
 }
 
 bool AbstractType::TypeTest(TypeTestKind test_kind,
@@ -17449,10 +17522,6 @@
   return Isolate::Current()->object_store()->int_type();
 }
 
-RawType* Type::Int64Type() {
-  return Isolate::Current()->object_store()->int64_type();
-}
-
 RawType* Type::SmiType() {
   return Isolate::Current()->object_store()->smi_type();
 }
@@ -17501,7 +17570,7 @@
   ASSERT(type_class.NumTypeArguments() == 0);
   Type& type = Type::Handle(type_class.CanonicalType());
   if (type.IsNull()) {
-    type ^= Type::New(Object::Handle(type_class.raw()),
+    type ^= Type::New(Class::Handle(type_class.raw()),
                       Object::null_type_arguments(), TokenPosition::kNoSource);
     type.SetIsFinalized();
     type ^= type.Canonicalize();
@@ -17513,7 +17582,6 @@
 void Type::SetIsFinalized() const {
   ASSERT(!IsFinalized());
   if (IsInstantiated()) {
-    ASSERT(HasResolvedTypeClass());
     set_type_state(RawType::kFinalizedInstantiated);
   } else {
     set_type_state(RawType::kFinalizedUninstantiated);
@@ -17605,33 +17673,14 @@
   set_type_state(RawType::kResolved);
 }
 
-bool Type::HasResolvedTypeClass() const {
-  return !raw_ptr()->type_class_id_->IsHeapObject();
-}
-
 classid_t Type::type_class_id() const {
-  ASSERT(HasResolvedTypeClass());
-  return Smi::Value(reinterpret_cast<RawSmi*>(raw_ptr()->type_class_id_));
+  return Smi::Value(raw_ptr()->type_class_id_);
 }
 
 RawClass* Type::type_class() const {
   return Isolate::Current()->class_table()->At(type_class_id());
 }
 
-RawUnresolvedClass* Type::unresolved_class() const {
-#ifdef DEBUG
-  ASSERT(!HasResolvedTypeClass());
-  UnresolvedClass& unresolved_class = UnresolvedClass::Handle();
-  unresolved_class ^= raw_ptr()->type_class_id_;
-  ASSERT(!unresolved_class.IsNull());
-  return unresolved_class.raw();
-#else
-  ASSERT(!Object::Handle(raw_ptr()->type_class_id_).IsNull());
-  ASSERT(Object::Handle(raw_ptr()->type_class_id_).IsUnresolvedClass());
-  return reinterpret_cast<RawUnresolvedClass*>(raw_ptr()->type_class_id_);
-#endif
-}
-
 bool Type::IsInstantiated(Genericity genericity,
                           intptr_t num_free_fun_type_params,
                           TrailPtr trail) const {
@@ -17660,19 +17709,13 @@
   intptr_t len = num_type_args;  // Check the full vector of type args.
   ASSERT(num_type_args > 0);
   // This type is not instantiated if it refers to type parameters.
-  // Although this type may still be unresolved, the type parameters it may
-  // refer to are resolved by definition. We can therefore return the correct
-  // result even for an unresolved type. We just need to look at all type
-  // arguments and not just at the type parameters.
-  if (HasResolvedTypeClass()) {
-    const Class& cls = Class::Handle(type_class());
-    len = cls.NumTypeParameters();  // Check the type parameters only.
-    if (len > num_type_args) {
-      // This type has the wrong number of arguments and is not finalized yet.
-      // Type arguments are reset to null when finalizing such a type.
-      ASSERT(!IsFinalized());
-      len = num_type_args;
-    }
+  const Class& cls = Class::Handle(type_class());
+  len = cls.NumTypeParameters();  // Check the type parameters only.
+  if (len > num_type_args) {
+    // This type has the wrong number of arguments and is not finalized yet.
+    // Type arguments are reset to null when finalizing such a type.
+    ASSERT(!IsFinalized());
+    len = num_type_args;
   }
   return (len == 0) ||
          args.IsSubvectorInstantiated(num_type_args - len, len, genericity,
@@ -18299,13 +18342,7 @@
 
 void Type::set_type_class(const Class& value) const {
   ASSERT(!value.IsNull());
-  StorePointer(&raw_ptr()->type_class_id_,
-               reinterpret_cast<RawObject*>(Smi::New(value.id())));
-}
-
-void Type::set_unresolved_class(const Object& value) const {
-  ASSERT(!value.IsNull() && value.IsUnresolvedClass());
-  StorePointer(&raw_ptr()->type_class_id_, value.raw());
+  StorePointer(&raw_ptr()->type_class_id_, Smi::New(value.id()));
 }
 
 void Type::set_arguments(const TypeArguments& value) const {
@@ -18319,17 +18356,13 @@
   return reinterpret_cast<RawType*>(raw);
 }
 
-RawType* Type::New(const Object& clazz,
+RawType* Type::New(const Class& clazz,
                    const TypeArguments& arguments,
                    TokenPosition token_pos,
                    Heap::Space space) {
   Zone* Z = Thread::Current()->zone();
   const Type& result = Type::Handle(Z, Type::New(space));
-  if (clazz.IsClass()) {
-    result.set_type_class(Class::Cast(clazz));
-  } else {
-    result.set_unresolved_class(clazz);
-  }
+  result.set_type_class(clazz);
   result.set_arguments(arguments);
   result.SetHash(0);
   result.set_token_pos(token_pos);
@@ -18356,38 +18389,31 @@
     return "Type: null";
   }
   Zone* zone = Thread::Current()->zone();
-  const char* unresolved = IsResolved() ? "" : "Unresolved ";
   const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
   const char* args_cstr = type_args.IsNull() ? "null" : type_args.ToCString();
-  Class& cls = Class::Handle(zone);
+  const Class& cls = Class::Handle(zone, type_class());
   const char* class_name;
-  if (HasResolvedTypeClass()) {
-    cls = type_class();
-    const String& name = String::Handle(zone, cls.Name());
-    class_name = name.IsNull() ? "<null>" : name.ToCString();
-  } else {
-    class_name = UnresolvedClass::Handle(zone, unresolved_class()).ToCString();
-  }
+  const String& name = String::Handle(zone, cls.Name());
+  class_name = name.IsNull() ? "<null>" : name.ToCString();
   if (IsFunctionType()) {
     const Function& sig_fun = Function::Handle(zone, signature());
     const String& sig = String::Handle(zone, sig_fun.Signature());
     if (cls.IsClosureClass()) {
       ASSERT(type_args.IsNull());
-      return OS::SCreate(zone, "%sFunction Type: %s", unresolved,
-                         sig.ToCString());
+      return OS::SCreate(zone, "Function Type: %s", sig.ToCString());
     }
-    return OS::SCreate(zone, "%s Function Type: %s (class: %s, args: %s)",
-                       unresolved, sig.ToCString(), class_name, args_cstr);
+    return OS::SCreate(zone, "Function Type: %s (class: %s, args: %s)",
+                       sig.ToCString(), class_name, args_cstr);
   }
   if (type_args.IsNull()) {
-    return OS::SCreate(zone, "%sType: class '%s'", unresolved, class_name);
-  } else if (IsResolved() && IsFinalized() && IsRecursive()) {
+    return OS::SCreate(zone, "Type: class '%s'", class_name);
+  } else if (IsFinalized() && IsRecursive()) {
     const intptr_t hash = Hash();
     return OS::SCreate(zone, "Type: (@%p H%" Px ") class '%s', args:[%s]",
                        raw(), hash, class_name, args_cstr);
   } else {
-    return OS::SCreate(zone, "%sType: class '%s', args:[%s]", unresolved,
-                       class_name, args_cstr);
+    return OS::SCreate(zone, "Type: class '%s', args:[%s]", class_name,
+                       args_cstr);
   }
 }
 
@@ -18474,7 +18500,7 @@
 }
 
 void TypeRef::set_type(const AbstractType& value) const {
-  ASSERT(value.IsFunctionType() || value.HasResolvedTypeClass());
+  ASSERT(value.IsFunctionType() || value.HasTypeClass());
   ASSERT(!value.IsTypeRef());
   StorePointer(&raw_ptr()->type_, value.raw());
 }
@@ -18723,7 +18749,7 @@
       // is not and its class is not compiled yet, i.e. we cannot look for
       // a call method yet.
       if (!bounded_type.IsFunctionType() && upper_bound.IsFunctionType() &&
-          bounded_type.HasResolvedTypeClass() &&
+          bounded_type.HasTypeClass() &&
           !Class::Handle(bounded_type.type_class()).is_finalized()) {
         return false;  // Not a subtype yet, but no bound error yet.
       }
@@ -19051,7 +19077,7 @@
                !instantiated_upper_bound.IsInstantiated() ||
                (!instantiated_bounded_type.IsFunctionType() &&
                 instantiated_upper_bound.IsFunctionType() &&
-                instantiated_bounded_type.HasResolvedTypeClass() &&
+                instantiated_bounded_type.HasTypeClass() &&
                 !Class::Handle(instantiated_bounded_type.type_class())
                      .is_finalized()));
         // Postpone bound check by returning a new BoundedType with unfinalized
@@ -19265,6 +19291,9 @@
 RawInteger* Integer::New(const String& str, Heap::Space space) {
   // We are not supposed to have integers represented as two byte strings.
   ASSERT(str.IsOneByteString());
+  if (str.IsNull() || (str.Length() == 0)) {
+    return Integer::null();
+  }
   int64_t value = 0;
   const char* cstr = str.ToCString();
   if (!OS::StringToInt64(cstr, &value)) {
@@ -19918,22 +19947,6 @@
   return ExternalTwoByteString::CharAt(*this, index);
 }
 
-Scanner::CharAtFunc String::CharAtFunc() const {
-  intptr_t class_id = raw()->GetClassId();
-  ASSERT(RawObject::IsStringClassId(class_id));
-  if (class_id == kOneByteStringCid) {
-    return &OneByteString::CharAt;
-  }
-  if (class_id == kTwoByteStringCid) {
-    return &TwoByteString::CharAt;
-  }
-  if (class_id == kExternalOneByteStringCid) {
-    return &ExternalOneByteString::CharAt;
-  }
-  ASSERT(class_id == kExternalTwoByteStringCid);
-  return &ExternalTwoByteString::CharAt;
-}
-
 intptr_t String::CharSize() const {
   intptr_t class_id = raw()->GetClassId();
   if (class_id == kOneByteStringCid || class_id == kExternalOneByteStringCid) {
@@ -19978,10 +19991,8 @@
     return false;  // Lengths don't match.
   }
 
-  Scanner::CharAtFunc this_char_at_func = this->CharAtFunc();
-  Scanner::CharAtFunc str_char_at_func = str.CharAtFunc();
   for (intptr_t i = 0; i < len; i++) {
-    if (this_char_at_func(*this, i) != str_char_at_func(str, begin_index + i)) {
+    if (CharAt(i) != str.CharAt(begin_index + i)) {
       return false;
     }
   }
@@ -20657,9 +20668,8 @@
     startChar = ExternalOneByteString::CharAddr(str, start);
   } else {
     uint8_t* chars = Thread::Current()->zone()->Alloc<uint8_t>(length);
-    const Scanner::CharAtFunc char_at = str.CharAtFunc();
     for (intptr_t i = 0; i < length; i++) {
-      int32_t ch = char_at(str, start + i);
+      int32_t ch = str.CharAt(start + i);
       if (ch < 128) {
         chars[i] = ch;
       } else {
@@ -21338,7 +21348,12 @@
 
 RawArray* Array::New(intptr_t len, Heap::Space space) {
   ASSERT(Isolate::Current()->object_store()->array_class() != Class::null());
-  return New(kClassId, len, space);
+  RawArray* result = New(kClassId, len, space);
+  if (result->Size() > Heap::kNewAllocatableSize) {
+    ASSERT(result->IsOldObject());
+    result->SetCardRememberedBitUnsynchronized();
+  }
+  return result;
 }
 
 RawArray* Array::New(intptr_t len,
@@ -21375,7 +21390,7 @@
   // allocated array with values from the given source array instead of
   // null-initializing all elements.
   Array& dest = Array::Handle(Array::New(count));
-  dest.StorePointers(dest.ObjectAddr(0), ObjectAddr(start), count);
+  dest.StoreArrayPointers(dest.ObjectAddr(0), ObjectAddr(start), count);
 
   if (with_type_argument) {
     dest.SetTypeArguments(TypeArguments::Handle(GetTypeArguments()));
@@ -22227,12 +22242,13 @@
   return code_array.Length();
 }
 
-RawCode* StackTrace::CodeAtFrame(intptr_t frame_index) const {
+RawObject* StackTrace::CodeAtFrame(intptr_t frame_index) const {
   const Array& code_array = Array::Handle(raw_ptr()->code_array_);
-  return reinterpret_cast<RawCode*>(code_array.At(frame_index));
+  return code_array.At(frame_index);
 }
 
-void StackTrace::SetCodeAtFrame(intptr_t frame_index, const Code& code) const {
+void StackTrace::SetCodeAtFrame(intptr_t frame_index,
+                                const Object& code) const {
   const Array& code_array = Array::Handle(raw_ptr()->code_array_);
   code_array.SetAt(frame_index, code);
 }
@@ -22343,7 +22359,9 @@
   Zone* zone = Thread::Current()->zone();
   StackTrace& stack_trace = StackTrace::Handle(zone, stack_trace_in.raw());
   Function& function = Function::Handle(zone);
+  Object& code_object = Object::Handle(zone);
   Code& code = Code::Handle(zone);
+  Bytecode& bytecode = Bytecode::Handle(zone);
 
   GrowableArray<const Function*> inlined_functions;
   GrowableArray<TokenPosition> inlined_token_positions;
@@ -22354,8 +22372,8 @@
   intptr_t frame_index = 0;
   do {
     for (intptr_t i = 0; i < stack_trace.Length(); i++) {
-      code = stack_trace.CodeAtFrame(i);
-      if (code.IsNull()) {
+      code_object = stack_trace.CodeAtFrame(i);
+      if (code_object.IsNull()) {
         // Check for a null function, which indicates a gap in a StackOverflow
         // or OutOfMemory trace.
         if ((i < (stack_trace.Length() - 1)) &&
@@ -22365,7 +22383,7 @@
           // To account for gap frames.
           frame_index += Smi::Value(stack_trace.PcOffsetAtFrame(i));
         }
-      } else if (code.raw() ==
+      } else if (code_object.raw() ==
                  StubCode::AsynchronousGapMarker_entry()->code()) {
         buffer.AddString("<asynchronous suspension>\n");
         // The frame immediately after the asynchronous gap marker is the
@@ -22373,25 +22391,39 @@
         // the readability of the trace.
         i++;
       } else {
-        ASSERT(code.IsFunctionCode());
         intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i));
-        if (code.is_optimized() && stack_trace.expand_inlined()) {
-          code.GetInlinedFunctionsAtReturnAddress(pc_offset, &inlined_functions,
-                                                  &inlined_token_positions);
-          ASSERT(inlined_functions.length() >= 1);
-          for (intptr_t j = inlined_functions.length() - 1; j >= 0; j--) {
-            if (inlined_functions[j]->is_visible() ||
-                FLAG_show_invisible_frames) {
-              PrintStackTraceFrame(zone, &buffer, *inlined_functions[j],
-                                   inlined_token_positions[j], frame_index);
+        if (code_object.IsCode()) {
+          code ^= code_object.raw();
+          ASSERT(code.IsFunctionCode());
+          if (code.is_optimized() && stack_trace.expand_inlined()) {
+            code.GetInlinedFunctionsAtReturnAddress(
+                pc_offset, &inlined_functions, &inlined_token_positions);
+            ASSERT(inlined_functions.length() >= 1);
+            for (intptr_t j = inlined_functions.length() - 1; j >= 0; j--) {
+              if (inlined_functions[j]->is_visible() ||
+                  FLAG_show_invisible_frames) {
+                PrintStackTraceFrame(zone, &buffer, *inlined_functions[j],
+                                     inlined_token_positions[j], frame_index);
+                frame_index++;
+              }
+            }
+          } else {
+            function = code.function();
+            if (function.is_visible() || FLAG_show_invisible_frames) {
+              uword pc = code.PayloadStart() + pc_offset;
+              const TokenPosition token_pos = code.GetTokenIndexOfPC(pc);
+              PrintStackTraceFrame(zone, &buffer, function, token_pos,
+                                   frame_index);
               frame_index++;
             }
           }
         } else {
-          function = code.function();
+          ASSERT(code_object.IsBytecode());
+          bytecode ^= code_object.raw();
+          function = bytecode.function();
           if (function.is_visible() || FLAG_show_invisible_frames) {
-            uword pc = code.PayloadStart() + pc_offset;
-            const TokenPosition token_pos = code.GetTokenIndexOfPC(pc);
+            uword pc = bytecode.PayloadStart() + pc_offset;
+            const TokenPosition token_pos = bytecode.GetTokenIndexOfPC(pc);
             PrintStackTraceFrame(zone, &buffer, function, token_pos,
                                  frame_index);
             frame_index++;
@@ -22410,7 +22442,7 @@
 #if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
   Zone* zone = Thread::Current()->zone();
   StackTrace& stack_trace = StackTrace::Handle(zone, stack_trace_in.raw());
-  Code& code = Code::Handle(zone);
+  Object& code = Object::Handle(zone);
   ZoneTextBuffer buffer(zone, 1024);
 
   // The Dart standard requires the output of StackTrace.toString to include
@@ -22451,7 +22483,9 @@
         intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i));
         // This output is formatted like Android's debuggerd. Note debuggerd
         // prints call addresses instead of return addresses.
-        uword return_addr = code.PayloadStart() + pc_offset;
+        uword start = code.IsBytecode() ? Bytecode::Cast(code).PayloadStart()
+                                        : Code::Cast(code).PayloadStart();
+        uword return_addr = start + pc_offset;
         uword call_addr = return_addr - 1;
         uword dso_base;
         char* dso_name;
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index f792344..b58ee61 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -5,6 +5,8 @@
 #ifndef RUNTIME_VM_OBJECT_H_
 #define RUNTIME_VM_OBJECT_H_
 
+#include <tuple>
+
 #include "include/dart_api.h"
 #include "platform/assert.h"
 #include "platform/utils.h"
@@ -21,7 +23,6 @@
 #include "vm/os.h"
 #include "vm/raw_object.h"
 #include "vm/report.h"
-#include "vm/scanner.h"
 #include "vm/tags.h"
 #include "vm/thread.h"
 #include "vm/token_position.h"
@@ -64,6 +65,7 @@
 
 #define BASE_OBJECT_IMPLEMENTATION(object, super)                              \
  public: /* NOLINT */                                                          \
+  using RawObjectType = Raw##object;                                           \
   Raw##object* raw() const { return reinterpret_cast<Raw##object*>(raw_); }    \
   bool Is##object() const { return true; }                                     \
   static object& Handle(Zone* zone, Raw##object* raw_ptr) {                    \
@@ -87,9 +89,6 @@
     }                                                                          \
     return *obj;                                                               \
   }                                                                            \
-  static object& CheckedHandle(RawObject* raw_ptr) {                           \
-    return CheckedHandle(Thread::Current()->zone(), raw_ptr);                  \
-  }                                                                            \
   static object& ZoneHandle(Zone* zone, Raw##object* raw_ptr) {                \
     object* obj =                                                              \
         reinterpret_cast<object*>(VMHandles::AllocateZoneHandle(zone));        \
@@ -243,6 +242,9 @@
 
 class Object {
  public:
+  using RawObjectType = RawObject;
+  static RawObject* RawCast(RawObject* obj) { return obj; }
+
   virtual ~Object() {}
 
   RawObject* raw() const { return raw_; }
@@ -413,7 +415,6 @@
   static RawClass* class_class() { return class_class_; }
   static RawClass* dynamic_class() { return dynamic_class_; }
   static RawClass* void_class() { return void_class_; }
-  static RawClass* unresolved_class_class() { return unresolved_class_class_; }
   static RawClass* type_arguments_class() { return type_arguments_class_; }
   static RawClass* patch_class_class() { return patch_class_class_; }
   static RawClass* function_class() { return function_class_; }
@@ -428,6 +429,7 @@
     return kernel_program_info_class_;
   }
   static RawClass* code_class() { return code_class_; }
+  static RawClass* bytecode_class() { return bytecode_class_; }
   static RawClass* instructions_class() { return instructions_class_; }
   static RawClass* object_pool_class() { return object_pool_class_; }
   static RawClass* pc_descriptors_class() { return pc_descriptors_class_; }
@@ -552,24 +554,9 @@
   // methods below or their counterparts in RawObject, to ensure that the
   // write barrier is correctly applied.
 
-  template <typename type>
+  template <typename type, MemoryOrder order = MemoryOrder::kRelaxed>
   void StorePointer(type const* addr, type value) const {
-    raw()->StorePointer(addr, value);
-  }
-
-  // Store a range of pointers [from, from + count) into [to, to + count).
-  // TODO(koda): Use this to fix Object::Clone's broken store buffer logic.
-  void StorePointers(RawObject* const* to,
-                     RawObject* const* from,
-                     intptr_t count) {
-    ASSERT(Contains(reinterpret_cast<uword>(to)));
-    if (raw()->IsNewObject()) {
-      memmove(const_cast<RawObject**>(to), from, count * kWordSize);
-    } else {
-      for (intptr_t i = 0; i < count; ++i) {
-        StorePointer(&to[i], from[i]);
-      }
-    }
+    raw()->StorePointer<type, order>(addr, value);
   }
 
   // Use for storing into an explicitly Smi-typed field of an object
@@ -678,7 +665,6 @@
   static RawClass* class_class_;             // Class of the Class vm object.
   static RawClass* dynamic_class_;           // Class of the 'dynamic' type.
   static RawClass* void_class_;              // Class of the 'void' type.
-  static RawClass* unresolved_class_class_;  // Class of UnresolvedClass.
   static RawClass* type_arguments_class_;  // Class of TypeArguments vm object.
   static RawClass* patch_class_class_;     // Class of the PatchClass vm object.
   static RawClass* function_class_;        // Class of the Function vm object.
@@ -692,6 +678,7 @@
   static RawClass* kernel_program_info_class_;  // Class of KernelProgramInfo vm
                                                 // object.
   static RawClass* code_class_;                 // Class of the Code vm object.
+  static RawClass* bytecode_class_;      // Class of the Bytecode vm object.
   static RawClass* instructions_class_;  // Class of the Instructions vm object.
   static RawClass* object_pool_class_;   // Class of the ObjectPool vm object.
   static RawClass* pc_descriptors_class_;   // Class of PcDescriptors vm object.
@@ -1268,14 +1255,6 @@
   // expression fails. The method has the formal (type) parameters given in
   // (type_)param_names, and is invoked with the (type)argument values given in
   // (type_)param_values.
-  RawObject* Evaluate(const String& expr,
-                      const Array& param_names,
-                      const Array& param_values) const;
-  RawObject* Evaluate(const String& expr,
-                      const Array& param_names,
-                      const Array& param_values,
-                      const Array& type_param_names,
-                      const TypeArguments& type_param_values) const;
   RawObject* EvaluateCompiledExpression(
       const uint8_t* kernel_bytes,
       intptr_t kernel_length,
@@ -1525,37 +1504,6 @@
   friend class ClassFunctionVisitor;
 };
 
-// Unresolved class is used for storing unresolved names which will be resolved
-// to a class after all classes have been loaded and finalized.
-class UnresolvedClass : public Object {
- public:
-  RawObject* library_or_library_prefix() const {
-    return raw_ptr()->library_or_library_prefix_;
-  }
-  RawString* ident() const { return raw_ptr()->ident_; }
-  TokenPosition token_pos() const { return raw_ptr()->token_pos_; }
-
-  RawString* Name() const;
-
-  static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(RawUnresolvedClass));
-  }
-
-  static RawUnresolvedClass* New(const Object& library_prefix,
-                                 const String& ident,
-                                 TokenPosition token_pos);
-
- private:
-  void set_library_or_library_prefix(const Object& library_prefix) const;
-  void set_ident(const String& ident) const;
-  void set_token_pos(TokenPosition token_pos) const;
-
-  static RawUnresolvedClass* New();
-
-  FINAL_HEAP_OBJECT_IMPLEMENTATION(UnresolvedClass, Object);
-  friend class Class;
-};
-
 // Classification of type genericity according to type parameter owners.
 enum Genericity {
   kAny,           // Consider type params of current class and functions.
@@ -2111,7 +2059,9 @@
  private:
   static RawICData* New();
 
-  RawArray* ic_data() const { return raw_ptr()->ic_data_; }
+  RawArray* ic_data() const {
+    return AtomicOperations::LoadAcquire(&raw_ptr()->ic_data_);
+  }
 
   void set_owner(const Function& value) const;
   void set_target_name(const String& value) const;
@@ -2172,6 +2122,7 @@
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(ICData, Object);
   friend class Class;
+  friend class ICDataTestTask;
   friend class Interpreter;
   friend class SnapshotWriter;
   friend class Serializer;
@@ -2378,8 +2329,8 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   bool IsBytecodeAllowed(Zone* zone) const;
-  void AttachBytecode(const Code& bytecode) const;
-  RawCode* Bytecode() const { return raw_ptr()->bytecode_; }
+  void AttachBytecode(const Bytecode& bytecode) const;
+  RawBytecode* bytecode() const { return raw_ptr()->bytecode_; }
   bool HasBytecode() const;
 #endif
 
@@ -2680,6 +2631,13 @@
                               intptr_t num_named_arguments,
                               String* error_message) const;
 
+  // Returns a TypeError if the provided arguments don't match the function
+  // parameter types, NULL otherwise. Assumes AreValidArguments is called first.
+  RawObject* DoArgumentTypesMatch(
+      const Array& args,
+      const ArgumentsDescriptor& arg_names,
+      const TypeArguments& instantiator_type_args) const;
+
   // Returns true if the type argument count, total argument count and the names
   // of optional arguments are valid for calling this function.
   // Otherwise, it returns false and the reason (if error_message is not NULL).
@@ -2850,11 +2808,6 @@
     return RoundedAllocationSize(sizeof(RawFunction));
   }
 
-  static RawFunction* EvaluateHelper(const Class& cls,
-                                     const String& expr,
-                                     const Array& param_names,
-                                     bool is_static);
-
   static RawFunction* New(const String& name,
                           RawFunction::Kind kind,
                           bool is_static,
@@ -3793,16 +3746,6 @@
   // evaluating the expression fails. The method has the formal (type)
   // parameters given in (type_)param_names, and is invoked with the (type)
   // argument values given in (type_)param_values.
-  RawObject* Evaluate(const String& expr,
-                      const Array& param_names,
-                      const Array& param_values) const;
-
-  RawObject* Evaluate(const String& expr,
-                      const Array& param_names,
-                      const Array& param_values,
-                      const Array& type_param_names,
-                      const TypeArguments& type_arguments) const;
-
   RawObject* EvaluateCompiledExpression(
       const uint8_t* kernel_bytes,
       intptr_t kernel_length,
@@ -4273,6 +4216,9 @@
     StoreNonPointer(&EntryAddr(index)->raw_value_, raw_value);
   }
 
+  // Used during reloading (see object_reload.cc). Calls Reset on all ICDatas.
+  void ResetICDatas(Zone* zone) const;
+
   static intptr_t InstanceSize() {
     ASSERT(sizeof(RawObjectPool) ==
            OFFSET_OF_RETURNED_VALUE(RawObjectPool, data));
@@ -4344,6 +4290,14 @@
     return FlagsBits::decode(instr->ptr()->size_and_flags_);
   }
 
+  static bool ContainsPc(RawInstructions* instruction, uword pc) {
+    const uword offset = pc - PayloadStart(instruction);
+    // We use <= instead of < here because the saved-pc can be outside the
+    // instruction stream if the last instruction is a call we don't expect to
+    // return (e.g. because it throws an exception).
+    return offset <= static_cast<uword>(Size(instruction));
+  }
+
   uword PayloadStart() const { return PayloadStart(raw()); }
   uword MonomorphicEntryPoint() const { return MonomorphicEntryPoint(raw()); }
   uword EntryPoint() const { return EntryPoint(raw()); }
@@ -4421,11 +4375,13 @@
   }
 
   bool Equals(const Instructions& other) const {
-    if (Size() != other.Size()) {
-      return false;
-    }
+    return Equals(raw(), other.raw());
+  }
+
+  static bool Equals(RawInstructions* a, RawInstructions* b) {
+    if (Size(a) != Size(b)) return false;
     NoSafepointScope no_safepoint;
-    return memcmp(raw_ptr(), other.raw_ptr(), InstanceSize(Size())) == 0;
+    return memcmp(a->ptr(), b->ptr(), InstanceSize(Size(a))) == 0;
   }
 
   CodeStatistics* stats() const {
@@ -4901,10 +4857,13 @@
   }
   intptr_t Size() const { return Instructions::Size(instructions()); }
   RawObjectPool* GetObjectPool() const { return object_pool(); }
+
   bool ContainsInstructionAt(uword addr) const {
-    const Instructions& instr = Instructions::Handle(instructions());
-    const uword offset = addr - instr.PayloadStart();
-    return offset < static_cast<uword>(instr.Size());
+    return ContainsInstructionAt(raw(), addr);
+  }
+
+  static bool ContainsInstructionAt(RawCode* code, uword addr) {
+    return Instructions::ContainsPc(code->ptr()->instructions_, addr);
   }
 
   // Returns true if there is a debugger breakpoint set in this code object.
@@ -4931,7 +4890,7 @@
   void set_await_token_positions(const Array& await_token_positions) const;
 
   // Used during reloading (see object_reload.cc). Calls Reset on all ICDatas
-  // that are embedded inside the Code object.
+  // that are embedded inside the Code or ObjecPool objects.
   void ResetICDatas(Zone* zone) const;
 
   // Array of DeoptInfo objects.
@@ -4961,13 +4920,27 @@
                            Array* stackmaps,
                            StackMap* map) const;
 
-  enum {
-    kSCallTableOffsetEntry = 0,
-    kSCallTableFunctionEntry = 1,
-    kSCallTableCodeEntry = 2,
+  enum CallKind {
+    kPcRelativeCall = 1,
+    kPcRelativeTailCall = 2,
+    kCallViaCode = 3,
+  };
+
+  enum SCallTableEntry {
+    kSCallTableKindAndOffset = 0,
+    kSCallTableCodeTarget = 1,
+    kSCallTableFunctionTarget = 2,
     kSCallTableEntryLength = 3,
   };
 
+  enum class PoolAttachment {
+    kAttachPool,
+    kNotAttachPool,
+  };
+
+  class KindField : public BitField<intptr_t, CallKind, 0, 2> {};
+  class OffsetField : public BitField<intptr_t, intptr_t, 2, 28> {};
+
   void set_static_calls_target_table(const Array& value) const;
   RawArray* static_calls_target_table() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -5129,20 +5102,26 @@
     return RoundedAllocationSize(sizeof(RawCode) + (len * kBytesPerElement));
   }
 #if !defined(DART_PRECOMPILED_RUNTIME)
+  // Finalizes the generated code, by generating various kinds of metadata (e.g.
+  // stack maps, pc descriptors, ...) and attach them to a newly generated
+  // [Code] object.
+  //
+  // If Code::PoolAttachment::kAttachPool is specified for [pool_attachment]
+  // then a new [ObjectPool] will be attached to the code object as well.
+  // Otherwise the caller is responsible for doing this via
+  // `Object::set_object_pool()`.
   static RawCode* FinalizeCode(const Function& function,
                                FlowGraphCompiler* compiler,
                                Assembler* assembler,
+                               PoolAttachment pool_attachment,
                                bool optimized = false,
                                CodeStatistics* stats = nullptr);
   static RawCode* FinalizeCode(const char* name,
                                FlowGraphCompiler* compiler,
                                Assembler* assembler,
+                               PoolAttachment pool_attachment,
                                bool optimized,
                                CodeStatistics* stats = nullptr);
-  static RawCode* FinalizeBytecode(const void* bytecode_data,
-                                   intptr_t bytecode_size,
-                                   const ObjectPool& object_pool,
-                                   CodeStatistics* stats = nullptr);
 #endif
   static RawCode* LookupCode(uword pc);
   static RawCode* LookupCodeInVmIsolate(uword pc);
@@ -5272,6 +5251,8 @@
   friend class SnapshotWriter;
   friend class FunctionSerializationCluster;
   friend class CodeSerializationCluster;
+  friend class StubCode;               // for set_object_pool
+  friend class MegamorphicCacheTable;  // for set_object_pool
   friend class CodePatcher;     // for set_instructions
   friend class ProgramVisitor;  // for set_instructions
   // So that the RawFunction pointer visitor can determine whether code the
@@ -5279,6 +5260,105 @@
   friend class RawFunction;
 };
 
+class Bytecode : public Object {
+ public:
+  RawExternalTypedData* instructions() const {
+    return raw_ptr()->instructions_;
+  }
+  uword PayloadStart() const;
+  intptr_t Size() const;
+
+  RawObjectPool* object_pool() const { return raw_ptr()->object_pool_; }
+
+  bool ContainsInstructionAt(uword addr) const {
+    return RawBytecode::ContainsPC(raw(), addr);
+  }
+
+  RawPcDescriptors* pc_descriptors() const {
+    return raw_ptr()->pc_descriptors_;
+  }
+  void set_pc_descriptors(const PcDescriptors& descriptors) const {
+    ASSERT(descriptors.IsOld());
+    StorePointer(&raw_ptr()->pc_descriptors_, descriptors.raw());
+  }
+
+  void Disassemble(DisassemblyFormatter* formatter = NULL) const;
+
+  RawExceptionHandlers* exception_handlers() const {
+    return raw_ptr()->exception_handlers_;
+  }
+  void set_exception_handlers(const ExceptionHandlers& handlers) const {
+    ASSERT(handlers.IsOld());
+    StorePointer(&raw_ptr()->exception_handlers_, handlers.raw());
+  }
+
+  RawFunction* function() const { return raw_ptr()->function_; }
+
+  void set_function(const Function& function) const {
+    ASSERT(function.IsOld());
+    StorePointer(&raw_ptr()->function_, function.raw());
+  }
+
+  // Used during reloading (see object_reload.cc). Calls Reset on all ICDatas
+  // that are embedded inside the Code or ObjecPool objects.
+  void ResetICDatas(Zone* zone) const;
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(RawBytecode));
+  }
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  static RawBytecode* New(const ExternalTypedData& instructions,
+                          const ObjectPool& object_pool);
+#endif
+
+  RawExternalTypedData* GetBinary(Zone* zone) const;
+
+  TokenPosition GetTokenIndexOfPC(uword pc) const;
+
+  intptr_t source_positions_binary_offset() const {
+    return raw_ptr()->source_positions_binary_offset_;
+  }
+  void set_source_positions_binary_offset(intptr_t value) const {
+    StoreNonPointer(&raw_ptr()->source_positions_binary_offset_, value);
+  }
+  bool HasSourcePositions() const {
+    return (source_positions_binary_offset() != 0);
+  }
+
+  const char* Name() const;
+  const char* QualifiedName() const;
+
+  class SlowFindRawBytecodeVisitor : public FindObjectVisitor {
+   public:
+    explicit SlowFindRawBytecodeVisitor(uword pc) : pc_(pc) {}
+    virtual ~SlowFindRawBytecodeVisitor() {}
+
+    // Check if object matches find condition.
+    virtual bool FindObject(RawObject* obj) const;
+
+   private:
+    const uword pc_;
+
+    DISALLOW_COPY_AND_ASSIGN(SlowFindRawBytecodeVisitor);
+  };
+
+  static RawBytecode* FindCode(uword pc);
+
+ private:
+  void set_object_pool(const ObjectPool& object_pool) const {
+    StorePointer(&raw_ptr()->object_pool_, object_pool.raw());
+  }
+
+  friend class RawObject;  // For RawObject::SizeFromClass().
+  friend class RawBytecode;
+
+  void set_instructions(const ExternalTypedData& instructions) const;
+
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(Bytecode, Object);
+  friend class Class;
+  friend class SnapshotWriter;
+};
+
 class Context : public Object {
  public:
   RawContext* parent() const { return raw_ptr()->parent_; }
@@ -5788,18 +5868,6 @@
   // evaluating the expression fails. The method has the formal (type)
   // parameters given in (type_)param_names, and is invoked with the (type)
   // argument values given in (type_)param_values.
-  RawObject* Evaluate(const Class& method_cls,
-                      const String& expr,
-                      const Array& param_names,
-                      const Array& param_values) const;
-
-  RawObject* Evaluate(const Class& method_cls,
-                      const String& expr,
-                      const Array& param_names,
-                      const Array& param_values,
-                      const Array& type_param_names,
-                      const TypeArguments& type_param_values) const;
-
   RawObject* EvaluateCompiledExpression(
       const Class& method_cls,
       const uint8_t* kernel_bytes,
@@ -6034,6 +6102,7 @@
                                TrailPtr trail = NULL) const;
   bool IsUninstantiatedIdentity() const;
   bool CanShareInstantiatorTypeArguments(const Class& instantiator_class) const;
+  bool CanShareFunctionTypeArguments(const Function& function) const;
 
   // Return true if all types of this vector are respectively, resolved,
   // finalized, or bounded.
@@ -6185,10 +6254,9 @@
   virtual void set_error(const LanguageError& value) const;
   virtual bool IsResolved() const;
   virtual void SetIsResolved() const;
-  virtual bool HasResolvedTypeClass() const;
+  virtual bool HasTypeClass() const { return type_class_id() != kIllegalCid; }
   virtual classid_t type_class_id() const;
   virtual RawClass* type_class() const;
-  virtual RawUnresolvedClass* unresolved_class() const;
   virtual RawTypeArguments* arguments() const;
   virtual void set_arguments(const TypeArguments& value) const;
   virtual TokenPosition token_pos() const;
@@ -6332,9 +6400,6 @@
   // Check if this type represents the 'int' type.
   bool IsIntType() const;
 
-  // Check if this type represents the '_int64' type.
-  bool IsInt64Type() const;
-
   // Check if this type represents the 'double' type.
   bool IsDoubleType() const;
 
@@ -6427,7 +6492,6 @@
 
 // A Type consists of a class, possibly parameterized with type
 // arguments. Example: C<T1, T2>.
-// An unresolved class is a String specifying the class name.
 //
 // Caution: 'RawType*' denotes a 'raw' pointer to a VM object of class Type, as
 // opposed to 'Type' denoting a 'handle' to the same object. 'RawType' does not
@@ -6461,12 +6525,13 @@
     return raw_ptr()->type_state_ >= RawType::kResolved;
   }
   virtual void SetIsResolved() const;
-  virtual bool HasResolvedTypeClass() const;  // Own type class resolved.
+  virtual bool HasTypeClass() const {
+    ASSERT(type_class_id() != kIllegalCid);
+    return true;
+  }
   virtual classid_t type_class_id() const;
   virtual RawClass* type_class() const;
   void set_type_class(const Class& value) const;
-  void set_unresolved_class(const Object& value) const;
-  virtual RawUnresolvedClass* unresolved_class() const;
   virtual RawTypeArguments* arguments() const { return raw_ptr()->arguments_; }
   virtual void set_arguments(const TypeArguments& value) const;
   virtual TokenPosition token_pos() const { return raw_ptr()->token_pos_; }
@@ -6529,9 +6594,6 @@
   // The 'int' type.
   static RawType* IntType();
 
-  // The '_int64' type.
-  static RawType* Int64Type();
-
   // The 'Smi' type.
   static RawType* SmiType();
 
@@ -6568,7 +6630,7 @@
   // The finalized type of the given non-parameterized class.
   static RawType* NewNonParameterizedType(const Class& type_class);
 
-  static RawType* New(const Object& clazz,
+  static RawType* New(const Class& clazz,
                       const TypeArguments& arguments,
                       TokenPosition token_pos,
                       Heap::Space space = Heap::kOld);
@@ -6617,9 +6679,9 @@
     return AbstractType::Handle(type()).error();
   }
   virtual bool IsResolved() const { return true; }
-  virtual bool HasResolvedTypeClass() const {
+  virtual bool HasTypeClass() const {
     return (type() != AbstractType::null()) &&
-           AbstractType::Handle(type()).HasResolvedTypeClass();
+           AbstractType::Handle(type()).HasTypeClass();
   }
   RawAbstractType* type() const { return raw_ptr()->type_; }
   void set_type(const AbstractType& value) const;
@@ -6695,7 +6757,8 @@
   virtual bool IsMalbounded() const { return false; }
   virtual bool IsMalformedOrMalbounded() const { return false; }
   virtual bool IsResolved() const { return true; }
-  virtual bool HasResolvedTypeClass() const { return false; }
+  virtual bool HasTypeClass() const { return false; }
+  virtual classid_t type_class_id() const { return kIllegalCid; }
   classid_t parameterized_class_id() const;
   RawClass* parameterized_class() const;
   RawFunction* parameterized_function() const {
@@ -6798,8 +6861,8 @@
   virtual bool IsMalformedOrMalbounded() const;
   virtual RawLanguageError* error() const;
   virtual bool IsResolved() const { return true; }
-  virtual bool HasResolvedTypeClass() const {
-    return AbstractType::Handle(type()).HasResolvedTypeClass();
+  virtual bool HasTypeClass() const {
+    return AbstractType::Handle(type()).HasTypeClass();
   }
   virtual classid_t type_class_id() const {
     return AbstractType::Handle(type()).type_class_id();
@@ -6807,9 +6870,6 @@
   virtual RawClass* type_class() const {
     return AbstractType::Handle(type()).type_class();
   }
-  virtual RawUnresolvedClass* unresolved_class() const {
-    return AbstractType::Handle(type()).unresolved_class();
-  }
   virtual RawTypeArguments* arguments() const {
     return AbstractType::Handle(type()).arguments();
   }
@@ -6895,7 +6955,7 @@
   virtual bool IsMalbounded() const { return false; }
   virtual bool IsMalformedOrMalbounded() const { return false; }
   virtual bool IsResolved() const { return false; }
-  virtual bool HasResolvedTypeClass() const { return false; }
+  virtual bool HasTypeClass() const { return false; }
   virtual RawString* Name() const;
   virtual TokenPosition token_pos() const;
 
@@ -7287,8 +7347,6 @@
 
   uint16_t CharAt(intptr_t index) const;
 
-  Scanner::CharAtFunc CharAtFunc() const;
-
   intptr_t CharSize() const;
 
   inline bool Equals(const String& str) const;
@@ -8017,9 +8075,9 @@
   // architecture.
   static const intptr_t kHashBits = 30;
 
-  intptr_t Length() const {
-    ASSERT(!IsNull());
-    return Smi::Value(raw_ptr()->length_);
+  intptr_t Length() const { return LengthOf(raw()); }
+  static intptr_t LengthOf(const RawArray* array) {
+    return Smi::Value(array->ptr()->length_);
   }
   static intptr_t length_offset() { return OFFSET_OF(RawArray, length_); }
   static intptr_t data_offset() {
@@ -8029,10 +8087,19 @@
     return OFFSET_OF_RETURNED_VALUE(RawArray, data) + kWordSize * index;
   }
 
+  static bool Equals(RawArray* a, RawArray* b) {
+    if (a == b) return true;
+    if (a->IsRawNull() || b->IsRawNull()) return false;
+    if (a->ptr()->length_ != b->ptr()->length_) return false;
+    if (a->ptr()->type_arguments_ != b->ptr()->type_arguments_) return false;
+    const intptr_t length = LengthOf(a);
+    return memcmp(a->ptr()->data(), b->ptr()->data(), kWordSize * length) == 0;
+  }
+
   RawObject* At(intptr_t index) const { return *ObjectAddr(index); }
   void SetAt(intptr_t index, const Object& value) const {
     // TODO(iposva): Add storing NoSafepointScope.
-    StorePointer(ObjectAddr(index), value.raw());
+    StoreArrayPointer(ObjectAddr(index), value.raw());
   }
 
   bool IsImmutable() const { return raw()->GetClassId() == kImmutableArrayCid; }
@@ -8049,7 +8116,7 @@
             value.IsInstantiated() /*&& value.IsCanonical()*/));
     // TODO(asiva): Values read from a message snapshot are not properly marked
     // as canonical. See for example tests/isolate/mandel_isolate_test.dart.
-    StorePointer(&raw_ptr()->type_arguments_, value.raw());
+    StoreArrayPointer(&raw_ptr()->type_arguments_, value.raw());
   }
 
   virtual bool CanonicalizeEquals(const Instance& other) const;
@@ -8131,6 +8198,26 @@
     StoreSmi(&raw_ptr()->length_, Smi::New(value));
   }
 
+  template <typename type>
+  void StoreArrayPointer(type const* addr, type value) const {
+    raw()->StoreArrayPointer(addr, value);
+  }
+
+  // Store a range of pointers [from, from + count) into [to, to + count).
+  // TODO(koda): Use this to fix Object::Clone's broken store buffer logic.
+  void StoreArrayPointers(RawObject* const* to,
+                          RawObject* const* from,
+                          intptr_t count) {
+    ASSERT(Contains(reinterpret_cast<uword>(to)));
+    if (raw()->IsNewObject()) {
+      memmove(const_cast<RawObject**>(to), from, count * kWordSize);
+    } else {
+      for (intptr_t i = 0; i < count; ++i) {
+        StoreArrayPointer(&to[i], from[i]);
+      }
+    }
+  }
+
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Array, Instance);
   friend class Class;
   friend class ImmutableArray;
@@ -8203,7 +8290,7 @@
     ASSERT(index < Length());
 
     // TODO(iposva): Add storing NoSafepointScope.
-    data()->StorePointer(ObjectAddr(index), value.raw());
+    data()->StoreArrayPointer(ObjectAddr(index), value.raw());
   }
 
   void Add(const Object& value, Heap::Space space = Heap::kNew) const;
@@ -8566,6 +8653,10 @@
 
 class ExternalTypedData : public Instance {
  public:
+  // Alignment of data when serializing ExternalTypedData in a clustered
+  // snapshot. Should be independent of word size.
+  static const int kDataSerializationAlignment = 8;
+
   intptr_t Length() const {
     ASSERT(!IsNull());
     return Smi::Value(raw_ptr()->length_);
@@ -9024,8 +9115,8 @@
   void set_expand_inlined(bool value) const;
 
   RawArray* code_array() const { return raw_ptr()->code_array_; }
-  RawCode* CodeAtFrame(intptr_t frame_index) const;
-  void SetCodeAtFrame(intptr_t frame_index, const Code& code) const;
+  RawObject* CodeAtFrame(intptr_t frame_index) const;
+  void SetCodeAtFrame(intptr_t frame_index, const Object& code) const;
 
   RawArray* pc_offset_array() const { return raw_ptr()->pc_offset_array_; }
   RawSmi* PcOffsetAtFrame(intptr_t frame_index) const;
@@ -9491,6 +9582,138 @@
   StoreSmi(&raw_ptr()->hash_, Smi::New(value));
 }
 
+// A view on an [Array] as a list of tuples, optionally starting at an offset.
+//
+// Example: We store a list of (kind, function, code) tuples into the
+// [Code::static_calls_target_table] array of type [Array].
+//
+// This helper class can then be used via
+//
+//     using CallTableView = ArrayOfTuplesVied<
+//         Code::Kind, std::tuple<Smi, Function, Code>>;
+//
+//     auto& array = Array::Handle(code.static_calls_targets_table());
+//     CallTableView static_calls(array);
+//
+//     // Using convenient for loop.
+//     auto& function = Function::Handle();
+//     for (auto& call : static_calls) {
+//       function = call.Get<Code::kSCallTableFunctionTarget>();
+//       call.Set<Code::kSCallTableFunctionTarget>(function);
+//     }
+//
+//     // Using manual loop.
+//     auto& function = Function::Handle();
+//     for (intptr_t i = 0; i < static_calls.Length(); ++i) {
+//       auto call = static_calls[i];
+//       function = call.Get<Code::kSCallTableFunctionTarget>();
+//       call.Set<Code::kSCallTableFunctionTarget>(function);
+//     }
+//
+//
+// Template parameters:
+//
+//   * [EnumType] must be a normal enum which enumerates the entries of the
+//     tuple
+//
+//   * [kStartOffset] is the offset at which the first tuple in the array
+//     starts (can be 0).
+//
+//   * [TupleT] must be a std::tuple<...> where "..." are the heap object handle
+//     classes (e.g. 'Code', 'Smi', 'Object')
+template <typename EnumType, typename TupleT, int kStartOffset = 0>
+class ArrayOfTuplesView {
+ public:
+  static constexpr intptr_t EntrySize = std::tuple_size<TupleT>::value;
+
+  class Iterator;
+
+  class TupleView {
+   public:
+    TupleView(const Array& array, intptr_t index)
+        : array_(array), index_(index) {}
+
+    template <EnumType kElement>
+    typename std::tuple_element<kElement, TupleT>::type::RawObjectType* Get()
+        const {
+      using object_type = typename std::tuple_element<kElement, TupleT>::type;
+      return object_type::RawCast(array_.At(index_ + kElement));
+    }
+
+    template <EnumType kElement>
+    void Set(const typename std::tuple_element<kElement, TupleT>::type& value)
+        const {
+      array_.SetAt(index_ + kElement, value);
+    }
+
+    intptr_t index() const { return (index_ - kStartOffset) / EntrySize; }
+
+   private:
+    const Array& array_;
+    intptr_t index_;
+
+    friend class Iterator;
+  };
+
+  class Iterator {
+   public:
+    Iterator(const Array& array, intptr_t index) : entry_(array, index) {}
+
+    bool operator==(const Iterator& other) {
+      return entry_.index_ == other.entry_.index_;
+    }
+    bool operator!=(const Iterator& other) {
+      return entry_.index_ != other.entry_.index_;
+    }
+
+    const TupleView& operator*() const { return entry_; }
+
+    Iterator& operator++() {
+      entry_.index_ += EntrySize;
+      return *this;
+    }
+
+   private:
+    TupleView entry_;
+  };
+
+  explicit ArrayOfTuplesView(const Array& array) : array_(array), index_(-1) {
+    ASSERT(array.Length() >= kStartOffset);
+    ASSERT((array.Length() - kStartOffset) % EntrySize == kStartOffset);
+  }
+
+  intptr_t Length() const {
+    return (array_.Length() - kStartOffset) / EntrySize;
+  }
+
+  TupleView At(intptr_t i) const {
+    return TupleView(array_, kStartOffset + i * EntrySize);
+  }
+
+  TupleView operator[](intptr_t i) const { return At(i); }
+
+  Iterator begin() const { return Iterator(array_, kStartOffset); }
+
+  Iterator end() const {
+    return Iterator(array_, kStartOffset + Length() * EntrySize);
+  }
+
+ private:
+  const Array& array_;
+  intptr_t index_;
+};
+
+using StaticCallsTable =
+    ArrayOfTuplesView<Code::SCallTableEntry, std::tuple<Smi, Code, Function>>;
+using SubtypeTestCacheTable = ArrayOfTuplesView<SubtypeTestCache::Entries,
+                                                std::tuple<Object,
+                                                           Object,
+                                                           TypeArguments,
+                                                           TypeArguments,
+                                                           TypeArguments,
+                                                           TypeArguments,
+                                                           TypeArguments>>;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_OBJECT_H_
diff --git a/runtime/vm/object_id_ring_test.cc b/runtime/vm/object_id_ring_test.cc
index d1c8801..92d3400 100644
--- a/runtime/vm/object_id_ring_test.cc
+++ b/runtime/vm/object_id_ring_test.cc
@@ -176,7 +176,11 @@
   EXPECT_NE(RawObject::ToAddr(raw_obj1), RawObject::ToAddr(raw_object_moved1));
   EXPECT_NE(RawObject::ToAddr(raw_obj2), RawObject::ToAddr(raw_object_moved2));
   // Test that we still point at the same list.
-  Dart_Handle moved_handle = Api::NewHandle(thread, raw_object_moved1);
+  Dart_Handle moved_handle;
+  {
+    TransitionNativeToVM transition(thread);
+    moved_handle = Api::NewHandle(thread, raw_object_moved1);
+  }
   EXPECT_VALID(moved_handle);
   EXPECT(!Dart_IsNull(moved_handle));
   EXPECT(Dart_IsList(moved_handle));
@@ -197,7 +201,7 @@
   intptr_t raw_obj_id1 = -1;
   intptr_t raw_obj_id2 = -1;
   {
-    Dart_EnterScope();
+    Api::Scope api_scope(thread);
     Dart_Handle result;
     // Create a string in the old heap.
     result = Api::NewHandle(thread, String::New("old", Heap::kOld));
@@ -225,7 +229,6 @@
     EXPECT_EQ(RawObject::ToAddr(raw_obj), RawObject::ToAddr(raw_obj1));
     EXPECT_EQ(RawObject::ToAddr(raw_obj), RawObject::ToAddr(raw_obj2));
     // Exit scope. Freeing result handle.
-    Dart_ExitScope();
   }
   // Force a GC. No reference exist to the old string anymore. It should be
   // collected and the object id ring will now return the null object for
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index bc78047..e63ed7a 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -82,14 +82,29 @@
   }
 #else
   const ObjectPool& pool = ObjectPool::Handle(zone, object_pool());
-  Object& object = Object::Handle(zone);
   ASSERT(!pool.IsNull());
-  for (intptr_t i = 0; i < pool.Length(); i++) {
-    ObjectPool::EntryType entry_type = pool.TypeAt(i);
+  pool.ResetICDatas(zone);
+#endif
+}
+
+void Bytecode::ResetICDatas(Zone* zone) const {
+  // Iterate over the Bytecode's object pool and reset all ICDatas.
+  const ObjectPool& pool = ObjectPool::Handle(zone, object_pool());
+  ASSERT(!pool.IsNull());
+  pool.ResetICDatas(zone);
+}
+
+void ObjectPool::ResetICDatas(Zone* zone) const {
+#ifdef TARGET_ARCH_IA32
+  UNREACHABLE();
+#else
+  Object& object = Object::Handle(zone);
+  for (intptr_t i = 0; i < Length(); i++) {
+    ObjectPool::EntryType entry_type = TypeAt(i);
     if (entry_type != ObjectPool::kTaggedObject) {
       continue;
     }
-    object = pool.ObjectAt(i);
+    object = ObjectAt(i);
     if (object.IsICData()) {
       ICData::Cast(object).Reset(zone);
     }
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index d82135f..fe68a1b 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -173,10 +173,6 @@
   }
 }
 
-void UnresolvedClass::PrintJSONImpl(JSONStream* stream, bool ref) const {
-  Object::PrintJSONImpl(stream, ref);
-}
-
 void TypeArguments::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   // The index in the canonical_type_arguments table cannot be used as part of
@@ -312,6 +308,12 @@
   if (!code.IsNull()) {
     jsobj.AddProperty("code", code);
   }
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  Bytecode& bytecode = Bytecode::Handle(this->bytecode());
+  if (!bytecode.IsNull()) {
+    jsobj.AddProperty("_bytecode", bytecode);
+  }
+#endif  // !DART_PRECOMPILED_RUNTIME
   Array& ics = Array::Handle(ic_data_array());
   if (!ics.IsNull()) {
     jsobj.AddProperty("_icDataArray", ics);
@@ -788,6 +790,8 @@
 }
 
 void Code::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  // N.B. This is polymorphic with Bytecode.
+
   JSONObject jsobj(stream);
   AddCommonObjectProperties(&jsobj, "Code", ref);
   jsobj.AddFixedServiceId("code/%" Px64 "-%" Px "", compile_timestamp(),
@@ -853,6 +857,47 @@
 #endif
 }
 
+void Bytecode::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  // N.B. This is polymorphic with Code.
+
+  JSONObject jsobj(stream);
+  AddCommonObjectProperties(&jsobj, "Code", ref);
+  int64_t compile_timestamp = 0;
+  jsobj.AddFixedServiceId("code/%" Px64 "-%" Px "", compile_timestamp,
+                          PayloadStart());
+  const char* qualified_name = QualifiedName();
+  const char* vm_name = Name();
+  AddNameProperties(&jsobj, qualified_name, vm_name);
+
+  jsobj.AddProperty("kind", "Dart");
+  jsobj.AddProperty("_optimized", false);
+  jsobj.AddProperty("_intrinsic", false);
+  jsobj.AddProperty("_native", false);
+  if (ref) {
+    return;
+  }
+  const Function& fun = Function::Handle(function());
+  jsobj.AddProperty("function", fun);
+  jsobj.AddPropertyF("_startAddress", "%" Px "", PayloadStart());
+  jsobj.AddPropertyF("_endAddress", "%" Px "", PayloadStart() + Size());
+  jsobj.AddProperty("_alive", true);
+  const ObjectPool& obj_pool = ObjectPool::Handle(object_pool());
+  jsobj.AddProperty("_objectPool", obj_pool);
+  {
+    JSONArray jsarr(&jsobj, "_disassembly");
+    DisassembleToJSONStream formatter(jsarr);
+    Disassemble(&formatter);
+  }
+  const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
+  if (!descriptors.IsNull()) {
+    JSONObject desc(&jsobj, "_descriptors");
+    descriptors.PrintToJSONObject(&desc, false);
+  }
+
+  { JSONArray inlined_functions(&jsobj, "_inlinedFunctions"); }
+  { JSONArray inline_intervals(&jsobj, "_inlinedIntervals"); }
+}
+
 void Context::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   // TODO(turnidge): Should the user level type for Context be Context
@@ -1057,18 +1102,14 @@
   JSONObject jsobj(stream);
   PrintSharedInstanceJSON(&jsobj, ref);
   jsobj.AddProperty("kind", "Type");
-  if (HasResolvedTypeClass()) {
-    const Class& type_cls = Class::Handle(type_class());
-    if (type_cls.CanonicalType() == raw()) {
-      intptr_t cid = type_cls.id();
-      jsobj.AddFixedServiceId("classes/%" Pd "/types/%d", cid, 0);
-    } else {
-      jsobj.AddServiceId(*this);
-    }
-    jsobj.AddProperty("typeClass", type_cls);
+  const Class& type_cls = Class::Handle(type_class());
+  if (type_cls.CanonicalType() == raw()) {
+    intptr_t cid = type_cls.id();
+    jsobj.AddFixedServiceId("classes/%" Pd "/types/%d", cid, 0);
   } else {
     jsobj.AddServiceId(*this);
   }
+  jsobj.AddProperty("typeClass", type_cls);
   const String& user_name = String::Handle(UserVisibleName());
   const String& vm_name = String::Handle(Name());
   AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 0428856..c43828a 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2249,9 +2249,6 @@
   const char* kScript = "main() {}";
   Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(h_lib);
-  Library& lib = Library::Handle();
-  lib ^= Api::UnwrapHandle(h_lib);
-  EXPECT(!lib.IsNull());
   Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
   EXPECT_VALID(result);
 }
@@ -2431,13 +2428,14 @@
 
 ISOLATE_UNIT_TEST_CASE(CheckedHandle) {
   // Ensure that null handles have the correct C++ vtable setup.
-  const String& str1 = String::Handle();
+  Zone* zone = Thread::Current()->zone();
+  const String& str1 = String::Handle(zone);
   EXPECT(str1.IsString());
   EXPECT(str1.IsNull());
-  const String& str2 = String::CheckedHandle(Object::null());
+  const String& str2 = String::CheckedHandle(zone, Object::null());
   EXPECT(str2.IsString());
   EXPECT(str2.IsNull());
-  String& str3 = String::Handle();
+  String& str3 = String::Handle(zone);
   str3 ^= Object::null();
   EXPECT(str3.IsString());
   EXPECT(str3.IsNull());
@@ -2476,8 +2474,8 @@
   Assembler _assembler_(&object_pool_wrapper);
   GenerateIncrement(&_assembler_);
   const Function& function = Function::Handle(CreateFunction("Test_Code"));
-  Code& code =
-      Code::Handle(Code::FinalizeCode(function, nullptr, &_assembler_));
+  Code& code = Code::Handle(Code::FinalizeCode(
+      function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
   function.AttachCode(code);
   const Instructions& instructions = Instructions::Handle(code.instructions());
   uword payload_start = instructions.PayloadStart();
@@ -2498,8 +2496,8 @@
   Assembler _assembler_(&object_pool_wrapper);
   GenerateIncrement(&_assembler_);
   const Function& function = Function::Handle(CreateFunction("Test_Code"));
-  Code& code =
-      Code::Handle(Code::FinalizeCode(function, nullptr, &_assembler_));
+  Code& code = Code::Handle(Code::FinalizeCode(
+      function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
   function.AttachCode(code);
   Instructions& instructions = Instructions::Handle(code.instructions());
   uword payload_start = instructions.PayloadStart();
@@ -2526,8 +2524,8 @@
   GenerateEmbedStringInCode(&_assembler_, kHello);
   const Function& function =
       Function::Handle(CreateFunction("Test_EmbedStringInCode"));
-  const Code& code =
-      Code::Handle(Code::FinalizeCode(function, nullptr, &_assembler_));
+  const Code& code = Code::Handle(Code::FinalizeCode(
+      function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
   function.AttachCode(code);
   const Object& result =
       Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
@@ -2549,8 +2547,8 @@
   GenerateEmbedSmiInCode(&_assembler_, kSmiTestValue);
   const Function& function =
       Function::Handle(CreateFunction("Test_EmbedSmiInCode"));
-  const Code& code =
-      Code::Handle(Code::FinalizeCode(function, nullptr, &_assembler_));
+  const Code& code = Code::Handle(Code::FinalizeCode(
+      function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
   function.AttachCode(code);
   const Object& result =
       Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
@@ -2567,8 +2565,8 @@
   GenerateEmbedSmiInCode(&_assembler_, kSmiTestValue);
   const Function& function =
       Function::Handle(CreateFunction("Test_EmbedSmiIn64BitCode"));
-  const Code& code =
-      Code::Handle(Code::FinalizeCode(function, nullptr, &_assembler_));
+  const Code& code = Code::Handle(Code::FinalizeCode(
+      function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
   function.AttachCode(code);
   const Object& result =
       Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
@@ -2596,8 +2594,9 @@
   ObjectPoolWrapper object_pool_wrapper;
   Assembler _assembler_(&object_pool_wrapper);
   GenerateIncrement(&_assembler_);
-  Code& code = Code::Handle(Code::FinalizeCode(
-      Function::Handle(CreateFunction("Test_Code")), nullptr, &_assembler_));
+  Code& code = Code::Handle(
+      Code::FinalizeCode(Function::Handle(CreateFunction("Test_Code")), nullptr,
+                         &_assembler_, Code::PoolAttachment::kAttachPool));
   code.set_exception_handlers(exception_handlers);
 
   // Verify the exception handler table entries by accessing them.
@@ -2637,8 +2636,9 @@
   ObjectPoolWrapper object_pool_wrapper;
   Assembler _assembler_(&object_pool_wrapper);
   GenerateIncrement(&_assembler_);
-  Code& code = Code::Handle(Code::FinalizeCode(
-      Function::Handle(CreateFunction("Test_Code")), nullptr, &_assembler_));
+  Code& code = Code::Handle(
+      Code::FinalizeCode(Function::Handle(CreateFunction("Test_Code")), nullptr,
+                         &_assembler_, Code::PoolAttachment::kAttachPool));
   code.set_pc_descriptors(descriptors);
 
   // Verify the PcDescriptor entries by accessing them.
@@ -2699,8 +2699,9 @@
   ObjectPoolWrapper object_pool_wrapper;
   Assembler _assembler_(&object_pool_wrapper);
   GenerateIncrement(&_assembler_);
-  Code& code = Code::Handle(Code::FinalizeCode(
-      Function::Handle(CreateFunction("Test_Code")), nullptr, &_assembler_));
+  Code& code = Code::Handle(
+      Code::FinalizeCode(Function::Handle(CreateFunction("Test_Code")), nullptr,
+                         &_assembler_, Code::PoolAttachment::kAttachPool));
   code.set_pc_descriptors(descriptors);
 
   // Verify the PcDescriptor entries by accessing them.
@@ -3831,7 +3832,7 @@
   Dart_Handle result = Dart_Invoke(lib, NewString("test"), 0, NULL);
   EXPECT_VALID(result);
 
-  Function& func_b = Function::Handle();
+  // With no breakpoint, function A.b is inlineable.
   {
     TransitionNativeToVM transition(thread);
     const String& name = String::Handle(String::New(TestCase::url()));
@@ -3840,16 +3841,25 @@
     EXPECT(!vmlib.IsNull());
     const Class& class_a = Class::Handle(
         vmlib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
-    func_b = GetFunction(class_a, "b");
+    Function& func_b = Function::Handle(GetFunction(class_a, "b"));
+    EXPECT(func_b.CanBeInlined());
   }
 
-  // With no breakpoint, function A.b is inlineable.
-  EXPECT(func_b.CanBeInlined());
-
-  // After setting a breakpoint in a function A.b, it is no longer inlineable.
   result = Dart_SetBreakpoint(NewString(TestCase::url()), kBreakpointLine);
   EXPECT_VALID(result);
-  EXPECT(!func_b.CanBeInlined());
+
+  // After setting a breakpoint in a function A.b, it is no longer inlineable.
+  {
+    TransitionNativeToVM transition(thread);
+    const String& name = String::Handle(String::New(TestCase::url()));
+    const Library& vmlib =
+        Library::Handle(Library::LookupLibrary(thread, name));
+    EXPECT(!vmlib.IsNull());
+    const Class& class_a = Class::Handle(
+        vmlib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
+    Function& func_b = Function::Handle(GetFunction(class_a, "b"));
+    EXPECT(!func_b.CanBeInlined());
+  }
 }
 
 ISOLATE_UNIT_TEST_CASE(SpecialClassesHaveEmptyArrays) {
@@ -4191,13 +4201,12 @@
 
   Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(h_lib);
-  Library& lib = Library::Handle();
-  lib ^= Api::UnwrapHandle(h_lib);
-  EXPECT(!lib.IsNull());
   Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
   EXPECT_VALID(result);
 
   TransitionNativeToVM transition(thread);
+  Library& lib = Library::Handle();
+  lib ^= Api::UnwrapHandle(h_lib);
   const Class& clazz = Class::Handle(GetClass(lib, "A"));
   EXPECT(!clazz.IsNull());
   const Instance& a0 = Instance::Handle(Instance::New(clazz));
@@ -4218,15 +4227,12 @@
 
   Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(h_lib);
-  Library& lib = Library::Handle();
-  lib ^= Api::UnwrapHandle(h_lib);
-  EXPECT(!lib.IsNull());
   Dart_Handle h_result = Dart_Invoke(h_lib, NewString("foo"), 0, NULL);
   EXPECT_VALID(h_result);
-  Integer& result = Integer::Handle();
-  result ^= Api::UnwrapHandle(h_result);
 
   TransitionNativeToVM transition(thread);
+  Integer& result = Integer::Handle();
+  result ^= Api::UnwrapHandle(h_result);
   String& foo = String::Handle(String::New("foo"));
   Integer& expected = Integer::Handle();
   expected ^= foo.HashCode();
@@ -4286,9 +4292,6 @@
       "}";
   Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(h_lib);
-  Library& lib = Library::Handle();
-  lib ^= Api::UnwrapHandle(h_lib);
-  EXPECT(!lib.IsNull());
   Dart_Handle h_result = Dart_Invoke(h_lib, NewString("makeMap"), 0, NULL);
   EXPECT_VALID(h_result);
 
@@ -4313,12 +4316,10 @@
       "}";
   Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(h_lib);
-  Library& lib = Library::Handle();
-  lib ^= Api::UnwrapHandle(h_lib);
-  EXPECT(!lib.IsNull());
   Dart_Handle h_result = Dart_Invoke(h_lib, NewString("makeMap"), 0, NULL);
   EXPECT_VALID(h_result);
 
+  TransitionNativeToVM transition(thread);
   Instance& dart_map = Instance::Handle();
   dart_map ^= Api::UnwrapHandle(h_result);
   ASSERT(dart_map.IsLinkedHashMap());
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 0ff1668..54bda8a 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -324,6 +324,8 @@
   int i = 0;
   if (str[0] == '-') {
     i = 1;
+  } else if (str[0] == '+') {
+    i = 1;
   }
   if ((str[i] == '0') && (str[i + 1] == 'x' || str[i + 1] == 'X') &&
       (str[i + 2] != '\0')) {
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index 7f4ff12..70094af 100644
--- a/runtime/vm/os_fuchsia.cc
+++ b/runtime/vm/os_fuchsia.cc
@@ -222,6 +222,8 @@
   int i = 0;
   if (str[0] == '-') {
     i = 1;
+  } else if (str[0] == '+') {
+    i = 1;
   }
   if ((str[i] == '0') && (str[i + 1] == 'x' || str[i + 1] == 'X') &&
       (str[i + 2] != '\0')) {
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index 1d48dad..1079bdb 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -620,6 +620,8 @@
   int i = 0;
   if (str[0] == '-') {
     i = 1;
+  } else if (str[0] == '+') {
+    i = 1;
   }
   if ((str[i] == '0') && (str[i + 1] == 'x' || str[i + 1] == 'X') &&
       (str[i + 2] != '\0')) {
diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc
index 05813dc..16ce7e8 100644
--- a/runtime/vm/os_macos.cc
+++ b/runtime/vm/os_macos.cc
@@ -270,6 +270,8 @@
   int i = 0;
   if (str[0] == '-') {
     i = 1;
+  } else if (str[0] == '+') {
+    i = 1;
   }
   if ((str[i] == '0') && (str[i + 1] == 'x' || str[i + 1] == 'X') &&
       (str[i + 2] != '\0')) {
diff --git a/runtime/vm/os_thread_win.cc b/runtime/vm/os_thread_win.cc
index 5f75a32..56b5e2f 100644
--- a/runtime/vm/os_thread_win.cc
+++ b/runtime/vm/os_thread_win.cc
@@ -51,8 +51,6 @@
   uword parameter = data->parameter();
   delete data;
 
-  MonitorData::GetMonitorWaitDataForThread();
-
   // Create new OSThread object and set as TLS for new thread.
   OSThread* thread = OSThread::CreateOSThread();
   if (thread != NULL) {
@@ -63,9 +61,6 @@
     function(parameter);
   }
 
-  // Clean up the monitor wait data for this thread.
-  MonitorWaitData::ThreadExit();
-
   return 0;
 }
 
@@ -220,15 +215,7 @@
     : name_(name)
 #endif
 {
-  // Allocate unnamed semaphore with initial count 1 and max count 1.
-  data_.semaphore_ = CreateSemaphore(NULL, 1, 1, NULL);
-  if (data_.semaphore_ == NULL) {
-#if defined(PRODUCT)
-    FATAL1("Mutex allocation failed %d", GetLastError());
-#else
-    FATAL2("[%s] Mutex allocation failed %d", name_, GetLastError());
-#endif
-  }
+  InitializeSRWLock(&data_.lock_);
 #if defined(DEBUG)
   // When running with assertions enabled we do track the owner.
   owner_ = OSThread::kInvalidThreadId;
@@ -236,7 +223,6 @@
 }
 
 Mutex::~Mutex() {
-  CloseHandle(data_.semaphore_);
 #if defined(DEBUG)
   // When running with assertions enabled we do track the owner.
   ASSERT(owner_ == OSThread::kInvalidThreadId);
@@ -244,10 +230,7 @@
 }
 
 void Mutex::Lock() {
-  DWORD result = WaitForSingleObject(data_.semaphore_, INFINITE);
-  if (result != WAIT_OBJECT_0) {
-    FATAL1("Mutex lock failed %d", GetLastError());
-  }
+  AcquireSRWLockExclusive(&data_.lock_);
 #if defined(DEBUG)
   // When running with assertions enabled we do track the owner.
   owner_ = OSThread::GetCurrentThreadId();
@@ -255,19 +238,13 @@
 }
 
 bool Mutex::TryLock() {
-  // Attempt to pass the semaphore but return immediately.
-  DWORD result = WaitForSingleObject(data_.semaphore_, 0);
-  if (result == WAIT_OBJECT_0) {
+  if (TryAcquireSRWLockExclusive(&data_.lock_) != 0) {
 #if defined(DEBUG)
     // When running with assertions enabled we do track the owner.
     owner_ = OSThread::GetCurrentThreadId();
 #endif  // defined(DEBUG)
     return true;
   }
-  if (result == WAIT_ABANDONED || result == WAIT_FAILED) {
-    FATAL1("Mutex try lock failed %d", GetLastError());
-  }
-  ASSERT(result == WAIT_TIMEOUT);
   return false;
 }
 
@@ -277,20 +254,12 @@
   ASSERT(IsOwnedByCurrentThread());
   owner_ = OSThread::kInvalidThreadId;
 #endif  // defined(DEBUG)
-  BOOL result = ReleaseSemaphore(data_.semaphore_, 1, NULL);
-  if (result == 0) {
-    FATAL1("Mutex unlock failed %d", GetLastError());
-  }
+  ReleaseSRWLockExclusive(&data_.lock_);
 }
 
-ThreadLocalKey MonitorWaitData::monitor_wait_data_key_ = kUnsetThreadLocalKey;
-
 Monitor::Monitor() {
-  InitializeCriticalSection(&data_.cs_);
-  InitializeCriticalSection(&data_.waiters_cs_);
-  data_.waiters_head_ = NULL;
-  data_.waiters_tail_ = NULL;
-
+  InitializeSRWLock(&data_.lock_);
+  InitializeConditionVariable(&data_.cond_);
 #if defined(DEBUG)
   // When running with assertions enabled we track the owner.
   owner_ = OSThread::kInvalidThreadId;
@@ -302,27 +271,23 @@
   // When running with assertions enabled we track the owner.
   ASSERT(owner_ == OSThread::kInvalidThreadId);
 #endif  // defined(DEBUG)
-
-  DeleteCriticalSection(&data_.cs_);
-  DeleteCriticalSection(&data_.waiters_cs_);
 }
 
 bool Monitor::TryEnter() {
   // Attempt to pass the semaphore but return immediately.
-  BOOL result = TryEnterCriticalSection(&data_.cs_);
-  if (!result) {
-    return false;
-  }
+  if (TryAcquireSRWLockExclusive(&data_.lock_) != 0) {
 #if defined(DEBUG)
-  // When running with assertions enabled we do track the owner.
-  ASSERT(owner_ == OSThread::kInvalidThreadId);
-  owner_ = OSThread::GetCurrentThreadId();
+    // When running with assertions enabled we do track the owner.
+    ASSERT(owner_ == OSThread::kInvalidThreadId);
+    owner_ = OSThread::GetCurrentThreadId();
 #endif  // defined(DEBUG)
-  return true;
+    return true;
+  }
+  return false;
 }
 
 void Monitor::Enter() {
-  EnterCriticalSection(&data_.cs_);
+  AcquireSRWLockExclusive(&data_.lock_);
 
 #if defined(DEBUG)
   // When running with assertions enabled we track the owner.
@@ -338,130 +303,7 @@
   owner_ = OSThread::kInvalidThreadId;
 #endif  // defined(DEBUG)
 
-  LeaveCriticalSection(&data_.cs_);
-}
-
-void MonitorWaitData::ThreadExit() {
-  if (MonitorWaitData::monitor_wait_data_key_ != kUnsetThreadLocalKey) {
-    uword raw_wait_data =
-        OSThread::GetThreadLocal(MonitorWaitData::monitor_wait_data_key_);
-    // Clear in case this is called a second time.
-    OSThread::SetThreadLocal(MonitorWaitData::monitor_wait_data_key_, 0);
-    if (raw_wait_data != 0) {
-      MonitorWaitData* wait_data =
-          reinterpret_cast<MonitorWaitData*>(raw_wait_data);
-      delete wait_data;
-    }
-  }
-}
-
-void MonitorData::AddWaiter(MonitorWaitData* wait_data) {
-  // Add the MonitorWaitData object to the list of objects waiting for
-  // this monitor.
-  EnterCriticalSection(&waiters_cs_);
-  if (waiters_tail_ == NULL) {
-    ASSERT(waiters_head_ == NULL);
-    waiters_head_ = waiters_tail_ = wait_data;
-  } else {
-    waiters_tail_->next_ = wait_data;
-    waiters_tail_ = wait_data;
-  }
-  LeaveCriticalSection(&waiters_cs_);
-}
-
-void MonitorData::RemoveWaiter(MonitorWaitData* wait_data) {
-  // Remove the MonitorWaitData object from the list of objects
-  // waiting for this monitor.
-  EnterCriticalSection(&waiters_cs_);
-  MonitorWaitData* previous = NULL;
-  MonitorWaitData* current = waiters_head_;
-  while (current != NULL) {
-    if (current == wait_data) {
-      if (waiters_head_ == waiters_tail_) {
-        waiters_head_ = waiters_tail_ = NULL;
-      } else if (current == waiters_head_) {
-        waiters_head_ = waiters_head_->next_;
-      } else if (current == waiters_tail_) {
-        ASSERT(previous != NULL);
-        waiters_tail_ = previous;
-        previous->next_ = NULL;
-      } else {
-        ASSERT(previous != NULL);
-        previous->next_ = current->next_;
-      }
-      // Clear next.
-      wait_data->next_ = NULL;
-      break;
-    }
-    previous = current;
-    current = current->next_;
-  }
-  LeaveCriticalSection(&waiters_cs_);
-}
-
-void MonitorData::SignalAndRemoveFirstWaiter() {
-  EnterCriticalSection(&waiters_cs_);
-  MonitorWaitData* first = waiters_head_;
-  if (first != NULL) {
-    // Remove from list.
-    if (waiters_head_ == waiters_tail_) {
-      waiters_tail_ = waiters_head_ = NULL;
-    } else {
-      waiters_head_ = waiters_head_->next_;
-    }
-    // Clear next.
-    first->next_ = NULL;
-    // Signal event.
-    BOOL result = SetEvent(first->event_);
-    if (result == 0) {
-      FATAL1("Monitor::Notify failed to signal event %d", GetLastError());
-    }
-  }
-  LeaveCriticalSection(&waiters_cs_);
-}
-
-void MonitorData::SignalAndRemoveAllWaiters() {
-  EnterCriticalSection(&waiters_cs_);
-  // Extract list to signal.
-  MonitorWaitData* current = waiters_head_;
-  // Clear list.
-  waiters_head_ = waiters_tail_ = NULL;
-  // Iterate and signal all events.
-  while (current != NULL) {
-    // Copy next.
-    MonitorWaitData* next = current->next_;
-    // Clear next.
-    current->next_ = NULL;
-    // Signal event.
-    BOOL result = SetEvent(current->event_);
-    if (result == 0) {
-      FATAL1("Failed to set event for NotifyAll %d", GetLastError());
-    }
-    current = next;
-  }
-  LeaveCriticalSection(&waiters_cs_);
-}
-
-MonitorWaitData* MonitorData::GetMonitorWaitDataForThread() {
-  // Ensure that the thread local key for monitor wait data objects is
-  // initialized.
-  ASSERT(MonitorWaitData::monitor_wait_data_key_ != kUnsetThreadLocalKey);
-
-  // Get the MonitorWaitData object containing the event for this
-  // thread from thread local storage. Create it if it does not exist.
-  uword raw_wait_data =
-      OSThread::GetThreadLocal(MonitorWaitData::monitor_wait_data_key_);
-  MonitorWaitData* wait_data = NULL;
-  if (raw_wait_data == 0) {
-    HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
-    wait_data = new MonitorWaitData(event);
-    OSThread::SetThreadLocal(MonitorWaitData::monitor_wait_data_key_,
-                             reinterpret_cast<uword>(wait_data));
-  } else {
-    wait_data = reinterpret_cast<MonitorWaitData*>(raw_wait_data);
-    ASSERT(wait_data->next_ == NULL);
-  }
-  return wait_data;
+  ReleaseSRWLockExclusive(&data_.lock_);
 }
 
 Monitor::WaitResult Monitor::Wait(int64_t millis) {
@@ -473,60 +315,17 @@
 #endif  // defined(DEBUG)
 
   Monitor::WaitResult retval = kNotified;
-
-  // Get the wait data object containing the event to wait for.
-  MonitorWaitData* wait_data = MonitorData::GetMonitorWaitDataForThread();
-
-  // Start waiting by adding the MonitorWaitData to the list of
-  // waiters.
-  data_.AddWaiter(wait_data);
-
-  // Leave the monitor critical section while waiting.
-  LeaveCriticalSection(&data_.cs_);
-
-  // Perform the actual wait on the event.
-  DWORD result = WAIT_FAILED;
-  if (millis == 0) {
-    // Wait forever for a Notify or a NotifyAll event.
-    result = WaitForSingleObject(wait_data->event_, INFINITE);
-    if (result == WAIT_FAILED) {
-      FATAL1("Monitor::Wait failed %d", GetLastError());
-    }
+  if (millis == kNoTimeout) {
+    SleepConditionVariableSRW(&data_.cond_, &data_.lock_, INFINITE, 0);
   } else {
     // Wait for the given period of time for a Notify or a NotifyAll
     // event.
-    result = WaitForSingleObject(wait_data->event_, millis);
-    if (result == WAIT_FAILED) {
-      FATAL1("Monitor::Wait with timeout failed %d", GetLastError());
-    }
-    if (result == WAIT_TIMEOUT) {
-      // No longer waiting. Remove from the list of waiters.
-      data_.RemoveWaiter(wait_data);
-      // Caveat: wait_data->event_ might have been signaled between
-      // WaitForSingleObject and RemoveWaiter because we are not in any critical
-      // section here. Leaving it in a signaled state would break invariants
-      // that Monitor::Wait code relies on. We assume that when
-      // WaitForSingleObject(wait_data->event_, ...) returns successfully then
-      // corresponding wait_data is not on the waiters list anymore.
-      // This is guaranteed because we only signal these events from
-      // SignalAndRemoveAllWaiters/SignalAndRemoveFirstWaiter which
-      // simultaneously remove MonitorWaitData from the list.
-      // Now imagine that wait_data->event_ is left signaled here. In this case
-      // the next WaitForSingleObject(wait_data->event_, ...) will immediately
-      // return while wait_data is still on the waiters list. This would
-      // leave waiters list in the inconsistent state.
-      // To prevent this from happening simply reset the event.
-      // Note: wait_data is no longer on the waiters list so it can't be
-      // signaled anymore at this point so there is no race possible from
-      // this point onward.
-      ResetEvent(wait_data->event_);
+    if (!SleepConditionVariableSRW(&data_.cond_, &data_.lock_, millis, 0)) {
+      ASSERT(GetLastError() == ERROR_TIMEOUT);
       retval = kTimedOut;
     }
   }
 
-  // Reacquire the monitor critical section before continuing.
-  EnterCriticalSection(&data_.cs_);
-
 #if defined(DEBUG)
   // When running with assertions enabled we track the owner.
   ASSERT(owner_ == OSThread::kInvalidThreadId);
@@ -551,18 +350,13 @@
 void Monitor::Notify() {
   // When running with assertions enabled we track the owner.
   ASSERT(IsOwnedByCurrentThread());
-  data_.SignalAndRemoveFirstWaiter();
+  WakeConditionVariable(&data_.cond_);
 }
 
 void Monitor::NotifyAll() {
   // When running with assertions enabled we track the owner.
   ASSERT(IsOwnedByCurrentThread());
-  // If one of the objects in the list of waiters wakes because of a
-  // timeout before we signal it, that object will get an extra
-  // signal. This will be treated as a spurious wake-up and is OK
-  // since all uses of monitors should recheck the condition after a
-  // Wait.
-  data_.SignalAndRemoveAllWaiters();
+  WakeAllConditionVariable(&data_.cond_);
 }
 
 void ThreadLocalData::AddThreadLocal(ThreadLocalKey key,
@@ -677,7 +471,6 @@
   // and on W2K and W2K3. So don't assume it is sent.
   if (DLL_THREAD_DETACH == reason || DLL_PROCESS_DETACH == reason) {
     dart::ThreadLocalData::RunDestructors();
-    dart::MonitorWaitData::ThreadExit();
   }
 }
 
diff --git a/runtime/vm/os_thread_win.h b/runtime/vm/os_thread_win.h
index 24f4031..8e1e917 100644
--- a/runtime/vm/os_thread_win.h
+++ b/runtime/vm/os_thread_win.h
@@ -44,7 +44,7 @@
   MutexData() {}
   ~MutexData() {}
 
-  HANDLE semaphore_;
+  SRWLOCK lock_;
 
   friend class Mutex;
 
@@ -52,64 +52,15 @@
   DISALLOW_COPY_AND_ASSIGN(MutexData);
 };
 
-class MonitorWaitData {
- public:
-  static void ThreadExit();
-
- private:
-  explicit MonitorWaitData(HANDLE event) : event_(event), next_(NULL) {}
-  ~MonitorWaitData() {
-    CloseHandle(event_);
-    ASSERT(next_ == NULL);
-  }
-
-  // ThreadLocalKey used to fetch and store the MonitorWaitData object
-  // for a given thread.
-  static ThreadLocalKey monitor_wait_data_key_;
-
-  // Auto-reset event used for waiting.
-  HANDLE event_;
-  // Link to next element in the singly-linked list of waiters.
-  MonitorWaitData* next_;
-
-  friend class Monitor;
-  friend class MonitorData;
-  friend class OS;
-
-  DISALLOW_COPY_AND_ASSIGN(MonitorWaitData);
-};
-
 class MonitorData {
  private:
   MonitorData() {}
   ~MonitorData() {}
 
-  // Helper methods to manipulate the list of waiters for this
-  // monitor.
-  void AddWaiter(MonitorWaitData* wait_data);
-  void RemoveWaiter(MonitorWaitData* wait_data);
-  void SignalAndRemoveFirstWaiter();
-  void SignalAndRemoveAllWaiters();
-  static MonitorWaitData* GetMonitorWaitDataForThread();
-
-  // The external critical section for the monitor.
-  CRITICAL_SECTION cs_;
-
-  // Condition variables are only available since Windows Vista. To
-  // support at least Windows XP, we implement our own condition
-  // variables using SetEvent on Event objects.
-
-  // Singly-linked list of event objects, one for each thread waiting
-  // on this monitor. New waiters are added at the end of the list.
-  // Notify signals the first element of the list (FIFO
-  // order). NotifyAll, signals all the elements of the list.
-  CRITICAL_SECTION waiters_cs_;
-  MonitorWaitData* waiters_head_;
-  MonitorWaitData* waiters_tail_;
+  SRWLOCK lock_;
+  CONDITION_VARIABLE cond_;
 
   friend class Monitor;
-  friend class OS;
-  friend unsigned int __stdcall ThreadEntry(void* data_ptr);
 
   DISALLOW_ALLOCATION();
   DISALLOW_COPY_AND_ASSIGN(MonitorData);
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc
index d01ccf9..8b8ce38 100644
--- a/runtime/vm/os_win.cc
+++ b/runtime/vm/os_win.cc
@@ -287,6 +287,8 @@
   int i = 0;
   if (str[0] == '-') {
     i = 1;
+  } else if (str[0] == '+') {
+    i = 1;
   }
   if ((str[i] == '0') && (str[i + 1] == 'x' || str[i + 1] == 'X') &&
       (str[i + 2] != '\0')) {
@@ -321,8 +323,6 @@
   // Do not pop up a message box when abort is called.
   _set_abort_behavior(0, _WRITE_ABORT_MSG);
   ThreadLocalData::Init();
-  MonitorWaitData::monitor_wait_data_key_ = OSThread::CreateThreadLocal();
-  MonitorData::GetMonitorWaitDataForThread();
   LARGE_INTEGER ticks_per_sec;
   if (!QueryPerformanceFrequency(&ticks_per_sec)) {
     qpc_ticks_per_second = 0;
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 199d018..a9e21d1 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -31,7 +31,6 @@
 #include "vm/os.h"
 #include "vm/regexp_assembler.h"
 #include "vm/resolver.h"
-#include "vm/scanner.h"
 #include "vm/scopes.h"
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 7ca6fa3..fbb891a 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -520,7 +520,6 @@
                           uword pc,
                           uword fp,
                           uword sp,
-                          bool exited_dart_code,
                           bool allocation_sample,
                           intptr_t skip_count = 0)
       : ProfilerStackWalker((thread->isolate() != NULL)
@@ -529,128 +528,126 @@
                             sample,
                             sample_buffer,
                             skip_count),
+        thread_(thread),
         pc_(reinterpret_cast<uword*>(pc)),
         fp_(reinterpret_cast<uword*>(fp)),
         sp_(reinterpret_cast<uword*>(sp)),
         stack_upper_(stack_upper),
-        stack_lower_(stack_lower),
-        has_exit_frame_(exited_dart_code) {
-    if (exited_dart_code) {
-// On Windows and Fuchsia the profiler does not run on the thread being
-// profiled.
-#if defined(HOST_OS_WINDOWS) || defined(HOST_OS_FUCHSIA)
-      const StackFrameIterator::CrossThreadPolicy cross_thread_policy =
-          StackFrameIterator::kAllowCrossThreadIteration;
+        stack_lower_(stack_lower) {}
+
+  bool IsInterpretedFrame(uword* fp) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    return false;
 #else
-      const StackFrameIterator::CrossThreadPolicy cross_thread_policy =
-          StackFrameIterator::kNoCrossThreadIteration;
+    Interpreter* interpreter = thread_->interpreter();
+    if (interpreter == nullptr) return false;
+    return interpreter->HasFrame(reinterpret_cast<uword>(fp));
 #endif
-      StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames, thread,
-                                  cross_thread_policy);
-      pc_ = NULL;
-      fp_ = NULL;
-      sp_ = NULL;
-      if (!iterator.HasNextFrame()) {
-        return;
-      }
-      // Ensure we are able to get to the exit frame.
-      StackFrame* frame = iterator.NextFrame();
-      if (!frame->IsExitFrame()) {
-        return;
-      }
-      // Skip the exit frame.
-      if (!iterator.HasNextFrame()) {
-        return;
-      }
-      frame = iterator.NextFrame();
-      // Record frame details of the first frame from which we start walking.
-      pc_ = reinterpret_cast<uword*>(frame->pc());
-      fp_ = reinterpret_cast<uword*>(frame->fp());
-      sp_ = reinterpret_cast<uword*>(frame->sp());
-      is_interpreted_frame_ = frame->is_interpreted();
-    }
   }
 
   void walk() {
-    sample_->set_exit_frame_sample(has_exit_frame_);
-    if (!ValidFramePointer()) {
+    RELEASE_ASSERT(StubCode::HasBeenInitialized());
+    if (thread_->isolate()->IsDeoptimizing()) {
       sample_->set_ignore_sample(true);
       return;
     }
-    ASSERT(ValidFramePointer());
-    uword return_pc = InitialReturnAddress();
-    if (StubCode::InInvocationStub(return_pc, is_interpreted_frame_)) {
-      // Edge case- we have called out from the Invocation Stub but have not
-      // created the stack frame of the callee. Attempt to locate the exit
-      // frame before walking the stack.
-      if (!NextExit() || !ValidFramePointer()) {
-        // Nothing to sample.
+
+    uword* exit_fp = reinterpret_cast<uword*>(thread_->top_exit_frame_info());
+    bool in_interpreted_frame;
+    bool has_exit_frame = exit_fp != 0;
+    if (has_exit_frame) {
+      if (IsInterpretedFrame(exit_fp)) {
+        // Exited from interpreter.
+        pc_ = 0;
+        fp_ = exit_fp;
+        in_interpreted_frame = true;
+        RELEASE_ASSERT(IsInterpretedFrame(fp_));
+      } else {
+        // Exited from compiled code.
+        pc_ = 0;
+        fp_ = exit_fp;
+        in_interpreted_frame = false;
+      }
+
+      // Skip exit frame.
+      pc_ = CallerPC(in_interpreted_frame);
+      fp_ = CallerFP(in_interpreted_frame);
+
+      // Can only move between interpreted and compiled frames after an exit
+      // frame.
+      RELEASE_ASSERT(IsInterpretedFrame(fp_) == in_interpreted_frame);
+    } else {
+      if (thread_->vm_tag() == VMTag::kDartCompiledTagId) {
+        // Running compiled code.
+        // Use the FP and PC from the thread interrupt or simulator; already set
+        // in the constructor.
+        in_interpreted_frame = false;
+      } else if (thread_->vm_tag() == VMTag::kDartInterpretedTagId) {
+        // Running interpreter.
+#if defined(DART_PRECOMPILED_RUNTIME)
+        UNREACHABLE();
+#else
+        pc_ = reinterpret_cast<uword*>(thread_->interpreter()->get_pc());
+        fp_ = reinterpret_cast<uword*>(thread_->interpreter()->get_fp());
+#endif
+        in_interpreted_frame = true;
+        RELEASE_ASSERT(IsInterpretedFrame(fp_));
+      } else {
+        // No Dart on the stack; caller shouldn't use this walker.
+        UNREACHABLE();
+      }
+    }
+
+    sample_->set_exit_frame_sample(has_exit_frame);
+
+    for (;;) {
+      // Skip entry frame.
+      if (StubCode::InInvocationStub(reinterpret_cast<uword>(pc_),
+                                     in_interpreted_frame)) {
+        pc_ = 0;
+        fp_ = ExitLink(in_interpreted_frame);
+        if (fp_ == 0) {
+          break;  // End of Dart stack.
+        }
+        in_interpreted_frame = IsInterpretedFrame(fp_);
+
+        // Skip exit frame.
+        pc_ = CallerPC(in_interpreted_frame);
+        fp_ = CallerFP(in_interpreted_frame);
+
+        // At least one frame between exit and next entry frame.
+        RELEASE_ASSERT(!StubCode::InInvocationStub(reinterpret_cast<uword>(pc_),
+                                                   in_interpreted_frame));
+      }
+
+#if !defined(TARGET_ARCH_DBC)
+      RawCode* marker = PCMarker(in_interpreted_frame);
+      if (marker == StubCode::InvokeDartCode_entry()->code() ||
+          marker == StubCode::InvokeDartCodeFromBytecode_entry()->code()) {
+        // During the prologue of a function, CallerPC will return the caller's
+        // caller. For most frames, the missing PC will be added during profile
+        // processing. However, during this stack walk, it can cause us to fail
+        // to identify the entry frame and lead the stack walk into the weeds.
+        RELEASE_ASSERT(!has_exit_frame);
         sample_->set_ignore_sample(true);
         return;
       }
-    }
-    while (true) {
+#endif
+
       if (!Append(reinterpret_cast<uword>(pc_))) {
-        return;
+        break;  // Sample is full.
       }
-      if (!Next()) {
-        return;
-      }
+
+      pc_ = CallerPC(in_interpreted_frame);
+      fp_ = CallerFP(in_interpreted_frame);
+
+      // Can only move between interpreted and compiled frames after an exit
+      // frame.
+      RELEASE_ASSERT(IsInterpretedFrame(fp_) == in_interpreted_frame);
     }
   }
 
  private:
-  bool Next() {
-    if (!ValidFramePointer()) {
-      return false;
-    }
-    if (StubCode::InInvocationStub(reinterpret_cast<uword>(pc_),
-                                   is_interpreted_frame_)) {
-      // In invocation stub.
-      return NextExit();
-    }
-    // In regular Dart frame.
-    uword* new_pc = CallerPC();
-    // Check if we've moved into the invocation stub.
-    if (StubCode::InInvocationStub(reinterpret_cast<uword>(new_pc),
-                                   is_interpreted_frame_)) {
-      // New PC is inside invocation stub, skip.
-      return NextExit();
-    }
-    uword* new_fp = CallerFP();
-    if (!IsCalleeFrameOf(reinterpret_cast<uword>(new_fp),
-                         reinterpret_cast<uword>(fp_))) {
-      // FP didn't move to a caller (higher address on most architectures).
-      return false;
-    }
-    // Success, update fp and pc.
-    fp_ = new_fp;
-    pc_ = new_pc;
-    return true;
-  }
-
-  bool NextExit() {
-    if (!ValidFramePointer()) {
-      return false;
-    }
-    uword* new_fp = ExitLink();
-    if (new_fp == NULL) {
-      // No exit link.
-      return false;
-    }
-    if (new_fp <= fp_) {
-      // FP didn't move to a higher address.
-      return false;
-    }
-    if (!ValidFramePointer(new_fp)) {
-      return false;
-    }
-    // Success, update fp and pc.
-    fp_ = new_fp;
-    pc_ = CallerPC();
-    return true;
-  }
-
   uword InitialReturnAddress() const {
     ASSERT(sp_ != NULL);
     // MSan/ASan are unaware of frames initialized by generated code.
@@ -659,27 +656,44 @@
     return *(sp_);
   }
 
-  uword* CallerPC() const {
+  uword* CallerPC(bool interp) const {
     ASSERT(fp_ != NULL);
-    uword* caller_pc_ptr = fp_ + kSavedCallerPcSlotFromFp;
+    uword* caller_pc_ptr =
+        fp_ + (interp ? kKBCSavedCallerPcSlotFromFp : kSavedCallerPcSlotFromFp);
     // MSan/ASan are unaware of frames initialized by generated code.
     MSAN_UNPOISON(caller_pc_ptr, kWordSize);
     ASAN_UNPOISON(caller_pc_ptr, kWordSize);
     return reinterpret_cast<uword*>(*caller_pc_ptr);
   }
 
-  uword* CallerFP() const {
+  uword* CallerFP(bool interp) const {
     ASSERT(fp_ != NULL);
-    uword* caller_fp_ptr = fp_ + kSavedCallerFpSlotFromFp;
+    uword* caller_fp_ptr =
+        fp_ + (interp ? kKBCSavedCallerFpSlotFromFp : kSavedCallerFpSlotFromFp);
     // MSan/ASan are unaware of frames initialized by generated code.
     MSAN_UNPOISON(caller_fp_ptr, kWordSize);
     ASAN_UNPOISON(caller_fp_ptr, kWordSize);
     return reinterpret_cast<uword*>(*caller_fp_ptr);
   }
 
-  uword* ExitLink() const {
+  RawCode* PCMarker(bool interp) const {
     ASSERT(fp_ != NULL);
-    uword* exit_link_ptr = fp_ + kExitLinkSlotFromEntryFp;
+    if (interp) {
+      // We don't need this extra check for the interpreter because its frame
+      // build is atomic from the profiler's point of view.
+      return NULL;
+    }
+    uword* pc_marker_ptr = fp_ + kPcMarkerSlotFromFp;
+    // MSan/ASan are unaware of frames initialized by generated code.
+    MSAN_UNPOISON(pc_marker_ptr, kWordSize);
+    ASAN_UNPOISON(pc_marker_ptr, kWordSize);
+    return reinterpret_cast<RawCode*>(*pc_marker_ptr);
+  }
+
+  uword* ExitLink(bool interp) const {
+    ASSERT(fp_ != NULL);
+    uword* exit_link_ptr =
+        fp_ + (interp ? kKBCExitLinkSlotFromEntryFp : kExitLinkSlotFromEntryFp);
     // MSan/ASan are unaware of frames initialized by generated code.
     MSAN_UNPOISON(exit_link_ptr, kWordSize);
     ASAN_UNPOISON(exit_link_ptr, kWordSize);
@@ -697,13 +711,12 @@
     return (cursor >= stack_lower_) && (cursor < stack_upper_);
   }
 
+  Thread* const thread_;
   uword* pc_;
   uword* fp_;
   uword* sp_;
-  bool is_interpreted_frame_;
   const uword stack_upper_;
   const uword stack_lower_;
-  bool has_exit_frame_;
 };
 
 // If the VM is compiled without frame pointers (which is the default on
@@ -1187,7 +1200,7 @@
   } else if (exited_dart_code) {
     ProfilerDartStackWalker dart_exit_stack_walker(
         thread, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp,
-        exited_dart_code, true);
+        /* allocation_sample*/ true);
     dart_exit_stack_walker.walk();
   } else {
     // Fall back.
@@ -1388,7 +1401,7 @@
   const bool exited_dart_code = thread->HasExitedDartCode();
   ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer,
                                             stack_lower, stack_upper, pc, fp,
-                                            sp, exited_dart_code, false);
+                                            sp, /* allocation_sample*/ false);
 
   // All memory access is done inside CollectSample.
   CollectSample(isolate, exited_dart_code, in_dart_code, sample,
@@ -1396,9 +1409,7 @@
                 &counters_);
 }
 
-CodeDescriptor::CodeDescriptor(const Code& code) : code_(code) {
-  ASSERT(!code_.IsNull());
-}
+CodeDescriptor::CodeDescriptor(const AbstractCode code) : code_(code) {}
 
 uword CodeDescriptor::Start() const {
   return code_.PayloadStart();
@@ -1425,15 +1436,10 @@
   ~CodeLookupTableBuilder() {}
 
   void VisitObject(RawObject* raw_obj) {
-    uint32_t tags = raw_obj->ptr()->tags_;
-    if (RawObject::ClassIdTag::decode(tags) == kCodeCid) {
-      RawCode* raw_code = reinterpret_cast<RawCode*>(raw_obj);
-      const Code& code = Code::Handle(raw_code);
-      ASSERT(!code.IsNull());
-      const Instructions& instructions =
-          Instructions::Handle(code.instructions());
-      ASSERT(!instructions.IsNull());
-      table_->Add(code);
+    if (raw_obj->IsCode()) {
+      table_->Add(Code::Handle(Code::RawCast(raw_obj)));
+    } else if (raw_obj->IsBytecode()) {
+      table_->Add(Bytecode::Handle(Bytecode::RawCast(raw_obj)));
     }
   }
 
@@ -1482,9 +1488,10 @@
 #endif
 }
 
-void CodeLookupTable::Add(const Code& code) {
+void CodeLookupTable::Add(const Object& code) {
   ASSERT(!code.IsNull());
-  CodeDescriptor* cd = new CodeDescriptor(code);
+  ASSERT(code.IsCode() || code.IsBytecode());
+  CodeDescriptor* cd = new CodeDescriptor(AbstractCode(code.raw()));
   code_objects_.Add(cd);
 }
 
@@ -1659,7 +1666,12 @@
                                                uword pc_marker,
                                                uword* stack_buffer) {
   ASSERT(cd != NULL);
-  const Code& code = Code::Handle(cd->code());
+  if (cd->code().IsBytecode()) {
+    // Bytecode frame build is atomic from the profiler's perspective: no
+    // missing frame.
+    return;
+  }
+  const Code& code = Code::Handle(Code::RawCast(cd->code().raw()));
   ASSERT(!code.IsNull());
   // Some stubs (and intrinsics) do not push a frame onto the stack leaving
   // the frame pointer in the caller.
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index 951abed..c6f868d 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -434,10 +434,83 @@
   }
 };
 
+class AbstractCode {
+ public:
+  explicit AbstractCode(RawObject* code) : code_(Object::Handle(code)) {
+    ASSERT(code_.IsNull() || code_.IsCode() || code_.IsBytecode());
+  }
+
+  RawObject* raw() const { return code_.raw(); }
+  const Object* handle() const { return &code_; }
+
+  uword PayloadStart() const {
+    if (code_.IsCode()) {
+      return Code::Cast(code_).PayloadStart();
+    } else {
+      return Bytecode::Cast(code_).PayloadStart();
+    }
+  }
+
+  uword Size() const {
+    if (code_.IsCode()) {
+      return Code::Cast(code_).Size();
+    } else {
+      return Bytecode::Cast(code_).Size();
+    }
+  }
+
+  int64_t compile_timestamp() const {
+    if (code_.IsCode()) {
+      return Code::Cast(code_).compile_timestamp();
+    } else {
+      return 0;
+    }
+  }
+
+  const char* Name() const {
+    if (code_.IsCode()) {
+      return Code::Cast(code_).Name();
+    } else {
+      return Bytecode::Cast(code_).Name();
+    }
+  }
+
+  const char* QualifiedName() const {
+    if (code_.IsCode()) {
+      return Code::Cast(code_).QualifiedName();
+    } else {
+      return Bytecode::Cast(code_).QualifiedName();
+    }
+  }
+
+  RawObject* owner() const {
+    if (code_.IsCode()) {
+      return Code::Cast(code_).owner();
+    } else {
+      return Bytecode::Cast(code_).function();
+    }
+  }
+
+  bool IsNull() const { return code_.IsNull(); }
+  bool IsCode() const { return code_.IsCode(); }
+  bool IsBytecode() const { return code_.IsBytecode(); }
+
+  bool is_optimized() const {
+    if (code_.IsCode()) {
+      return Code::Cast(code_).is_optimized();
+    } else {
+      return false;
+    }
+  }
+
+ private:
+  const Object& code_;
+};
+
 // A Code object descriptor.
 class CodeDescriptor : public ZoneAllocated {
  public:
-  explicit CodeDescriptor(const Code& code);
+  explicit CodeDescriptor(const AbstractCode code);
 
   uword Start() const;
 
@@ -445,7 +518,7 @@
 
   int64_t CompileTimestamp() const;
 
-  RawCode* code() const { return code_.raw(); }
+  const AbstractCode code() const { return code_; }
 
   const char* Name() const { return code_.Name(); }
 
@@ -471,7 +544,7 @@
   }
 
  private:
-  const Code& code_;
+  const AbstractCode code_;
 
   DISALLOW_COPY_AND_ASSIGN(CodeDescriptor);
 };
@@ -492,7 +565,7 @@
  private:
   void Build(Thread* thread);
 
-  void Add(const Code& code);
+  void Add(const Object& code);
 
   // Code objects sorted by entry.
   ZoneGrowableArray<CodeDescriptor*> code_objects_;
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 856df68..b2405f8 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -272,7 +272,7 @@
                          uword start,
                          uword end,
                          int64_t timestamp,
-                         const Code& code)
+                         const AbstractCode code)
     : kind_(kind),
       start_(start),
       end_(end),
@@ -482,7 +482,7 @@
   obj.AddProperty("exclusiveTicks", exclusive_ticks());
   if (kind() == kDartCode) {
     ASSERT(!code_.IsNull());
-    obj.AddProperty("code", code_);
+    obj.AddProperty("code", *code_.handle());
   } else if (kind() == kCollectedCode) {
     PrintCollectedCode(&obj);
   } else if (kind() == kReusedCode) {
@@ -626,7 +626,19 @@
   } else if (kind() == kNativeCode) {
     if (name() == NULL) {
       // Lazily set generated name.
-      GenerateAndSetSymbolName("[Native]");
+      const intptr_t kBuffSize = 512;
+      char buff[kBuffSize];
+      uword dso_base;
+      char* dso_name;
+      if (NativeSymbolResolver::LookupSharedObject(start(), &dso_base,
+                                                   &dso_name)) {
+        uword dso_offset = start() - dso_base;
+        Utils::SNPrint(&buff[0], kBuffSize - 1, "[Native] %s+0x%" Px, dso_name,
+                       dso_offset);
+      } else {
+        Utils::SNPrint(&buff[0], kBuffSize - 1, "[Native] %" Px, start());
+      }
+      SetName(buff);
     }
     function = table->AddNative(start(), name());
   } else if (kind() == kTagCode) {
@@ -1184,7 +1196,7 @@
         extra_tags_(extra_tags),
         profile_(profile),
         deoptimized_code_(new DeoptimizedCodeSet(thread->isolate())),
-        null_code_(Code::ZoneHandle()),
+        null_code_(Code::null()),
         null_function_(Function::ZoneHandle()),
         tick_functions_(false),
         inclusive_tree_(false),
@@ -1276,8 +1288,7 @@
     for (intptr_t i = 0; i < code_lookup_table.length(); i++) {
       const CodeDescriptor* descriptor = code_lookup_table.At(i);
       ASSERT(descriptor != NULL);
-      const Code& code = Code::Handle(descriptor->code());
-      ASSERT(!code.IsNull());
+      const AbstractCode code = descriptor->code();
       RegisterLiveProfileCode(new ProfileCode(
           ProfileCode::kDartCode, code.PayloadStart(),
           code.PayloadStart() + code.Size(), code.compile_timestamp(), code));
@@ -1414,7 +1425,6 @@
       }
 
       // Walk the sampled PCs.
-      Code& code = Code::Handle();
       for (intptr_t frame_index = sample->length() - 1; frame_index >= 0;
            frame_index--) {
         ASSERT(sample->At(frame_index) != 0);
@@ -1424,7 +1434,7 @@
         ProfileCode* profile_code =
             GetProfileCode(sample->At(frame_index), sample->timestamp());
         ASSERT(profile_code->code_table_index() == index);
-        code ^= profile_code->code();
+        const AbstractCode code = profile_code->code();
         current = AppendKind(code, current, sample);
         current = current->GetChild(index);
         current->Tick(sample, (frame_index == 0));
@@ -1457,7 +1467,6 @@
       }
 
       // Walk the sampled PCs.
-      Code& code = Code::Handle();
       for (intptr_t frame_index = 0; frame_index < sample->length();
            frame_index++) {
         ASSERT(sample->At(frame_index) != 0);
@@ -1467,7 +1476,7 @@
         ProfileCode* profile_code =
             GetProfileCode(sample->At(frame_index), sample->timestamp());
         ASSERT(profile_code->code_table_index() == index);
-        code ^= profile_code->code();
+        const AbstractCode code = profile_code->code();
         current = current->GetChild(index);
         if (ShouldTickNode(sample, frame_index)) {
           current->Tick(sample, (frame_index == 0));
@@ -1580,7 +1589,12 @@
     ASSERT(function != NULL);
     const intptr_t code_index = profile_code->code_table_index();
     ASSERT(profile_code != NULL);
-    const Code& code = Code::ZoneHandle(profile_code->code());
+    Code& code = Code::ZoneHandle();
+    if (profile_code->code().IsCode()) {
+      code ^= profile_code->code().raw();
+    } else {
+      // No inlining in bytecode.
+    }
     GrowableArray<const Function*>* inlined_functions = NULL;
     GrowableArray<TokenPosition>* inlined_token_positions = NULL;
     TokenPosition token_position = TokenPosition::kNoSource;
@@ -1834,7 +1848,7 @@
     return current;
   }
 
-  ProfileCodeTrieNode* AppendKind(const Code& code,
+  ProfileCodeTrieNode* AppendKind(const AbstractCode code,
                                   ProfileCodeTrieNode* current,
                                   ProcessedSample* sample) {
     if (code.IsNull()) {
@@ -2188,7 +2202,6 @@
     }
 
     // We haven't seen this pc yet.
-    Code& code = Code::Handle(thread_->zone());
 
     // Check NativeSymbolResolver for pc.
     uintptr_t native_start = 0;
@@ -2225,7 +2238,7 @@
 
     ASSERT(pc >= native_start);
     profile_code = new ProfileCode(ProfileCode::kNativeCode, native_start,
-                                   pc + 1, 0, code);
+                                   pc + 1, 0, null_code_);
     if (native_name != NULL) {
       profile_code->SetName(native_name);
       NativeSymbolResolver::FreeSymbolName(native_name);
@@ -2289,7 +2302,7 @@
   intptr_t extra_tags_;
   Profile* profile_;
   DeoptimizedCodeSet* deoptimized_code_;
-  const Code& null_code_;
+  const AbstractCode null_code_;
   const Function& null_function_;
   bool tick_functions_;
   bool inclusive_tree_;
diff --git a/runtime/vm/profiler_service.h b/runtime/vm/profiler_service.h
index ba1981a..6e7d660 100644
--- a/runtime/vm/profiler_service.h
+++ b/runtime/vm/profiler_service.h
@@ -10,6 +10,7 @@
 #include "vm/globals.h"
 #include "vm/growable_array.h"
 #include "vm/object.h"
+#include "vm/profiler.h"
 #include "vm/tags.h"
 #include "vm/thread_interrupter.h"
 #include "vm/token_position.h"
@@ -158,7 +159,7 @@
               uword start,
               uword end,
               int64_t timestamp,
-              const Code& code);
+              const AbstractCode code);
 
   Kind kind() const { return kind_; }
 
@@ -195,7 +196,7 @@
   void IncInclusiveTicks() { inclusive_ticks_++; }
 
   bool IsOptimizedDart() const;
-  RawCode* code() const { return code_.raw(); }
+  const AbstractCode code() const { return code_; }
 
   const char* name() const { return name_; }
   void SetName(const char* name);
@@ -228,7 +229,7 @@
   intptr_t inclusive_ticks_;
   intptr_t inclusive_serial_;
 
-  const Code& code_;
+  const AbstractCode code_;
   char* name_;
   int64_t compile_timestamp_;
   ProfileFunction* function_;
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index 36f8318..1cb8236 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -18,6 +18,7 @@
 #ifndef PRODUCT
 
 DECLARE_FLAG(bool, profile_vm);
+DECLARE_FLAG(bool, profile_vm_allocation);
 DECLARE_FLAG(int, max_profile_depth);
 DECLARE_FLAG(bool, enable_inlining_annotations);
 DECLARE_FLAG(int, optimization_counter_threshold);
@@ -25,14 +26,21 @@
 // Some tests are written assuming native stack trace profiling is disabled.
 class DisableNativeProfileScope : public ValueObject {
  public:
-  DisableNativeProfileScope() : FLAG_profile_vm_(FLAG_profile_vm) {
+  DisableNativeProfileScope()
+      : FLAG_profile_vm_(FLAG_profile_vm),
+        FLAG_profile_vm_allocation_(FLAG_profile_vm_allocation) {
     FLAG_profile_vm = false;
+    FLAG_profile_vm_allocation = false;
   }
 
-  ~DisableNativeProfileScope() { FLAG_profile_vm = FLAG_profile_vm_; }
+  ~DisableNativeProfileScope() {
+    FLAG_profile_vm = FLAG_profile_vm_;
+    FLAG_profile_vm_allocation = FLAG_profile_vm_allocation_;
+  }
 
  private:
   const bool FLAG_profile_vm_;
+  const bool FLAG_profile_vm_allocation_;
 };
 
 class DisableBackgroundCompilationScope : public ValueObject {
@@ -148,9 +156,19 @@
   delete sample_buffer;
 }
 
+static RawLibrary* LoadTestScript(const char* script) {
+  Dart_Handle api_lib;
+  {
+    TransitionVMToNative transition(Thread::Current());
+    api_lib = TestCase::LoadTestScript(script, NULL);
+  }
+  Library& lib = Library::Handle();
+  lib ^= Api::UnwrapHandle(api_lib);
+  return lib.raw();
+}
+
 static RawClass* GetClass(const Library& lib, const char* name) {
   Thread* thread = Thread::Current();
-  TransitionNativeToVM transition(thread);
   const Class& cls = Class::Handle(
       lib.LookupClassAllowPrivate(String::Handle(Symbols::New(thread, name))));
   EXPECT(!cls.IsNull());  // No ambiguity error expected.
@@ -159,13 +177,23 @@
 
 static RawFunction* GetFunction(const Library& lib, const char* name) {
   Thread* thread = Thread::Current();
-  TransitionNativeToVM transition(thread);
   const Function& func = Function::Handle(lib.LookupFunctionAllowPrivate(
       String::Handle(Symbols::New(thread, name))));
   EXPECT(!func.IsNull());  // No ambiguity error expected.
   return func.raw();
 }
 
+static void Invoke(const Library& lib,
+                   const char* name,
+                   intptr_t argc = 0,
+                   Dart_Handle* argv = NULL) {
+  Thread* thread = Thread::Current();
+  Dart_Handle api_lib = Api::NewHandle(thread, lib.raw());
+  TransitionVMToNative transition(thread);
+  Dart_Handle result = Dart_Invoke(api_lib, NewString(name), argc, argv);
+  EXPECT_VALID(result);
+}
+
 class AllocationFilter : public SampleFilter {
  public:
   AllocationFilter(Dart_Port port,
@@ -201,9 +229,10 @@
   }
 }
 
-TEST_CASE(Profiler_TrivialRecordAllocation) {
+ISOLATE_UNIT_TEST_CASE(Profiler_TrivialRecordAllocation) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
+  DisableBackgroundCompilationScope dbcs;
   const char* kScript =
       "class A {\n"
       "  var a;\n"
@@ -218,18 +247,14 @@
       "  return B.boo();\n"
       "}\n";
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
   const int64_t before_allocations_micros = Dart_TimelineGetMicros();
   const Class& class_a = Class::Handle(GetClass(root_library, "A"));
   EXPECT(!class_a.IsNull());
   class_a.SetTraceAllocation(true);
 
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   const int64_t after_allocations_micros = Dart_TimelineGetMicros();
   const int64_t allocation_extent_micros =
@@ -237,7 +262,6 @@
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -258,18 +282,18 @@
     EXPECT(walker.Down());
     EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] B.boo", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("main", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] main", walker.CurrentName());
     EXPECT(!walker.Down());
 
     // Inclusive code: main -> B.boo.
     walker.Reset(Profile::kInclusiveCode);
     // Move down from the root.
     EXPECT(walker.Down());
-    EXPECT_STREQ("main", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] main", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] B.boo", walker.CurrentName());
     EXPECT(walker.Down());
     EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
     EXPECT(walker.Down());
@@ -307,7 +331,6 @@
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -356,7 +379,6 @@
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -499,7 +521,6 @@
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -516,7 +537,6 @@
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -535,10 +555,11 @@
 #endif  // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) &&
         // !defined(TARGET_ARCH_DBC) && !defined(HOST_OS_FUCHSIA)
 
-TEST_CASE(Profiler_ToggleRecordAllocation) {
+ISOLATE_UNIT_TEST_CASE(Profiler_ToggleRecordAllocation) {
   EnableProfiler();
 
   DisableNativeProfileScope dnps;
+  DisableBackgroundCompilationScope dbcs;
   const char* kScript =
       "class A {\n"
       "  var a;\n"
@@ -553,21 +574,16 @@
       "  return B.boo();\n"
       "}\n";
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
   const Class& class_a = Class::Handle(GetClass(root_library, "A"));
   EXPECT(!class_a.IsNull());
 
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -580,13 +596,11 @@
   // Turn on allocation tracing for A.
   class_a.SetTraceAllocation(true);
 
-  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -604,18 +618,18 @@
     EXPECT(walker.Down());
     EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] B.boo", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("main", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] main", walker.CurrentName());
     EXPECT(!walker.Down());
 
     // Inclusive code: main -> B.boo.
     walker.Reset(Profile::kInclusiveCode);
     // Move down from the root.
     EXPECT(walker.Down());
-    EXPECT_STREQ("main", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] main", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] B.boo", walker.CurrentName());
     EXPECT(walker.Down());
     EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
     EXPECT(walker.Down());
@@ -652,13 +666,11 @@
   // Turn off allocation tracing for A.
   class_a.SetTraceAllocation(false);
 
-  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -669,9 +681,10 @@
   }
 }
 
-TEST_CASE(Profiler_CodeTicks) {
+ISOLATE_UNIT_TEST_CASE(Profiler_CodeTicks) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
+  DisableBackgroundCompilationScope dbcs;
   const char* kScript =
       "class A {\n"
       "  var a;\n"
@@ -686,21 +699,16 @@
       "  return B.boo();\n"
       "}\n";
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
   const Class& class_a = Class::Handle(GetClass(root_library, "A"));
   EXPECT(!class_a.IsNull());
 
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -714,17 +722,13 @@
   class_a.SetTraceAllocation(true);
 
   // Allocate three times.
-  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
+  Invoke(root_library, "main");
+  Invoke(root_library, "main");
 
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -743,11 +747,11 @@
     EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
     EXPECT_EQ(3, walker.CurrentExclusiveTicks());
     EXPECT(walker.Down());
-    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] B.boo", walker.CurrentName());
     EXPECT_EQ(3, walker.CurrentNodeTickCount());
     EXPECT_EQ(3, walker.CurrentInclusiveTicks());
     EXPECT(walker.Down());
-    EXPECT_STREQ("main", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] main", walker.CurrentName());
     EXPECT_EQ(3, walker.CurrentNodeTickCount());
     EXPECT_EQ(3, walker.CurrentInclusiveTicks());
     EXPECT_EQ(0, walker.CurrentExclusiveTicks());
@@ -757,12 +761,12 @@
     walker.Reset(Profile::kInclusiveCode);
     // Move down from the root.
     EXPECT(walker.Down());
-    EXPECT_STREQ("main", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] main", walker.CurrentName());
     EXPECT_EQ(3, walker.CurrentNodeTickCount());
     EXPECT_EQ(3, walker.CurrentInclusiveTicks());
     EXPECT_EQ(0, walker.CurrentExclusiveTicks());
     EXPECT(walker.Down());
-    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] B.boo", walker.CurrentName());
     EXPECT_EQ(3, walker.CurrentNodeTickCount());
     EXPECT_EQ(3, walker.CurrentInclusiveTicks());
     EXPECT(walker.Down());
@@ -774,9 +778,10 @@
   }
 }
 
-TEST_CASE(Profiler_FunctionTicks) {
+ISOLATE_UNIT_TEST_CASE(Profiler_FunctionTicks) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
+  DisableBackgroundCompilationScope dbcs;
   const char* kScript =
       "class A {\n"
       "  var a;\n"
@@ -791,21 +796,16 @@
       "  return B.boo();\n"
       "}\n";
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
   const Class& class_a = Class::Handle(GetClass(root_library, "A"));
   EXPECT(!class_a.IsNull());
 
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -819,17 +819,13 @@
   class_a.SetTraceAllocation(true);
 
   // Allocate three times.
-  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
+  Invoke(root_library, "main");
+  Invoke(root_library, "main");
 
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -879,29 +875,28 @@
   }
 }
 
-TEST_CASE(Profiler_IntrinsicAllocation) {
+ISOLATE_UNIT_TEST_CASE(Profiler_IntrinsicAllocation) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
+  DisableBackgroundCompilationScope dbcs;
   const char* kScript = "double foo(double a, double b) => a + b;";
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
   Isolate* isolate = thread->isolate();
 
   const Class& double_class =
       Class::Handle(isolate->object_store()->double_class());
   EXPECT(!double_class.IsNull());
 
-  Dart_Handle args[2] = {
-      Dart_NewDouble(1.0), Dart_NewDouble(2.0),
-  };
+  Dart_Handle args[2];
+  {
+    TransitionVMToNative transition(thread);
+    args[0] = Dart_NewDouble(1.0);
+    args[1] = Dart_NewDouble(2.0);
+  }
 
-  Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo", 2, &args[0]);
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -912,11 +907,9 @@
   }
 
   double_class.SetTraceAllocation(true);
-  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo", 2, &args[0]);
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -930,20 +923,18 @@
     EXPECT(walker.Down());
     EXPECT_STREQ("Double_add", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("_Double._add", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] _Double._add", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("_Double.+", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] _Double.+", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("foo", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] foo", walker.CurrentName());
     EXPECT(!walker.Down());
   }
 
   double_class.SetTraceAllocation(false);
-  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo", 2, &args[0]);
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -954,27 +945,23 @@
   }
 }
 
-TEST_CASE(Profiler_ArrayAllocation) {
+ISOLATE_UNIT_TEST_CASE(Profiler_ArrayAllocation) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
+  DisableBackgroundCompilationScope dbcs;
   const char* kScript =
       "List foo() => new List(4);\n"
       "List bar() => new List();\n";
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
   Isolate* isolate = thread->isolate();
 
   const Class& array_class =
       Class::Handle(isolate->object_store()->array_class());
   EXPECT(!array_class.IsNull());
 
-  Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo");
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -985,11 +972,9 @@
   }
 
   array_class.SetTraceAllocation(true);
-  result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo");
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1005,18 +990,16 @@
     EXPECT(walker.Down());
     EXPECT_STREQ("[Stub] AllocateArray", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("new _List", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] new _List", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("foo", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] foo", walker.CurrentName());
     EXPECT(!walker.Down());
   }
 
   array_class.SetTraceAllocation(false);
-  result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo");
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1030,18 +1013,15 @@
   ProfilerService::ClearSamples();
 
   // Compile bar (many List objects allocated).
-  result = Dart_Invoke(lib, NewString("bar"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "bar");
 
   // Enable again.
   array_class.SetTraceAllocation(true);
 
   // Run bar.
-  result = Dart_Invoke(lib, NewString("bar"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "bar");
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1053,29 +1033,25 @@
   }
 }
 
-TEST_CASE(Profiler_ContextAllocation) {
+ISOLATE_UNIT_TEST_CASE(Profiler_ContextAllocation) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
+  DisableBackgroundCompilationScope dbcs;
   const char* kScript =
       "var msg1 = 'a';\n"
       "foo() {\n"
       "  var msg = msg1 + msg1;\n"
       "  return (x) { return '$msg + $msg'; }(msg);\n"
       "}\n";
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
   Isolate* isolate = thread->isolate();
 
   const Class& context_class = Class::Handle(Object::context_class());
   EXPECT(!context_class.IsNull());
 
-  Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo");
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1086,11 +1062,9 @@
   }
 
   context_class.SetTraceAllocation(true);
-  result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo");
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1106,16 +1080,14 @@
     EXPECT(walker.Down());
     EXPECT_STREQ("[Stub] AllocateContext", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("foo", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] foo", walker.CurrentName());
     EXPECT(!walker.Down());
   }
 
   context_class.SetTraceAllocation(false);
-  result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo");
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1126,9 +1098,10 @@
   }
 }
 
-TEST_CASE(Profiler_ClosureAllocation) {
+ISOLATE_UNIT_TEST_CASE(Profiler_ClosureAllocation) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
+  DisableBackgroundCompilationScope dbcs;
   const char* kScript =
       "var msg1 = 'a';\n"
       "\n"
@@ -1143,10 +1116,7 @@
       "  return (x, y) { return '$x + $y'; }(msg, msg2);\n"
       "}\n";
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
   Isolate* isolate = thread->isolate();
 
   const Class& closure_class =
@@ -1155,11 +1125,9 @@
   closure_class.SetTraceAllocation(true);
 
   // Invoke "foo" which during compilation, triggers a closure allocation.
-  Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo");
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1184,11 +1152,9 @@
   closure_class.SetTraceAllocation(false);
 
   // Invoke "bar" which during compilation, triggers a closure allocation.
-  result = Dart_Invoke(lib, NewString("bar"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "bar");
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1200,16 +1166,14 @@
   }
 }
 
-TEST_CASE(Profiler_TypedArrayAllocation) {
+ISOLATE_UNIT_TEST_CASE(Profiler_TypedArrayAllocation) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
+  DisableBackgroundCompilationScope dbcs;
   const char* kScript =
       "import 'dart:typed_data';\n"
       "List foo() => new Float32List(4);\n";
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
   Isolate* isolate = thread->isolate();
 
   const Library& typed_data_library =
@@ -1219,11 +1183,9 @@
       Class::Handle(GetClass(typed_data_library, "_Float32List"));
   EXPECT(!float32_list_class.IsNull());
 
-  Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo");
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1234,11 +1196,9 @@
   }
 
   float32_list_class.SetTraceAllocation(true);
-  result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo");
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1252,18 +1212,16 @@
     EXPECT(walker.Down());
     EXPECT_STREQ("TypedData_Float32Array_new", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("new Float32List", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] new Float32List", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("foo", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] foo", walker.CurrentName());
     EXPECT(!walker.Down());
   }
 
   float32_list_class.SetTraceAllocation(false);
-  result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo");
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1274,11 +1232,9 @@
   }
 
   float32_list_class.SetTraceAllocation(true);
-  result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo");
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1289,29 +1245,28 @@
   }
 }
 
-TEST_CASE(Profiler_StringAllocation) {
+ISOLATE_UNIT_TEST_CASE(Profiler_StringAllocation) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
+  DisableBackgroundCompilationScope dbcs;
   const char* kScript = "String foo(String a, String b) => a + b;";
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
   Isolate* isolate = thread->isolate();
 
   const Class& one_byte_string_class =
       Class::Handle(isolate->object_store()->one_byte_string_class());
   EXPECT(!one_byte_string_class.IsNull());
 
-  Dart_Handle args[2] = {
-      NewString("a"), NewString("b"),
-  };
+  Dart_Handle args[2];
+  {
+    TransitionVMToNative transition(thread);
+    args[0] = NewString("a");
+    args[1] = NewString("b");
+  }
 
-  Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo", 2, &args[0]);
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1322,11 +1277,9 @@
   }
 
   one_byte_string_class.SetTraceAllocation(true);
-  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo", 2, &args[0]);
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1341,19 +1294,17 @@
     EXPECT_STREQ("String_concat", walker.CurrentName());
     EXPECT(walker.Down());
 #if 1
-    EXPECT_STREQ("_StringBase.+", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] _StringBase.+", walker.CurrentName());
     EXPECT(walker.Down());
 #endif
-    EXPECT_STREQ("foo", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] foo", walker.CurrentName());
     EXPECT(!walker.Down());
   }
 
   one_byte_string_class.SetTraceAllocation(false);
-  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo", 2, &args[0]);
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1364,11 +1315,9 @@
   }
 
   one_byte_string_class.SetTraceAllocation(true);
-  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo", 2, &args[0]);
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1379,30 +1328,28 @@
   }
 }
 
-TEST_CASE(Profiler_StringInterpolation) {
+ISOLATE_UNIT_TEST_CASE(Profiler_StringInterpolation) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
   DisableBackgroundCompilationScope dbcs;
   const char* kScript = "String foo(String a, String b) => '$a | $b';";
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
   Isolate* isolate = thread->isolate();
 
   const Class& one_byte_string_class =
       Class::Handle(isolate->object_store()->one_byte_string_class());
   EXPECT(!one_byte_string_class.IsNull());
 
-  Dart_Handle args[2] = {
-      NewString("a"), NewString("b"),
-  };
+  Dart_Handle args[2];
+  {
+    TransitionVMToNative transition(thread);
+    args[0] = NewString("a");
+    args[1] = NewString("b");
+  }
 
-  Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo", 2, &args[0]);
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1413,11 +1360,9 @@
   }
 
   one_byte_string_class.SetTraceAllocation(true);
-  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo", 2, &args[0]);
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1431,22 +1376,23 @@
     EXPECT(walker.Down());
     EXPECT_STREQ("OneByteString_allocate", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("_OneByteString._allocate", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] _OneByteString._allocate",
+                 walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("_OneByteString._concatAll", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] _OneByteString._concatAll",
+                 walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("_StringBase._interpolate", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] _StringBase._interpolate",
+                 walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("foo", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] foo", walker.CurrentName());
     EXPECT(!walker.Down());
   }
 
   one_byte_string_class.SetTraceAllocation(false);
-  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo", 2, &args[0]);
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1457,11 +1403,9 @@
   }
 
   one_byte_string_class.SetTraceAllocation(true);
-  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
-  EXPECT_VALID(result);
+  Invoke(root_library, "foo", 2, &args[0]);
 
   {
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1472,10 +1416,11 @@
   }
 }
 
-TEST_CASE(Profiler_FunctionInline) {
+ISOLATE_UNIT_TEST_CASE(Profiler_FunctionInline) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
   DisableBackgroundCompilationScope dbcs;
+  SetFlagScope<int> sfs(&FLAG_optimization_counter_threshold, 30000);
 
   const char* kScript =
       "class A {\n"
@@ -1503,26 +1448,20 @@
       "  B.boo(true);\n"
       "}\n";
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
   const Class& class_a = Class::Handle(GetClass(root_library, "A"));
   EXPECT(!class_a.IsNull());
 
   // Compile "main".
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
   // Compile "mainA".
-  result = Dart_Invoke(lib, NewString("mainA"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "mainA");
   // At this point B.boo should be optimized and inlined B.foo and B.choo.
 
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1536,13 +1475,11 @@
   class_a.SetTraceAllocation(true);
 
   // Allocate 50,000 instances of A.
-  result = Dart_Invoke(lib, NewString("mainA"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "mainA");
 
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1559,12 +1496,12 @@
     EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
     EXPECT_EQ(50000, walker.CurrentExclusiveTicks());
     EXPECT(walker.Down());
-    EXPECT_STREQ("*B.boo", walker.CurrentName());
+    EXPECT_STREQ("[Optimized] B.boo", walker.CurrentName());
     EXPECT_EQ(1, walker.SiblingCount());
     EXPECT_EQ(50000, walker.CurrentNodeTickCount());
     EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
     EXPECT(walker.Down());
-    EXPECT_STREQ("mainA", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] mainA", walker.CurrentName());
     EXPECT_EQ(1, walker.SiblingCount());
     EXPECT_EQ(50000, walker.CurrentNodeTickCount());
     EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
@@ -1573,13 +1510,13 @@
     // We have two code objects: mainA and B.boo.
     walker.Reset(Profile::kInclusiveCode);
     EXPECT(walker.Down());
-    EXPECT_STREQ("mainA", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] mainA", walker.CurrentName());
     EXPECT_EQ(1, walker.SiblingCount());
     EXPECT_EQ(50000, walker.CurrentNodeTickCount());
     EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
     EXPECT_EQ(0, walker.CurrentExclusiveTicks());
     EXPECT(walker.Down());
-    EXPECT_STREQ("*B.boo", walker.CurrentName());
+    EXPECT_STREQ("[Optimized] B.boo", walker.CurrentName());
     EXPECT_EQ(1, walker.SiblingCount());
     EXPECT_EQ(50000, walker.CurrentNodeTickCount());
     EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
@@ -1661,7 +1598,6 @@
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1680,11 +1616,11 @@
     EXPECT(walker.Down());
     EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("*B.boo", walker.CurrentName());
+    EXPECT_STREQ("[Optimized] B.boo", walker.CurrentName());
     EXPECT(walker.Down());
     EXPECT_STREQ("[Optimized Code]", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("mainA", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] mainA", walker.CurrentName());
     EXPECT(walker.Down());
     EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName());
     EXPECT(!walker.Down());
@@ -1693,11 +1629,11 @@
     EXPECT(walker.Down());
     EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("mainA", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] mainA", walker.CurrentName());
     EXPECT(walker.Down());
     EXPECT_STREQ("[Optimized Code]", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("*B.boo", walker.CurrentName());
+    EXPECT_STREQ("[Optimized] B.boo", walker.CurrentName());
     EXPECT(walker.Down());
     EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName());
     EXPECT(walker.Down());
@@ -1760,7 +1696,7 @@
   }
 }
 
-TEST_CASE(Profiler_InliningIntervalBoundry) {
+ISOLATE_UNIT_TEST_CASE(Profiler_InliningIntervalBoundry) {
   // The PC of frames below the top frame is a call's return address,
   // which can belong to a different inlining interval than the call.
   // This test checks the profiler service takes this into account; see
@@ -1769,6 +1705,8 @@
   EnableProfiler();
   DisableNativeProfileScope dnps;
   DisableBackgroundCompilationScope dbcs;
+  SetFlagScope<int> sfs(&FLAG_optimization_counter_threshold, 30000);
+
   const char* kScript =
       "class A {\n"
       "}\n"
@@ -1803,19 +1741,14 @@
       "  a();\n"
       "}\n";
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
   const Class& class_a = Class::Handle(GetClass(root_library, "A"));
   EXPECT(!class_a.IsNull());
 
   // Compile and optimize.
-  Dart_Handle result = Dart_Invoke(lib, NewString("mainNoAlloc"), 0, NULL);
-  EXPECT_VALID(result);
-  result = Dart_Invoke(lib, NewString("mainAlloc"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "mainNoAlloc");
+  Invoke(root_library, "mainAlloc");
 
   // At this point a should be optimized and have inlined both right and wrong,
   // but not maybeAllocate or doNothing.
@@ -1835,7 +1768,6 @@
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1848,13 +1780,11 @@
   // Turn on allocation tracing for A.
   class_a.SetTraceAllocation(true);
 
-  result = Dart_Invoke(lib, NewString("mainAlloc"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "mainAlloc");
 
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1877,12 +1807,9 @@
     EXPECT_STREQ("a", walker.CurrentName());
     EXPECT(walker.Down());
     EXPECT_STREQ("mainAlloc", walker.CurrentName());
-    EXPECT(walker.Down());  // Account for "[Native] [xxxxxxx, xxxxxxx)"
-    EXPECT(!walker.Down());
 
     // Inline expansion should show us the complete call chain:
     walker.Reset(Profile::kInclusiveFunction);
-    EXPECT(walker.Down());  // Account for "[Native] [xxxxxxx, xxxxxxx)"
     EXPECT(walker.Down());
     EXPECT_STREQ("mainAlloc", walker.CurrentName());
     EXPECT(walker.Down());
@@ -1899,7 +1826,7 @@
   }
 }
 
-TEST_CASE(Profiler_ChainedSamples) {
+ISOLATE_UNIT_TEST_CASE(Profiler_ChainedSamples) {
   EnableProfiler();
   MaxProfileDepthScope mpds(32);
   DisableNativeProfileScope dnps;
@@ -1938,22 +1865,17 @@
       "  return go();\n"
       "}\n";
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
   const Class& class_a = Class::Handle(GetClass(root_library, "A"));
   EXPECT(!class_a.IsNull());
   class_a.SetTraceAllocation(true);
 
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -1970,50 +1892,50 @@
     EXPECT(walker.Down());
     EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("B.boo", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] B.boo", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("orange", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] orange", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("napkin", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] napkin", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("mayo", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] mayo", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("lemon", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] lemon", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("kindle", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] kindle", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("jeep", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] jeep", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("ice", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] ice", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("haystack", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] haystack", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("granola", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] granola", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("fred", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] fred", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("elephant", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] elephant", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("dog", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] dog", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("cantaloupe", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] cantaloupe", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("banana", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] banana", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("apple", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] apple", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("secondInit", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] secondInit", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("init", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] init", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("go", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] go", walker.CurrentName());
     EXPECT(walker.Down());
-    EXPECT_STREQ("main", walker.CurrentName());
+    EXPECT_STREQ("[Unoptimized] main", walker.CurrentName());
     EXPECT(!walker.Down());
   }
 }
 
-TEST_CASE(Profiler_BasicSourcePosition) {
+ISOLATE_UNIT_TEST_CASE(Profiler_BasicSourcePosition) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
   DisableBackgroundCompilationScope dbcs;
@@ -2035,28 +1957,22 @@
       "  B.boo();\n"
       "}\n";
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
   const Class& class_a = Class::Handle(GetClass(root_library, "A"));
   EXPECT(!class_a.IsNull());
 
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   // Turn on allocation tracing for A.
   class_a.SetTraceAllocation(true);
 
   // Allocate one time.
-  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -2089,7 +2005,7 @@
   }
 }
 
-TEST_CASE(Profiler_BasicSourcePositionOptimized) {
+ISOLATE_UNIT_TEST_CASE(Profiler_BasicSourcePositionOptimized) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
   DisableBackgroundCompilationScope dbcs;
@@ -2115,10 +2031,7 @@
       "  B.boo();\n"
       "}\n";
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
   const Class& class_a = Class::Handle(GetClass(root_library, "A"));
   EXPECT(!class_a.IsNull());
@@ -2128,8 +2041,7 @@
 
   // Warm up function.
   while (true) {
-    Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-    EXPECT_VALID(result);
+    Invoke(root_library, "main");
     const Code& code = Code::Handle(main.CurrentCode());
     if (code.is_optimized()) {
       // Warmed up.
@@ -2141,8 +2053,7 @@
   class_a.SetTraceAllocation(true);
 
   // Allocate one time.
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   // Still optimized.
   const Code& code = Code::Handle(main.CurrentCode());
@@ -2151,7 +2062,6 @@
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -2184,7 +2094,7 @@
   }
 }
 
-TEST_CASE(Profiler_SourcePosition) {
+ISOLATE_UNIT_TEST_CASE(Profiler_SourcePosition) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
   DisableBackgroundCompilationScope dbcs;
@@ -2218,28 +2128,22 @@
       "  new C()..bacon();\n"
       "}\n";
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
   const Class& class_a = Class::Handle(GetClass(root_library, "A"));
   EXPECT(!class_a.IsNull());
 
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   // Turn on allocation tracing for A.
   class_a.SetTraceAllocation(true);
 
   // Allocate one time.
-  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -2290,7 +2194,7 @@
   }
 }
 
-TEST_CASE(Profiler_SourcePositionOptimized) {
+ISOLATE_UNIT_TEST_CASE(Profiler_SourcePositionOptimized) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
   DisableBackgroundCompilationScope dbcs;
@@ -2329,10 +2233,7 @@
       "  new C()..bacon();\n"
       "}\n";
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
   const Class& class_a = Class::Handle(GetClass(root_library, "A"));
   EXPECT(!class_a.IsNull());
@@ -2342,8 +2243,7 @@
 
   // Warm up function.
   while (true) {
-    Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-    EXPECT_VALID(result);
+    Invoke(root_library, "main");
     const Code& code = Code::Handle(main.CurrentCode());
     if (code.is_optimized()) {
       // Warmed up.
@@ -2355,8 +2255,7 @@
   class_a.SetTraceAllocation(true);
 
   // Allocate one time.
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   // Still optimized.
   const Code& code = Code::Handle(main.CurrentCode());
@@ -2365,7 +2264,6 @@
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -2416,7 +2314,7 @@
   }
 }
 
-TEST_CASE(Profiler_BinaryOperatorSourcePosition) {
+ISOLATE_UNIT_TEST_CASE(Profiler_BinaryOperatorSourcePosition) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
   DisableBackgroundCompilationScope dbcs;
@@ -2453,28 +2351,22 @@
       "  new C()..bacon();\n"
       "}\n";
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
   const Class& class_a = Class::Handle(GetClass(root_library, "A"));
   EXPECT(!class_a.IsNull());
 
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   // Turn on allocation tracing for A.
   class_a.SetTraceAllocation(true);
 
   // Allocate one time.
-  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -2531,7 +2423,7 @@
   }
 }
 
-TEST_CASE(Profiler_BinaryOperatorSourcePositionOptimized) {
+ISOLATE_UNIT_TEST_CASE(Profiler_BinaryOperatorSourcePositionOptimized) {
   EnableProfiler();
   DisableNativeProfileScope dnps;
   DisableBackgroundCompilationScope dbcs;
@@ -2573,10 +2465,7 @@
       "  new C()..bacon();\n"
       "}\n";
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
   const Class& class_a = Class::Handle(GetClass(root_library, "A"));
   EXPECT(!class_a.IsNull());
@@ -2586,8 +2475,7 @@
 
   // Warm up function.
   while (true) {
-    Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-    EXPECT_VALID(result);
+    Invoke(root_library, "main");
     const Code& code = Code::Handle(main.CurrentCode());
     if (code.is_optimized()) {
       // Warmed up.
@@ -2599,8 +2487,7 @@
   class_a.SetTraceAllocation(true);
 
   // Allocate one time.
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   // Still optimized.
   const Code& code = Code::Handle(main.CurrentCode());
@@ -2609,7 +2496,6 @@
   {
     Thread* thread = Thread::Current();
     Isolate* isolate = thread->isolate();
-    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
@@ -2705,7 +2591,7 @@
   return 0;
 }
 
-TEST_CASE(Profiler_GetSourceReport) {
+ISOLATE_UNIT_TEST_CASE(Profiler_GetSourceReport) {
   EnableProfiler();
   const char* kScript =
       "doWork(i) => i * i;\n"
@@ -2718,10 +2604,10 @@
       "}\n";
 
   // Token position of * in `i * i`.
-  const TokenPosition squarePosition = TokenPosition(6);
+  const TokenPosition squarePosition = TokenPosition(15);
 
   // Token position of the call to `doWork`.
-  const TokenPosition callPosition = TokenPosition(39);
+  const TokenPosition callPosition = TokenPosition(90);
 
   DisableNativeProfileScope dnps;
   // Disable profiling for this thread.
@@ -2732,14 +2618,10 @@
   SampleBuffer* sample_buffer = Profiler::sample_buffer();
   EXPECT(sample_buffer != NULL);
 
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& root_library = Library::Handle();
-  root_library ^= Api::UnwrapHandle(lib);
+  const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
   // Invoke main so that it gets compiled.
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
+  Invoke(root_library, "main");
 
   {
     // Clear the profile for this isolate.
@@ -2781,10 +2663,6 @@
       FindPCForTokenPosition(do_work_code, TokenPosition::kControlFlow);
   EXPECT(controlFlowPc != 0);
 
-  uword tempMovePc =
-      FindPCForTokenPosition(main_code, TokenPosition::kTempMove);
-  EXPECT(tempMovePc != 0);
-
   // Insert fake samples.
 
   // Sample 1:
@@ -2808,41 +2686,34 @@
                      callPositionPc,  // main.
                      0};
 
-  // Sample 4:
-  // tempMovePc exclusive.
-  uword sample4[] = {tempMovePc,  // main.
-                     0};
-
   InsertFakeSample(sample_buffer, &sample1[0]);
   InsertFakeSample(sample_buffer, &sample2[0]);
   InsertFakeSample(sample_buffer, &sample3[0]);
-  InsertFakeSample(sample_buffer, &sample4[0]);
 
   // Generate source report for main.
   JSONStream js;
   {
-    TransitionNativeToVM transition(thread);
     SourceReport sourceReport(SourceReport::kProfile);
     sourceReport.PrintJSON(&js, script, do_work.token_pos(),
                            main.end_token_pos());
   }
 
   // Verify positions in do_work.
-  EXPECT_SUBSTRING("\"positions\":[\"ControlFlow\",6]", js.ToCString());
+  EXPECT_SUBSTRING("\"positions\":[\"ControlFlow\",15]", js.ToCString());
   // Verify exclusive ticks in do_work.
   EXPECT_SUBSTRING("\"exclusiveTicks\":[1,2]", js.ToCString());
   // Verify inclusive ticks in do_work.
   EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString());
 
   // Verify positions in main.
-  EXPECT_SUBSTRING("\"positions\":[\"TempMove\",39]", js.ToCString());
+  EXPECT_SUBSTRING("\"positions\":[90]", js.ToCString());
   // Verify exclusive ticks in main.
-  EXPECT_SUBSTRING("\"exclusiveTicks\":[1,0]", js.ToCString());
+  EXPECT_SUBSTRING("\"exclusiveTicks\":[0]", js.ToCString());
   // Verify inclusive ticks in main.
-  EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString());
+  EXPECT_SUBSTRING("\"inclusiveTicks\":[2]", js.ToCString());
 }
 
-TEST_CASE(Profiler_ProfileCodeTableTest) {
+ISOLATE_UNIT_TEST_CASE(Profiler_ProfileCodeTableTest) {
   Zone* Z = Thread::Current()->zone();
 
   ProfileCodeTable* table = new (Z) ProfileCodeTable();
@@ -2850,7 +2721,7 @@
   EXPECT_EQ(table->FindCodeForPC(42), static_cast<ProfileCode*>(NULL));
 
   int64_t timestamp = 0;
-  Code& null_code = Code::Handle(Z);
+  const AbstractCode null_code(Code::null());
 
   ProfileCode* code1 = new (Z)
       ProfileCode(ProfileCode::kNativeCode, 50, 60, timestamp, null_code);
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 76a2569..3dbbd42 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -10,6 +10,7 @@
 #include "vm/heap/freelist.h"
 #include "vm/isolate.h"
 #include "vm/object.h"
+#include "vm/runtime_entry.h"
 #include "vm/visitor.h"
 
 namespace dart {
@@ -298,9 +299,21 @@
       break;
   }
 
+#if defined(DEBUG)
   ASSERT(size != 0);
-  ASSERT(size == Size());
+  const intptr_t expected_size = Size();
+
+  // In general we expect that visitors return exactly the same size that Size
+  // would compute. However in case of Arrays we might have a discrepancy when
+  // concurrently visiting an array that is being shrunk with
+  // Array::MakeFixedLength: the visitor might have visited the full array while
+  // here we are observing a smaller Size().
+  ASSERT(size == expected_size ||
+         (class_id == kArrayCid && size > expected_size));
+  return size;  // Prefer larger size.
+#else
   return size;
+#endif
 }
 
 bool RawObject::FindObject(FindObjectVisitor* visitor) {
@@ -369,7 +382,7 @@
   }
 
 REGULAR_VISITOR(Class)
-REGULAR_VISITOR(UnresolvedClass)
+REGULAR_VISITOR(Bytecode)
 REGULAR_VISITOR(Type)
 REGULAR_VISITOR(TypeRef)
 REGULAR_VISITOR(TypeParameter)
@@ -507,9 +520,8 @@
 }
 
 bool RawCode::ContainsPC(RawObject* raw_obj, uword pc) {
-  uint32_t tags = raw_obj->ptr()->tags_;
-  if (RawObject::ClassIdTag::decode(tags) == kCodeCid) {
-    RawCode* raw_code = reinterpret_cast<RawCode*>(raw_obj);
+  if (raw_obj->IsCode()) {
+    RawCode* raw_code = static_cast<RawCode*>(raw_obj);
     return RawInstructions::ContainsPC(raw_code->ptr()->instructions_, pc);
   }
   return false;
@@ -543,6 +555,17 @@
 #endif
 }
 
+bool RawBytecode::ContainsPC(RawObject* raw_obj, uword pc) {
+  if (raw_obj->IsBytecode()) {
+    RawBytecode* raw_bytecode = static_cast<RawBytecode*>(raw_obj);
+    RawExternalTypedData* bytes = raw_bytecode->ptr()->instructions_;
+    uword start = reinterpret_cast<uword>(bytes->ptr()->data_);
+    uword size = Smi::Value(bytes->ptr()->length_);
+    return (pc - start) < size;
+  }
+  return false;
+}
+
 intptr_t RawObjectPool::VisitObjectPoolPointers(RawObjectPool* raw_obj,
                                                 ObjectPointerVisitor* visitor) {
   const intptr_t length = raw_obj->ptr()->length_;
@@ -593,4 +616,19 @@
   return RawArray::VisitArrayPointers(raw_obj, visitor);
 }
 
+void RawObject::RememberCard(RawObject* const* slot) {
+  HeapPage::Of(this)->RememberCard(slot);
+}
+
+DEFINE_LEAF_RUNTIME_ENTRY(void,
+                          RememberCard,
+                          2,
+                          RawObject* object,
+                          RawObject** slot) {
+  ASSERT(object->IsOldObject());
+  ASSERT(object->IsCardRemembered());
+  HeapPage::Of(object)->RememberCard(slot);
+}
+END_LEAF_RUNTIME_ENTRY
+
 }  // namespace dart
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 98d2b44..a617d89 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -22,7 +22,6 @@
 // Macrobatics to define the Object hierarchy of VM implementation classes.
 #define CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V)                           \
   V(Class)                                                                     \
-  V(UnresolvedClass)                                                           \
   V(PatchClass)                                                                \
   V(Function)                                                                  \
   V(ClosureData)                                                               \
@@ -34,6 +33,7 @@
   V(Namespace)                                                                 \
   V(KernelProgramInfo)                                                         \
   V(Code)                                                                      \
+  V(Bytecode)                                                                  \
   V(Instructions)                                                              \
   V(ObjectPool)                                                                \
   V(PcDescriptors)                                                             \
@@ -241,6 +241,11 @@
 #undef V
 };
 
+enum class MemoryOrder {
+  kRelaxed,
+  kRelease,
+};
+
 #define SNAPSHOT_WRITER_SUPPORT()                                              \
   void WriteTo(SnapshotWriter* writer, intptr_t object_id,                     \
                Snapshot::Kind kind, bool as_reference);                        \
@@ -287,7 +292,7 @@
   // The tags field which is a part of the object header uses the following
   // bit fields for storing tags.
   enum TagBits {
-    kReservedBit = 0,
+    kCardRememberedBit = 0,
     kOldAndNotMarkedBit = 1,      // Incremental barrier target.
     kNewBit = 2,                  // Generational barrier target.
     kOldBit = 3,                  // Incremental barrier source.
@@ -315,7 +320,7 @@
   // The bit in the Smi tag position must be something that can be set to 0
   // for a dead filler object of either generation.
   // See Object::MakeUnusedSpaceTraversable.
-  COMPILE_ASSERT(kReservedBit == 0);
+  COMPILE_ASSERT(kCardRememberedBit == 0);
 
   COMPILE_ASSERT(kClassIdTagSize == (sizeof(classid_t) * kBitsPerByte));
 
@@ -354,6 +359,9 @@
   class ClassIdTag
       : public BitField<uint32_t, intptr_t, kClassIdTagPos, kClassIdTagSize> {};
 
+  class CardRememberedBit
+      : public BitField<uint32_t, bool, kCardRememberedBit, 1> {};
+
   class OldAndNotMarkedBit
       : public BitField<uint32_t, bool, kOldAndNotMarkedBit, 1> {};
 
@@ -388,6 +396,12 @@
     uword addr = reinterpret_cast<uword>(this);
     return (addr & kNewObjectAlignmentOffset) == kNewObjectAlignmentOffset;
   }
+  bool IsNewObjectMayBeSmi() const {
+    static const uword kNewObjectBits =
+        (kNewObjectAlignmentOffset | kHeapObjectTag);
+    const uword addr = reinterpret_cast<uword>(this);
+    return (addr & kObjectAlignmentMask) == kNewObjectBits;
+  }
   // Assumes this is a heap object.
   bool IsOldObject() const {
     ASSERT(IsHeapObject());
@@ -471,6 +485,7 @@
   }
   void SetRememberedBit() {
     ASSERT(!IsRemembered());
+    ASSERT(!IsCardRemembered());
     UpdateTagBit<OldAndNotRememberedBit>(false);
   }
   void ClearRememberedBit() {
@@ -478,6 +493,16 @@
     UpdateTagBit<OldAndNotRememberedBit>(true);
   }
 
+  bool IsCardRemembered() const {
+    return CardRememberedBit::decode(ptr()->tags_);
+  }
+  void SetCardRememberedBitUnsynchronized() {
+    ASSERT(!IsRemembered());
+    ASSERT(!IsCardRemembered());
+    uint32_t tags = ptr()->tags_;
+    ptr()->tags_ = CardRememberedBit::update(true, tags);
+  }
+
 #define DEFINE_IS_CID(clazz)                                                   \
   bool Is##clazz() const { return ((GetClassId() == k##clazz##Cid)); }
   CLASS_LIST(DEFINE_IS_CID)
@@ -685,9 +710,13 @@
   // methods below or their counterparts in Object, to ensure that the
   // write barrier is correctly applied.
 
-  template <typename type>
+  template <typename type, MemoryOrder order = MemoryOrder::kRelaxed>
   void StorePointer(type const* addr, type value) {
-    *const_cast<type*>(addr) = value;
+    if (order == MemoryOrder::kRelease) {
+      AtomicOperations::StoreRelease(const_cast<type*>(addr), value);
+    } else {
+      *const_cast<type*>(addr) = value;
+    }
     if (value->IsHeapObject()) {
       CheckHeapPointerStore(value, Thread::Current());
     }
@@ -724,6 +753,51 @@
     }
   }
 
+  template <typename type>
+  void StoreArrayPointer(type const* addr, type value) {
+    *const_cast<type*>(addr) = value;
+    if (value->IsHeapObject()) {
+      CheckArrayPointerStore(addr, value, Thread::Current());
+    }
+  }
+
+  template <typename type>
+  void StoreArrayPointer(type const* addr, type value, Thread* thread) {
+    *const_cast<type*>(addr) = value;
+    if (value->IsHeapObject()) {
+      CheckArrayPointerStore(addr, value, thread);
+    }
+  }
+
+  template <typename type>
+  DART_FORCE_INLINE void CheckArrayPointerStore(type const* addr,
+                                                RawObject* value,
+                                                Thread* thread) {
+    uint32_t source_tags = this->ptr()->tags_;
+    uint32_t target_tags = value->ptr()->tags_;
+    if (((source_tags >> kBarrierOverlapShift) & target_tags &
+         thread->write_barrier_mask()) != 0) {
+      if (value->IsNewObject()) {
+        // Generational barrier: record when a store creates an
+        // old-and-not-remembered -> new reference.
+        ASSERT(!this->IsRemembered());
+        if (this->IsCardRemembered()) {
+          RememberCard(reinterpret_cast<RawObject* const*>(addr));
+        } else {
+          this->SetRememberedBit();
+          Thread::Current()->StoreBufferAddObject(this);
+        }
+      } else {
+        // Incremental barrier: record when a store creates an
+        // old -> old-and-not-marked reference.
+        ASSERT(value->IsOldObject());
+        if (value->TryAcquireMarkBit()) {
+          thread->MarkingStackAddObject(value);
+        }
+      }
+    }
+  }
+
   // Use for storing into an explicitly Smi-typed field of an object
   // (i.e., both the previous and new value are Smis).
   void StoreSmi(RawSmi* const* addr, RawSmi* value) {
@@ -732,6 +806,10 @@
     *const_cast<RawSmi**>(addr) = value;
   }
 
+ protected:
+  friend class StoreBufferUpdateVisitor;  // RememberCard
+  void RememberCard(RawObject* const* slot);
+
   friend class Api;
   friend class ApiMessageReader;  // GetClassId
   friend class Serializer;        // GetClassId
@@ -881,17 +959,6 @@
   friend class CidRewriteVisitor;
 };
 
-class RawUnresolvedClass : public RawObject {
-  RAW_HEAP_OBJECT_IMPLEMENTATION(UnresolvedClass);
-
-  VISIT_FROM(RawObject*, library_or_library_prefix_);
-  RawObject* library_or_library_prefix_;  // Library or library prefix qualifier
-                                          // for the ident.
-  RawString* ident_;                      // Name of the unresolved identifier.
-  VISIT_TO(RawObject*, ident_);
-  TokenPosition token_pos_;
-};
-
 class RawPatchClass : public RawObject {
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(PatchClass);
@@ -1000,7 +1067,7 @@
     return reinterpret_cast<RawObject**>(&ptr()->ic_data_array_);
   }
   RawCode* code_;  // Currently active code. Accessed from generated code.
-  NOT_IN_PRECOMPILED(RawCode* bytecode_);
+  NOT_IN_PRECOMPILED(RawBytecode* bytecode_);
   NOT_IN_PRECOMPILED(RawCode* unoptimized_code_);  // Unoptimized code, keep it
                                                    // after optimization.
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -1398,6 +1465,25 @@
   friend class FunctionDeserializationCluster;
 };
 
+class RawBytecode : public RawObject {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(Bytecode);
+
+  VISIT_FROM(RawObject*, object_pool_);
+  RawObjectPool* object_pool_;
+  RawExternalTypedData* instructions_;
+  RawFunction* function_;
+  RawExceptionHandlers* exception_handlers_;
+  RawPcDescriptors* pc_descriptors_;
+  VISIT_TO(RawObject*, pc_descriptors_);
+
+  intptr_t source_positions_binary_offset_;
+
+  static bool ContainsPC(RawObject* raw_obj, uword pc);
+
+  friend class Function;
+  friend class StackFrame;
+};
+
 class RawObjectPool : public RawObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ObjectPool);
 
@@ -1928,8 +2014,7 @@
   RAW_HEAP_OBJECT_IMPLEMENTATION(Type);
 
   VISIT_FROM(RawObject*, type_class_id_)
-  // Either the id of the resolved class as a Smi or an UnresolvedClass.
-  RawObject* type_class_id_;
+  RawSmi* type_class_id_;
   RawTypeArguments* arguments_;
   RawSmi* hash_;
   // This type object represents a function type if its signature field is a
@@ -2174,6 +2259,8 @@
   friend class Object;
   friend class ICData;            // For high performance access.
   friend class SubtypeTestCache;  // For high performance access.
+
+  friend class HeapPage;
 };
 
 class RawImmutableArray : public RawArray {
@@ -2297,6 +2384,8 @@
   VISIT_TO(RawCompressed, length_)
 
   uint8_t* data_;
+
+  friend class RawBytecode;
 };
 
 // VM implementations of the basic types in the isolate.
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 94366af..54806bf 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -72,50 +72,6 @@
   }
 }
 
-RawUnresolvedClass* UnresolvedClass::ReadFrom(SnapshotReader* reader,
-                                              intptr_t object_id,
-                                              intptr_t tags,
-                                              Snapshot::Kind kind,
-                                              bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate unresolved class object.
-  UnresolvedClass& unresolved_class =
-      UnresolvedClass::ZoneHandle(reader->zone(), UnresolvedClass::New());
-  reader->AddBackRef(object_id, &unresolved_class, kIsDeserialized);
-
-  // Set all non object fields.
-  unresolved_class.set_token_pos(
-      TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
-
-  // Set all the object fields.
-  READ_OBJECT_FIELDS(unresolved_class, unresolved_class.raw()->from(),
-                     unresolved_class.raw()->to(), kAsReference);
-
-  return unresolved_class.raw();
-}
-
-void RawUnresolvedClass::WriteTo(SnapshotWriter* writer,
-                                 intptr_t object_id,
-                                 Snapshot::Kind kind,
-                                 bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kUnresolvedClassCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the non object pointer fields.
-  writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitPointers(from(), to());
-}
-
 RawAbstractType* AbstractType::ReadFrom(SnapshotReader* reader,
                                         intptr_t object_id,
                                         intptr_t tags,
@@ -695,6 +651,22 @@
   UNREACHABLE();
 }
 
+RawBytecode* Bytecode::ReadFrom(SnapshotReader* reader,
+                                intptr_t object_id,
+                                intptr_t tags,
+                                Snapshot::Kind kind,
+                                bool as_reference) {
+  UNREACHABLE();
+  return Bytecode::null();
+}
+
+void RawBytecode::WriteTo(SnapshotWriter* writer,
+                          intptr_t object_id,
+                          Snapshot::Kind kind,
+                          bool as_reference) {
+  UNREACHABLE();
+}
+
 RawInstructions* Instructions::ReadFrom(SnapshotReader* reader,
                                         intptr_t object_id,
                                         intptr_t tags,
diff --git a/runtime/vm/reusable_handles.h b/runtime/vm/reusable_handles.h
index 7c452bc..2c06da9 100644
--- a/runtime/vm/reusable_handles.h
+++ b/runtime/vm/reusable_handles.h
@@ -86,6 +86,8 @@
   ReusableClassHandleScope reused_class_handle(thread);
 #define REUSABLE_CODE_HANDLESCOPE(thread)                                      \
   ReusableCodeHandleScope reused_code_handle(thread);
+#define REUSABLE_BYTECODE_HANDLESCOPE(thread)                                  \
+  ReusableBytecodeHandleScope reused_bytecode_handle(thread);
 #define REUSABLE_ERROR_HANDLESCOPE(thread)                                     \
   ReusableErrorHandleScope reused_error_handle(thread);
 #define REUSABLE_EXCEPTION_HANDLERS_HANDLESCOPE(thread)                        \
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 5994aed..372493e 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -50,18 +50,6 @@
             trace_deoptimization_verbose,
             false,
             "Trace deoptimization verbose");
-DEFINE_FLAG(bool, trace_ic, false, "Trace IC handling");
-DEFINE_FLAG(bool,
-            trace_ic_miss_in_optimized,
-            false,
-            "Trace IC miss in optimized code");
-DEFINE_FLAG(bool,
-            trace_optimized_ic_calls,
-            false,
-            "Trace IC calls in optimized code.");
-DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code.");
-DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls");
-DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks.");
 
 DECLARE_FLAG(bool, enable_interpreter);
 DECLARE_FLAG(int, max_deoptimization_counter_threshold);
@@ -89,14 +77,6 @@
 DECLARE_FLAG(bool, reload_every_optimized);
 DECLARE_FLAG(bool, reload_every_back_off);
 
-#ifdef DEBUG
-DEFINE_FLAG(charp,
-            gc_at_instance_allocation,
-            NULL,
-            "Perform a GC before allocation of instances of "
-            "the specified class");
-#endif
-
 #if defined(TESTING) || defined(DEBUG)
 void VerifyOnTransition() {
   Thread* thread = Thread::Current();
@@ -127,49 +107,33 @@
   return function;
 }
 
-DEFINE_RUNTIME_ENTRY(TraceFunctionEntry, 1) {
-  const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
-  const String& function_name = String::Handle(function.name());
-  const String& class_name =
-      String::Handle(Class::Handle(function.Owner()).Name());
-  OS::PrintErr("> Entering '%s.%s'\n", class_name.ToCString(),
-               function_name.ToCString());
-}
-
-DEFINE_RUNTIME_ENTRY(TraceFunctionExit, 1) {
-  const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
-  const String& function_name = String::Handle(function.name());
-  const String& class_name =
-      String::Handle(Class::Handle(function.Owner()).Name());
-  OS::PrintErr("< Exiting '%s.%s'\n", class_name.ToCString(),
-               function_name.ToCString());
-}
-
 DEFINE_RUNTIME_ENTRY(RangeError, 2) {
-  const Instance& length = Instance::CheckedHandle(arguments.ArgAt(0));
-  const Instance& index = Instance::CheckedHandle(arguments.ArgAt(1));
+  const Instance& length = Instance::CheckedHandle(zone, arguments.ArgAt(0));
+  const Instance& index = Instance::CheckedHandle(zone, arguments.ArgAt(1));
   if (!length.IsInteger()) {
     // Throw: new ArgumentError.value(length, "length", "is not an integer");
-    const Array& args = Array::Handle(Array::New(3));
+    const Array& args = Array::Handle(zone, Array::New(3));
     args.SetAt(0, length);
     args.SetAt(1, Symbols::Length());
-    args.SetAt(2, String::Handle(String::New("is not an integer")));
+    args.SetAt(2, String::Handle(zone, String::New("is not an integer")));
     Exceptions::ThrowByType(Exceptions::kArgumentValue, args);
   }
   if (!index.IsInteger()) {
     // Throw: new ArgumentError.value(index, "index", "is not an integer");
-    const Array& args = Array::Handle(Array::New(3));
+    const Array& args = Array::Handle(zone, Array::New(3));
     args.SetAt(0, index);
     args.SetAt(1, Symbols::Index());
-    args.SetAt(2, String::Handle(String::New("is not an integer")));
+    args.SetAt(2, String::Handle(zone, String::New("is not an integer")));
     Exceptions::ThrowByType(Exceptions::kArgumentValue, args);
   }
   // Throw: new RangeError.range(index, 0, length - 1, "length");
-  const Array& args = Array::Handle(Array::New(4));
+  const Array& args = Array::Handle(zone, Array::New(4));
   args.SetAt(0, index);
-  args.SetAt(1, Integer::Handle(Integer::New(0)));
-  args.SetAt(2, Integer::Handle(Integer::Cast(length).ArithmeticOp(
-                    Token::kSUB, Integer::Handle(Integer::New(1)))));
+  args.SetAt(1, Integer::Handle(zone, Integer::New(0)));
+  args.SetAt(
+      2, Integer::Handle(
+             zone, Integer::Cast(length).ArithmeticOp(
+                       Token::kSUB, Integer::Handle(zone, Integer::New(1)))));
   args.SetAt(3, Symbols::Length());
   Exceptions::ThrowByType(Exceptions::kRange, args);
 }
@@ -201,6 +165,7 @@
                              StackFrameIterator::kNoCrossThreadIteration);
   const StackFrame* caller_frame = iterator.NextFrame();
   ASSERT(caller_frame->IsDartFrame());
+  ASSERT(!caller_frame->is_interpreted());
   const Code& code = Code::Handle(zone, caller_frame->LookupDartCode());
   const uword pc_offset = caller_frame->pc() - code.PayloadStart();
 
@@ -225,12 +190,12 @@
 }
 
 DEFINE_RUNTIME_ENTRY(NullErrorWithSelector, 1) {
-  const String& selector = String::CheckedHandle(arguments.ArgAt(0));
+  const String& selector = String::CheckedHandle(zone, arguments.ArgAt(0));
   NullErrorHelper(zone, selector);
 }
 
 DEFINE_RUNTIME_ENTRY(ArgumentError, 1) {
-  const Instance& value = Instance::CheckedHandle(arguments.ArgAt(0));
+  const Instance& value = Instance::CheckedHandle(zone, arguments.ArgAt(0));
   Exceptions::ThrowArgumentError(value);
 }
 
@@ -242,7 +207,7 @@
 }
 
 DEFINE_RUNTIME_ENTRY(IntegerDivisionByZeroException, 0) {
-  const Array& args = Array::Handle(Array::New(0));
+  const Array& args = Array::Handle(zone, Array::New(0));
   Exceptions::ThrowByType(Exceptions::kIntegerDivisionByZeroException, args);
 }
 
@@ -266,37 +231,39 @@
 // Arg1: array type arguments, i.e. vector of 1 type, the element type.
 // Return value: newly allocated array of length arg0.
 DEFINE_RUNTIME_ENTRY(AllocateArray, 2) {
-  const Instance& length = Instance::CheckedHandle(arguments.ArgAt(0));
+  const Instance& length = Instance::CheckedHandle(zone, arguments.ArgAt(0));
   if (!length.IsInteger()) {
     // Throw: new ArgumentError.value(length, "length", "is not an integer");
-    const Array& args = Array::Handle(Array::New(3));
+    const Array& args = Array::Handle(zone, Array::New(3));
     args.SetAt(0, length);
     args.SetAt(1, Symbols::Length());
-    args.SetAt(2, String::Handle(String::New("is not an integer")));
+    args.SetAt(2, String::Handle(zone, String::New("is not an integer")));
     Exceptions::ThrowByType(Exceptions::kArgumentValue, args);
   }
   if (length.IsSmi()) {
     const intptr_t len = Smi::Cast(length).Value();
     if ((len >= 0) && (len <= Array::kMaxElements)) {
-      const Array& array = Array::Handle(Array::New(len, Heap::kNew));
+      const Array& array = Array::Handle(zone, Array::New(len, Heap::kNew));
       arguments.SetReturn(array);
       TypeArguments& element_type =
-          TypeArguments::CheckedHandle(arguments.ArgAt(1));
+          TypeArguments::CheckedHandle(zone, arguments.ArgAt(1));
       // An Array is raw or takes one type argument. However, its type argument
       // vector may be longer than 1 due to a type optimization reusing the type
       // argument vector of the instantiator.
       ASSERT(element_type.IsNull() ||
              ((element_type.Length() >= 1) && element_type.IsInstantiated()));
       array.SetTypeArguments(element_type);  // May be null.
-      EnsureNewOrRemembered(isolate, thread, array);
+      if (!array.raw()->IsCardRemembered()) {
+        EnsureNewOrRemembered(isolate, thread, array);
+      }
       return;
     }
   }
   // Throw: new RangeError.range(length, 0, Array::kMaxElements, "length");
-  const Array& args = Array::Handle(Array::New(4));
+  const Array& args = Array::Handle(zone, Array::New(4));
   args.SetAt(0, length);
-  args.SetAt(1, Integer::Handle(Integer::New(0)));
-  args.SetAt(2, Integer::Handle(Integer::New(Array::kMaxElements)));
+  args.SetAt(1, Integer::Handle(zone, Integer::New(0)));
+  args.SetAt(2, Integer::Handle(zone, Integer::New(Array::kMaxElements)));
   args.SetAt(3, Symbols::Length());
   Exceptions::ThrowByType(Exceptions::kRange, args);
 }
@@ -315,29 +282,18 @@
 // Arg1: type arguments of the object that needs to be allocated.
 // Return value: newly allocated object.
 DEFINE_RUNTIME_ENTRY(AllocateObject, 2) {
-  const Class& cls = Class::CheckedHandle(arguments.ArgAt(0));
-
-#ifdef DEBUG
-  if (FLAG_gc_at_instance_allocation != NULL) {
-    const String& name = String::Handle(cls.Name());
-    if (String::EqualsIgnoringPrivateKey(
-            name,
-            String::Handle(String::New(FLAG_gc_at_instance_allocation)))) {
-      Isolate::Current()->heap()->CollectAllGarbage(Heap::kDebugging);
-    }
-  }
-#endif
-  Heap::Space space = Heap::kNew;
-  const Instance& instance = Instance::Handle(Instance::New(cls, space));
+  const Class& cls = Class::CheckedHandle(zone, arguments.ArgAt(0));
+  const Instance& instance =
+      Instance::Handle(zone, Instance::New(cls, Heap::kNew));
 
   arguments.SetReturn(instance);
   if (cls.NumTypeArguments() == 0) {
     // No type arguments required for a non-parameterized type.
-    ASSERT(Instance::CheckedHandle(arguments.ArgAt(1)).IsNull());
+    ASSERT(Instance::CheckedHandle(zone, arguments.ArgAt(1)).IsNull());
     return;
   }
   TypeArguments& type_arguments =
-      TypeArguments::CheckedHandle(arguments.ArgAt(1));
+      TypeArguments::CheckedHandle(zone, arguments.ArgAt(1));
   // Unless null (for a raw type), the type argument vector may be longer than
   // necessary due to a type optimization reusing the type argument vector of
   // the instantiator.
@@ -483,7 +439,8 @@
 // Return value: newly allocated context.
 DEFINE_RUNTIME_ENTRY(AllocateContext, 1) {
   const Smi& num_variables = Smi::CheckedHandle(zone, arguments.ArgAt(0));
-  const Context& context = Context::Handle(Context::New(num_variables.Value()));
+  const Context& context =
+      Context::Handle(zone, Context::New(num_variables.Value()));
   arguments.SetReturn(context);
   if (Heap::IsAllocatableInNewSpace(
           Context::InstanceSize(num_variables.Value()))) {
@@ -499,7 +456,7 @@
   const Context& ctx = Context::CheckedHandle(zone, arguments.ArgAt(0));
   Context& cloned_ctx =
       Context::Handle(zone, Context::New(ctx.num_variables()));
-  cloned_ctx.set_parent(Context::Handle(ctx.parent()));
+  cloned_ctx.set_parent(Context::Handle(zone, ctx.parent()));
   Object& inst = Object::Handle(zone);
   for (int i = 0; i < ctx.num_variables(); i++) {
     inst = ctx.At(i);
@@ -889,6 +846,7 @@
       DartFrameIterator iterator(thread,
                                  StackFrameIterator::kNoCrossThreadIteration);
       StackFrame* caller_frame = iterator.NextFrame();
+      ASSERT(!caller_frame->is_interpreted());
       const Code& caller_code =
           Code::Handle(zone, caller_frame->LookupDartCode());
       const ObjectPool& pool =
@@ -926,6 +884,7 @@
       DartFrameIterator iterator(thread,
                                  StackFrameIterator::kNoCrossThreadIteration);
       StackFrame* caller_frame = iterator.NextFrame();
+      ASSERT(!caller_frame->is_interpreted());
       const Code& caller_code =
           Code::Handle(zone, caller_frame->LookupDartCode());
       const ObjectPool& pool =
@@ -1027,6 +986,7 @@
                              StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* caller_frame = iterator.NextFrame();
   ASSERT(caller_frame != NULL);
+  ASSERT(!caller_frame->is_interpreted());
   const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode());
   ASSERT(!caller_code.IsNull());
   ASSERT(caller_code.is_optimized());
@@ -1228,9 +1188,12 @@
     if (ic_data.IsTrackingExactness()) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
       const auto& receiver = *args[0];
-      const auto state = StaticTypeExactnessState::Compute(
-          Type::Cast(AbstractType::Handle(ic_data.StaticReceiverType())),
-          receiver);
+      const auto state = receiver.IsNull()
+                             ? StaticTypeExactnessState::NotExact()
+                             : StaticTypeExactnessState::Compute(
+                                   Type::Cast(AbstractType::Handle(
+                                       ic_data.StaticReceiverType())),
+                                   receiver);
       ic_data.AddReceiverCheck(
           receiver.GetClassId(), target_function,
           /*count=*/1, /*exactness=*/state.CollapseSuperTypeExactness());
@@ -1279,8 +1242,8 @@
 //   Returns: target function with compiled code or null.
 // Modifies the instance call to hold the updated IC data array.
 DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerOneArg, 2) {
-  const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
-  const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
+  const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
+  const ICData& ic_data = ICData::CheckedHandle(zone, arguments.ArgAt(1));
   GrowableArray<const Instance*> args(1);
   args.Add(&receiver);
   const Function& result =
@@ -1295,9 +1258,9 @@
 //   Returns: target function with compiled code or null.
 // Modifies the instance call to hold the updated IC data array.
 DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerTwoArgs, 3) {
-  const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
-  const Instance& other = Instance::CheckedHandle(arguments.ArgAt(1));
-  const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(2));
+  const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
+  const Instance& other = Instance::CheckedHandle(zone, arguments.ArgAt(1));
+  const ICData& ic_data = ICData::CheckedHandle(zone, arguments.ArgAt(2));
   GrowableArray<const Instance*> args(2);
   args.Add(&receiver);
   args.Add(&other);
@@ -1311,8 +1274,8 @@
 // Arg0: argument.
 // Arg1: IC data object.
 DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerOneArg, 2) {
-  const Instance& arg = Instance::CheckedHandle(arguments.ArgAt(0));
-  const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
+  const Instance& arg = Instance::CheckedHandle(zone, arguments.ArgAt(0));
+  const ICData& ic_data = ICData::CheckedHandle(zone, arguments.ArgAt(1));
   // IC data for static call is prepopulated with the statically known target.
   ASSERT(ic_data.NumberOfChecksIs(1));
   const Function& target = Function::Handle(ic_data.GetTargetAt(0));
@@ -1336,9 +1299,9 @@
 // Arg1: argument 1.
 // Arg2: IC data object.
 DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerTwoArgs, 3) {
-  const Instance& arg0 = Instance::CheckedHandle(arguments.ArgAt(0));
-  const Instance& arg1 = Instance::CheckedHandle(arguments.ArgAt(1));
-  const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(2));
+  const Instance& arg0 = Instance::CheckedHandle(zone, arguments.ArgAt(0));
+  const Instance& arg1 = Instance::CheckedHandle(zone, arguments.ArgAt(1));
+  const ICData& ic_data = ICData::CheckedHandle(zone, arguments.ArgAt(2));
   // IC data for static call is prepopulated with the statically known target.
   ASSERT(!ic_data.NumberOfChecksIs(0));
   const Function& target = Function::Handle(ic_data.GetTargetAt(0));
@@ -1855,9 +1818,10 @@
 // Arg1: arguments descriptor array.
 // Arg2: arguments array.
 DEFINE_RUNTIME_ENTRY(InvokeClosureNoSuchMethod, 3) {
-  const Closure& receiver = Closure::CheckedHandle(arguments.ArgAt(0));
-  const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(1));
-  const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(2));
+  const Closure& receiver = Closure::CheckedHandle(zone, arguments.ArgAt(0));
+  const Array& orig_arguments_desc =
+      Array::CheckedHandle(zone, arguments.ArgAt(1));
+  const Array& orig_arguments = Array::CheckedHandle(zone, arguments.ArgAt(2));
 
   // For closure the function name is always 'call'. Replace it with the
   // name of the closurized function so that exception contains more
@@ -1908,21 +1872,29 @@
                                StackFrameIterator::kNoCrossThreadIteration);
     StackFrame* frame = iterator.NextFrame();
     ASSERT(frame != NULL);
-    const Code& code = Code::Handle(frame->LookupDartCode());
-    ASSERT(!code.IsNull());
-    const Function& function = Function::Handle(code.function());
+    Code& code = Code::Handle();
+    Function& function = Function::Handle();
+    if (frame->is_interpreted()) {
+      function = frame->LookupDartFunction();
+    } else {
+      code = frame->LookupDartCode();
+      ASSERT(!code.IsNull());
+      function = code.function();
+    }
     ASSERT(!function.IsNull());
     const char* function_name = function.ToFullyQualifiedCString();
     ASSERT(function_name != NULL);
-    if (!code.is_optimized() && FLAG_reload_every_optimized) {
-      // Don't do the reload if we aren't inside optimized code.
-      do_reload = false;
-    }
-    if (code.is_optimized() && FLAG_deoptimize_filter != NULL &&
-        strstr(function_name, FLAG_deoptimize_filter) != NULL) {
-      OS::PrintErr("*** Forcing deoptimization (%s)\n",
-                   function.ToFullyQualifiedCString());
-      do_deopt = true;
+    if (!code.IsNull()) {
+      if (!code.is_optimized() && FLAG_reload_every_optimized) {
+        // Don't do the reload if we aren't inside optimized code.
+        do_reload = false;
+      }
+      if (code.is_optimized() && FLAG_deoptimize_filter != NULL &&
+          strstr(function_name, FLAG_deoptimize_filter) != NULL) {
+        OS::PrintErr("*** Forcing deoptimization (%s)\n",
+                     function.ToFullyQualifiedCString());
+        do_deopt = true;
+      }
     }
     if (FLAG_stacktrace_filter != NULL &&
         strstr(function_name, FLAG_stacktrace_filter) != NULL) {
@@ -2137,8 +2109,8 @@
 }
 
 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) {
-  const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0));
-  const Function& function = Function::CheckedHandle(arguments.ArgAt(1));
+  const ICData& ic_data = ICData::CheckedHandle(zone, arguments.ArgAt(0));
+  const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(1));
   DartFrameIterator iterator(thread,
                              StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = iterator.NextFrame();
@@ -2158,13 +2130,11 @@
   ASSERT(!function.IsNull());
 
   // If running with interpreter, do the unoptimized compilation first.
-  const bool unoptimized_compilation =
-      FLAG_enable_interpreter &&
-      (function.unoptimized_code() == Object::null());
+  const bool optimizing_compilation = function.ShouldCompilerOptimize();
+  ASSERT(FLAG_enable_interpreter || optimizing_compilation);
+  ASSERT((!optimizing_compilation) || function.HasCode());
 
-  ASSERT(unoptimized_compilation || function.HasCode());
-
-  if (unoptimized_compilation ||
+  if ((!optimizing_compilation) ||
       Compiler::CanOptimizeFunction(thread, function)) {
     if (FLAG_background_compilation) {
       Field& field = Field::Handle(zone, isolate->GetDeoptimizingBoxedField());
@@ -2211,8 +2181,12 @@
                   function.ToFullyQualifiedCString());
       }
     }
-    const Object& result = Object::Handle(
-        zone, Compiler::CompileOptimizedFunction(thread, function));
+    Object& result = Object::Handle(zone);
+    if (optimizing_compilation) {
+      result = Compiler::CompileOptimizedFunction(thread, function);
+    } else {
+      result = Compiler::CompileFunction(thread, function);
+    }
     if (result.IsError()) {
       Exceptions::PropagateError(Error::Cast(result));
     }
@@ -2398,9 +2372,11 @@
   StackFrame* frame = iterator.NextFrame();
   Code& optimized_code = Code::Handle();
   while (frame != NULL) {
-    optimized_code = frame->LookupDartCode();
-    if (optimized_code.is_optimized()) {
-      DeoptimizeAt(optimized_code, frame);
+    if (!frame->is_interpreted()) {
+      optimized_code = frame->LookupDartCode();
+      if (optimized_code.is_optimized()) {
+        DeoptimizeAt(optimized_code, frame);
+      }
     }
     frame = iterator.NextFrame();
   }
@@ -2623,7 +2599,7 @@
 //   Arg1: Value that is being stored.
 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  const Field& field = Field::CheckedHandle(arguments.ArgAt(0));
+  const Field& field = Field::CheckedHandle(zone, arguments.ArgAt(0));
   const Object& value = Object::Handle(arguments.ArgAt(1));
   field.RecordStore(value);
 #else
@@ -2632,7 +2608,7 @@
 }
 
 DEFINE_RUNTIME_ENTRY(InitStaticField, 1) {
-  const Field& field = Field::CheckedHandle(arguments.ArgAt(0));
+  const Field& field = Field::CheckedHandle(zone, arguments.ArgAt(0));
   field.EvaluateInitializer();
 }
 
diff --git a/runtime/vm/runtime_entry.h b/runtime/vm/runtime_entry.h
index b337cea..e0c9e56 100644
--- a/runtime/vm/runtime_entry.h
+++ b/runtime/vm/runtime_entry.h
@@ -10,27 +10,13 @@
 #include "vm/heap/safepoint.h"
 #include "vm/native_arguments.h"
 #include "vm/runtime_entry_list.h"
-#include "vm/tags.h"
 
 namespace dart {
 
 class Assembler;
 
-DECLARE_FLAG(bool, trace_runtime_calls);
-
 typedef void (*RuntimeFunction)(NativeArguments arguments);
 
-enum RuntimeFunctionId {
-  kNoRuntimeFunctionId = -1,
-#define DECLARE_ENUM_VALUE(name) k##name##Id,
-  RUNTIME_ENTRY_LIST(DECLARE_ENUM_VALUE)
-#undef DECLARE_ENUM_VALUE
-
-#define DECLARE_LEAF_ENUM_VALUE(type, name, ...) k##name##Id,
-      LEAF_RUNTIME_ENTRY_LIST(DECLARE_LEAF_ENUM_VALUE)
-#undef DECLARE_LEAF_ENUM_VALUE
-};
-
 // Class RuntimeEntry is used to encapsulate runtime functions, it includes
 // the entry point for the runtime function and the number of arguments expected
 // by the function.
@@ -45,10 +31,7 @@
         function_(function),
         argument_count_(argument_count),
         is_leaf_(is_leaf),
-        is_float_(is_float),
-        next_(NULL) {
-    VMTag::RegisterRuntimeEntry(this);
-  }
+        is_float_(is_float) {}
 
   const char* name() const { return name_; }
   RuntimeFunction function() const { return function_; }
@@ -61,12 +44,6 @@
   NOT_IN_PRECOMPILED(void Call(Assembler* assembler, intptr_t argument_count)
                          const);
 
-  void set_next(const RuntimeEntry* next) { next_ = next; }
-  const RuntimeEntry* next() const { return next_; }
-
-  static inline uword AddressFromId(RuntimeFunctionId id);
-  static inline RuntimeFunctionId RuntimeFunctionIdFromAddress(uword address);
-
   static uword InterpretCallEntry();
   static RawObject* InterpretCall(RawFunction* function,
                                   RawArray* argdesc,
@@ -75,17 +52,16 @@
                                   Thread* thread);
 
  private:
-  const char* name_;
+  const char* const name_;
   const RuntimeFunction function_;
   const intptr_t argument_count_;
   const bool is_leaf_;
   const bool is_float_;
-  const RuntimeEntry* next_;
 
   DISALLOW_COPY_AND_ASSIGN(RuntimeEntry);
 };
 
-#ifndef PRODUCT
+#ifdef DEBUG
 #define TRACE_RUNTIME_CALL(format, name)                                       \
   if (FLAG_trace_runtime_calls) {                                              \
     THR_Print("Runtime call: " format "\n", name);                             \
@@ -152,38 +128,6 @@
 RUNTIME_ENTRY_LIST(DECLARE_RUNTIME_ENTRY)
 LEAF_RUNTIME_ENTRY_LIST(DECLARE_LEAF_RUNTIME_ENTRY)
 
-uword RuntimeEntry::AddressFromId(RuntimeFunctionId id) {
-  switch (id) {
-#define DEFINE_RUNTIME_CASE(name)                                              \
-  case k##name##Id:                                                            \
-    return k##name##RuntimeEntry.GetEntryPoint();
-    RUNTIME_ENTRY_LIST(DEFINE_RUNTIME_CASE)
-#undef DEFINE_RUNTIME_CASE
-
-#define DEFINE_LEAF_RUNTIME_CASE(type, name, ...)                              \
-  case k##name##Id:                                                            \
-    return k##name##RuntimeEntry.GetEntryPoint();
-    LEAF_RUNTIME_ENTRY_LIST(DEFINE_LEAF_RUNTIME_CASE)
-#undef DEFINE_LEAF_RUNTIME_CASE
-    default:
-      break;
-  }
-  return 0;
-}
-
-RuntimeFunctionId RuntimeEntry::RuntimeFunctionIdFromAddress(uword address) {
-#define CHECK_RUNTIME_ADDRESS(name)                                            \
-  if (address == k##name##RuntimeEntry.GetEntryPoint()) return k##name##Id;
-  RUNTIME_ENTRY_LIST(CHECK_RUNTIME_ADDRESS)
-#undef CHECK_RUNTIME_ADDRESS
-
-#define CHECK_LEAF_RUNTIME_ADDRESS(type, name, ...)                            \
-  if (address == k##name##RuntimeEntry.GetEntryPoint()) return k##name##Id;
-  LEAF_RUNTIME_ENTRY_LIST(CHECK_LEAF_RUNTIME_ADDRESS)
-#undef CHECK_LEAF_RUNTIME_ADDRESS
-  return kNoRuntimeFunctionId;
-}
-
 const char* DeoptReasonToCString(ICData::DeoptReasonId deopt_reason);
 
 void DeoptimizeAt(const Code& optimized_code, StackFrame* frame);
diff --git a/runtime/vm/runtime_entry_arm.cc b/runtime/vm/runtime_entry_arm.cc
index 8f44e23..4b19f0d 100644
--- a/runtime/vm/runtime_entry_arm.cc
+++ b/runtime/vm/runtime_entry_arm.cc
@@ -45,7 +45,11 @@
 void RuntimeEntry::Call(Assembler* assembler, intptr_t argument_count) const {
   if (is_leaf()) {
     ASSERT(argument_count == this->argument_count());
-    __ BranchLinkOffset(THR, Thread::OffsetFromThread(this));
+    __ LoadFromOffset(kWord, TMP, THR, Thread::OffsetFromThread(this));
+    __ str(TMP, Address(THR, Thread::vm_tag_offset()));
+    __ blx(TMP);
+    __ LoadImmediate(TMP, VMTag::kDartCompiledTagId);
+    __ str(TMP, Address(THR, Thread::vm_tag_offset()));
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
diff --git a/runtime/vm/runtime_entry_arm64.cc b/runtime/vm/runtime_entry_arm64.cc
index 04a80e6..250e05f 100644
--- a/runtime/vm/runtime_entry_arm64.cc
+++ b/runtime/vm/runtime_entry_arm64.cc
@@ -61,7 +61,10 @@
     __ ReserveAlignedFrameSpace(0);
     __ mov(CSP, SP);
     __ ldr(TMP, Address(THR, Thread::OffsetFromThread(this)));
+    __ str(TMP, Address(THR, Thread::vm_tag_offset()));
     __ blr(TMP);
+    __ LoadImmediate(TMP, VMTag::kDartCompiledTagId);
+    __ str(TMP, Address(THR, Thread::vm_tag_offset()));
     __ mov(SP, R25);
     __ mov(CSP, R23);
   } else {
diff --git a/runtime/vm/runtime_entry_ia32.cc b/runtime/vm/runtime_entry_ia32.cc
index 917f6cc..26f300e 100644
--- a/runtime/vm/runtime_entry_ia32.cc
+++ b/runtime/vm/runtime_entry_ia32.cc
@@ -30,8 +30,10 @@
 void RuntimeEntry::Call(Assembler* assembler, intptr_t argument_count) const {
   if (is_leaf()) {
     ASSERT(argument_count == this->argument_count());
-    ExternalLabel label(GetEntryPoint());
-    __ call(&label);
+    __ movl(EAX, Immediate(GetEntryPoint()));
+    __ movl(Assembler::VMTagAddress(), EAX);
+    __ call(EAX);
+    __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index 1ddd02b..5bafc0e 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -46,8 +46,6 @@
   V(ReThrow)                                                                   \
   V(StackOverflow)                                                             \
   V(Throw)                                                                     \
-  V(TraceFunctionEntry)                                                        \
-  V(TraceFunctionExit)                                                         \
   V(DeoptimizeMaterialize)                                                     \
   V(RewindPostDeopt)                                                           \
   V(UpdateFieldCid)                                                            \
@@ -63,6 +61,7 @@
   V(void, DeoptimizeFillFrame, uword)                                          \
   V(void, StoreBufferBlockProcess, Thread*)                                    \
   V(void, MarkingStackBlockProcess, Thread*)                                   \
+  V(void, RememberCard, RawObject*, RawObject**)                               \
   V(double, LibcPow, double, double)                                           \
   V(double, DartModulo, double, double)                                        \
   V(double, LibcFloor, double)                                                 \
diff --git a/runtime/vm/runtime_entry_x64.cc b/runtime/vm/runtime_entry_x64.cc
index 105d71c..0875c69 100644
--- a/runtime/vm/runtime_entry_x64.cc
+++ b/runtime/vm/runtime_entry_x64.cc
@@ -29,7 +29,9 @@
     ASSERT(argument_count == this->argument_count());
     COMPILE_ASSERT(CallingConventions::kVolatileCpuRegisters & (1 << RAX));
     __ movq(RAX, Address(THR, Thread::OffsetFromThread(this)));
+    __ movq(Assembler::VMTagAddress(), RAX);
     __ CallCFunction(RAX);
+    __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
diff --git a/runtime/vm/scanner.cc b/runtime/vm/scanner.cc
deleted file mode 100644
index 765c869..0000000
--- a/runtime/vm/scanner.cc
+++ /dev/null
@@ -1,918 +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/scanner.h"
-
-#include "platform/assert.h"
-#include "vm/dart.h"
-#include "vm/flags.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
-#include "vm/symbols.h"
-#include "vm/token.h"
-#include "vm/unicode.h"
-
-namespace dart {
-
-// Quick access to the locally defined zone() and thread() methods.
-#define Z (zone())
-#define T (thread())
-
-class ScanContext : public ZoneAllocated {
- public:
-  explicit ScanContext(Scanner* scanner)
-      : next_(scanner->saved_context_),
-        string_delimiter_(scanner->string_delimiter_),
-        string_is_multiline_(scanner->string_is_multiline_),
-        brace_level_(scanner->brace_level_) {}
-
-  void CopyTo(Scanner* scanner) {
-    scanner->string_delimiter_ = string_delimiter_;
-    scanner->string_is_multiline_ = string_is_multiline_;
-    scanner->brace_level_ = brace_level_;
-  }
-
-  ScanContext* next() const { return next_; }
-
- private:
-  ScanContext* next_;
-  const char string_delimiter_;
-  const bool string_is_multiline_;
-  const int brace_level_;
-};
-
-Scanner::KeywordTable Scanner::keywords_[Token::kNumKeywords];
-int Scanner::keywords_char_offset_[Scanner::kNumLowercaseChars];
-
-void Scanner::Reset() {
-  // Non-changing newline properties.
-  newline_token_.kind = Token::kNEWLINE;
-  newline_token_.literal = NULL;
-  // We don't preserve the column information.
-  newline_token_.position.column = 0;
-
-  // Non-changing empty string token properties.
-  empty_string_token_.kind = Token::kSTRING;
-  empty_string_token_.literal = &Symbols::Empty();
-  empty_string_token_.position.column = 0;
-
-  lookahead_pos_ = -1;
-  token_start_ = 0;
-  c0_ = '\0';
-  newline_seen_ = false;
-  prev_token_line_ = 1;
-  saved_context_ = NULL;
-  string_delimiter_ = '\0';
-  string_is_multiline_ = false;
-  brace_level_ = 0;
-  c0_pos_.line = 1;
-  c0_pos_.column = 0;
-  ReadChar();
-}
-
-Scanner::Scanner(const String& src, const String& private_key)
-    : source_(src),
-      source_length_(src.Length()),
-      saved_context_(NULL),
-      private_key_(String::ZoneHandle(private_key.raw())),
-      char_at_func_(src.CharAtFunc()),
-      thread_(Thread::Current()),
-      zone_(thread_->zone()) {
-  Reset();
-}
-
-Scanner::~Scanner() {}
-
-void Scanner::ErrorMsg(const char* msg) {
-  current_token_.kind = Token::kERROR;
-  current_token_.literal = &String::ZoneHandle(Z, Symbols::New(T, msg));
-  current_token_.position = c0_pos_;
-  token_start_ = lookahead_pos_;
-  current_token_.offset = lookahead_pos_;
-}
-
-void Scanner::PushContext() {
-  ScanContext* ctx = new (Z) ScanContext(this);
-  saved_context_ = ctx;
-  string_delimiter_ = '\0';
-  string_is_multiline_ = false;
-  brace_level_ = 1;  // Account for the opening ${ token.
-}
-
-void Scanner::PopContext() {
-  ASSERT(saved_context_ != NULL);
-  ASSERT(brace_level_ == 0);
-  ASSERT(string_delimiter_ == '\0');
-  ScanContext* ctx = saved_context_;
-  ctx->CopyTo(this);
-  saved_context_ = ctx->next();
-  ASSERT(string_delimiter_ != '\0');
-}
-
-void Scanner::BeginStringLiteral(const char delimiter) {
-  string_delimiter_ = delimiter;
-}
-
-void Scanner::EndStringLiteral() {
-  string_delimiter_ = '\0';
-  string_is_multiline_ = false;
-}
-
-bool Scanner::IsLetter(int32_t c) {
-  return (('A' <= c) && (c <= 'Z')) || (('a' <= c) && (c <= 'z'));
-}
-
-bool Scanner::IsDecimalDigit(int32_t c) {
-  return '0' <= c && c <= '9';
-}
-
-bool Scanner::IsNumberStart(int32_t ch) {
-  return IsDecimalDigit(ch) || ch == '.';
-}
-
-bool Scanner::IsHexDigit(int32_t c) {
-  return IsDecimalDigit(c) || (('A' <= c) && (c <= 'F')) ||
-         (('a' <= c) && (c <= 'f'));
-}
-
-bool Scanner::IsIdentStartChar(int32_t c) {
-  return IsLetter(c) || (c == '_') || (c == '$');
-}
-
-bool Scanner::IsIdentChar(int32_t c) {
-  return IsLetter(c) || IsDecimalDigit(c) || (c == '_') || (c == '$');
-}
-
-bool Scanner::IsIdent(const String& str) {
-  if (!str.IsOneByteString()) {
-    return false;
-  }
-  if (str.Length() == 0 || !IsIdentStartChar(CallCharAt()(str, 0))) {
-    return false;
-  }
-  for (int i = 1; i < str.Length(); i++) {
-    if (!IsIdentChar(CallCharAt()(str, i))) {
-      return false;
-    }
-  }
-  return true;
-}
-
-// This method is used when parsing integers in Dart code. We
-// are reusing the Scanner's handling of number literals in that situation.
-bool Scanner::IsValidInteger(const String& str,
-                             bool* is_positive,
-                             const String** value) {
-  Scanner s(str, Symbols::Empty());
-  TokenDescriptor tokens[3];
-  s.Scan();
-  tokens[0] = s.current_token();
-  s.Scan();
-  tokens[1] = s.current_token();
-  s.Scan();
-  tokens[2] = s.current_token();
-
-  if ((tokens[0].kind == Token::kINTEGER) && (tokens[1].kind == Token::kEOS)) {
-    *is_positive = true;
-    *value = tokens[0].literal;
-    return true;
-  }
-  if (((tokens[0].kind == Token::kADD) || (tokens[0].kind == Token::kSUB)) &&
-      (tokens[1].kind == Token::kINTEGER) && (tokens[2].kind == Token::kEOS)) {
-    // Check there is no space between "+/-" and number.
-    if ((tokens[0].offset + 1) != tokens[1].offset) {
-      return false;
-    }
-    *is_positive = tokens[0].kind == Token::kADD;
-    *value = tokens[1].literal;
-    return true;
-  }
-  return false;
-}
-
-void Scanner::ReadChar() {
-  if (lookahead_pos_ < source_length_) {
-    if (c0_ == '\n') {
-      newline_seen_ = true;
-      c0_pos_.line++;
-      c0_pos_.column = 0;
-      if (CallCharAt()(source_, lookahead_pos_) == '\r') {
-        // Replace a sequence of '\r' '\n' with a single '\n'.
-        if (LookaheadChar(1) == '\n') {
-          lookahead_pos_++;
-        }
-      }
-    }
-    lookahead_pos_++;
-    c0_pos_.column++;
-    c0_ = LookaheadChar(0);
-    // Replace '\r' with '\n'.
-    if (c0_ == '\r') {
-      c0_ = '\n';
-    }
-  }
-}
-
-// Look ahead 'how_many' characters. Returns the character, or '\0' if
-// the lookahead position is beyond the end of the string. Does not
-// normalize line end characters into '\n'.
-int32_t Scanner::LookaheadChar(int how_many) {
-  ASSERT(how_many >= 0);
-  int32_t lookahead_char = '\0';
-  if (lookahead_pos_ + how_many < source_length_) {
-    lookahead_char = CallCharAt()(source_, lookahead_pos_ + how_many);
-  }
-  return lookahead_char;
-}
-
-void Scanner::ConsumeWhiteSpace() {
-  while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n') {
-    ReadChar();
-  }
-}
-
-void Scanner::ConsumeLineComment() {
-  ASSERT(c0_ == '/');
-  while (c0_ != '\n' && c0_ != '\0') {
-    ReadChar();
-  }
-  ReadChar();
-  current_token_.kind = Token::kWHITESP;
-}
-
-void Scanner::ConsumeBlockComment() {
-  ASSERT(c0_ == '*');
-  ReadChar();
-  int nesting_level = 1;
-
-  while (true) {
-    const char c = c0_;
-    ReadChar();
-    if (c0_ == '\0') {
-      break;
-    }
-    if (c == '/' && c0_ == '*') {
-      nesting_level++;
-      ReadChar();  // Consume asterisk.
-    } else if (c == '*' && c0_ == '/') {
-      nesting_level--;
-      ReadChar();  // Consume slash.
-      if (nesting_level == 0) {
-        break;
-      }
-    }
-  }
-  current_token_.kind =
-      (nesting_level == 0) ? Token::kWHITESP : Token::kILLEGAL;
-}
-
-void Scanner::ScanIdentChars(bool allow_dollar) {
-  ASSERT(IsIdentStartChar(c0_));
-  ASSERT(allow_dollar || (c0_ != '$'));
-  int ident_length = 0;
-  int ident_pos = lookahead_pos_;
-  int32_t ident_char0 = CallCharAt()(source_, ident_pos);
-  while (IsIdentChar(c0_) && (allow_dollar || (c0_ != '$'))) {
-    ReadChar();
-    ident_length++;
-  }
-
-  // Check whether the characters we read are a known keyword.
-  // Note, can't use strcmp since token_chars is not null-terminated.
-  if (('a' <= ident_char0) && (ident_char0 <= 'z')) {
-    int i = keywords_char_offset_[ident_char0 - 'a'];
-    while ((i < Token::kNumKeywords) &&
-           (keywords_[i].keyword_chars[0] <= ident_char0)) {
-      if (keywords_[i].keyword_len == ident_length) {
-        const char* keyword = keywords_[i].keyword_chars;
-        int char_pos = 1;
-        while ((char_pos < ident_length) &&
-               (keyword[char_pos] ==
-                CallCharAt()(source_, ident_pos + char_pos))) {
-          char_pos++;
-        }
-        if (char_pos == ident_length) {
-          current_token_.literal = keywords_[i].keyword_symbol;
-          current_token_.kind = keywords_[i].kind;
-          return;
-        }
-      }
-      i++;
-    }
-  }
-
-  // We did not read a keyword.
-  current_token_.kind = Token::kIDENT;
-  String& literal = String::ZoneHandle(Z);
-  if (ident_char0 == Library::kPrivateIdentifierStart) {
-    // Private identifiers are mangled on a per library basis.
-    literal = String::SubString(T, source_, ident_pos, ident_length);
-    literal = Symbols::FromConcat(T, literal, private_key_);
-  } else {
-    literal = Symbols::New(T, source_, ident_pos, ident_length);
-  }
-  current_token_.literal = &literal;
-}
-
-// Parse integer or double number literal of format:
-// NUMBER = INTEGER | DOUBLE
-// INTEGER = D+ | (("0x" | "0X") H+)
-// DOUBLE = ((D+ ["." D*]) | ("." D+)) [ EXPONENT ]
-// EXPONENT = ("e" | "E") ["+" | "-"] D+
-void Scanner::ScanNumber(bool dec_point_seen) {
-  ASSERT(IsDecimalDigit(c0_));
-  char first_digit = c0_;
-
-  Recognize(dec_point_seen ? Token::kDOUBLE : Token::kINTEGER);
-  if (!dec_point_seen && first_digit == '0' && (c0_ == 'x' || c0_ == 'X')) {
-    ReadChar();
-    if (!IsHexDigit(c0_)) {
-      ErrorMsg("hexadecimal digit expected");
-      return;
-    }
-    while (IsHexDigit(c0_)) {
-      ReadChar();
-    }
-  } else {
-    while (IsDecimalDigit(c0_)) {
-      ReadChar();
-    }
-    if (c0_ == '.' && !dec_point_seen && IsDecimalDigit(LookaheadChar(1))) {
-      Recognize(Token::kDOUBLE);
-      while (IsDecimalDigit(c0_)) {
-        ReadChar();
-      }
-    }
-    if (((c0_ == 'e') || (c0_ == 'E')) &&
-        (IsDecimalDigit(LookaheadChar(1)) || (LookaheadChar(1) == '-') ||
-         (LookaheadChar(1) == '+'))) {
-      Recognize(Token::kDOUBLE);
-      if ((c0_ == '-') || (c0_ == '+')) {
-        ReadChar();
-      }
-      if (!IsDecimalDigit(c0_)) {
-        ErrorMsg("missing exponent digits");
-        return;
-      }
-      while (IsDecimalDigit(c0_)) {
-        ReadChar();
-      }
-    }
-  }
-  if (current_token_.kind != Token::kILLEGAL) {
-    intptr_t len = lookahead_pos_ - token_start_;
-    const String& str =
-        String::ZoneHandle(Z, Symbols::New(T, source_, token_start_, len));
-    current_token_.literal = &str;
-  }
-}
-
-void Scanner::SkipLine() {
-  while (c0_ != '\n' && c0_ != '\0') {
-    ReadChar();
-  }
-}
-
-void Scanner::ScanScriptTag() {
-  ReadChar();
-  ASSERT(c0_ == '!');
-  Recognize(Token::kSCRIPTTAG);
-  // The script tag extends to the end of the line. Just treat this
-  // similar to a line comment.
-  SkipLine();
-}
-
-void Scanner::ScanLiteralString(bool is_raw) {
-  ASSERT(!IsScanningString());
-  ASSERT(c0_ == '"' || c0_ == '\'');
-
-  // Entering string scanning mode.
-  BeginStringLiteral(c0_);
-  ReadChar();
-
-  if ((c0_ == string_delimiter_) && (LookaheadChar(1) == string_delimiter_)) {
-    string_is_multiline_ = true;
-    ReadChar();  // Skip two additional string delimiters.
-    ReadChar();
-  }
-  ScanLiteralStringChars(is_raw, string_is_multiline_);
-}
-
-bool Scanner::ScanHexDigits(int digits, int32_t* value) {
-  *value = 0;
-  for (int i = 0; i < digits; ++i) {
-    ReadChar();
-    if (!IsHexDigit(c0_)) {
-      ErrorMsg("too few hexadecimal digits");
-      return false;
-    }
-    *value <<= 4;
-    *value |= Utils::HexDigitToInt(c0_);
-  }
-  return true;
-}
-
-bool Scanner::ScanHexDigits(int min_digits, int max_digits, int32_t* value) {
-  *value = 0;
-  ReadChar();
-  for (int i = 0; i < max_digits; ++i) {
-    if (!IsHexDigit(c0_)) {
-      if (i < min_digits) {
-        ErrorMsg("hexadecimal digit expected");
-        return false;
-      }
-      break;
-    }
-    *value <<= 4;
-    *value |= Utils::HexDigitToInt(c0_);
-    ReadChar();
-  }
-  return true;
-}
-
-void Scanner::ScanEscapedCodePoint(int32_t* code_point) {
-  ASSERT(c0_ == 'u' || c0_ == 'x');
-  bool is_valid;
-  if (c0_ == 'x') {
-    is_valid = ScanHexDigits(2, code_point);
-  } else if (c0_ == 'u' && LookaheadChar(1) != '{') {
-    is_valid = ScanHexDigits(4, code_point);
-  } else {
-    ReadChar();  // Skip left curly bracket.
-    is_valid = ScanHexDigits(1, 6, code_point);
-    if (is_valid) {
-      if (c0_ != '}') {
-        ErrorMsg("expected '}' after character code");
-        return;
-      }
-    }
-  }
-  if (is_valid && (Utf::IsOutOfRange(*code_point))) {
-    ErrorMsg("invalid code point");
-  }
-}
-
-void Scanner::ScanLiteralStringChars(bool is_raw, bool remove_whitespace) {
-  GrowableArray<int32_t> string_chars(64);
-
-  ASSERT(IsScanningString());
-  // We are at the first character of a string literal piece. A string literal
-  // can be broken up into multiple pieces by string interpolation.
-  while (true) {
-    if ((c0_ == '\0') || ((c0_ == '\n') && !string_is_multiline_)) {
-      ErrorMsg("unterminated string literal");
-      EndStringLiteral();
-      return;
-    }
-    if (c0_ == '\\' && !is_raw) {
-      // Parse escape sequence.
-      int32_t escape_char = '\0';
-      ReadChar();
-      switch (c0_) {
-        case 'n':
-          escape_char = '\n';
-          break;
-        case 'r':
-          escape_char = '\r';
-          break;
-        case 'f':
-          escape_char = '\f';
-          break;
-        case 't':
-          escape_char = '\t';
-          break;
-        case 'b':
-          escape_char = '\b';
-          break;
-        case 'v':
-          escape_char = '\v';
-          break;
-        case 'u':
-        case 'x': {
-          ScanEscapedCodePoint(&escape_char);
-          break;
-        }
-        default:
-          if ((c0_ == '\0') || ((c0_ == '\n') && !string_is_multiline_)) {
-            ErrorMsg("unterminated string literal");
-            EndStringLiteral();
-            return;
-          }
-          escape_char = c0_;
-          break;
-      }
-      string_chars.Add(escape_char);
-    } else if (c0_ == '$' && !is_raw) {
-      // Scanned a string piece.
-      ASSERT(string_chars.data() != NULL);
-      // Strings are canonicalized: Allocate a symbol.
-      current_token_.literal = &String::ZoneHandle(
-          Z, Symbols::FromUTF32(T, string_chars.data(), string_chars.length()));
-      // Preserve error tokens.
-      if (current_token_.kind != Token::kERROR) {
-        current_token_.kind = Token::kSTRING;
-      }
-      return;
-    } else if (c0_ == string_delimiter_) {
-      // Check if we are at the end of the string literal.
-      if (!string_is_multiline_ || ((LookaheadChar(1) == string_delimiter_) &&
-                                    (LookaheadChar(2) == string_delimiter_))) {
-        if (string_is_multiline_) {
-          ReadChar();  // Skip two string delimiters.
-          ReadChar();
-        }
-        // Preserve error tokens.
-        if (current_token_.kind == Token::kERROR) {
-          ReadChar();
-        } else {
-          Recognize(Token::kSTRING);
-          ASSERT(string_chars.data() != NULL);
-          // Strings are canonicalized: Allocate a symbol.
-          current_token_.literal =
-              &String::ZoneHandle(Z, Symbols::FromUTF32(T, string_chars.data(),
-                                                        string_chars.length()));
-        }
-        EndStringLiteral();
-        return;
-      } else {
-        string_chars.Add(string_delimiter_);
-      }
-    } else {
-      // Test for a two part utf16 sequence, and decode to a code point
-      // if we find one.
-      int32_t ch1 = c0_;
-      if (Utf16::IsLeadSurrogate(ch1)) {
-        const int32_t ch2 = LookaheadChar(1);
-        if (Utf16::IsTrailSurrogate(ch2)) {
-          ch1 = Utf16::Decode(ch1, ch2);
-          ReadChar();
-        }
-      }
-      string_chars.Add(ch1);
-    }
-    // The first line of a multi-line string is discarded if it only
-    // contains whitespace.
-    if (remove_whitespace && (string_chars.Last() == '\n')) {
-      bool whitespace_only = true;
-      // Last character is the newline, don't inspect it.
-      const intptr_t len = string_chars.length() - 1;
-      for (int i = 0; i < len; i++) {
-        int32_t ch = string_chars[i];
-        if ((ch != ' ') && (ch != '\t')) {
-          // Non-whitespace character, keep the first line.
-          whitespace_only = false;
-          break;
-        }
-      }
-      if (whitespace_only) {
-        string_chars.Clear();  // Discard characters on first line.
-      }
-      remove_whitespace = false;
-    }
-    ReadChar();
-  }
-}
-
-void Scanner::Scan() {
-  newline_seen_ = false;
-
-  do {
-    if (!IsScanningString()) {
-      ConsumeWhiteSpace();
-    }
-    token_start_ = lookahead_pos_;
-    current_token_.offset = lookahead_pos_;
-    current_token_.position = c0_pos_;
-    current_token_.literal = NULL;
-    current_token_.kind = Token::kILLEGAL;
-    if (IsScanningString()) {
-      if (c0_ == '$') {
-        ReadChar();  // Skip the '$' character.
-        if (IsIdentStartChar(c0_) && (c0_ != '$')) {
-          ScanIdentNoDollar();
-          current_token_.kind = Token::kINTERPOL_VAR;
-        } else if (c0_ == '{') {
-          Recognize(Token::kINTERPOL_START);
-          PushContext();
-        } else {
-          ErrorMsg("illegal character after $ in string interpolation");
-          EndStringLiteral();
-          break;
-        }
-      } else {
-        ScanLiteralStringChars(false, false);
-      }
-      break;
-    }
-    switch (c0_) {
-      case '\0':
-        current_token_.kind = Token::kEOS;
-        break;
-
-      case '+':  // +  ++  +=
-        Recognize(Token::kADD);
-        if (c0_ == '+') {
-          Recognize(Token::kINCR);
-        } else if (c0_ == '=') {
-          Recognize(Token::kASSIGN_ADD);
-        }
-        break;
-
-      case '-':  // -  --  -=
-        Recognize(Token::kSUB);
-        if (c0_ == '-') {
-          Recognize(Token::kDECR);
-        } else if (c0_ == '=') {
-          Recognize(Token::kASSIGN_SUB);
-        }
-        break;
-
-      case '*':  // *  *=
-        Recognize(Token::kMUL);
-        if (c0_ == '=') {
-          Recognize(Token::kASSIGN_MUL);
-        }
-        break;
-
-      case '%':  // %  %=
-        Recognize(Token::kMOD);
-        if (c0_ == '=') {
-          Recognize(Token::kASSIGN_MOD);
-        }
-        break;
-
-      case '/':  //  /  /=  //  /*
-        Recognize(Token::kDIV);
-        if (c0_ == '/') {
-          ConsumeLineComment();
-        } else if (c0_ == '*') {
-          ConsumeBlockComment();
-        } else if (c0_ == '=') {
-          Recognize(Token::kASSIGN_DIV);
-        }
-        break;
-
-      case '&':  // &  &=  &&
-        Recognize(Token::kBIT_AND);
-        if (c0_ == '=') {
-          Recognize(Token::kASSIGN_AND);
-        } else if (c0_ == '&') {
-          Recognize(Token::kAND);
-        }
-        break;
-
-      case '|':  // |  |=  ||
-        Recognize(Token::kBIT_OR);
-        if (c0_ == '=') {
-          Recognize(Token::kASSIGN_OR);
-        } else if (c0_ == '|') {
-          Recognize(Token::kOR);
-        }
-        break;
-
-      case '^':  // ^  ^=
-        Recognize(Token::kBIT_XOR);
-        if (c0_ == '=') {
-          Recognize(Token::kASSIGN_XOR);
-        }
-        break;
-
-      case '[':  // [  []  []=
-        Recognize(Token::kLBRACK);
-        if (c0_ == ']') {
-          Recognize(Token::kINDEX);
-          if (c0_ == '=') {
-            Recognize(Token::kASSIGN_INDEX);
-          }
-        }
-        break;
-
-      case ']':  //  ]
-        Recognize(Token::kRBRACK);
-        break;
-
-      case '<':  // <  <=  <<  <<=
-        Recognize(Token::kLT);
-        if (c0_ == '=') {
-          Recognize(Token::kLTE);
-        } else if (c0_ == '<') {
-          Recognize(Token::kSHL);
-          if (c0_ == '=') {
-            Recognize(Token::kASSIGN_SHL);
-          }
-        }
-        break;
-
-      case '>':  // >  >=  >>  >>=
-        Recognize(Token::kGT);
-        if (c0_ == '=') {
-          Recognize(Token::kGTE);
-        } else if (c0_ == '>') {
-          Recognize(Token::kSHR);
-          if (c0_ == '=') {
-            Recognize(Token::kASSIGN_SHR);
-          }
-        }
-        break;
-
-      case '!':  // !  !=
-        Recognize(Token::kNOT);
-        if (c0_ == '=') {
-          Recognize(Token::kNE);
-        }
-        break;
-
-      case '~':
-        Recognize(Token::kBIT_NOT);
-        if (c0_ == '/') {
-          Recognize(Token::kTRUNCDIV);
-          if (c0_ == '=') {
-            Recognize(Token::kASSIGN_TRUNCDIV);
-          }
-        }
-        break;
-
-      case '=':  // =  ==  =>
-        Recognize(Token::kASSIGN);
-        if (c0_ == '=') {
-          Recognize(Token::kEQ);
-        } else if (c0_ == '>') {
-          Recognize(Token::kARROW);
-        }
-        break;
-
-      case '.':  // .  ..  Number
-        Recognize(Token::kPERIOD);
-        if (c0_ == '.') {
-          Recognize(Token::kCASCADE);
-        } else if (IsDecimalDigit(c0_)) {
-          ScanNumber(true);
-        }
-        break;
-
-      case '?':  // ?  ?.  ??  ??=
-        Recognize(Token::kCONDITIONAL);
-        if (c0_ == '.') {
-          Recognize(Token::kQM_PERIOD);
-        } else if (c0_ == '?') {
-          Recognize(Token::kIFNULL);
-          if (c0_ == '=') {
-            Recognize(Token::kASSIGN_COND);
-          }
-        }
-        break;
-
-      case ':':
-        Recognize(Token::kCOLON);
-        break;
-
-      case ';':
-        Recognize(Token::kSEMICOLON);
-        break;
-
-      case '{':
-        Recognize(Token::kLBRACE);
-        if (IsNestedContext()) {
-          brace_level_++;
-        }
-        break;
-
-      case '}':
-        Recognize(Token::kRBRACE);
-        if (IsNestedContext()) {
-          ASSERT(brace_level_ > 0);
-          brace_level_--;
-          if (brace_level_ == 0) {
-            current_token_.kind = Token::kINTERPOL_END;
-            PopContext();
-          }
-        }
-        break;
-
-      case '(':
-        Recognize(Token::kLPAREN);
-        break;
-
-      case ')':
-        Recognize(Token::kRPAREN);
-        break;
-
-      case ',':
-        Recognize(Token::kCOMMA);
-        break;
-
-      case '@':
-        Recognize(Token::kAT);
-        break;
-
-      case 'r':
-        if ((LookaheadChar(1) == '"') || (LookaheadChar(1) == '\'')) {
-          ReadChar();
-          ScanLiteralString(true);
-        } else {
-          ScanIdent();
-        }
-        break;
-
-      case '"':
-      case '\'':
-        ScanLiteralString(false);
-        break;
-
-      case '#':
-        if (LookaheadChar(1) == '!') {
-          ScanScriptTag();
-        } else {
-          Recognize(Token::kHASH);
-        }
-        break;
-
-      default:
-        if (IsIdentStartChar(c0_)) {
-          ScanIdent();
-        } else if (IsDecimalDigit(c0_)) {
-          ScanNumber(false);
-        } else {
-          char msg[128];
-          char utf8_char[5];
-          int len = Utf8::Encode(c0_, utf8_char);
-          utf8_char[len] = '\0';
-          Utils::SNPrint(msg, sizeof(msg),
-                         "unexpected character: '%s' (U+%04X)\n", utf8_char,
-                         c0_);
-          ErrorMsg(msg);
-          ReadChar();
-        }
-    }
-  } while (current_token_.kind == Token::kWHITESP);
-}
-
-void Scanner::ScanAll(TokenCollector* collector) {
-  Reset();
-  do {
-    Scan();
-    bool inserted_new_lines = false;
-    for (intptr_t diff = current_token_.position.line - prev_token_line_;
-         diff > 0; diff--) {
-      newline_token_.position.line = current_token_.position.line - diff;
-      collector->AddToken(newline_token_);
-      inserted_new_lines = true;
-    }
-    if (inserted_new_lines &&
-        ((current_token_.kind == Token::kINTERPOL_VAR) ||
-         (current_token_.kind == Token::kINTERPOL_START))) {
-      // NOTE: If this changes, be sure to update
-      // Script::GenerateLineNumberArray to stay in sync.
-      empty_string_token_.position.line = current_token_.position.line;
-      collector->AddToken(empty_string_token_);
-    }
-    collector->AddToken(current_token_);
-    prev_token_line_ = current_token_.position.line;
-  } while (current_token_.kind != Token::kEOS);
-}
-
-void Scanner::ScanTo(intptr_t token_index) {
-  ASSERT(token_index >= 0);
-  intptr_t index = 0;
-  Reset();
-  do {
-    Scan();
-    bool inserted_new_lines = false;
-    for (intptr_t diff = current_token_.position.line - prev_token_line_;
-         diff > 0; diff--) {
-      // Advance the index to account for tokens added in ScanAll.
-      index++;
-      inserted_new_lines = true;
-    }
-    if (inserted_new_lines &&
-        ((current_token_.kind == Token::kINTERPOL_VAR) ||
-         (current_token_.kind == Token::kINTERPOL_START))) {
-      // Advance the index to account for tokens added in ScanAll.
-      index++;
-    }
-    index++;
-    prev_token_line_ = current_token_.position.line;
-  } while ((token_index >= index) && (current_token_.kind != Token::kEOS));
-}
-
-void Scanner::Init() {
-  ASSERT(Isolate::Current() == Dart::vm_isolate());
-  for (int i = 0; i < kNumLowercaseChars; i++) {
-    keywords_char_offset_[i] = Token::kNumKeywords;
-  }
-  for (int i = 0; i < Token::kNumKeywords; i++) {
-    Token::Kind token = static_cast<Token::Kind>(Token::kFirstKeyword + i);
-    keywords_[i].kind = token;
-    keywords_[i].keyword_chars = Token::Str(token);
-    keywords_[i].keyword_len = strlen(Token::Str(token));
-    keywords_[i].keyword_symbol = &Symbols::Token(token);
-
-    int ch = keywords_[i].keyword_chars[0] - 'a';
-    if (keywords_char_offset_[ch] == Token::kNumKeywords) {
-      keywords_char_offset_[ch] = i;
-    }
-  }
-}
-
-}  // namespace dart
diff --git a/runtime/vm/scanner.h b/runtime/vm/scanner.h
deleted file mode 100644
index 69ce33e..0000000
--- a/runtime/vm/scanner.h
+++ /dev/null
@@ -1,218 +0,0 @@
-// Copyright (c) 2011, 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.
-//
-// Scanner class for the Dart language. The scanner reads source text
-// and produces a stream of tokens which is used by the parser.
-//
-
-#ifndef RUNTIME_VM_SCANNER_H_
-#define RUNTIME_VM_SCANNER_H_
-
-#include "vm/growable_array.h"
-#include "vm/token.h"
-
-namespace dart {
-
-// Forward declarations.
-class Array;
-class Library;
-class RawString;
-class ScanContext;
-class String;
-
-// A call to Scan() scans the source one token at at time.
-// The scanned token is returned by current_token().
-// GetStream() scans the entire source text and returns a stream of tokens.
-class Scanner : ValueObject {
- public:
-  typedef uint16_t (*CharAtFunc)(const String& str, intptr_t index);
-
-  // SourcePosition describes a text location in user friendly
-  // terms of line number and column.
-  struct SourcePosition {
-    int line;
-    int column;
-  };
-
-  // TokenDesc defines the kind of a token and its location in
-  // the source text.
-  struct TokenDescriptor {
-    Token::Kind kind;
-    int offset;               // Offset in source string.
-    SourcePosition position;  // Text position in source.
-    const String* literal;    // Identifier, number or string literal.
-  };
-
-  class TokenCollector : public ValueObject {
-   public:
-    TokenCollector() {}
-    virtual ~TokenCollector() {}
-    virtual void AddToken(const TokenDescriptor& token) {}
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(TokenCollector);
-  };
-
-  // Initializes scanner to scan string source.
-  Scanner(const String& source, const String& private_key);
-  ~Scanner();
-
-  // Scans one token at a time.
-  void Scan();
-
-  // Scans the entire source and collects tokens in the provided collector.
-  void ScanAll(TokenCollector* collector);
-
-  // Scans to specified token position.
-  // Use CurrentPosition() to extract line and column number.
-  void ScanTo(intptr_t token_index);
-
-  // Info about most recently recognized token.
-  const TokenDescriptor& current_token() const { return current_token_; }
-
-  // Was there a line break before the current token?
-  bool NewlineBeforeToken() const { return newline_seen_; }
-
-  // Source code line number and column of current token.
-  const SourcePosition& CurrentPosition() const {
-    return current_token_.position;
-  }
-
-  static void Init();
-
-  // Return true if str is an identifier.
-  bool IsIdent(const String& str);
-
-  // Does the token stream contain a valid integer literal.
-  static bool IsValidInteger(const String& str,
-                             bool* is_positive,
-                             const String** value);
-
-  static bool IsIdentStartChar(int32_t c);
-  static bool IsIdentChar(int32_t c);
-
- private:
-  friend class ScanContext;
-
-  static const int kNumLowercaseChars = 26;
-
-  struct KeywordTable {
-    Token::Kind kind;
-    const char* keyword_chars;
-    int keyword_len;
-    const String* keyword_symbol;
-  };
-
-  // Rewind scanner position to token 0.
-  void Reset();
-
-  // Reads next lookahead character.
-  void ReadChar();
-
-  // Read and discard characters up to end of line.
-  void SkipLine();
-
-  // Recognizes token 'kind' and reads next character in input.
-  void Recognize(Token::Kind kind) {
-    ReadChar();
-    current_token_.kind = kind;
-  }
-
-  int32_t LookaheadChar(int how_many);
-
-  void ErrorMsg(const char* msg);
-
-  // These functions return true if the given character is a letter,
-  // a decimal digit, a hexadecimal digit, etc.
-  static bool IsLetter(int32_t c);
-  static bool IsDecimalDigit(int32_t c);
-  static bool IsNumberStart(int32_t);
-  static bool IsHexDigit(int32_t c);
-
-  // Skips up to next non-whitespace character.
-  void ConsumeWhiteSpace();
-
-  // Skips characters up to end of line.
-  void ConsumeLineComment();
-
-  // Skips characters up to matching '*/'.
-  void ConsumeBlockComment();
-
-  // Is this scanner currently scanning a string literal.
-  bool IsScanningString() const { return string_delimiter_ != '\0'; }
-  void BeginStringLiteral(const char delimiter);
-  void EndStringLiteral();
-
-  // Is this scanner currently scanning a string interpolation expression.
-  bool IsNestedContext() const { return saved_context_ != NULL; }
-  void PushContext();
-  void PopContext();
-
-  // Starts reading a string literal.
-  void ScanLiteralString(bool is_raw);
-
-  // Read the characters of a string literal. Remove whitespace up to
-  // and including the first newline character if remove_whitespace
-  // is true.
-  void ScanLiteralStringChars(bool is_raw, bool remove_whitespace);
-
-  // Reads a fixed number of hexadecimal digits.
-  bool ScanHexDigits(int digits, int32_t* value);
-
-  // Reads a variable number of hexadecimal digits.
-  bool ScanHexDigits(int min_digits, int max_digits, int32_t* value);
-
-  // Reads an escaped code point from within a string literal.
-  void ScanEscapedCodePoint(int32_t* escaped_char);
-
-  // Reads identifier.
-  void ScanIdentChars(bool allow_dollar);
-  void ScanIdent() { ScanIdentChars(true); }
-  void ScanIdentNoDollar() { ScanIdentChars(false); }
-
-  // Reads a number literal.
-  void ScanNumber(bool dec_point_seen);
-
-  void ScanScriptTag();
-
-  CharAtFunc CallCharAt() const { return char_at_func_; }
-
-  Thread* thread() const { return thread_; }
-  Zone* zone() const { return zone_; }
-
-  TokenDescriptor current_token_;       // Current token.
-  TokenDescriptor newline_token_;       // Newline token.
-  TokenDescriptor empty_string_token_;  // Token for "".
-  const String& source_;                // The source text being tokenized.
-  intptr_t source_length_;              // The length of the source text.
-  intptr_t lookahead_pos_;              // Position of lookahead character
-                                        // within source_.
-  intptr_t token_start_;                // Begin of current token in src_.
-  int32_t c0_;                          // Lookahead character.
-  bool newline_seen_;                   // Newline before current token.
-  intptr_t prev_token_line_;            // Line number of the previous token.
-
-  // The following fields keep track whether we are scanning a string literal
-  // and its interpolated expressions.
-  ScanContext* saved_context_;
-  int32_t string_delimiter_;
-  bool string_is_multiline_;
-  int brace_level_;
-
-  const String& private_key_;
-
-  SourcePosition c0_pos_;  // Source position of lookahead character c0_.
-
-  const CharAtFunc char_at_func_;
-
-  Thread* thread_;
-  Zone* zone_;
-
-  static KeywordTable keywords_[Token::kNumKeywords];
-  static int keywords_char_offset_[kNumLowercaseChars];
-};
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_SCANNER_H_
diff --git a/runtime/vm/scanner_test.cc b/runtime/vm/scanner_test.cc
deleted file mode 100644
index f7546cb..0000000
--- a/runtime/vm/scanner_test.cc
+++ /dev/null
@@ -1,398 +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/scanner.h"
-#include "platform/assert.h"
-#include "vm/os.h"
-#include "vm/token.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-typedef ZoneGrowableArray<Scanner::TokenDescriptor> GrowableTokenStream;
-
-static void LogTokenDesc(Scanner::TokenDescriptor token) {
-  OS::PrintErr("pos %2d:%d-%d token %s  ", token.position.line,
-               token.position.column, token.position.column,
-               Token::Name(token.kind));
-  if (token.literal != NULL) {
-    OS::PrintErr("%s", token.literal->ToCString());
-  }
-  OS::PrintErr("\n");
-}
-
-static void LogTokenStream(const GrowableTokenStream& token_stream) {
-  int token_index = 0;
-  EXPECT_GT(token_stream.length(), 0);
-  while (token_index < token_stream.length()) {
-    LogTokenDesc(token_stream[token_index]);
-    ASSERT(token_stream[token_index].kind != Token::kILLEGAL);
-    token_index++;
-  }
-  printf("%d tokens in stream.\n", token_index);
-  EXPECT_EQ(token_stream.Last().kind, Token::kEOS);
-}
-
-static void CheckKind(const GrowableTokenStream& token_stream,
-                      int index,
-                      Token::Kind kind) {
-  if (token_stream[index].kind != kind) {
-    OS::PrintErr("Token %d: expected kind %s but got %s\n", index,
-                 Token::Name(kind), Token::Name(token_stream[index].kind));
-  }
-  EXPECT_EQ(kind, token_stream[index].kind);
-}
-
-static void CheckLiteral(const GrowableTokenStream& token_stream,
-                         int index,
-                         const char* literal) {
-  if (token_stream[index].literal == NULL) {
-    OS::PrintErr("Token %d: expected literal \"%s\" but got nothing\n", index,
-                 literal);
-  } else if (strcmp(literal, token_stream[index].literal->ToCString())) {
-    OS::PrintErr("Token %d: expected literal \"%s\" but got \"%s\"\n", index,
-                 literal, token_stream[index].literal->ToCString());
-  }
-}
-
-static void CheckIdent(const GrowableTokenStream& token_stream,
-                       int index,
-                       const char* literal) {
-  CheckKind(token_stream, index, Token::kIDENT);
-  CheckLiteral(token_stream, index, literal);
-}
-
-static void CheckInteger(const GrowableTokenStream& token_stream,
-                         int index,
-                         const char* literal) {
-  CheckKind(token_stream, index, Token::kINTEGER);
-  CheckLiteral(token_stream, index, literal);
-}
-
-static void CheckLineNumber(const GrowableTokenStream& token_stream,
-                            int index,
-                            int line_number) {
-  if (token_stream[index].position.line != line_number) {
-    OS::PrintErr("Token %d: expected line number %d but got %d\n", index,
-                 line_number, token_stream[index].position.line);
-  }
-}
-
-static void CheckNumTokens(const GrowableTokenStream& token_stream, int index) {
-  if (token_stream.length() != index) {
-    OS::PrintErr("Expected %d tokens but got only %" Pd ".\n", index,
-                 token_stream.length());
-  }
-}
-
-class Collector : public Scanner::TokenCollector {
- public:
-  explicit Collector(GrowableTokenStream* ts) : ts_(ts) {}
-  virtual ~Collector() {}
-
-  virtual void AddToken(const Scanner::TokenDescriptor& token) {
-    ts_->Add(token);
-  }
-
- private:
-  GrowableTokenStream* ts_;
-};
-
-static const GrowableTokenStream& Scan(const char* source) {
-  OS::PrintErr("\nScanning: <%s>\n", source);
-
-  Scanner scanner(String::Handle(String::New(source)),
-                  String::Handle(String::New("")));
-  GrowableTokenStream* tokens = new GrowableTokenStream(128);
-  Collector collector(tokens);
-
-  scanner.ScanAll(&collector);
-  LogTokenStream(*tokens);
-  return *tokens;
-}
-
-static void BoringTest() {
-  const GrowableTokenStream& tokens = Scan("x = iffy++;");
-
-  CheckNumTokens(tokens, 6);
-  CheckIdent(tokens, 0, "x");
-  CheckKind(tokens, 1, Token::kASSIGN);
-  CheckIdent(tokens, 2, "iffy");
-  CheckKind(tokens, 3, Token::kINCR);
-  CheckKind(tokens, 4, Token::kSEMICOLON);
-}
-
-static void CommentTest() {
-  const GrowableTokenStream& tokens = Scan(
-      "Foo( /*block \n"
-      "comment*/ 0xff) // line comment;");
-
-  CheckNumTokens(tokens, 6);
-  CheckIdent(tokens, 0, "Foo");
-  CheckLineNumber(tokens, 0, 1);
-  CheckKind(tokens, 1, Token::kLPAREN);
-  CheckKind(tokens, 2, Token::kNEWLINE);
-  CheckInteger(tokens, 3, "0xff");
-  CheckKind(tokens, 4, Token::kRPAREN);
-  CheckLineNumber(tokens, 4, 2);
-}
-
-static void GreedIsGood() {
-  // means i++ + j
-  const GrowableTokenStream& tokens = Scan("x=i+++j");
-
-  CheckNumTokens(tokens, 7);
-  CheckIdent(tokens, 0, "x");
-  CheckKind(tokens, 1, Token::kASSIGN);
-  CheckIdent(tokens, 2, "i");
-  CheckKind(tokens, 3, Token::kINCR);
-  CheckKind(tokens, 4, Token::kADD);
-  CheckIdent(tokens, 5, "j");
-}
-
-static void StringEscapes() {
-  // sss = "\" \\ \n\r\t \'"
-  const GrowableTokenStream& tokens =
-      Scan("sss = \"\\\" \\\\ \\n\\r\\t \\\'\"");
-
-  EXPECT_EQ(4, tokens.length());
-  CheckIdent(tokens, 0, "sss");
-  CheckKind(tokens, 1, Token::kASSIGN);
-  CheckKind(tokens, 2, Token::kSTRING);
-  CheckKind(tokens, 3, Token::kEOS);
-  CheckLineNumber(tokens, 2, 1);
-  const char* litchars = (tokens)[2].literal->ToCString();
-  EXPECT_EQ(9, (tokens)[2].literal->Length());
-
-  EXPECT_EQ('"', litchars[0]);
-  EXPECT_EQ(' ', litchars[1]);
-  EXPECT_EQ('\\', litchars[2]);
-  EXPECT_EQ('\n', litchars[4]);
-  EXPECT_EQ('\r', litchars[5]);
-  EXPECT_EQ('\t', litchars[6]);
-  EXPECT_EQ('\'', litchars[8]);
-}
-
-static void InvalidStringEscapes() {
-  const GrowableTokenStream& out_of_range_low = Scan("\"\\u{110000}\"");
-  EXPECT_EQ(2, out_of_range_low.length());
-  CheckKind(out_of_range_low, 0, Token::kERROR);
-  EXPECT(out_of_range_low[0].literal->Equals("invalid code point"));
-  CheckKind(out_of_range_low, 1, Token::kEOS);
-
-  const GrowableTokenStream& out_of_range_high = Scan("\"\\u{FFFFFF}\"");
-  EXPECT_EQ(2, out_of_range_high.length());
-  CheckKind(out_of_range_high, 0, Token::kERROR);
-  EXPECT(out_of_range_high[0].literal->Equals("invalid code point"));
-  CheckKind(out_of_range_high, 1, Token::kEOS);
-}
-
-static void RawString() {
-  // rs = @"\' \\"
-  const GrowableTokenStream& tokens = Scan("rs = r\"\\\' \\\\\"");
-
-  EXPECT_EQ(4, tokens.length());
-  CheckIdent(tokens, 0, "rs");
-  CheckKind(tokens, 1, Token::kASSIGN);
-  CheckKind(tokens, 2, Token::kSTRING);
-  CheckKind(tokens, 3, Token::kEOS);
-  CheckLineNumber(tokens, 2, 1);
-  const char* litchars = (tokens)[2].literal->ToCString();
-  EXPECT_EQ(5, (tokens)[2].literal->Length());
-
-  EXPECT_EQ('\\', litchars[0]);
-  EXPECT_EQ('\'', litchars[1]);
-  EXPECT_EQ(' ', litchars[2]);
-  EXPECT_EQ('\\', litchars[3]);
-  EXPECT_EQ('\\', litchars[4]);
-}
-
-static void MultilineString() {
-  // |mls = '''
-  // |1' x
-  // |2''';
-  const GrowableTokenStream& tokens = Scan("mls = '''\n1' x\n2''';");
-
-  EXPECT_EQ(7, tokens.length());
-  CheckIdent(tokens, 0, "mls");
-  CheckKind(tokens, 1, Token::kASSIGN);
-  CheckKind(tokens, 2, Token::kSTRING);
-  CheckKind(tokens, 3, Token::kNEWLINE);
-  CheckKind(tokens, 4, Token::kNEWLINE);
-  CheckKind(tokens, 5, Token::kSEMICOLON);
-  CheckKind(tokens, 6, Token::kEOS);
-  CheckLineNumber(tokens, 0, 1);
-  CheckLineNumber(tokens, 5, 3);  // Semicolon is on line 3.
-  const char* litchars = (tokens)[2].literal->ToCString();
-  EXPECT_EQ(6, (tokens)[2].literal->Length());
-
-  EXPECT_EQ('1', litchars[0]);  // First newline is dropped.
-  EXPECT_EQ('\'', litchars[1]);
-  EXPECT_EQ(' ', litchars[2]);
-  EXPECT_EQ('x', litchars[3]);
-  EXPECT_EQ('\n', litchars[4]);
-  EXPECT_EQ('2', litchars[5]);
-}
-
-static void EmptyString() {
-  // es = "";
-  const GrowableTokenStream& tokens = Scan("es = \"\";");
-
-  EXPECT_EQ(5, tokens.length());
-  CheckIdent(tokens, 0, "es");
-  CheckKind(tokens, 1, Token::kASSIGN);
-  CheckKind(tokens, 2, Token::kSTRING);
-  CheckKind(tokens, 3, Token::kSEMICOLON);
-  CheckKind(tokens, 4, Token::kEOS);
-  EXPECT_EQ(0, (tokens)[2].literal->Length());
-}
-
-static void EmptyMultilineString() {
-  // es = """""";
-  const GrowableTokenStream& tokens = Scan("es = \"\"\"\"\"\";");
-
-  EXPECT_EQ(5, tokens.length());
-  CheckIdent(tokens, 0, "es");
-  CheckKind(tokens, 1, Token::kASSIGN);
-  CheckKind(tokens, 2, Token::kSTRING);
-  CheckKind(tokens, 3, Token::kSEMICOLON);
-  CheckKind(tokens, 4, Token::kEOS);
-  EXPECT_EQ(0, (tokens)[2].literal->Length());
-}
-
-static void NumberLiteral() {
-  const GrowableTokenStream& tokens = Scan("5 0x5d 0.3 0.33 1E+12 .42 +5");
-
-  CheckKind(tokens, 0, Token::kINTEGER);
-  CheckKind(tokens, 1, Token::kINTEGER);
-  CheckKind(tokens, 2, Token::kDOUBLE);
-  CheckKind(tokens, 3, Token::kDOUBLE);
-  CheckKind(tokens, 4, Token::kDOUBLE);
-  CheckKind(tokens, 5, Token::kDOUBLE);
-  CheckKind(tokens, 6, Token::kADD);
-  CheckKind(tokens, 7, Token::kINTEGER);
-  CheckKind(tokens, 8, Token::kEOS);
-}
-
-static void ScanLargeText() {
-  const char* dart_source =
-      "// This source is not meant to be valid Dart code. The text is used to"
-      "// test the Dart scanner."
-      ""
-      "// Cartesian point implementation."
-      "class Point {"
-      ""
-      "  // Constructor"
-      "  Point(Number x, Number y) : x(x), y(y) { }"
-      ""
-      "  // Addition for points."
-      "  Point operator +(Point other) {"
-      "    return new Point(x + other.x, y + other.y);"
-      "  }"
-      ""
-      "  // Fields are const and they cannot be changed."
-      "  const Number x;"
-      "  const Number y;"
-      "}"
-      ""
-      ""
-      "// Polar point class that implements the Point interface."
-      "class PolarPoint implements Point {"
-      ""
-      "  PolarPoint(Number theta, Number radius)"
-      "      : theta(theta), radius(radius) { }"
-      ""
-      "  Number get x { return radius * Math.cos(theta); }"
-      "  Number get y { return radius * Math.sin(theta); }"
-      ""
-      "  const Number theta;"
-      "  const Number radius;"
-      "}"
-      ""
-      "interface Map<K ,V> default HashMap<K, V> {"
-      "  V operator [](K key);"
-      "  void operator []=(K key, V value);"
-      "  void forEach(function f(K key, V value));"
-      "}"
-      ""
-      "class Foo {"
-      "  static const Array kMyArray = [1,2,3,4,5,6];"
-      "  static const Point kMyPoint = Point(1,2);"
-      "}"
-      ""
-      "class DequeEntry<T> implements QueueEntry<T>{"
-      "  DequeEntry<T> next;"
-      "  DequeEntry<T> previous;"
-      "  T value;"
-      "}"
-      ""
-      "void forEach(void function f(T element)) {"
-      "  for (int i = 0; i < this.length; i++) {"
-      "    f(this[i]);"
-      "  }"
-      "}"
-      ""
-      ""
-      "j!==!iffy  // means j !== !iffy";
-  Scan(dart_source);
-}
-
-void InvalidText() {
-  const GrowableTokenStream& tokens = Scan("\\");
-
-  EXPECT_EQ(2, tokens.length());
-  CheckKind(tokens, 0, Token::kERROR);
-  CheckKind(tokens, 1, Token::kEOS);
-}
-
-void NewlinesTest() {
-  const char* source =
-      "var es = /* a\n"
-      "            b\n"
-      "          */ \"\"\"\n"
-      "c\n"
-      "d\n"
-      "\"\"\";";
-
-  const GrowableTokenStream& tokens = Scan(source);
-
-  EXPECT_EQ(11, tokens.length());
-  CheckKind(tokens, 0, Token::kVAR);
-  CheckIdent(tokens, 1, "es");
-  CheckKind(tokens, 2, Token::kASSIGN);
-  CheckKind(tokens, 3, Token::kNEWLINE);
-  CheckKind(tokens, 4, Token::kNEWLINE);
-  CheckKind(tokens, 5, Token::kSTRING);
-  CheckKind(tokens, 6, Token::kNEWLINE);
-  CheckKind(tokens, 7, Token::kNEWLINE);
-  CheckKind(tokens, 8, Token::kNEWLINE);
-  CheckKind(tokens, 9, Token::kSEMICOLON);
-  CheckKind(tokens, 10, Token::kEOS);
-
-  EXPECT_EQ(4, (tokens)[5].literal->Length());
-  const char* litchars = (tokens)[5].literal->ToCString();
-  EXPECT_EQ('c', litchars[0]);  // First newline is dropped.
-  EXPECT_EQ('\n', litchars[1]);
-  EXPECT_EQ('d', litchars[2]);
-  EXPECT_EQ('\n', litchars[3]);
-}
-
-ISOLATE_UNIT_TEST_CASE(Scanner_Test) {
-  ScanLargeText();
-
-  BoringTest();
-  CommentTest();
-  GreedIsGood();
-  StringEscapes();
-  InvalidStringEscapes();
-  RawString();
-  MultilineString();
-  EmptyString();
-  EmptyMultilineString();
-  NumberLiteral();
-  InvalidText();
-  NewlinesTest();
-}
-
-}  // namespace dart
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index 0af2a71..91b3caa 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -29,11 +29,11 @@
       function_level_(function_level),
       loop_level_(loop_level),
       context_level_(LocalScope::kUnitializedContextLevel),
-      num_context_variables_(0),
       begin_token_pos_(TokenPosition::kNoSourcePos),
       end_token_pos_(TokenPosition::kNoSourcePos),
       variables_(),
       labels_(),
+      context_variables_(),
       referenced_() {
   // Hook this node into the children of the parent, unless the parent has a
   // different function_level, since the local scope of a nested function can
@@ -149,7 +149,7 @@
   // code generation time how far to walk up the context chain in order to
   // access the variable from the current context level.
   if ((*context_owner) == NULL) {
-    ASSERT(num_context_variables_ == 0);
+    ASSERT(num_context_variables() == 0);
     // This scope becomes the current context owner.
     set_context_level(1);
     *context_owner = this;
@@ -157,7 +157,7 @@
     // The captured variable is in a child scope of the context owner and we do
     // not share contexts.
     // This scope will allocate and chain a new context.
-    ASSERT(num_context_variables_ == 0);
+    ASSERT(num_context_variables() == 0);
     // This scope becomes the current context owner.
     set_context_level((*context_owner)->context_level() + 1);
     *context_owner = this;
@@ -165,7 +165,7 @@
     ASSERT(FLAG_share_enclosing_context);
     // The captured variable is at a deeper loop level than the current context.
     // This scope will allocate and chain a new context.
-    ASSERT(num_context_variables_ == 0);
+    ASSERT(num_context_variables() == 0);
     // This scope becomes the current context owner.
     set_context_level((*context_owner)->context_level() + 1);
     *context_owner = this;
@@ -178,8 +178,13 @@
       ASSERT(context_level() == (*context_owner)->context_level());
     }
   }
-  variable->set_index(
-      VariableIndex((*context_owner)->num_context_variables_++));
+
+  (*context_owner)->AddContextVariable(variable);
+}
+
+void LocalScope::AddContextVariable(LocalVariable* variable) {
+  variable->set_index(VariableIndex(context_variables_.length()));
+  context_variables_.Add(variable);
 }
 
 VariableIndex LocalScope::AllocateVariables(VariableIndex first_parameter_index,
diff --git a/runtime/vm/scopes.h b/runtime/vm/scopes.h
index 952ecc7..38abf8f 100644
--- a/runtime/vm/scopes.h
+++ b/runtime/vm/scopes.h
@@ -88,6 +88,7 @@
         is_invisible_(false),
         is_captured_parameter_(false),
         is_forced_stack_(false),
+        is_explicit_covariant_parameter_(false),
         type_check_mode_(kDoTypeCheck),
         index_() {
     ASSERT(type.IsZoneHandle() || type.IsReadOnlyHandle());
@@ -121,6 +122,13 @@
   bool is_forced_stack() const { return is_forced_stack_; }
   void set_is_forced_stack() { is_forced_stack_ = true; }
 
+  bool is_explicit_covariant_parameter() const {
+    return is_explicit_covariant_parameter_;
+  }
+  void set_is_explicit_covariant_parameter() {
+    is_explicit_covariant_parameter_ = true;
+  }
+
   enum TypeCheckMode {
     kDoTypeCheck,
     kSkipTypeCheck,
@@ -197,6 +205,7 @@
   bool is_invisible_;
   bool is_captured_parameter_;
   bool is_forced_stack_;
+  bool is_explicit_covariant_parameter_;
   TypeCheckMode type_check_mode_;
   VariableIndex index_;
 
@@ -303,14 +312,25 @@
   TokenPosition end_token_pos() const { return end_token_pos_; }
   void set_end_token_pos(TokenPosition value) { end_token_pos_ = value; }
 
+  // Return the list of variables allocated in the context and belonging to this
+  // scope and to its children at the same loop level.
+  const GrowableArray<LocalVariable*>& context_variables() const {
+    return context_variables_;
+  }
+
   // The number of variables allocated in the context and belonging to this
   // scope and to its children at the same loop level.
-  int num_context_variables() const { return num_context_variables_; }
+  int num_context_variables() const { return context_variables().length(); }
 
   // Add a variable to the scope. Returns false if a variable with the
   // same name is already present.
   bool AddVariable(LocalVariable* variable);
 
+  // Add a variable to the scope as a context allocated variable and assigns
+  // it an index within the context. Does not check if the scope already
+  // contains this variable or a variable with the same name.
+  void AddContextVariable(LocalVariable* var);
+
   // Insert a formal parameter variable to the scope at the given position,
   // possibly in front of aliases already added with AddVariable.
   // Returns false if a variable with the same name is already present.
@@ -437,12 +457,14 @@
   int function_level_;         // Reflects the nesting level of local functions.
   int loop_level_;             // Reflects the loop nesting level.
   int context_level_;          // Reflects the level of the runtime context.
-  int num_context_variables_;  // Only set if this scope is a context owner.
   TokenPosition begin_token_pos_;  // Token index of beginning of scope.
   TokenPosition end_token_pos_;    // Token index of end of scope.
   GrowableArray<LocalVariable*> variables_;
   GrowableArray<SourceLabel*> labels_;
 
+  // List of variables allocated into the context which is owned by this scope.
+  GrowableArray<LocalVariable*> context_variables_;
+
   // List of names referenced in this scope and its children that
   // are not resolved to local variables.
   GrowableArray<NameReference*> referenced_;
diff --git a/runtime/vm/scopes_test.cc b/runtime/vm/scopes_test.cc
index 07f4dd7..1005d4c 100644
--- a/runtime/vm/scopes_test.cc
+++ b/runtime/vm/scopes_test.cc
@@ -8,7 +8,7 @@
 
 namespace dart {
 
-TEST_CASE(LocalScope) {
+ISOLATE_UNIT_TEST_CASE(LocalScope) {
   // Allocate a couple of local variables first.
   const Type& dynamic_type = Type::ZoneHandle(Type::DynamicType());
   const String& a = String::ZoneHandle(Symbols::New(thread, "a"));
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index e46a8b3..7e2cb38 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -167,16 +167,19 @@
 
 RawObject* Service::RequestAssets() {
   Thread* T = Thread::Current();
-  TransitionVMToNative transition(T);
-  Api::Scope api_scope(T);
-  if (get_service_assets_callback_ == NULL) {
-    return Object::null();
+  Object& object = Object::Handle();
+  {
+    Api::Scope api_scope(T);
+    TransitionVMToNative transition(T);
+    if (get_service_assets_callback_ == NULL) {
+      return Object::null();
+    }
+    Dart_Handle handle = get_service_assets_callback_();
+    if (Dart_IsError(handle)) {
+      Dart_PropagateError(handle);
+    }
+    object = Api::UnwrapHandle(handle);
   }
-  Dart_Handle handle = get_service_assets_callback_();
-  if (Dart_IsError(handle)) {
-    Dart_PropagateError(handle);
-  }
-  const Object& object = Object::Handle(Api::UnwrapHandle(handle));
   if (object.IsNull()) {
     return Object::null();
   }
@@ -197,7 +200,7 @@
     Exceptions::PropagateError(error);
     return Object::null();
   }
-  return Api::UnwrapHandle(handle);
+  return object.raw();
 }
 
 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
@@ -1327,6 +1330,42 @@
   return true;
 }
 
+static const MethodParameter* get_scripts_params[] = {
+    RUNNABLE_ISOLATE_PARAMETER,
+    NULL,
+};
+
+static bool GetScripts(Thread* thread, JSONStream* js) {
+  Isolate* isolate = thread->isolate();
+  Zone* zone = thread->zone();
+  ASSERT(isolate != NULL);
+
+  const GrowableObjectArray& libs =
+      GrowableObjectArray::Handle(zone, isolate->object_store()->libraries());
+  intptr_t num_libs = libs.Length();
+
+  Library& lib = Library::Handle(zone);
+  Array& scripts = Array::Handle(zone);
+  Script& script = Script::Handle(zone);
+
+  JSONObject jsobj(js);
+  {
+    jsobj.AddProperty("type", "ScriptList");
+    JSONArray script_array(&jsobj, "scripts");
+    for (intptr_t i = 0; i < num_libs; i++) {
+      lib ^= libs.At(i);
+      ASSERT(!lib.IsNull());
+      scripts ^= lib.LoadedScripts();
+      for (intptr_t j = 0; j < scripts.Length(); j++) {
+        script ^= scripts.At(j);
+        ASSERT(!script.IsNull());
+        script_array.AddValue(script);
+      }
+    }
+  }
+  return true;
+}
+
 static const MethodParameter* get_unused_changes_in_last_reload_params[] = {
     ISOLATE_PARAMETER, NULL,
 };
@@ -1825,6 +1864,10 @@
   if (!code.IsNull()) {
     return code.raw();
   }
+  Bytecode& bytecode = Bytecode::Handle(Bytecode::FindCode(pc));
+  if (!bytecode.IsNull()) {
+    return bytecode.raw();
+  }
 
   // Not found.
   return Object::sentinel().raw();
@@ -2362,7 +2405,6 @@
     // We don't use Instance::Cast here because it doesn't allow null.
     Instance& instance = Instance::Handle(zone);
     instance ^= receiver.raw();
-
     const Object& result =
         Object::Handle(zone, instance.Invoke(selector, args, arg_names));
     result.PrintJSON(js, true);
@@ -2490,76 +2532,12 @@
 }
 
 static bool Evaluate(Thread* thread, JSONStream* js) {
-  if (CheckDebuggerDisabled(thread, js)) {
-    return true;
-  }
-
-  const char* target_id = js->LookupParam("targetId");
-  if (target_id == NULL) {
-    PrintMissingParamError(js, "targetId");
-    return true;
-  }
-  const char* expr = js->LookupParam("expression");
-  if (expr == NULL) {
-    PrintMissingParamError(js, "expression");
-    return true;
-  }
-
-  Zone* zone = thread->zone();
-  const GrowableObjectArray& names =
-      GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
-  const GrowableObjectArray& values =
-      GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
-  if (BuildScope(thread, js, names, values)) {
-    return true;
-  }
-  const Array& names_array = Array::Handle(zone, Array::MakeFixedLength(names));
-  const Array& values_array =
-      Array::Handle(zone, Array::MakeFixedLength(values));
-
-  const String& expr_str = String::Handle(zone, String::New(expr));
-  ObjectIdRing::LookupResult lookup_result;
-  Object& obj =
-      Object::Handle(zone, LookupHeapObject(thread, target_id, &lookup_result));
-  if (obj.raw() == Object::sentinel().raw()) {
-    if (lookup_result == ObjectIdRing::kCollected) {
-      PrintSentinel(js, kCollectedSentinel);
-    } else if (lookup_result == ObjectIdRing::kExpired) {
-      PrintSentinel(js, kExpiredSentinel);
-    } else {
-      PrintInvalidParamError(js, "targetId");
-    }
-    return true;
-  }
-  if (obj.IsLibrary()) {
-    const Library& lib = Library::Cast(obj);
-    const Object& result =
-        Object::Handle(zone, lib.Evaluate(expr_str, names_array, values_array));
-    result.PrintJSON(js, true);
-    return true;
-  }
-  if (obj.IsClass()) {
-    const Class& cls = Class::Cast(obj);
-    const Object& result =
-        Object::Handle(zone, cls.Evaluate(expr_str, names_array, values_array));
-    result.PrintJSON(js, true);
-    return true;
-  }
-  if ((obj.IsInstance() || obj.IsNull()) && !ContainsNonInstance(obj)) {
-    // We don't use Instance::Cast here because it doesn't allow null.
-    Instance& instance = Instance::Handle(zone);
-    instance ^= obj.raw();
-    const Class& receiver_cls = Class::Handle(zone, instance.clazz());
-    const Object& result = Object::Handle(
-        zone,
-        instance.Evaluate(receiver_cls, expr_str, names_array, values_array));
-    result.PrintJSON(js, true);
-    return true;
-  }
-  js->PrintError(kInvalidParams,
-                 "%s: invalid 'targetId' parameter: "
-                 "Cannot evaluate against a VM-internal object",
-                 js->method());
+  // If a compilation service is available, this RPC invocation will have been
+  // intercepted by RunningIsolates.routeRequest.
+  js->PrintError(
+      kExpressionCompilationError,
+      "%s: No compilation service available; cannot evaluate from source.",
+      js->method());
   return true;
 }
 
@@ -2769,7 +2747,6 @@
 
   bool is_static = BoolParameter::Parse(js->LookupParam("isStatic"), false);
 
-  Dart_KernelCompilationResult compilation_result;
   const GrowableObjectArray& params =
       GrowableObjectArray::Handle(thread->zone(), GrowableObjectArray::New());
   if (!ParseCSVList(js->LookupParam("definitions"), params)) {
@@ -2784,14 +2761,12 @@
     return true;
   }
 
-  {
-    TransitionVMToNative transition(thread);
-    compilation_result = KernelIsolate::CompileExpressionToKernel(
-        js->LookupParam("expression"),
-        Array::Handle(Array::MakeFixedLength(params)),
-        Array::Handle(Array::MakeFixedLength(type_params)),
-        js->LookupParam("libraryUri"), js->LookupParam("klass"), is_static);
-  }
+  Dart_KernelCompilationResult compilation_result =
+      KernelIsolate::CompileExpressionToKernel(
+          js->LookupParam("expression"),
+          Array::Handle(Array::MakeFixedLength(params)),
+          Array::Handle(Array::MakeFixedLength(type_params)),
+          js->LookupParam("libraryUri"), js->LookupParam("klass"), is_static);
 
   if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
     js->PrintError(kExpressionCompilationError, "%s", compilation_result.error);
@@ -2941,34 +2916,12 @@
 };
 
 static bool EvaluateInFrame(Thread* thread, JSONStream* js) {
-  if (CheckDebuggerDisabled(thread, js)) {
-    return true;
-  }
-
-  Isolate* isolate = thread->isolate();
-  DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
-  intptr_t framePos = UIntParameter::Parse(js->LookupParam("frameIndex"));
-  if (framePos >= stack->Length()) {
-    PrintInvalidParamError(js, "frameIndex");
-    return true;
-  }
-  ActivationFrame* frame = stack->FrameAt(framePos);
-
-  Zone* zone = thread->zone();
-  const GrowableObjectArray& names =
-      GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
-  const GrowableObjectArray& values =
-      GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
-  if (BuildScope(thread, js, names, values)) {
-    return true;
-  }
-
-  const char* expr = js->LookupParam("expression");
-  const String& expr_str = String::Handle(zone, String::New(expr));
-
-  const Object& result =
-      Object::Handle(zone, frame->Evaluate(expr_str, names, values));
-  result.PrintJSON(js, true);
+  // If a compilation service is available, this RPC invocation will have been
+  // intercepted by RunningIsolates.routeRequest.
+  js->PrintError(
+      kExpressionCompilationError,
+      "%s: No compilation service available; cannot evaluate from source.",
+      js->method());
   return true;
 }
 
@@ -3157,8 +3110,7 @@
   }
 
   Isolate* isolate = thread->isolate();
-  Dart_LibraryTagHandler handler = isolate->library_tag_handler();
-  if (handler == NULL) {
+  if (!isolate->HasTagHandler()) {
     js->PrintError(kFeatureDisabled,
                    "A library tag handler must be installed.");
     return true;
@@ -4832,6 +4784,8 @@
     get_retained_size_params },
   { "_getRetainingPath", GetRetainingPath,
     get_retaining_path_params },
+  { "getScripts", GetScripts,
+    get_scripts_params },
   { "getSourceReport", GetSourceReport,
     get_source_report_params },
   { "getStack", GetStack,
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index cdf1812..ca29775 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 11
+#define SERVICE_PROTOCOL_MINOR_VERSION 12
 
 class Array;
 class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index d563a2c..3929ba0 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.11
+# Dart VM Service Protocol 3.12
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.11_ of the Dart VM Service Protocol. This
+This document describes of _version 3.12_ 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.
@@ -31,6 +31,7 @@
   - [evaluateInFrame](#evaluateinframe)
   - [getFlagList](#getflaglist)
   - [getIsolate](#getisolate)
+  - [getScripts](#getisolatescripts)
   - [getObject](#getobject)
   - [getSourceReport](#getsourcereport)
   - [getStack](#getstack)
@@ -82,6 +83,7 @@
   - [Sentinel](#sentinel)
   - [SentinelKind](#sentinelkind)
   - [Script](#script)
+  - [ScriptList](#scriptlist)
   - [SourceLocation](#sourcelocation)
   - [SourceReport](#sourcereport)
   - [SourceReportCoverage](#sourcereportcoverage)
@@ -595,6 +597,17 @@
 
 See [Isolate](#isolate).
 
+### getScripts
+
+```
+ScriptList getScripts(string isolateId)
+```
+
+The _getScripts_ RPC is used to retrieve a _ScriptList_ containing all
+scripts for an isolate based on the isolate's _isolateId_.
+
+See [ScriptList](#scriptlist).
+
 ### getObject
 
 ```
@@ -1975,7 +1988,7 @@
   // Vector instance kinds.
   Float32x4,
   Float64x2,
-  Int32x4
+  Int32x4,
 
   // An instance of the built-in VM TypedData implementations. User-defined
   // TypedDatas will be PlainInstance.
@@ -2404,6 +2417,14 @@
 101 | 1 | 8
 102 | 2 | 7
 
+### ScriptList
+
+```
+class ScriptList extends Response {
+  @Script[] scripts;
+}
+```
+
 ### SourceLocation
 
 ```
@@ -2709,5 +2730,6 @@
 3.9 | Changed numbers for errors related to service extensions.
 3.10 | Add 'invoke'.
 3.11 | Rename 'invoke' parameter 'receiverId' to 'targetId.
+3.12 | Add 'getScripts' RPC and `ScriptList` object.
 
 [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 3d26758..39dd081 100644
--- a/runtime/vm/service/service_dev.md
+++ b/runtime/vm/service/service_dev.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.12-dev
+# Dart VM Service Protocol 3.13-dev
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.12-dev_ of the Dart VM Service Protocol. This
+This document describes of _version 3.13-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.
@@ -31,6 +31,7 @@
   - [evaluateInFrame](#evaluateinframe)
   - [getFlagList](#getflaglist)
   - [getIsolate](#getisolate)
+  - [getScripts](#getisolatescripts)
   - [getObject](#getobject)
   - [getSourceReport](#getsourcereport)
   - [getStack](#getstack)
@@ -82,6 +83,7 @@
   - [Sentinel](#sentinel)
   - [SentinelKind](#sentinelkind)
   - [Script](#script)
+  - [ScriptList](#scriptlist)
   - [SourceLocation](#sourcelocation)
   - [SourceReport](#sourcereport)
   - [SourceReportCoverage](#sourcereportcoverage)
@@ -595,6 +597,17 @@
 
 See [Isolate](#isolate).
 
+### getScripts
+
+```
+ScriptList getScripts(string isolateId)
+```
+
+The _getScripts_ RPC is used to retrieve a _ScriptList_ containing all
+scripts for an isolate based on the isolate's _isolateId_.
+
+See [ScriptList](#scriptlist).
+
 ### getObject
 
 ```
@@ -1975,7 +1988,7 @@
   // Vector instance kinds.
   Float32x4,
   Float64x2,
-  Int32x4
+  Int32x4,
 
   // An instance of the built-in VM TypedData implementations. User-defined
   // TypedDatas will be PlainInstance.
@@ -2404,6 +2417,14 @@
 101 | 1 | 8
 102 | 2 | 7
 
+### ScriptList
+
+```
+class ScriptList extends Response {
+  @Script[] scripts;
+}
+```
+
 ### SourceLocation
 
 ```
@@ -2709,5 +2730,6 @@
 3.9 | Changed numbers for errors related to service extensions.
 3.10 | Add 'invoke'.
 3.11 | Rename 'invoke' parameter 'receiverId' to 'targetId.
+3.12 | Add 'getScripts' RPC and `ScriptList` object.
 
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index 607f8b5..8eddb65 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -384,7 +384,6 @@
       if (!error.IsNull() && !error.IsUnwindError()) {
         OS::PrintErr("vm-service: Error: %s\n", error.ToErrorCString());
       }
-      TransitionVMToNative transition(T);
       Dart::RunShutdownCallback();
     }
     ASSERT(ServiceIsolate::IsServiceIsolate(I));
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 72e7ed8..779a863 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -276,6 +276,7 @@
   Code& unoptimized_code = Code::Handle();
   while (frame != NULL) {
     if (frame->IsDartFrame()) {
+      ASSERT(!frame->is_interpreted());  // Not yet supported.
       code = frame->LookupDartCode();
       function = code.function();
       if (code.is_optimized()) {
@@ -3736,7 +3737,7 @@
   set_register(FP, static_cast<int32_t>(fp));
   set_register(THR, reinterpret_cast<uword>(thread));
   // Set the tag.
-  thread->set_vm_tag(VMTag::kDartTagId);
+  thread->set_vm_tag(VMTag::kDartCompiledTagId);
   // Clear top exit frame.
   thread->set_top_exit_frame_info(0);
   // Restore pool pointer.
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 9ae3d30..12a2b71 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -299,6 +299,7 @@
   Code& unoptimized_code = Code::Handle();
   while (frame != NULL) {
     if (frame->IsDartFrame()) {
+      ASSERT(!frame->is_interpreted());  // Not yet supported.
       code = frame->LookupDartCode();
       function = code.function();
       if (code.is_optimized()) {
@@ -3556,7 +3557,7 @@
   set_register(NULL, FP, static_cast<int64_t>(fp));
   set_register(NULL, THR, reinterpret_cast<int64_t>(thread));
   // Set the tag.
-  thread->set_vm_tag(VMTag::kDartTagId);
+  thread->set_vm_tag(VMTag::kDartCompiledTagId);
   // Clear top exit frame.
   thread->set_top_exit_frame_info(0);
   // Restore pool pointer.
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 4ce6696..f0d7dad 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -202,8 +202,8 @@
     RawSmi* index = static_cast<RawSmi*>(args[1]);
     RawArray* array = static_cast<RawArray*>(args[0]);
     if (CheckIndex(index, array->ptr()->length_)) {
-      array->StorePointer(array->ptr()->data() + Smi::Value(index), args[2],
-                          thread);
+      array->StoreArrayPointer(array->ptr()->data() + Smi::Value(index),
+                               args[2], thread);
       return true;
     }
     return false;
@@ -238,8 +238,8 @@
         static_cast<RawGrowableObjectArray*>(args[0]);
     if (CheckIndex(index, array->ptr()->length_)) {
       RawArray* data = array->ptr()->data_;
-      data->StorePointer(data->ptr()->data() + Smi::Value(index), args[2],
-                         thread);
+      data->StoreArrayPointer(data->ptr()->data() + Smi::Value(index), args[2],
+                              thread);
       return true;
     }
     return false;
@@ -957,7 +957,7 @@
   if (!setjmp(buffer.buffer_)) {
     thread->set_vm_tag(reinterpret_cast<uword>(drt));
     drt(args);
-    thread->set_vm_tag(VMTag::kDartTagId);
+    thread->set_vm_tag(VMTag::kDartCompiledTagId);
     thread->set_top_exit_frame_info(0);
     return true;
   } else {
@@ -974,7 +974,7 @@
   if (!setjmp(buffer.buffer_)) {
     thread->set_vm_tag(reinterpret_cast<uword>(function));
     wrapper(args, function);
-    thread->set_vm_tag(VMTag::kDartTagId);
+    thread->set_vm_tag(VMTag::kDartCompiledTagId);
     thread->set_top_exit_frame_info(0);
     return true;
   } else {
@@ -1023,8 +1023,8 @@
   USE(rB);                                                                     \
   USE(rC)
 #define DECODE_A_B_C                                                           \
-  rB = ((op >> Bytecode::kBShift) & Bytecode::kBMask);                         \
-  rC = ((op >> Bytecode::kCShift) & Bytecode::kCMask);
+  rB = ((op >> SimulatorBytecode::kBShift) & SimulatorBytecode::kBMask);       \
+  rC = ((op >> SimulatorBytecode::kCShift) & SimulatorBytecode::kCMask);
 
 #define DECLARE_A_B_Y                                                          \
   uint16_t rB;                                                                 \
@@ -1032,8 +1032,8 @@
   USE(rB);                                                                     \
   USE(rY)
 #define DECODE_A_B_Y                                                           \
-  rB = ((op >> Bytecode::kBShift) & Bytecode::kBMask);                         \
-  rY = ((op >> Bytecode::kYShift) & Bytecode::kYMask);
+  rB = ((op >> SimulatorBytecode::kBShift) & SimulatorBytecode::kBMask);       \
+  rY = ((op >> SimulatorBytecode::kYShift) & SimulatorBytecode::kYMask);
 
 #define DECLARE_0
 #define DECODE_0
@@ -1044,7 +1044,7 @@
 #define DECLARE___D                                                            \
   uint32_t rD;                                                                 \
   USE(rD)
-#define DECODE___D rD = (op >> Bytecode::kDShift);
+#define DECODE___D rD = (op >> SimulatorBytecode::kDShift);
 
 #define DECLARE_A_D DECLARE___D
 #define DECODE_A_D DECODE___D
@@ -1052,12 +1052,13 @@
 #define DECLARE_A_X                                                            \
   int32_t rD;                                                                  \
   USE(rD)
-#define DECODE_A_X rD = (static_cast<int32_t>(op) >> Bytecode::kDShift);
+#define DECODE_A_X                                                             \
+  rD = (static_cast<int32_t>(op) >> SimulatorBytecode::kDShift);
 
 #define SMI_FASTPATH_ICDATA_INC                                                \
   do {                                                                         \
-    ASSERT(Bytecode::IsCallOpcode(*pc));                                       \
-    const uint16_t kidx = Bytecode::DecodeD(*pc);                              \
+    ASSERT(SimulatorBytecode::IsCallOpcode(*pc));                              \
+    const uint16_t kidx = SimulatorBytecode::DecodeD(*pc);                     \
     const RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx));           \
     RawObject** entries = icdata->ptr()->ic_data_->ptr()->data();              \
     SimulatorHelpers::IncrementICUsageCount(entries, 0, 2);                    \
@@ -1226,7 +1227,7 @@
 
   // Save current VM tag and mark thread as executing Dart code.
   const uword vm_tag = thread->vm_tag();
-  thread->set_vm_tag(VMTag::kDartTagId);
+  thread->set_vm_tag(VMTag::kDartCompiledTagId);
 
   // Save current top stack resource and reset the list.
   StackResource* top_resource = thread->top_resource();
@@ -1766,10 +1767,10 @@
     RawObject** args = SP - argc + 1;
     const intptr_t receiver_cid = SimulatorHelpers::GetClassId(args[0]);
     for (intptr_t i = 0; i < 2 * cids_length; i += 2) {
-      const intptr_t icdata_cid = Bytecode::DecodeD(*(pc + i));
+      const intptr_t icdata_cid = SimulatorBytecode::DecodeD(*(pc + i));
       if (receiver_cid == icdata_cid) {
-        RawFunction* target =
-            RAW_CAST(Function, LOAD_CONSTANT(Bytecode::DecodeD(*(pc + i + 1))));
+        RawFunction* target = RAW_CAST(
+            Function, LOAD_CONSTANT(SimulatorBytecode::DecodeD(*(pc + i + 1))));
         *++SP = target;
         pc++;
         break;
@@ -1787,11 +1788,11 @@
     const intptr_t receiver_cid = SimulatorHelpers::GetClassId(args[0]);
     for (intptr_t i = 0; i < 3 * cids_length; i += 3) {
       // Note unsigned types to get an unsigned range compare.
-      const uintptr_t cid_start = Bytecode::DecodeD(*(pc + i));
-      const uintptr_t cids = Bytecode::DecodeD(*(pc + i + 1));
+      const uintptr_t cid_start = SimulatorBytecode::DecodeD(*(pc + i));
+      const uintptr_t cids = SimulatorBytecode::DecodeD(*(pc + i + 1));
       if (receiver_cid - cid_start < cids) {
-        RawFunction* target =
-            RAW_CAST(Function, LOAD_CONSTANT(Bytecode::DecodeD(*(pc + i + 2))));
+        RawFunction* target = RAW_CAST(
+            Function, LOAD_CONSTANT(SimulatorBytecode::DecodeD(*(pc + i + 2))));
         *++SP = target;
         pc++;
         break;
@@ -2616,7 +2617,7 @@
     }
 
     // Look at the caller to determine how many arguments to pop.
-    const uint8_t argc = Bytecode::DecodeArgc(pc[-1]);
+    const uint8_t argc = SimulatorBytecode::DecodeArgc(pc[-1]);
 
     // Restore SP, FP and PP. Push result and dispatch.
     SP = FrameArguments(FP, argc);
@@ -2659,7 +2660,7 @@
   {
     BYTECODE(StoreFieldExt, A_D);
     // The offset is stored in the following nop-instruction which is skipped.
-    const uint16_t offset_in_words = Bytecode::DecodeD(*pc++);
+    const uint16_t offset_in_words = SimulatorBytecode::DecodeD(*pc++);
     RawInstance* instance = reinterpret_cast<RawInstance*>(FP[rA]);
     RawObject* value = FP[rD];
 
@@ -2694,7 +2695,7 @@
   {
     BYTECODE(LoadFieldExt, A_D);
     // The offset is stored in the following nop-instruction which is skipped.
-    const uint16_t offset_in_words = Bytecode::DecodeD(*pc++);
+    const uint16_t offset_in_words = SimulatorBytecode::DecodeD(*pc++);
     const uint16_t instance_reg = rD;
     RawInstance* instance = reinterpret_cast<RawInstance*>(FP[instance_reg]);
     FP[rA] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
@@ -2820,7 +2821,7 @@
         thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size);
     if (LIKELY(start != 0)) {
       RawObject* type_args = SP[0];
-      const intptr_t type_args_offset = Bytecode::DecodeD(*pc);
+      const intptr_t type_args_offset = SimulatorBytecode::DecodeD(*pc);
       // Writes both the tags and the initial identity hash on 64 bit platforms.
       tags = RawObject::NewBit::update(true, tags);
       *reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags;
@@ -3163,9 +3164,9 @@
     const intptr_t cid = SimulatorHelpers::GetClassId(FP[rA]);
     const intptr_t num_cases = rD;
     for (intptr_t i = 0; i < num_cases; i++) {
-      ASSERT(Bytecode::DecodeOpcode(pc[i]) == Bytecode::kNop);
-      intptr_t test_target = Bytecode::DecodeA(pc[i]);
-      intptr_t test_cid = Bytecode::DecodeD(pc[i]);
+      ASSERT(SimulatorBytecode::DecodeOpcode(pc[i]) == SimulatorBytecode::kNop);
+      intptr_t test_target = SimulatorBytecode::DecodeA(pc[i]);
+      intptr_t test_cid = SimulatorBytecode::DecodeD(pc[i]);
       if (cid == test_cid) {
         if (test_target != 0) {
           pc += 1;  // Match true.
@@ -3213,7 +3214,7 @@
     const intptr_t actual_cid =
         reinterpret_cast<intptr_t>(FP[rA]) >> kSmiTagSize;
     const uintptr_t cid_start = rD;
-    const uintptr_t cid_range = Bytecode::DecodeD(*pc);
+    const uintptr_t cid_range = SimulatorBytecode::DecodeD(*pc);
     // Unsigned comparison.  Skip either just the nop or both the nop and the
     // following instruction.
     pc += (actual_cid - cid_start <= cid_range) ? 2 : 1;
@@ -3224,9 +3225,9 @@
     BYTECODE(CheckBitTest, A_D);
     const intptr_t raw_value = reinterpret_cast<intptr_t>(FP[rA]);
     const bool is_smi = ((raw_value & kSmiTagMask) == kSmiTag);
-    const intptr_t cid_min = Bytecode::DecodeD(*pc);
-    const intptr_t cid_mask =
-        Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(Bytecode::DecodeD(*(pc + 1)))));
+    const intptr_t cid_min = SimulatorBytecode::DecodeD(*pc);
+    const intptr_t cid_mask = Smi::Value(
+        RAW_CAST(Smi, LOAD_CONSTANT(SimulatorBytecode::DecodeD(*(pc + 1)))));
     if (LIKELY(!is_smi)) {
       const intptr_t cid_max = Utils::HighestBit(cid_mask) + cid_min;
       const intptr_t cid = SimulatorHelpers::GetClassId(FP[rA]);
@@ -3253,7 +3254,7 @@
     if (LIKELY(!is_smi)) {
       const intptr_t cid = SimulatorHelpers::GetClassId(FP[rA]);
       for (intptr_t i = 0; i < cids_length; i++) {
-        const intptr_t desired_cid = Bytecode::DecodeD(*(pc + i));
+        const intptr_t desired_cid = SimulatorBytecode::DecodeD(*(pc + i));
         if (cid == desired_cid) {
           pc++;
           break;
@@ -3277,8 +3278,8 @@
       const intptr_t cid = SimulatorHelpers::GetClassId(FP[rA]);
       for (intptr_t i = 0; i < cids_length; i += 2) {
         // Note unsigned type to get unsigned range check below.
-        const uintptr_t cid_start = Bytecode::DecodeD(*(pc + i));
-        const uintptr_t cids = Bytecode::DecodeD(*(pc + i + 1));
+        const uintptr_t cid_start = SimulatorBytecode::DecodeD(*(pc + i));
+        const uintptr_t cids = SimulatorBytecode::DecodeD(*(pc + i + 1));
         if (cid - cid_start < cids) {
           pc++;
           break;
@@ -3635,8 +3636,8 @@
     RawSmi* index = RAW_CAST(Smi, SP[2]);
     RawObject* value = SP[3];
     ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    array->StorePointer(array->ptr()->data() + Smi::Value(index), value,
-                        thread);
+    array->StoreArrayPointer(array->ptr()->data() + Smi::Value(index), value,
+                             thread);
     DISPATCH();
   }
 
@@ -3646,8 +3647,8 @@
     RawSmi* index = RAW_CAST(Smi, FP[rB]);
     RawObject* value = FP[rC];
     ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    array->StorePointer(array->ptr()->data() + Smi::Value(index), value,
-                        thread);
+    array->StoreArrayPointer(array->ptr()->data() + Smi::Value(index), value,
+                             thread);
     DISPATCH();
   }
 
@@ -3890,8 +3891,9 @@
     pc = SavedCallerPC(FP);
 
     const bool has_dart_caller = (reinterpret_cast<uword>(pc) & 2) == 0;
-    const intptr_t argc = has_dart_caller ? Bytecode::DecodeArgc(pc[-1])
-                                          : (reinterpret_cast<uword>(pc) >> 2);
+    const intptr_t argc = has_dart_caller
+                              ? SimulatorBytecode::DecodeArgc(pc[-1])
+                              : (reinterpret_cast<uword>(pc) >> 2);
     const bool has_function_type_args =
         has_dart_caller && SimulatorHelpers::ArgDescTypeArgsLen(argdesc_) > 0;
 
@@ -3965,7 +3967,7 @@
   StackResource::Unwind(thread);
 
   // Set the tag.
-  thread->set_vm_tag(VMTag::kDartTagId);
+  thread->set_vm_tag(VMTag::kDartCompiledTagId);
   // Clear top exit frame.
   thread->set_top_exit_frame_info(0);
 
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index eaae077..61521ac 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -1079,7 +1079,7 @@
 
   // Check if it is a code object in that case just write a Null object
   // as we do not want code objects in the snapshot.
-  if (cid == kCodeCid) {
+  if ((cid == kCodeCid) || (cid == kBytecodeCid)) {
     WriteVMIsolateObject(kNullObject);
     return true;
   }
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 2010460..8bded02 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -90,7 +90,6 @@
 class RawTypeParameter;
 class RawTypeRef;
 class RawUnhandledException;
-class RawUnresolvedClass;
 class RawWeakProperty;
 class String;
 class TypeArguments;
@@ -177,9 +176,6 @@
   }
   Kind kind() const { return static_cast<Kind>(Read<int64_t>(kKindOffset)); }
   void set_kind(Kind value) { return Write<int64_t>(kKindOffset, value); }
-  const uint8_t* content() const {
-    return reinterpret_cast<const uint8_t*>(this) + kHeaderSize;
-  }
 
   static bool IsFull(Kind kind) {
     return (kind == kFull) || (kind == kFullJIT) || (kind == kFullAOT);
@@ -187,6 +183,9 @@
   static bool IncludesCode(Kind kind) {
     return (kind == kFullJIT) || (kind == kFullAOT);
   }
+  static bool IncludesBytecode(Kind kind) {
+    return (kind == kFull) || (kind == kFullJIT);
+  }
 
   const uint8_t* Addr() const { return reinterpret_cast<const uint8_t*>(this); }
 
@@ -479,7 +478,6 @@
   friend class TypeParameter;
   friend class TypeRef;
   friend class UnhandledException;
-  friend class UnresolvedClass;
   friend class WeakProperty;
   DISALLOW_COPY_AND_ASSIGN(SnapshotReader);
 };
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 5ff4dd8..f1f05d7 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -403,6 +403,7 @@
   TEST_ROUND_TRIP_IDENTICAL(Object::script_class());
   TEST_ROUND_TRIP_IDENTICAL(Object::library_class());
   TEST_ROUND_TRIP_IDENTICAL(Object::code_class());
+  TEST_ROUND_TRIP_IDENTICAL(Object::bytecode_class());
   TEST_ROUND_TRIP_IDENTICAL(Object::instructions_class());
   TEST_ROUND_TRIP_IDENTICAL(Object::pc_descriptors_class());
   TEST_ROUND_TRIP_IDENTICAL(Object::exception_handlers_class());
@@ -760,24 +761,23 @@
   {
     TestIsolateScope __test_isolate__;
 
+    // Create a test library and Load up a test script in it.
+    TestCase::LoadTestScript(kScriptChars, NULL);
+
     Thread* thread = Thread::Current();
+    TransitionNativeToVM transition(thread);
     StackZone zone(thread);
     HandleScope scope(thread);
 
-    // Create a test library and Load up a test script in it.
-    TestCase::LoadTestScript(kScriptChars, NULL);
     EXPECT_VALID(Api::CheckAndFinalizePendingClasses(thread));
     timer1.Stop();
     OS::PrintErr("Without Snapshot: %" Pd64 "us\n", timer1.TotalElapsedTime());
 
     // Write snapshot with object content.
-    {
-      TransitionNativeToVM transition(thread);
-      FullSnapshotWriter writer(
-          Snapshot::kFull, NULL, &isolate_snapshot_data_buffer,
-          &malloc_allocator, NULL, NULL /* image_writer */);
-      writer.WriteFullSnapshot();
-    }
+    FullSnapshotWriter writer(Snapshot::kFull, NULL,
+                              &isolate_snapshot_data_buffer, &malloc_allocator,
+                              NULL, NULL /* image_writer */);
+    writer.WriteFullSnapshot();
   }
 
   // Now Create another isolate using the snapshot and execute a method
@@ -869,8 +869,11 @@
 // Helper function to call a top level Dart function and serialize the result.
 static Message* GetSerialized(Dart_Handle lib, const char* dart_function) {
   Dart_Handle result;
-  result = Dart_Invoke(lib, NewString(dart_function), 0, NULL);
-  EXPECT_VALID(result);
+  {
+    TransitionVMToNative transition(Thread::Current());
+    result = Dart_Invoke(lib, NewString(dart_function), 0, NULL);
+    EXPECT_VALID(result);
+  }
   Object& obj = Object::Handle(Api::UnwrapHandle(result));
 
   // Serialize the object into a message.
@@ -1009,6 +1012,7 @@
   {
     Thread* thread = Thread::Current();
     CHECK_API_SCOPE(thread);
+    TransitionNativeToVM transition(thread);
     HANDLESCOPE(thread);
 
     {
@@ -1081,6 +1085,7 @@
 
   {
     CHECK_API_SCOPE(thread);
+    TransitionNativeToVM transition(thread);
     HANDLESCOPE(thread);
     StackZone zone(thread);
     {
@@ -1208,6 +1213,7 @@
 
   {
     CHECK_API_SCOPE(thread);
+    TransitionNativeToVM transition(thread);
     HANDLESCOPE(thread);
     StackZone zone(thread);
     {
@@ -1445,6 +1451,7 @@
 
   {
     CHECK_API_SCOPE(thread);
+    TransitionNativeToVM transition(thread);
     HANDLESCOPE(thread);
     StackZone zone(thread);
     {
@@ -1653,6 +1660,7 @@
 
   {
     CHECK_API_SCOPE(thread);
+    TransitionNativeToVM transition(thread);
     HANDLESCOPE(thread);
     StackZone zone(thread);
     {
@@ -1883,6 +1891,7 @@
 
   {
     CHECK_API_SCOPE(thread);
+    TransitionNativeToVM transition(thread);
     HANDLESCOPE(thread);
     StackZone zone(thread);
     {
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 0bcef13..edc5923 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -389,12 +389,13 @@
   const TokenPosition end_pos = func.end_token_pos();
 
   Code& code = Code::Handle(zone(), func.unoptimized_code());
+  Bytecode& bytecode = Bytecode::Handle(zone());
 #if !defined(DART_PRECOMPILED_RUNTIME)
   if (FLAG_enable_interpreter && code.IsNull() && func.HasBytecode()) {
-    code = func.Bytecode();
+    bytecode = func.bytecode();
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
-  if (code.IsNull()) {
+  if (code.IsNull() && bytecode.IsNull()) {
     if (func.HasCode() || (compile_mode_ == kForceCompile)) {
       const Error& err =
           Error::Handle(Compiler::EnsureUnoptimizedCode(thread(), func));
@@ -411,7 +412,7 @@
       code = func.unoptimized_code();
 #if !defined(DART_PRECOMPILED_RUNTIME)
       if (FLAG_enable_interpreter && code.IsNull() && func.HasBytecode()) {
-        code = func.Bytecode();
+        bytecode = func.bytecode();
       }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
     } else {
@@ -424,7 +425,7 @@
       return;
     }
   }
-  ASSERT(!code.IsNull());
+  ASSERT(!code.IsNull() || !bytecode.IsNull());
 
   // We skip compiled async functions.  Once an async function has
   // been compiled, there is another function with the same range which
@@ -438,8 +439,14 @@
   range.AddProperty("scriptIndex", GetScriptIndex(script));
   range.AddProperty("startPos", begin_pos);
   range.AddProperty("endPos", end_pos);
-  range.AddProperty("compiled", true);
+  // 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());
 
+  // 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/source_report_test.cc b/runtime/vm/source_report_test.cc
index 6c5e1cf..78ad2ba 100644
--- a/runtime/vm/source_report_test.cc
+++ b/runtime/vm/source_report_test.cc
@@ -11,15 +11,15 @@
 #ifndef PRODUCT
 
 static RawObject* ExecuteScript(const char* script) {
-  TransitionVMToNative transition(Thread::Current());
-  Dart_Handle h_lib = TestCase::LoadTestScript(script, NULL);
-  EXPECT_VALID(h_lib);
-  Library& lib = Library::Handle();
-  lib ^= Api::UnwrapHandle(h_lib);
-  EXPECT(!lib.IsNull());
-  Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-  return Api::UnwrapHandle(h_lib);
+  Dart_Handle lib;
+  {
+    TransitionVMToNative transition(Thread::Current());
+    lib = TestCase::LoadTestScript(script, NULL);
+    EXPECT_VALID(lib);
+    Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+    EXPECT_VALID(result);
+  }
+  return Api::UnwrapHandle(lib);
 }
 
 ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_NoCalls) {
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index a8936df..a43e7d6 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -86,6 +86,15 @@
   ASSERT(thread_ == Thread::Current());
   Zone* zone = Thread::Current()->zone();
   if (IsDartFrame()) {
+    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());
+    }
     const Code& code = Code::Handle(zone, LookupDartCode());
     ASSERT(!code.IsNull());
     const Object& owner = Object::Handle(zone, code.owner());
@@ -163,12 +172,21 @@
   // be able to reuse the handle based code and avoid having to add
   // helper functions to the raw object interface.
   NoSafepointScope no_safepoint;
-  Code code;
-  RawCode* raw_code = UncheckedGetCodeObject();
-  // May forward raw_code. Note we don't just visit the pc marker slot first
+  RawObject* pc_marker = *(reinterpret_cast<RawObject**>(
+      fp() + ((is_interpreted() ? kKBCPcMarkerSlotFromFp
+                                : runtime_frame_layout.code_from_fp) *
+              kWordSize)));
+  // May forward raw code. Note we don't just visit the pc marker slot first
   // because the visitor's forwarding might not be idempotent.
-  visitor->VisitPointer(reinterpret_cast<RawObject**>(&raw_code));
-  code ^= raw_code;
+  visitor->VisitPointer(&pc_marker);
+  Code code;
+  if (pc_marker->IsHeapObject() && (pc_marker->GetClassId() == kCodeCid)) {
+    code ^= pc_marker;
+  } else {
+    ASSERT(pc_marker == Object::null() ||
+           (is_interpreted() && (!pc_marker->IsHeapObject() ||
+                                 (pc_marker->GetClassId() == kBytecodeCid))));
+  }
   if (!code.IsNull()) {
     // Optimized frames have a stack map. We need to visit the frame based
     // on the stack map.
@@ -289,6 +307,11 @@
 }
 
 RawFunction* StackFrame::LookupDartFunction() const {
+  if (is_interpreted()) {
+    const Bytecode& bytecode = Bytecode::Handle(LookupDartBytecode());
+    ASSERT(!bytecode.IsNull());
+    return bytecode.function();
+  }
   const Code& code = Code::Handle(LookupDartCode());
   if (!code.IsNull()) {
     return code.function();
@@ -314,17 +337,33 @@
 }
 
 RawCode* StackFrame::GetCodeObject() const {
-  RawCode* pc_marker = UncheckedGetCodeObject();
+  ASSERT(!is_interpreted());
+  RawObject* pc_marker = *(reinterpret_cast<RawObject**>(
+      fp() + runtime_frame_layout.code_from_fp * kWordSize));
   ASSERT((pc_marker == Object::null()) ||
          (pc_marker->GetClassId() == kCodeCid));
-  return pc_marker;
+  return reinterpret_cast<RawCode*>(pc_marker);
 }
 
-RawCode* StackFrame::UncheckedGetCodeObject() const {
-  return *(reinterpret_cast<RawCode**>(
-      fp() + ((is_interpreted() ? kKBCPcMarkerSlotFromFp
-                                : runtime_frame_layout.code_from_fp) *
-              kWordSize)));
+RawBytecode* StackFrame::LookupDartBytecode() const {
+// We add a no gc scope to ensure that the code below does not trigger
+// a GC as we are handling raw object references here. It is possible
+// that the code is called while a GC is in progress, that is ok.
+#if !defined(HOST_OS_WINDOWS) && !defined(HOST_OS_FUCHSIA)
+  // On Windows and Fuchsia, the profiler calls this from a separate thread
+  // where Thread::Current() is NULL, so we cannot create a NoSafepointScope.
+  NoSafepointScope no_safepoint;
+#endif
+  return GetBytecodeObject();
+}
+
+RawBytecode* StackFrame::GetBytecodeObject() const {
+  ASSERT(is_interpreted());
+  RawObject* pc_marker = *(
+      reinterpret_cast<RawObject**>(fp() + kKBCPcMarkerSlotFromFp * kWordSize));
+  ASSERT((pc_marker == Object::null()) ||
+         (pc_marker->GetClassId() == kBytecodeCid));
+  return reinterpret_cast<RawBytecode*>(pc_marker);
 }
 
 bool StackFrame::FindExceptionHandler(Thread* thread,
@@ -334,32 +373,46 @@
                                       bool* is_optimized) const {
   REUSABLE_CODE_HANDLESCOPE(thread);
   Code& code = reused_code_handle.Handle();
-  code = LookupDartCode();
-  if (code.IsNull()) {
-    return false;  // Stub frames do not have exception handlers.
+  REUSABLE_BYTECODE_HANDLESCOPE(thread);
+  Bytecode& bytecode = reused_bytecode_handle.Handle();
+  REUSABLE_EXCEPTION_HANDLERS_HANDLESCOPE(thread);
+  ExceptionHandlers& handlers = reused_exception_handlers_handle.Handle();
+  REUSABLE_PC_DESCRIPTORS_HANDLESCOPE(thread);
+  PcDescriptors& descriptors = reused_pc_descriptors_handle.Handle();
+  uword start;
+  intptr_t size;
+  if (is_interpreted()) {
+    bytecode = LookupDartBytecode();
+    ASSERT(!bytecode.IsNull());
+    start = bytecode.PayloadStart();
+    size = bytecode.Size();
+    handlers = bytecode.exception_handlers();
+    descriptors = bytecode.pc_descriptors();
+  } else {
+    code = LookupDartCode();
+    if (code.IsNull()) {
+      return false;  // Stub frames do not have exception handlers.
+    }
+    start = code.PayloadStart();
+    size = code.Size();
+    handlers = code.exception_handlers();
+    descriptors = code.pc_descriptors();
+    *is_optimized = code.is_optimized();
   }
-  *is_optimized = code.is_optimized();
   HandlerInfoCache* cache = thread->isolate()->handler_info_cache();
   ExceptionHandlerInfo* info = cache->Lookup(pc());
   if (info != NULL) {
-    *handler_pc = code.PayloadStart() + info->handler_pc_offset;
+    *handler_pc = start + info->handler_pc_offset;
     *needs_stacktrace = info->needs_stacktrace;
     *has_catch_all = info->has_catch_all;
     return true;
   }
-  uword pc_offset = pc() - code.PayloadStart();
+  uword pc_offset = pc() - start;
 
-  REUSABLE_EXCEPTION_HANDLERS_HANDLESCOPE(thread);
-  ExceptionHandlers& handlers = reused_exception_handlers_handle.Handle();
-  handlers = code.exception_handlers();
   if (handlers.num_entries() == 0) {
     return false;
   }
 
-  // Find pc descriptor for the current pc.
-  REUSABLE_PC_DESCRIPTORS_HANDLESCOPE(thread);
-  PcDescriptors& descriptors = reused_pc_descriptors_handle.Handle();
-  descriptors = code.pc_descriptors();
   PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind);
   intptr_t try_index = -1;
   if (is_interpreted()) {
@@ -394,7 +447,7 @@
   }
   ExceptionHandlerInfo handler_info;
   handlers.GetHandlerInfo(try_index, &handler_info);
-  *handler_pc = code.PayloadStart() + handler_info.handler_pc_offset;
+  *handler_pc = start + handler_info.handler_pc_offset;
   *needs_stacktrace = handler_info.needs_stacktrace;
   *has_catch_all = handler_info.has_catch_all;
   cache->Insert(pc(), handler_info);
@@ -402,6 +455,13 @@
 }
 
 TokenPosition StackFrame::GetTokenPos() const {
+  if (is_interpreted()) {
+    const Bytecode& bytecode = Bytecode::Handle(LookupDartBytecode());
+    if (bytecode.IsNull()) {
+      return TokenPosition::kNoSource;  // Stub frames do not have token_pos.
+    }
+    return bytecode.GetTokenIndexOfPC(pc());
+  }
   const Code& code = Code::Handle(LookupDartCode());
   if (code.IsNull()) {
     return TokenPosition::kNoSource;  // Stub frames do not have token_pos.
@@ -423,6 +483,9 @@
   if (IsEntryFrame() || IsExitFrame() || IsStubFrame()) {
     return true;
   }
+  if (is_interpreted()) {
+    return (LookupDartBytecode() != Bytecode::null());
+  }
   return (LookupDartCode() != Code::null());
 }
 
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index c43b60f..0ffe5da 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -165,6 +165,7 @@
 
   RawFunction* LookupDartFunction() const;
   RawCode* LookupDartCode() const;
+  RawBytecode* LookupDartBytecode() const;
   bool FindExceptionHandler(Thread* thread,
                             uword* handler_pc,
                             bool* needs_stacktrace,
@@ -189,7 +190,7 @@
 
  private:
   RawCode* GetCodeObject() const;
-  RawCode* UncheckedGetCodeObject() const;
+  RawBytecode* GetBytecodeObject() const;
 
   uword GetCallerSp() const {
     return fp() +
diff --git a/runtime/vm/stack_frame_test.cc b/runtime/vm/stack_frame_test.cc
index 1fa5faf..9b89101 100644
--- a/runtime/vm/stack_frame_test.cc
+++ b/runtime/vm/stack_frame_test.cc
@@ -39,8 +39,12 @@
 
 void FUNCTION_NAME(StackFrame_equals)(Dart_NativeArguments args) {
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
-  const Instance& expected = Instance::CheckedHandle(arguments->NativeArgAt(0));
-  const Instance& actual = Instance::CheckedHandle(arguments->NativeArgAt(1));
+  TransitionNativeToVM transition(arguments->thread());
+  Zone* zone = arguments->thread()->zone();
+  const Instance& expected =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
+  const Instance& actual =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
   if (!expected.OperatorEquals(actual)) {
     OS::PrintErr("expected: '%s' actual: '%s'\n", expected.ToCString(),
                  actual.ToCString());
@@ -49,32 +53,28 @@
 }
 
 void FUNCTION_NAME(StackFrame_frameCount)(Dart_NativeArguments args) {
+  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
+  TransitionNativeToVM transition(arguments->thread());
   int count = 0;
   StackFrameIterator frames(ValidationPolicy::kValidateFrames,
-                            Thread::Current(),
+                            arguments->thread(),
                             StackFrameIterator::kNoCrossThreadIteration);
   while (frames.NextFrame() != NULL) {
     count += 1;  // Count the frame.
   }
-  {
-    TransitionNativeToVM transition(Thread::Current());
-    VerifyPointersVisitor::VerifyPointers();
-  }
-  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
+  VerifyPointersVisitor::VerifyPointers();
   arguments->SetReturn(Object::Handle(Smi::New(count)));
 }
 
 void FUNCTION_NAME(StackFrame_dartFrameCount)(Dart_NativeArguments args) {
+  TransitionNativeToVM transition(Thread::Current());
   int count = 0;
   DartFrameIterator frames(Thread::Current(),
                            StackFrameIterator::kNoCrossThreadIteration);
   while (frames.NextFrame() != NULL) {
     count += 1;  // Count the dart frame.
   }
-  {
-    TransitionNativeToVM transition(Thread::Current());
-    VerifyPointersVisitor::VerifyPointers();
-  }
+  VerifyPointersVisitor::VerifyPointers();
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
   arguments->SetReturn(Object::Handle(Smi::New(count)));
 }
@@ -87,13 +87,13 @@
   Dart_Handle name = Dart_GetNativeArgument(args, 1);
 
   TransitionNativeToVM transition(thread);
-  const Smi& frame_index_smi = Smi::CheckedHandle(Api::UnwrapHandle(index));
+  const Smi& frame_index_smi =
+      Smi::CheckedHandle(zone, Api::UnwrapHandle(index));
   const char* expected_name =
-      String::CheckedHandle(Api::UnwrapHandle(name)).ToCString();
+      String::CheckedHandle(zone, Api::UnwrapHandle(name)).ToCString();
   int frame_index = frame_index_smi.Value();
   int count = 0;
-  DartFrameIterator frames(Thread::Current(),
-                           StackFrameIterator::kNoCrossThreadIteration);
+  DartFrameIterator frames(thread, StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = frames.NextFrame();
   while (frame != NULL) {
     if (count == frame_index) {
@@ -143,6 +143,7 @@
                                          bool* auto_setup_scope) {
   ASSERT(auto_setup_scope != NULL);
   *auto_setup_scope = false;
+  TransitionNativeToVM transition(Thread::Current());
   const Object& obj = Object::Handle(Api::UnwrapHandle(name));
   ASSERT(obj.IsString());
   const char* function_name = obj.ToCString();
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index 8f5829d..a16b98d 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -17,7 +17,6 @@
                             StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = frames.NextFrame();
   ASSERT(frame != NULL);  // We expect to find a dart invocation frame.
-  Code& code = Code::Handle(zone);
   Function& function = Function::Handle(zone);
   const bool async_function_is_null = async_function.IsNull();
   while (frame != NULL) {
@@ -25,8 +24,7 @@
       if (skip_frames > 0) {
         skip_frames--;
       } else {
-        code = frame->LookupDartCode();
-        function = code.function();
+        function = frame->LookupDartFunction();
         frame_count++;
         if (!async_function_is_null &&
             (async_function.raw() == function.parent_function())) {
@@ -54,6 +52,7 @@
   ASSERT(frame != NULL);  // We expect to find a dart invocation frame.
   Function& function = Function::Handle(zone);
   Code& code = Code::Handle(zone);
+  Bytecode& bytecode = Bytecode::Handle(zone);
   Smi& offset = Smi::Handle(zone);
   intptr_t collected_frames_count = 0;
   while ((frame != NULL) && (collected_frames_count < count)) {
@@ -61,10 +60,17 @@
       if (skip_frames > 0) {
         skip_frames--;
       } else {
-        code = frame->LookupDartCode();
-        function = code.function();
-        offset = Smi::New(frame->pc() - code.PayloadStart());
-        code_array.SetAt(array_offset, code);
+        if (frame->is_interpreted()) {
+          bytecode = frame->LookupDartBytecode();
+          function = bytecode.function();
+          offset = Smi::New(frame->pc() - bytecode.PayloadStart());
+          code_array.SetAt(array_offset, bytecode);
+        } else {
+          code = frame->LookupDartCode();
+          function = code.function();
+          offset = Smi::New(frame->pc() - code.PayloadStart());
+          code_array.SetAt(array_offset, code);
+        }
         pc_offset_array.SetAt(array_offset, offset);
         array_offset++;
         collected_frames_count++;
@@ -100,8 +106,13 @@
   ASSERT(async_code_array->At(0) != Code::null());
   ASSERT(async_code_array->At(0) ==
          StubCode::AsynchronousGapMarker_entry()->code());
-  const Code& code = Code::Handle(Code::RawCast(async_code_array->At(1)));
-  *async_function = code.function();
+  const Object& code_object = Object::Handle(async_code_array->At(1));
+  if (code_object.IsCode()) {
+    *async_function = Code::Cast(code_object).function();
+  } else {
+    ASSERT(code_object.IsBytecode());
+    *async_function = Bytecode::Cast(code_object).function();
+  }
   ASSERT(!async_function->IsNull());
   ASSERT(async_function->IsAsyncFunction() ||
          async_function->IsAsyncGenerator());
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 823dea5..aad2c87 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -55,16 +55,28 @@
 #else
 
 #define STUB_CODE_GENERATE(name)                                               \
-  code ^= Generate("_stub_" #name, StubCode::Generate##name##Stub);            \
+  code ^= Generate("_stub_" #name, &object_pool_wrapper,                       \
+                   StubCode::Generate##name##Stub);                            \
   entries_[k##name##Index] = new StubEntry(code);
 
+#define STUB_CODE_SET_OBJECT_POOL(name)                                        \
+  code = entries_[k##name##Index]->code();                                     \
+  code.set_object_pool(object_pool.raw());
+
 void StubCode::Init() {
+  ObjectPoolWrapper object_pool_wrapper;
+
   // Generate all the stubs.
   Code& code = Code::Handle();
   VM_STUB_CODE_LIST(STUB_CODE_GENERATE);
+
+  const ObjectPool& object_pool =
+      ObjectPool::Handle(object_pool_wrapper.MakeObjectPool());
+  VM_STUB_CODE_LIST(STUB_CODE_SET_OBJECT_POOL)
 }
 
 #undef STUB_CODE_GENERATE
+#undef STUB_CODE_SET_OBJECT_POOL
 
 #define STUB_CODE_CLEANUP(name)                                                \
   delete entries_[k##name##Index];                                             \
@@ -77,12 +89,13 @@
 #undef STUB_CODE_CLEANUP
 
 RawCode* StubCode::Generate(const char* name,
+                            ObjectPoolWrapper* object_pool_wrapper,
                             void (*GenerateStub)(Assembler* assembler)) {
-  ObjectPoolWrapper object_pool_wrapper;
-  Assembler assembler(&object_pool_wrapper);
+  Assembler assembler(object_pool_wrapper);
   GenerateStub(&assembler);
-  const Code& code = Code::Handle(
-      Code::FinalizeCode(name, nullptr, &assembler, false /* optimized */));
+  const Code& code = Code::Handle(Code::FinalizeCode(
+      name, nullptr, &assembler, Code::PoolAttachment::kNotAttachPool,
+      /*optimized=*/false));
 #ifndef PRODUCT
   if (FLAG_support_disassembler && FLAG_disassemble_stubs) {
     LogBlock lb;
@@ -91,7 +104,9 @@
     code.Disassemble(&formatter);
     THR_Print("}\n");
     const ObjectPool& object_pool = ObjectPool::Handle(code.object_pool());
-    object_pool.DebugPrint();
+    if (!object_pool.IsNull()) {
+      object_pool.DebugPrint();
+    }
   }
 #endif  // !PRODUCT
   return code.raw();
@@ -169,8 +184,9 @@
     StubCode::GenerateAllocationStubForClass(&assembler, cls);
 
     if (thread->IsMutatorThread()) {
-      stub ^=
-          Code::FinalizeCode(name, nullptr, &assembler, false /* optimized */);
+      stub ^= Code::FinalizeCode(name, nullptr, &assembler,
+                                 Code::PoolAttachment::kAttachPool,
+                                 /*optimized1*/ false);
       // Check if background compilation thread has not already added the stub.
       if (cls.allocation_stub() == Code::null()) {
         stub.set_owner(cls);
@@ -195,6 +211,7 @@
         // heap to grow.
         NoHeapGrowthControlScope no_growth_control;
         stub ^= Code::FinalizeCode(name, nullptr, &assembler,
+                                   Code::PoolAttachment::kAttachPool,
                                    false /* optimized */);
         stub.set_owner(cls);
         cls.set_allocation_stub(stub);
@@ -212,7 +229,9 @@
       stub.Disassemble(&formatter);
       THR_Print("}\n");
       const ObjectPool& object_pool = ObjectPool::Handle(stub.object_pool());
-      object_pool.DebugPrint();
+      if (!object_pool.IsNull()) {
+        object_pool.DebugPrint();
+      }
     }
 #endif  // !PRODUCT
   }
@@ -231,8 +250,9 @@
   StubCode::GenerateBuildMethodExtractorStub(&assembler);
 
   const char* name = "BuildMethodExtractor";
-  const Code& stub = Code::Handle(
-      Code::FinalizeCode(name, nullptr, &assembler, false /* optimized */));
+  const Code& stub = Code::Handle(Code::FinalizeCode(
+      name, nullptr, &assembler, Code::PoolAttachment::kAttachPool,
+      /*optimized=*/false));
 #ifndef PRODUCT
   if (FLAG_support_disassembler && FLAG_disassemble_stubs) {
     LogBlock lb;
@@ -241,7 +261,9 @@
     stub.Disassemble(&formatter);
     THR_Print("}\n");
     const ObjectPool& object_pool = ObjectPool::Handle(stub.object_pool());
-    object_pool.DebugPrint();
+    if (!object_pool.IsNull()) {
+      object_pool.DebugPrint();
+    }
   }
 #endif  // !PRODUCT
   return stub.raw();
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index cd336be..ca61e06 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -28,6 +28,7 @@
   V(DeoptForRewind)                                                            \
   V(WriteBarrier)                                                              \
   V(WriteBarrierWrappers)                                                      \
+  V(ArrayWriteBarrier)                                                         \
   V(PrintStopMessage)                                                          \
   V(AllocateArray)                                                             \
   V(AllocateContext)                                                           \
@@ -214,6 +215,7 @@
   // Generate the stub and finalize the generated code into the stub
   // code executable area.
   static RawCode* Generate(const char* name,
+                           ObjectPoolWrapper* object_pool_wrapper,
                            void (*GenerateStub)(Assembler* assembler));
 
   static void GenerateSharedStub(Assembler* assembler,
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 7b08bf6..7209ac5 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -29,7 +29,6 @@
             use_slow_path,
             false,
             "Set to true for debugging & verifying the slow paths.");
-DECLARE_FLAG(bool, trace_optimized_ic_calls);
 
 // Input parameters:
 //   LR : return address.
@@ -56,7 +55,7 @@
     Label ok;
     // Check that we are always entering from Dart code.
     __ LoadFromOffset(kWord, R8, THR, Thread::vm_tag_offset());
-    __ CompareImmediate(R8, VMTag::kDartTagId);
+    __ CompareImmediate(R8, VMTag::kDartCompiledTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
     __ Bind(&ok);
@@ -95,7 +94,7 @@
   __ blx(R9);
 
   // Mark that the thread is executing Dart code.
-  __ LoadImmediate(R2, VMTag::kDartTagId);
+  __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
   __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
@@ -312,7 +311,7 @@
     Label ok;
     // Check that we are always entering from Dart code.
     __ LoadFromOffset(kWord, R8, THR, Thread::vm_tag_offset());
-    __ CompareImmediate(R8, VMTag::kDartTagId);
+    __ CompareImmediate(R8, VMTag::kDartCompiledTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
     __ Bind(&ok);
@@ -359,7 +358,7 @@
   __ blx(LR);
 
   // Mark that the thread is executing Dart code.
-  __ LoadImmediate(R2, VMTag::kDartTagId);
+  __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
   __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
@@ -405,7 +404,7 @@
     Label ok;
     // Check that we are always entering from Dart code.
     __ LoadFromOffset(kWord, R8, THR, Thread::vm_tag_offset());
-    __ CompareImmediate(R8, VMTag::kDartTagId);
+    __ CompareImmediate(R8, VMTag::kDartCompiledTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
     __ Bind(&ok);
@@ -449,7 +448,7 @@
   __ blx(R9);
 
   // Mark that the thread is executing Dart code.
-  __ LoadImmediate(R2, VMTag::kDartTagId);
+  __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
   __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
@@ -968,10 +967,6 @@
   __ LoadFromOffset(kWord, R9, THR, Thread::vm_tag_offset());
   __ Push(R9);
 
-  // Mark that the thread is executing Dart code.
-  __ LoadImmediate(R9, VMTag::kDartTagId);
-  __ StoreToOffset(kWord, R9, THR, Thread::vm_tag_offset());
-
   // Save top resource and top exit frame info. Use R4-6 as temporary registers.
   // StackFrameIterator reads the top exit frame info saved in this frame.
   __ LoadFromOffset(kWord, R9, THR, Thread::top_exit_frame_info_offset());
@@ -989,6 +984,11 @@
 #endif
   __ Push(R9);
 
+  // Mark that the thread is executing Dart code. Do this after initializing the
+  // exit link for the profiler.
+  __ LoadImmediate(R9, VMTag::kDartCompiledTagId);
+  __ StoreToOffset(kWord, R9, THR, Thread::vm_tag_offset());
+
   // Load arguments descriptor array into R4, which is passed to Dart code.
   __ ldr(R4, Address(R1, VMHandles::kOffsetOfRawPtrInHandle));
 
@@ -1203,28 +1203,33 @@
 // Input parameters:
 //   R1: Object (old)
 //   R0: Value (old or new)
+//   R9: Slot
 // If R0 is new, add R1 to the store buffer. Otherwise R0 is old, mark R0
 // and add it to the mark list.
 COMPILE_ASSERT(kWriteBarrierObjectReg == R1);
 COMPILE_ASSERT(kWriteBarrierValueReg == R0);
-void StubCode::GenerateWriteBarrierStub(Assembler* assembler) {
-#if defined(CONCURRENT_MARKING)
-  Label add_to_mark_stack;
+COMPILE_ASSERT(kWriteBarrierSlotReg == R9);
+static void GenerateWriteBarrierStubHelper(Assembler* assembler,
+                                           Address stub_code,
+                                           bool cards) {
+  Label add_to_mark_stack, remember_card;
   __ tst(R0, Operand(1 << kNewObjectBitPosition));
   __ b(&add_to_mark_stack, ZERO);
-#else
-  Label add_to_buffer;
-  // Check whether this object has already been remembered. Skip adding to the
-  // store buffer if the object is in the store buffer already.
-  // Spilled: R2, R3, R4
-  // R1: Address being stored
-  __ ldr(TMP, FieldAddress(R1, Object::tags_offset()));
-  __ tst(TMP, Operand(1 << RawObject::kOldAndNotRememberedBit));
-  __ b(&add_to_buffer, NE);
-  __ Ret();
 
-  __ Bind(&add_to_buffer);
+  if (cards) {
+    __ ldr(TMP, FieldAddress(R1, Object::tags_offset()));
+    __ tst(TMP, Operand(1 << RawObject::kCardRememberedBit));
+    __ b(&remember_card, NOT_ZERO);
+  } else {
+#if defined(DEBUG)
+    Label ok;
+    __ ldr(TMP, FieldAddress(R1, Object::tags_offset()));
+    __ tst(TMP, Operand(1 << RawObject::kCardRememberedBit));
+    __ b(&ok, ZERO);
+    __ Stop("Wrong barrier");
+    __ Bind(&ok);
 #endif
+  }
 
   // Save values being destroyed.
   __ PushList((1 << R2) | (1 << R3) | (1 << R4));
@@ -1275,7 +1280,7 @@
   // Setup frame, push callee-saved registers.
 
   __ Push(CODE_REG);
-  __ ldr(CODE_REG, Address(THR, Thread::write_barrier_code_offset()));
+  __ ldr(CODE_REG, stub_code);
   __ EnterCallRuntimeFrame(0 * kWordSize);
   __ mov(R0, Operand(THR));
   __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
@@ -1284,7 +1289,6 @@
   __ Pop(CODE_REG);
   __ Ret();
 
-#if defined(CONCURRENT_MARKING)
   __ Bind(&add_to_mark_stack);
   __ PushList((1 << R2) | (1 << R3) | (1 << R4));  // Spill.
 
@@ -1325,7 +1329,7 @@
 
   __ Bind(&marking_overflow);
   __ Push(CODE_REG);
-  __ ldr(CODE_REG, Address(THR, Thread::write_barrier_code_offset()));
+  __ ldr(CODE_REG, stub_code);
   __ EnterCallRuntimeFrame(0 * kWordSize);
   __ mov(R0, Operand(THR));
   __ CallRuntime(kMarkingStackBlockProcessRuntimeEntry, 1);
@@ -1336,7 +1340,53 @@
   __ Bind(&lost_race);
   __ PopList((1 << R2) | (1 << R3) | (1 << R4));  // Unspill.
   __ Ret();
-#endif
+
+  if (cards) {
+    Label remember_card_slow;
+
+    // Get card table.
+    __ Bind(&remember_card);
+    __ AndImmediate(TMP, R1, kPageMask);                       // HeapPage.
+    __ ldr(TMP, Address(TMP, HeapPage::card_table_offset()));  // Card table.
+    __ cmp(TMP, Operand(0));
+    __ b(&remember_card_slow, EQ);
+
+    // Dirty the card.
+    __ AndImmediate(TMP, R1, kPageMask);  // HeapPage.
+    __ sub(R9, R9, Operand(TMP));         // Offset in page.
+    __ ldr(TMP, Address(TMP, HeapPage::card_table_offset()));  // Card table.
+    __ add(TMP, TMP,
+           Operand(R9, LSR, HeapPage::kBytesPerCardLog2));  // Card address.
+    __ strb(R1,
+            Address(TMP, 0));  // Low byte of R0 is non-zero from object tag.
+    __ Ret();
+
+    // Card table not yet allocated.
+    __ Bind(&remember_card_slow);
+    __ Push(CODE_REG);
+    __ Push(R0);
+    __ Push(R1);
+    __ ldr(CODE_REG, stub_code);
+    __ mov(R0, Operand(R1));  // Arg0 = Object
+    __ mov(R1, Operand(R9));  // Arg1 = Slot
+    __ EnterCallRuntimeFrame(0);
+    __ CallRuntime(kRememberCardRuntimeEntry, 2);
+    __ LeaveCallRuntimeFrame();
+    __ Pop(R1);
+    __ Pop(R0);
+    __ Pop(CODE_REG);
+    __ Ret();
+  }
+}
+
+void StubCode::GenerateWriteBarrierStub(Assembler* assembler) {
+  GenerateWriteBarrierStubHelper(
+      assembler, Address(THR, Thread::write_barrier_code_offset()), false);
+}
+
+void StubCode::GenerateArrayWriteBarrierStub(Assembler* assembler) {
+  GenerateWriteBarrierStubHelper(
+      assembler, Address(THR, Thread::array_write_barrier_code_offset()), true);
 }
 
 // Called for inline allocation of objects.
@@ -2409,7 +2459,7 @@
   __ mov(FP, Operand(R2));   // Frame_pointer.
   __ mov(SP, Operand(IP));   // Set Stack pointer.
   // Set the tag.
-  __ LoadImmediate(R2, VMTag::kDartTagId);
+  __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
   __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset());
   // Clear top exit frame.
   __ LoadImmediate(R2, 0);
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 2bf5573..f1ff4f6 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -27,7 +27,6 @@
             use_slow_path,
             false,
             "Set to true for debugging & verifying the slow paths.");
-DECLARE_FLAG(bool, trace_optimized_ic_calls);
 DECLARE_FLAG(bool, enable_interpreter);
 
 // Input parameters:
@@ -57,7 +56,7 @@
     Label ok;
     // Check that we are always entering from Dart code.
     __ LoadFromOffset(R8, THR, Thread::vm_tag_offset());
-    __ CompareImmediate(R8, VMTag::kDartTagId);
+    __ CompareImmediate(R8, VMTag::kDartCompiledTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
     __ Bind(&ok);
@@ -119,7 +118,7 @@
 
   // Retval is next to 1st argument.
   // Mark that the thread is executing Dart code.
-  __ LoadImmediate(R2, VMTag::kDartTagId);
+  __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
   __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
@@ -330,7 +329,7 @@
     Label ok;
     // Check that we are always entering from Dart code.
     __ LoadFromOffset(R6, THR, Thread::vm_tag_offset());
-    __ CompareImmediate(R6, VMTag::kDartTagId);
+    __ CompareImmediate(R6, VMTag::kDartCompiledTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
     __ Bind(&ok);
@@ -393,7 +392,7 @@
   __ ldr(BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
 
   // Mark that the thread is executing Dart code.
-  __ LoadImmediate(R2, VMTag::kDartTagId);
+  __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
   __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
@@ -438,7 +437,7 @@
     Label ok;
     // Check that we are always entering from Dart code.
     __ LoadFromOffset(R6, THR, Thread::vm_tag_offset());
-    __ CompareImmediate(R6, VMTag::kDartTagId);
+    __ CompareImmediate(R6, VMTag::kDartCompiledTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
     __ Bind(&ok);
@@ -498,7 +497,7 @@
   __ ldr(BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
 
   // Mark that the thread is executing Dart code.
-  __ LoadImmediate(R2, VMTag::kDartTagId);
+  __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
   __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
@@ -1049,10 +1048,6 @@
   __ LoadFromOffset(R4, THR, Thread::vm_tag_offset());
   __ Push(R4);
 
-  // Mark that the thread is executing Dart code.
-  __ LoadImmediate(R6, VMTag::kDartTagId);
-  __ StoreToOffset(R6, THR, Thread::vm_tag_offset());
-
   // Save top resource and top exit frame info. Use R6 as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
   __ LoadFromOffset(R6, THR, Thread::top_resource_offset());
@@ -1064,6 +1059,11 @@
   ASSERT(kExitLinkSlotFromEntryFp == -22);
   __ Push(R6);
 
+  // Mark that the thread is executing Dart code. Do this after initializing the
+  // exit link for the profiler.
+  __ LoadImmediate(R6, VMTag::kDartCompiledTagId);
+  __ StoreToOffset(R6, THR, Thread::vm_tag_offset());
+
   // Load arguments descriptor array into R4, which is passed to Dart code.
   __ LoadFromOffset(R4, R1, VMHandles::kOffsetOfRawPtrInHandle);
 
@@ -1188,10 +1188,6 @@
   __ LoadFromOffset(R4, THR, Thread::vm_tag_offset());
   __ Push(R4);
 
-  // Mark that the thread is executing Dart code.
-  __ LoadImmediate(R6, VMTag::kDartTagId);
-  __ StoreToOffset(R6, THR, Thread::vm_tag_offset());
-
   // Save top resource and top exit frame info. Use R6 as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
   __ LoadFromOffset(R6, THR, Thread::top_resource_offset());
@@ -1203,6 +1199,11 @@
   ASSERT(kExitLinkSlotFromEntryFp == -22);
   __ Push(R6);
 
+  // Mark that the thread is executing Dart code. Do this after initializing the
+  // exit link for the profiler.
+  __ LoadImmediate(R6, VMTag::kDartCompiledTagId);
+  __ StoreToOffset(R6, THR, Thread::vm_tag_offset());
+
   // Load arguments descriptor array into R4, which is passed to Dart code.
   __ mov(R4, R1);
 
@@ -1411,28 +1412,34 @@
   }
 }
 
-// Helper stub to implement Assembler::StoreIntoObject.
+// Helper stub to implement Assembler::StoreIntoObject/Array.
 // Input parameters:
 //   R1: Object (old)
 //   R0: Value (old or new)
+//  R25: Slot
 // If R0 is new, add R1 to the store buffer. Otherwise R0 is old, mark R0
 // and add it to the mark list.
 COMPILE_ASSERT(kWriteBarrierObjectReg == R1);
 COMPILE_ASSERT(kWriteBarrierValueReg == R0);
-void StubCode::GenerateWriteBarrierStub(Assembler* assembler) {
-#if defined(CONCURRENT_MARKING)
-  Label add_to_mark_stack;
+COMPILE_ASSERT(kWriteBarrierSlotReg == R25);
+static void GenerateWriteBarrierStubHelper(Assembler* assembler,
+                                           Address stub_code,
+                                           bool cards) {
+  Label add_to_mark_stack, remember_card;
   __ tbz(&add_to_mark_stack, R0, kNewObjectBitPosition);
-#else
-  Label add_to_buffer;
-  // Check whether this object has already been remembered. Skip adding to the
-  // store buffer if the object is in the store buffer already.
-  __ LoadFieldFromOffset(TMP, R1, Object::tags_offset(), kWord);
-  __ tbnz(&add_to_buffer, TMP, RawObject::kOldAndNotRememberedBit);
-  __ ret();
 
-  __ Bind(&add_to_buffer);
+  if (cards) {
+    __ LoadFieldFromOffset(TMP, R1, Object::tags_offset(), kWord);
+    __ tbnz(&remember_card, TMP, RawObject::kCardRememberedBit);
+  } else {
+#if defined(DEBUG)
+    Label ok;
+    __ LoadFieldFromOffset(TMP, R1, Object::tags_offset(), kWord);
+    __ tbz(&ok, TMP, RawObject::kCardRememberedBit);
+    __ Stop("Wrong barrier");
+    __ Bind(&ok);
 #endif
+  }
 
   // Save values being destroyed.
   __ Push(R2);
@@ -1478,7 +1485,7 @@
   // Setup frame, push callee-saved registers.
 
   __ Push(CODE_REG);
-  __ ldr(CODE_REG, Address(THR, Thread::write_barrier_code_offset()));
+  __ ldr(CODE_REG, stub_code);
   __ EnterCallRuntimeFrame(0 * kWordSize);
   __ mov(R0, THR);
   __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
@@ -1487,7 +1494,6 @@
   __ Pop(CODE_REG);
   __ ret();
 
-#if defined(CONCURRENT_MARKING)
   __ Bind(&add_to_mark_stack);
   __ Push(R2);  // Spill.
   __ Push(R3);  // Spill.
@@ -1522,7 +1528,7 @@
 
   __ Bind(&marking_overflow);
   __ Push(CODE_REG);
-  __ ldr(CODE_REG, Address(THR, Thread::write_barrier_code_offset()));
+  __ ldr(CODE_REG, stub_code);
   __ EnterCallRuntimeFrame(0 * kWordSize);
   __ mov(R0, THR);
   __ CallRuntime(kMarkingStackBlockProcessRuntimeEntry, 1);
@@ -1535,7 +1541,50 @@
   __ Pop(R3);  // Unspill.
   __ Pop(R2);  // Unspill.
   __ ret();
-#endif
+
+  if (cards) {
+    Label remember_card_slow;
+
+    // Get card table.
+    __ Bind(&remember_card);
+    __ AndImmediate(TMP, R1, kPageMask);                       // HeapPage.
+    __ ldr(TMP, Address(TMP, HeapPage::card_table_offset()));  // Card table.
+    __ cbz(&remember_card_slow, TMP);
+
+    // Dirty the card.
+    __ AndImmediate(TMP, R1, kPageMask);  // HeapPage.
+    __ sub(R25, R25, Operand(TMP));       // Offset in page.
+    __ ldr(TMP, Address(TMP, HeapPage::card_table_offset()));  // Card table.
+    __ add(TMP, TMP,
+           Operand(R25, LSR, HeapPage::kBytesPerCardLog2));  // Card address.
+    __ str(R1, Address(TMP, 0),
+           kUnsignedByte);  // Low byte of R1 is non-zero from object tag.
+    __ ret();
+
+    // Card table not yet allocated.
+    __ Bind(&remember_card_slow);
+    __ Push(CODE_REG);
+    __ PushPair(R0, R1);
+    __ ldr(CODE_REG, stub_code);
+    __ mov(R0, R1);   // Arg0 = Object
+    __ mov(R1, R25);  // Arg1 = Slot
+    __ EnterCallRuntimeFrame(0);
+    __ CallRuntime(kRememberCardRuntimeEntry, 2);
+    __ LeaveCallRuntimeFrame();
+    __ PopPair(R0, R1);
+    __ Pop(CODE_REG);
+    __ ret();
+  }
+}
+
+void StubCode::GenerateWriteBarrierStub(Assembler* assembler) {
+  GenerateWriteBarrierStubHelper(
+      assembler, Address(THR, Thread::write_barrier_code_offset()), false);
+}
+
+void StubCode::GenerateArrayWriteBarrierStub(Assembler* assembler) {
+  GenerateWriteBarrierStubHelper(
+      assembler, Address(THR, Thread::array_write_barrier_code_offset()), true);
 }
 
 // Called for inline allocation of objects.
@@ -2129,7 +2178,7 @@
     Label ok;
     // Check that we are always entering from Dart code.
     __ LoadFromOffset(R8, THR, Thread::vm_tag_offset());
-    __ CompareImmediate(R8, VMTag::kDartTagId);
+    __ CompareImmediate(R8, VMTag::kDartCompiledTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
     __ Bind(&ok);
@@ -2185,7 +2234,7 @@
   __ ldr(BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
 
   // Mark that the thread is executing Dart code.
-  __ LoadImmediate(R2, VMTag::kDartTagId);
+  __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
   __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
@@ -2676,7 +2725,7 @@
   __ mov(THR, R3);
   __ ldr(BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
   // Set the tag.
-  __ LoadImmediate(R2, VMTag::kDartTagId);
+  __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
   __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
   // Clear top exit frame.
   __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
diff --git a/runtime/vm/stub_code_arm64_test.cc b/runtime/vm/stub_code_arm64_test.cc
index a194b7c..6d4af28 100644
--- a/runtime/vm/stub_code_arm64_test.cc
+++ b/runtime/vm/stub_code_arm64_test.cc
@@ -58,8 +58,9 @@
   ObjectPoolWrapper object_pool_wrapper;
   Assembler assembler(&object_pool_wrapper);
   GenerateCallToCallRuntimeStub(&assembler, length);
-  const Code& code = Code::Handle(Code::FinalizeCode(
-      *CreateFunction("Test_CallRuntimeStubCode"), nullptr, &assembler));
+  const Code& code = Code::Handle(
+      Code::FinalizeCode(*CreateFunction("Test_CallRuntimeStubCode"), nullptr,
+                         &assembler, Code::PoolAttachment::kAttachPool));
   const Function& function = RegisterFakeFunction(kName, code);
   Array& result = Array::Handle();
   result ^= DartEntry::InvokeFunction(function, Object::empty_array());
@@ -100,7 +101,8 @@
   GenerateCallToCallLeafRuntimeStub(&assembler, str_value, lhs_index_value,
                                     rhs_index_value, length_value);
   const Code& code = Code::Handle(Code::FinalizeCode(
-      *CreateFunction("Test_CallLeafRuntimeStubCode"), nullptr, &assembler));
+      *CreateFunction("Test_CallLeafRuntimeStubCode"), nullptr, &assembler,
+      Code::PoolAttachment::kAttachPool));
   const Function& function = RegisterFakeFunction(kName, code);
   Instance& result = Instance::Handle();
   result ^= DartEntry::InvokeFunction(function, Object::empty_array());
diff --git a/runtime/vm/stub_code_arm_test.cc b/runtime/vm/stub_code_arm_test.cc
index 2741204..c1699b7 100644
--- a/runtime/vm/stub_code_arm_test.cc
+++ b/runtime/vm/stub_code_arm_test.cc
@@ -57,8 +57,9 @@
   ObjectPoolWrapper object_pool_wrapper;
   Assembler assembler(&object_pool_wrapper);
   GenerateCallToCallRuntimeStub(&assembler, length);
-  const Code& code = Code::Handle(Code::FinalizeCode(
-      *CreateFunction("Test_CallRuntimeStubCode"), nullptr, &assembler));
+  const Code& code = Code::Handle(
+      Code::FinalizeCode(*CreateFunction("Test_CallRuntimeStubCode"), nullptr,
+                         &assembler, Code::PoolAttachment::kAttachPool));
   const Function& function = RegisterFakeFunction(kName, code);
   Array& result = Array::Handle();
   result ^= DartEntry::InvokeFunction(function, Object::empty_array());
@@ -98,7 +99,8 @@
   GenerateCallToCallLeafRuntimeStub(&assembler, str_value, lhs_index_value,
                                     rhs_index_value, length_value);
   const Code& code = Code::Handle(Code::FinalizeCode(
-      *CreateFunction("Test_CallLeafRuntimeStubCode"), nullptr, &assembler));
+      *CreateFunction("Test_CallLeafRuntimeStubCode"), nullptr, &assembler,
+      Code::PoolAttachment::kAttachPool));
   const Function& function = RegisterFakeFunction(kName, code);
   Instance& result = Instance::Handle();
   result ^= DartEntry::InvokeFunction(function, Object::empty_array());
diff --git a/runtime/vm/stub_code_dbc.cc b/runtime/vm/stub_code_dbc.cc
index c1fbc5e..fa35e41 100644
--- a/runtime/vm/stub_code_dbc.cc
+++ b/runtime/vm/stub_code_dbc.cc
@@ -27,7 +27,6 @@
             use_slow_path,
             false,
             "Set to true for debugging & verifying the slow paths.");
-DECLARE_FLAG(bool, trace_optimized_ic_calls);
 
 void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
   __ Compile();
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index d609e2a..bab20db 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -27,7 +27,6 @@
             use_slow_path,
             false,
             "Set to true for debugging & verifying the slow paths.");
-DECLARE_FLAG(bool, trace_optimized_ic_calls);
 
 #define INT32_SIZEOF(x) static_cast<int32_t>(sizeof(x))
 
@@ -56,7 +55,7 @@
   {
     Label ok;
     // Check that we are always entering from Dart code.
-    __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
+    __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
     __ j(EQUAL, &ok, Assembler::kNearJump);
     __ Stop("Not coming from Dart code.");
     __ Bind(&ok);
@@ -84,7 +83,7 @@
   __ movl(Address(ESP, retval_offset), EAX);  // Set retval in NativeArguments.
   __ call(ECX);
 
-  __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
+  __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
 
   // Reset exit frame information in Isolate structure.
   __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
@@ -161,7 +160,7 @@
   {
     Label ok;
     // Check that we are always entering from Dart code.
-    __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
+    __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
     __ j(EQUAL, &ok, Assembler::kNearJump);
     __ Stop("Not coming from Dart code.");
     __ Bind(&ok);
@@ -192,7 +191,7 @@
   __ movl(Address(ESP, kWordSize), ECX);  // Function to call.
   __ call(wrapper);
 
-  __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
+  __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
 
   // Reset exit frame information in Isolate structure.
   __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
@@ -238,7 +237,7 @@
   {
     Label ok;
     // Check that we are always entering from Dart code.
-    __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
+    __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
     __ j(EQUAL, &ok, Assembler::kNearJump);
     __ Stop("Not coming from Dart code.");
     __ Bind(&ok);
@@ -266,7 +265,7 @@
   __ movl(Address(ESP, 0), EAX);  // Pass the pointer to the NativeArguments.
   __ call(ECX);
 
-  __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
+  __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
 
   // Reset exit frame information in Isolate structure.
   __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
@@ -757,9 +756,6 @@
   __ movl(ECX, Assembler::VMTagAddress());
   __ pushl(ECX);
 
-  // Mark that the thread is executing Dart code.
-  __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
-
   // Save top resource and top exit frame info. Use EDX as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
   __ movl(EDX, Address(THR, Thread::top_resource_offset()));
@@ -772,6 +768,10 @@
   __ pushl(EDX);
   __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
 
+  // Mark that the thread is executing Dart code. Do this after initializing the
+  // exit link for the profiler.
+  __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
+
   // Load arguments descriptor array into EDX.
   __ movl(EDX, Address(EBP, kArgumentsDescOffset));
   __ movl(EDX, Address(EDX, VMHandles::kOffsetOfRawPtrInHandle));
@@ -978,13 +978,19 @@
   __ Breakpoint();
 }
 
-// Helper stub to implement Assembler::StoreIntoObject.
+// Helper stub to implement Assembler::StoreIntoObject/Array.
 // Input parameters:
 //   EDX: Object (old)
+//   EDI: Slot
 // If EDX is not remembered, mark as remembered and add to the store buffer.
 COMPILE_ASSERT(kWriteBarrierObjectReg == EDX);
 COMPILE_ASSERT(kWriteBarrierValueReg == kNoRegister);
-void StubCode::GenerateWriteBarrierStub(Assembler* assembler) {
+COMPILE_ASSERT(kWriteBarrierSlotReg == EDI);
+static void GenerateWriteBarrierStubHelper(Assembler* assembler,
+                                           Address stub_code,
+                                           bool cards) {
+  Label remember_card;
+
   // Save values being destroyed.
   __ pushl(EAX);
   __ pushl(ECX);
@@ -1005,6 +1011,21 @@
   // EDX: Address being stored
   // EAX: Current tag value
   __ Bind(&add_to_buffer);
+
+  if (cards) {
+    // Check if this object is using remembered cards.
+    __ testl(EAX, Immediate(1 << RawObject::kCardRememberedBit));
+    __ j(NOT_EQUAL, &remember_card, Assembler::kFarJump);  // Unlikely.
+  } else {
+#if defined(DEBUG)
+    Label ok;
+    __ testl(EAX, Immediate(1 << RawObject::kCardRememberedBit));
+    __ j(ZERO, &ok, Assembler::kFarJump);  // Unlikely.
+    __ Stop("Wrong barrier");
+    __ Bind(&ok);
+#endif
+  }
+
   // lock+andl is an atomic read-modify-write.
   __ lock();
   __ andl(FieldAddress(EDX, Object::tags_offset()),
@@ -1043,6 +1064,48 @@
   // Restore callee-saved registers, tear down frame.
   __ LeaveCallRuntimeFrame();
   __ ret();
+
+  if (cards) {
+    Label remember_card_slow;
+
+    // Get card table.
+    __ Bind(&remember_card);
+    __ movl(EAX, EDX);                   // Object.
+    __ andl(EAX, Immediate(kPageMask));  // HeapPage.
+    __ cmpl(Address(EAX, HeapPage::card_table_offset()), Immediate(0));
+    __ j(EQUAL, &remember_card_slow, Assembler::kNearJump);
+
+    // Dirty the card.
+    __ subl(EDI, EAX);  // Offset in page.
+    __ movl(EAX, Address(EAX, HeapPage::card_table_offset()));  // Card table.
+    __ shrl(EDI,
+            Immediate(HeapPage::kBytesPerCardLog2));  // Index in card table.
+    __ movb(Address(EAX, EDI, TIMES_1, 0), Immediate(1));
+    __ popl(ECX);
+    __ popl(EAX);
+    __ ret();
+
+    // Card table not yet allocated.
+    __ Bind(&remember_card_slow);
+    __ EnterCallRuntimeFrame(2 * kWordSize);
+    __ movl(Address(ESP, 0 * kWordSize), EDX);  // Object
+    __ movl(Address(ESP, 1 * kWordSize), EDI);  // Slot
+    __ CallRuntime(kRememberCardRuntimeEntry, 2);
+    __ LeaveCallRuntimeFrame();
+    __ popl(ECX);
+    __ popl(EAX);
+    __ ret();
+  }
+}
+
+void StubCode::GenerateWriteBarrierStub(Assembler* assembler) {
+  GenerateWriteBarrierStubHelper(
+      assembler, Address(THR, Thread::write_barrier_code_offset()), false);
+}
+
+void StubCode::GenerateArrayWriteBarrierStub(Assembler* assembler) {
+  GenerateWriteBarrierStubHelper(
+      assembler, Address(THR, Thread::array_write_barrier_code_offset()), true);
 }
 
 // Called for inline allocation of objects.
@@ -1949,7 +2012,7 @@
   __ movl(EBX, Address(ESP, 1 * kWordSize));  // Load target PC into EBX.
   __ movl(ESP, Address(ESP, 2 * kWordSize));  // Load target stack_pointer.
   // Set tag.
-  __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
+  __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
   // Clear top exit frame.
   __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
   __ jmp(EBX);  // Jump to the exception handler code.
diff --git a/runtime/vm/stub_code_ia32_test.cc b/runtime/vm/stub_code_ia32_test.cc
index a4b5d5e..94bac2e 100644
--- a/runtime/vm/stub_code_ia32_test.cc
+++ b/runtime/vm/stub_code_ia32_test.cc
@@ -57,8 +57,9 @@
   const char* kName = "Test_CallRuntimeStubCode";
   Assembler assembler(nullptr);
   GenerateCallToCallRuntimeStub(&assembler, length);
-  const Code& code = Code::Handle(Code::FinalizeCode(
-      *CreateFunction("Test_CallRuntimeStubCode"), nullptr, &assembler));
+  const Code& code = Code::Handle(
+      Code::FinalizeCode(*CreateFunction("Test_CallRuntimeStubCode"), nullptr,
+                         &assembler, Code::PoolAttachment::kAttachPool));
   const Function& function = RegisterFakeFunction(kName, code);
   Array& result = Array::Handle();
   result ^= DartEntry::InvokeFunction(function, Object::empty_array());
@@ -102,7 +103,8 @@
   GenerateCallToCallLeafRuntimeStub(&assembler, str_value, lhs_index_value,
                                     rhs_index_value, length_value);
   const Code& code = Code::Handle(Code::FinalizeCode(
-      *CreateFunction("Test_CallLeafRuntimeStubCode"), nullptr, &assembler));
+      *CreateFunction("Test_CallLeafRuntimeStubCode"), nullptr, &assembler,
+      Code::PoolAttachment::kAttachPool));
   const Function& function = RegisterFakeFunction(kName, code);
   Instance& result = Instance::Handle();
   result ^= DartEntry::InvokeFunction(function, Object::empty_array());
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 0839632..1ce8502 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -32,7 +32,6 @@
             use_slow_path,
             false,
             "Set to true for debugging & verifying the slow paths.");
-DECLARE_FLAG(bool, trace_optimized_ic_calls);
 DECLARE_FLAG(bool, enable_interpreter);
 
 // Input parameters:
@@ -60,7 +59,7 @@
   {
     Label ok;
     // Check that we are always entering from Dart code.
-    __ movq(RAX, Immediate(VMTag::kDartTagId));
+    __ movq(RAX, Immediate(VMTag::kDartCompiledTagId));
     __ cmpq(RAX, Assembler::VMTagAddress());
     __ j(EQUAL, &ok, Assembler::kNearJump);
     __ Stop("Not coming from Dart code.");
@@ -94,7 +93,7 @@
   __ CallCFunction(RBX);
 
   // Mark that the thread is executing Dart code.
-  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
+  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
 
   // Reset exit frame information in Isolate structure.
   __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
@@ -315,7 +314,7 @@
   {
     Label ok;
     // Check that we are always entering from Dart code.
-    __ movq(R8, Immediate(VMTag::kDartTagId));
+    __ movq(R8, Immediate(VMTag::kDartCompiledTagId));
     __ cmpq(R8, Assembler::VMTagAddress());
     __ j(EQUAL, &ok, Assembler::kNearJump);
     __ Stop("Not coming from Dart code.");
@@ -350,7 +349,7 @@
   __ CallCFunction(RAX);
 
   // Mark that the thread is executing Dart code.
-  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
+  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
 
   // Reset exit frame information in Isolate structure.
   __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
@@ -398,7 +397,7 @@
   {
     Label ok;
     // Check that we are always entering from Dart code.
-    __ movq(R8, Immediate(VMTag::kDartTagId));
+    __ movq(R8, Immediate(VMTag::kDartCompiledTagId));
     __ cmpq(R8, Assembler::VMTagAddress());
     __ j(EQUAL, &ok, Assembler::kNearJump);
     __ Stop("Not coming from Dart code.");
@@ -429,7 +428,7 @@
   __ CallCFunction(RBX);
 
   // Mark that the thread is executing Dart code.
-  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
+  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
 
   // Reset exit frame information in Isolate structure.
   __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
@@ -965,9 +964,6 @@
   __ movq(RAX, Assembler::VMTagAddress());
   __ pushq(RAX);
 
-  // Mark that the thread is executing Dart code.
-  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
-
   // Save top resource and top exit frame info. Use RAX as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
   __ movq(RAX, Address(THR, Thread::top_resource_offset()));
@@ -991,6 +987,10 @@
 
   __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
 
+  // Mark that the thread is executing Dart code. Do this after initializing the
+  // exit link for the profiler.
+  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
+
   // Load arguments descriptor array into R10, which is passed to Dart code.
   __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle));
 
@@ -1106,9 +1106,6 @@
   __ movq(RAX, Assembler::VMTagAddress());
   __ pushq(RAX);
 
-  // Mark that the thread is executing Dart code.
-  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
-
   // Save top resource and top exit frame info. Use RAX as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
   __ movq(RAX, Address(THR, Thread::top_resource_offset()));
@@ -1131,6 +1128,10 @@
   }
 #endif
 
+  // Mark that the thread is executing Dart code. Do this after initializing the
+  // exit link for the profiler.
+  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
+
   // Load arguments descriptor array into R10, which is passed to Dart code.
   __ movq(R10, kArgDescReg);
 
@@ -1344,31 +1345,37 @@
   }
 }
 
-// Helper stub to implement Assembler::StoreIntoObject.
+// Helper stub to implement Assembler::StoreIntoObject/Array.
 // Input parameters:
 //   RDX: Object (old)
 //   RAX: Value (old or new)
+//   R13: Slot
 // If RAX is new, add RDX to the store buffer. Otherwise RAX is old, mark RAX
 // and add it to the mark list.
 COMPILE_ASSERT(kWriteBarrierObjectReg == RDX);
 COMPILE_ASSERT(kWriteBarrierValueReg == RAX);
-void StubCode::GenerateWriteBarrierStub(Assembler* assembler) {
-#if defined(CONCURRENT_MARKING)
-  Label add_to_mark_stack;
+COMPILE_ASSERT(kWriteBarrierSlotReg == R13);
+static void GenerateWriteBarrierStubHelper(Assembler* assembler,
+                                           Address stub_code,
+                                           bool cards) {
+  Label add_to_mark_stack, remember_card;
   __ testq(RAX, Immediate(1 << kNewObjectBitPosition));
   __ j(ZERO, &add_to_mark_stack);
-#else
-  Label add_to_buffer;
-  // Check whether this object has already been remembered. Skip adding to the
-  // store buffer if the object is in the store buffer already.
-  // RDX: Address being stored
-  __ movl(TMP, FieldAddress(RDX, Object::tags_offset()));
-  __ testl(TMP, Immediate(1 << RawObject::kOldAndNotRememberedBit));
-  __ j(NOT_EQUAL, &add_to_buffer, Assembler::kNearJump);
-  __ ret();
 
-  __ Bind(&add_to_buffer);
+  if (cards) {
+    __ movl(TMP, FieldAddress(RDX, Object::tags_offset()));
+    __ testl(TMP, Immediate(1 << RawObject::kCardRememberedBit));
+    __ j(NOT_ZERO, &remember_card, Assembler::kFarJump);
+  } else {
+#if defined(DEBUG)
+    Label ok;
+    __ movl(TMP, FieldAddress(RDX, Object::tags_offset()));
+    __ testl(TMP, Immediate(1 << RawObject::kCardRememberedBit));
+    __ j(ZERO, &ok, Assembler::kFarJump);
+    __ Stop("Wrong barrier");
+    __ Bind(&ok);
 #endif
+  }
 
   // Update the tags that this object has been remembered.
   // Note that we use 32 bit operations here to match the size of the
@@ -1408,7 +1415,7 @@
   __ Bind(&overflow);
   // Setup frame, push callee-saved registers.
   __ pushq(CODE_REG);
-  __ movq(CODE_REG, Address(THR, Thread::write_barrier_code_offset()));
+  __ movq(CODE_REG, stub_code);
   __ EnterCallRuntimeFrame(0);
   __ movq(CallingConventions::kArg1Reg, THR);
   __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
@@ -1416,7 +1423,6 @@
   __ popq(CODE_REG);
   __ ret();
 
-#if defined(CONCURRENT_MARKING)
   __ Bind(&add_to_mark_stack);
   __ pushq(RAX);  // Spill.
   __ pushq(RCX);  // Spill.
@@ -1449,7 +1455,7 @@
 
   __ Bind(&marking_overflow);
   __ pushq(CODE_REG);
-  __ movq(CODE_REG, Address(THR, Thread::write_barrier_code_offset()));
+  __ movq(CODE_REG, stub_code);
   __ EnterCallRuntimeFrame(0);
   __ movq(CallingConventions::kArg1Reg, THR);
   __ CallRuntime(kMarkingStackBlockProcessRuntimeEntry, 1);
@@ -1461,7 +1467,47 @@
   __ popq(RCX);  // Unspill.
   __ popq(RAX);  // Unspill.
   __ ret();
-#endif
+
+  if (cards) {
+    Label remember_card_slow;
+
+    // Get card table.
+    __ Bind(&remember_card);
+    __ movq(TMP, RDX);                   // Object.
+    __ andq(TMP, Immediate(kPageMask));  // HeapPage.
+    __ cmpq(Address(TMP, HeapPage::card_table_offset()), Immediate(0));
+    __ j(EQUAL, &remember_card_slow, Assembler::kNearJump);
+
+    // Dirty the card.
+    __ subq(R13, TMP);  // Offset in page.
+    __ movq(TMP, Address(TMP, HeapPage::card_table_offset()));  // Card table.
+    __ shrq(R13,
+            Immediate(HeapPage::kBytesPerCardLog2));  // Index in card table.
+    __ movb(Address(TMP, R13, TIMES_1, 0), Immediate(1));
+    __ ret();
+
+    // Card table not yet allocated.
+    __ Bind(&remember_card_slow);
+    __ pushq(CODE_REG);
+    __ movq(CODE_REG, stub_code);
+    __ EnterCallRuntimeFrame(0);
+    __ movq(CallingConventions::kArg1Reg, RDX);
+    __ movq(CallingConventions::kArg2Reg, R13);
+    __ CallRuntime(kRememberCardRuntimeEntry, 2);
+    __ LeaveCallRuntimeFrame();
+    __ popq(CODE_REG);
+    __ ret();
+  }
+}
+
+void StubCode::GenerateWriteBarrierStub(Assembler* assembler) {
+  GenerateWriteBarrierStubHelper(
+      assembler, Address(THR, Thread::write_barrier_code_offset()), false);
+}
+
+void StubCode::GenerateArrayWriteBarrierStub(Assembler* assembler) {
+  GenerateWriteBarrierStubHelper(
+      assembler, Address(THR, Thread::array_write_barrier_code_offset()), true);
 }
 
 // Called for inline allocation of objects.
@@ -2143,7 +2189,7 @@
   {
     Label ok;
     // Check that we are always entering from Dart code.
-    __ movq(R8, Immediate(VMTag::kDartTagId));
+    __ movq(R8, Immediate(VMTag::kDartCompiledTagId));
     __ cmpq(R8, Assembler::VMTagAddress());
     __ j(EQUAL, &ok, Assembler::kNearJump);
     __ Stop("Not coming from Dart code.");
@@ -2194,7 +2240,7 @@
   __ call(RAX);
 
   // Mark that the thread is executing Dart code.
-  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
+  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
 
   // Reset exit frame information in Isolate structure.
   __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
@@ -2685,7 +2731,7 @@
   __ movq(RBP, CallingConventions::kArg3Reg);
   __ movq(RSP, CallingConventions::kArg2Reg);
   // Set the tag.
-  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
+  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
   // Clear top exit frame.
   __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
   // Restore the pool pointer.
diff --git a/runtime/vm/stub_code_x64_test.cc b/runtime/vm/stub_code_x64_test.cc
index c9d9474..7739541 100644
--- a/runtime/vm/stub_code_x64_test.cc
+++ b/runtime/vm/stub_code_x64_test.cc
@@ -58,8 +58,9 @@
   ObjectPoolWrapper object_pool_wrapper;
   Assembler assembler(&object_pool_wrapper);
   GenerateCallToCallRuntimeStub(&assembler, length);
-  const Code& code = Code::Handle(Code::FinalizeCode(
-      *CreateFunction("Test_CallRuntimeStubCode"), nullptr, &assembler));
+  const Code& code = Code::Handle(
+      Code::FinalizeCode(*CreateFunction("Test_CallRuntimeStubCode"), nullptr,
+                         &assembler, Code::PoolAttachment::kAttachPool));
   const Function& function = RegisterFakeFunction(kName, code);
   Array& result = Array::Handle();
   result ^= DartEntry::InvokeFunction(function, Object::empty_array());
@@ -100,7 +101,8 @@
   GenerateCallToCallLeafRuntimeStub(&assembler, str_value, lhs_index_value,
                                     rhs_index_value, length_value);
   const Code& code = Code::Handle(Code::FinalizeCode(
-      *CreateFunction("Test_CallLeafRuntimeStubCode"), nullptr, &assembler));
+      *CreateFunction("Test_CallLeafRuntimeStubCode"), nullptr, &assembler,
+      Code::PoolAttachment::kAttachPool));
   const Function& function = RegisterFakeFunction(kName, code);
   Instance& result = Instance::Handle();
   result ^= DartEntry::InvokeFunction(function, Object::empty_array());
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index f3572c2..c818530 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -164,7 +164,6 @@
   V(Null, "Null")                                                              \
   V(null, "null")                                                              \
   V(Dynamic, "dynamic")                                                        \
-  V(UnresolvedClass, "UnresolvedClass")                                        \
   V(Type, "Type")                                                              \
   V(_Type, "_Type")                                                            \
   V(_TypeRef, "_TypeRef")                                                      \
@@ -190,6 +189,7 @@
   V(Namespace, "Namespace")                                                    \
   V(KernelProgramInfo, "KernelProgramInfo")                                    \
   V(Code, "Code")                                                              \
+  V(Bytecode, "Bytecode")                                                      \
   V(Instructions, "Instructions")                                              \
   V(ObjectPool, "ObjectPool")                                                  \
   V(PcDescriptors, "PcDescriptors")                                            \
@@ -239,7 +239,6 @@
   V(ColonStream, ":stream")                                                    \
   V(Object, "Object")                                                          \
   V(Int, "int")                                                                \
-  V(Int64, "_int64")                                                           \
   V(Double, "double")                                                          \
   V(Float32x4, "Float32x4")                                                    \
   V(Float64x2, "Float64x2")                                                    \
diff --git a/runtime/vm/tags.cc b/runtime/vm/tags.cc
index f1cd1e0..fad8fe7 100644
--- a/runtime/vm/tags.cc
+++ b/runtime/vm/tags.cc
@@ -36,7 +36,7 @@
 }
 
 bool VMTag::IsDartTag(uword id) {
-  return id == kDartTagId;
+  return (id == kDartCompiledTagId) || (id == kDartInterpretedTagId);
 }
 
 bool VMTag::IsExitFrameTag(uword id) {
@@ -44,34 +44,26 @@
          (id != kVMTagId) && (id != kEmbedderTagId);
 }
 
-static RuntimeEntry* runtime_entry_list = NULL;
-
 bool VMTag::IsRuntimeEntryTag(uword id) {
-  const RuntimeEntry* current = runtime_entry_list;
-  while (current != NULL) {
-    if (reinterpret_cast<uword>(current->function()) == id) {
-      return true;
-    }
-    current = current->next();
-  }
-  return false;
+  return RuntimeEntryTagName(id) != nullptr;
 }
 
 const char* VMTag::RuntimeEntryTagName(uword id) {
-  const RuntimeEntry* current = runtime_entry_list;
-  while (current != NULL) {
-    if (reinterpret_cast<uword>(current->function()) == id) {
-      return current->name();
-    }
-    current = current->next();
-  }
-  return NULL;
-}
+  void* address = reinterpret_cast<void*>(id);
 
-void VMTag::RegisterRuntimeEntry(RuntimeEntry* runtime_entry) {
-  ASSERT(runtime_entry != NULL);
-  runtime_entry->set_next(runtime_entry_list);
-  runtime_entry_list = runtime_entry;
+#define CHECK_RUNTIME_ADDRESS(n)                                               \
+  if (address == k##n##RuntimeEntry.function())                                \
+    return k##n##RuntimeEntry.name();
+  RUNTIME_ENTRY_LIST(CHECK_RUNTIME_ADDRESS)
+#undef CHECK_RUNTIME_ADDRESS
+
+#define CHECK_LEAF_RUNTIME_ADDRESS(type, n, ...)                               \
+  if (address == k##n##RuntimeEntry.function())                                \
+    return k##n##RuntimeEntry.name();
+  LEAF_RUNTIME_ENTRY_LIST(CHECK_LEAF_RUNTIME_ADDRESS)
+#undef CHECK_LEAF_RUNTIME_ADDRESS
+
+  return nullptr;
 }
 
 VMTag::TagEntry VMTag::entries_[] = {
diff --git a/runtime/vm/tags.h b/runtime/vm/tags.h
index 42320c3..e2b08a1 100644
--- a/runtime/vm/tags.h
+++ b/runtime/vm/tags.h
@@ -17,15 +17,13 @@
   V(Idle)     /* isolate is idle and is_runnable() */                          \
   V(LoadWait) /* isolate is idle and !is_runnable() */                         \
   V(VM)       /* Catch all */                                                  \
+  V(LoadBytecode)                                                              \
   V(CompileOptimized)                                                          \
   V(CompileUnoptimized)                                                        \
   V(CompileClass)                                                              \
-  V(CompileTopLevel)                                                           \
-  V(CompileScanner)                                                            \
-  V(CompileParseFunction)                                                      \
   V(CompileParseRegExp)                                                        \
-  V(CompileFlowGraphBuilder)                                                   \
-  V(Dart)                                                                      \
+  V(DartCompiled)                                                              \
+  V(DartInterpreted)                                                           \
   V(GCNewSpace)                                                                \
   V(GCOldSpace)                                                                \
   V(Embedder)                                                                  \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index bc6c6ad..740e8ef 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -72,6 +72,9 @@
       vm_tag_(0),
       async_stack_trace_(StackTrace::null()),
       unboxed_int64_runtime_arg_(0),
+      active_exception_(Object::null()),
+      active_stacktrace_(Object::null()),
+      resume_pc_(0),
       task_kind_(kUnknownTask),
       dart_stream_(NULL),
       os_thread_(NULL),
@@ -86,7 +89,6 @@
       no_callback_scope_depth_(0),
 #if defined(DEBUG)
       top_handle_scope_(NULL),
-      no_handle_scope_depth_(0),
       no_safepoint_scope_depth_(0),
 #endif
       reusable_handles_(),
@@ -99,9 +101,6 @@
       hierarchy_info_(NULL),
       type_usage_info_(NULL),
       pending_functions_(GrowableObjectArray::null()),
-      active_exception_(Object::null()),
-      active_stacktrace_(Object::null()),
-      resume_pc_(0),
       sticky_error_(Error::null()),
       REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
           REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) safepoint_state_(0),
@@ -638,11 +637,11 @@
 }
 
 bool Thread::IsExecutingDartCode() const {
-  return (top_exit_frame_info() == 0) && (vm_tag() == VMTag::kDartTagId);
+  return (top_exit_frame_info() == 0) && VMTag::IsDartTag(vm_tag());
 }
 
 bool Thread::HasExitedDartCode() const {
-  return (top_exit_frame_info() != 0) && (vm_tag() != VMTag::kDartTagId);
+  return (top_exit_frame_info() != 0) && !VMTag::IsDartTag(vm_tag());
 }
 
 template <class C>
@@ -885,6 +884,33 @@
   return total;
 }
 
+void Thread::EnterApiScope() {
+  ASSERT(MayAllocateHandles());
+  ApiLocalScope* new_scope = api_reusable_scope();
+  if (new_scope == NULL) {
+    new_scope = new ApiLocalScope(api_top_scope(), top_exit_frame_info());
+    ASSERT(new_scope != NULL);
+  } else {
+    new_scope->Reinit(this, api_top_scope(), top_exit_frame_info());
+    set_api_reusable_scope(NULL);
+  }
+  set_api_top_scope(new_scope);  // New scope is now the top scope.
+}
+
+void Thread::ExitApiScope() {
+  ASSERT(MayAllocateHandles());
+  ApiLocalScope* scope = api_top_scope();
+  ApiLocalScope* reusable_scope = api_reusable_scope();
+  set_api_top_scope(scope->previous());  // Reset top scope to previous.
+  if (reusable_scope == NULL) {
+    scope->Reset(this);  // Reset the old scope which we just exited.
+    set_api_reusable_scope(scope);
+  } else {
+    ASSERT(reusable_scope != scope);
+    delete scope;
+  }
+}
+
 void Thread::UnwindScopes(uword stack_marker) {
   // Unwind all scopes using the same stack_marker, i.e. all scopes allocated
   // under the same top_exit_frame_info.
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 49e3c07..2041022 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -25,6 +25,7 @@
 class CompilerState;
 class Class;
 class Code;
+class Bytecode;
 class Error;
 class ExceptionHandlers;
 class Field;
@@ -65,6 +66,7 @@
   V(Array)                                                                     \
   V(Class)                                                                     \
   V(Code)                                                                      \
+  V(Bytecode)                                                                  \
   V(Error)                                                                     \
   V(ExceptionHandlers)                                                         \
   V(Field)                                                                     \
@@ -85,6 +87,8 @@
 #define CACHED_VM_STUBS_LIST(V)                                                \
   V(RawCode*, write_barrier_code_, StubCode::WriteBarrier_entry()->code(),     \
     NULL)                                                                      \
+  V(RawCode*, array_write_barrier_code_,                                       \
+    StubCode::ArrayWriteBarrier_entry()->code(), NULL)                         \
   V(RawCode*, fix_callers_target_code_,                                        \
     StubCode::FixCallersTarget_entry()->code(), NULL)                          \
   V(RawCode*, fix_allocation_stub_code_,                                       \
@@ -142,6 +146,8 @@
 #define CACHED_VM_STUBS_ADDRESSES_LIST(V)                                      \
   V(uword, write_barrier_entry_point_,                                         \
     StubCode::WriteBarrier_entry()->EntryPoint(), 0)                           \
+  V(uword, array_write_barrier_entry_point_,                                   \
+    StubCode::ArrayWriteBarrier_entry()->EntryPoint(), 0)                      \
   V(uword, call_to_runtime_entry_point_,                                       \
     StubCode::CallToRuntime_entry()->EntryPoint(), 0)                          \
   V(uword, null_error_shared_without_fpu_regs_entry_point_,                    \
@@ -356,6 +362,9 @@
   ApiLocalScope* api_top_scope() const { return api_top_scope_; }
   void set_api_top_scope(ApiLocalScope* value) { api_top_scope_ = value; }
 
+  void EnterApiScope();
+  void ExitApiScope();
+
   // The isolate that this thread is operating on, or NULL if none.
   Isolate* isolate() const { return isolate_; }
   static intptr_t isolate_offset() { return OFFSET_OF(Thread, isolate_); }
@@ -474,28 +483,6 @@
   bool bump_allocate() const { return bump_allocate_; }
   void set_bump_allocate(bool b) { bump_allocate_ = b; }
 
-  int32_t no_handle_scope_depth() const {
-#if defined(DEBUG)
-    return no_handle_scope_depth_;
-#else
-    return 0;
-#endif
-  }
-
-  void IncrementNoHandleScopeDepth() {
-#if defined(DEBUG)
-    ASSERT(no_handle_scope_depth_ < INT_MAX);
-    no_handle_scope_depth_ += 1;
-#endif
-  }
-
-  void DecrementNoHandleScopeDepth() {
-#if defined(DEBUG)
-    ASSERT(no_handle_scope_depth_ > 0);
-    no_handle_scope_depth_ -= 1;
-#endif
-  }
-
   HandleScope* top_handle_scope() const {
 #if defined(DEBUG)
     return top_handle_scope_;
@@ -731,6 +718,11 @@
     execution_state_ = static_cast<uint32_t>(state);
   }
 
+  bool MayAllocateHandles() {
+    return (execution_state() == kThreadInVM) ||
+           (execution_state() == kThreadInGenerated);
+  }
+
   bool TryEnterSafepoint() {
     uint32_t new_state = SetAtSafepoint(true, 0);
     if (AtomicOperations::CompareAndSwapUint32(&safepoint_state_, 0,
@@ -850,7 +842,18 @@
     defined(TARGET_ARCH_X64)
   uword write_barrier_wrappers_entry_points_[kNumberOfDartAvailableCpuRegs];
 #endif
-  // End accessed from generated code.
+
+  // JumpToExceptionHandler state:
+  RawObject* active_exception_;
+  RawObject* active_stacktrace_;
+  uword resume_pc_;
+
+  // ---- End accessed from generated code. ----
+
+  // The layout of Thread object up to this point should not depend
+  // on DART_PRECOMPILED_RUNTIME, as it is accessed from generated code.
+  // The code is generated without DART_PRECOMPILED_RUNTIME, but used with
+  // DART_PRECOMPILED_RUNTIME.
 
   TaskKind task_kind_;
   TimelineStream* dart_stream_;
@@ -866,7 +869,6 @@
   int32_t no_callback_scope_depth_;
 #if defined(DEBUG)
   HandleScope* top_handle_scope_;
-  int32_t no_handle_scope_depth_;
   int32_t no_safepoint_scope_depth_;
 #endif
   VMHandles reusable_handles_;
@@ -883,11 +885,6 @@
   TypeUsageInfo* type_usage_info_;
   RawGrowableObjectArray* pending_functions_;
 
-  // JumpToExceptionHandler state:
-  RawObject* active_exception_;
-  RawObject* active_stacktrace_;
-  uword resume_pc_;
-
   RawError* sticky_error_;
 
 // Reusable handles support.
diff --git a/runtime/vm/thread_interrupter_android.cc b/runtime/vm/thread_interrupter_android.cc
index 5987846..92a21f5 100644
--- a/runtime/vm/thread_interrupter_android.cc
+++ b/runtime/vm/thread_interrupter_android.cc
@@ -18,7 +18,6 @@
 
 #ifndef PRODUCT
 
-DECLARE_FLAG(bool, thread_interrupter);
 DECLARE_FLAG(bool, trace_thread_interrupter);
 
 class ThreadInterrupterAndroid : public AllStatic {
diff --git a/runtime/vm/thread_interrupter_fuchsia.cc b/runtime/vm/thread_interrupter_fuchsia.cc
index d2f19c6..3ae857c 100644
--- a/runtime/vm/thread_interrupter_fuchsia.cc
+++ b/runtime/vm/thread_interrupter_fuchsia.cc
@@ -23,7 +23,6 @@
 
 #ifndef PRODUCT
 
-DECLARE_FLAG(bool, thread_interrupter);
 DECLARE_FLAG(bool, trace_thread_interrupter);
 
 // TODO(ZX-430): Currently, CPU profiling for Fuchsia is arranged very similarly
diff --git a/runtime/vm/thread_interrupter_linux.cc b/runtime/vm/thread_interrupter_linux.cc
index 21945a8..dc2bfd0 100644
--- a/runtime/vm/thread_interrupter_linux.cc
+++ b/runtime/vm/thread_interrupter_linux.cc
@@ -17,7 +17,6 @@
 
 #ifndef PRODUCT
 
-DECLARE_FLAG(bool, thread_interrupter);
 DECLARE_FLAG(bool, trace_thread_interrupter);
 
 class ThreadInterrupterLinux : public AllStatic {
diff --git a/runtime/vm/thread_interrupter_macos.cc b/runtime/vm/thread_interrupter_macos.cc
index c8108aa..9ea36b4 100644
--- a/runtime/vm/thread_interrupter_macos.cc
+++ b/runtime/vm/thread_interrupter_macos.cc
@@ -22,7 +22,6 @@
 
 #ifndef PRODUCT
 
-DECLARE_FLAG(bool, thread_interrupter);
 DECLARE_FLAG(bool, trace_thread_interrupter);
 
 // Returns true if the current process is being debugged (either
diff --git a/runtime/vm/thread_interrupter_win.cc b/runtime/vm/thread_interrupter_win.cc
index 9963983..13c6f8d 100644
--- a/runtime/vm/thread_interrupter_win.cc
+++ b/runtime/vm/thread_interrupter_win.cc
@@ -14,7 +14,6 @@
 
 #ifndef PRODUCT
 
-DECLARE_FLAG(bool, thread_interrupter);
 DECLARE_FLAG(bool, trace_thread_interrupter);
 
 #define kThreadError -1
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index b0687de..48df459 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -8,6 +8,7 @@
 #include "vm/lockers.h"
 #include "vm/profiler.h"
 #include "vm/stack_frame.h"
+#include "vm/symbols.h"
 #include "vm/thread_pool.h"
 #include "vm/unit_test.h"
 
@@ -387,6 +388,143 @@
   EXPECT_STREQ("foo", orig_str);
 }
 
+// A helper thread that repeatedly reads ICData
+class ICDataTestTask : public ThreadPool::Task {
+ public:
+  static const intptr_t kTaskCount;
+
+  ICDataTestTask(Isolate* isolate,
+                 const Array& ic_datas,
+                 Monitor* monitor,
+                 intptr_t* exited,
+                 bool* done)
+      : isolate_(isolate),
+        ic_datas_(ic_datas),
+        len_(ic_datas.Length()),
+        monitor_(monitor),
+        exited_(exited),
+        done_(done) {}
+
+  virtual void Run() {
+    Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
+
+    Thread* thread = Thread::Current();
+
+    {
+      StackZone stack_zone(thread);
+      HANDLESCOPE(thread);
+
+      ICData& ic_data = ICData::Handle();
+      Array& arr = Array::Handle();
+      while (true) {
+        for (intptr_t cnt = 0; cnt < 0x1000; cnt++) {
+          for (intptr_t i = 0; i < len_; i++) {
+            ic_data ^= ic_datas_.At(i);
+            arr = ic_data.ic_data();
+            intptr_t num_checks = arr.Length() / 3;
+            if (num_checks < 0 || num_checks > 5) {
+              OS::PrintErr("Failure: %" Pd " checks!\n", num_checks);
+              abort();
+            }
+          }
+        }
+
+        if (AtomicOperations::LoadAcquire(done_)) {
+          break;
+        }
+
+        TransitionVMToBlocked blocked(thread);
+      }
+    }
+
+    Thread::ExitIsolateAsHelper();
+    {
+      MonitorLocker ml(monitor_);
+      ++*exited_;
+      ml.Notify();
+    }
+  }
+
+ private:
+  Isolate* isolate_;
+  const Array& ic_datas_;
+  const intptr_t len_;
+  Monitor* monitor_;
+  intptr_t* exited_;  // # tasks that are no longer running.
+  bool* done_;        // Signal that helper threads can stop working.
+};
+
+static Function* CreateFunction(const char* name) {
+  const String& class_name =
+      String::Handle(Symbols::New(Thread::Current(), "ownerClass"));
+  const Script& script = Script::Handle();
+  const Library& lib = Library::Handle(Library::New(class_name));
+  const Class& owner_class = Class::Handle(
+      Class::New(lib, class_name, script, TokenPosition::kNoSource));
+  const String& function_name =
+      String::ZoneHandle(Symbols::New(Thread::Current(), name));
+  Function& function = Function::ZoneHandle(Function::New(
+      function_name, RawFunction::kRegularFunction, true, false, false, false,
+      false, owner_class, TokenPosition::kNoSource));
+  return &function;
+}
+
+const intptr_t ICDataTestTask::kTaskCount = 1;
+
+// Test that checks that other threads only see a fully initialized ICData
+// whenever ICData is updated.
+ISOLATE_UNIT_TEST_CASE(ICDataTest) {
+  Isolate* isolate = thread->isolate();
+  USE(isolate);
+  Monitor monitor;
+  intptr_t exited = 0;
+  bool done = false;
+
+  const intptr_t kNumICData = 0x10;
+
+  const Array& ic_datas = Array::Handle(Array::New(kNumICData));
+  ICData& ic_data = ICData::Handle();
+  Function& owner = *CreateFunction("DummyFunction");
+  String& name = String::Handle(String::New("foo"));
+  const Array& args_desc =
+      Array::Handle(ArgumentsDescriptor::New(0, 0, Object::empty_array()));
+  for (intptr_t i = 0; i < kNumICData; i++) {
+    ic_data = ICData::New(owner, name, args_desc, /*deopt_id=*/0,
+                          /*num_args_tested=*/1, ICData::kInstance,
+                          Object::null_abstract_type());
+    ic_datas.SetAt(i, ic_data);
+  }
+
+  for (int i = 0; i < ICDataTestTask::kTaskCount; i++) {
+    Dart::thread_pool()->Run(
+        new ICDataTestTask(isolate, ic_datas, &monitor, &exited, &done));
+  }
+
+  for (int i = 0; i < 0x10000; i++) {
+    for (intptr_t i = 0; i < kNumICData; i++) {
+      ic_data ^= ic_datas.At(i);
+      if (ic_data.NumberOfChecks() < 4) {
+        ic_data.AddReceiverCheck(kInstanceCid + ic_data.NumberOfChecks(), owner,
+                                 1);
+      } else {
+        ic_data = ICData::New(owner, name, args_desc, /*deopt_id=*/0,
+                              /*num_args_tested=*/1, ICData::kInstance,
+                              Object::null_abstract_type());
+        ic_datas.SetAt(i, ic_data);
+      }
+    }
+  }
+  // Ensure we looped long enough to allow all helpers to succeed and exit.
+  {
+    AtomicOperations::StoreRelease(&done, true);
+    MonitorLocker ml(&monitor);
+    while (exited != ICDataTestTask::kTaskCount) {
+      ml.Wait();
+    }
+    EXPECT_EQ(ICDataTestTask::kTaskCount, exited);
+  }
+}
+
 // A helper thread that alternatingly cooperates and organizes
 // safepoint rendezvous. At rendezvous, it explicitly visits the
 // stacks looking for a specific marker (Smi) to verify that the expected
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 2e635c1..1f849fd 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -153,7 +153,6 @@
   }
 
   if (type.IsCanonical()) {
-    ASSERT(type.IsResolved());
     if (type.IsType()) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
       // Lazily create the type testing stubs array.
@@ -345,13 +344,13 @@
   ASSERT(!type_class.IsNull());
 
   // To use the already-defined __ Macro !
-  ObjectPoolWrapper object_pool_wrapper;
-  Assembler assembler(&object_pool_wrapper);
+  Assembler assembler(nullptr);
   BuildOptimizedTypeTestStub(&assembler, hi, type, type_class);
 
   const char* name = namer_.StubNameForType(type);
-  const Code& code = Code::Handle(
-      Code::FinalizeCode(name, nullptr, &assembler, false /* optimized */));
+  const Code& code = Code::Handle(Code::FinalizeCode(
+      name, nullptr, &assembler, Code::PoolAttachment::kAttachPool,
+      false /* optimized */));
 #ifndef PRODUCT
   if (FLAG_support_disassembler && FLAG_disassemble_stubs) {
     LogBlock lb;
@@ -360,7 +359,9 @@
     code.Disassemble(&formatter);
     THR_Print("}\n");
     const ObjectPool& object_pool = ObjectPool::Handle(code.object_pool());
-    object_pool.DebugPrint();
+    if (!object_pool.IsNull()) {
+      object_pool.DebugPrint();
+    }
   }
 #endif  // !PRODUCT
 
@@ -629,9 +630,9 @@
     if (cid != kDynamicCid) {
       const Class& instance_klass =
           Class::Handle(Isolate::Current()->class_table()->At(cid));
-      if (instance_klass.IsGeneric() &&
+      if (load_field->slot().IsTypeArguments() && instance_klass.IsGeneric() &&
           instance_klass.type_arguments_field_offset() ==
-              load_field->offset_in_bytes()) {
+              load_field->slot().offset_in_bytes()) {
         // This is a subset of Case c) above, namely forwarding the type
         // argument vector.
         //
@@ -994,7 +995,7 @@
   if (type.IsTypeRef()) {
     dereferenced_type = &AbstractType::Handle(TypeRef::Cast(type).type());
   }
-  if (dereferenced_type->IsResolved() && dereferenced_type->IsFinalized()) {
+  if (dereferenced_type->IsFinalized()) {
     return assert_assignable_types_.HasKey(dereferenced_type);
   }
   return false;
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index ed188dd..50e55a0 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -663,16 +663,13 @@
 
   Object& val = Object::Handle();
   if (!KernelIsolate::IsRunning()) {
-    val = lib.Evaluate(expr, param_names, param_values);
+    UNREACHABLE();
   } else {
-    Dart_KernelCompilationResult compilation_result;
-    {
-      TransitionVMToNative transition(thread);
-      compilation_result = KernelIsolate::CompileExpressionToKernel(
-          expr.ToCString(), param_names, Array::empty_array(),
-          String::Handle(lib.url()).ToCString(), /* klass=*/nullptr,
-          /* is_static= */ false);
-    }
+    Dart_KernelCompilationResult compilation_result =
+        KernelIsolate::CompileExpressionToKernel(
+            expr.ToCString(), param_names, Array::empty_array(),
+            String::Handle(lib.url()).ToCString(), /* klass=*/nullptr,
+            /* is_static= */ false);
     if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
       return Dart_NewApiError(compilation_result.error);
     }
@@ -711,7 +708,8 @@
   Function& function = Function::ZoneHandle(
       Function::New(function_name, RawFunction::kRegularFunction, true, false,
                     false, false, false, cls, TokenPosition::kMinSource));
-  code_ = Code::FinalizeCode(function, nullptr, assembler_);
+  code_ = Code::FinalizeCode(function, nullptr, assembler_,
+                             Code::PoolAttachment::kAttachPool);
   code_.set_owner(function);
   code_.set_exception_handlers(Object::empty_exception_handlers());
 #ifndef PRODUCT
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index 81a23cf..6c53746 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -64,8 +64,10 @@
     TestIsolateScope __test_isolate__;                                         \
     Thread* __thread__ = Thread::Current();                                    \
     ASSERT(__thread__->isolate() == __test_isolate__.isolate());               \
+    TransitionNativeToVM transition1(__thread__);                              \
     StackZone __zone__(__thread__);                                            \
     HandleScope __hs__(__thread__);                                            \
+    TransitionVMToNative transition2(__thread__);                              \
     Dart_TestHelper##name(__thread__);                                         \
   }                                                                            \
   static void Dart_TestHelper##name(Thread* thread)
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index 3605252..50882d9 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -247,8 +247,6 @@
   "runtime_entry_ia32.cc",
   "runtime_entry_list.h",
   "runtime_entry_x64.cc",
-  "scanner.cc",
-  "scanner.h",
   "scope_timer.h",
   "scopes.cc",
   "scopes.h",
@@ -415,7 +413,6 @@
   "regexp_test.cc",
   "resolver_test.cc",
   "ring_buffer_test.cc",
-  "scanner_test.cc",
   "scopes_test.cc",
   "service_test.cc",
   "snapshot_test.cc",
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 12455bf..1de45ab 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -58,9 +58,6 @@
 # ......dart_tools_api.h
 # ....lib/
 # ......libraries.json
-# ......dart_client.platform
-# ......dart_server.platform
-# ......dart_shared.platform
 # ......_internal/
 #.........strong.sum
 #.........dart2js_platform.dill
@@ -753,19 +750,6 @@
   ]
 }
 
-# This rule copies .platform files to lib/
-copy("copy_platform_files") {
-  visibility = [ ":create_common_sdk" ]
-  sources = [
-    "lib/dart_client.platform",
-    "lib/dart_server.platform",
-    "lib/dart_shared.platform",
-  ]
-  outputs = [
-    "$root_out_dir/dart-sdk/lib/{{source_file_part}}",
-  ]
-}
-
 # This is the main rule to copy libraries in _platform_sdk_libraries to lib/
 group("copy_platform_sdk_libraries") {
   visibility = [
@@ -914,7 +898,6 @@
     ":copy_libraries_dart",
     ":copy_license",
     ":copy_libraries_specification",
-    ":copy_platform_files",
     ":copy_readme",
     ":copy_vm_dill_files",
     ":write_revision_file",
diff --git a/sdk/bin/dart2js_sdk b/sdk/bin/dart2js_sdk
index 70c60b7..e7999b4 100755
--- a/sdk/bin/dart2js_sdk
+++ b/sdk/bin/dart2js_sdk
@@ -40,7 +40,7 @@
 declare -a EXTRA_VM_OPTIONS
 
 if test -f "$SNAPSHOT"; then
-  EXTRA_OPTIONS+=("--library-root=$SDK_DIR")
+  EXTRA_OPTIONS+=("--libraries-spec=$SDK_DIR/lib/libraries.json")
 fi
 
 case $0 in
diff --git a/sdk/bin/dart2js_sdk.bat b/sdk/bin/dart2js_sdk.bat
index acc4e17..8485cdc 100755
--- a/sdk/bin/dart2js_sdk.bat
+++ b/sdk/bin/dart2js_sdk.bat
@@ -28,7 +28,7 @@
 )
 
 if exist "%SNAPSHOT%" (
-  set EXTRA_OPTIONS=%EXTRA_OPTIONS% "--library-root=%SDK_DIR%"
+  set EXTRA_OPTIONS=%EXTRA_OPTIONS% "--libraries-spec=%SDK_DIR%\lib\libraries.json"
 )
 
 rem We allow extra vm options to be passed in through an environment variable.
diff --git a/sdk/lib/_http/http.dart b/sdk/lib/_http/http.dart
index 29e785b..b69a600 100644
--- a/sdk/lib/_http/http.dart
+++ b/sdk/lib/_http/http.dart
@@ -36,6 +36,7 @@
 abstract class HttpStatus {
   static const int continue_ = 100;
   static const int switchingProtocols = 101;
+  static const int processing = 102;
   static const int ok = 200;
   static const int created = 201;
   static const int accepted = 202;
@@ -43,6 +44,9 @@
   static const int noContent = 204;
   static const int resetContent = 205;
   static const int partialContent = 206;
+  static const int multiStatus = 207;
+  static const int alreadyReported = 208;
+  static const int imUsed = 226;
   static const int multipleChoices = 300;
   static const int movedPermanently = 301;
   static const int found = 302;
@@ -51,6 +55,7 @@
   static const int notModified = 304;
   static const int useProxy = 305;
   static const int temporaryRedirect = 307;
+  static const int permanentRedirect = 308;
   static const int badRequest = 400;
   static const int unauthorized = 401;
   static const int paymentRequired = 402;
@@ -69,13 +74,28 @@
   static const int unsupportedMediaType = 415;
   static const int requestedRangeNotSatisfiable = 416;
   static const int expectationFailed = 417;
+  static const int misdirectedRequest = 421;
+  static const int unprocessableEntity = 422;
+  static const int locked = 423;
+  static const int failedDependency = 424;
   static const int upgradeRequired = 426;
+  static const int preconditionRequired = 428;
+  static const int tooManyRequests = 429;
+  static const int requestHeaderFieldsTooLarge = 431;
+  static const int connectionClosedWithoutResponse = 444;
+  static const int unavailableForLegalReasons = 451;
+  static const int clientClosedRequest = 499;
   static const int internalServerError = 500;
   static const int notImplemented = 501;
   static const int badGateway = 502;
   static const int serviceUnavailable = 503;
   static const int gatewayTimeout = 504;
   static const int httpVersionNotSupported = 505;
+  static const int variantAlsoNegotiates = 506;
+  static const int insufficientStorage = 507;
+  static const int loopDetected = 508;
+  static const int notExtended = 510;
+  static const int networkAuthenticationRequired = 511;
   // Client generated status code.
   static const int networkConnectTimeoutError = 599;
 
@@ -1320,7 +1340,7 @@
   /**
    * Gets and sets the content length of the response. If the size of
    * the response is not known in advance set the content length to
-   * -1 - which is also the default if not set.
+   * -1, which is also the default if not set.
    */
   int contentLength;
 
@@ -1602,11 +1622,10 @@
    * a possible query) is specified using [path].
    * The path may also contain a URI fragment, which will be ignored.
    *
-   * The `Host` header for the request will be set to the value
-   * [host]:[port]. This can be overridden through the
-   * [HttpClientRequest] interface before the request is sent.  NOTE
-   * if [host] is an IP address this will still be set in the `Host`
-   * header.
+   * The `Host` header for the request will be set to the value [host]:[port]
+   * (if [host] is an IP address, it will still be used in the `Host` header).
+   * This can be overridden through the [HttpClientRequest] interface before
+   * the request is sent.
    *
    * For additional information on the sequence of events during an
    * HTTP transaction, and the objects returned by the futures, see
@@ -1622,10 +1641,9 @@
    * [url].
    *
    * The `Host` header for the request will be set to the value
-   * [Uri.host]:[Uri.port] from [url]. This can be overridden through the
-   * [HttpClientRequest] interface before the request is sent.  NOTE
-   * if [Uri.host] is an IP address this will still be set in the `Host`
-   * header.
+   * [Uri.host]:[Uri.port] from [url] (if [url.host] is an IP address, it will
+   * still be used in the `Host` header). This can be overridden through the
+   * [HttpClientRequest] interface before the request is sent.
    *
    * For additional information on the sequence of events during an
    * HTTP transaction, and the objects returned by the futures, see
@@ -2092,16 +2110,16 @@
    * the response body is not known in advance.
    *
    * If the content length needs to be set, it must be set before the
-   * body is written to. Setting the reason phrase after writing to
-   * the body will throw a `StateError`.
+   * body is written to. Setting the content length after writing to the body
+   * will throw a `StateError`.
    */
   int get contentLength;
 
   /**
    * Gets the persistent connection state returned by the server.
    *
-   * if the persistent connection state needs to be set, it must be
-   * set before the body is written to. Setting the reason phrase
+   * If the persistent connection state needs to be set, it must be
+   * set before the body is written to. Setting the persistent connection state
    * after writing to the body will throw a `StateError`.
    */
   bool get persistentConnection;
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index 059ce00..a5438a4 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -375,6 +375,26 @@
 
   @patch
   int get weekday => Primitives.getWeekday(this);
+
+  @patch
+  bool operator ==(dynamic other) =>
+      other is DateTime &&
+      _value == other.millisecondsSinceEpoch &&
+      isUtc == other.isUtc;
+
+  @patch
+  bool isBefore(DateTime other) => _value < other.millisecondsSinceEpoch;
+
+  @patch
+  bool isAfter(DateTime other) => _value > other.millisecondsSinceEpoch;
+
+  @patch
+  bool isAtSameMomentAs(DateTime other) =>
+      _value == other.millisecondsSinceEpoch;
+
+  @patch
+  int compareTo(DateTime other) =>
+      _value.compareTo(other.millisecondsSinceEpoch);
 }
 
 // Patch for Stopwatch implementation.
diff --git a/sdk/lib/async/async_error.dart b/sdk/lib/async/async_error.dart
index df6ad29..1520c54 100644
--- a/sdk/lib/async/async_error.dart
+++ b/sdk/lib/async/async_error.dart
@@ -7,6 +7,10 @@
 _invokeErrorHandler(
     Function errorHandler, Object error, StackTrace stackTrace) {
   if (errorHandler is ZoneBinaryCallback<dynamic, Null, Null>) {
+    // Dynamic invocation because we don't know the actual type of the
+    // first argument or the error object, but we should successfully call
+    // the handler if they match up.
+    // TODO(lrn): Should we? Why not the same below for the unary case?
     return (errorHandler as dynamic)(error, stackTrace);
   } else {
     ZoneUnaryCallback unaryErrorHandler = errorHandler;
diff --git a/sdk/lib/async/broadcast_stream_controller.dart b/sdk/lib/async/broadcast_stream_controller.dart
index 44e468d..32e4582 100644
--- a/sdk/lib/async/broadcast_stream_controller.dart
+++ b/sdk/lib/async/broadcast_stream_controller.dart
@@ -57,11 +57,7 @@
 }
 
 abstract class _BroadcastStreamController<T>
-    implements
-        StreamController<T>,
-        _StreamControllerLifecycle<T>,
-        _EventSink<T>,
-        _EventDispatch<T> {
+    implements _StreamControllerBase<T> {
   static const int _STATE_INITIAL = 0;
   static const int _STATE_EVENT_ID = 1;
   static const int _STATE_FIRING = 2;
@@ -206,7 +202,7 @@
   StreamSubscription<T> _subscribe(void onData(T data), Function onError,
       void onDone(), bool cancelOnError) {
     if (isClosed) {
-      if (onDone == null) onDone = _nullDoneHandler;
+      onDone ??= _nullDoneHandler;
       return new _DoneStreamSubscription<T>(onDone);
     }
     StreamSubscription<T> subscription = new _BroadcastSubscription<T>(
@@ -466,9 +462,7 @@
   bool get _hasPending => _pending != null && !_pending.isEmpty;
 
   void _addPendingEvent(_DelayedEvent event) {
-    if (_pending == null) {
-      _pending = new _StreamImplEvents<T>();
-    }
+    _pending ??= new _StreamImplEvents<T>();
     _pending.add(event);
   }
 
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index beb982e..c968cbd 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -312,10 +312,14 @@
   factory Future.delayed(Duration duration, [FutureOr<T> computation()]) {
     _Future<T> result = new _Future<T>();
     new Timer(duration, () {
-      try {
-        result._complete(computation?.call());
-      } catch (e, s) {
-        _completeWithErrorCallback(result, e, s);
+      if (computation == null) {
+        result._complete(null);
+      } else {
+        try {
+          result._complete(computation());
+        } catch (e, s) {
+          _completeWithErrorCallback(result, e, s);
+        }
       }
     });
     return result;
@@ -361,7 +365,7 @@
     // Handle an error from any of the futures.
     // TODO(jmesserly): use `void` return type once it can be inferred for the
     // `then` call below.
-    handleError(theError, theStackTrace) {
+    handleError(theError, StackTrace theStackTrace) {
       remaining--;
       if (values != null) {
         if (cleanUp != null) {
@@ -457,7 +461,7 @@
     var onValue = (T value) {
       if (!completer.isCompleted) completer.complete(value);
     };
-    var onError = (error, stack) {
+    var onError = (error, StackTrace stack) {
       if (!completer.isCompleted) completer.completeError(error, stack);
     };
     for (var future in futures) {
@@ -521,7 +525,7 @@
    */
   static Future doWhile(FutureOr<bool> action()) {
     _Future doneSignal = new _Future();
-    var nextIteration;
+    void Function(bool) nextIteration;
     // Bind this callback explicitly so that each iteration isn't bound in the
     // context of all the previous iterations' callbacks.
     // This avoids, e.g., deeply nested stack traces from the stack trace
@@ -906,7 +910,7 @@
 
 // Helper function completing a _Future with error, but checking the zone
 // for error replacement first.
-void _completeWithErrorCallback(_Future result, error, stackTrace) {
+void _completeWithErrorCallback(_Future result, error, StackTrace stackTrace) {
   AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
   if (replacement != null) {
     error = _nonNullError(replacement.error);
@@ -916,7 +920,8 @@
 }
 
 // Like [_completeWithErrorCallback] but completes asynchronously.
-void _asyncCompleteWithErrorCallback(_Future result, error, stackTrace) {
+void _asyncCompleteWithErrorCallback(
+    _Future result, error, StackTrace stackTrace) {
   AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
   if (replacement != null) {
     error = _nonNullError(replacement.error);
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index b85e6ab..3fd6b59 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -68,7 +68,7 @@
   static const int stateCatcherrorTest = maskError | maskTestError;
   static const int stateWhencomplete = maskWhencomplete;
   // Listeners on the same future are linked through this link.
-  _FutureListener _nextListener = null;
+  _FutureListener _nextListener;
   // The future to complete when this listener is activated.
   final _Future<T> result;
   // Which fields means what.
@@ -84,14 +84,11 @@
         errorCallback = errorCallback,
         state = (errorCallback == null) ? stateThen : stateThenOnerror;
 
-  _FutureListener.catchError(
-      this.result, this.errorCallback, _FutureErrorTest test)
-      : callback = test,
-        state = (test == null) ? stateCatcherror : stateCatcherrorTest;
+  _FutureListener.catchError(this.result, this.errorCallback, this.callback)
+      : state = (callback == null) ? stateCatcherror : stateCatcherrorTest;
 
-  _FutureListener.whenComplete(this.result, _FutureAction onComplete)
-      : callback = onComplete,
-        errorCallback = null,
+  _FutureListener.whenComplete(this.result, this.callback)
+      : errorCallback = null,
         state = stateWhencomplete;
 
   Zone get _zone => result._zone;
@@ -395,7 +392,7 @@
   }
 
   _FutureListener _reverseListeners(_FutureListener listeners) {
-    _FutureListener prev = null;
+    _FutureListener prev;
     _FutureListener current = listeners;
     while (current != null) {
       _FutureListener next = current._nextListener;
@@ -429,7 +426,7 @@
           // and dependent on the listeners of the target future. If none of
           // the target future's listeners want to have the stack trace we don't
           // need a trace.
-          onError: (error, [stackTrace]) {
+          onError: (error, [StackTrace stackTrace]) {
         assert(target._isPendingComplete);
         target._completeError(error, stackTrace);
       });
@@ -739,7 +736,7 @@
         timer.cancel();
         result._completeWithValue(v);
       }
-    }, onError: (e, s) {
+    }, onError: (e, StackTrace s) {
       if (timer.isActive) {
         timer.cancel();
         result._completeError(e, s);
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index de9b332..798e63f 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -147,7 +147,7 @@
         if (--count == 0) controller._closeUnchecked();
       }
     };
-    var onError = (error, stack) {
+    var onError = (error, StackTrace stack) {
       if (!controller.isClosed) {
         controller._addError(error, stack);
         if (--count == 0) controller._closeUnchecked();
@@ -426,15 +426,14 @@
    * The returned stream is a broadcast stream if this stream is.
    */
   Stream<E> asyncMap<E>(FutureOr<E> convert(T event)) {
-    StreamController<E> controller;
+    _StreamControllerBase<E> controller;
     StreamSubscription<T> subscription;
 
     void onListen() {
       final add = controller.add;
-      assert(controller is _StreamController ||
+      assert(controller is _StreamController<E> ||
           controller is _BroadcastStreamController);
-      final _EventSink<E> eventSink = controller as Object;
-      final addError = eventSink._addError;
+      final addError = controller._addError;
       subscription = this.listen((T event) {
         FutureOr<E> newValue;
         try {
@@ -495,12 +494,11 @@
    * The returned stream is a broadcast stream if this stream is.
    */
   Stream<E> asyncExpand<E>(Stream<E> convert(T event)) {
-    StreamController<E> controller;
+    _StreamControllerBase<E> controller;
     StreamSubscription<T> subscription;
     void onListen() {
       assert(controller is _StreamController ||
           controller is _BroadcastStreamController);
-      final _EventSink<E> eventSink = controller as Object;
       subscription = this.listen((T event) {
         Stream<E> newStream;
         try {
@@ -514,7 +512,7 @@
           controller.addStream(newStream).whenComplete(subscription.resume);
         }
       },
-          onError: eventSink._addError, // Avoid Zone error replacement.
+          onError: controller._addError, // Avoid Zone error replacement.
           onDone: controller.close);
     }
 
@@ -1195,7 +1193,7 @@
    */
   Future<T> get last {
     _Future<T> future = new _Future<T>();
-    T result = null;
+    T result;
     bool foundResult = false;
     listen(
         (T value) {
@@ -1230,7 +1228,7 @@
    */
   Future<T> get single {
     _Future<T> future = new _Future<T>();
-    T result = null;
+    T result;
     bool foundResult = false;
     StreamSubscription subscription;
     subscription = this.listen(
@@ -1328,7 +1326,7 @@
    */
   Future<T> lastWhere(bool test(T element), {T orElse()}) {
     _Future<T> future = new _Future();
-    T result = null;
+    T result;
     bool foundResult = false;
     StreamSubscription subscription;
     subscription = this.listen(
@@ -1368,7 +1366,7 @@
    */
   Future<T> singleWhere(bool test(T element), {T orElse()}) {
     _Future<T> future = new _Future<T>();
-    T result = null;
+    T result;
     bool foundResult = false;
     StreamSubscription subscription;
     subscription = this.listen(
@@ -1474,7 +1472,7 @@
    * and the subscriptions' timers can be paused individually.
    */
   Stream<T> timeout(Duration timeLimit, {void onTimeout(EventSink<T> sink)}) {
-    StreamController<T> controller;
+    _StreamControllerBase<T> controller;
     // The following variables are set on listen.
     StreamSubscription<T> subscription;
     Timer timer;
@@ -1491,8 +1489,7 @@
       timer.cancel();
       assert(controller is _StreamController ||
           controller is _BroadcastStreamController);
-      dynamic eventSink = controller;
-      eventSink._addError(error, stackTrace); // Avoid Zone error replacement.
+      controller._addError(error, stackTrace); // Avoid Zone error replacement.
       timer = zone.createTimer(timeLimit, timeout);
     }
 
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index 71b857f..34c6adf 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -381,17 +381,20 @@
   Future _recordCancel(StreamSubscription<T> subscription) => null;
 }
 
+// Base type for implementations of stream controllers.
+abstract class _StreamControllerBase<T>
+    implements
+        StreamController<T>,
+        _StreamControllerLifecycle<T>,
+        _EventSink<T>,
+        _EventDispatch<T> {}
+
 /**
  * Default implementation of [StreamController].
  *
  * Controls a stream that only supports a single controller.
  */
-abstract class _StreamController<T>
-    implements
-        StreamController<T>,
-        _StreamControllerLifecycle<T>,
-        _EventSink<T>,
-        _EventDispatch<T> {
+abstract class _StreamController<T> implements _StreamControllerBase<T> {
   // The states are bit-flags. More than one can be set at a time.
   //
   // The "subscription state" goes through the states:
@@ -516,7 +519,7 @@
   _StreamImplEvents<T> _ensurePendingEvents() {
     assert(_isInitialState);
     if (!_isAddingStream) {
-      if (_varData == null) _varData = new _StreamImplEvents<T>();
+      _varData ??= new _StreamImplEvents<T>();
       return _varData;
     }
     _StreamControllerAddStreamState<T> state = _varData;
@@ -571,9 +574,7 @@
   Future get done => _ensureDoneFuture();
 
   Future _ensureDoneFuture() {
-    if (_doneFuture == null) {
-      _doneFuture = _isCanceled ? Future._nullFuture : new _Future();
-    }
+    _doneFuture ??= _isCanceled ? Future._nullFuture : new _Future();
     return _doneFuture;
   }
 
@@ -824,9 +825,8 @@
 
   bool operator ==(Object other) {
     if (identical(this, other)) return true;
-    if (other is! _ControllerStream) return false;
-    _ControllerStream otherStream = other;
-    return identical(otherStream._controller, this._controller);
+    return other is _ControllerStream &&
+        identical(other._controller, this._controller);
   }
 }
 
@@ -933,7 +933,7 @@
   var varData;
 
   _StreamControllerAddStreamState(_StreamController<T> controller, this.varData,
-      Stream source, bool cancelOnError)
+      Stream<T> source, bool cancelOnError)
       : super(controller, source, cancelOnError) {
     if (controller.isPaused) {
       addSubscription.pause();
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 6c2b8ba..956de3b 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -133,14 +133,14 @@
   // StreamSubscription interface.
 
   void onData(void handleData(T event)) {
-    if (handleData == null) handleData = _nullDataHandler;
+    handleData ??= _nullDataHandler;
     // TODO(floitsch): the return type should be 'void', and the type
     // should be inferred.
     _onData = _zone.registerUnaryCallback<dynamic, T>(handleData);
   }
 
   void onError(Function handleError) {
-    if (handleError == null) handleError = _nullErrorHandler;
+    handleError ??= _nullErrorHandler;
     if (handleError is void Function(Object, StackTrace)) {
       _onError = _zone
           .registerBinaryCallback<dynamic, Object, StackTrace>(handleError);
@@ -153,7 +153,7 @@
   }
 
   void onDone(void handleDone()) {
-    if (handleDone == null) handleDone = _nullDoneHandler;
+    handleDone ??= _nullDoneHandler;
     _onDone = _zone.registerCallback(handleDone);
   }
 
@@ -203,7 +203,7 @@
     _onDone = () {
       result._complete(futureValue);
     };
-    _onError = (error, stackTrace) {
+    _onError = (error, StackTrace stackTrace) {
       Future cancelFuture = cancel();
       if (!identical(cancelFuture, Future._nullFuture)) {
         cancelFuture.whenComplete(() {
@@ -682,10 +682,10 @@
 /** Class holding pending events for a [_StreamImpl]. */
 class _StreamImplEvents<T> extends _PendingEvents<T> {
   /// Single linked list of [_DelayedEvent] objects.
-  _DelayedEvent firstPendingEvent = null;
+  _DelayedEvent firstPendingEvent;
 
   /// Last element in the list of pending events. New events are added after it.
-  _DelayedEvent lastPendingEvent = null;
+  _DelayedEvent lastPendingEvent;
 
   bool get isEmpty => lastPendingEvent == null;
 
@@ -813,10 +813,8 @@
       // it will only ever send one done event.
       return new _DoneStreamSubscription<T>(onDone);
     }
-    if (_subscription == null) {
-      _subscription = _source.listen(_controller.add,
-          onError: _controller.addError, onDone: _controller.close);
-    }
+    _subscription ??= _source.listen(_controller.add,
+        onError: _controller.addError, onDone: _controller.close);
     cancelOnError = identical(true, cancelOnError);
     return _controller._subscribe(onData, onError, onDone, cancelOnError);
   }
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index 3cb1145..31d5bab 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -179,7 +179,7 @@
 
 typedef bool _Predicate<T>(T value);
 
-void _addErrorWithReplacement(_EventSink sink, error, stackTrace) {
+void _addErrorWithReplacement(_EventSink sink, error, StackTrace stackTrace) {
   AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
   if (replacement != null) {
     error = _nonNullError(replacement.error);
@@ -456,7 +456,7 @@
 typedef bool _Equality<T>(T a, T b);
 
 class _DistinctStream<T> extends _ForwardingStream<T, T> {
-  static var _SENTINEL = new Object();
+  static final _SENTINEL = new Object();
 
   final _Equality<T> _equals;
 
diff --git a/sdk/lib/async/stream_transformers.dart b/sdk/lib/async/stream_transformers.dart
index 5488d55..9a4b1dc 100644
--- a/sdk/lib/async/stream_transformers.dart
+++ b/sdk/lib/async/stream_transformers.dart
@@ -123,7 +123,7 @@
     }
   }
 
-  void _handleError(error, [stackTrace]) {
+  void _handleError(error, [StackTrace stackTrace]) {
     try {
       _transformerSink.addError(error, stackTrace);
     } catch (e, s) {
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index 6f11023..911ecff 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -95,19 +95,19 @@
    * the ones in [other].
    */
   factory ZoneSpecification.from(ZoneSpecification other,
-      {HandleUncaughtErrorHandler handleUncaughtError: null,
-      RunHandler run: null,
-      RunUnaryHandler runUnary: null,
-      RunBinaryHandler runBinary: null,
-      RegisterCallbackHandler registerCallback: null,
-      RegisterUnaryCallbackHandler registerUnaryCallback: null,
-      RegisterBinaryCallbackHandler registerBinaryCallback: null,
-      ErrorCallbackHandler errorCallback: null,
-      ScheduleMicrotaskHandler scheduleMicrotask: null,
-      CreateTimerHandler createTimer: null,
-      CreatePeriodicTimerHandler createPeriodicTimer: null,
-      PrintHandler print: null,
-      ForkHandler fork: null}) {
+      {HandleUncaughtErrorHandler handleUncaughtError,
+      RunHandler run,
+      RunUnaryHandler runUnary,
+      RunBinaryHandler runBinary,
+      RegisterCallbackHandler registerCallback,
+      RegisterUnaryCallbackHandler registerUnaryCallback,
+      RegisterBinaryCallbackHandler registerBinaryCallback,
+      ErrorCallbackHandler errorCallback,
+      ScheduleMicrotaskHandler scheduleMicrotask,
+      CreateTimerHandler createTimer,
+      CreatePeriodicTimerHandler createPeriodicTimer,
+      PrintHandler print,
+      ForkHandler fork}) {
     return new ZoneSpecification(
         handleUncaughtError: handleUncaughtError ?? other.handleUncaughtError,
         run: run ?? other.run,
@@ -150,19 +150,19 @@
  */
 class _ZoneSpecification implements ZoneSpecification {
   const _ZoneSpecification(
-      {this.handleUncaughtError: null,
-      this.run: null,
-      this.runUnary: null,
-      this.runBinary: null,
-      this.registerCallback: null,
-      this.registerUnaryCallback: null,
-      this.registerBinaryCallback: null,
-      this.errorCallback: null,
-      this.scheduleMicrotask: null,
-      this.createTimer: null,
-      this.createPeriodicTimer: null,
-      this.print: null,
-      this.fork: null});
+      {this.handleUncaughtError,
+      this.run,
+      this.runUnary,
+      this.runBinary,
+      this.registerCallback,
+      this.registerUnaryCallback,
+      this.registerBinaryCallback,
+      this.errorCallback,
+      this.scheduleMicrotask,
+      this.createTimer,
+      this.createPeriodicTimer,
+      this.print,
+      this.fork});
 
   final HandleUncaughtErrorHandler handleUncaughtError;
   final RunHandler run;
@@ -1108,7 +1108,7 @@
 void _rootHandleUncaughtError(
     Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) {
   _schedulePriorityAsyncCallback(() {
-    if (error == null) error = new NullThrownError();
+    error ??= new NullThrownError();
     if (stackTrace == null) throw error;
     _rethrow(error, stackTrace);
   });
@@ -1277,7 +1277,7 @@
   /// This is always a [HashMap].
   Map get _map => _rootMap;
 
-  static Map _rootMap = new HashMap();
+  static final _rootMap = new HashMap();
 
   static ZoneDelegate _rootDelegate;
 
diff --git a/sdk/lib/collection/iterable.dart b/sdk/lib/collection/iterable.dart
index 79d6188..dc84459 100644
--- a/sdk/lib/collection/iterable.dart
+++ b/sdk/lib/collection/iterable.dart
@@ -168,7 +168,7 @@
   }
 
   E lastWhere(bool test(E value), {E orElse()}) {
-    E result = null;
+    E result;
     bool foundMatching = false;
     for (E element in this) {
       if (test(element)) {
@@ -182,7 +182,7 @@
   }
 
   E singleWhere(bool test(E element), {E orElse()}) {
-    E result = null;
+    E result;
     bool foundMatching = false;
     for (E element in this) {
       if (test(element)) {
@@ -238,7 +238,7 @@
       }
       return "$leftDelimiter...$rightDelimiter";
     }
-    List parts = [];
+    List<String> parts = <String>[];
     _toStringVisiting.add(iterable);
     try {
       _iterablePartsToStrings(iterable, parts);
@@ -296,7 +296,7 @@
 /**
  * Convert elements of [iterable] to strings and store them in [parts].
  */
-void _iterablePartsToStrings(Iterable iterable, List parts) {
+void _iterablePartsToStrings(Iterable iterable, List<String> parts) {
   /*
    * This is the complicated part of [iterableToShortString].
    * It is extracted as a separate function to avoid having too much code
@@ -337,8 +337,8 @@
 
   // Find last two elements. One or more of them may already be in the
   // parts array. Include their length in `length`.
-  var penultimate = null;
-  var ultimate = null;
+  Object penultimate;
+  Object ultimate;
   if (!it.moveNext()) {
     if (count <= headCount + tailCount) return;
     ultimateString = parts.removeLast();
@@ -388,7 +388,7 @@
 
   // If there is a gap between the initial run and the last two,
   // prepare to add an ellipsis.
-  String elision = null;
+  String elision;
   if (count > parts.length + tailCount) {
     elision = "...";
     length += ellipsisSize + overhead;
diff --git a/sdk/lib/collection/list.dart b/sdk/lib/collection/list.dart
index a719679..4b50c6a 100644
--- a/sdk/lib/collection/list.dart
+++ b/sdk/lib/collection/list.dart
@@ -163,7 +163,7 @@
 
   E singleWhere(bool test(E element), {E orElse()}) {
     int length = this.length;
-    E match = null;
+    E match;
     bool matchFound = false;
     for (int i = 0; i < length; i++) {
       E element = this[i];
@@ -346,7 +346,7 @@
   }
 
   void shuffle([Random random]) {
-    if (random == null) random = new Random();
+    random ??= new Random();
     int length = this.length;
     while (length > 1) {
       int pos = random.nextInt(length);
@@ -370,7 +370,7 @@
 
   List<E> sublist(int start, [int end]) {
     int listLength = this.length;
-    if (end == null) end = listLength;
+    end ??= listLength;
     RangeError.checkValidRange(start, end, listLength);
     int length = end - start;
     List<E> result = <E>[]..length = length;
diff --git a/sdk/lib/collection/maps.dart b/sdk/lib/collection/maps.dart
index 60f66e1..f54404f 100644
--- a/sdk/lib/collection/maps.dart
+++ b/sdk/lib/collection/maps.dart
@@ -250,7 +250,7 @@
 class _MapBaseValueIterator<K, V> implements Iterator<V> {
   final Iterator<K> _keys;
   final Map<K, V> _map;
-  V _current = null;
+  V _current;
 
   _MapBaseValueIterator(Map<K, V> map)
       : _map = map,
diff --git a/sdk/lib/collection/queue.dart b/sdk/lib/collection/queue.dart
index 30239cb..7f82357 100644
--- a/sdk/lib/collection/queue.dart
+++ b/sdk/lib/collection/queue.dart
@@ -525,7 +525,7 @@
 
 class _DoubleLinkedQueueIterator<E> implements Iterator<E> {
   _DoubleLinkedQueueSentinel<E> _sentinel;
-  _DoubleLinkedQueueEntry<E> _nextEntry = null;
+  _DoubleLinkedQueueEntry<E> _nextEntry;
   E _current;
 
   _DoubleLinkedQueueIterator(_DoubleLinkedQueueSentinel<E> sentinel)
diff --git a/sdk/lib/collection/set.dart b/sdk/lib/collection/set.dart
index 80ec9d3..0d986f9 100644
--- a/sdk/lib/collection/set.dart
+++ b/sdk/lib/collection/set.dart
@@ -245,7 +245,7 @@
   }
 
   E lastWhere(bool test(E value), {E orElse()}) {
-    E result = null;
+    E result;
     bool foundMatching = false;
     for (E element in this) {
       if (test(element)) {
@@ -259,7 +259,7 @@
   }
 
   E singleWhere(bool test(E value), {E orElse()}) {
-    E result = null;
+    E result;
     bool foundMatching = false;
     for (E element in this) {
       if (test(element)) {
diff --git a/sdk/lib/collection/splay_tree.dart b/sdk/lib/collection/splay_tree.dart
index b61f37a..5bc9a6c 100644
--- a/sdk/lib/collection/splay_tree.dart
+++ b/sdk/lib/collection/splay_tree.dart
@@ -444,7 +444,6 @@
   }
 
   bool containsValue(Object value) {
-    bool found = false;
     int initialSplayCount = _splayCount;
     bool visit(_SplayTreeMapNode node) {
       while (node != null) {
@@ -593,14 +592,14 @@
    * only the tree that has been reordered.
    */
   void _rebuildWorkList(_SplayTreeNode<K> currentNode) {
-    assert(!_workList.isEmpty);
+    assert(_workList.isNotEmpty);
     _workList.clear();
     if (currentNode == null) {
       _findLeftMostDescendent(_tree._root);
     } else {
       _tree._splay(currentNode.key);
       _findLeftMostDescendent(_tree._root.right);
-      assert(!_workList.isEmpty);
+      assert(_workList.isNotEmpty);
     }
   }
 
diff --git a/sdk/lib/convert/ascii.dart b/sdk/lib/convert/ascii.dart
index 0e07316..35105ac 100644
--- a/sdk/lib/convert/ascii.dart
+++ b/sdk/lib/convert/ascii.dart
@@ -4,58 +4,52 @@
 
 part of dart.convert;
 
-/**
- * An instance of the default implementation of the [AsciiCodec].
- *
- * This instance provides a convenient access to the most common ASCII
- * use cases.
- *
- * Examples:
- * ```dart
- * var encoded = ascii.encode("This is ASCII!");
- * var decoded = ascii.decode([0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
- *                             0x20, 0x41, 0x53, 0x43, 0x49, 0x49, 0x21]);
- * ```
- */
-const AsciiCodec ascii = const AsciiCodec();
+/// An instance of the default implementation of the [AsciiCodec].
+///
+/// This instance provides a convenient access to the most common ASCII
+/// use cases.
+///
+/// Examples:
+/// ```dart
+/// var encoded = ascii.encode("This is ASCII!");
+/// var decoded = ascii.decode([0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
+///                             0x20, 0x41, 0x53, 0x43, 0x49, 0x49, 0x21]);
+/// ```
+const AsciiCodec ascii = AsciiCodec();
 
 const int _asciiMask = 0x7F;
 
-/**
- * An [AsciiCodec] allows encoding strings as ASCII bytes
- * and decoding ASCII bytes to strings.
- */
+/// An [AsciiCodec] allows encoding strings as ASCII bytes
+/// and decoding ASCII bytes to strings.
 class AsciiCodec extends Encoding {
   final bool _allowInvalid;
-  /**
-   * Instantiates a new [AsciiCodec].
-   *
-   * If [allowInvalid] is true, the [decode] method and the converter
-   * returned by [decoder] will default to allowing invalid values.
-   * If allowing invalid values, the values will be decoded into the Unicode
-   * Replacement character (U+FFFD). If not, an exception will be thrown.
-   * Calls to the [decode] method can choose to override this default.
-   *
-   * Encoders will not accept invalid (non Latin-1) characters.
-   */
-  const AsciiCodec({bool allowInvalid: false}) : _allowInvalid = allowInvalid;
 
+  /// Instantiates a new [AsciiCodec].
+  ///
+  /// If [allowInvalid] is true, the [decode] method and the converter
+  /// returned by [decoder] will default to allowing invalid values.
+  /// If allowing invalid values, the values will be decoded into the Unicode
+  /// Replacement character (U+FFFD). If not, an exception will be thrown.
+  /// Calls to the [decode] method can choose to override this default.
+  ///
+  /// Encoders will not accept invalid (non ASCII) characters.
+  const AsciiCodec({bool allowInvalid = false}) : _allowInvalid = allowInvalid;
+
+  /// The name of this codec, "us-ascii".
   String get name => "us-ascii";
 
   Uint8List encode(String source) => encoder.convert(source);
 
-  /**
-   * Decodes the ASCII [bytes] (a list of unsigned 7-bit integers) to the
-   * corresponding string.
-   *
-   * If [bytes] contains values that are not in the range 0 .. 127, the decoder
-   * will eventually throw a [FormatException].
-   *
-   * If [allowInvalid] is not provided, it defaults to the value used to create
-   * this [AsciiCodec].
-   */
+  /// Decodes the ASCII [bytes] (a list of unsigned 7-bit integers) to the
+  /// corresponding string.
+  ///
+  /// If [bytes] contains values that are not in the range 0 .. 127, the decoder
+  /// will eventually throw a [FormatException].
+  ///
+  /// If [allowInvalid] is not provided, it defaults to the value used to create
+  /// this [AsciiCodec].
   String decode(List<int> bytes, {bool allowInvalid}) {
-    if (allowInvalid == null) allowInvalid = _allowInvalid;
+    allowInvalid ??= _allowInvalid;
     if (allowInvalid) {
       return const AsciiDecoder(allowInvalid: true).convert(bytes);
     } else {
@@ -77,56 +71,46 @@
 
   const _UnicodeSubsetEncoder(this._subsetMask);
 
-  /**
-   * Converts the [String] into a list of its code units.
-   *
-   * If [start] and [end] are provided, only the substring
-   * `string.substring(start, end)` is used as input to the conversion.
-   */
+  /// Converts the [String] into a list of its code units.
+  ///
+  /// If [start] and [end] are provided, only the substring
+  /// `string.substring(start, end)` is used as input to the conversion.
   Uint8List convert(String string, [int start = 0, int end]) {
-    int stringLength = string.length;
-    RangeError.checkValidRange(start, end, stringLength);
-    if (end == null) end = stringLength;
-    int length = end - start;
-    var result = new Uint8List(length);
-    for (int i = 0; i < length; i++) {
+    var stringLength = string.length;
+    end = RangeError.checkValidRange(start, end, stringLength);
+    var length = end - start;
+    var result = Uint8List(length);
+    for (var i = 0; i < length; i++) {
       var codeUnit = string.codeUnitAt(start + i);
       if ((codeUnit & ~_subsetMask) != 0) {
-        throw new ArgumentError("String contains invalid characters.");
+        throw ArgumentError.value(
+            string, "string", "Contains invalid characters.");
       }
       result[i] = codeUnit;
     }
     return result;
   }
 
-  /**
-   * Starts a chunked conversion.
-   *
-   * The converter works more efficiently if the given [sink] is a
-   * [ByteConversionSink].
-   */
+  /// Starts a chunked conversion.
+  ///
+  /// The converter works more efficiently if the given [sink] is a
+  /// [ByteConversionSink].
   StringConversionSink startChunkedConversion(Sink<List<int>> sink) {
-    if (sink is! ByteConversionSink) {
-      sink = new ByteConversionSink.from(sink);
-    }
-    return new _UnicodeSubsetEncoderSink(_subsetMask, sink);
+    return _UnicodeSubsetEncoderSink(_subsetMask,
+        sink is ByteConversionSink ? sink : ByteConversionSink.from(sink));
   }
 
   // Override the base-class' bind, to provide a better type.
   Stream<List<int>> bind(Stream<String> stream) => super.bind(stream);
 }
 
-/**
- * This class converts strings of only ASCII characters to bytes.
- */
+/// This class converts strings of only ASCII characters to bytes.
 class AsciiEncoder extends _UnicodeSubsetEncoder {
   const AsciiEncoder() : super(_asciiMask);
 }
 
-/**
- * This class encodes chunked strings to bytes (unsigned 8-bit
- * integers).
- */
+/// This class encodes chunked strings to bytes (unsigned 8-bit
+/// integers).
 class _UnicodeSubsetEncoderSink extends StringConversionSinkBase {
   final ByteConversionSink _sink;
   final int _subsetMask;
@@ -139,10 +123,10 @@
 
   void addSlice(String source, int start, int end, bool isLast) {
     RangeError.checkValidRange(start, end, source.length);
-    for (int i = start; i < end; i++) {
-      int codeUnit = source.codeUnitAt(i);
+    for (var i = start; i < end; i++) {
+      var codeUnit = source.codeUnitAt(i);
       if ((codeUnit & ~_subsetMask) != 0) {
-        throw new ArgumentError(
+        throw ArgumentError(
             "Source contains invalid character with code point: $codeUnit.");
       }
     }
@@ -153,70 +137,62 @@
   }
 }
 
-/**
- * This class converts Latin-1 bytes (lists of unsigned 8-bit integers)
- * to a string.
- */
+/// This class converts Latin-1 bytes (lists of unsigned 8-bit integers)
+/// to a string.
 abstract class _UnicodeSubsetDecoder extends Converter<List<int>, String> {
   final bool _allowInvalid;
   final int _subsetMask;
 
-  /**
-   * Instantiates a new decoder.
-   *
-   * The [_allowInvalid] argument defines how [convert] deals
-   * with invalid bytes.
-   *
-   * The [_subsetMask] argument is a bit mask used to define the subset
-   * of Unicode being decoded. Use [_LATIN1_MASK] for Latin-1 (8-bit) or
-   * [_asciiMask] for ASCII (7-bit).
-   *
-   * If [_allowInvalid] is `true`, [convert] replaces invalid bytes with the
-   * Unicode Replacement character `U+FFFD` (�).
-   * Otherwise it throws a [FormatException].
-   */
+  /// Instantiates a new decoder.
+  ///
+  /// The [_allowInvalid] argument defines how [convert] deals
+  /// with invalid bytes.
+  ///
+  /// The [_subsetMask] argument is a bit mask used to define the subset
+  /// of Unicode being decoded. Use [_LATIN1_MASK] for Latin-1 (8-bit) or
+  /// [_asciiMask] for ASCII (7-bit).
+  ///
+  /// If [_allowInvalid] is `true`, [convert] replaces invalid bytes with the
+  /// Unicode Replacement character `U+FFFD` (�).
+  /// Otherwise it throws a [FormatException].
   const _UnicodeSubsetDecoder(this._allowInvalid, this._subsetMask);
 
-  /**
-   * Converts the [bytes] (a list of unsigned 7- or 8-bit integers) to the
-   * corresponding string.
-   *
-   * If [start] and [end] are provided, only the sub-list of bytes from
-   * `start` to `end` (`end` not inclusive) is used as input to the conversion.
-   */
+  /// Converts the [bytes] (a list of unsigned 7- or 8-bit integers) to the
+  /// corresponding string.
+  ///
+  /// If [start] and [end] are provided, only the sub-list of bytes from
+  /// `start` to `end` (`end` not inclusive) is used as input to the conversion.
   String convert(List<int> bytes, [int start = 0, int end]) {
-    int byteCount = bytes.length;
+    var byteCount = bytes.length;
     RangeError.checkValidRange(start, end, byteCount);
-    if (end == null) end = byteCount;
+    end ??= byteCount;
 
-    for (int i = start; i < end; i++) {
-      int byte = bytes[i];
+    for (var i = start; i < end; i++) {
+      var byte = bytes[i];
       if ((byte & ~_subsetMask) != 0) {
         if (!_allowInvalid) {
-          throw new FormatException("Invalid value in input: $byte");
+          throw FormatException("Invalid value in input: $byte");
         }
         return _convertInvalid(bytes, start, end);
       }
     }
-    return new String.fromCharCodes(bytes, start, end);
+    return String.fromCharCodes(bytes, start, end);
   }
 
   String _convertInvalid(List<int> bytes, int start, int end) {
-    StringBuffer buffer = new StringBuffer();
-    for (int i = start; i < end; i++) {
-      int value = bytes[i];
+    var buffer = StringBuffer();
+    for (var i = start; i < end; i++) {
+      var value = bytes[i];
       if ((value & ~_subsetMask) != 0) value = 0xFFFD;
       buffer.writeCharCode(value);
     }
     return buffer.toString();
   }
 
-  /**
-   * Starts a chunked conversion.
-   *
-   * The converter works more efficiently if the given [sink] is a
-   * [StringConversionSink].
-   */
+  /// Starts a chunked conversion.
+  ///
+  /// The converter works more efficiently if the given [sink] is a
+  /// [StringConversionSink].
   ByteConversionSink startChunkedConversion(Sink<String> sink);
 
   // Override the base-class's bind, to provide a better type.
@@ -224,30 +200,28 @@
 }
 
 class AsciiDecoder extends _UnicodeSubsetDecoder {
-  const AsciiDecoder({bool allowInvalid: false})
+  const AsciiDecoder({bool allowInvalid = false})
       : super(allowInvalid, _asciiMask);
 
-  /**
-   * Starts a chunked conversion.
-   *
-   * The converter works more efficiently if the given [sink] is a
-   * [StringConversionSink].
-   */
+  /// Starts a chunked conversion.
+  ///
+  /// The converter works more efficiently if the given [sink] is a
+  /// [StringConversionSink].
   ByteConversionSink startChunkedConversion(Sink<String> sink) {
     StringConversionSink stringSink;
     if (sink is StringConversionSink) {
       stringSink = sink;
     } else {
-      stringSink = new StringConversionSink.from(sink);
+      stringSink = StringConversionSink.from(sink);
     }
     // TODO(lrn): Use asUtf16Sink when it becomes available. It
     // works just as well, is likely to have less decoding overhead,
     // and make adding U+FFFD easier.
     // At that time, merge this with _Latin1DecoderSink;
     if (_allowInvalid) {
-      return new _ErrorHandlingAsciiDecoderSink(stringSink.asUtf8Sink(false));
+      return _ErrorHandlingAsciiDecoderSink(stringSink.asUtf8Sink(false));
     } else {
-      return new _SimpleAsciiDecoderSink(stringSink);
+      return _SimpleAsciiDecoderSink(stringSink);
     }
   }
 }
@@ -266,7 +240,7 @@
 
   void addSlice(List<int> source, int start, int end, bool isLast) {
     RangeError.checkValidRange(start, end, source.length);
-    for (int i = start; i < end; i++) {
+    for (var i = start; i < end; i++) {
       if ((source[i] & ~_asciiMask) != 0) {
         if (i > start) _utf8Sink.addSlice(source, start, i, false);
         // Add UTF-8 encoding of U+FFFD.
@@ -291,16 +265,16 @@
   }
 
   void add(List<int> source) {
-    for (int i = 0; i < source.length; i++) {
+    for (var i = 0; i < source.length; i++) {
       if ((source[i] & ~_asciiMask) != 0) {
-        throw new FormatException("Source contains non-ASCII bytes.");
+        throw FormatException("Source contains non-ASCII bytes.");
       }
     }
-    _sink.add(new String.fromCharCodes(source));
+    _sink.add(String.fromCharCodes(source));
   }
 
   void addSlice(List<int> source, int start, int end, bool isLast) {
-    final int length = source.length;
+    final length = source.length;
     RangeError.checkValidRange(start, end, length);
     if (start < end) {
       if (start != 0 || end != length) {
diff --git a/sdk/lib/convert/base64.dart b/sdk/lib/convert/base64.dart
index a523669..1b31387 100644
--- a/sdk/lib/convert/base64.dart
+++ b/sdk/lib/convert/base64.dart
@@ -4,72 +4,60 @@
 
 part of dart.convert;
 
-/**
- * A [base64](https://tools.ietf.org/html/rfc4648) encoder and decoder.
- *
- * It encodes using the default base64 alphabet,
- * decodes using both the base64 and base64url alphabets,
- * does not allow invalid characters and requires padding.
- *
- * Examples:
- *
- *     var encoded = base64.encode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
- *                                  0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
- *     var decoded = base64.decode("YmzDpWLDpnJncsO4ZAo=");
- */
-const Base64Codec base64 = const Base64Codec();
+/// A [base64](https://tools.ietf.org/html/rfc4648) encoder and decoder.
+///
+/// It encodes using the default base64 alphabet,
+/// decodes using both the base64 and base64url alphabets,
+/// does not allow invalid characters and requires padding.
+///
+/// Examples:
+///
+///     var encoded = base64.encode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
+///                                  0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
+///     var decoded = base64.decode("YmzDpWLDpnJncsO4ZAo=");
+const Base64Codec base64 = Base64Codec();
 
-/**
- * A [base64url](https://tools.ietf.org/html/rfc4648) encoder and decoder.
- *
- * It encodes and decodes using the base64url alphabet,
- * decodes using both the base64 and base64url alphabets,
- * does not allow invalid characters and requires padding.
- *
- * Examples:
- *
- *     var encoded = base64Url.encode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
- *                                     0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
- *     var decoded = base64Url.decode("YmzDpWLDpnJncsO4ZAo=");
- */
-const Base64Codec base64Url = const Base64Codec.urlSafe();
+/// A [base64url](https://tools.ietf.org/html/rfc4648) encoder and decoder.
+///
+/// It encodes and decodes using the base64url alphabet,
+/// decodes using both the base64 and base64url alphabets,
+/// does not allow invalid characters and requires padding.
+///
+/// Examples:
+///
+///     var encoded = base64Url.encode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
+///                                     0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
+///     var decoded = base64Url.decode("YmzDpWLDpnJncsO4ZAo=");
+const Base64Codec base64Url = Base64Codec.urlSafe();
 
-/**
- * Encodes [bytes] using [base64](https://tools.ietf.org/html/rfc4648) encoding.
- *
- * Shorthand for [base64.encode].
- */
+/// Encodes [bytes] using [base64](https://tools.ietf.org/html/rfc4648) encoding.
+///
+/// Shorthand for [base64.encode].
 String base64Encode(List<int> bytes) => base64.encode(bytes);
 
-/**
- * Encodes [bytes] using [base64url](https://tools.ietf.org/html/rfc4648) encoding.
- *
- * Shorthand for [base64url.encode].
- */
+/// Encodes [bytes] using [base64url](https://tools.ietf.org/html/rfc4648) encoding.
+///
+/// Shorthand for [base64url.encode].
 String base64UrlEncode(List<int> bytes) => base64Url.encode(bytes);
 
-/**
- * Decodes [base64](https://tools.ietf.org/html/rfc4648) or [base64url](https://tools.ietf.org/html/rfc4648) encoded bytes.
- *
- * Shorthand for [base64.decode].
- */
+/// Decodes [base64](https://tools.ietf.org/html/rfc4648) or [base64url](https://tools.ietf.org/html/rfc4648) encoded bytes.
+///
+/// Shorthand for [base64.decode].
 Uint8List base64Decode(String source) => base64.decode(source);
 
 // Constants used in more than one class.
 const int _paddingChar = 0x3d; // '='.
 
-/**
- * A [base64](https://tools.ietf.org/html/rfc4648) encoder and decoder.
- *
- * A [Base64Codec] allows base64 encoding bytes into ASCII strings and
- * decoding valid encodings back to bytes.
- *
- * This implementation only handles the simplest RFC 4648 base64 and base64url
- * encodings.
- * It does not allow invalid characters when decoding and it requires,
- * and generates, padding so that the input is always a multiple of four
- * characters.
- */
+/// A [base64](https://tools.ietf.org/html/rfc4648) encoder and decoder.
+///
+/// A [Base64Codec] allows base64 encoding bytes into ASCII strings and
+/// decoding valid encodings back to bytes.
+///
+/// This implementation only handles the simplest RFC 4648 base64 and base64url
+/// encodings.
+/// It does not allow invalid characters when decoding and it requires,
+/// and generates, padding so that the input is always a multiple of four
+/// characters.
 class Base64Codec extends Codec<List<int>, String> {
   final Base64Encoder _encoder;
   const Base64Codec() : _encoder = const Base64Encoder();
@@ -79,46 +67,42 @@
 
   Base64Decoder get decoder => const Base64Decoder();
 
-  /**
-   * Decodes [encoded].
-   *
-   * The input is decoded as if by `decoder.convert`.
-   *
-   * The returned [Uint8List] contains exactly the decoded bytes,
-   * so the [Uint8List.length] is precisely the number of decoded bytes.
-   * The [Uint8List.buffer] may be larger than the decoded bytes.
-   */
+  /// Decodes [encoded].
+  ///
+  /// The input is decoded as if by `decoder.convert`.
+  ///
+  /// The returned [Uint8List] contains exactly the decoded bytes,
+  /// so the [Uint8List.length] is precisely the number of decoded bytes.
+  /// The [Uint8List.buffer] may be larger than the decoded bytes.
   Uint8List decode(String encoded) => decoder.convert(encoded);
 
-  /**
-   * Validates and normalizes the base64 encoded data in [source].
-   *
-   * Only acts on the substring from [start] to [end], with [end]
-   * defaulting to the end of the string.
-   *
-   * Normalization will:
-   * * Unescape any `%`-escapes.
-   * * Only allow valid characters (`A`-`Z`, `a`-`z`, `0`-`9`, `/` and `+`).
-   * * Normalize a `_` or `-` character to `/` or `+`.
-   * * Validate that existing padding (trailing `=` characters) is correct.
-   * * If no padding exists, add correct padding if necessary and possible.
-   * * Validate that the length is correct (a multiple of four).
-   */
+  /// Validates and normalizes the base64 encoded data in [source].
+  ///
+  /// Only acts on the substring from [start] to [end], with [end]
+  /// defaulting to the end of the string.
+  ///
+  /// Normalization will:
+  /// * Unescape any `%`-escapes.
+  /// * Only allow valid characters (`A`-`Z`, `a`-`z`, `0`-`9`, `/` and `+`).
+  /// * Normalize a `_` or `-` character to `/` or `+`.
+  /// * Validate that existing padding (trailing `=` characters) is correct.
+  /// * If no padding exists, add correct padding if necessary and possible.
+  /// * Validate that the length is correct (a multiple of four).
   String normalize(String source, [int start = 0, int end]) {
     end = RangeError.checkValidRange(start, end, source.length);
-    const int percent = 0x25;
-    const int equals = 0x3d;
-    StringBuffer buffer = null;
-    int sliceStart = start;
+    const percent = 0x25;
+    const equals = 0x3d;
+    StringBuffer buffer;
+    var sliceStart = start;
     var alphabet = _Base64Encoder._base64Alphabet;
     var inverseAlphabet = _Base64Decoder._inverseAlphabet;
-    int firstPadding = -1;
-    int firstPaddingSourceIndex = -1;
-    int paddingCount = 0;
-    for (int i = start; i < end;) {
-      int sliceEnd = i;
-      int char = source.codeUnitAt(i++);
-      int originalChar = char;
+    var firstPadding = -1;
+    var firstPaddingSourceIndex = -1;
+    var paddingCount = 0;
+    for (var i = start; i < end;) {
+      var sliceEnd = i;
+      var char = source.codeUnitAt(i++);
+      var originalChar = char;
       // Normalize char, keep originalChar to see if it matches the source.
       if (char == percent) {
         if (i + 2 <= end) {
@@ -135,7 +119,7 @@
       }
       // If char is negative here, hex-decoding failed in some way.
       if (0 <= char && char <= 127) {
-        int value = inverseAlphabet[char];
+        var value = inverseAlphabet[char];
         if (value >= 0) {
           char = alphabet.codeUnitAt(value);
           if (char == originalChar) continue;
@@ -151,14 +135,14 @@
           if (originalChar == equals) continue;
         }
         if (value != _Base64Decoder._invalid) {
-          buffer ??= new StringBuffer();
+          buffer ??= StringBuffer();
           buffer.write(source.substring(sliceStart, sliceEnd));
           buffer.writeCharCode(char);
           sliceStart = i;
           continue;
         }
       }
-      throw new FormatException("Invalid base64 data", source, sliceEnd);
+      throw FormatException("Invalid base64 data", source, sliceEnd);
     }
     if (buffer != null) {
       buffer.write(source.substring(sliceStart, end));
@@ -170,11 +154,10 @@
             paddingCount, buffer.length);
       } else {
         // Length of last chunk (1-4 chars) in the encoding.
-        int endLength = ((buffer.length - 1) % 4) + 1;
+        var endLength = ((buffer.length - 1) % 4) + 1;
         if (endLength == 1) {
           // The data must have length 0, 2 or 3 modulo 4.
-          throw new FormatException(
-              "Invalid base64 encoding length ", source, end);
+          throw FormatException("Invalid base64 encoding length ", source, end);
         }
         while (endLength < 4) {
           buffer.write("=");
@@ -184,17 +167,16 @@
       return source.replaceRange(start, end, buffer.toString());
     }
     // Original was already normalized, only check padding.
-    int length = end - start;
+    var length = end - start;
     if (firstPadding >= 0) {
       _checkPadding(source, firstPaddingSourceIndex, end, firstPadding,
           paddingCount, length);
     } else {
       // No padding given, so add some if needed it.
-      int endLength = length % 4;
+      var endLength = length % 4;
       if (endLength == 1) {
         // The data must have length 0, 2 or 3 modulo 4.
-        throw new FormatException(
-            "Invalid base64 encoding length ", source, end);
+        throw FormatException("Invalid base64 encoding length ", source, end);
       }
       if (endLength > 1) {
         // There is no "insertAt" on String, but this works as well.
@@ -207,18 +189,18 @@
   static void _checkPadding(String source, int sourceIndex, int sourceEnd,
       int firstPadding, int paddingCount, int length) {
     if (length % 4 != 0) {
-      throw new FormatException(
+      throw FormatException(
           "Invalid base64 padding, padded length must be multiple of four, "
           "is $length",
           source,
           sourceEnd);
     }
     if (firstPadding + paddingCount != length) {
-      throw new FormatException(
+      throw FormatException(
           "Invalid base64 padding, '=' not at the end", source, sourceIndex);
     }
     if (paddingCount > 2) {
-      throw new FormatException(
+      throw FormatException(
           "Invalid base64 padding, more than two '=' characters",
           source,
           sourceIndex);
@@ -230,13 +212,11 @@
 // Encoder
 // ------------------------------------------------------------------------
 
-/**
- * Base64 and base64url encoding converter.
- *
- * Encodes lists of bytes using base64 or base64url encoding.
- *
- * The results are ASCII strings using a restricted alphabet.
- */
+/// Base64 and base64url encoding converter.
+///
+/// Encodes lists of bytes using base64 or base64url encoding.
+///
+/// The results are ASCII strings using a restricted alphabet.
 class Base64Encoder extends Converter<List<int>, String> {
   final bool _urlSafe;
 
@@ -245,95 +225,87 @@
 
   String convert(List<int> input) {
     if (input.isEmpty) return "";
-    var encoder = new _Base64Encoder(_urlSafe);
-    Uint8List buffer = encoder.encode(input, 0, input.length, true);
-    return new String.fromCharCodes(buffer);
+    var encoder = _Base64Encoder(_urlSafe);
+    var buffer = encoder.encode(input, 0, input.length, true);
+    return String.fromCharCodes(buffer);
   }
 
   ByteConversionSink startChunkedConversion(Sink<String> sink) {
     if (sink is StringConversionSink) {
-      return new _Utf8Base64EncoderSink(sink.asUtf8Sink(false), _urlSafe);
+      return _Utf8Base64EncoderSink(sink.asUtf8Sink(false), _urlSafe);
     }
-    return new _AsciiBase64EncoderSink(sink, _urlSafe);
+    return _AsciiBase64EncoderSink(sink, _urlSafe);
   }
 }
 
-/**
- * Helper class for encoding bytes to base64.
- */
+/// Helper class for encoding bytes to base64.
 class _Base64Encoder {
-  /** The RFC 4648 base64 encoding alphabet. */
+  /// The RFC 4648 base64 encoding alphabet.
   static const String _base64Alphabet =
       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
-  /** The RFC 4648 base64url encoding alphabet. */
+  /// The RFC 4648 base64url encoding alphabet.
   static const String _base64UrlAlphabet =
       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
 
-  /** Shift-count to extract the values stored in [_state]. */
+  /// Shift-count to extract the values stored in [_state].
   static const int _valueShift = 2;
 
-  /** Mask to extract the count value stored in [_state]. */
+  /// Mask to extract the count value stored in [_state].
   static const int _countMask = 3;
 
   static const int _sixBitMask = 0x3F;
 
-  /**
-   * Intermediate state between chunks.
-   *
-   * Encoding handles three bytes at a time.
-   * If fewer than three bytes has been seen, this value encodes
-   * the number of bytes seen (0, 1 or 2) and their values.
-   */
+  /// Intermediate state between chunks.
+  ///
+  /// Encoding handles three bytes at a time.
+  /// If fewer than three bytes has been seen, this value encodes
+  /// the number of bytes seen (0, 1 or 2) and their values.
   int _state = 0;
 
-  /** Alphabet used for encoding. */
+  /// Alphabet used for encoding.
   final String _alphabet;
 
   _Base64Encoder(bool urlSafe)
       : _alphabet = urlSafe ? _base64UrlAlphabet : _base64Alphabet;
 
-  /** Encode count and bits into a value to be stored in [_state]. */
+  /// Encode count and bits into a value to be stored in [_state].
   static int _encodeState(int count, int bits) {
     assert(count <= _countMask);
     return bits << _valueShift | count;
   }
 
-  /** Extract bits from encoded state. */
+  /// Extract bits from encoded state.
   static int _stateBits(int state) => state >> _valueShift;
 
-  /** Extract count from encoded state. */
+  /// Extract count from encoded state.
   static int _stateCount(int state) => state & _countMask;
 
-  /**
-   * Create a [Uint8List] with the provided length.
-   */
-  Uint8List createBuffer(int bufferLength) => new Uint8List(bufferLength);
+  /// Create a [Uint8List] with the provided length.
+  Uint8List createBuffer(int bufferLength) => Uint8List(bufferLength);
 
-  /**
-   * Encode [bytes] from [start] to [end] and the bits in [_state].
-   *
-   * Returns a [Uint8List] of the ASCII codes of the encoded data.
-   *
-   * If the input, including left over [_state] from earlier encodings,
-   * are not a multiple of three bytes, then the partial state is stored
-   * back into [_state].
-   * If [isLast] is true, partial state is encoded in the output instead,
-   * with the necessary padding.
-   *
-   * Returns `null` if there is no output.
-   */
+  /// Encode [bytes] from [start] to [end] and the bits in [_state].
+  ///
+  /// Returns a [Uint8List] of the ASCII codes of the encoded data.
+  ///
+  /// If the input, including left over [_state] from earlier encodings,
+  /// are not a multiple of three bytes, then the partial state is stored
+  /// back into [_state].
+  /// If [isLast] is true, partial state is encoded in the output instead,
+  /// with the necessary padding.
+  ///
+  /// Returns `null` if there is no output.
   Uint8List encode(List<int> bytes, int start, int end, bool isLast) {
     assert(0 <= start);
     assert(start <= end);
     assert(bytes == null || end <= bytes.length);
-    int length = end - start;
+    var length = end - start;
 
-    int count = _stateCount(_state);
-    int byteCount = (count + length);
-    int fullChunks = byteCount ~/ 3;
-    int partialChunkLength = byteCount - fullChunks * 3;
-    int bufferLength = fullChunks * 4;
+    var count = _stateCount(_state);
+    var byteCount = (count + length);
+    var fullChunks = byteCount ~/ 3;
+    var partialChunkLength = byteCount - fullChunks * 3;
+    var bufferLength = fullChunks * 4;
     if (isLast && partialChunkLength > 0) {
       bufferLength += 4; // Room for padding.
     }
@@ -348,16 +320,16 @@
 
   static int encodeChunk(String alphabet, List<int> bytes, int start, int end,
       bool isLast, Uint8List output, int outputIndex, int state) {
-    int bits = _stateBits(state);
+    var bits = _stateBits(state);
     // Count number of missing bytes in three-byte chunk.
-    int expectedChars = 3 - _stateCount(state);
+    var expectedChars = 3 - _stateCount(state);
 
     // The input must be a list of bytes (integers in the range 0..255).
     // The value of `byteOr` will be the bitwise or of all the values in
     // `bytes` and a later check will validate that they were all valid bytes.
-    int byteOr = 0;
-    for (int i = start; i < end; i++) {
-      int byte = bytes[i];
+    var byteOr = 0;
+    for (var i = start; i < end; i++) {
+      var byte = bytes[i];
       byteOr |= byte;
       bits = ((bits << 8) | byte) & 0xFFFFFF; // Never store more than 24 bits.
       expectedChars--;
@@ -379,22 +351,20 @@
     }
 
     // There was an invalid byte value somewhere in the input - find it!
-    int i = start;
+    var i = start;
     while (i < end) {
-      int byte = bytes[i];
+      var byte = bytes[i];
       if (byte < 0 || byte > 255) break;
       i++;
     }
-    throw new ArgumentError.value(
+    throw ArgumentError.value(
         bytes, "Not a byte value at index $i: 0x${bytes[i].toRadixString(16)}");
   }
 
-  /**
-   * Writes a final encoded four-character chunk.
-   *
-   * Only used when the [_state] contains a partial (1 or 2 byte)
-   * input.
-   */
+  /// Writes a final encoded four-character chunk.
+  ///
+  /// Only used when the [_state] contains a partial (1 or 2 byte)
+  /// input.
   static void writeFinalChunk(
       String alphabet, Uint8List output, int outputIndex, int count, int bits) {
     assert(count > 0);
@@ -414,22 +384,20 @@
 }
 
 class _BufferCachingBase64Encoder extends _Base64Encoder {
-  /**
-   * Reused buffer.
-   *
-   * When the buffer isn't released to the sink, only used to create another
-   * value (a string), the buffer can be reused between chunks.
-   */
+  /// Reused buffer.
+  ///
+  /// When the buffer isn't released to the sink, only used to create another
+  /// value (a string), the buffer can be reused between chunks.
   Uint8List bufferCache;
 
   _BufferCachingBase64Encoder(bool urlSafe) : super(urlSafe);
 
   Uint8List createBuffer(int bufferLength) {
     if (bufferCache == null || bufferCache.length < bufferLength) {
-      bufferCache = new Uint8List(bufferLength);
+      bufferCache = Uint8List(bufferLength);
     }
     // Return a view of the buffer, so it has the requested length.
-    return new Uint8List.view(bufferCache.buffer, 0, bufferLength);
+    return Uint8List.view(bufferCache.buffer, 0, bufferLength);
   }
 }
 
@@ -443,7 +411,7 @@
   }
 
   void addSlice(List<int> source, int start, int end, bool isLast) {
-    if (end == null) throw new ArgumentError.notNull("end");
+    if (end == null) throw ArgumentError.notNull("end");
     RangeError.checkValidRange(start, end, source.length);
     _add(source, start, end, isLast);
   }
@@ -456,12 +424,12 @@
   final _Base64Encoder _encoder;
 
   _AsciiBase64EncoderSink(this._sink, bool urlSafe)
-      : _encoder = new _BufferCachingBase64Encoder(urlSafe);
+      : _encoder = _BufferCachingBase64Encoder(urlSafe);
 
   void _add(List<int> source, int start, int end, bool isLast) {
-    Uint8List buffer = _encoder.encode(source, start, end, isLast);
+    var buffer = _encoder.encode(source, start, end, isLast);
     if (buffer != null) {
-      String string = new String.fromCharCodes(buffer);
+      var string = String.fromCharCodes(buffer);
       _sink.add(string);
     }
     if (isLast) {
@@ -475,10 +443,10 @@
   final _Base64Encoder _encoder;
 
   _Utf8Base64EncoderSink(this._sink, bool urlSafe)
-      : _encoder = new _Base64Encoder(urlSafe);
+      : _encoder = _Base64Encoder(urlSafe);
 
   void _add(List<int> source, int start, int end, bool isLast) {
-    Uint8List buffer = _encoder.encode(source, start, end, isLast);
+    var buffer = _encoder.encode(source, start, end, isLast);
     if (buffer != null) {
       _sink.addSlice(buffer, 0, buffer.length, isLast);
     }
@@ -489,72 +457,64 @@
 // Decoder
 // ------------------------------------------------------------------------
 
-/**
- * Decoder for base64 encoded data.
- *
- * This decoder accepts both base64 and base64url ("url-safe") encodings.
- *
- * The encoding is required to be properly padded.
- */
+/// Decoder for base64 encoded data.
+///
+/// This decoder accepts both base64 and base64url ("url-safe") encodings.
+///
+/// The encoding is required to be properly padded.
 class Base64Decoder extends Converter<String, List<int>> {
   const Base64Decoder();
 
-  /**
-   * Decodes the characters of [input] from [start] to [end] as base64.
-   *
-   * If [start] is omitted, it defaults to the start of [input].
-   * If [end] is omitted, it defaults to the end of [input].
-   *
-   * The returned [Uint8List] contains exactly the decoded bytes,
-   * so the [Uint8List.length] is precisely the number of decoded bytes.
-   * The [Uint8List.buffer] may be larger than the decoded bytes.
-   */
+  /// Decodes the characters of [input] from [start] to [end] as base64.
+  ///
+  /// If [start] is omitted, it defaults to the start of [input].
+  /// If [end] is omitted, it defaults to the end of [input].
+  ///
+  /// The returned [Uint8List] contains exactly the decoded bytes,
+  /// so the [Uint8List.length] is precisely the number of decoded bytes.
+  /// The [Uint8List.buffer] may be larger than the decoded bytes.
   Uint8List convert(String input, [int start = 0, int end]) {
     end = RangeError.checkValidRange(start, end, input.length);
-    if (start == end) return new Uint8List(0);
-    var decoder = new _Base64Decoder();
-    Uint8List buffer = decoder.decode(input, start, end);
+    if (start == end) return Uint8List(0);
+    var decoder = _Base64Decoder();
+    var buffer = decoder.decode(input, start, end);
     decoder.close(input, end);
     return buffer;
   }
 
   StringConversionSink startChunkedConversion(Sink<List<int>> sink) {
-    return new _Base64DecoderSink(sink);
+    return _Base64DecoderSink(sink);
   }
 }
 
-/**
- * Helper class implementing base64 decoding with intermediate state.
- */
+/// Helper class implementing base64 decoding with intermediate state.
 class _Base64Decoder {
-  /** Shift-count to extract the values stored in [_state]. */
+  /// Shift-count to extract the values stored in [_state].
   static const int _valueShift = 2;
 
-  /** Mask to extract the count value stored in [_state]. */
+  /// Mask to extract the count value stored in [_state].
   static const int _countMask = 3;
 
-  /** Invalid character in decoding table. */
+  /// Invalid character in decoding table.
   static const int _invalid = -2;
 
-  /** Padding character in decoding table. */
+  /// Padding character in decoding table.
   static const int _padding = -1;
 
   // Shorthands to make the table more readable.
   static const int __ = _invalid;
   static const int _p = _padding;
 
-  /**
-   * Mapping from ASCII characters to their index in the base64 alphabet.
-   *
-   * Uses [_invalid] for invalid indices and [_padding] for the padding
-   * character.
-   *
-   * Accepts the "URL-safe" alphabet as well (`-` and `_` are the
-   * 62nd and 63rd alphabet characters), and considers `%` a padding
-   * character, which must then be followed by `3D`, the percent-escape
-   * for `=`.
-   */
-  static final List<int> _inverseAlphabet = new Int8List.fromList([
+  /// Mapping from ASCII characters to their index in the base64 alphabet.
+  ///
+  /// Uses [_invalid] for invalid indices and [_padding] for the padding
+  /// character.
+  ///
+  /// Accepts the "URL-safe" alphabet as well (`-` and `_` are the
+  /// 62nd and 63rd alphabet characters), and considers `%` a padding
+  /// character, which must then be followed by `3D`, the percent-escape
+  /// for `=`.
+  static final List<int> _inverseAlphabet = Int8List.fromList([
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, //
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, //
     __, __, __, __, __, _p, __, __, __, __, __, 62, __, 62, __, 63, //
@@ -570,63 +530,51 @@
   static const int _char_3 = 0x33; // '3'.
   static const int _char_d = 0x64; // 'd'.
 
-  /**
-   * Maintains the intermediate state of a partly-decoded input.
-   *
-   * Base64 is decoded in chunks of four characters. If a chunk does not
-   * contain a full block, the decoded bits (six per character) of the
-   * available characters are stored in [_state] until the next call to
-   * [_decode] or [_close].
-   *
-   * If no padding has been seen, the value is
-   *   `numberOfCharactersSeen | (decodedBits << 2)`
-   * where `numberOfCharactersSeen` is between 0 and 3 and decoded bits
-   * contains six bits per seen character.
-   *
-   * If padding has been seen the value is negative. It's the bitwise negation
-   * of the number of remaining allowed padding characters (always ~0 or ~1).
-   *
-   * A state of `0` or `~0` are valid places to end decoding, all other values
-   * mean that a four-character block has not been completed.
-   */
+  /// Maintains the intermediate state of a partly-decoded input.
+  ///
+  /// Base64 is decoded in chunks of four characters. If a chunk does not
+  /// contain a full block, the decoded bits (six per character) of the
+  /// available characters are stored in [_state] until the next call to
+  /// [_decode] or [_close].
+  ///
+  /// If no padding has been seen, the value is
+  ///   `numberOfCharactersSeen | (decodedBits << 2)`
+  /// where `numberOfCharactersSeen` is between 0 and 3 and decoded bits
+  /// contains six bits per seen character.
+  ///
+  /// If padding has been seen the value is negative. It's the bitwise negation
+  /// of the number of remaining allowed padding characters (always ~0 or ~1).
+  ///
+  /// A state of `0` or `~0` are valid places to end decoding, all other values
+  /// mean that a four-character block has not been completed.
   int _state = 0;
 
-  /**
-   * Encodes [count] and [bits] as a value to be stored in [_state].
-   */
+  /// Encodes [count] and [bits] as a value to be stored in [_state].
   static int _encodeCharacterState(int count, int bits) {
     assert(count == (count & _countMask));
     return (bits << _valueShift | count);
   }
 
-  /**
-   * Extracts count from a [_state] value.
-   */
+  /// Extracts count from a [_state] value.
   static int _stateCount(int state) {
     assert(state >= 0);
     return state & _countMask;
   }
 
-  /**
-   * Extracts value bits from a [_state] value.
-   */
+  /// Extracts value bits from a [_state] value.
   static int _stateBits(int state) {
     assert(state >= 0);
     return state >> _valueShift;
   }
 
-  /**
-   * Encodes a number of expected padding characters to be stored in [_state].
-   */
+  /// Encodes a number of expected padding characters to be stored in [_state].
   static int _encodePaddingState(int expectedPadding) {
     assert(expectedPadding >= 0);
     assert(expectedPadding <= 5);
     return -expectedPadding - 1; // ~expectedPadding adapted to dart2js.
   }
 
-  /**
-   * Extracts expected padding character count from a [_state] value.
-   */
+  /// Extracts expected padding character count from a [_state] value.
   static int _statePadding(int state) {
     assert(state < 0);
     return -state - 1; // ~state adapted to dart2js.
@@ -634,13 +582,11 @@
 
   static bool _hasSeenPadding(int state) => state < 0;
 
-  /**
-   * Decodes [input] from [start] to [end].
-   *
-   * Returns a [Uint8List] with the decoded bytes.
-   * If a previous call had an incomplete four-character block, the bits from
-   * those are included in decoding
-   */
+  /// Decodes [input] from [start] to [end].
+  ///
+  /// Returns a [Uint8List] with the decoded bytes.
+  /// If a previous call had an incomplete four-character block, the bits from
+  /// those are included in decoding
   Uint8List decode(String input, int start, int end) {
     assert(0 <= start);
     assert(start <= end);
@@ -649,50 +595,48 @@
       _state = _checkPadding(input, start, end, _state);
       return null;
     }
-    if (start == end) return new Uint8List(0);
-    Uint8List buffer = _allocateBuffer(input, start, end, _state);
+    if (start == end) return Uint8List(0);
+    var buffer = _allocateBuffer(input, start, end, _state);
     _state = decodeChunk(input, start, end, buffer, 0, _state);
     return buffer;
   }
 
-  /** Checks that [_state] represents a valid decoding. */
+  /// Checks that [_state] represents a valid decoding.
   void close(String input, int end) {
     if (_state < _encodePaddingState(0)) {
-      throw new FormatException("Missing padding character", input, end);
+      throw FormatException("Missing padding character", input, end);
     }
     if (_state > 0) {
-      throw new FormatException(
+      throw FormatException(
           "Invalid length, must be multiple of four", input, end);
     }
     _state = _encodePaddingState(0);
   }
 
-  /**
-   * Decodes [input] from [start] to [end].
-   *
-   * Includes the state returned by a previous call in the decoding.
-   * Writes the decoding to [output] at [outIndex], and there must
-   * be room in the output.
-   */
+  /// Decodes [input] from [start] to [end].
+  ///
+  /// Includes the state returned by a previous call in the decoding.
+  /// Writes the decoding to [output] at [outIndex], and there must
+  /// be room in the output.
   static int decodeChunk(String input, int start, int end, Uint8List output,
       int outIndex, int state) {
     assert(!_hasSeenPadding(state));
-    const int asciiMask = 127;
-    const int asciiMax = 127;
-    const int eightBitMask = 0xFF;
-    const int bitsPerCharacter = 6;
+    const asciiMask = 127;
+    const asciiMax = 127;
+    const eightBitMask = 0xFF;
+    const bitsPerCharacter = 6;
 
-    int bits = _stateBits(state);
-    int count = _stateCount(state);
+    var bits = _stateBits(state);
+    var count = _stateCount(state);
     // String contents should be all ASCII.
     // Instead of checking for each character, we collect the bitwise-or of
     // all the characters in `charOr` and later validate that all characters
     // were ASCII.
-    int charOr = 0;
-    for (int i = start; i < end; i++) {
+    var charOr = 0;
+    for (var i = start; i < end; i++) {
       var char = input.codeUnitAt(i);
       charOr |= char;
-      int code = _inverseAlphabet[char & asciiMask];
+      var code = _inverseAlphabet[char & asciiMask];
       if (code >= 0) {
         bits = ((bits << bitsPerCharacter) | code) & 0xFFFFFF;
         count = (count + 1) & 3;
@@ -708,15 +652,13 @@
         if (charOr < 0 || charOr > asciiMax) break;
         if (count == 3) {
           if ((bits & 0x03) != 0) {
-            throw new FormatException(
-                "Invalid encoding before padding", input, i);
+            throw FormatException("Invalid encoding before padding", input, i);
           }
           output[outIndex++] = bits >> 10;
           output[outIndex++] = bits >> 2;
         } else {
           if ((bits & 0x0F) != 0) {
-            throw new FormatException(
-                "Invalid encoding before padding", input, i);
+            throw FormatException("Invalid encoding before padding", input, i);
           }
           output[outIndex++] = bits >> 4;
         }
@@ -725,12 +667,12 @@
         //
         // Expect either zero or one padding depending on count (2 or 3),
         // plus two more characters if the code was `%` (a partial padding).
-        int expectedPadding = (3 - count) * 3;
+        var expectedPadding = (3 - count) * 3;
         if (char == _char_percent) expectedPadding += 2;
         state = _encodePaddingState(expectedPadding);
         return _checkPadding(input, i + 1, end, state);
       }
-      throw new FormatException("Invalid character", input, i);
+      throw FormatException("Invalid character", input, i);
     }
     if (charOr >= 0 && charOr <= asciiMax) {
       return _encodeCharacterState(count, bits);
@@ -738,58 +680,54 @@
     // There is an invalid (non-ASCII) character in the input.
     int i;
     for (i = start; i < end; i++) {
-      int char = input.codeUnitAt(i);
+      var char = input.codeUnitAt(i);
       if (char < 0 || char > asciiMax) break;
     }
-    throw new FormatException("Invalid character", input, i);
+    throw FormatException("Invalid character", input, i);
   }
 
-  /**
-   * Allocates a buffer with room for the decoding of a substring of [input].
-   *
-   * Includes room for the characters in [state], and handles padding correctly.
-   */
+  /// Allocates a buffer with room for the decoding of a substring of [input].
+  ///
+  /// Includes room for the characters in [state], and handles padding correctly.
   static Uint8List _allocateBuffer(
       String input, int start, int end, int state) {
     assert(state >= 0);
-    int paddingStart = _trimPaddingChars(input, start, end);
-    int length = _stateCount(state) + (paddingStart - start);
+    var paddingStart = _trimPaddingChars(input, start, end);
+    var length = _stateCount(state) + (paddingStart - start);
     // Three bytes per full four bytes in the input.
-    int bufferLength = (length >> 2) * 3;
+    var bufferLength = (length >> 2) * 3;
     // If padding was seen, then this is the last chunk, and the final partial
     // chunk should be decoded too.
-    int remainderLength = length & 3;
+    var remainderLength = length & 3;
     if (remainderLength != 0 && paddingStart < end) {
       bufferLength += remainderLength - 1;
     }
-    if (bufferLength > 0) return new Uint8List(bufferLength);
+    if (bufferLength > 0) return Uint8List(bufferLength);
     // If the input plus state is less than four characters, and it's not
     // at the end of input, no buffer is needed.
     return null;
   }
 
-  /**
-   * Returns the position of the start of padding at the end of the input.
-   *
-   * Returns the end of input if there is no padding.
-   *
-   * This is used to ensure that the decoding buffer has the exact size
-   * it needs when input is valid, and at least enough bytes to reach the error
-   * when input is invalid.
-   *
-   * Never count more than two padding sequences since any more than that
-   * will raise an error anyway, and we only care about being precise for
-   * successful conversions.
-   */
+  /// Returns the position of the start of padding at the end of the input.
+  ///
+  /// Returns the end of input if there is no padding.
+  ///
+  /// This is used to ensure that the decoding buffer has the exact size
+  /// it needs when input is valid, and at least enough bytes to reach the error
+  /// when input is invalid.
+  ///
+  /// Never count more than two padding sequences since any more than that
+  /// will raise an error anyway, and we only care about being precise for
+  /// successful conversions.
   static int _trimPaddingChars(String input, int start, int end) {
     // This may count '%=' as two paddings. That's ok, it will err later,
     // but the buffer will be large enough to reach the error.
-    int padding = 0;
-    int index = end;
-    int newEnd = end;
+    var padding = 0;
+    var index = end;
+    var newEnd = end;
     while (index > start && padding < 2) {
       index--;
-      int char = input.codeUnitAt(index);
+      var char = input.codeUnitAt(index);
       if (char == _paddingChar) {
         padding++;
         newEnd = index;
@@ -815,34 +753,32 @@
     return newEnd;
   }
 
-  /**
-   * Check that the remainder of the string is valid padding.
-   *
-   * Valid padding is a correct number (0, 1 or 2) of `=` characters
-   * or `%3D` sequences depending on the number of preceding base64 characters.
-   * The [state] parameter encodes which padding continuations are allowed
-   * as the number of expected characters. That number is the number of
-   * expected padding characters times 3 minus the number of padding characters
-   * seen so far, where `=` counts as 3 counts as three characters,
-   * and the padding sequence `%3D` counts as one character per character.
-   *
-   * The number of missing characters is always between 0 and 5 because we
-   * only call this function after having seen at least one `=` or `%`
-   * character.
-   * If the number of missing characters is not 3 or 0, we have seen (at least)
-   * a `%` character and expects the rest of the `%3D` sequence, and a `=` is
-   * not allowed. When missing 3 characters, either `=` or `%` is allowed.
-   *
-   * When the value is 0, no more padding (or any other character) is allowed.
-   */
+  /// Check that the remainder of the string is valid padding.
+  ///
+  /// Valid padding is a correct number (0, 1 or 2) of `=` characters
+  /// or `%3D` sequences depending on the number of preceding base64 characters.
+  /// The [state] parameter encodes which padding continuations are allowed
+  /// as the number of expected characters. That number is the number of
+  /// expected padding characters times 3 minus the number of padding characters
+  /// seen so far, where `=` counts as 3 counts as three characters,
+  /// and the padding sequence `%3D` counts as one character per character.
+  ///
+  /// The number of missing characters is always between 0 and 5 because we
+  /// only call this function after having seen at least one `=` or `%`
+  /// character.
+  /// If the number of missing characters is not 3 or 0, we have seen (at least)
+  /// a `%` character and expects the rest of the `%3D` sequence, and a `=` is
+  /// not allowed. When missing 3 characters, either `=` or `%` is allowed.
+  ///
+  /// When the value is 0, no more padding (or any other character) is allowed.
   static int _checkPadding(String input, int start, int end, int state) {
     assert(_hasSeenPadding(state));
     if (start == end) return state;
-    int expectedPadding = _statePadding(state);
+    var expectedPadding = _statePadding(state);
     assert(expectedPadding >= 0);
     assert(expectedPadding < 6);
     while (expectedPadding > 0) {
-      int char = input.codeUnitAt(start);
+      var char = input.codeUnitAt(start);
       if (expectedPadding == 3) {
         if (char == _paddingChar) {
           expectedPadding -= 3;
@@ -859,7 +795,7 @@
         }
       }
       // Partial padding means we have seen part of a "%3D" escape.
-      int expectedPartialPadding = expectedPadding;
+      var expectedPartialPadding = expectedPadding;
       if (expectedPartialPadding > 3) expectedPartialPadding -= 3;
       if (expectedPartialPadding == 2) {
         // Expects '3'
@@ -876,22 +812,22 @@
       if (start == end) break;
     }
     if (start != end) {
-      throw new FormatException("Invalid padding character", input, start);
+      throw FormatException("Invalid padding character", input, start);
     }
     return _encodePaddingState(expectedPadding);
   }
 }
 
 class _Base64DecoderSink extends StringConversionSinkBase {
-  /** Output sink */
+  /// Output sink
   final Sink<List<int>> _sink;
-  final _Base64Decoder _decoder = new _Base64Decoder();
+  final _Base64Decoder _decoder = _Base64Decoder();
 
   _Base64DecoderSink(this._sink);
 
   void add(String string) {
     if (string.isEmpty) return;
-    Uint8List buffer = _decoder.decode(string, 0, string.length);
+    var buffer = _decoder.decode(string, 0, string.length);
     if (buffer != null) _sink.add(buffer);
   }
 
@@ -903,7 +839,7 @@
   void addSlice(String string, int start, int end, bool isLast) {
     end = RangeError.checkValidRange(start, end, string.length);
     if (start == end) return;
-    Uint8List buffer = _decoder.decode(string, start, end);
+    var buffer = _decoder.decode(string, start, end);
     if (buffer != null) _sink.add(buffer);
     if (isLast) {
       _decoder.close(string, end);
diff --git a/sdk/lib/convert/byte_conversion.dart b/sdk/lib/convert/byte_conversion.dart
index aaeac3e..1071b90 100644
--- a/sdk/lib/convert/byte_conversion.dart
+++ b/sdk/lib/convert/byte_conversion.dart
@@ -4,43 +4,37 @@
 
 part of dart.convert;
 
-/**
- * The [ByteConversionSink] provides an interface for converters to
- * efficiently transmit byte data.
- *
- * Instead of limiting the interface to one non-chunked list of bytes it
- * accepts its input in chunks (themselves being lists of bytes).
- *
- * This abstract class will likely get more methods over time. Implementers are
- * urged to extend or mix in [ByteConversionSinkBase] to ensure that their
- * class covers the newly added methods.
- */
+/// The [ByteConversionSink] provides an interface for converters to
+/// efficiently transmit byte data.
+///
+/// Instead of limiting the interface to one non-chunked list of bytes it
+/// accepts its input in chunks (themselves being lists of bytes).
+///
+/// This abstract class will likely get more methods over time. Implementers are
+/// urged to extend or mix in [ByteConversionSinkBase] to ensure that their
+/// class covers the newly added methods.
 abstract class ByteConversionSink extends ChunkedConversionSink<List<int>> {
   ByteConversionSink();
   factory ByteConversionSink.withCallback(
       void callback(List<int> accumulated)) = _ByteCallbackSink;
   factory ByteConversionSink.from(Sink<List<int>> sink) = _ByteAdapterSink;
 
-  /**
-   * Adds the next [chunk] to `this`.
-   *
-   * Adds the bytes defined by [start] and [end]-exclusive to `this`.
-   *
-   * If [isLast] is `true` closes `this`.
-   *
-   * Contrary to `add` the given [chunk] must not be held onto. Once the method
-   * returns, it is safe to overwrite the data in it.
-   */
+  /// Adds the next [chunk] to `this`.
+  ///
+  /// Adds the bytes defined by [start] and [end]-exclusive to `this`.
+  ///
+  /// If [isLast] is `true` closes `this`.
+  ///
+  /// Contrary to `add` the given [chunk] must not be held onto. Once the method
+  /// returns, it is safe to overwrite the data in it.
   void addSlice(List<int> chunk, int start, int end, bool isLast);
 
   // TODO(floitsch): add more methods:
   // - iterateBytes.
 }
 
-/**
- * This class provides a base-class for converters that need to accept byte
- * inputs.
- */
+/// This class provides a base-class for converters that need to accept byte
+/// inputs.
 abstract class ByteConversionSinkBase extends ByteConversionSink {
   void add(List<int> chunk);
   void close();
@@ -51,12 +45,10 @@
   }
 }
 
-/**
- * This class adapts a simple [Sink] to a [ByteConversionSink].
- *
- * All additional methods of the [ByteConversionSink] (compared to the
- * ChunkedConversionSink) are redirected to the `add` method.
- */
+/// This class adapts a simple [Sink] to a [ByteConversionSink].
+///
+/// All additional methods of the [ByteConversionSink] (compared to the
+/// ChunkedConversionSink) are redirected to the `add` method.
 class _ByteAdapterSink extends ByteConversionSinkBase {
   final Sink<List<int>> _sink;
 
@@ -71,29 +63,27 @@
   }
 }
 
-/**
- * This class accumulates all chunks into one list of bytes
- * and invokes a callback when the sink is closed.
- *
- * This class can be used to terminate a chunked conversion.
- */
+/// This class accumulates all chunks into one list of bytes
+/// and invokes a callback when the sink is closed.
+///
+/// This class can be used to terminate a chunked conversion.
 class _ByteCallbackSink extends ByteConversionSinkBase {
   static const _INITIAL_BUFFER_SIZE = 1024;
 
   final _ChunkedConversionCallback<List<int>> _callback;
-  List<int> _buffer = new Uint8List(_INITIAL_BUFFER_SIZE);
+  List<int> _buffer = Uint8List(_INITIAL_BUFFER_SIZE);
   int _bufferIndex = 0;
 
   _ByteCallbackSink(void callback(List<int> accumulated))
-      : this._callback = callback;
+      : _callback = callback;
 
   void add(Iterable<int> chunk) {
-    int freeCount = _buffer.length - _bufferIndex;
+    var freeCount = _buffer.length - _bufferIndex;
     if (chunk.length > freeCount) {
       // Grow the buffer.
-      int oldLength = _buffer.length;
-      int newLength = _roundToPowerOf2(chunk.length + oldLength) * 2;
-      List<int> grown = new Uint8List(newLength);
+      var oldLength = _buffer.length;
+      var newLength = _roundToPowerOf2(chunk.length + oldLength) * 2;
+      var grown = Uint8List(newLength);
       grown.setRange(0, _buffer.length, _buffer);
       _buffer = grown;
     }
diff --git a/sdk/lib/convert/chunked_conversion.dart b/sdk/lib/convert/chunked_conversion.dart
index ff1294f..6a9479a 100644
--- a/sdk/lib/convert/chunked_conversion.dart
+++ b/sdk/lib/convert/chunked_conversion.dart
@@ -6,44 +6,36 @@
 
 typedef void _ChunkedConversionCallback<T>(T accumulated);
 
-/**
- * A [ChunkedConversionSink] is used to transmit data more efficiently between
- * two converters during chunked conversions.
- *
- * The basic `ChunkedConversionSink` is just a [Sink], and converters should
- * work with a plain `Sink`, but may work more efficiently with certain
- * specialized types of `ChunkedConversionSink`.
- *
- * It is recommended that implementations of `ChunkedConversionSink` extend
- * this class, to inherit any further methods that may be added to the class.
- */
+/// A [ChunkedConversionSink] is used to transmit data more efficiently between
+/// two converters during chunked conversions.
+///
+/// The basic `ChunkedConversionSink` is just a [Sink], and converters should
+/// work with a plain `Sink`, but may work more efficiently with certain
+/// specialized types of `ChunkedConversionSink`.
+///
+/// It is recommended that implementations of `ChunkedConversionSink` extend
+/// this class, to inherit any further methods that may be added to the class.
 abstract class ChunkedConversionSink<T> implements Sink<T> {
   ChunkedConversionSink();
   factory ChunkedConversionSink.withCallback(
       void callback(List<T> accumulated)) = _SimpleCallbackSink<T>;
 
-  /**
-   * Adds chunked data to this sink.
-   *
-   * This method is also used when converters are used as [StreamTransformer]s.
-   */
+  /// Adds chunked data to this sink.
+  ///
+  /// This method is also used when converters are used as [StreamTransformer]s.
   void add(T chunk);
 
-  /**
-   * Closes the sink.
-   *
-   * This signals the end of the chunked conversion. This method is called
-   * when converters are used as [StreamTransformer]'s.
-   */
+  /// Closes the sink.
+  ///
+  /// This signals the end of the chunked conversion. This method is called
+  /// when converters are used as [StreamTransformer]'s.
   void close();
 }
 
-/**
- * This class accumulates all chunks and invokes a callback with a list of
- * the chunks when the sink is closed.
- *
- * This class can be used to terminate a chunked conversion.
- */
+/// This class accumulates all chunks and invokes a callback with a list of
+/// the chunks when the sink is closed.
+///
+/// This class can be used to terminate a chunked conversion.
 class _SimpleCallbackSink<T> extends ChunkedConversionSink<T> {
   final _ChunkedConversionCallback<List<T>> _callback;
   final List<T> _accumulated = <T>[];
@@ -59,27 +51,23 @@
   }
 }
 
-/**
- * This class implements the logic for a chunked conversion as a
- * stream transformer.
- *
- * It is used as strategy in the [EventTransformStream].
- *
- * It also implements the [ChunkedConversionSink] interface so that it
- * can be used as output sink in a chunked conversion.
- */
+/// This class implements the logic for a chunked conversion as a
+/// stream transformer.
+///
+/// It is used as strategy in the [EventTransformStream].
+///
+/// It also implements the [ChunkedConversionSink] interface so that it
+/// can be used as output sink in a chunked conversion.
 class _ConverterStreamEventSink<S, T> implements EventSink<S> {
-  /** The output sink for the converter. */
+  /// The output sink for the converter.
   final EventSink<T> _eventSink;
 
-  /**
-   * The input sink for new data. All data that is received with
-   * [handleData] is added into this sink.
-   */
+  /// The input sink for new data. All data that is received with
+  /// [handleData] is added into this sink.
   final Sink<S> _chunkedSink;
 
   _ConverterStreamEventSink(Converter<S, T> converter, EventSink<T> sink)
-      : this._eventSink = sink,
+      : _eventSink = sink,
         _chunkedSink = converter.startChunkedConversion(sink);
 
   void add(S o) {
diff --git a/sdk/lib/convert/codec.dart b/sdk/lib/convert/codec.dart
index 95aadd1..38e4a3c 100644
--- a/sdk/lib/convert/codec.dart
+++ b/sdk/lib/convert/codec.dart
@@ -4,92 +4,77 @@
 
 part of dart.convert;
 
-/**
- * A [Codec] encodes and (if supported) decodes data.
- *
- * Codecs can be fused. For example fusing [json] and [utf8] produces
- * an encoder that can convert Json objects directly to bytes, or can decode
- * bytes directly to json objects.
- *
- * Fused codecs generally attempt to optimize the operations and can be faster
- * than executing each step of an encoding separately.
- */
+/// A [Codec] encodes and (if supported) decodes data.
+///
+/// Codecs can be fused. For example fusing [json] and [utf8] produces
+/// an encoder that can convert Json objects directly to bytes, or can decode
+/// bytes directly to json objects.
+///
+/// Fused codecs generally attempt to optimize the operations and can be faster
+/// than executing each step of an encoding separately.
 abstract class Codec<S, T> {
   const Codec();
 
-  /**
-   * Encodes [input].
-   *
-   * The input is encoded as if by `encoder.convert`.
-   */
+  /// Encodes [input].
+  ///
+  /// The input is encoded as if by `encoder.convert`.
   T encode(S input) => encoder.convert(input);
 
-  /**
-   * Decodes [encoded] data.
-   *
-   * The input is decoded as if by `decoder.convert`.
-   */
+  /// Decodes [encoded] data.
+  ///
+  /// The input is decoded as if by `decoder.convert`.
   S decode(T encoded) => decoder.convert(encoded);
 
-  /**
-   * Returns the encoder from [S] to [T].
-   *
-   * It may be stateful and should not be reused.
-   */
+  /// Returns the encoder from [S] to [T].
+  ///
+  /// It may be stateful and should not be reused.
   Converter<S, T> get encoder;
-  /**
-   * Returns the decoder of `this`, converting from [T] to [S].
-   *
-   * It may be stateful and should not be reused.
-   */
+
+  /// Returns the decoder of `this`, converting from [T] to [S].
+  ///
+  /// It may be stateful and should not be reused.
   Converter<T, S> get decoder;
 
-  /**
-   * Fuses `this` with `other`.
-   *
-   * When encoding, the resulting codec encodes with `this` before
-   * encoding with [other].
-   *
-   * When decoding, the resulting codec decodes with [other] before decoding
-   * with `this`.
-   *
-   * In some cases one needs to use the [inverted] codecs to be able to fuse
-   * them correctly. That is, the output type of `this` ([T]) must match the
-   * input type of the second codec [other].
-   *
-   * Examples:
-   * ```dart
-   * final jsonToBytes = json.fuse(utf8);
-   * List<int> bytes = jsonToBytes.encode(["json-object"]);
-   * var decoded = jsonToBytes.decode(bytes);
-   * assert(decoded is List && decoded[0] == "json-object");
-   *
-   * var inverted = json.inverted;
-   * var jsonIdentity = json.fuse(inverted);
-   * var jsonObject = jsonIdentity.encode(["1", 2]);
-   * assert(jsonObject is List && jsonObject[0] == "1" && jsonObject[1] == 2);
-   * ```
-   */
+  /// Fuses `this` with `other`.
+  ///
+  /// When encoding, the resulting codec encodes with `this` before
+  /// encoding with [other].
+  ///
+  /// When decoding, the resulting codec decodes with [other] before decoding
+  /// with `this`.
+  ///
+  /// In some cases one needs to use the [inverted] codecs to be able to fuse
+  /// them correctly. That is, the output type of `this` ([T]) must match the
+  /// input type of the second codec [other].
+  ///
+  /// Examples:
+  /// ```dart
+  /// final jsonToBytes = json.fuse(utf8);
+  /// List<int> bytes = jsonToBytes.encode(["json-object"]);
+  /// var decoded = jsonToBytes.decode(bytes);
+  /// assert(decoded is List && decoded[0] == "json-object");
+  ///
+  /// var inverted = json.inverted;
+  /// var jsonIdentity = json.fuse(inverted);
+  /// var jsonObject = jsonIdentity.encode(["1", 2]);
+  /// assert(jsonObject is List && jsonObject[0] == "1" && jsonObject[1] == 2);
+  /// ```
   // TODO(floitsch): use better example with line-splitter once that one is
   // in this library.
   Codec<S, R> fuse<R>(Codec<T, R> other) {
-    return new _FusedCodec<S, T, R>(this, other);
+    return _FusedCodec<S, T, R>(this, other);
   }
 
-  /**
-   * Inverts `this`.
-   *
-   * The [encoder] and [decoder] of the resulting codec are swapped.
-   */
-  Codec<T, S> get inverted => new _InvertedCodec<T, S>(this);
+  /// Inverts `this`.
+  ///
+  /// The [encoder] and [decoder] of the resulting codec are swapped.
+  Codec<T, S> get inverted => _InvertedCodec<T, S>(this);
 }
 
-/**
- * Fuses the given codecs.
- *
- * In the non-chunked conversion simply invokes the non-chunked conversions in
- * sequence.
- */
+/// Fuses the given codecs.
+///
+/// In the non-chunked conversion simply invokes the non-chunked conversions in
+/// sequence.
 class _FusedCodec<S, M, T> extends Codec<S, T> {
   final Codec<S, M> _first;
   final Codec<M, T> _second;
diff --git a/sdk/lib/convert/convert.dart b/sdk/lib/convert/convert.dart
index 8125f34..6173782 100644
--- a/sdk/lib/convert/convert.dart
+++ b/sdk/lib/convert/convert.dart
@@ -2,57 +2,55 @@
 // 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.
 
-/**
- *
- * Encoders and decoders for converting between different data representations,
- * including JSON and UTF-8.
- *
- * In addition to converters for common data representations, this library
- * provides support for implementing converters in a way which makes them easy to
- * chain and to use with streams.
- *
- * To use this library in your code:
- *
- *     import 'dart:convert';
- *
- * Two commonly used converters are the top-level instances of
- * [JsonCodec] and [Utf8Codec], named [json] and [utf8], respectively.
- *
- * JSON is a simple text format for representing
- * structured objects and collections.
- * The JSON encoder/decoder transforms between strings and
- * object structures, such as lists and maps, using the JSON format.
- *
- * UTF-8 is a common variable-width encoding that can represent
- * every character in the Unicode character set.
- * The UTF-8 encoder/decoder transforms between Strings and bytes.
- *
- * Converters are often used with streams
- * to transform the data that comes through the stream
- * as it becomes available.
- * The following code uses two converters.
- * The first is a UTF-8 decoder, which converts the data from bytes to UTF-8
- * as it's read from a file,
- * The second is an instance of [LineSplitter],
- * which splits the data on newline boundaries.
- *
- *     int lineNumber = 1;
- *     Stream<List<int>> stream = new File('quotes.txt').openRead();
- *
- *     stream.transform(utf8.decoder)
- *           .transform(const LineSplitter())
- *           .listen((line) {
- *             if (showLineNumbers) {
- *               stdout.write('${lineNumber++} ');
- *             }
- *             stdout.writeln(line);
- *           });
- *
- * See the documentation for the [Codec] and [Converter] classes
- * for information about creating your own converters.
- *
- * {@category Core}
- */
+///
+/// Encoders and decoders for converting between different data representations,
+/// including JSON and UTF-8.
+///
+/// In addition to converters for common data representations, this library
+/// provides support for implementing converters in a way which makes them easy to
+/// chain and to use with streams.
+///
+/// To use this library in your code:
+///
+///     import 'dart:convert';
+///
+/// Two commonly used converters are the top-level instances of
+/// [JsonCodec] and [Utf8Codec], named [json] and [utf8], respectively.
+///
+/// JSON is a simple text format for representing
+/// structured objects and collections.
+/// The JSON encoder/decoder transforms between strings and
+/// object structures, such as lists and maps, using the JSON format.
+///
+/// UTF-8 is a common variable-width encoding that can represent
+/// every character in the Unicode character set.
+/// The UTF-8 encoder/decoder transforms between Strings and bytes.
+///
+/// Converters are often used with streams
+/// to transform the data that comes through the stream
+/// as it becomes available.
+/// The following code uses two converters.
+/// The first is a UTF-8 decoder, which converts the data from bytes to UTF-8
+/// as it's read from a file,
+/// The second is an instance of [LineSplitter],
+/// which splits the data on newline boundaries.
+///
+///     var lineNumber = 1;
+///     var stream = File('quotes.txt').openRead();
+///
+///     stream.transform(utf8.decoder)
+///           .transform(const LineSplitter())
+///           .listen((line) {
+///             if (showLineNumbers) {
+///               stdout.write('${lineNumber++} ');
+///             }
+///             stdout.writeln(line);
+///           });
+///
+/// See the documentation for the [Codec] and [Converter] classes
+/// for information about creating your own converters.
+///
+/// {@category Core}
 library dart.convert;
 
 import 'dart:async';
diff --git a/sdk/lib/convert/converter.dart b/sdk/lib/convert/converter.dart
index 7f0b3f5..2167933 100644
--- a/sdk/lib/convert/converter.dart
+++ b/sdk/lib/convert/converter.dart
@@ -4,74 +4,60 @@
 
 part of dart.convert;
 
-/**
- * A [Converter] converts data from one representation into another.
- *
- * It is recommended that implementations of `Converter` extend this class,
- * to inherit any further methods that may be added to the class.
- */
+/// A [Converter] converts data from one representation into another.
+///
+/// It is recommended that implementations of `Converter` extend this class,
+/// to inherit any further methods that may be added to the class.
 abstract class Converter<S, T> extends StreamTransformerBase<S, T> {
   const Converter();
 
-  /**
-   * Adapts [source] to be a `Converter<TS, TT>`.
-   *
-   * This allows [source] to be used at the new type, but at run-time it
-   * must satisfy the requirements of both the new type and its original type.
-   *
-   * Conversion input must be both [SS] and [TS] and the output created by
-   * [source] for those input must be both [ST] and [TT].
-   */
+  /// Adapts [source] to be a `Converter<TS, TT>`.
+  ///
+  /// This allows [source] to be used at the new type, but at run-time it
+  /// must satisfy the requirements of both the new type and its original type.
+  ///
+  /// Conversion input must be both [SS] and [TS] and the output created by
+  /// [source] for those input must be both [ST] and [TT].
   static Converter<TS, TT> castFrom<SS, ST, TS, TT>(Converter<SS, ST> source) =>
-      new CastConverter<SS, ST, TS, TT>(source);
+      CastConverter<SS, ST, TS, TT>(source);
 
-  /**
-   * Converts [input] and returns the result of the conversion.
-   */
+  /// Converts [input] and returns the result of the conversion.
   T convert(S input);
 
-  /**
-   * Fuses `this` with [other].
-   *
-   * Encoding with the resulting converter is equivalent to converting with
-   * `this` before converting with `other`.
-   */
+  /// Fuses `this` with [other].
+  ///
+  /// Encoding with the resulting converter is equivalent to converting with
+  /// `this` before converting with `other`.
   Converter<S, TT> fuse<TT>(Converter<T, TT> other) {
-    return new _FusedConverter<S, T, TT>(this, other);
+    return _FusedConverter<S, T, TT>(this, other);
   }
 
-  /**
-   * Starts a chunked conversion.
-   *
-   * The returned sink serves as input for the long-running conversion. The
-   * given [sink] serves as output.
-   */
+  /// Starts a chunked conversion.
+  ///
+  /// The returned sink serves as input for the long-running conversion. The
+  /// given [sink] serves as output.
   Sink<S> startChunkedConversion(Sink<T> sink) {
-    throw new UnsupportedError(
+    throw UnsupportedError(
         "This converter does not support chunked conversions: $this");
   }
 
   Stream<T> bind(Stream<S> stream) {
-    return new Stream<T>.eventTransformed(
-        stream, (EventSink sink) => new _ConverterStreamEventSink(this, sink));
+    return Stream<T>.eventTransformed(
+        stream, (EventSink sink) => _ConverterStreamEventSink(this, sink));
   }
 
-  /**
-   * Provides a `Converter<RS, RT>` view of this stream transformer.
-   *
-   * The resulting transformer will check at run-time that all conversion
-   * inputs are actually instances of [S],
-   * and it will check that all conversion output produced by this converter
-   * are actually instances of [RT].
-   */
+  /// Provides a `Converter<RS, RT>` view of this stream transformer.
+  ///
+  /// The resulting transformer will check at run-time that all conversion
+  /// inputs are actually instances of [S],
+  /// and it will check that all conversion output produced by this converter
+  /// are actually instances of [RT].
   Converter<RS, RT> cast<RS, RT>() => Converter.castFrom<S, T, RS, RT>(this);
 }
 
-/**
- * Fuses two converters.
- *
- * For a non-chunked conversion converts the input in sequence.
- */
+/// Fuses two converters.
+///
+/// For a non-chunked conversion converts the input in sequence.
 class _FusedConverter<S, M, T> extends Converter<S, T> {
   final Converter<S, M> _first;
   final Converter<M, T> _second;
diff --git a/sdk/lib/convert/encoding.dart b/sdk/lib/convert/encoding.dart
index 388868e..7441e0a 100644
--- a/sdk/lib/convert/encoding.dart
+++ b/sdk/lib/convert/encoding.dart
@@ -4,34 +4,38 @@
 
 part of dart.convert;
 
-/**
- * Open-ended Encoding enum.
- */
+/// Open-ended Encoding enum.
 abstract class Encoding extends Codec<String, List<int>> {
   const Encoding();
 
+  /// Returns the encoder from `String` to `List<int>`.
+  ///
+  /// It may be stateful and should not be reused.
   Converter<String, List<int>> get encoder;
+
+  /// Returns the decoder of `this`, converting from `List<int>` to `String`.
+  ///
+  /// It may be stateful and should not be reused.
   Converter<List<int>, String> get decoder;
 
   Future<String> decodeStream(Stream<List<int>> byteStream) {
     return byteStream
-        .transform(decoder)
-        .fold(new StringBuffer(), (buffer, string) => buffer..write(string))
-        .then((buffer) => buffer.toString());
+        .transform<String>(decoder)
+        .fold(StringBuffer(),
+            (StringBuffer buffer, String string) => buffer..write(string))
+        .then((StringBuffer buffer) => buffer.toString());
   }
 
-  /**
-   * Name of the encoding.
-   *
-   * If the encoding is standardized, this is the lower-case version of one of
-   * the IANA official names for the character set (see
-   * http://www.iana.org/assignments/character-sets/character-sets.xml)
-   */
+  /// Name of the encoding.
+  ///
+  /// If the encoding is standardized, this is the lower-case version of one of
+  /// the IANA official names for the character set (see
+  /// http://www.iana.org/assignments/character-sets/character-sets.xml)
   String get name;
 
   // All aliases (in lowercase) of supported encoding from
   // http://www.iana.org/assignments/character-sets/character-sets.xml.
-  static Map<String, Encoding> _nameToEncoding = <String, Encoding>{
+  static final Map<String, Encoding> _nameToEncoding = <String, Encoding>{
     // ISO_8859-1:1987.
     "iso_8859-1:1987": latin1,
     "iso-ir-100": latin1,
@@ -61,16 +65,14 @@
     "utf-8": utf8
   };
 
-  /**
-  * Gets an [Encoding] object from the name of the character set
-  * name. The names used are the IANA official names for the
-  * character set (see
-  * http://www.iana.org/assignments/character-sets/character-sets.xml).
-  *
-  * The [name] passed is case insensitive.
-  *
-  * If character set is not supported [:null:] is returned.
-  */
+  /// Gets an [Encoding] object from the name of the character set
+  /// name. The names used are the IANA official names for the
+  /// character set (see
+  /// http://www.iana.org/assignments/character-sets/character-sets.xml).
+  ///
+  /// The [name] passed is case insensitive.
+  ///
+  /// If character set is not supported [:null:] is returned.
   static Encoding getByName(String name) {
     if (name == null) return null;
     name = name.toLowerCase();
diff --git a/sdk/lib/convert/html_escape.dart b/sdk/lib/convert/html_escape.dart
index 3d5de0a..a0a7119 100644
--- a/sdk/lib/convert/html_escape.dart
+++ b/sdk/lib/convert/html_escape.dart
@@ -4,165 +4,149 @@
 
 part of dart.convert;
 
-/**
- * A `String` converter that converts characters to HTML entities.
- *
- * This is intended to sanitize text before inserting the text into an HTML
- * document. Characters that are meaningful in HTML are converted to
- * HTML entities (like `&amp;` for `&`).
- *
- * The general converter escapes all characters that are meaningful in HTML
- * attributes or normal element context. Elements with special content types
- * (like CSS or JavaScript) may need a more specialized escaping that
- * understands that content type.
- *
- * If the context where the text will be inserted is known in more detail,
- * it's possible to omit escaping some characters (like quotes when not
- * inside an attribute value).
- *
- * The escaped text should only be used inside quoted HTML attributes values
- * or as text content of a normal element. Using the escaped text inside a
- * tag, but not inside a quoted attribute value, is still dangerous.
- */
-const HtmlEscape htmlEscape = const HtmlEscape();
+/// A `String` converter that converts characters to HTML entities.
+///
+/// This is intended to sanitize text before inserting the text into an HTML
+/// document. Characters that are meaningful in HTML are converted to
+/// HTML entities (like `&amp;` for `&`).
+///
+/// The general converter escapes all characters that are meaningful in HTML
+/// attributes or normal element context. Elements with special content types
+/// (like CSS or JavaScript) may need a more specialized escaping that
+/// understands that content type.
+///
+/// If the context where the text will be inserted is known in more detail,
+/// it's possible to omit escaping some characters (like quotes when not
+/// inside an attribute value).
+///
+/// The escaped text should only be used inside quoted HTML attributes values
+/// or as text content of a normal element. Using the escaped text inside a
+/// tag, but not inside a quoted attribute value, is still dangerous.
+const HtmlEscape htmlEscape = HtmlEscape();
 
-/**
- * HTML escape modes.
- *
- * Allows specifying a mode for HTML escaping that depend on the context
- * where the escaped result is going to be used.
- * The relevant contexts are:
- *
- * * as text content of an HTML element.
- * * as value of a (single- or double-) quoted attribute value.
- *
- * All modes require escaping of `&` (ampersand) characters, and may
- * enable escaping of more characters.
- *
- * Custom escape modes can be created using the [HtmlEscapeMode.HtmlEscapeMode]
- * constructor.
- */
+/// HTML escape modes.
+///
+/// Allows specifying a mode for HTML escaping that depend on the context
+/// where the escaped result is going to be used.
+/// The relevant contexts are:
+///
+/// * as text content of an HTML element.
+/// * as value of a (single- or double-) quoted attribute value.
+///
+/// All modes require escaping of `&` (ampersand) characters, and may
+/// enable escaping of more characters.
+///
+/// Custom escape modes can be created using the [HtmlEscapeMode.HtmlEscapeMode]
+/// constructor.
 class HtmlEscapeMode {
   final String _name;
-  /** Whether to escape '<' and '>'. */
+
+  /// Whether to escape '<' and '>'.
   final bool escapeLtGt;
-  /** Whether to escape '"' (quote). */
+
+  /// Whether to escape '"' (quote).
   final bool escapeQuot;
-  /** Whether to escape "'" (apostrophe). */
+
+  /// Whether to escape "'" (apostrophe).
   final bool escapeApos;
-  /**
-   * Whether to escape "/" (forward slash, solidus).
-   *
-   * Escaping a slash is recommended to avoid cross-site scripting attacks by
-   * [the Open Web Application Security Project](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content)
-   */
+
+  /// Whether to escape "/" (forward slash, solidus).
+  ///
+  /// Escaping a slash is recommended to avoid cross-site scripting attacks by
+  /// [the Open Web Application Security Project](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content)
   final bool escapeSlash;
 
-  /**
-   * Default escaping mode which escape all characters.
-   *
-   * The result of such an escaping is usable both in element content and
-   * in any attribute value.
-   *
-   * The escaping only works for elements with normal HTML content,
-   * and not for, for example, script or style element content,
-   * which require escapes matching their particular content syntax.
-   */
+  /// Default escaping mode which escape all characters.
+  ///
+  /// The result of such an escaping is usable both in element content and
+  /// in any attribute value.
+  ///
+  /// The escaping only works for elements with normal HTML content,
+  /// and not for, for example, script or style element content,
+  /// which require escapes matching their particular content syntax.
   static const HtmlEscapeMode unknown =
-      const HtmlEscapeMode._('unknown', true, true, true, true);
+      HtmlEscapeMode._('unknown', true, true, true, true);
 
-  /**
-   * Escaping mode for text going into double-quoted HTML attribute values.
-   *
-   * The result should not be used as the content of an unquoted
-   * or single-quoted attribute value.
-   *
-   * Escapes double quotes (`"`) but not single quotes (`'`),
-   * and escapes `<` and `>` characters because they are not allowed
-   * in strict XHTML attributes
-   */
+  /// Escaping mode for text going into double-quoted HTML attribute values.
+  ///
+  /// The result should not be used as the content of an unquoted
+  /// or single-quoted attribute value.
+  ///
+  /// Escapes double quotes (`"`) but not single quotes (`'`),
+  /// and escapes `<` and `>` characters because they are not allowed
+  /// in strict XHTML attributes
   static const HtmlEscapeMode attribute =
-      const HtmlEscapeMode._('attribute', true, true, false, false);
+      HtmlEscapeMode._('attribute', true, true, false, false);
 
-  /**
-   * Escaping mode for text going into single-quoted HTML attribute values.
-   *
-   * The result should not be used as the content of an unquoted
-   * or double-quoted attribute value.
-   *
-   * Escapes single quotes (`'`) but not double quotes (`"`),
-   * and escapes `<` and `>` characters because they are not allowed
-   * in strict XHTML attributes
-   */
+  /// Escaping mode for text going into single-quoted HTML attribute values.
+  ///
+  /// The result should not be used as the content of an unquoted
+  /// or double-quoted attribute value.
+  ///
+  /// Escapes single quotes (`'`) but not double quotes (`"`),
+  /// and escapes `<` and `>` characters because they are not allowed
+  /// in strict XHTML attributes
   static const HtmlEscapeMode sqAttribute =
-      const HtmlEscapeMode._('attribute', true, false, true, false);
+      HtmlEscapeMode._('attribute', true, false, true, false);
 
-  /**
-   * Escaping mode for text going into HTML element content.
-   *
-   * The escaping only works for elements with normal HTML content,
-   * and not for, for example, script or style element content,
-   * which require escapes matching their particular content syntax.
-   *
-   * Escapes `<` and `>` characters.
-   */
+  /// Escaping mode for text going into HTML element content.
+  ///
+  /// The escaping only works for elements with normal HTML content,
+  /// and not for, for example, script or style element content,
+  /// which require escapes matching their particular content syntax.
+  ///
+  /// Escapes `<` and `>` characters.
   static const HtmlEscapeMode element =
-      const HtmlEscapeMode._('element', true, false, false, false);
+      HtmlEscapeMode._('element', true, false, false, false);
 
   const HtmlEscapeMode._(this._name, this.escapeLtGt, this.escapeQuot,
       this.escapeApos, this.escapeSlash);
 
-  /**
-   * Create a custom escaping mode.
-   *
-   * All modes escape `&`.
-   * The mode can further be set to escape `<` and `>` ([escapeLtGt]),
-   * `"` ([escapeQuot]), `'` ([escapeApos]), and/or `/` ([escapeSlash]).
-   */
+  /// Create a custom escaping mode.
+  ///
+  /// All modes escape `&`.
+  /// The mode can further be set to escape `<` and `>` ([escapeLtGt]),
+  /// `"` ([escapeQuot]), `'` ([escapeApos]), and/or `/` ([escapeSlash]).
   const HtmlEscapeMode(
-      {String name: "custom",
-      this.escapeLtGt: false,
-      this.escapeQuot: false,
-      this.escapeApos: false,
-      this.escapeSlash: false})
+      {String name = "custom",
+      this.escapeLtGt = false,
+      this.escapeQuot = false,
+      this.escapeApos = false,
+      this.escapeSlash = false})
       : _name = name;
 
   String toString() => _name;
 }
 
-/**
- * Converter which escapes characters with special meaning in HTML.
- *
- * The converter finds characters that are significant in HTML source and
- * replaces them with corresponding HTML entities.
- *
- * The characters that need escaping in HTML are:
- *
- * * `&` (ampersand) always need to be escaped.
- * * `<` (less than) and '>' (greater than) when inside an element.
- * * `"` (quote) when inside a double-quoted attribute value.
- * * `'` (apostrophe) when inside a single-quoted attribute value.
- *       Apostrophe is escaped as `&#39;` instead of `&apos;` since
- *       not all browsers understand `&apos;`.
- * * `/` (slash) is recommended to be escaped because it may be used
- *       to terminate an element in some HTML dialects.
- *
- * Escaping `>` (greater than) isn't necessary, but the result is often
- * found to be easier to read if greater-than is also escaped whenever
- * less-than is.
- */
+/// Converter which escapes characters with special meaning in HTML.
+///
+/// The converter finds characters that are significant in HTML source and
+/// replaces them with corresponding HTML entities.
+///
+/// The characters that need escaping in HTML are:
+///
+/// * `&` (ampersand) always need to be escaped.
+/// * `<` (less than) and '>' (greater than) when inside an element.
+/// * `"` (quote) when inside a double-quoted attribute value.
+/// * `'` (apostrophe) when inside a single-quoted attribute value.
+///       Apostrophe is escaped as `&#39;` instead of `&apos;` since
+///       not all browsers understand `&apos;`.
+/// * `/` (slash) is recommended to be escaped because it may be used
+///       to terminate an element in some HTML dialects.
+///
+/// Escaping `>` (greater than) isn't necessary, but the result is often
+/// found to be easier to read if greater-than is also escaped whenever
+/// less-than is.
 class HtmlEscape extends Converter<String, String> {
-  /** The [HtmlEscapeMode] used by the converter. */
+  /// The [HtmlEscapeMode] used by the converter.
   final HtmlEscapeMode mode;
 
-  /**
-   * Create converter that escapes HTML characters.
-   *
-   * If [mode] is provided as either [HtmlEscapeMode.attribute] or
-   * [HtmlEscapeMode.element], only the corresponding subset of HTML
-   * characters are escaped.
-   * The default is to escape all HTML characters.
-   */
+  /// Create converter that escapes HTML characters.
+  ///
+  /// If [mode] is provided as either [HtmlEscapeMode.attribute] or
+  /// [HtmlEscapeMode.element], only the corresponding subset of HTML
+  /// characters are escaped.
+  /// The default is to escape all HTML characters.
   const HtmlEscape([this.mode = HtmlEscapeMode.unknown]);
 
   String convert(String text) {
@@ -170,17 +154,15 @@
     return val == null ? text : val;
   }
 
-  /**
-   * Converts the substring of text from start to end.
-   *
-   * Returns `null` if no changes were necessary, otherwise returns
-   * the converted string.
-   */
+  /// Converts the substring of text from start to end.
+  ///
+  /// Returns `null` if no changes were necessary, otherwise returns
+  /// the converted string.
   String _convert(String text, int start, int end) {
-    StringBuffer result = null;
-    for (int i = start; i < end; i++) {
+    StringBuffer result;
+    for (var i = start; i < end; i++) {
       var ch = text[i];
-      String replacement = null;
+      String replacement;
       switch (ch) {
         case '&':
           replacement = '&amp;';
@@ -202,7 +184,7 @@
           break;
       }
       if (replacement != null) {
-        if (result == null) result = new StringBuffer();
+        result ??= StringBuffer();
         if (i > start) result.write(text.substring(start, i));
         result.write(replacement);
         start = i + 1;
@@ -214,10 +196,8 @@
   }
 
   StringConversionSink startChunkedConversion(Sink<String> sink) {
-    if (sink is! StringConversionSink) {
-      sink = new StringConversionSink.from(sink);
-    }
-    return new _HtmlEscapeSink(this, sink);
+    return _HtmlEscapeSink(this,
+        sink is StringConversionSink ? sink : StringConversionSink.from(sink));
   }
 }
 
diff --git a/sdk/lib/convert/json.dart b/sdk/lib/convert/json.dart
index 1d3c69a..35bc351 100644
--- a/sdk/lib/convert/json.dart
+++ b/sdk/lib/convert/json.dart
@@ -4,16 +4,14 @@
 
 part of dart.convert;
 
-/**
- * Error thrown by JSON serialization if an object cannot be serialized.
- *
- * The [unsupportedObject] field holds that object that failed to be serialized.
- *
- * If an object isn't directly serializable, the serializer calls the `toJson`
- * method on the object. If that call fails, the error will be stored in the
- * [cause] field. If the call returns an object that isn't directly
- * serializable, the [cause] is null.
- */
+/// Error thrown by JSON serialization if an object cannot be serialized.
+///
+/// The [unsupportedObject] field holds that object that failed to be serialized.
+///
+/// If an object isn't directly serializable, the serializer calls the `toJson`
+/// method on the object. If that call fails, the error will be stored in the
+/// [cause] field. If the call returns an object that isn't directly
+/// serializable, the [cause] is null.
 class JsonUnsupportedObjectError extends Error {
   /// The object that could not be serialized.
   final Object unsupportedObject;
@@ -30,7 +28,7 @@
       {this.cause, this.partialResult});
 
   String toString() {
-    String safeString = Error.safeToString(unsupportedObject);
+    var safeString = Error.safeToString(unsupportedObject);
     String prefix;
     if (cause != null) {
       prefix = "Converting object to an encodable object failed:";
@@ -41,330 +39,298 @@
   }
 }
 
-/**
- * Reports that an object could not be stringified due to cyclic references.
- *
- * An object that references itself cannot be serialized by
- * [JsonCodec.encode]/[JsonEncoder.convert].
- * When the cycle is detected, a [JsonCyclicError] is thrown.
- */
+/// Reports that an object could not be stringified due to cyclic references.
+///
+/// An object that references itself cannot be serialized by
+/// [JsonCodec.encode]/[JsonEncoder.convert].
+/// When the cycle is detected, a [JsonCyclicError] is thrown.
 class JsonCyclicError extends JsonUnsupportedObjectError {
-  /** The first object that was detected as part of a cycle. */
+  /// The first object that was detected as part of a cycle.
   JsonCyclicError(Object object) : super(object);
   String toString() => "Cyclic error in JSON stringify";
 }
 
-/**
- * An instance of the default implementation of the [JsonCodec].
- *
- * This instance provides a convenient access to the most common JSON
- * use cases.
- *
- * Examples:
- *
- *     var encoded = json.encode([1, 2, { "a": null }]);
- *     var decoded = json.decode('["foo", { "bar": 499 }]');
- */
-const JsonCodec json = const JsonCodec();
+/// An instance of the default implementation of the [JsonCodec].
+///
+/// This instance provides a convenient access to the most common JSON
+/// use cases.
+///
+/// Examples:
+///
+///     var encoded = json.encode([1, 2, { "a": null }]);
+///     var decoded = json.decode('["foo", { "bar": 499 }]');
+const JsonCodec json = JsonCodec();
 
-/**
- * Converts [value] to a JSON string.
- *
- * If value contains objects that are not directly encodable to a JSON
- * string (a value that is not a number, boolean, string, null, list or a map
- * with string keys), the [toEncodable] function is used to convert it to an
- * object that must be directly encodable.
- *
- * If [toEncodable] is omitted, it defaults to a function that returns the
- * result of calling `.toJson()` on the unencodable object.
- *
- * Shorthand for [json.encode].
- */
+/// Converts [value] to a JSON string.
+///
+/// If value contains objects that are not directly encodable to a JSON
+/// string (a value that is not a number, boolean, string, null, list or a map
+/// with string keys), the [toEncodable] function is used to convert it to an
+/// object that must be directly encodable.
+///
+/// If [toEncodable] is omitted, it defaults to a function that returns the
+/// result of calling `.toJson()` on the unencodable object.
+///
+/// Shorthand for [json.encode].
 String jsonEncode(Object object, {Object toEncodable(Object nonEncodable)}) =>
     json.encode(object, toEncodable: toEncodable);
 
-/**
- * Parses the string and returns the resulting Json object.
- *
- * The optional [reviver] function is called once for each object or list
- * property that has been parsed during decoding. The `key` argument is either
- * the integer list index for a list property, the string map key for object
- * properties, or `null` for the final result.
- *
- * The default [reviver] (when not provided) is the identity function.
- *
- * Shorthand for [json.decode].
- */
+/// Parses the string and returns the resulting Json object.
+///
+/// The optional [reviver] function is called once for each object or list
+/// property that has been parsed during decoding. The `key` argument is either
+/// the integer list index for a list property, the string map key for object
+/// properties, or `null` for the final result.
+///
+/// The default [reviver] (when not provided) is the identity function.
+///
+/// Shorthand for [json.decode].
 dynamic jsonDecode(String source, {Object reviver(Object key, Object value)}) =>
     json.decode(source, reviver: reviver);
 
 typedef _Reviver(Object key, Object value);
 typedef _ToEncodable(var o);
 
-/**
- * A [JsonCodec] encodes JSON objects to strings and decodes strings to
- * JSON objects.
- *
- * Examples:
- *
- *     var encoded = json.encode([1, 2, { "a": null }]);
- *     var decoded = json.decode('["foo", { "bar": 499 }]');
- */
+/// A [JsonCodec] encodes JSON objects to strings and decodes strings to
+/// JSON objects.
+///
+/// Examples:
+///
+///     var encoded = json.encode([1, 2, { "a": null }]);
+///     var decoded = json.decode('["foo", { "bar": 499 }]');
 class JsonCodec extends Codec<Object, String> {
   final _Reviver _reviver;
   final _ToEncodable _toEncodable;
 
-  /**
-   * Creates a `JsonCodec` with the given reviver and encoding function.
-   *
-   * The [reviver] function is called during decoding. It is invoked once for
-   * each object or list property that has been parsed.
-   * The `key` argument is either the integer list index for a list property,
-   * the string map key for object properties, or `null` for the final result.
-   *
-   * If [reviver] is omitted, it defaults to returning the value argument.
-   *
-   * The [toEncodable] function is used during encoding. It is invoked for
-   * values that are not directly encodable to a string (a value that is not a
-   * number, boolean, string, null, list or a map with string keys). The
-   * function must return an object that is directly encodable. The elements of
-   * a returned list and values of a returned map do not need to be directly
-   * encodable, and if they aren't, `toEncodable` will be used on them as well.
-   * Please notice that it is possible to cause an infinite recursive regress
-   * in this way, by effectively creating an infinite data structure through
-   * repeated call to `toEncodable`.
-   *
-   * If [toEncodable] is omitted, it defaults to a function that returns the
-   * result of calling `.toJson()` on the unencodable object.
-   */
+  /// Creates a `JsonCodec` with the given reviver and encoding function.
+  ///
+  /// The [reviver] function is called during decoding. It is invoked once for
+  /// each object or list property that has been parsed.
+  /// The `key` argument is either the integer list index for a list property,
+  /// the string map key for object properties, or `null` for the final result.
+  ///
+  /// If [reviver] is omitted, it defaults to returning the value argument.
+  ///
+  /// The [toEncodable] function is used during encoding. It is invoked for
+  /// values that are not directly encodable to a string (a value that is not a
+  /// number, boolean, string, null, list or a map with string keys). The
+  /// function must return an object that is directly encodable. The elements of
+  /// a returned list and values of a returned map do not need to be directly
+  /// encodable, and if they aren't, `toEncodable` will be used on them as well.
+  /// Please notice that it is possible to cause an infinite recursive regress
+  /// in this way, by effectively creating an infinite data structure through
+  /// repeated call to `toEncodable`.
+  ///
+  /// If [toEncodable] is omitted, it defaults to a function that returns the
+  /// result of calling `.toJson()` on the unencodable object.
   const JsonCodec({reviver(Object key, Object value), toEncodable(var object)})
       : _reviver = reviver,
         _toEncodable = toEncodable;
 
-  /**
-   * Creates a `JsonCodec` with the given reviver.
-   *
-   * The [reviver] function is called once for each object or list property
-   * that has been parsed during decoding. The `key` argument is either the
-   * integer list index for a list property, the string map key for object
-   * properties, or `null` for the final result.
-   */
+  /// Creates a `JsonCodec` with the given reviver.
+  ///
+  /// The [reviver] function is called once for each object or list property
+  /// that has been parsed during decoding. The `key` argument is either the
+  /// integer list index for a list property, the string map key for object
+  /// properties, or `null` for the final result.
   JsonCodec.withReviver(reviver(Object key, Object value))
       : this(reviver: reviver);
 
-  /**
-   * Parses the string and returns the resulting Json object.
-   *
-   * The optional [reviver] function is called once for each object or list
-   * property that has been parsed during decoding. The `key` argument is either
-   * the integer list index for a list property, the string map key for object
-   * properties, or `null` for the final result.
-   *
-   * The default [reviver] (when not provided) is the identity function.
-   */
+  /// Parses the string and returns the resulting Json object.
+  ///
+  /// The optional [reviver] function is called once for each object or list
+  /// property that has been parsed during decoding. The `key` argument is either
+  /// the integer list index for a list property, the string map key for object
+  /// properties, or `null` for the final result.
+  ///
+  /// The default [reviver] (when not provided) is the identity function.
   dynamic decode(String source, {reviver(Object key, Object value)}) {
-    if (reviver == null) reviver = _reviver;
+    reviver ??= _reviver;
     if (reviver == null) return decoder.convert(source);
-    return new JsonDecoder(reviver).convert(source);
+    return JsonDecoder(reviver).convert(source);
   }
 
-  /**
-   * Converts [value] to a JSON string.
-   *
-   * If value contains objects that are not directly encodable to a JSON
-   * string (a value that is not a number, boolean, string, null, list or a map
-   * with string keys), the [toEncodable] function is used to convert it to an
-   * object that must be directly encodable.
-   *
-   * If [toEncodable] is omitted, it defaults to a function that returns the
-   * result of calling `.toJson()` on the unencodable object.
-   */
+  /// Converts [value] to a JSON string.
+  ///
+  /// If value contains objects that are not directly encodable to a JSON
+  /// string (a value that is not a number, boolean, string, null, list or a map
+  /// with string keys), the [toEncodable] function is used to convert it to an
+  /// object that must be directly encodable.
+  ///
+  /// If [toEncodable] is omitted, it defaults to a function that returns the
+  /// result of calling `.toJson()` on the unencodable object.
   String encode(Object value, {toEncodable(object)}) {
-    if (toEncodable == null) toEncodable = _toEncodable;
+    toEncodable ??= _toEncodable;
     if (toEncodable == null) return encoder.convert(value);
-    return new JsonEncoder(toEncodable).convert(value);
+    return JsonEncoder(toEncodable).convert(value);
   }
 
   JsonEncoder get encoder {
     if (_toEncodable == null) return const JsonEncoder();
-    return new JsonEncoder(_toEncodable);
+    return JsonEncoder(_toEncodable);
   }
 
   JsonDecoder get decoder {
     if (_reviver == null) return const JsonDecoder();
-    return new JsonDecoder(_reviver);
+    return JsonDecoder(_reviver);
   }
 }
 
-/**
- * This class converts JSON objects to strings.
- */
+/// This class converts JSON objects to strings.
 class JsonEncoder extends Converter<Object, String> {
-  /**
-   * The string used for indention.
-   *
-   * When generating multi-line output, this string is inserted once at the
-   * beginning of each indented line for each level of indentation.
-   *
-   * If `null`, the output is encoded as a single line.
-   */
+  /// The string used for indention.
+  ///
+  /// When generating multi-line output, this string is inserted once at the
+  /// beginning of each indented line for each level of indentation.
+  ///
+  /// If `null`, the output is encoded as a single line.
   final String indent;
 
-  /**
-   * Function called on non-encodable objects to return a replacement
-   * encodable object that will be encoded in the orignal's place.
-   */
+  /// Function called on non-encodable objects to return a replacement
+  /// encodable object that will be encoded in the orignal's place.
   final _ToEncodable _toEncodable;
 
-  /**
-   * Creates a JSON encoder.
-   *
-   * The JSON encoder handles numbers, strings, booleans, null, lists and
-   * maps with string keys directly.
-   *
-   * Any other object is attempted converted by [toEncodable] to an
-   * object that is of one of the convertible types.
-   *
-   * If [toEncodable] is omitted, it defaults to calling `.toJson()` on
-   * the object.
-   */
+  /// Creates a JSON encoder.
+  ///
+  /// The JSON encoder handles numbers, strings, booleans, null, lists and
+  /// maps with string keys directly.
+  ///
+  /// Any other object is attempted converted by [toEncodable] to an
+  /// object that is of one of the convertible types.
+  ///
+  /// If [toEncodable] is omitted, it defaults to calling `.toJson()` on
+  /// the object.
   const JsonEncoder([toEncodable(object)])
-      : this.indent = null,
-        this._toEncodable = toEncodable;
+      : indent = null,
+        _toEncodable = toEncodable;
 
-  /**
-   * Creates a JSON encoder that creates multi-line JSON.
-   *
-   * The encoding of elements of lists and maps are indented and put on separate
-   * lines. The [indent] string is prepended to these elements, once for each
-   * level of indentation.
-   *
-   * If [indent] is `null`, the output is encoded as a single line.
-   *
-   * The JSON encoder handles numbers, strings, booleans, null, lists and
-   * maps with string keys directly.
-   *
-   * Any other object is attempted converted by [toEncodable] to an
-   * object that is of one of the convertible types.
-   *
-   * If [toEncodable] is omitted, it defaults to calling `.toJson()` on
-   * the object.
-   */
+  /// Creates a JSON encoder that creates multi-line JSON.
+  ///
+  /// The encoding of elements of lists and maps are indented and put on separate
+  /// lines. The [indent] string is prepended to these elements, once for each
+  /// level of indentation.
+  ///
+  /// If [indent] is `null`, the output is encoded as a single line.
+  ///
+  /// The JSON encoder handles numbers, strings, booleans, null, lists and
+  /// maps with string keys directly.
+  ///
+  /// Any other object is attempted converted by [toEncodable] to an
+  /// object that is of one of the convertible types.
+  ///
+  /// If [toEncodable] is omitted, it defaults to calling `.toJson()` on
+  /// the object.
   const JsonEncoder.withIndent(this.indent, [toEncodable(object)])
-      : this._toEncodable = toEncodable;
+      : _toEncodable = toEncodable;
 
-  /**
-   * Converts [object] to a JSON [String].
-   *
-   * Directly serializable values are [num], [String], [bool], and [Null], as
-   * well as some [List] and [Map] values. For [List], the elements must all be
-   * serializable. For [Map], the keys must be [String] and the values must be
-   * serializable.
-   *
-   * If a value of any other type is attempted to be serialized, the
-   * `toEncodable` function provided in the constructor is called with the value
-   * as argument. The result, which must be a directly serializable value, is
-   * serialized instead of the original value.
-   *
-   * If the conversion throws, or returns a value that is not directly
-   * serializable, a [JsonUnsupportedObjectError] exception is thrown.
-   * If the call throws, the error is caught and stored in the
-   * [JsonUnsupportedObjectError]'s [:cause:] field.
-   *
-   * If a [List] or [Map] contains a reference to itself, directly or through
-   * other lists or maps, it cannot be serialized and a [JsonCyclicError] is
-   * thrown.
-   *
-   * [object] should not change during serialization.
-   *
-   * If an object is serialized more than once, [convert] may cache the text
-   * for it. In other words, if the content of an object changes after it is
-   * first serialized, the new values may not be reflected in the result.
-   */
+  /// Converts [object] to a JSON [String].
+  ///
+  /// Directly serializable values are [num], [String], [bool], and [Null], as
+  /// well as some [List] and [Map] values. For [List], the elements must all be
+  /// serializable. For [Map], the keys must be [String] and the values must be
+  /// serializable.
+  ///
+  /// If a value of any other type is attempted to be serialized, the
+  /// `toEncodable` function provided in the constructor is called with the value
+  /// as argument. The result, which must be a directly serializable value, is
+  /// serialized instead of the original value.
+  ///
+  /// If the conversion throws, or returns a value that is not directly
+  /// serializable, a [JsonUnsupportedObjectError] exception is thrown.
+  /// If the call throws, the error is caught and stored in the
+  /// [JsonUnsupportedObjectError]'s [:cause:] field.
+  ///
+  /// If a [List] or [Map] contains a reference to itself, directly or through
+  /// other lists or maps, it cannot be serialized and a [JsonCyclicError] is
+  /// thrown.
+  ///
+  /// [object] should not change during serialization.
+  ///
+  /// If an object is serialized more than once, [convert] may cache the text
+  /// for it. In other words, if the content of an object changes after it is
+  /// first serialized, the new values may not be reflected in the result.
   String convert(Object object) =>
       _JsonStringStringifier.stringify(object, _toEncodable, indent);
 
-  /**
-   * Starts a chunked conversion.
-   *
-   * The converter works more efficiently if the given [sink] is a
-   * [StringConversionSink].
-   *
-   * Returns a chunked-conversion sink that accepts at most one object. It is
-   * an error to invoke `add` more than once on the returned sink.
-   */
+  /// Starts a chunked conversion.
+  ///
+  /// The converter works more efficiently if the given [sink] is a
+  /// [StringConversionSink].
+  ///
+  /// Returns a chunked-conversion sink that accepts at most one object. It is
+  /// an error to invoke `add` more than once on the returned sink.
   ChunkedConversionSink<Object> startChunkedConversion(Sink<String> sink) {
-    if (sink is! StringConversionSink) {
-      sink = new StringConversionSink.from(sink);
-    } else if (sink is _Utf8EncoderSink) {
-      return new _JsonUtf8EncoderSink(
+    if (sink is _Utf8EncoderSink) {
+      return _JsonUtf8EncoderSink(
           sink._sink,
           _toEncodable,
           JsonUtf8Encoder._utf8Encode(indent),
           JsonUtf8Encoder._defaultBufferSize);
     }
-    return new _JsonEncoderSink(sink, _toEncodable, indent);
+    return _JsonEncoderSink(
+        sink is StringConversionSink ? sink : StringConversionSink.from(sink),
+        _toEncodable,
+        indent);
   }
 
   // Override the base class's bind, to provide a better type.
   Stream<String> bind(Stream<Object> stream) => super.bind(stream);
 
   Converter<Object, T> fuse<T>(Converter<String, T> other) {
-    if (other is Utf8Encoder) {
+    if (other is Utf8Encoder && T is List<int>) {
       // The instance check guarantees that `T` is (a subtype of) List<int>,
       // but the static type system doesn't know that, and so we cast.
       // Cast through dynamic to keep the cast implicit for builds using
       // unchecked implicit casts.
-      return new JsonUtf8Encoder(indent, _toEncodable) as dynamic;
+      return JsonUtf8Encoder(indent, _toEncodable) as dynamic;
     }
     return super.fuse<T>(other);
   }
 }
 
-/**
- * Encoder that encodes a single object as a UTF-8 encoded JSON string.
- *
- * This encoder works equivalently to first converting the object to
- * a JSON string, and then UTF-8 encoding the string, but without
- * creating an intermediate string.
- */
+/// Encoder that encodes a single object as a UTF-8 encoded JSON string.
+///
+/// This encoder works equivalently to first converting the object to
+/// a JSON string, and then UTF-8 encoding the string, but without
+/// creating an intermediate string.
 class JsonUtf8Encoder extends Converter<Object, List<int>> {
-  /** Default buffer size used by the JSON-to-UTF-8 encoder. */
+  /// Default buffer size used by the JSON-to-UTF-8 encoder.
   static const int _defaultBufferSize = 256;
   @deprecated
   static const int DEFAULT_BUFFER_SIZE = _defaultBufferSize;
-  /** Indentation used in pretty-print mode, `null` if not pretty. */
+
+  /// Indentation used in pretty-print mode, `null` if not pretty.
   final List<int> _indent;
-  /** Function called with each un-encodable object encountered. */
+
+  /// Function called with each un-encodable object encountered.
   final _ToEncodable _toEncodable;
-  /** UTF-8 buffer size. */
+
+  /// UTF-8 buffer size.
   final int _bufferSize;
 
-  /**
-   * Create converter.
-   *
-   * If [indent] is non-`null`, the converter attempts to "pretty-print" the
-   * JSON, and uses `indent` as the indentation. Otherwise the result has no
-   * whitespace outside of string literals.
-   * If `indent` contains characters that are not valid JSON whitespace
-   * characters, the result will not be valid JSON. JSON whitespace characters
-   * are space (U+0020), tab (U+0009), line feed (U+000a) and carriage return
-   * (U+000d) ([ECMA
-   * 404](http://www.ecma-international.org/publications/standards/Ecma-404.htm)).
-   *
-   * The [bufferSize] is the size of the internal buffers used to collect
-   * UTF-8 code units.
-   * If using [startChunkedConversion], it will be the size of the chunks.
-   *
-   * The JSON encoder handles numbers, strings, booleans, null, lists and maps
-   * directly.
-   *
-   * Any other object is attempted converted by [toEncodable] to an object that
-   * is of one of the convertible types.
-   *
-   * If [toEncodable] is omitted, it defaults to calling `.toJson()` on the
-   * object.
-   */
+  /// Create converter.
+  ///
+  /// If [indent] is non-`null`, the converter attempts to "pretty-print" the
+  /// JSON, and uses `indent` as the indentation. Otherwise the result has no
+  /// whitespace outside of string literals.
+  /// If `indent` contains characters that are not valid JSON whitespace
+  /// characters, the result will not be valid JSON. JSON whitespace characters
+  /// are space (U+0020), tab (U+0009), line feed (U+000a) and carriage return
+  /// (U+000d) ([ECMA
+  /// 404](http://www.ecma-international.org/publications/standards/Ecma-404.htm)).
+  ///
+  /// The [bufferSize] is the size of the internal buffers used to collect
+  /// UTF-8 code units.
+  /// If using [startChunkedConversion], it will be the size of the chunks.
+  ///
+  /// The JSON encoder handles numbers, strings, booleans, null, lists and maps
+  /// directly.
+  ///
+  /// Any other object is attempted converted by [toEncodable] to an object that
+  /// is of one of the convertible types.
+  ///
+  /// If [toEncodable] is omitted, it defaults to calling `.toJson()` on the
+  /// object.
   JsonUtf8Encoder(
       [String indent, toEncodable(object), int bufferSize = _defaultBufferSize])
       : _indent = _utf8Encode(indent),
@@ -373,10 +339,10 @@
 
   static List<int> _utf8Encode(String string) {
     if (string == null) return null;
-    if (string.isEmpty) return new Uint8List(0);
+    if (string.isEmpty) return Uint8List(0);
     checkAscii:
     {
-      for (int i = 0; i < string.length; i++) {
+      for (var i = 0; i < string.length; i++) {
         if (string.codeUnitAt(i) >= 0x80) break checkAscii;
       }
       return string.codeUnits;
@@ -384,16 +350,16 @@
     return utf8.encode(string);
   }
 
-  /** Convert [object] into UTF-8 encoded JSON. */
+  /// Convert [object] into UTF-8 encoded JSON.
   List<int> convert(Object object) {
-    List<List<int>> bytes = [];
+    var bytes = <List<int>>[];
     // The `stringify` function always converts into chunks.
     // Collect the chunks into the `bytes` list, then combine them afterwards.
     void addChunk(Uint8List chunk, int start, int end) {
       if (start > 0 || end < chunk.length) {
-        int length = end - start;
-        chunk = new Uint8List.view(
-            chunk.buffer, chunk.offsetInBytes + start, length);
+        var length = end - start;
+        chunk =
+            Uint8List.view(chunk.buffer, chunk.offsetInBytes + start, length);
       }
       bytes.add(chunk);
     }
@@ -401,12 +367,12 @@
     _JsonUtf8Stringifier.stringify(
         object, _indent, _toEncodable, _bufferSize, addChunk);
     if (bytes.length == 1) return bytes[0];
-    int length = 0;
-    for (int i = 0; i < bytes.length; i++) {
+    var length = 0;
+    for (var i = 0; i < bytes.length; i++) {
       length += bytes[i].length;
     }
-    Uint8List result = new Uint8List(length);
-    for (int i = 0, offset = 0; i < bytes.length; i++) {
+    var result = Uint8List(length);
+    for (var i = 0, offset = 0; i < bytes.length; i++) {
       var byteList = bytes[i];
       int end = offset + byteList.length;
       result.setRange(offset, end, byteList);
@@ -415,23 +381,20 @@
     return result;
   }
 
-  /**
-   * Start a chunked conversion.
-   *
-   * Only one object can be passed into the returned sink.
-   *
-   * The argument [sink] will receive byte lists in sizes depending on the
-   * `bufferSize` passed to the constructor when creating this encoder.
-   */
+  /// Start a chunked conversion.
+  ///
+  /// Only one object can be passed into the returned sink.
+  ///
+  /// The argument [sink] will receive byte lists in sizes depending on the
+  /// `bufferSize` passed to the constructor when creating this encoder.
   ChunkedConversionSink<Object> startChunkedConversion(Sink<List<int>> sink) {
     ByteConversionSink byteSink;
     if (sink is ByteConversionSink) {
       byteSink = sink;
     } else {
-      byteSink = new ByteConversionSink.from(sink);
+      byteSink = ByteConversionSink.from(sink);
     }
-    return new _JsonUtf8EncoderSink(
-        byteSink, _toEncodable, _indent, _bufferSize);
+    return _JsonUtf8EncoderSink(byteSink, _toEncodable, _indent, _bufferSize);
   }
 
   // Override the base class's bind, to provide a better type.
@@ -440,11 +403,9 @@
   }
 }
 
-/**
- * Implements the chunked conversion from object to its JSON representation.
- *
- * The sink only accepts one value, but will produce output in a chunked way.
- */
+/// Implements the chunked conversion from object to its JSON representation.
+///
+/// The sink only accepts one value, but will produce output in a chunked way.
 class _JsonEncoderSink extends ChunkedConversionSink<Object> {
   final String _indent;
   final _ToEncodable _toEncodable;
@@ -453,19 +414,17 @@
 
   _JsonEncoderSink(this._sink, this._toEncodable, this._indent);
 
-  /**
-   * Encodes the given object [o].
-   *
-   * It is an error to invoke this method more than once on any instance. While
-   * this makes the input effectively non-chunked the output will be generated
-   * in a chunked way.
-   */
+  /// Encodes the given object [o].
+  ///
+  /// It is an error to invoke this method more than once on any instance. While
+  /// this makes the input effectively non-chunked the output will be generated
+  /// in a chunked way.
   void add(Object o) {
     if (_isDone) {
-      throw new StateError("Only one call to add allowed");
+      throw StateError("Only one call to add allowed");
     }
     _isDone = true;
-    ClosableStringSink stringSink = _sink.asStringSink();
+    var stringSink = _sink.asStringSink();
     _JsonStringStringifier.printOn(o, stringSink, _toEncodable, _indent);
     stringSink.close();
   }
@@ -473,11 +432,9 @@
   void close() {/* do nothing */}
 }
 
-/**
- * Sink returned when starting a chunked conversion from object to bytes.
- */
+/// Sink returned when starting a chunked conversion from object to bytes.
 class _JsonUtf8EncoderSink extends ChunkedConversionSink<Object> {
-  /** The byte sink receiveing the encoded chunks. */
+  /// The byte sink receiveing the encoded chunks.
   final ByteConversionSink _sink;
   final List<int> _indent;
   final _ToEncodable _toEncodable;
@@ -486,14 +443,14 @@
   _JsonUtf8EncoderSink(
       this._sink, this._toEncodable, this._indent, this._bufferSize);
 
-  /** Callback called for each slice of result bytes. */
+  /// Callback called for each slice of result bytes.
   void _addChunk(Uint8List chunk, int start, int end) {
     _sink.addSlice(chunk, start, end, false);
   }
 
   void add(Object object) {
     if (_isDone) {
-      throw new StateError("Only one call to add allowed");
+      throw StateError("Only one call to add allowed");
     }
     _isDone = true;
     _JsonUtf8Stringifier.stringify(
@@ -509,41 +466,33 @@
   }
 }
 
-/**
- * This class parses JSON strings and builds the corresponding objects.
- */
+/// This class parses JSON strings and builds the corresponding objects.
 class JsonDecoder extends Converter<String, Object> {
   final _Reviver _reviver;
-  /**
-   * Constructs a new JsonDecoder.
-   *
-   * The [reviver] may be `null`.
-   */
-  const JsonDecoder([reviver(Object key, Object value)])
-      : this._reviver = reviver;
 
-  /**
-   * Converts the given JSON-string [input] to its corresponding object.
-   *
-   * Parsed JSON values are of the types [num], [String], [bool], [Null],
-   * [List]s of parsed JSON values or [Map]s from [String] to parsed JSON
-   * values.
-   *
-   * If `this` was initialized with a reviver, then the parsing operation
-   * invokes the reviver on every object or list property that has been parsed.
-   * The arguments are the property name ([String]) or list index ([int]), and
-   * the value is the parsed value. The return value of the reviver is used as
-   * the value of that property instead the parsed value.
-   *
-   * Throws [FormatException] if the input is not valid JSON text.
-   */
+  /// Constructs a new JsonDecoder.
+  ///
+  /// The [reviver] may be `null`.
+  const JsonDecoder([reviver(Object key, Object value)]) : _reviver = reviver;
+
+  /// Converts the given JSON-string [input] to its corresponding object.
+  ///
+  /// Parsed JSON values are of the types [num], [String], [bool], [Null],
+  /// [List]s of parsed JSON values or [Map]s from [String] to parsed JSON
+  /// values.
+  ///
+  /// If `this` was initialized with a reviver, then the parsing operation
+  /// invokes the reviver on every object or list property that has been parsed.
+  /// The arguments are the property name ([String]) or list index ([int]), and
+  /// the value is the parsed value. The return value of the reviver is used as
+  /// the value of that property instead the parsed value.
+  ///
+  /// Throws [FormatException] if the input is not valid JSON text.
   dynamic convert(String input) => _parseJson(input, _reviver);
 
-  /**
-   * Starts a conversion from a chunked JSON string to its corresponding object.
-   *
-   * The output [sink] receives exactly one decoded element through `add`.
-   */
+  /// Starts a conversion from a chunked JSON string to its corresponding object.
+  ///
+  /// The output [sink] receives exactly one decoded element through `add`.
   external StringConversionSink startChunkedConversion(Sink<Object> sink);
 
   // Override the base class's bind, to provide a better type.
@@ -557,12 +506,10 @@
 
 dynamic _defaultToEncodable(dynamic object) => object.toJson();
 
-/**
- * JSON encoder that traverses an object structure and writes JSON source.
- *
- * This is an abstract implementation that doesn't decide on the output
- * format, but writes the JSON through abstract methods like [writeString].
- */
+/// JSON encoder that traverses an object structure and writes JSON source.
+///
+/// This is an abstract implementation that doesn't decide on the output
+/// format, but writes the JSON through abstract methods like [writeString].
 abstract class _JsonStringifier {
   // Character code constants.
   static const int backspace = 0x08;
@@ -580,9 +527,10 @@
   static const int char_t = 0x74;
   static const int char_u = 0x75;
 
-  /** List of objects currently being traversed. Used to detect cycles. */
-  final List _seen = new List();
-  /** Function called for each un-encodable object encountered. */
+  /// List of objects currently being traversed. Used to detect cycles.
+  final List _seen = [];
+
+  /// Function called for each un-encodable object encountered.
   final _ToEncodable _toEncodable;
 
   _JsonStringifier(toEncodable(o))
@@ -590,26 +538,27 @@
 
   String get _partialResult;
 
-  /** Append a string to the JSON output. */
+  /// Append a string to the JSON output.
   void writeString(String characters);
-  /** Append part of a string to the JSON output. */
+
+  /// Append part of a string to the JSON output.
   void writeStringSlice(String characters, int start, int end);
-  /** Append a single character, given by its code point, to the JSON output. */
+
+  /// Append a single character, given by its code point, to the JSON output.
   void writeCharCode(int charCode);
-  /** Write a number to the JSON output. */
+
+  /// Write a number to the JSON output.
   void writeNumber(num number);
 
   // ('0' + x) or ('a' + x - 10)
   static int hexDigit(int x) => x < 10 ? 48 + x : 87 + x;
 
-  /**
-   * Write, and suitably escape, a string's content as a JSON string literal.
-   */
+  /// Write, and suitably escape, a string's content as a JSON string literal.
   void writeStringContent(String s) {
-    int offset = 0;
-    final int length = s.length;
-    for (int i = 0; i < length; i++) {
-      int charCode = s.codeUnitAt(i);
+    var offset = 0;
+    final length = s.length;
+    for (var i = 0; i < length; i++) {
+      var charCode = s.codeUnitAt(i);
       if (charCode > backslash) continue;
       if (charCode < 32) {
         if (i > offset) writeStringSlice(s, offset, i);
@@ -653,39 +602,33 @@
     }
   }
 
-  /**
-   * Check if an encountered object is already being traversed.
-   *
-   * Records the object if it isn't already seen. Should have a matching call to
-   * [_removeSeen] when the object is no longer being traversed.
-   */
+  /// Check if an encountered object is already being traversed.
+  ///
+  /// Records the object if it isn't already seen. Should have a matching call to
+  /// [_removeSeen] when the object is no longer being traversed.
   void _checkCycle(object) {
-    for (int i = 0; i < _seen.length; i++) {
+    for (var i = 0; i < _seen.length; i++) {
       if (identical(object, _seen[i])) {
-        throw new JsonCyclicError(object);
+        throw JsonCyclicError(object);
       }
     }
     _seen.add(object);
   }
 
-  /**
-   * Remove [object] from the list of currently traversed objects.
-   *
-   * Should be called in the opposite order of the matching [_checkCycle]
-   * calls.
-   */
+  /// Remove [object] from the list of currently traversed objects.
+  ///
+  /// Should be called in the opposite order of the matching [_checkCycle]
+  /// calls.
   void _removeSeen(object) {
-    assert(!_seen.isEmpty);
+    assert(_seen.isNotEmpty);
     assert(identical(_seen.last, object));
     _seen.removeLast();
   }
 
-  /**
-   * Write an object.
-   *
-   * If [object] isn't directly encodable, the [_toEncodable] function gets one
-   * chance to return a replacement which is encodable.
-   */
+  /// Write an object.
+  ///
+  /// If [object] isn't directly encodable, the [_toEncodable] function gets one
+  /// chance to return a replacement which is encodable.
   void writeObject(object) {
     // Tries stringifying object directly. If it's not a simple value, List or
     // Map, call toJson() to get a custom representation and try serializing
@@ -695,22 +638,19 @@
     try {
       var customJson = _toEncodable(object);
       if (!writeJsonValue(customJson)) {
-        throw new JsonUnsupportedObjectError(object,
-            partialResult: _partialResult);
+        throw JsonUnsupportedObjectError(object, partialResult: _partialResult);
       }
       _removeSeen(object);
     } catch (e) {
-      throw new JsonUnsupportedObjectError(object,
+      throw JsonUnsupportedObjectError(object,
           cause: e, partialResult: _partialResult);
     }
   }
 
-  /**
-   * Serialize a [num], [String], [bool], [Null], [List] or [Map] value.
-   *
-   * Returns true if the value is one of these types, and false if not.
-   * If a value is both a [List] and a [Map], it's serialized as a [List].
-   */
+  /// Serialize a [num], [String], [bool], [Null], [List] or [Map] value.
+  ///
+  /// Returns true if the value is one of these types, and false if not.
+  /// If a value is both a [List] and a [Map], it's serialized as a [List].
   bool writeJsonValue(object) {
     if (object is num) {
       if (!object.isFinite) return false;
@@ -746,12 +686,12 @@
     }
   }
 
-  /** Serialize a [List]. */
+  /// Serialize a [List].
   void writeList(List list) {
     writeString('[');
-    if (list.length > 0) {
+    if (list.isNotEmpty) {
       writeObject(list[0]);
-      for (int i = 1; i < list.length; i++) {
+      for (var i = 1; i < list.length; i++) {
         writeString(',');
         writeObject(list[i]);
       }
@@ -759,15 +699,15 @@
     writeString(']');
   }
 
-  /** Serialize a [Map]. */
+  /// Serialize a [Map].
   bool writeMap(Map map) {
     if (map.isEmpty) {
       writeString("{}");
       return true;
     }
-    List keyValueList = new List(map.length * 2);
-    int i = 0;
-    bool allStringKeys = true;
+    var keyValueList = List(map.length * 2);
+    var i = 0;
+    var allStringKeys = true;
     map.forEach((key, value) {
       if (key is! String) {
         allStringKeys = false;
@@ -777,8 +717,8 @@
     });
     if (!allStringKeys) return false;
     writeString('{');
-    String separator = '"';
-    for (int i = 0; i < keyValueList.length; i += 2) {
+    var separator = '"';
+    for (var i = 0; i < keyValueList.length; i += 2) {
       writeString(separator);
       separator = ',"';
       writeStringContent(keyValueList[i]);
@@ -790,18 +730,14 @@
   }
 }
 
-/**
- * A modification of [_JsonStringifier] which indents the contents of [List] and
- * [Map] objects using the specified indent value.
- *
- * Subclasses should implement [writeIndentation].
- */
+/// A modification of [_JsonStringifier] which indents the contents of [List] and
+/// [Map] objects using the specified indent value.
+///
+/// Subclasses should implement [writeIndentation].
 abstract class _JsonPrettyPrintMixin implements _JsonStringifier {
   int _indentLevel = 0;
 
-  /**
-   * Add [indentLevel] indentations to the JSON output.
-   */
+  /// Add [indentLevel] indentations to the JSON output.
   void writeIndentation(int indentLevel);
 
   void writeList(List list) {
@@ -812,7 +748,7 @@
       _indentLevel++;
       writeIndentation(_indentLevel);
       writeObject(list[0]);
-      for (int i = 1; i < list.length; i++) {
+      for (var i = 1; i < list.length; i++) {
         writeString(',\n');
         writeIndentation(_indentLevel);
         writeObject(list[i]);
@@ -829,9 +765,9 @@
       writeString("{}");
       return true;
     }
-    List keyValueList = new List(map.length * 2);
-    int i = 0;
-    bool allStringKeys = true;
+    var keyValueList = List(map.length * 2);
+    var i = 0;
+    var allStringKeys = true;
     map.forEach((key, value) {
       if (key is! String) {
         allStringKeys = false;
@@ -842,8 +778,8 @@
     if (!allStringKeys) return false;
     writeString('{\n');
     _indentLevel++;
-    String separator = "";
-    for (int i = 0; i < keyValueList.length; i += 2) {
+    var separator = "";
+    for (var i = 0; i < keyValueList.length; i += 2) {
       writeString(separator);
       separator = ",\n";
       writeIndentation(_indentLevel);
@@ -860,44 +796,38 @@
   }
 }
 
-/**
- * A specialziation of [_JsonStringifier] that writes its JSON to a string.
- */
+/// A specialization of [_JsonStringifier] that writes its JSON to a string.
 class _JsonStringStringifier extends _JsonStringifier {
   final StringSink _sink;
 
-  _JsonStringStringifier(this._sink, _toEncodable) : super(_toEncodable);
+  _JsonStringStringifier(this._sink, dynamic Function(dynamic) _toEncodable)
+      : super(_toEncodable);
 
-  /**
-   * Convert object to a string.
-   *
-   * The [toEncodable] function is used to convert non-encodable objects
-   * to encodable ones.
-   *
-   * If [indent] is not `null`, the resulting JSON will be "pretty-printed"
-   * with newlines and indentation. The `indent` string is added as indentation
-   * for each indentation level. It should only contain valid JSON whitespace
-   * characters (space, tab, carriage return or line feed).
-   */
+  /// Convert object to a string.
+  ///
+  /// The [toEncodable] function is used to convert non-encodable objects
+  /// to encodable ones.
+  ///
+  /// If [indent] is not `null`, the resulting JSON will be "pretty-printed"
+  /// with newlines and indentation. The `indent` string is added as indentation
+  /// for each indentation level. It should only contain valid JSON whitespace
+  /// characters (space, tab, carriage return or line feed).
   static String stringify(object, toEncodable(o), String indent) {
-    StringBuffer output = new StringBuffer();
+    var output = StringBuffer();
     printOn(object, output, toEncodable, indent);
     return output.toString();
   }
 
-  /**
-   * Convert object to a string, and write the result to the [output] sink.
-   *
-   * The result is written piecemally to the sink.
-   */
+  /// Convert object to a string, and write the result to the [output] sink.
+  ///
+  /// The result is written piecemally to the sink.
   static void printOn(
       object, StringSink output, toEncodable(o), String indent) {
     _JsonStringifier stringifier;
     if (indent == null) {
-      stringifier = new _JsonStringStringifier(output, toEncodable);
+      stringifier = _JsonStringStringifier(output, toEncodable);
     } else {
-      stringifier =
-          new _JsonStringStringifierPretty(output, toEncodable, indent);
+      stringifier = _JsonStringStringifierPretty(output, toEncodable, indent);
     }
     stringifier.writeObject(object);
   }
@@ -929,57 +859,50 @@
       : super(sink, toEncodable);
 
   void writeIndentation(int count) {
-    for (int i = 0; i < count; i++) writeString(_indent);
+    for (var i = 0; i < count; i++) writeString(_indent);
   }
 }
 
 typedef void _AddChunk(Uint8List list, int start, int end);
 
-/**
- * Specialization of [_JsonStringifier] that writes the JSON as UTF-8.
- *
- * The JSON text is UTF-8 encoded and written to [Uint8List] buffers.
- * The buffers are then passed back to a user provided callback method.
- */
+/// Specialization of [_JsonStringifier] that writes the JSON as UTF-8.
+///
+/// The JSON text is UTF-8 encoded and written to [Uint8List] buffers.
+/// The buffers are then passed back to a user provided callback method.
 class _JsonUtf8Stringifier extends _JsonStringifier {
   final int bufferSize;
   final _AddChunk addChunk;
   Uint8List buffer;
   int index = 0;
 
-  _JsonUtf8Stringifier(toEncodable(o), int bufferSize, this.addChunk)
-      : this.bufferSize = bufferSize,
-        buffer = new Uint8List(bufferSize),
+  _JsonUtf8Stringifier(toEncodable(o), this.bufferSize, this.addChunk)
+      : buffer = Uint8List(bufferSize),
         super(toEncodable);
 
-  /**
-   * Convert [object] to UTF-8 encoded JSON.
-   *
-   * Calls [addChunk] with slices of UTF-8 code units.
-   * These will typically have size [bufferSize], but may be shorter.
-   * The buffers are not reused, so the [addChunk] call may keep and reuse the
-   * chunks.
-   *
-   * If [indent] is non-`null`, the result will be "pretty-printed" with extra
-   * newlines and indentation, using [indent] as the indentation.
-   */
+  /// Convert [object] to UTF-8 encoded JSON.
+  ///
+  /// Calls [addChunk] with slices of UTF-8 code units.
+  /// These will typically have size [bufferSize], but may be shorter.
+  /// The buffers are not reused, so the [addChunk] call may keep and reuse the
+  /// chunks.
+  ///
+  /// If [indent] is non-`null`, the result will be "pretty-printed" with extra
+  /// newlines and indentation, using [indent] as the indentation.
   static void stringify(Object object, List<int> indent, toEncodable(o),
       int bufferSize, void addChunk(Uint8List chunk, int start, int end)) {
     _JsonUtf8Stringifier stringifier;
     if (indent != null) {
-      stringifier = new _JsonUtf8StringifierPretty(
-          toEncodable, indent, bufferSize, addChunk);
+      stringifier =
+          _JsonUtf8StringifierPretty(toEncodable, indent, bufferSize, addChunk);
     } else {
-      stringifier = new _JsonUtf8Stringifier(toEncodable, bufferSize, addChunk);
+      stringifier = _JsonUtf8Stringifier(toEncodable, bufferSize, addChunk);
     }
     stringifier.writeObject(object);
     stringifier.flush();
   }
 
-  /**
-   * Must be called at the end to push the last chunk to the [addChunk]
-   * callback.
-   */
+  /// Must be called at the end to push the last chunk to the [addChunk]
+  /// callback.
   void flush() {
     if (index > 0) {
       addChunk(buffer, 0, index);
@@ -994,12 +917,12 @@
     writeAsciiString(number.toString());
   }
 
-  /** Write a string that is known to not have non-ASCII characters. */
+  /// Write a string that is known to not have non-ASCII characters.
   void writeAsciiString(String string) {
     // TODO(lrn): Optimize by copying directly into buffer instead of going
     // through writeCharCode;
-    for (int i = 0; i < string.length; i++) {
-      int char = string.codeUnitAt(i);
+    for (var i = 0; i < string.length; i++) {
+      var char = string.codeUnitAt(i);
       assert(char <= 0x7f);
       writeByte(char);
     }
@@ -1013,14 +936,14 @@
     // TODO(lrn): Optimize by copying directly into buffer instead of going
     // through writeCharCode/writeByte. Assumption is the most characters
     // in starings are plain ASCII.
-    for (int i = start; i < end; i++) {
-      int char = string.codeUnitAt(i);
+    for (var i = start; i < end; i++) {
+      var char = string.codeUnitAt(i);
       if (char <= 0x7f) {
         writeByte(char);
       } else {
         if ((char & 0xFC00) == 0xD800 && i + 1 < end) {
           // Lead surrogate.
-          int nextChar = string.codeUnitAt(i + 1);
+          var nextChar = string.codeUnitAt(i + 1);
           if ((nextChar & 0xFC00) == 0xDC00) {
             // Tail surrogate.
             char = 0x10000 + ((char & 0x3ff) << 10) + (nextChar & 0x3ff);
@@ -1069,28 +992,26 @@
     assert(byte <= 0xff);
     if (index == buffer.length) {
       addChunk(buffer, 0, index);
-      buffer = new Uint8List(bufferSize);
+      buffer = Uint8List(bufferSize);
       index = 0;
     }
     buffer[index++] = byte;
   }
 }
 
-/**
- * Pretty-printing version of [_JsonUtf8Stringifier].
- */
+/// Pretty-printing version of [_JsonUtf8Stringifier].
 class _JsonUtf8StringifierPretty extends _JsonUtf8Stringifier
     with _JsonPrettyPrintMixin {
   final List<int> indent;
-  _JsonUtf8StringifierPretty(toEncodable(o), this.indent, bufferSize,
+  _JsonUtf8StringifierPretty(toEncodable(o), this.indent, int bufferSize,
       void addChunk(Uint8List buffer, int start, int end))
       : super(toEncodable, bufferSize, addChunk);
 
   void writeIndentation(int count) {
-    List<int> indent = this.indent;
-    int indentLength = indent.length;
+    var indent = this.indent;
+    var indentLength = indent.length;
     if (indentLength == 1) {
-      int char = indent[0];
+      var char = indent[0];
       while (count > 0) {
         writeByte(char);
         count -= 1;
@@ -1099,12 +1020,12 @@
     }
     while (count > 0) {
       count--;
-      int end = index + indentLength;
+      var end = index + indentLength;
       if (end <= buffer.length) {
         buffer.setRange(index, end, indent);
         index = end;
       } else {
-        for (int i = 0; i < indentLength; i++) {
+        for (var i = 0; i < indentLength; i++) {
           writeByte(indent[i]);
         }
       }
diff --git a/sdk/lib/convert/latin1.dart b/sdk/lib/convert/latin1.dart
index e9c316d..c22010c 100644
--- a/sdk/lib/convert/latin1.dart
+++ b/sdk/lib/convert/latin1.dart
@@ -4,57 +4,51 @@
 
 part of dart.convert;
 
-/**
- * An instance of the default implementation of the [Latin1Codec].
- *
- * This instance provides a convenient access to the most common ISO Latin 1
- * use cases.
- *
- * Examples:
- * ```dart
- * var encoded = latin1.encode("blåbærgrød");
- * var decoded = latin1.decode([0x62, 0x6c, 0xe5, 0x62, 0xe6,
- *                              0x72, 0x67, 0x72, 0xf8, 0x64]);
- * ```
- */
-const Latin1Codec latin1 = const Latin1Codec();
+/// An instance of the default implementation of the [Latin1Codec].
+///
+/// This instance provides a convenient access to the most common ISO Latin 1
+/// use cases.
+///
+/// Examples:
+/// ```dart
+/// var encoded = latin1.encode("blåbærgrød");
+/// var decoded = latin1.decode([0x62, 0x6c, 0xe5, 0x62, 0xe6,
+///                              0x72, 0x67, 0x72, 0xf8, 0x64]);
+/// ```
+const Latin1Codec latin1 = Latin1Codec();
 
 const int _latin1Mask = 0xFF;
 
-/**
- * A [Latin1Codec] encodes strings to ISO Latin-1 (aka ISO-8859-1) bytes
- * and decodes Latin-1 bytes to strings.
- */
+/// A [Latin1Codec] encodes strings to ISO Latin-1 (aka ISO-8859-1) bytes
+/// and decodes Latin-1 bytes to strings.
 class Latin1Codec extends Encoding {
   final bool _allowInvalid;
-  /**
-   * Instantiates a new [Latin1Codec].
-   *
-   * If [allowInvalid] is true, the [decode] method and the converter
-   * returned by [decoder] will default to allowing invalid values. Invalid
-   * values are decoded into the Unicode Replacement character (U+FFFD).
-   * Calls to the [decode] method can override this default.
-   *
-   * Encoders will not accept invalid (non Latin-1) characters.
-   */
-  const Latin1Codec({bool allowInvalid: false}) : _allowInvalid = allowInvalid;
 
+  /// Instantiates a new [Latin1Codec].
+  ///
+  /// If [allowInvalid] is true, the [decode] method and the converter
+  /// returned by [decoder] will default to allowing invalid values. Invalid
+  /// values are decoded into the Unicode Replacement character (U+FFFD).
+  /// Calls to the [decode] method can override this default.
+  ///
+  /// Encoders will not accept invalid (non Latin-1) characters.
+  const Latin1Codec({bool allowInvalid = false}) : _allowInvalid = allowInvalid;
+
+  /// The name of this codec, "iso-8859-1".
   String get name => "iso-8859-1";
 
   Uint8List encode(String source) => encoder.convert(source);
 
-  /**
-   * Decodes the Latin-1 [bytes] (a list of unsigned 8-bit integers) to the
-   * corresponding string.
-   *
-   * If [bytes] contains values that are not in the range 0 .. 255, the decoder
-   * will eventually throw a [FormatException].
-   *
-   * If [allowInvalid] is not provided, it defaults to the value used to create
-   * this [Latin1Codec].
-   */
+  /// Decodes the Latin-1 [bytes] (a list of unsigned 8-bit integers) to the
+  /// corresponding string.
+  ///
+  /// If [bytes] contains values that are not in the range 0 .. 255, the decoder
+  /// will eventually throw a [FormatException].
+  ///
+  /// If [allowInvalid] is not provided, it defaults to the value used to create
+  /// this [Latin1Codec].
   String decode(List<int> bytes, {bool allowInvalid}) {
-    if (allowInvalid == null) allowInvalid = _allowInvalid;
+    allowInvalid ??= _allowInvalid;
     if (allowInvalid) {
       return const Latin1Decoder(allowInvalid: true).convert(bytes);
     } else {
@@ -69,47 +63,39 @@
       : const Latin1Decoder(allowInvalid: false);
 }
 
-/**
- * This class converts strings of only ISO Latin-1 characters to bytes.
- */
+/// This class converts strings of only ISO Latin-1 characters to bytes.
 class Latin1Encoder extends _UnicodeSubsetEncoder {
   const Latin1Encoder() : super(_latin1Mask);
 }
 
-/**
- * This class converts Latin-1 bytes (lists of unsigned 8-bit integers)
- * to a string.
- */
+/// This class converts Latin-1 bytes (lists of unsigned 8-bit integers)
+/// to a string.
 class Latin1Decoder extends _UnicodeSubsetDecoder {
-  /**
-   * Instantiates a new [Latin1Decoder].
-   *
-   * The optional [allowInvalid] argument defines how [convert] deals
-   * with invalid bytes.
-   *
-   * If it is `true`, [convert] replaces invalid bytes with the Unicode
-   * Replacement character `U+FFFD` (�).
-   * Otherwise it throws a [FormatException].
-   */
-  const Latin1Decoder({bool allowInvalid: false})
+  /// Instantiates a new [Latin1Decoder].
+  ///
+  /// The optional [allowInvalid] argument defines how [convert] deals
+  /// with invalid bytes.
+  ///
+  /// If it is `true`, [convert] replaces invalid bytes with the Unicode
+  /// Replacement character `U+FFFD` (�).
+  /// Otherwise it throws a [FormatException].
+  const Latin1Decoder({bool allowInvalid = false})
       : super(allowInvalid, _latin1Mask);
 
-  /**
-   * Starts a chunked conversion.
-   *
-   * The converter works more efficiently if the given [sink] is a
-   * [StringConversionSink].
-   */
+  /// Starts a chunked conversion.
+  ///
+  /// The converter works more efficiently if the given [sink] is a
+  /// [StringConversionSink].
   ByteConversionSink startChunkedConversion(Sink<String> sink) {
     StringConversionSink stringSink;
     if (sink is StringConversionSink) {
       stringSink = sink;
     } else {
-      stringSink = new StringConversionSink.from(sink);
+      stringSink = StringConversionSink.from(sink);
     }
     // TODO(lrn): Use stringSink.asUtf16Sink() if it becomes available.
-    if (!_allowInvalid) return new _Latin1DecoderSink(stringSink);
-    return new _Latin1AllowInvalidDecoderSink(stringSink);
+    if (!_allowInvalid) return _Latin1DecoderSink(stringSink);
+    return _Latin1AllowInvalidDecoderSink(stringSink);
   }
 }
 
@@ -131,7 +117,7 @@
     // _sink.addSlice(source, start, end, isLast).
     // The code below is an moderately stupid workaround until a real
     // solution can be made.
-    _sink.add(new String.fromCharCodes(source, start, end));
+    _sink.add(String.fromCharCodes(source, start, end));
     if (isLast) close();
   }
 
@@ -148,8 +134,8 @@
   }
 
   static void _checkValidLatin1(List<int> source, int start, int end) {
-    int mask = 0;
-    for (int i = start; i < end; i++) {
+    var mask = 0;
+    for (var i = start; i < end; i++) {
       mask |= source[i];
     }
     if (mask >= 0 && mask <= _latin1Mask) {
@@ -160,10 +146,10 @@
 
   static void _reportInvalidLatin1(List<int> source, int start, int end) {
     // Find the index of the first non-Latin-1 character code.
-    for (int i = start; i < end; i++) {
-      int char = source[i];
+    for (var i = start; i < end; i++) {
+      var char = source[i];
       if (char < 0 || char > _latin1Mask) {
-        throw new FormatException(
+        throw FormatException(
             "Source contains non-Latin-1 characters.", source, i);
       }
     }
@@ -177,8 +163,8 @@
 
   void addSlice(List<int> source, int start, int end, bool isLast) {
     RangeError.checkValidRange(start, end, source.length);
-    for (int i = start; i < end; i++) {
-      int char = source[i];
+    for (var i = start; i < end; i++) {
+      var char = source[i];
       if (char > _latin1Mask || char < 0) {
         if (i > start) _addSliceToSink(source, start, i, false);
         // Add UTF-8 encoding of U+FFFD.
diff --git a/sdk/lib/convert/line_splitter.dart b/sdk/lib/convert/line_splitter.dart
index 2522b14..71be2c0 100644
--- a/sdk/lib/convert/line_splitter.dart
+++ b/sdk/lib/convert/line_splitter.dart
@@ -8,15 +8,13 @@
 const int _LF = 10;
 const int _CR = 13;
 
-/**
- * A [StreamTransformer] that splits a [String] into individual lines.
- *
- * A line is terminated by either a CR (U+000D), a LF (U+000A), a
- * CR+LF sequence (DOS line ending),
- * and a final non-empty line can be ended by the end of the string.
- *
- * The returned lines do not contain the line terminators.
- */
+/// A [StreamTransformer] that splits a [String] into individual lines.
+///
+/// A line is terminated by either a CR (U+000D), a LF (U+000A), a
+/// CR+LF sequence (DOS line ending),
+/// and a final non-empty line can be ended by the end of the string.
+///
+/// The returned lines do not contain the line terminators.
 
 class LineSplitter extends StreamTransformerBase<String, String> {
   const LineSplitter();
@@ -29,10 +27,10 @@
   /// (`0 <= start <= end <= lines.length`).
   static Iterable<String> split(String lines, [int start = 0, int end]) sync* {
     end = RangeError.checkValidRange(start, end, lines.length);
-    int sliceStart = start;
-    int char = 0;
-    for (int i = start; i < end; i++) {
-      int previousChar = char;
+    var sliceStart = start;
+    var char = 0;
+    for (var i = start; i < end; i++) {
+      var previousChar = char;
       char = lines.codeUnitAt(i);
       if (char != _CR) {
         if (char != _LF) continue;
@@ -50,12 +48,12 @@
   }
 
   List<String> convert(String data) {
-    List<String> lines = <String>[];
-    int end = data.length;
-    int sliceStart = 0;
-    int char = 0;
-    for (int i = 0; i < end; i++) {
-      int previousChar = char;
+    var lines = <String>[];
+    var end = data.length;
+    var sliceStart = 0;
+    var char = 0;
+    for (var i = 0; i < end; i++) {
+      var previousChar = char;
       char = data.codeUnitAt(i);
       if (char != _CR) {
         if (char != _LF) continue;
@@ -74,15 +72,13 @@
   }
 
   StringConversionSink startChunkedConversion(Sink<String> sink) {
-    if (sink is! StringConversionSink) {
-      sink = new StringConversionSink.from(sink);
-    }
-    return new _LineSplitterSink(sink);
+    return _LineSplitterSink(
+        sink is StringConversionSink ? sink : StringConversionSink.from(sink));
   }
 
   Stream<String> bind(Stream<String> stream) {
-    return new Stream<String>.eventTransformed(
-        stream, (EventSink<String> sink) => new _LineSplitterEventSink(sink));
+    return Stream<String>.eventTransformed(
+        stream, (EventSink<String> sink) => _LineSplitterEventSink(sink));
   }
 }
 
@@ -139,10 +135,10 @@
   }
 
   void _addLines(String lines, int start, int end) {
-    int sliceStart = start;
-    int char = 0;
-    for (int i = start; i < end; i++) {
-      int previousChar = char;
+    var sliceStart = start;
+    var char = 0;
+    for (var i = start; i < end; i++) {
+      var previousChar = char;
       char = lines.codeUnitAt(i);
       if (char != _CR) {
         if (char != _LF) continue;
@@ -168,7 +164,7 @@
 
   _LineSplitterEventSink(EventSink<String> eventSink)
       : _eventSink = eventSink,
-        super(new StringConversionSink.from(eventSink));
+        super(StringConversionSink.from(eventSink));
 
   void addError(Object o, [StackTrace stackTrace]) {
     _eventSink.addError(o, stackTrace);
diff --git a/sdk/lib/convert/string_conversion.dart b/sdk/lib/convert/string_conversion.dart
index 15ce510..6c2d31f 100644
--- a/sdk/lib/convert/string_conversion.dart
+++ b/sdk/lib/convert/string_conversion.dart
@@ -4,87 +4,69 @@
 
 part of dart.convert;
 
-/**
- * This class provides an interface for converters to
- * efficiently transmit String data.
- *
- * Instead of limiting the interface to one non-chunked String it accepts
- * partial strings or can be transformed into a byte sink that
- * accepts UTF-8 code units.
- *
- * This abstract class will likely get more methods over time. Implementers are
- * urged to extend [StringConversionSinkBase] or to mix in
- * [StringConversionSinkMixin], to ensure that their class covers the newly
- * added methods.
- */
+/// This class provides an interface for converters to
+/// efficiently transmit String data.
+///
+/// Instead of limiting the interface to one non-chunked String it accepts
+/// partial strings or can be transformed into a byte sink that
+/// accepts UTF-8 code units.
+///
+/// This abstract class will likely get more methods over time. Implementers are
+/// urged to extend [StringConversionSinkBase] or to mix in
+/// [StringConversionSinkMixin], to ensure that their class covers the newly
+/// added methods.
 abstract class StringConversionSink extends ChunkedConversionSink<String> {
   StringConversionSink();
   factory StringConversionSink.withCallback(void callback(String accumulated)) =
       _StringCallbackSink;
   factory StringConversionSink.from(Sink<String> sink) = _StringAdapterSink;
 
-  /**
-   * Creates a new instance wrapping the given [sink].
-   *
-   * Every string that is added to the returned instance is forwarded to
-   * the [sink]. The instance is allowed to buffer and is not required to
-   * forward immediately.
-   */
+  /// Creates a new instance wrapping the given [sink].
+  ///
+  /// Every string that is added to the returned instance is forwarded to
+  /// the [sink]. The instance is allowed to buffer and is not required to
+  /// forward immediately.
   factory StringConversionSink.fromStringSink(StringSink sink) =
-      _StringSinkConversionSink;
+      _StringSinkConversionSink<StringSink>;
 
-  /**
-   * Adds the next [chunk] to `this`.
-   *
-   * Adds the substring defined by [start] and [end]-exclusive to `this`.
-   *
-   * If [isLast] is `true` closes `this`.
-   */
+  /// Adds the next [chunk] to `this`.
+  ///
+  /// Adds the substring defined by [start] and [end]-exclusive to `this`.
+  ///
+  /// If [isLast] is `true` closes `this`.
   void addSlice(String chunk, int start, int end, bool isLast);
 
-  /**
-   * Returns `this` as a sink that accepts UTF-8 input.
-   *
-   * If used, this method must be the first and only call to `this`. It
-   * invalidates `this`. All further operations must be performed on the result.
-   */
+  /// Returns `this` as a sink that accepts UTF-8 input.
+  ///
+  /// If used, this method must be the first and only call to `this`. It
+  /// invalidates `this`. All further operations must be performed on the result.
   ByteConversionSink asUtf8Sink(bool allowMalformed);
   // - asRuneSink
   // - asCodeUnitsSink
 
-  /**
-   * Returns `this` as a [ClosableStringSink].
-   *
-   * If used, this method must be the first and only call to `this`. It
-   * invalidates `this`. All further operations must be performed on the result.
-   */
+  /// Returns `this` as a [ClosableStringSink].
+  ///
+  /// If used, this method must be the first and only call to `this`. It
+  /// invalidates `this`. All further operations must be performed on the result.
   ClosableStringSink asStringSink();
 }
 
-/**
- * A [ClosableStringSink] extends the [StringSink] interface by adding a
- * `close` method.
- */
+/// A [ClosableStringSink] extends the [StringSink] interface by adding a
+/// `close` method.
 abstract class ClosableStringSink extends StringSink {
-  /**
-   * Creates a new instance combining a [StringSink] [sink] and a callback
-   * [onClose] which is invoked when the returned instance is closed.
-   */
+  /// Creates a new instance combining a [StringSink] [sink] and a callback
+  /// [onClose] which is invoked when the returned instance is closed.
   factory ClosableStringSink.fromStringSink(StringSink sink, void onClose()) =
       _ClosableStringSink;
 
-  /**
-   * Closes `this` and flushes any outstanding data.
-   */
+  /// Closes `this` and flushes any outstanding data.
   void close();
 }
 
 typedef void _StringSinkCloseCallback();
 
-/**
- * This class wraps an existing [StringSink] and invokes a
- * closure when [close] is invoked.
- */
+/// This class wraps an existing [StringSink] and invokes a
+/// closure when [close] is invoked.
 class _ClosableStringSink implements ClosableStringSink {
   final _StringSinkCloseCallback _callback;
   final StringSink _sink;
@@ -112,11 +94,9 @@
   }
 }
 
-/**
- * This class wraps an existing [StringConversionSink] and exposes a
- * [ClosableStringSink] interface. The wrapped sink only needs to implement
- * `add` and `close`.
- */
+/// This class wraps an existing [StringConversionSink] and exposes a
+/// [ClosableStringSink] interface. The wrapped sink only needs to implement
+/// `add` and `close`.
 // TODO(floitsch): make this class public?
 class _StringConversionSinkAsStringSinkAdapter implements ClosableStringSink {
   static const _MIN_STRING_SIZE = 16;
@@ -125,7 +105,7 @@
   StringConversionSink _chunkedSink;
 
   _StringConversionSinkAsStringSinkAdapter(this._chunkedSink)
-      : _buffer = new StringBuffer();
+      : _buffer = StringBuffer();
 
   void close() {
     if (_buffer.isNotEmpty) _flush();
@@ -149,7 +129,7 @@
 
   void writeAll(Iterable objects, [String separator = ""]) {
     if (_buffer.isNotEmpty) _flush();
-    Iterator iterator = objects.iterator;
+    var iterator = objects.iterator;
     if (!iterator.moveNext()) return;
     if (separator.isEmpty) {
       do {
@@ -165,22 +145,18 @@
   }
 
   void _flush() {
-    String accumulated = _buffer.toString();
+    var accumulated = _buffer.toString();
     _buffer.clear();
     _chunkedSink.add(accumulated);
   }
 }
 
-/**
- * This class provides a base-class for converters that need to accept String
- * inputs.
- */
+/// This class provides a base-class for converters that need to accept String
+/// inputs.
 abstract class StringConversionSinkBase extends StringConversionSinkMixin {}
 
-/**
- * This class provides a mixin for converters that need to accept String
- * inputs.
- */
+/// This class provides a mixin for converters that need to accept String
+/// inputs.
 abstract class StringConversionSinkMixin implements StringConversionSink {
   void addSlice(String str, int start, int end, bool isLast);
   void close();
@@ -190,25 +166,24 @@
   }
 
   ByteConversionSink asUtf8Sink(bool allowMalformed) {
-    return new _Utf8ConversionSink(this, allowMalformed);
+    return _Utf8ConversionSink(this, allowMalformed);
   }
 
   ClosableStringSink asStringSink() {
-    return new _StringConversionSinkAsStringSinkAdapter(this);
+    return _StringConversionSinkAsStringSinkAdapter(this);
   }
 }
 
-/**
- * This class is a [StringConversionSink] that wraps a [StringSink].
- */
-class _StringSinkConversionSink extends StringConversionSinkBase {
-  StringSink _stringSink;
+/// This class is a [StringConversionSink] that wraps a [StringSink].
+class _StringSinkConversionSink<TStringSink extends StringSink>
+    extends StringConversionSinkBase {
+  TStringSink _stringSink;
   _StringSinkConversionSink(this._stringSink);
 
   void close() {}
   void addSlice(String str, int start, int end, bool isLast) {
     if (start != 0 || end != str.length) {
-      for (int i = start; i < end; i++) {
+      for (var i = start; i < end; i++) {
         _stringSink.writeCharCode(str.codeUnitAt(i));
       }
     } else {
@@ -222,43 +197,38 @@
   }
 
   ByteConversionSink asUtf8Sink(bool allowMalformed) {
-    return new _Utf8StringSinkAdapter(this, _stringSink, allowMalformed);
+    return _Utf8StringSinkAdapter(this, _stringSink, allowMalformed);
   }
 
   ClosableStringSink asStringSink() {
-    return new ClosableStringSink.fromStringSink(_stringSink, this.close);
+    return ClosableStringSink.fromStringSink(_stringSink, close);
   }
 }
 
-/**
- * This class accumulates all chunks into one string
- * and invokes a callback when the sink is closed.
- *
- * This class can be used to terminate a chunked conversion.
- */
-class _StringCallbackSink extends _StringSinkConversionSink {
+/// This class accumulates all chunks into one string
+/// and invokes a callback when the sink is closed.
+///
+/// This class can be used to terminate a chunked conversion.
+class _StringCallbackSink extends _StringSinkConversionSink<StringBuffer> {
   final _ChunkedConversionCallback<String> _callback;
-  _StringCallbackSink(this._callback) : super(new StringBuffer());
+  _StringCallbackSink(this._callback) : super(StringBuffer());
 
   void close() {
-    StringBuffer buffer = _stringSink;
-    String accumulated = buffer.toString();
-    buffer.clear();
+    var accumulated = _stringSink.toString();
+    _stringSink.clear();
     _callback(accumulated);
   }
 
   ByteConversionSink asUtf8Sink(bool allowMalformed) {
-    return new _Utf8StringSinkAdapter(this, _stringSink, allowMalformed);
+    return _Utf8StringSinkAdapter(this, _stringSink, allowMalformed);
   }
 }
 
-/**
- * This class adapts a simple [ChunkedConversionSink] to a
- * [StringConversionSink].
- *
- * All additional methods of the [StringConversionSink] (compared to the
- * ChunkedConversionSink) are redirected to the `add` method.
- */
+/// This class adapts a simple [ChunkedConversionSink] to a
+/// [StringConversionSink].
+///
+/// All additional methods of the [StringConversionSink] (compared to the
+/// ChunkedConversionSink) are redirected to the `add` method.
 class _StringAdapterSink extends StringConversionSinkBase {
   final Sink<String> _sink;
 
@@ -282,15 +252,13 @@
   }
 }
 
-/**
- * Decodes UTF-8 code units and stores them in a [StringSink].
- */
+/// Decodes UTF-8 code units and stores them in a [StringSink].
 class _Utf8StringSinkAdapter extends ByteConversionSink {
   final _Utf8Decoder _decoder;
   final Sink _sink;
 
   _Utf8StringSinkAdapter(this._sink, StringSink stringSink, bool allowMalformed)
-      : _decoder = new _Utf8Decoder(stringSink, allowMalformed);
+      : _decoder = _Utf8Decoder(stringSink, allowMalformed);
 
   void close() {
     _decoder.close();
@@ -308,28 +276,26 @@
   }
 }
 
-/**
- * Decodes UTF-8 code units.
- *
- * Forwards the decoded strings to the given [StringConversionSink].
- */
+/// Decodes UTF-8 code units.
+///
+/// Forwards the decoded strings to the given [StringConversionSink].
 // TODO(floitsch): make this class public?
 class _Utf8ConversionSink extends ByteConversionSink {
   final _Utf8Decoder _decoder;
   final StringConversionSink _chunkedSink;
   final StringBuffer _buffer;
   _Utf8ConversionSink(StringConversionSink sink, bool allowMalformed)
-      : this._(sink, new StringBuffer(), allowMalformed);
+      : this._(sink, StringBuffer(), allowMalformed);
 
   _Utf8ConversionSink._(
       this._chunkedSink, StringBuffer stringBuffer, bool allowMalformed)
-      : _decoder = new _Utf8Decoder(stringBuffer, allowMalformed),
+      : _decoder = _Utf8Decoder(stringBuffer, allowMalformed),
         _buffer = stringBuffer;
 
   void close() {
     _decoder.close();
     if (_buffer.isNotEmpty) {
-      String accumulated = _buffer.toString();
+      var accumulated = _buffer.toString();
       _buffer.clear();
       _chunkedSink.addSlice(accumulated, 0, accumulated.length, true);
     } else {
@@ -344,7 +310,7 @@
   void addSlice(List<int> chunk, int startIndex, int endIndex, bool isLast) {
     _decoder.convert(chunk, startIndex, endIndex);
     if (_buffer.isNotEmpty) {
-      String accumulated = _buffer.toString();
+      var accumulated = _buffer.toString();
       _chunkedSink.addSlice(accumulated, 0, accumulated.length, isLast);
       _buffer.clear();
       return;
diff --git a/sdk/lib/convert/utf.dart b/sdk/lib/convert/utf.dart
index 13aecd8..567c8b2 100644
--- a/sdk/lib/convert/utf.dart
+++ b/sdk/lib/convert/utf.dart
@@ -4,133 +4,115 @@
 
 part of dart.convert;
 
-/** The Unicode Replacement character `U+FFFD` (�). */
+/// The Unicode Replacement character `U+FFFD` (�).
 const int unicodeReplacementCharacterRune = 0xFFFD;
 
-/** The Unicode Byte Order Marker (BOM) character `U+FEFF`. */
+/// The Unicode Byte Order Marker (BOM) character `U+FEFF`.
 const int unicodeBomCharacterRune = 0xFEFF;
 
-/**
- * An instance of the default implementation of the [Utf8Codec].
- *
- * This instance provides a convenient access to the most common UTF-8
- * use cases.
- *
- * Examples:
- *
- *     var encoded = utf8.encode("Îñţérñåţîöñåļîžåţîờñ");
- *     var decoded = utf8.decode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
- *                                0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
- */
-const Utf8Codec utf8 = const Utf8Codec();
+/// An instance of the default implementation of the [Utf8Codec].
+///
+/// This instance provides a convenient access to the most common UTF-8
+/// use cases.
+///
+/// Examples:
+///
+///     var encoded = utf8.encode("Îñţérñåţîöñåļîžåţîờñ");
+///     var decoded = utf8.decode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
+///                                0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
+const Utf8Codec utf8 = Utf8Codec();
 
-/**
- * A [Utf8Codec] encodes strings to utf-8 code units (bytes) and decodes
- * UTF-8 code units to strings.
- */
+/// A [Utf8Codec] encodes strings to utf-8 code units (bytes) and decodes
+/// UTF-8 code units to strings.
 class Utf8Codec extends Encoding {
   final bool _allowMalformed;
 
-  /**
-   * Instantiates a new [Utf8Codec].
-   *
-   * The optional [allowMalformed] argument defines how [decoder] (and [decode])
-   * deal with invalid or unterminated character sequences.
-   *
-   * If it is `true` (and not overridden at the method invocation) [decode] and
-   * the [decoder] replace invalid (or unterminated) octet
-   * sequences with the Unicode Replacement character `U+FFFD` (�). Otherwise
-   * they throw a [FormatException].
-   */
-  const Utf8Codec({bool allowMalformed: false})
+  /// Instantiates a new [Utf8Codec].
+  ///
+  /// The optional [allowMalformed] argument defines how [decoder] (and [decode])
+  /// deal with invalid or unterminated character sequences.
+  ///
+  /// If it is `true` (and not overridden at the method invocation) [decode] and
+  /// the [decoder] replace invalid (or unterminated) octet
+  /// sequences with the Unicode Replacement character `U+FFFD` (�). Otherwise
+  /// they throw a [FormatException].
+  const Utf8Codec({bool allowMalformed = false})
       : _allowMalformed = allowMalformed;
 
+  /// The name of this codec, "utf-8".
   String get name => "utf-8";
 
-  /**
-   * Decodes the UTF-8 [codeUnits] (a list of unsigned 8-bit integers) to the
-   * corresponding string.
-   *
-   * If the [codeUnits] start with the encoding of a
-   * [unicodeBomCharacterRune], that character is discarded.
-   *
-   * If [allowMalformed] is `true` the decoder replaces invalid (or
-   * unterminated) character sequences with the Unicode Replacement character
-   * `U+FFFD` (�). Otherwise it throws a [FormatException].
-   *
-   * If [allowMalformed] is not given, it defaults to the `allowMalformed` that
-   * was used to instantiate `this`.
-   */
+  /// Decodes the UTF-8 [codeUnits] (a list of unsigned 8-bit integers) to the
+  /// corresponding string.
+  ///
+  /// If the [codeUnits] start with the encoding of a
+  /// [unicodeBomCharacterRune], that character is discarded.
+  ///
+  /// If [allowMalformed] is `true` the decoder replaces invalid (or
+  /// unterminated) character sequences with the Unicode Replacement character
+  /// `U+FFFD` (�). Otherwise it throws a [FormatException].
+  ///
+  /// If [allowMalformed] is not given, it defaults to the `allowMalformed` that
+  /// was used to instantiate `this`.
   String decode(List<int> codeUnits, {bool allowMalformed}) {
-    if (allowMalformed == null) allowMalformed = _allowMalformed;
-    return new Utf8Decoder(allowMalformed: allowMalformed).convert(codeUnits);
+    allowMalformed ??= _allowMalformed;
+    return Utf8Decoder(allowMalformed: allowMalformed).convert(codeUnits);
   }
 
   Utf8Encoder get encoder => const Utf8Encoder();
   Utf8Decoder get decoder {
-    return new Utf8Decoder(allowMalformed: _allowMalformed);
+    return Utf8Decoder(allowMalformed: _allowMalformed);
   }
 }
 
-/**
- * This class converts strings to their UTF-8 code units (a list of
- * unsigned 8-bit integers).
- */
+/// This class converts strings to their UTF-8 code units (a list of
+/// unsigned 8-bit integers).
 class Utf8Encoder extends Converter<String, List<int>> {
   const Utf8Encoder();
 
-  /**
-   * Converts [string] to its UTF-8 code units (a list of
-   * unsigned 8-bit integers).
-   *
-   * If [start] and [end] are provided, only the substring
-   * `string.substring(start, end)` is converted.
-   */
+  /// Converts [string] to its UTF-8 code units (a list of
+  /// unsigned 8-bit integers).
+  ///
+  /// If [start] and [end] are provided, only the substring
+  /// `string.substring(start, end)` is converted.
   List<int> convert(String string, [int start = 0, int end]) {
-    int stringLength = string.length;
-    RangeError.checkValidRange(start, end, stringLength);
-    if (end == null) end = stringLength;
-    int length = end - start;
-    if (length == 0) return new Uint8List(0);
+    var stringLength = string.length;
+    end = RangeError.checkValidRange(start, end, stringLength);
+    var length = end - start;
+    if (length == 0) return Uint8List(0);
     // Create a new encoder with a length that is guaranteed to be big enough.
     // A single code unit uses at most 3 bytes, a surrogate pair at most 4.
-    _Utf8Encoder encoder = new _Utf8Encoder.withBufferSize(length * 3);
-    int endPosition = encoder._fillBuffer(string, start, end);
+    var encoder = _Utf8Encoder.withBufferSize(length * 3);
+    var endPosition = encoder._fillBuffer(string, start, end);
     assert(endPosition >= end - 1);
     if (endPosition != end) {
       // Encoding skipped the last code unit.
       // That can only happen if the last code unit is a leadsurrogate.
       // Force encoding of the lead surrogate by itself.
-      int lastCodeUnit = string.codeUnitAt(end - 1);
+      var lastCodeUnit = string.codeUnitAt(end - 1);
       assert(_isLeadSurrogate(lastCodeUnit));
       // We use a non-surrogate as `nextUnit` so that _writeSurrogate just
       // writes the lead-surrogate.
-      bool wasCombined = encoder._writeSurrogate(lastCodeUnit, 0);
+      var wasCombined = encoder._writeSurrogate(lastCodeUnit, 0);
       assert(!wasCombined);
     }
     return encoder._buffer.sublist(0, encoder._bufferIndex);
   }
 
-  /**
-   * Starts a chunked conversion.
-   *
-   * The converter works more efficiently if the given [sink] is a
-   * [ByteConversionSink].
-   */
+  /// Starts a chunked conversion.
+  ///
+  /// The converter works more efficiently if the given [sink] is a
+  /// [ByteConversionSink].
   StringConversionSink startChunkedConversion(Sink<List<int>> sink) {
-    if (sink is! ByteConversionSink) {
-      sink = new ByteConversionSink.from(sink);
-    }
-    return new _Utf8EncoderSink(sink);
+    return _Utf8EncoderSink(
+        sink is ByteConversionSink ? sink : ByteConversionSink.from(sink));
   }
 
   // Override the base-classes bind, to provide a better type.
   Stream<List<int>> bind(Stream<String> stream) => super.bind(stream);
 }
 
-/**
- * This class encodes Strings to UTF-8 code units (unsigned 8 bit integers).
- */
+/// This class encodes Strings to UTF-8 code units (unsigned 8 bit integers).
 // TODO(floitsch): make this class public.
 class _Utf8Encoder {
   int _carry = 0;
@@ -144,25 +126,21 @@
   _Utf8Encoder.withBufferSize(int bufferSize)
       : _buffer = _createBuffer(bufferSize);
 
-  /**
-   * Allow an implementation to pick the most efficient way of storing bytes.
-   */
-  static List<int> _createBuffer(int size) => new Uint8List(size);
+  /// Allow an implementation to pick the most efficient way of storing bytes.
+  static List<int> _createBuffer(int size) => Uint8List(size);
 
-  /**
-   * Tries to combine the given [leadingSurrogate] with the [nextCodeUnit] and
-   * writes it to [_buffer].
-   *
-   * Returns true if the [nextCodeUnit] was combined with the
-   * [leadingSurrogate]. If it wasn't then nextCodeUnit was not a trailing
-   * surrogate and has not been written yet.
-   *
-   * It is safe to pass 0 for [nextCodeUnit] in which case only the leading
-   * surrogate is written.
-   */
+  /// Tries to combine the given [leadingSurrogate] with the [nextCodeUnit] and
+  /// writes it to [_buffer].
+  ///
+  /// Returns true if the [nextCodeUnit] was combined with the
+  /// [leadingSurrogate]. If it wasn't then nextCodeUnit was not a trailing
+  /// surrogate and has not been written yet.
+  ///
+  /// It is safe to pass 0 for [nextCodeUnit] in which case only the leading
+  /// surrogate is written.
   bool _writeSurrogate(int leadingSurrogate, int nextCodeUnit) {
     if (_isTailSurrogate(nextCodeUnit)) {
-      int rune = _combineSurrogatePair(leadingSurrogate, nextCodeUnit);
+      var rune = _combineSurrogatePair(leadingSurrogate, nextCodeUnit);
       // If the rune is encoded with 2 code-units then it must be encoded
       // with 4 bytes in UTF-8.
       assert(rune > _THREE_BYTE_LIMIT);
@@ -185,15 +163,13 @@
     }
   }
 
-  /**
-   * Fills the [_buffer] with as many characters as possible.
-   *
-   * Does not encode any trailing lead-surrogate. This must be done by the
-   * caller.
-   *
-   * Returns the position in the string. The returned index points to the
-   * first code unit that hasn't been encoded.
-   */
+  /// Fills the [_buffer] with as many characters as possible.
+  ///
+  /// Does not encode any trailing lead-surrogate. This must be done by the
+  /// caller.
+  ///
+  /// Returns the position in the string. The returned index points to the
+  /// first code unit that hasn't been encoded.
   int _fillBuffer(String str, int start, int end) {
     if (start != end && _isLeadSurrogate(str.codeUnitAt(end - 1))) {
       // Don't handle a trailing lead-surrogate in this loop. The caller has
@@ -202,7 +178,7 @@
     }
     int stringIndex;
     for (stringIndex = start; stringIndex < end; stringIndex++) {
-      int codeUnit = str.codeUnitAt(stringIndex);
+      var codeUnit = str.codeUnitAt(stringIndex);
       // ASCII has the same representation in UTF-8 and UTF-16.
       if (codeUnit <= _ONE_BYTE_LIMIT) {
         if (_bufferIndex >= _buffer.length) break;
@@ -211,11 +187,11 @@
         if (_bufferIndex + 3 >= _buffer.length) break;
         // Note that it is safe to read the next code unit. We decremented
         // [end] above when the last valid code unit was a leading surrogate.
-        int nextCodeUnit = str.codeUnitAt(stringIndex + 1);
-        bool wasCombined = _writeSurrogate(codeUnit, nextCodeUnit);
+        var nextCodeUnit = str.codeUnitAt(stringIndex + 1);
+        var wasCombined = _writeSurrogate(codeUnit, nextCodeUnit);
         if (wasCombined) stringIndex++;
       } else {
-        int rune = codeUnit;
+        var rune = codeUnit;
         if (rune <= _TWO_BYTE_LIMIT) {
           if (_bufferIndex + 1 >= _buffer.length) break;
           _buffer[_bufferIndex++] = 0xC0 | (rune >> 6);
@@ -233,10 +209,8 @@
   }
 }
 
-/**
- * This class encodes chunked strings to UTF-8 code units (unsigned 8-bit
- * integers).
- */
+/// This class encodes chunked strings to UTF-8 code units (unsigned 8-bit
+/// integers).
 class _Utf8EncoderSink extends _Utf8Encoder with StringConversionSinkMixin {
   final ByteConversionSink _sink;
 
@@ -259,13 +233,13 @@
     }
 
     if (_carry != 0) {
-      int nextCodeUnit = 0;
+      var nextCodeUnit = 0;
       if (start != end) {
         nextCodeUnit = str.codeUnitAt(start);
       } else {
         assert(isLast);
       }
-      bool wasCombined = _writeSurrogate(_carry, nextCodeUnit);
+      var wasCombined = _writeSurrogate(_carry, nextCodeUnit);
       // Either we got a non-empty string, or we must not have been combined.
       assert(!wasCombined || start != end);
       if (wasCombined) start++;
@@ -273,13 +247,13 @@
     }
     do {
       start = _fillBuffer(str, start, end);
-      bool isLastSlice = isLast && (start == end);
+      var isLastSlice = isLast && (start == end);
       if (start == end - 1 && _isLeadSurrogate(str.codeUnitAt(start))) {
         if (isLast && _bufferIndex < _buffer.length - 3) {
           // There is still space for the last incomplete surrogate.
           // We use a non-surrogate as second argument. This way the
           // function will just add the surrogate-half to the buffer.
-          bool hasBeenCombined = _writeSurrogate(str.codeUnitAt(start), 0);
+          var hasBeenCombined = _writeSurrogate(str.codeUnitAt(start), 0);
           assert(!hasBeenCombined);
         } else {
           // Otherwise store it in the carry. If isLast is true, then
@@ -298,66 +272,57 @@
   // needs to deal with malformed input.
 }
 
-/**
- * This class converts UTF-8 code units (lists of unsigned 8-bit integers)
- * to a string.
- */
+/// This class converts UTF-8 code units (lists of unsigned 8-bit integers)
+/// to a string.
 class Utf8Decoder extends Converter<List<int>, String> {
   final bool _allowMalformed;
 
-  /**
-   * Instantiates a new [Utf8Decoder].
-   *
-   * The optional [allowMalformed] argument defines how [convert] deals
-   * with invalid or unterminated character sequences.
-   *
-   * If it is `true` [convert] replaces invalid (or unterminated) character
-   * sequences with the Unicode Replacement character `U+FFFD` (�). Otherwise
-   * it throws a [FormatException].
-   */
-  const Utf8Decoder({bool allowMalformed: false})
-      : this._allowMalformed = allowMalformed;
+  /// Instantiates a new [Utf8Decoder].
+  ///
+  /// The optional [allowMalformed] argument defines how [convert] deals
+  /// with invalid or unterminated character sequences.
+  ///
+  /// If it is `true` [convert] replaces invalid (or unterminated) character
+  /// sequences with the Unicode Replacement character `U+FFFD` (�). Otherwise
+  /// it throws a [FormatException].
+  const Utf8Decoder({bool allowMalformed = false})
+      : _allowMalformed = allowMalformed;
 
-  /**
-   * Converts the UTF-8 [codeUnits] (a list of unsigned 8-bit integers) to the
-   * corresponding string.
-   *
-   * Uses the code units from [start] to, but no including, [end].
-   * If [end] is omitted, it defaults to `codeUnits.length`.
-   *
-   * If the [codeUnits] start with the encoding of a
-   * [unicodeBomCharacterRune], that character is discarded.
-   */
+  /// Converts the UTF-8 [codeUnits] (a list of unsigned 8-bit integers) to the
+  /// corresponding string.
+  ///
+  /// Uses the code units from [start] to, but no including, [end].
+  /// If [end] is omitted, it defaults to `codeUnits.length`.
+  ///
+  /// If the [codeUnits] start with the encoding of a
+  /// [unicodeBomCharacterRune], that character is discarded.
   String convert(List<int> codeUnits, [int start = 0, int end]) {
     // Allow the implementation to intercept and specialize based on the type
     // of codeUnits.
-    String result = _convertIntercepted(_allowMalformed, codeUnits, start, end);
+    var result = _convertIntercepted(_allowMalformed, codeUnits, start, end);
     if (result != null) {
       return result;
     }
 
-    int length = codeUnits.length;
-    RangeError.checkValidRange(start, end, length);
-    if (end == null) end = length;
-    StringBuffer buffer = new StringBuffer();
-    _Utf8Decoder decoder = new _Utf8Decoder(buffer, _allowMalformed);
+    var length = codeUnits.length;
+    end = RangeError.checkValidRange(start, end, length);
+    var buffer = StringBuffer();
+    var decoder = _Utf8Decoder(buffer, _allowMalformed);
     decoder.convert(codeUnits, start, end);
     decoder.flush(codeUnits, end);
     return buffer.toString();
   }
 
-  /**
-   * Starts a chunked conversion.
-   *
-   * The converter works more efficiently if the given [sink] is a
-   * [StringConversionSink].
-   */
+  /// Starts a chunked conversion.
+  ///
+  /// The converter works more efficiently if the given [sink] is a
+  /// [StringConversionSink].
   ByteConversionSink startChunkedConversion(Sink<String> sink) {
     StringConversionSink stringSink;
     if (sink is StringConversionSink) {
       stringSink = sink;
     } else {
-      stringSink = new StringConversionSink.from(sink);
+      stringSink = StringConversionSink.from(sink);
     }
     return stringSink.asUtf8Sink(_allowMalformed);
   }
@@ -378,7 +343,6 @@
 const int _FOUR_BYTE_LIMIT = 0x10ffff; // 21 bits, truncated to Unicode max.
 
 // UTF-16 constants.
-const int _SURROGATE_MASK = 0xF800;
 const int _SURROGATE_TAG_MASK = 0xFC00;
 const int _SURROGATE_VALUE_MASK = 0x3FF;
 const int _LEAD_SURROGATE_MIN = 0xD800;
@@ -392,11 +356,9 @@
     0x10000 + ((lead & _SURROGATE_VALUE_MASK) << 10) |
     (tail & _SURROGATE_VALUE_MASK);
 
-/**
- * Decodes UTF-8.
- *
- * The decoder handles chunked input.
- */
+/// Decodes UTF-8.
+///
+/// The decoder handles chunked input.
 // TODO(floitsch): make this class public.
 class _Utf8Decoder {
   final bool _allowMalformed;
@@ -411,7 +373,7 @@
   bool get hasPartialInput => _expectedUnits > 0;
 
   // Limits of one through four byte encodings.
-  static const List<int> _LIMITS = const <int>[
+  static const List<int> _LIMITS = <int>[
     _ONE_BYTE_LIMIT,
     _TWO_BYTE_LIMIT,
     _THREE_BYTE_LIMIT,
@@ -422,19 +384,17 @@
     flush();
   }
 
-  /**
-   * Flushes this decoder as if closed.
-   *
-   * This method throws if the input was partial and the decoder was
-   * constructed with `allowMalformed` set to `false`.
-   *
-   * The [source] and [offset] of the current position may be provided,
-   * and are included in the exception if one is thrown.
-   */
+  /// Flushes this decoder as if closed.
+  ///
+  /// This method throws if the input was partial and the decoder was
+  /// constructed with `allowMalformed` set to `false`.
+  ///
+  /// The [source] and [offset] of the current position may be provided,
+  /// and are included in the exception if one is thrown.
   void flush([List<int> source, int offset]) {
     if (hasPartialInput) {
       if (!_allowMalformed) {
-        throw new FormatException(
+        throw FormatException(
             "Unfinished UTF-8 octet sequence", source, offset);
       }
       _stringSink.writeCharCode(unicodeReplacementCharacterRune);
@@ -445,9 +405,9 @@
   }
 
   void convert(List<int> codeUnits, int startIndex, int endIndex) {
-    int value = _value;
-    int expectedUnits = _expectedUnits;
-    int extraUnits = _extraUnits;
+    var value = _value;
+    var expectedUnits = _expectedUnits;
+    var extraUnits = _extraUnits;
     _value = 0;
     _expectedUnits = 0;
     _extraUnits = 0;
@@ -465,10 +425,10 @@
     void addSingleBytes(int from, int to) {
       assert(from >= startIndex && from <= endIndex);
       assert(to >= startIndex && to <= endIndex);
-      _stringSink.write(new String.fromCharCodes(codeUnits, from, to));
+      _stringSink.write(String.fromCharCodes(codeUnits, from, to));
     }
 
-    int i = startIndex;
+    var i = startIndex;
     loop:
     while (true) {
       multibyte:
@@ -477,11 +437,11 @@
           if (i == endIndex) {
             break loop;
           }
-          int unit = codeUnits[i];
+          var unit = codeUnits[i];
           if ((unit & 0xC0) != 0x80) {
             expectedUnits = 0;
             if (!_allowMalformed) {
-              throw new FormatException(
+              throw FormatException(
                   "Bad UTF-8 encoding 0x${unit.toRadixString(16)}",
                   codeUnits,
                   i);
@@ -499,7 +459,7 @@
           // Overly long encoding. The value could be encoded with a shorter
           // encoding.
           if (!_allowMalformed) {
-            throw new FormatException(
+            throw FormatException(
                 "Overlong encoding of 0x${value.toRadixString(16)}",
                 codeUnits,
                 i - extraUnits - 1);
@@ -509,7 +469,7 @@
         }
         if (value > _FOUR_BYTE_LIMIT) {
           if (!_allowMalformed) {
-            throw new FormatException(
+            throw FormatException(
                 "Character outside valid Unicode range: "
                 "0x${value.toRadixString(16)}",
                 codeUnits,
@@ -524,14 +484,14 @@
       }
 
       while (i < endIndex) {
-        int oneBytes = scanOneByteCharacters(codeUnits, i);
+        var oneBytes = scanOneByteCharacters(codeUnits, i);
         if (oneBytes > 0) {
           _isFirstCharacter = false;
           addSingleBytes(i, i + oneBytes);
           i += oneBytes;
           if (i == endIndex) break;
         }
-        int unit = codeUnits[i++];
+        var unit = codeUnits[i++];
         // TODO(floitsch): the way we test we could potentially allow
         // units that are too large, if they happen to have the
         // right bit-pattern. (Same is true for the multibyte loop above).
@@ -540,7 +500,7 @@
         if (unit < 0) {
           // TODO(floitsch): should this be unit <= 0 ?
           if (!_allowMalformed) {
-            throw new FormatException(
+            throw FormatException(
                 "Negative UTF-8 code unit: -0x${(-unit).toRadixString(16)}",
                 codeUnits,
                 i - 1);
@@ -565,7 +525,7 @@
             continue loop;
           }
           if (!_allowMalformed) {
-            throw new FormatException(
+            throw FormatException(
                 "Bad UTF-8 encoding 0x${unit.toRadixString(16)}",
                 codeUnits,
                 i - 1);
diff --git a/sdk/lib/core/date_time.dart b/sdk/lib/core/date_time.dart
index 75aba53..c541c66 100644
--- a/sdk/lib/core/date_time.dart
+++ b/sdk/lib/core/date_time.dart
@@ -404,10 +404,7 @@
    * See [isAtSameMomentAs] for a comparison that compares moments in time
    * independently of their zones.
    */
-  bool operator ==(other) {
-    if (!(other is DateTime)) return false;
-    return (_value == other._value && isUtc == other.isUtc);
-  }
+  external bool operator ==(dynamic other);
 
   /**
    * Returns true if [this] occurs before [other].
@@ -429,9 +426,7 @@
    * assert(!now.isBefore(now.toUtc()));
    * ```
    */
-  bool isBefore(DateTime other) {
-    return _value < other._value;
-  }
+  external bool isBefore(DateTime other);
 
   /**
    * Returns true if [this] occurs after [other].
@@ -453,9 +448,7 @@
    * assert(!now.isBefore(now.toUtc()));
    * ```
    */
-  bool isAfter(DateTime other) {
-    return _value > other._value;
-  }
+  external bool isAfter(DateTime other);
 
   /**
    * Returns true if [this] occurs at the same moment as [other].
@@ -477,9 +470,7 @@
    * assert(now.isAtSameMomentAs(now.toUtc()));
    * ```
    */
-  bool isAtSameMomentAs(DateTime other) {
-    return _value == other._value;
-  }
+  external bool isAtSameMomentAs(DateTime other);
 
   /**
    * Compares this DateTime object to [other],
@@ -489,7 +480,7 @@
    * if it [isAtSameMomentAs] [other], and returns a positive value otherwise
    * (when this [isAfter] [other]).
    */
-  int compareTo(DateTime other) => _value.compareTo(other._value);
+  external int compareTo(DateTime other);
 
   int get hashCode => (_value ^ (_value >> 30)) & 0x3FFFFFFF;
 
diff --git a/sdk/lib/core/duration.dart b/sdk/lib/core/duration.dart
index d21bb2a..7e192c2 100644
--- a/sdk/lib/core/duration.dart
+++ b/sdk/lib/core/duration.dart
@@ -23,32 +23,31 @@
  *
  * To create a new Duration object, use this class's single constructor
  * giving the appropriate arguments:
- *
- *     Duration fastestMarathon = new Duration(hours:2, minutes:3, seconds:2);
- *
+ * ```dart
+ * Duration fastestMarathon = new Duration(hours:2, minutes:3, seconds:2);
+ * ```
  * The [Duration] is the sum of all individual parts.
  * This means that individual parts can be larger than the next-bigger unit.
  * For example, [inMinutes] can be greater than 59.
- *
- *     assert(fastestMarathon.inMinutes == 123);
- *
+ * ```dart
+ * assert(fastestMarathon.inMinutes == 123);
+ * ```
  * All individual parts are allowed to be negative.
  *
  * Use one of the properties, such as [inDays],
  * to retrieve the integer value of the Duration in the specified time unit.
  * Note that the returned value is rounded down.
  * For example,
- *
- *     Duration aLongWeekend = new Duration(hours:88);
- *     assert(aLongWeekend.inDays == 3);
- *
+ * ```dart
+ * Duration aLongWeekend = new Duration(hours:88);
+ * assert(aLongWeekend.inDays == 3);
+ * ```
  * This class provides a collection of arithmetic
  * and comparison operators,
  * plus a set of constants useful for converting time units.
  *
  * See [DateTime] to represent a point in time.
  * See [Stopwatch] to measure time-spans.
- *
  */
 class Duration implements Comparable<Duration> {
   static const int microsecondsPerMillisecond = 1000;
@@ -212,17 +211,15 @@
   int get inMicroseconds => _duration;
 
   /**
-   * Returns `true` if this Duration is the same object as [other].
+   * Returns `true` if this [Duration] is the same object as [other].
    */
-  bool operator ==(other) {
-    if (other is! Duration) return false;
-    return _duration == other._duration;
-  }
+  bool operator ==(dynamic other) =>
+      other is Duration && _duration == other.inMicroseconds;
 
   int get hashCode => _duration.hashCode;
 
   /**
-   * Compares this Duration to [other], returning zero if the values are equal.
+   * Compares this [Duration] to [other], returning zero if the values are equal.
    *
    * Returns a negative integer if this `Duration` is shorter than
    * [other], or a positive integer if it is longer.
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index e569785..b772646 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -265,7 +265,7 @@
    * The [length] is the length of [indexable] at the time of the error.
    * If `length` is omitted, it defaults to `indexable.length`.
    */
-  factory RangeError.index(int index, indexable,
+  factory RangeError.index(int index, dynamic indexable,
       [String name, String message, int length]) = IndexError;
 
   /**
@@ -292,12 +292,12 @@
    * If [length] is provided, it is used as the length of the indexable object,
    * otherwise the length is found as `indexable.length`.
    */
-  static void checkValidIndex(int index, var indexable,
+  static void checkValidIndex(int index, dynamic indexable,
       [String name, int length, String message]) {
-    if (length == null) length = indexable.length;
+    length ??= indexable.length;
     // Comparing with `0` as receiver produces better dart2js type inference.
     if (0 > index || index >= length) {
-      if (name == null) name = "index";
+      name ??= "index";
       throw new RangeError.index(index, indexable, name, message, length);
     }
   }
@@ -323,12 +323,12 @@
     // Comparing with `0` as receiver produces better dart2js type inference.
     // Ditto `start > end` below.
     if (0 > start || start > length) {
-      if (startName == null) startName = "start";
+      startName ??= "start";
       throw new RangeError.range(start, 0, length, startName, message);
     }
     if (end != null) {
       if (start > end || end > length) {
-        if (endName == null) endName = "end";
+        endName ??= "end";
         throw new RangeError.range(end, start, length, endName, message);
       }
       return end;
@@ -390,10 +390,10 @@
    *
    * The message is used as part of the string representation of the error.
    */
-  IndexError(int invalidValue, indexable,
+  IndexError(int invalidValue, dynamic indexable,
       [String name, String message, int length])
       : this.indexable = indexable,
-        this.length = (length != null) ? length : indexable.length,
+        this.length = length ?? indexable.length,
         super.value(invalidValue, name,
             (message != null) ? message : "Index out of range");
 
@@ -404,6 +404,7 @@
   String get _errorName => "RangeError";
   String get _errorExplanation {
     assert(_hasValue);
+    int invalidValue = this.invalidValue;
     if (invalidValue < 0) {
       return ": index must not be negative";
     }
@@ -482,7 +483,7 @@
   @Deprecated("Use NoSuchMethod.withInvocation instead")
   external NoSuchMethodError(Object receiver, Symbol memberName,
       List positionalArguments, Map<Symbol, dynamic> namedArguments,
-      [@deprecated List existingArgumentNames = null]);
+      [@deprecated List existingArgumentNames]);
 
   external String toString();
 }
@@ -584,190 +585,3 @@
       ? "Reading static variable during its initialization"
       : "Reading static variable '$variableName' during its initialization";
 }
-
-/// Used by Fasta to wrap constant expressions so an illegal constant expression
-/// will throw an error.
-class _ConstantHelper {
-  _isNumStringBoolOrNull(Object e) {
-    return e is num || e is String || e is bool || e == null;
-  }
-
-  _isNumStringOrNull(Object e) {
-    return e is num || e is String || e == null;
-  }
-
-  _isNumOrNull(Object e) {
-    return e is num || e == null;
-  }
-
-  _isIntOrNull(Object e) {
-    return e is int || e == null;
-  }
-
-  ////////////////////////////////////////
-
-  // An expression of one of the forms e1 == e2 or e1 != e2 where e1 and e2 are
-  // constant expressions that evaluate to a numeric, string or boolean value or
-  // to null.
-
-  equals(Object e1, Object e2, Function onError) {
-    if (!_isNumStringBoolOrNull((e1)) || !_isNumStringBoolOrNull(e2)) onError();
-    return e1 == e2;
-  }
-
-  notEquals(Object e1, Object e2, Function onError) {
-    if (!_isNumStringBoolOrNull((e1)) || !_isNumStringBoolOrNull(e2)) onError();
-    return e1 != e2;
-  }
-
-  ////////////////////////////////////////
-
-  // An expression of one of the forms !e, e1 && e2 or e1 || e2 , where e, e1
-  // and e2 are constant expressions that evaluate to a boolean value.
-
-  not(Object e, Function onError) {
-    if (e is! bool) onError();
-    return !e;
-  }
-
-  logicalAnd(Object e1, Object e2, Function onError) {
-    if (e1 is! bool || e2 is! bool) onError();
-    return e1 && e2;
-  }
-
-  logicalOr(Object e1, Object e2, Function onError) {
-    if (e1 is! bool || e2 is! bool) onError();
-    return e1 || e2;
-  }
-
-  ////////////////////////////////////////
-
-  // An expression of one of the forms  ~e, e1 ˆ e2, e1 & e2, e1 | e2, e1 >> e2
-  // or e1 << e2, where e, e1 and e2 are constant expressions that evaluate to
-  // an integer value or to null.
-
-  bitwiseNot(dynamic e, Function onError) {
-    if (!_isIntOrNull(e)) onError();
-    return ~e;
-  }
-
-  bitwiseXor(dynamic e1, dynamic e2, Function onError) {
-    if (!_isIntOrNull(e1) || !_isIntOrNull(e2)) onError();
-    return e1 ^ e2;
-  }
-
-  bitwiseAnd(dynamic e1, dynamic e2, Function onError) {
-    if (!_isIntOrNull(e1) || !_isIntOrNull(e2)) onError();
-    return e1 & e2;
-  }
-
-  bitwiseOr(dynamic e1, dynamic e2, Function onError) {
-    if (!_isIntOrNull(e1) || !_isIntOrNull(e2)) onError();
-    return e1 | e2;
-  }
-
-  rightShift(dynamic e1, dynamic e2, Function onError) {
-    if (!_isIntOrNull(e1) || !_isIntOrNull(e2)) onError();
-    return e1 >> e2;
-  }
-
-  leftShift(dynamic e1, dynamic e2, Function onError) {
-    if (!_isIntOrNull(e1) || !_isIntOrNull(e2)) onError();
-    return e1 << e2;
-  }
-
-  ////////////////////////////////////////
-
-  // An expression of the form e1 + e2 where e1 and e2 are constant expressions
-  // that evaluate to a numeric or string value or to null.
-
-  plus(dynamic e1, dynamic e2, Function onError) {
-    if (!_isNumStringOrNull(e1) || !_isNumStringOrNull(e2)) onError();
-    return e1 + e2;
-  }
-
-  ////////////////////////////////////////
-
-  // An expression of one of the forms -e, e1 - e2, e1 * e2, e1 / e2, e1 ~/ e2,
-  // e1 > e2, e1 < e2, e1 >= e2, e1 <= e2 or e1 % e2, where e, e1 and e2 are
-  // constant expressions that evaluate to a numeric value or to null.
-
-  unary_minus(dynamic e, Function onError) {
-    if (!_isNumOrNull(e)) onError();
-    return -e;
-  }
-
-  minus(dynamic e1, dynamic e2, Function onError) {
-    if (!_isNumOrNull(e1) || !_isNumOrNull(e2)) onError();
-    return e1 - e2;
-  }
-
-  times(dynamic e1, dynamic e2, Function onError) {
-    if (!_isNumOrNull(e1) || !_isNumOrNull(e2)) onError();
-    return e1 * e2;
-  }
-
-  div(dynamic e1, dynamic e2, Function onError) {
-    if (!_isNumOrNull(e1) || !_isNumOrNull(e2)) onError();
-    return e1 / e2;
-  }
-
-  integerDiv(dynamic e1, dynamic e2, Function onError) {
-    if (!_isNumOrNull(e1) || !_isNumOrNull(e2)) onError();
-    return e1 ~/ e2;
-  }
-
-  greater(dynamic e1, dynamic e2, Function onError) {
-    if (!_isNumOrNull(e1) || !_isNumOrNull(e2)) onError();
-    return e1 > e2;
-  }
-
-  less(dynamic e1, dynamic e2, Function onError) {
-    if (!_isNumOrNull(e1) || !_isNumOrNull(e2)) onError();
-    return e1 < e2;
-  }
-
-  greaterEqual(dynamic e1, dynamic e2, Function onError) {
-    if (!_isNumOrNull(e1) || !_isNumOrNull(e2)) onError();
-    return e1 >= e2;
-  }
-
-  lessEqual(dynamic e1, dynamic e2, Function onError) {
-    if (!_isNumOrNull(e1) || !_isNumOrNull(e2)) onError();
-    return e1 <= e2;
-  }
-
-  mod(dynamic e1, dynamic e2, Function onError) {
-    if (!_isNumOrNull(e1) || !_isNumOrNull(e2)) onError();
-    return e1 % e2;
-  }
-
-  ////////////////////////////////////////
-
-  // An expression of the form e1 ? e2 : e3 where e1, e2 and e3 are constant
-  // expressions and e1 evaluates to a boolean value.
-
-  conditional(Object e1, Object e2, Object e3, Function onError) {
-    if (e1 is! bool) onError();
-    return e1 ? e2 : e3;
-  }
-
-  ////////////////////////////////////////
-
-  // An expression of the form e1 ?? e2 where e1 and e2 are constant expressions.
-
-  ifNull(Object e1, Object e2, Object e3, Function onError) {
-    if (e1 is! bool) onError();
-    return e1 ?? e2;
-  }
-
-  ////////////////////////////////////////
-
-  // An expression of the form e.length where e is a constant expression that
-  // evaluates to a string value.
-
-  dotLength(dynamic e, Function onError) {
-    if (e is! String) onError();
-    return e.length();
-  }
-}
diff --git a/sdk/lib/core/exceptions.dart b/sdk/lib/core/exceptions.dart
index 737fcb9..103940c 100644
--- a/sdk/lib/core/exceptions.dart
+++ b/sdk/lib/core/exceptions.dart
@@ -98,78 +98,81 @@
       report = "$report: $message";
     }
     int offset = this.offset;
-    if (source is! String) {
+    Object objectSource = this.source;
+    if (objectSource is String) {
+      String source = objectSource;
+      if (offset != null && (offset < 0 || offset > source.length)) {
+        offset = null;
+      }
+      // Source is string and offset is null or valid.
+      if (offset == null) {
+        if (source.length > 78) {
+          source = source.substring(0, 75) + "...";
+        }
+        return "$report\n$source";
+      }
+      int lineNum = 1;
+      int lineStart = 0;
+      bool previousCharWasCR = false;
+      for (int i = 0; i < offset; i++) {
+        int char = source.codeUnitAt(i);
+        if (char == 0x0a) {
+          if (lineStart != i || !previousCharWasCR) {
+            lineNum++;
+          }
+          lineStart = i + 1;
+          previousCharWasCR = false;
+        } else if (char == 0x0d) {
+          lineNum++;
+          lineStart = i + 1;
+          previousCharWasCR = true;
+        }
+      }
+      if (lineNum > 1) {
+        report += " (at line $lineNum, character ${offset - lineStart + 1})\n";
+      } else {
+        report += " (at character ${offset + 1})\n";
+      }
+      int lineEnd = source.length;
+      for (int i = offset; i < source.length; i++) {
+        int char = source.codeUnitAt(i);
+        if (char == 0x0a || char == 0x0d) {
+          lineEnd = i;
+          break;
+        }
+      }
+      int length = lineEnd - lineStart;
+      int start = lineStart;
+      int end = lineEnd;
+      String prefix = "";
+      String postfix = "";
+      if (length > 78) {
+        // Can't show entire line. Try to anchor at the nearest end, if
+        // one is within reach.
+        int index = offset - lineStart;
+        if (index < 75) {
+          end = start + 75;
+          postfix = "...";
+        } else if (end - offset < 75) {
+          start = end - 75;
+          prefix = "...";
+        } else {
+          // Neither end is near, just pick an area around the offset.
+          start = offset - 36;
+          end = offset + 36;
+          prefix = postfix = "...";
+        }
+      }
+      String slice = source.substring(start, end);
+      int markOffset = offset - start + prefix.length;
+      return "$report$prefix$slice$postfix\n${" " * markOffset}^\n";
+    } else {
+      // The source is not a string.
       if (offset != null) {
         report += " (at offset $offset)";
       }
       return report;
     }
-    if (offset != null && (offset < 0 || offset > source.length)) {
-      offset = null;
-    }
-    // Source is string and offset is null or valid.
-    if (offset == null) {
-      String source = this.source;
-      if (source.length > 78) {
-        source = source.substring(0, 75) + "...";
-      }
-      return "$report\n$source";
-    }
-    int lineNum = 1;
-    int lineStart = 0;
-    bool previousCharWasCR = false;
-    for (int i = 0; i < offset; i++) {
-      int char = source.codeUnitAt(i);
-      if (char == 0x0a) {
-        if (lineStart != i || !previousCharWasCR) {
-          lineNum++;
-        }
-        lineStart = i + 1;
-        previousCharWasCR = false;
-      } else if (char == 0x0d) {
-        lineNum++;
-        lineStart = i + 1;
-        previousCharWasCR = true;
-      }
-    }
-    if (lineNum > 1) {
-      report += " (at line $lineNum, character ${offset - lineStart + 1})\n";
-    } else {
-      report += " (at character ${offset + 1})\n";
-    }
-    int lineEnd = source.length;
-    for (int i = offset; i < source.length; i++) {
-      int char = source.codeUnitAt(i);
-      if (char == 0x0a || char == 0x0d) {
-        lineEnd = i;
-        break;
-      }
-    }
-    int length = lineEnd - lineStart;
-    int start = lineStart;
-    int end = lineEnd;
-    String prefix = "";
-    String postfix = "";
-    if (length > 78) {
-      // Can't show entire line. Try to anchor at the nearest end, if
-      // one is within reach.
-      int index = offset - lineStart;
-      if (index < 75) {
-        end = start + 75;
-        postfix = "...";
-      } else if (end - offset < 75) {
-        start = end - 75;
-        prefix = "...";
-      } else {
-        // Neither end is near, just pick an area around the offset.
-        start = offset - 36;
-        end = offset + 36;
-        prefix = postfix = "...";
-      }
-    }
-    String slice = source.substring(start, end);
-    int markOffset = offset - start + prefix.length;
-    return "$report$prefix$slice$postfix\n${" " * markOffset}^\n";
   }
 }
 
diff --git a/sdk/lib/core/int.dart b/sdk/lib/core/int.dart
index a6a9946..6964269 100644
--- a/sdk/lib/core/int.dart
+++ b/sdk/lib/core/int.dart
@@ -10,7 +10,7 @@
  * The default implementation of `int` is 64-bit two's complement integers
  * with operations that wrap to that range on overflow.
  *
- * **Note:** When compiling to JavaScript, integers are restricted to valus
+ * **Note:** When compiling to JavaScript, integers are restricted to values
  * that can be represented exactly by double-precision floating point values.
  * The available integer values include all integers between -2^53 and 2^53,
  * and some integers with larger magnitude. That includes some integers larger
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index 8aaf8e6a..1325dab 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -587,7 +587,7 @@
    * If [orElse] is omitted, it defaults to throwing a [StateError].
    */
   E lastWhere(bool test(E element), {E orElse()}) {
-    E result = null;
+    E result;
     bool foundMatching = false;
     for (E element in this) {
       if (test(element)) {
@@ -605,13 +605,12 @@
    *
    * Checks elements to see if `test(element)` returns true.
    * If exactly one element satisfies [test], that element is returned.
-   * Otherwise, if there are no matching elements, or if there is more than
-   * one matching element, the result of invoking the [orElse]
-   * function is returned.
+   * If more than one matching element is found, throws [StateError].
+   * If no matching element is found, returns the result of [orElse].
    * If [orElse] is omitted, it defaults to throwing a [StateError].
    */
   E singleWhere(bool test(E element), {E orElse()}) {
-    E result = null;
+    E result;
     bool foundMatching = false;
     for (E element in this) {
       if (test(element)) {
diff --git a/sdk/lib/core/regexp.dart b/sdk/lib/core/regexp.dart
index 95e12b5..9164fb9 100644
--- a/sdk/lib/core/regexp.dart
+++ b/sdk/lib/core/regexp.dart
@@ -40,6 +40,24 @@
    *
    * Throws a [FormatException] if [source] is not valid regular
    * expression syntax.
+   *
+   * If `multiLine` is enabled, then `^` and `$` will match the beginning and
+   * end of a _line_, in addition to matching beginning and end of input,
+   * respectively.
+   *
+   * If `caseSensitive` is disabled, then case is ignored.
+   *
+   * Example:
+   *
+   * ```dart
+   * var wordPattern = RegExp(r"(\w+)");
+   * var bracketedNumberValue = RegExp("$key: \\[\\d+\\]");
+   * ```
+   *
+   * Notice the use of a _raw string_ in the first example, and a regular
+   * string in the second. Because of the many character classes used in
+   * regular expressions, it is common to use a raw string here, unless string
+   * interpolation is required.
    */
   external factory RegExp(String source,
       {bool multiLine: false, bool caseSensitive: true});
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
index ce81a64..2d59ad4 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.dart
@@ -1256,7 +1256,7 @@
    *  * 2010:836B:4179::836B:4179
    */
   static List<int> parseIPv6Address(String host, [int start = 0, int end]) {
-    if (end == null) end = host.length;
+    end ??= host.length;
     // An IPv6 address consists of exactly 8 parts of 1-4 hex digits, separated
     // by `:`'s, with the following exceptions:
     //
@@ -1623,8 +1623,8 @@
   static Uri _makeHttpUri(String scheme, String authority, String unencodedPath,
       Map<String, String> queryParameters) {
     var userInfo = "";
-    var host = null;
-    var port = null;
+    String host;
+    int port;
 
     if (authority != null && authority.isNotEmpty) {
       var hostStart = 0;
@@ -1914,10 +1914,8 @@
   }
 
   Map<String, String> get queryParameters {
-    if (_queryParameters == null) {
-      _queryParameters =
-          new UnmodifiableMapView<String, String>(Uri.splitQueryString(query));
-    }
+    _queryParameters ??=
+        new UnmodifiableMapView<String, String>(Uri.splitQueryString(query));
     return _queryParameters;
   }
 
@@ -2009,7 +2007,7 @@
           index += 3;
           continue;
         }
-        if (buffer == null) buffer = new StringBuffer();
+        buffer ??= new StringBuffer();
         String slice = host.substring(sectionStart, index);
         if (!isNormalized) slice = slice.toLowerCase();
         buffer.write(slice);
@@ -2027,7 +2025,7 @@
       } else if (_isRegNameChar(char)) {
         if (isNormalized && _UPPER_CASE_A <= char && _UPPER_CASE_Z >= char) {
           // Put initial slice in buffer and continue in non-normalized mode
-          if (buffer == null) buffer = new StringBuffer();
+          buffer ??= new StringBuffer();
           if (sectionStart < index) {
             buffer.write(host.substring(sectionStart, index));
             sectionStart = index;
@@ -2046,7 +2044,7 @@
             sourceLength = 2;
           }
         }
-        if (buffer == null) buffer = new StringBuffer();
+        buffer ??= new StringBuffer();
         String slice = host.substring(sectionStart, index);
         if (!isNormalized) slice = slice.toLowerCase();
         buffer.write(slice);
@@ -2114,7 +2112,7 @@
     if (path != null && pathSegments != null) {
       throw new ArgumentError('Both path and pathSegments specified');
     }
-    var result;
+    String result;
     if (path != null) {
       result = _normalizeOrSubstring(path, start, end, _pathCharOrSlashTable,
           escapeDelimiters: true);
@@ -2333,7 +2331,7 @@
           }
           replacement = _escapeChar(char);
         }
-        if (buffer == null) buffer = new StringBuffer();
+        buffer ??= new StringBuffer();
         buffer.write(component.substring(sectionStart, index));
         buffer.write(replacement);
         index += sourceLength;
@@ -2625,7 +2623,7 @@
       throw new UnsupportedError(
           "Cannot extract a file path from a URI with a fragment component");
     }
-    if (windows == null) windows = _isWindows;
+    windows ??= _isWindows;
     return windows ? _toWindowsFilePath(this) : _toFilePath();
   }
 
@@ -2719,30 +2717,28 @@
 
   bool operator ==(Object other) {
     if (identical(this, other)) return true;
-    if (other is Uri) {
-      Uri uri = other;
-      return scheme == uri.scheme &&
-          hasAuthority == uri.hasAuthority &&
-          userInfo == uri.userInfo &&
-          host == uri.host &&
-          port == uri.port &&
-          path == uri.path &&
-          hasQuery == uri.hasQuery &&
-          query == uri.query &&
-          hasFragment == uri.hasFragment &&
-          fragment == uri.fragment;
-    }
-    return false;
+    return other is Uri &&
+        scheme == other.scheme &&
+        hasAuthority == other.hasAuthority &&
+        userInfo == other.userInfo &&
+        host == other.host &&
+        port == other.port &&
+        path == other.path &&
+        hasQuery == other.hasQuery &&
+        query == other.query &&
+        hasFragment == other.hasFragment &&
+        fragment == other.fragment;
   }
 
   int get hashCode {
     return _hashCodeCache ??= toString().hashCode;
   }
 
-  static List _createList() => [];
+  static List<String> _createList() => <String>[];
 
-  static Map _splitQueryStringAll(String query, {Encoding encoding: utf8}) {
-    Map result = {};
+  static Map<String, List<String>> _splitQueryStringAll(String query,
+      {Encoding encoding: utf8}) {
+    var result = <String, List<String>>{};
     int i = 0;
     int start = 0;
     int equalsIndex = -1;
@@ -3316,7 +3312,7 @@
       buffer.write(";charset=");
       buffer.write(_Uri._uriEncode(_tokenCharTable, charsetName, utf8, false));
     }
-    parameters?.forEach((var key, var value) {
+    parameters?.forEach((key, value) {
       if (key.isEmpty) {
         throw new ArgumentError.value("", "Parameter names must not be empty");
       }
@@ -3382,6 +3378,8 @@
    * content that can't be decoded successfully as a string, for example if
    * existing percent escapes represent bytes that cannot be decoded
    * by the chosen [Encoding] (see [contentAsString]).
+   *
+   * A [FormatException] is thrown if [uri] is not a valid data URI.
    */
   static UriData parse(String uri) {
     if (uri.length >= 5) {
@@ -3408,7 +3406,7 @@
   Uri get uri {
     if (_uriCache != null) return _uriCache;
     String path = _text;
-    String query = null;
+    String query;
     int colonIndex = _separatorIndices[0];
     int queryIndex = _text.indexOf('?', colonIndex + 1);
     int end = _text.length;
@@ -4597,7 +4595,7 @@
       throw new UnsupportedError(
           "Cannot extract a file path from a URI with a fragment component");
     }
-    if (windows == null) windows = _Uri._isWindows;
+    windows ??= _Uri._isWindows;
     return windows ? _Uri._toWindowsFilePath(this) : _toFilePath();
   }
 
@@ -4620,8 +4618,7 @@
 
   bool operator ==(Object other) {
     if (identical(this, other)) return true;
-    if (other is Uri) return _uri == other.toString();
-    return false;
+    return other is Uri && _uri == other.toString();
   }
 
   Uri _toNonSimple() {
diff --git a/sdk/lib/dart_client.platform b/sdk/lib/dart_client.platform
deleted file mode 100644
index 805ac5c..0000000
--- a/sdk/lib/dart_client.platform
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-# The platform for running dart on the web with dart2js.
-#
-# Includes dart:html and associated libraries.
-#
-# This configuration used to exclude dart:io, but we made it OK to import it.
-# This is allowed as a stopgap measure until config-specific imports are
-# supported in the language.  The returned library is an implementation of
-# dart:io that throws at runtime.
-
-[dart-spec]
-spec: 3rd edition.
-
-[features]
-# No extra features.
-
-[libraries]
-async: async/async.dart
-_chrome: _chrome/dart2js/chrome_dart2js.dart
-collection: collection/collection.dart
-convert: convert/convert.dart
-core: core/core.dart
-developer: developer/developer.dart
-html: html/dart2js/html_dart2js.dart
-html_common: html/html_common/html_common_dart2js.dart
-_http: unsupported:_http/http.dart
-indexed_db: indexed_db/dart2js/indexed_db_dart2js.dart
-io: unsupported:io/io.dart
-cli: unsupported:cli/cli.dart
-isolate: isolate/isolate.dart
-js: js/dart2js/js_dart2js.dart
-_js: js/_js.dart
-js_util: js_util/dart2js/js_util_dart2js.dart
-math: math/math.dart
-mirrors: mirrors/mirrors.dart
-nativewrappers: html/dartium/nativewrappers.dart
-typed_data: typed_data/typed_data.dart
-_native_typed_data: _internal/js_runtime/lib/native_typed_data.dart
-svg: svg/dart2js/svg_dart2js.dart
-web_audio: web_audio/dart2js/web_audio_dart2js.dart
-web_gl: web_gl/dart2js/web_gl_dart2js.dart
-web_sql: web_sql/dart2js/web_sql_dart2js.dart
-_internal: internal/internal.dart
-_js_helper: _internal/js_runtime/lib/js_helper.dart
-_interceptors: _internal/js_runtime/lib/interceptors.dart
-_foreign_helper: _internal/js_runtime/lib/foreign_helper.dart
-_js_names: _internal/js_runtime/lib/js_names.dart
-_js_primitives: _internal/js_runtime/lib/js_primitives.dart
-_js_embedded_names: _internal/js_runtime/lib/shared/embedded_names.dart
-_async_await_error_codes: _internal/js_runtime/lib/shared/async_await_error_codes.dart
-_metadata: html/html_common/metadata.dart
-_mirror_helper: unsupported:
diff --git a/sdk/lib/dart_server.platform b/sdk/lib/dart_server.platform
deleted file mode 100644
index 290e1ef..0000000
--- a/sdk/lib/dart_server.platform
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-# The platform for dart on the server with dart2js.
-#
-# Includes dart:io.
-# Does not include dart:html and associated libraries.
-
-[dart-spec]
-spec:3rd edition.
-
-[features]
-# No extra features.
-
-[libraries]
-async: async/async.dart
-collection: collection/collection.dart
-convert: convert/convert.dart
-core: core/core.dart
-developer: developer/developer.dart
-io: io/io.dart
-cli: cli/cli.dart
-isolate: isolate/isolate.dart
-math: math/math.dart
-mirrors: mirrors/mirrors.dart
-nativewrappers: html/dartium/nativewrappers.dart
-typed_data: typed_data/typed_data.dart
-_native_typed_data: _internal/js_runtime/lib/native_typed_data.dart
-html: unsupported:
-html_common: unsupported:
-_http: _http/http.dart
-indexed_db: unsupported:
-svg: unsupported:
-web_audio: unsupported:
-web_gl: unsupported:
-web_sql: unsupported:
-_chrome: unsupported:
-js: js/dart2js/js_dart2js.dart
-_js: js/_js.dart
-js_util: js_util/dart2js/js_util_dart2js.dart
-_mirror_helper: unsupported:
-_internal: internal/internal.dart
-_js_helper: _internal/js_runtime/lib/js_helper.dart
-_interceptors: _internal/js_runtime/lib/interceptors.dart
-_foreign_helper: _internal/js_runtime/lib/foreign_helper.dart
-_js_names: _internal/js_runtime/lib/js_names.dart
-_js_primitives: _internal/js_runtime/lib/js_primitives.dart
-_js_embedded_names: _internal/js_runtime/lib/shared/embedded_names.dart
-_async_await_error_codes: _internal/js_runtime/lib/shared/async_await_error_codes.dart
-_metadata: html/html_common/metadata.dart
diff --git a/sdk/lib/dart_shared.platform b/sdk/lib/dart_shared.platform
deleted file mode 100644
index e8aa11c..0000000
--- a/sdk/lib/dart_shared.platform
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-# A combination of the libraries for dart on the server and client.
-# For testing purposes only.
-
-[dart-spec]
-spec:3rd edition.
-
-[features]
-# No extra features.
-
-[libraries]
-async: async/async.dart
-_chrome: _chrome/dart2js/chrome_dart2js.dart
-collection: collection/collection.dart
-convert: convert/convert.dart
-core: core/core.dart
-developer: developer/developer.dart
-html: html/dart2js/html_dart2js.dart
-html_common: html/html_common/html_common_dart2js.dart
-_http: _http/http.dart
-indexed_db: indexed_db/dart2js/indexed_db_dart2js.dart
-io: io/io.dart
-cli: cli/cli.dart
-isolate: isolate/isolate.dart
-js: js/dart2js/js_dart2js.dart
-_js: js/_js.dart
-js_util: js_util/dart2js/js_util_dart2js.dart
-math: math/math.dart
-mirrors: mirrors/mirrors.dart
-nativewrappers: html/dartium/nativewrappers.dart
-typed_data: typed_data/typed_data.dart
-_native_typed_data: _internal/js_runtime/lib/native_typed_data.dart
-svg: svg/dart2js/svg_dart2js.dart
-web_audio: web_audio/dart2js/web_audio_dart2js.dart
-web_gl: web_gl/dart2js/web_gl_dart2js.dart
-web_sql: web_sql/dart2js/web_sql_dart2js.dart
-_internal: internal/internal.dart
-_js_helper: _internal/js_runtime/lib/js_helper.dart
-_interceptors: _internal/js_runtime/lib/interceptors.dart
-_foreign_helper: _internal/js_runtime/lib/foreign_helper.dart
-_js_names: _internal/js_runtime/lib/js_names.dart
-_js_primitives: _internal/js_runtime/lib/js_primitives.dart
-_js_embedded_names: _internal/js_runtime/lib/shared/embedded_names.dart
-_async_await_error_codes: _internal/js_runtime/lib/shared/async_await_error_codes.dart
-_metadata: html/html_common/metadata.dart
-_mirror_helper: unsupported:
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index a4f1b87..d5d6287 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -12387,8 +12387,10 @@
    *
    * See also:
    *
-   * * [CSS Inheritance and Cascade](http://docs.webplatform.org/wiki/tutorials/inheritance_and_cascade)
-   * * [Pseudo-elements](http://docs.webplatform.org/wiki/css/selectors/pseudo-elements)
+   * * [Cascade and Inheritance](https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS/Cascade_and_inheritance)
+   *   from MDN.
+   * * [Pseudo-elements](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements)
+   *   from MDN.
    */
   CssStyleDeclaration getComputedStyle([String pseudoElement]) {
     if (pseudoElement == null) {
@@ -12570,8 +12572,10 @@
    *
    * See also:
    *
-   * * [scrollIntoView](http://docs.webplatform.org/wiki/dom/methods/scrollIntoView)
-   * * [scrollIntoViewIfNeeded](http://docs.webplatform.org/wiki/dom/methods/scrollIntoViewIfNeeded)
+   * * [scrollIntoView](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView)
+   *   from MDN.
+   * * [scrollIntoViewIfNeeded](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded)
+   *   from MDN.
    */
   void scrollIntoView([ScrollAlignment alignment]) {
     var hasScrollIntoViewIfNeeded = true;
@@ -14039,9 +14043,9 @@
    *
    * ## Other resources
    *
-   * * [Using the fullscreen
-   *   API](http://docs.webplatform.org/wiki/tutorials/using_the_full-screen_api)
-   *   tutorial from WebPlatform.org.
+   * * [Fullscreen
+   *   API](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API)
+   *   from MDN.
    * * [Fullscreen specification](http://www.w3.org/TR/fullscreen/) from W3C.
    */
   @SupportedBrowser(SupportedBrowser.CHROME)
@@ -16845,9 +16849,9 @@
    *
    * ## Other resources
    *
-   * * [Using the fullscreen
-   *   API](http://docs.webplatform.org/wiki/tutorials/using_the_full-screen_api)
-   *   from WebPlatform.org.
+   * * [Fullscreen
+   *   API](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API)
+   *   from MDN.
    * * [Fullscreen specification](http://www.w3.org/TR/fullscreen/) from W3C.
    */
   @SupportedBrowser(SupportedBrowser.CHROME)
@@ -17092,9 +17096,6 @@
   /**
    * Creates a GET request for the specified [url].
    *
-   * The server response must be a `text/` mime type for this request to
-   * succeed.
-   *
    * This is similar to [request] but specialized for HTTP GET requests which
    * return text content.
    *
@@ -17105,7 +17106,7 @@
    *     var name = Uri.encodeQueryComponent('John');
    *     var id = Uri.encodeQueryComponent('42');
    *     HttpRequest.getString('users.json?name=$name&id=$id')
-   *       .then((HttpRequest resp) {
+   *       .then((String resp) {
    *         // Do something with the response.
    *     });
    *
@@ -17123,8 +17124,8 @@
   /**
    * Makes a server POST request with the specified data encoded as form data.
    *
-   * This is roughly the POST equivalent of getString. This method is similar
-   * to sending a FormData object with broader browser support but limited to
+   * This is roughly the POST equivalent of [getString]. This method is similar
+   * to sending a [FormData] object with broader browser support but limited to
    * String values.
    *
    * If [data] is supplied, the key/value pairs are URI encoded with
@@ -17421,11 +17422,11 @@
    * Specify the desired `url`, and `method` to use in making the request.
    *
    * By default the request is done asyncronously, with no user or password
-   * authentication information. If `async` is false, the request will be send
+   * authentication information. If `async` is false, the request will be sent
    * synchronously.
    *
    * Calling `open` again on a currently active request is equivalent to
-   * calling `abort`.
+   * calling [abort].
    *
    * Note: Most simple HTTP requests can be accomplished using the [getString],
    * [request], [requestCrossOrigin], or [postFormData] methods. Use of this
@@ -17655,7 +17656,7 @@
    * response.
    *
    * This value must be set before the request has been sent. See also the list
-   * of [IANA Official MIME types](https://www.iana.org/assignments/media-types/media-types.xhtml)
+   * of [IANA Official MIME types](https://www.iana.org/assignments/media-types/media-types.xhtml).
    */
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.FIREFOX)
@@ -30365,8 +30366,6 @@
    *
    * * [Window.open](https://developer.mozilla.org/en-US/docs/Web/API/Window.open)
    *   from MDN.
-   * * [Window open](http://docs.webplatform.org/wiki/dom/methods/open)
-   *   from WebPlatform.org.
    */
   WindowBase open(String url, String name, [String options]) {
     if (options == null) {
@@ -30753,8 +30752,8 @@
    *
    * ## Other resources
    *
-   * * [innerHeight](http://docs.webplatform.org/wiki/css/cssom/properties/innerHeight)
-   *   from WebPlatform.org.
+   * * [Window.innerHeight](https://developer.mozilla.org/en-US/docs/Web/API/Window/innerHeight)
+   *   from MDN.
    */
   final int innerHeight;
 
@@ -30763,8 +30762,8 @@
    *
    * ## Other resources
    *
-   * * [innerWidth](http://docs.webplatform.org/wiki/css/cssom/properties/innerWidth)
-   *   from WebPlatform.org.
+   * * [Window.innerWidth](https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth)
+   *   from MDN.
    */
   final int innerWidth;
 
@@ -30811,8 +30810,8 @@
    *
    * ## Other resources
    *
-   * * [Window name](http://docs.webplatform.org/wiki/html/attributes/name_(window))
-   *   from WebPlatform.org.
+   * * [Window.name](https://developer.mozilla.org/en-US/docs/Web/API/Window/name)
+   *   from MDN.
    */
   String name;
 
@@ -30832,7 +30831,7 @@
    *
    * ## Other resources
    *
-   * * [offscreenBuffering](http://docs.webplatform.org/wiki/dom/properties/offscreenBuffering)
+   * * [offscreenBuffering](https://webplatform.github.io/docs/dom/HTMLElement/offscreenBuffering/)
    *   from WebPlatform.org.
    */
   final bool offscreenBuffering;
@@ -30856,8 +30855,8 @@
    *
    * ## Other resources
    *
-   * * [outerHeight](http://docs.webplatform.org/wiki/css/cssom/properties/outerHeight)
-   *   from WebPlatform.org.
+   * * [Window.outerHeight](https://developer.mozilla.org/en-US/docs/Web/API/Window/outerHeight)
+   *   from MDN.
    */
   final int outerHeight;
 
@@ -30866,8 +30865,8 @@
    *
    * ## Other resources
    *
-   * * [outerWidth](http://docs.webplatform.org/wiki/css/cssom/properties/outerWidth)
-   *   from WebPlatform.org.
+   * * [Window.outerWidth](https://developer.mozilla.org/en-US/docs/Web/API/Window/outerWidth)
+   *   from MDN.
    */
   final int outerWidth;
 
@@ -31274,8 +31273,8 @@
    *
    * ## Other resources
    *
-   * * [Window resizeBy](http://docs.webplatform.org/wiki/dom/methods/resizeBy)
-   *   from WebPlatform.org.
+   * * [Window.resizeBy](https://developer.mozilla.org/en-US/docs/Web/API/Window/resizeBy)
+   *   from MDN.
    */
   void resizeBy(int x, int y) native;
 
@@ -31284,8 +31283,8 @@
    *
    * ## Other resources
    *
-   * * [Window resizeTo](http://docs.webplatform.org/wiki/dom/methods/resizeTo)
-   *   from WebPlatform.org.
+   * * [Window.resizeTo](https://developer.mozilla.org/en-US/docs/Web/API/Window/resizeTo)
+   *   from MDN.
    */
   void resizeTo(int x, int y) native;
 
@@ -31296,8 +31295,8 @@
    *
    * ## Other resources
    *
-   * * [Window scroll](http://docs.webplatform.org/wiki/dom/methods/scroll)
-   *   from WebPlatform.org.
+   * * [Window scroll](https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll)
+   *   from MDN.
    */
   void scroll([options_OR_x, y, Map scrollOptions]) {
     if (options_OR_x == null && y == null && scrollOptions == null) {
@@ -31333,8 +31332,8 @@
    *
    * ## Other resources
    *
-   * * [Window scroll](http://docs.webplatform.org/wiki/dom/methods/scroll)
-   *   from WebPlatform.org.
+   * * [Window scroll](https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll)
+   *   from MDN.
    */
   void _scroll_1() native;
   @JSName('scroll')
@@ -31345,8 +31344,8 @@
    *
    * ## Other resources
    *
-   * * [Window scroll](http://docs.webplatform.org/wiki/dom/methods/scroll)
-   *   from WebPlatform.org.
+   * * [Window scroll](https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll)
+   *   from MDN.
    */
   void _scroll_2(options) native;
   @JSName('scroll')
@@ -31357,8 +31356,8 @@
    *
    * ## Other resources
    *
-   * * [Window scroll](http://docs.webplatform.org/wiki/dom/methods/scroll)
-   *   from WebPlatform.org.
+   * * [Window scroll](https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll)
+   *   from MDN.
    */
   void _scroll_3(num x, num y) native;
   @JSName('scroll')
@@ -31369,8 +31368,8 @@
    *
    * ## Other resources
    *
-   * * [Window scroll](http://docs.webplatform.org/wiki/dom/methods/scroll)
-   *   from WebPlatform.org.
+   * * [Window scroll](https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll)
+   *   from MDN.
    */
   void _scroll_4(int x, int y) native;
   @JSName('scroll')
@@ -31381,8 +31380,8 @@
    *
    * ## Other resources
    *
-   * * [Window scroll](http://docs.webplatform.org/wiki/dom/methods/scroll)
-   *   from WebPlatform.org.
+   * * [Window scroll](https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll)
+   *   from MDN.
    */
   void _scroll_5(int x, int y, scrollOptions) native;
 
@@ -31391,8 +31390,8 @@
    *
    * ## Other resources
    *
-   * * [Window scrollBy](http://docs.webplatform.org/wiki/dom/methods/scrollBy)
-   *   from WebPlatform.org.
+   * * [Window scrollBy](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy)
+   *   from MDN.
    */
   void scrollBy([options_OR_x, y, Map scrollOptions]) {
     if (options_OR_x == null && y == null && scrollOptions == null) {
@@ -31426,8 +31425,8 @@
    *
    * ## Other resources
    *
-   * * [Window scrollBy](http://docs.webplatform.org/wiki/dom/methods/scrollBy)
-   *   from WebPlatform.org.
+   * * [Window scrollBy](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy)
+   *   from MDN.
    */
   void _scrollBy_1() native;
   @JSName('scrollBy')
@@ -31436,8 +31435,8 @@
    *
    * ## Other resources
    *
-   * * [Window scrollBy](http://docs.webplatform.org/wiki/dom/methods/scrollBy)
-   *   from WebPlatform.org.
+   * * [Window scrollBy](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy)
+   *   from MDN.
    */
   void _scrollBy_2(options) native;
   @JSName('scrollBy')
@@ -31446,8 +31445,8 @@
    *
    * ## Other resources
    *
-   * * [Window scrollBy](http://docs.webplatform.org/wiki/dom/methods/scrollBy)
-   *   from WebPlatform.org.
+   * * [Window scrollBy](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy)
+   *   from MDN.
    */
   void _scrollBy_3(num x, num y) native;
   @JSName('scrollBy')
@@ -31456,8 +31455,8 @@
    *
    * ## Other resources
    *
-   * * [Window scrollBy](http://docs.webplatform.org/wiki/dom/methods/scrollBy)
-   *   from WebPlatform.org.
+   * * [Window scrollBy](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy)
+   *   from MDN.
    */
   void _scrollBy_4(int x, int y) native;
   @JSName('scrollBy')
@@ -31466,8 +31465,8 @@
    *
    * ## Other resources
    *
-   * * [Window scrollBy](http://docs.webplatform.org/wiki/dom/methods/scrollBy)
-   *   from WebPlatform.org.
+   * * [Window scrollBy](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy)
+   *   from MDN.
    */
   void _scrollBy_5(int x, int y, scrollOptions) native;
 
@@ -31478,8 +31477,8 @@
    *
    * ## Other resources
    *
-   * * [Window scrollTo](http://docs.webplatform.org/wiki/dom/methods/scrollTo)
-   *   from WebPlatform.org.
+   * * [Window scrollTo](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo)
+   *   from MDN.
    */
   void scrollTo([options_OR_x, y, Map scrollOptions]) {
     if (options_OR_x == null && y == null && scrollOptions == null) {
@@ -31515,8 +31514,8 @@
    *
    * ## Other resources
    *
-   * * [Window scrollTo](http://docs.webplatform.org/wiki/dom/methods/scrollTo)
-   *   from WebPlatform.org.
+   * * [Window scrollTo](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo)
+   *   from MDN.
    */
   void _scrollTo_1() native;
   @JSName('scrollTo')
@@ -31527,8 +31526,8 @@
    *
    * ## Other resources
    *
-   * * [Window scrollTo](http://docs.webplatform.org/wiki/dom/methods/scrollTo)
-   *   from WebPlatform.org.
+   * * [Window scrollTo](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo)
+   *   from MDN.
    */
   void _scrollTo_2(options) native;
   @JSName('scrollTo')
@@ -31539,8 +31538,8 @@
    *
    * ## Other resources
    *
-   * * [Window scrollTo](http://docs.webplatform.org/wiki/dom/methods/scrollTo)
-   *   from WebPlatform.org.
+   * * [Window scrollTo](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo)
+   *   from MDN.
    */
   void _scrollTo_3(num x, num y) native;
   @JSName('scrollTo')
@@ -31551,8 +31550,8 @@
    *
    * ## Other resources
    *
-   * * [Window scrollTo](http://docs.webplatform.org/wiki/dom/methods/scrollTo)
-   *   from WebPlatform.org.
+   * * [Window scrollTo](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo)
+   *   from MDN.
    */
   void _scrollTo_4(int x, int y) native;
   @JSName('scrollTo')
@@ -31563,8 +31562,8 @@
    *
    * ## Other resources
    *
-   * * [Window scrollTo](http://docs.webplatform.org/wiki/dom/methods/scrollTo)
-   *   from WebPlatform.org.
+   * * [Window scrollTo](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo)
+   *   from MDN.
    */
   void _scrollTo_5(int x, int y, scrollOptions) native;
 
@@ -35259,7 +35258,8 @@
    *
    * See also:
    *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   * * [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
+   *   from MDN.
    */
   Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
       new _EventStream<T>(e, _eventType, useCapture);
@@ -35283,7 +35283,8 @@
    *
    * See also:
    *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   * * [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
+   *   from MDN.
    */
   ElementStream<T> forElement(Element e, {bool useCapture: false}) {
     return new _ElementEventStreamImpl<T>(e, _eventType, useCapture);
@@ -35301,7 +35302,8 @@
    *
    * See also:
    *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   * * [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
+   *   from MDN.
    */
   ElementStream<T> _forElementList(ElementList<Element> e,
       {bool useCapture: false}) {
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index 78dabae..7dd739d 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -67,8 +67,8 @@
  * check out
  * [Use IndexedDB](http://www.dartlang.org/docs/tutorials/indexeddb/).
  *
- * [IndexedDB reference](http://docs.webplatform.org/wiki/apis/indexeddb)
- * provides wiki-style docs about indexedDB
+ * MDN provides [API
+ * documentation](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API).
  *
  * {@category Web}
  */
diff --git a/sdk/lib/internal/iterable.dart b/sdk/lib/internal/iterable.dart
index 1c11e53..de62e02 100644
--- a/sdk/lib/internal/iterable.dart
+++ b/sdk/lib/internal/iterable.dart
@@ -526,7 +526,7 @@
   int _remaining;
 
   TakeIterator(this._iterator, this._remaining) {
-    assert(_remaining is int && _remaining >= 0);
+    assert(_remaining >= 0);
   }
 
   bool moveNext() {
@@ -633,7 +633,7 @@
   int _skipCount;
 
   SkipIterator(this._iterator, this._skipCount) {
-    assert(_skipCount is int && _skipCount >= 0);
+    assert(_skipCount >= 0);
   }
 
   bool moveNext() {
diff --git a/sdk/lib/io/common.dart b/sdk/lib/io/common.dart
index 74870cb..01476ea 100644
--- a/sdk/lib/io/common.dart
+++ b/sdk/lib/io/common.dart
@@ -72,7 +72,7 @@
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write("OS Error");
-    if (!message.isEmpty) {
+    if (message.isNotEmpty) {
       sb..write(": ")..write(message);
       if (errorCode != noErrorCode) {
         sb..write(", errno = ")..write(errorCode.toString());
diff --git a/sdk/lib/io/data_transformer.dart b/sdk/lib/io/data_transformer.dart
index ab0770b..2f51fe9 100644
--- a/sdk/lib/io/data_transformer.dart
+++ b/sdk/lib/io/data_transformer.dart
@@ -160,7 +160,7 @@
       this.windowBits: ZLibOption.defaultWindowBits,
       this.memLevel: ZLibOption.defaultMemLevel,
       this.strategy: ZLibOption.strategyDefault,
-      this.dictionary: null,
+      this.dictionary,
       this.raw: false,
       this.gzip: false}) {
     _validateZLibeLevel(level);
@@ -277,7 +277,7 @@
       this.windowBits: ZLibOption.defaultWindowBits,
       this.memLevel: ZLibOption.defaultMemLevel,
       this.strategy: ZLibOption.strategyDefault,
-      this.dictionary: null,
+      this.dictionary,
       this.raw: false,
       this.gzip: true}) {
     _validateZLibeLevel(level);
@@ -385,7 +385,7 @@
       this.windowBits: ZLibOption.defaultWindowBits,
       this.memLevel: ZLibOption.defaultMemLevel,
       this.strategy: ZLibOption.strategyDefault,
-      this.dictionary: null,
+      this.dictionary,
       this.raw: false}) {
     _validateZLibeLevel(level);
     _validateZLibMemLevel(memLevel);
@@ -450,7 +450,7 @@
 
   ZLibDecoder(
       {this.windowBits: ZLibOption.defaultWindowBits,
-      this.dictionary: null,
+      this.dictionary,
       this.raw: false}) {
     _validateZLibWindowBits(windowBits);
   }
@@ -629,6 +629,7 @@
         _sink.add(out);
       }
     } catch (e) {
+      // TODO(kevmoo): not sure why this isn't a try/finally
       _closed = true;
       throw e;
     }
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index ea1aa74..42d6865 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -145,7 +145,7 @@
       new Directory(_systemTemp(_Namespace._namespace));
 
   Future<Directory> createTemp([String prefix]) {
-    if (prefix == null) prefix = '';
+    prefix ??= '';
     if (path == '') {
       throw new ArgumentError("Directory.createTemp called with an empty path. "
           "To use the system temp directory, use Directory.systemTemp");
@@ -169,7 +169,7 @@
   }
 
   Directory createTempSync([String prefix]) {
-    if (prefix == null) prefix = '';
+    prefix ??= '';
     if (path == '') {
       throw new ArgumentError("Directory.createTemp called with an empty path. "
           "To use the system temp directory, use Directory.systemTemp");
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index a7f4c66..eb3db4c 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -989,7 +989,7 @@
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write("FileSystemException");
-    if (!message.isEmpty) {
+    if (message.isNotEmpty) {
       sb.write(": $message");
       if (path != null) {
         sb.write(", path = '$path'");
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index e8221bc..05508cc 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -28,7 +28,7 @@
   bool _atEnd = false;
 
   _FileStream(this._path, this._position, this._end) {
-    if (_position == null) _position = 0;
+    _position ??= 0;
   }
 
   _FileStream.forStdin() : _position = 0;
diff --git a/sdk/lib/io/io_sink.dart b/sdk/lib/io/io_sink.dart
index a8386dc..e8e4a08 100644
--- a/sdk/lib/io/io_sink.dart
+++ b/sdk/lib/io/io_sink.dart
@@ -104,6 +104,9 @@
    *
    * Returns a [Future] that completes when
    * all elements of the given [stream] are added to `this`.
+   *
+   * This function must not be called when a stream is currently being added
+   * using this function.
    */
   Future addStream(Stream<List<int>> stream);
 
diff --git a/sdk/lib/io/link.dart b/sdk/lib/io/link.dart
index 01b1d67..8b39682 100644
--- a/sdk/lib/io/link.dart
+++ b/sdk/lib/io/link.dart
@@ -22,6 +22,7 @@
     return overrides.createLink(path);
   }
 
+  @pragma("vm:entry-point")
   factory Link.fromRawPath(Uint8List rawPath) {
     // TODO(bkonyi): handle overrides
     return new _Link.fromRawPath(rawPath);
@@ -223,8 +224,8 @@
       return '\\??\\$result';
     } else {
       throw new FileSystemException(
-          'Target $result of Link.create on Windows cannot be converted' +
-              ' to start with a drive letter.  Unexpected error.');
+          'Target $result of Link.create on Windows cannot be converted'
+          ' to start with a drive letter.  Unexpected error.');
     }
   }
 
diff --git a/sdk/lib/io/platform_impl.dart b/sdk/lib/io/platform_impl.dart
index 6b918b5..a350119 100644
--- a/sdk/lib/io/platform_impl.dart
+++ b/sdk/lib/io/platform_impl.dart
@@ -38,7 +38,7 @@
 
   static String executable = _executable();
   static String resolvedExecutable = _resolvedExecutable();
-  static String packageRoot = null; // TODO(mfairhurst): remove this
+  static String packageRoot; // TODO(mfairhurst): remove this
   static String packageConfig = _packageConfig();
 
   @pragma("vm:entry-point")
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index b6c616a..769eae4 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -655,7 +655,7 @@
   final String message;
   final osError;
 
-  const SignalException(this.message, [this.osError = null]);
+  const SignalException(this.message, [this.osError]);
 
   String toString() {
     var msg = "";
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index 787762b..101ea7b 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -509,9 +509,7 @@
       this.requireClientCertificate,
       this.onBadCertificate,
       List<String> supportedProtocols) {
-    if (context == null) {
-      context = SecurityContext.defaultContext;
-    }
+    context ??= SecurityContext.defaultContext;
     _controller = new StreamController<RawSocketEvent>(
         sync: true,
         onListen: _onSubscriptionStateChange,
@@ -716,8 +714,8 @@
       return 0;
     }
     if (_status != connectedStatus) return 0;
-    if (offset == null) offset = 0;
-    if (bytes == null) bytes = data.length - offset;
+    offset ??= 0;
+    bytes ??= data.length - offset;
 
     int written =
         _secureFilter.buffers[writePlaintextId].write(data, offset, bytes);
@@ -1265,7 +1263,7 @@
   final OSError osError;
 
   @pragma("vm:entry-point")
-  const TlsException([String message = "", OSError osError = null])
+  const TlsException([String message = "", OSError osError])
       : this._("TlsException", message, osError);
 
   const TlsException._(this.type, this.message, this.osError);
@@ -1273,7 +1271,7 @@
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write(type);
-    if (!message.isEmpty) {
+    if (message.isNotEmpty) {
       sb.write(": $message");
       if (osError != null) {
         sb.write(" ($osError)");
@@ -1292,7 +1290,7 @@
 @pragma("vm:entry-point")
 class HandshakeException extends TlsException {
   @pragma("vm:entry-point")
-  const HandshakeException([String message = "", OSError osError = null])
+  const HandshakeException([String message = "", OSError osError])
       : super._("HandshakeException", message, osError);
 }
 
@@ -1303,6 +1301,6 @@
  */
 class CertificateException extends TlsException {
   @pragma("vm:entry-point")
-  const CertificateException([String message = "", OSError osError = null])
+  const CertificateException([String message = "", OSError osError])
       : super._("CertificateException", message, osError);
 }
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart
index b66e42b..fb46acf 100644
--- a/sdk/lib/io/socket.dart
+++ b/sdk/lib/io/socket.dart
@@ -823,7 +823,7 @@
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write("SocketException");
-    if (!message.isEmpty) {
+    if (message.isNotEmpty) {
       sb.write(": $message");
       if (osError != null) {
         sb.write(" ($osError)");
diff --git a/sdk/lib/io/stdio.dart b/sdk/lib/io/stdio.dart
index 241e7d2..1c1ce97 100644
--- a/sdk/lib/io/stdio.dart
+++ b/sdk/lib/io/stdio.dart
@@ -227,7 +227,7 @@
    */
   int get terminalColumns => _terminalColumns(_fd);
 
-  /*
+  /**
    * Get the number of lines of the terminal.
    *
    * If no terminal is attached to stdout, a [StdoutException] is thrown. See
@@ -268,9 +268,7 @@
    * Get a non-blocking `IOSink`.
    */
   IOSink get nonBlocking {
-    if (_nonBlocking == null) {
-      _nonBlocking = new IOSink(new _FileStreamConsumer.fromStdio(_fd));
-    }
+    _nonBlocking ??= new IOSink(new _FileStreamConsumer.fromStdio(_fd));
     return _nonBlocking;
   }
 }
@@ -405,9 +403,7 @@
 
 /// The standard input stream of data read by this program.
 Stdin get stdin {
-  if (_stdin == null) {
-    _stdin = _StdIOUtils._getStdioInputStream(_stdinFD);
-  }
+  _stdin ??= _StdIOUtils._getStdioInputStream(_stdinFD);
   return _stdin;
 }
 
@@ -417,9 +413,7 @@
 /// result in an unhandled asynchronous error unless there is an error handler
 /// on `done`.
 Stdout get stdout {
-  if (_stdout == null) {
-    _stdout = _StdIOUtils._getStdioOutputStream(_stdoutFD);
-  }
+  _stdout ??= _StdIOUtils._getStdioOutputStream(_stdoutFD);
   return _stdout;
 }
 
@@ -429,9 +423,7 @@
 /// result in an unhandled asynchronous error unless there is an error handler
 /// on `done`.
 Stdout get stderr {
-  if (_stderr == null) {
-    _stderr = _StdIOUtils._getStdioOutputStream(_stderrFD);
-  }
+  _stderr ??= _StdIOUtils._getStdioOutputStream(_stderrFD);
   return _stderr;
 }
 
diff --git a/sdk/lib/io/string_transformer.dart b/sdk/lib/io/string_transformer.dart
index 5f4a14c..f31c41e 100644
--- a/sdk/lib/io/string_transformer.dart
+++ b/sdk/lib/io/string_transformer.dart
@@ -6,20 +6,21 @@
 
 /// The current system encoding.
 ///
-/// This us used for converting from bytes to/from String when
+/// This is used for converting from bytes to and from Strings when
 /// communicating on stdin, stdout and stderr.
 ///
-/// On Windows this will use the currently active code page for the
-/// conversion. On all other systems it will always use UTF-8.
+/// On Windows this will use the currently active code page for the conversion.
+/// On all other systems it will always use UTF-8.
 const SystemEncoding systemEncoding = const SystemEncoding();
 @Deprecated("Use systemEncoding instead")
 const SystemEncoding SYSTEM_ENCODING = const SystemEncoding();
 
-/**
- * The system encoding is the current code page on Windows and UTF-8 on
- * Linux and Mac.
- */
+/// The system encoding is the current code page on Windows and UTF-8 on Linux
+/// and Mac.
 class SystemEncoding extends Encoding {
+  /// Creates a const SystemEncoding.
+  ///
+  /// Users should use the top-level constant, [systemEncoding].
   const SystemEncoding();
 
   String get name => 'system';
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index e517e0d..6e43fb7 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -554,8 +554,9 @@
     StreamController controller;
     RawReceivePort port;
     void handleError(message) {
-      String errorDescription = message[0];
-      String stackDescription = message[1];
+      List listMessage = message;
+      String errorDescription = listMessage[0];
+      String stackDescription = listMessage[1];
       var error = new RemoteError(errorDescription, stackDescription);
       controller.addError(error, error.stackTrace);
     }
diff --git a/sdk/lib/math/point.dart b/sdk/lib/math/point.dart
index af62968..f627dcf 100644
--- a/sdk/lib/math/point.dart
+++ b/sdk/lib/math/point.dart
@@ -23,10 +23,10 @@
    * `other` is a `Point` with
    * [x] equal to `other.x` and [y] equal to `other.y`.
    */
-  bool operator ==(other) {
-    if (other is! Point) return false;
-    return x == other.x && y == other.y;
-  }
+  bool operator ==(dynamic other) =>
+      // Cannot change parameter type to `Object` in case some class
+      // inherits the type and uses their argument dynamically.
+      other is Point && x == other.x && y == other.y;
 
   int get hashCode => _JenkinsSmiHash.hash2(x.hashCode, y.hashCode);
 
diff --git a/sdk/lib/math/rectangle.dart b/sdk/lib/math/rectangle.dart
index 563713c..88e0eda 100644
--- a/sdk/lib/math/rectangle.dart
+++ b/sdk/lib/math/rectangle.dart
@@ -38,13 +38,14 @@
     return 'Rectangle ($left, $top) $width x $height';
   }
 
-  bool operator ==(other) {
-    if (other is! Rectangle) return false;
-    return left == other.left &&
-        top == other.top &&
-        right == other.right &&
-        bottom == other.bottom;
-  }
+  bool operator ==(dynamic other) =>
+      // Can't change argument type to `Object` since subclasses inherit it
+      // and uses their argument dynamically.
+      other is Rectangle &&
+      left == other.left &&
+      top == other.top &&
+      right == other.right &&
+      bottom == other.bottom;
 
   int get hashCode => _JenkinsSmiHash.hash4(
       left.hashCode, top.hashCode, right.hashCode, bottom.hashCode);
diff --git a/tests/co19_2/co19_2-analyzer.status b/tests/co19_2/co19_2-analyzer.status
index 458b18f..5cb30f7 100644
--- a/tests/co19_2/co19_2-analyzer.status
+++ b/tests/co19_2/co19_2-analyzer.status
@@ -87,9 +87,6 @@
 Language/Mixins/Mixin_Application/syntax_t23: CompileTimeError # Issue 26409
 Language/Mixins/Mixin_Application/syntax_t24: CompileTimeError # Issue 26409
 Language/Mixins/Mixin_Application/syntax_t25: CompileTimeError # Issue 26409
-Language/Mixins/Mixin_Application/warning_t01: CompileTimeError # Issue 23878
-Language/Mixins/Mixin_Application/warning_t02: CompileTimeError # Issue 23878
-Language/Mixins/Mixin_Application/warning_t03: CompileTimeError # Issue 23878
 Language/Mixins/declaring_constructor_t05: MissingCompileTimeError # Issue 24767
 Language/Mixins/declaring_constructor_t06: MissingCompileTimeError # Issue 24767
 Language/Overview/Privacy/private_and_public_t11: CompileTimeError
@@ -120,53 +117,56 @@
 Language/Statements/Return/no_expression_function_t16: CompileTimeError # issue #34319
 Language/Statements/Return/no_expression_not_function_t01: CompileTimeError # issue #34319
 Language/Types/Interface_Types/subtype_t30: CompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t02: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t04: CompileTimeError # Please triage this failure
-LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l1_t03: CompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l1_t04: CompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t03: CompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t04: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t07: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t08: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l3_t02: CompileTimeError # Please triage this failure
-LanguageFeatures/Instantiate-to-bound/class/dynamic/class_typedef_l1_t04: CompileTimeError # Please triage this failure
-LanguageFeatures/Instantiate-to-bound/class/dynamic/class_typedef_l2_t01: CompileTimeError # Please triage this failure
-LanguageFeatures/Instantiate-to-bound/class/dynamic/class_typedef_l2_t02: CompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/01: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/02: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/03: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/04: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t02/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t04/none: CompileTimeError # Please triage this failure
-LanguageFeatures/Instantiate-to-bound/class/static/class_l1_t03/none: CompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/class/static/class_l1_t04/none: CompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t03/none: CompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t04/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t07/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t08/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/static/class_l3_t02/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/static/class_l4_t01/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l1_t04/none: CompileTimeError # Please triage this failure
-LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t01/none: CompileTimeError # Please triage this failure
-LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t02/none: CompileTimeError # Please triage this failure
-LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t08: CompileTimeError # Please triage this failure
-LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t03/none: CompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t02/none: CompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/01: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/02: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/03: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/04: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/05: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/06: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/07: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t05: MissingCompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t05/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t07/none: CompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/01: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/02: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/03: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/04: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/05: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/06: MissingCompileTimeError # Please triage this failure
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/07: MissingCompileTimeError # Please triage this failure
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t01/none: CompileTimeError # Please triage this failure
+LanguageFeatures/Simple-bounds/static/typedef_l2_t02/none: CompileTimeError # Please triage this failure
 LanguageFeatures/Super-bounded-types/static_analysis_A01_t02: CompileTimeError # Issue 32903
 LanguageFeatures/Super-bounded-types/static_analysis_A01_t05: CompileTimeError # Issue 32903
 LanguageFeatures/Super-bounded-types/static_analysis_A01_t08: CompileTimeError # Issue 32903
-LanguageFeatures/Super-mixins/more_specific_t01: CompileTimeError # Please triage this failure
-LanguageFeatures/Super-mixins/not_class_t02: CompileTimeError # Please triage this failure
-LanguageFeatures/Super-mixins/not_class_t03: CompileTimeError # Please triage this failure
-LanguageFeatures/Super-mixins/on_word_t02: CompileTimeError # Please triage this failure
-LanguageFeatures/Super-mixins/on_word_t03: CompileTimeError # Please triage this failure
-LanguageFeatures/Super_Mixins/declarations_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_application_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_application_t02: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_application_t03: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_application_t04: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_applying_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_member_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_member_t02: CompileTimeError
-LanguageFeatures/Super_Mixins/more_specific_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/super_invocation_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/syntax_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/syntax_t02: CompileTimeError
-LanguageFeatures/Super_Mixins/syntax_t04: CompileTimeError
 LanguageFeatures/regression/33585_t01: MissingCompileTimeError # Please triage this failure
 LanguageFeatures/regression/33585_t02: MissingCompileTimeError # Please triage this failure
 LanguageFeatures/regression/33597_t01: MissingCompileTimeError # Please triage this failure
 LanguageFeatures/regression/33701_t02: CompileTimeError # Please triage this failure
 LanguageFeatures/regression/34635_t01: CompileTimeError # Please triage this failure
 LanguageFeatures/regression/34635_t02: CompileTimeError # Please triage this failure
+LanguageFeatures/regression/34635_t03: CompileTimeError # Please triage this failure
 LibTest/async/Future/Future_A01_t01: CompileTimeError # Please triage this failure
diff --git a/tests/co19_2/co19_2-dart2js.status b/tests/co19_2/co19_2-dart2js.status
index 0f4eab7..9b8e576 100644
--- a/tests/co19_2/co19_2-dart2js.status
+++ b/tests/co19_2/co19_2-dart2js.status
@@ -71,32 +71,21 @@
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t02: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t03: Crash
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t04: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l1_t03: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t07: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t08: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l3_t02: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/dynamic/class_typedef_l1_t04: RuntimeError
-LanguageFeatures/Instantiate-to-bound/class/dynamic/class_typedef_l2_t01: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/dynamic/class_typedef_l2_t02: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t02: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t03/01: Crash
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t03/02: Crash
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t03/none: Crash
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t04/none: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/static/class_l1_t03/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t07/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t08/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_l3_t02/none: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/static/class_l4_t01/02: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l1_t04/none: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t01/none: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t02/none: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t03: RuntimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t04/none: Crash, Pass
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t05: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t07: RuntimeError
-LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t08: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t01: RuntimeError
-LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t03/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t05/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t07/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t01/none: CompileTimeError
@@ -128,11 +117,6 @@
 LanguageFeatures/Subtyping/dynamic/generated/positional_function_types_fail_global_variable_fail_A31_t01: RuntimeError
 LanguageFeatures/Subtyping/dynamic/generated/positional_function_types_fail_global_variable_fail_A32_t01: RuntimeError
 LanguageFeatures/Subtyping/dynamic/generated/positional_function_types_fail_return_value_fail_A31_t01: RuntimeError
-LanguageFeatures/Super-mixins/more_specific_t01: CompileTimeError
-LanguageFeatures/Super-mixins/not_class_t02: CompileTimeError
-LanguageFeatures/Super-mixins/not_class_t03: CompileTimeError
-LanguageFeatures/Super-mixins/on_word_t02: CompileTimeError
-LanguageFeatures/Super-mixins/on_word_t03: CompileTimeError
 LanguageFeatures/regression/33585_t01: MissingCompileTimeError
 LanguageFeatures/regression/33585_t02: MissingCompileTimeError
 LanguageFeatures/regression/33597_t01: MissingCompileTimeError
@@ -1238,6 +1222,7 @@
 WebPlatformTest/html/semantics/forms/the-meter-element/meter_t01: RuntimeError
 WebPlatformTest/html/semantics/forms/the-option-element/option-text-recurse_t01: RuntimeError
 WebPlatformTest/html/semantics/grouping-content/the-blockquote-element/grouping-blockquote_t01: RuntimeError
+WebPlatformTest/html/semantics/grouping-content/the-ol-element/ol.start-reflection_t02: RuntimeError
 WebPlatformTest/html/semantics/interactive-elements/the-dialog-element/dialog-showModal_t01: RuntimeError
 WebPlatformTest/html/semantics/scripting-1/the-script-element/script-text_t02: RuntimeError
 WebPlatformTest/html/semantics/selectors/pseudo-classes/dir_t01: RuntimeError
@@ -1332,10 +1317,15 @@
 Language/Types/Interface_Types/subtype_t23: RuntimeError
 Language/Variables/constant_variable_t09: RuntimeError
 LanguageFeatures/Instantiate-to-bound/check_types/typedef_param_t02: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t02: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t10: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t02: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_FutureOr_l1_t05: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_l1_t05: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_l1_t10: RuntimeError
+LanguageFeatures/Simple-bounds/dynamic/typedef_l2_t02: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_typedef_l1_t05: RuntimeError
+LanguageFeatures/Simple-bounds/dynamic/typedef_typedef_l1_t06: RuntimeError
 LanguageFeatures/Subtyping/dynamic/generated/named_function_types_fail_arguments_binding_fail_A51_t01: RuntimeError
 LanguageFeatures/Subtyping/dynamic/generated/named_function_types_fail_arguments_binding_fail_A51_t02: RuntimeError
 LanguageFeatures/Subtyping/dynamic/generated/named_function_types_fail_arguments_binding_fail_A53_t01: RuntimeError
@@ -1361,6 +1351,7 @@
 LanguageFeatures/Subtyping/dynamic/generated/positional_function_types_fail_local_variable_fail_A31_t01: RuntimeError
 LanguageFeatures/Subtyping/dynamic/generated/positional_function_types_fail_local_variable_fail_A32_t01: RuntimeError
 LanguageFeatures/Subtyping/dynamic/generated/positional_function_types_fail_return_value_fail_A32_t01: RuntimeError
+LanguageFeatures/Subtyping/static/generated/left_promoted_variable_arguments_binding_A03_t02: Timeout, Pass
 LanguageFeatures/regression/34803_t01: Crash
 LanguageFeatures/regression/34803_t02: Crash
 LayoutTests/fast/animation/request-animation-frame-cancel2_t01: Timeout, Pass
@@ -2149,7 +2140,6 @@
 LayoutTests/fast/dom/shadow/get-element-by-id-in-shadow-mutation_t01: RuntimeError
 LayoutTests/fast/dom/shadow/getelementbyid-shadow_t01: RuntimeError
 LayoutTests/fast/dom/shadow/host-context-pseudo-class-css-text_t01: RuntimeError
-LayoutTests/fast/dom/shadow/host-pseudo-class-css-text_t01: RuntimeError
 LayoutTests/fast/dom/shadow/host-wrapper-reclaimed_t01: RuntimeError
 LayoutTests/fast/dom/shadow/reinsert-insertion-point_t01: RuntimeError
 LayoutTests/fast/dom/shadow/remove-and-insert-style_t01: RuntimeError
@@ -2258,6 +2248,13 @@
 WebPlatformTest/webstorage/event_session_key_t01: RuntimeError
 WebPlatformTest/webstorage/storage_session_setitem_quotaexceedederr_t01: RuntimeError
 
+[ $compiler == dart2js && $runtime != chrome && $runtime != ff ]
+LayoutTests/fast/dom/shadow/host-pseudo-class-css-text_t01: RuntimeError
+
+[ $compiler == dart2js && $runtime != chrome && $runtime != ff && $runtime != safari ]
+LayoutTests/fast/dom/HTMLInputElement/input-hidden-value_t01: RuntimeError
+LayoutTests/fast/dom/MutationObserver/observe-attributes_t01: RuntimeError
+
 [ $compiler == dart2js && $runtime != chrome && $runtime != ff && $runtime != safari && !$fast_startup ]
 LayoutTests/fast/animation/request-animation-frame-callback-id_t01: RuntimeError
 LayoutTests/fast/animation/request-animation-frame-cancel_t01: RuntimeError
@@ -2668,6 +2665,7 @@
 LayoutTests/fast/files/file-reader-methods-illegal-arguments_t01: RuntimeError
 LayoutTests/fast/files/not-enough-arguments_t01: RuntimeError
 LayoutTests/fast/files/revoke-blob-url_t01: RuntimeError
+LayoutTests/fast/filesystem/input-access-entries_t01: RuntimeError
 LayoutTests/fast/flexbox/child-flexing_t01: RuntimeError
 LayoutTests/fast/flexbox/crash-anonymous-box_t01: RuntimeError
 LayoutTests/fast/flexbox/crash-button-keygen_t01: RuntimeError
@@ -3361,7 +3359,6 @@
 LayoutTests/fast/dom/HTMLSelectElement/selected-index-preserved-when-option-text-changes_t01: RuntimeError
 LayoutTests/fast/dom/MutationObserver/observe-options-attributes_t01: RuntimeError
 LayoutTests/fast/files/file-reader-readystate_t01: RuntimeError
-LayoutTests/fast/filesystem/input-access-entries_t01: RuntimeError
 LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-change-layout-by-value_t01: RuntimeError
 LayoutTests/fast/forms/date/date-input-type_t01: RuntimeError
 LayoutTests/fast/forms/date/input-valueasnumber-date_t01: RuntimeError
@@ -3431,9 +3428,8 @@
 LayoutTests/fast/dom/HTMLElement/attr-true-string_t01: RuntimeError
 LayoutTests/fast/dom/HTMLElement/set-false_t01: RuntimeError
 LayoutTests/fast/dom/HTMLElement/set-value-caseinsensitive_t01: RuntimeError
-LayoutTests/fast/dom/HTMLInputElement/input-hidden-value_t01: RuntimeError
+LayoutTests/fast/dom/HTMLInputElement/input-hidden-value_t01: Pass, RuntimeError
 LayoutTests/fast/dom/MutationObserver/database-callback-delivery_t01: RuntimeError
-LayoutTests/fast/dom/MutationObserver/observe-attributes_t01: RuntimeError
 LayoutTests/fast/dom/SelectorAPI/caseTagX_t01: RuntimeError
 LayoutTests/fast/dom/background-shorthand-csstext_t01: RuntimeError
 LayoutTests/fast/dom/boolean-attribute-reflection_t01: RuntimeError
@@ -3506,6 +3502,9 @@
 WebPlatformTest/html/semantics/forms/the-input-element/range_t02: RuntimeError
 WebPlatformTest/html/syntax/parsing/math-parse_t03: RuntimeError
 
+[ $compiler == dart2js && $runtime != chrome && $runtime != safari && !$fast_startup ]
+LayoutTests/fast/text/find-backwards_t01: RuntimeError
+
 [ $compiler == dart2js && $runtime != chrome && $system != macos ]
 LayoutTests/fast/canvas/canvas-alphaImageData-behavior_t01: RuntimeError
 LayoutTests/fast/canvas/canvas-scale-drawImage-shadow_t01: RuntimeError
@@ -3581,12 +3580,48 @@
 LanguageFeatures/Instantiate-to-bound/Callable/Callable_ret_extends_neg_assign_l1_t10: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/check_types/typedef_param_t02: RuntimeError
 LanguageFeatures/Instantiate-to-bound/class/class_extends_neg_l1_t05: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t01: Crash
+LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l1_t04: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t03: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t04: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/01: Crash
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/02: Crash
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/03: Crash
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/04: Crash
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/none: Crash
+LanguageFeatures/Instantiate-to-bound/class/static/class_l1_t04/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t03/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t04/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_l4_t01/01: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_l4_t01/03: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/function/function_ret_extends_Future_neg_assign_l1_t06: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/function/function_ret_extends_Future_neg_assign_l1_t07: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t02: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t10: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t02: RuntimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t02/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/01: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/02: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/03: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/04: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/05: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/06: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/07: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t05: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/01: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/02: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/03: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/04: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/05: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/06: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/07: MissingCompileTimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_FutureOr_l1_t05: RuntimeError, Pass
 LanguageFeatures/Simple-bounds/dynamic/typedef_l1_t05: RuntimeError, Pass
 LanguageFeatures/Simple-bounds/dynamic/typedef_l1_t10: RuntimeError, Pass
+LanguageFeatures/Simple-bounds/dynamic/typedef_l2_t02: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_typedef_l1_t05: RuntimeError
+LanguageFeatures/Simple-bounds/dynamic/typedef_typedef_l1_t06: RuntimeError
+LanguageFeatures/Simple-bounds/static/typedef_l2_t02/none: CompileTimeError
 LanguageFeatures/Subtyping/dynamic/generated/named_function_types_fail_arguments_binding_fail_A51_t01: RuntimeError
 LanguageFeatures/Subtyping/dynamic/generated/named_function_types_fail_arguments_binding_fail_A51_t02: RuntimeError
 LanguageFeatures/Subtyping/dynamic/generated/named_function_types_fail_arguments_binding_fail_A53_t01: RuntimeError
@@ -3612,8 +3647,7 @@
 LanguageFeatures/Subtyping/dynamic/generated/positional_function_types_fail_local_variable_fail_A31_t01: RuntimeError
 LanguageFeatures/Subtyping/dynamic/generated/positional_function_types_fail_local_variable_fail_A32_t01: RuntimeError
 LanguageFeatures/Subtyping/dynamic/generated/positional_function_types_fail_return_value_fail_A32_t01: RuntimeError
-LanguageFeatures/Super_Mixins/mixin_member_neg_t02: RuntimeError
-LanguageFeatures/Super_Mixins/super_invocation_t01: CompileTimeError
+LanguageFeatures/regression/34635_t03: CompileTimeError
 LanguageFeatures/regression/34803_t01: Crash, Pass
 LanguageFeatures/regression/34803_t02: Crash, Pass
 LayoutTests/fast/animation/request-animation-frame-prefix_t01: RuntimeError
@@ -5366,6 +5400,7 @@
 LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-flex-items_t01: RuntimeError
 LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-replaced-absolutes_t01: RuntimeError
 LayoutTests/fast/css-intrinsic-dimensions/width-shrinks-avoid-floats_t01: RuntimeError
+LayoutTests/fast/css/MarqueeLayoutTest_t01: RuntimeError, Pass
 LayoutTests/fast/css/aspect-ratio-inheritance_t01: RuntimeError
 LayoutTests/fast/css/auto-min-size_t01: RuntimeError
 LayoutTests/fast/css/background-serialize_t01: RuntimeError
@@ -5785,8 +5820,10 @@
 LayoutTests/fast/svg/whitespace-number_t01: RuntimeError
 LayoutTests/fast/table/incorrect-colgroup-span-values_t01: RuntimeError
 LayoutTests/fast/table/min-width-css-block-table_t01: RuntimeError
+LayoutTests/fast/table/table-colgroup-present-after-table-row_t01: Pass, RuntimeError
 LayoutTests/fast/table/table-size-integer-overflow_t01: RuntimeError
 LayoutTests/fast/table/td-bordercolor-attribute_t01: RuntimeError
+LayoutTests/fast/text/find-backwards_t01: Pass, RuntimeError
 LayoutTests/fast/text/find-kana_t01: RuntimeError
 LayoutTests/fast/text/find-russian_t01: RuntimeError
 LayoutTests/fast/text/find-soft-hyphen_t01: RuntimeError
@@ -7131,6 +7168,7 @@
 LayoutTests/fast/canvas/canvas-composite-canvas_t01: RuntimeError, Pass
 LayoutTests/fast/canvas/canvas-composite-stroke-alpha_t01: RuntimeError, Pass
 LayoutTests/fast/canvas/canvas-composite-text-alpha_t01: RuntimeError, Pass
+LayoutTests/fast/canvas/canvas-currentColor_t01: Pass, RuntimeError
 LayoutTests/fast/canvas/canvas-drawImage-scaled-copy-to-self_t01: RuntimeError
 LayoutTests/fast/canvas/canvas-fillRect_t01: RuntimeError, Pass
 LayoutTests/fast/canvas/canvas-fillStyle-no-quirks-parsing_t01: RuntimeError
@@ -7222,7 +7260,7 @@
 LayoutTests/fast/css/cursor-parsing-image-set_t01: RuntimeError
 LayoutTests/fast/css/device-aspect-ratio_t01: RuntimeError
 LayoutTests/fast/css/draggable-region-parser_t01: RuntimeError
-LayoutTests/fast/css/dynamic-class-pseudo-elements_t01: RuntimeError
+LayoutTests/fast/css/dynamic-class-pseudo-elements_t01: Pass, RuntimeError
 LayoutTests/fast/css/fixed-width-intrinsic-width-excludes-scrollbars_t01: RuntimeError
 LayoutTests/fast/css/font-face-cache-bug_t01: RuntimeError
 LayoutTests/fast/css/font-face-insert-link_t01: RuntimeError
@@ -7944,6 +7982,7 @@
 LayoutTests/fast/dom/HTMLAnchorElement/set-href-attribute-search_t01: RuntimeError, Pass
 LayoutTests/fast/forms/autofocus-input-css-style-change_t01: RuntimeError, Pass
 LayoutTests/fast/mediastream/getusermedia_t01: RuntimeError, Pass
+LayoutTests/fast/replaced/preferred-widths_t01: RuntimeError, Pass
 LayoutTests/fast/shapes/shape-outside-floats/shape-outside-floats-image-margin_t02: RuntimeError, Pass
 WebPlatformTest/dom/nodes/Document-createElementNS_t01: RuntimeError, Pass
 
@@ -7991,7 +8030,6 @@
 WebPlatformTest/dom/nodes/DOMImplementation-createDocumentType_t01: RuntimeError
 WebPlatformTest/dom/nodes/Document-createElementNS_t01: RuntimeError
 WebPlatformTest/dom/nodes/attributes/setAttributeNS_A02_t01: RuntimeError
-WebPlatformTest/html/semantics/grouping-content/the-ol-element/ol.start-reflection_t02: RuntimeError
 
 [ $compiler == dart2js && $system != macos ]
 LayoutTests/fast/text/zero-width-characters_t01: RuntimeError
diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status
index 8c374fc..3abbecc 100644
--- a/tests/co19_2/co19_2-kernel.status
+++ b/tests/co19_2/co19_2-kernel.status
@@ -1,15 +1,9 @@
 # Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
-LibTest/io/Link/rename_A02_t01: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/174
-LibTest/io/RawDatagramSocket/any_A01_t02: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
-LibTest/io/RawDatagramSocket/any_A01_t03: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
-LibTest/io/RawDatagramSocket/asBroadcastStream_A01_t02: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
-LibTest/io/RawDatagramSocket/distinct_A01_t05: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
-LibTest/io/RawDatagramSocket/lastWhere_A01_t02: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
-LibTest/io/RawDatagramSocket/timeout_A02_t01: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
-LibTest/io/RawDatagramSocket/timeout_A06_t01: Pass, Fail # Next roll might fix it (see https://github.com/dart-lang/co19/commit/8b2e2be5bc3bb9fec41efec8ac6fc777e231d915)
-LibTest/io/Stdin/readByteSync_A02_t01: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/175
+
+LibTest/io/FileSystemCreateEvent/isDirectory_A01_t06: Pass, Fail # https://github.com/dart-lang/co19/issues/186
+LibTest/io/Stdin/readLineSync_A03_t02: Pass, Fail # https://github.com/dart-lang/co19/issues/184
 
 [ $compiler == dartkp ]
 Language/Expressions/Instance_Creation/New/evaluation_t20: RuntimeError
@@ -76,6 +70,24 @@
 LibTest/typed_data/Int32List/any_A01_t01: RuntimeError
 LibTest/typed_data/Int32x4List/clear_A01_t01: RuntimeError
 
+[ $compiler == fasta ]
+Language/Statements/For/syntax_t13: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
+Language/Statements/For/syntax_t20: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
+Language/Statements/For/syntax_t20 tatements/For/syntax_t20: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
+
+[ $runtime == vm ]
+LibTest/io/FileSystemEntity/*: Skip # Temporary skip these tests
+LibTest/io/Link/rename_A02_t01: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/174
+LibTest/io/RawDatagramSocket/any_A01_t02: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
+LibTest/io/RawDatagramSocket/any_A01_t03: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
+LibTest/io/RawDatagramSocket/asBroadcastStream_A01_t02: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
+LibTest/io/RawDatagramSocket/distinct_A01_t05: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
+LibTest/io/RawDatagramSocket/lastWhere_A01_t02: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
+LibTest/io/RawDatagramSocket/listen_A02_t02: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
+LibTest/io/RawDatagramSocket/timeout_A02_t01: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/170
+LibTest/io/RawDatagramSocket/timeout_A06_t01: Pass, Fail # Next roll might fix it (see https://github.com/dart-lang/co19/commit/8b2e2be5bc3bb9fec41efec8ac6fc777e231d915)
+LibTest/io/Stdin/last_A02_t01: Pass, Fail # Issue https://github.com/dart-lang/co19/issues/182
+
 [ $fasta ]
 Language/Classes/Abstract_Instance_Members/override_default_value_t01: MissingCompileTimeError # Issue 34190
 Language/Classes/Abstract_Instance_Members/override_default_value_t02: MissingCompileTimeError # Issue 34190
@@ -186,9 +198,6 @@
 Language/Mixins/Mixin_Application/superclass_t01: MissingCompileTimeError
 Language/Mixins/Mixin_Application/superclass_t02: MissingCompileTimeError
 Language/Mixins/Mixin_Application/superinterfaces_t07: MissingCompileTimeError
-Language/Mixins/Mixin_Application/warning_t01: CompileTimeError # Expects a warning, but this is an error in Dart 2
-Language/Mixins/Mixin_Application/warning_t02: CompileTimeError # Expects a warning, but this is an error in Dart 2
-Language/Mixins/Mixin_Application/warning_t03: CompileTimeError # Expects a warning, but this is an error in Dart 2
 Language/Mixins/declaring_constructor_t05: MissingCompileTimeError # Mixin constructor
 Language/Mixins/declaring_constructor_t06: MissingCompileTimeError # Mixin constructor
 Language/Overview/Privacy/private_and_public_t11: CompileTimeError
@@ -207,63 +216,69 @@
 Language/Statements/Continue/label_t07: MissingCompileTimeError # Issue 34206
 Language/Statements/Try/catch_scope_t01: CompileTimeError
 Language/Types/Interface_Types/subtype_t30: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t01: Crash
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t02: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t03: Crash
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_FutureOr_l1_t04: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l1_t03: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l1_t04: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t03: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t04: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t07: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t08: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l3_t02: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/dynamic/class_typedef_l1_t04: RuntimeError
-LanguageFeatures/Instantiate-to-bound/class/dynamic/class_typedef_l2_t01: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/dynamic/class_typedef_l2_t02: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t02: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/01: Crash
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/02: Crash
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/03: Crash
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/04: Crash
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t01/none: Crash
+LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t02/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t03/01: Crash
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t03/02: Crash
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t03/none: Crash
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t04/none: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/static/class_l1_t03/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_l1_t04/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t03/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t04/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t07/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t08/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_l3_t02/none: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/static/class_l4_t01/02: MissingCompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l1_t04/none: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t01/none: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t02/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_l4_t01/01: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_l4_t01/03: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l1_t04/01: Crash, Pass
+LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l1_t04/02: Crash, Pass
+LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l1_t04/none: Crash
+LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t04/01: Crash, Pass
+LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l2_t04/none: Crash, Pass
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t07: RuntimeError
-LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t08: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t03/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t02/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/01: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/02: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/03: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/04: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/05: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/06: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t04/07: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t05: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t05/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t07/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/01: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/02: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/03: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/04: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/05: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/06: MissingCompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t09/07: MissingCompileTimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l2_t01/none: CompileTimeError
 LanguageFeatures/Simple-bounds/dynamic/class_FutureOr_l1_t02: CompileTimeError
 LanguageFeatures/Simple-bounds/static/class_FutureOr_l1_t02: CompileTimeError
-LanguageFeatures/Super-mixins/more_specific_t01: CompileTimeError
-LanguageFeatures/Super-mixins/not_class_t02: CompileTimeError
-LanguageFeatures/Super-mixins/not_class_t03: CompileTimeError
-LanguageFeatures/Super-mixins/on_word_t02: CompileTimeError
-LanguageFeatures/Super-mixins/on_word_t03: CompileTimeError
-LanguageFeatures/Super_Mixins/declarations_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_application_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_application_t02: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_application_t03: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_application_t04: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_applying_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_member_neg_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_member_neg_t02: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_member_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/mixin_member_t02: CompileTimeError
-LanguageFeatures/Super_Mixins/more_specific_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/super_invocation_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/syntax_t01: CompileTimeError
-LanguageFeatures/Super_Mixins/syntax_t02: CompileTimeError
-LanguageFeatures/Super_Mixins/syntax_t04: CompileTimeError
+LanguageFeatures/Simple-bounds/static/typedef_l2_t02/none: CompileTimeError
 LanguageFeatures/regression/33585_t01: MissingCompileTimeError
 LanguageFeatures/regression/33585_t02: MissingCompileTimeError
 LanguageFeatures/regression/33597_t01: MissingCompileTimeError
 LanguageFeatures/regression/33701_t01: MissingCompileTimeError
 LanguageFeatures/regression/34635_t01: CompileTimeError
 LanguageFeatures/regression/34635_t02: CompileTimeError
+LanguageFeatures/regression/34635_t03: CompileTimeError
 LanguageFeatures/regression/34803_t01: Crash
 LanguageFeatures/regression/34803_t02: Crash
 LibTest/async/Future/Future_A01_t01: CompileTimeError
@@ -280,6 +295,7 @@
 LibTest/io/Stdout/writeCharCode_A01_t03: Timeout, Pass
 
 [ $arch == simdbc64 && ($compiler == dartk || $compiler == dartkb) ]
+LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l1_t04/none: CompileTimeError
 LibTest/collection/ListBase/ListBase_class_A01_t02: Timeout, Pass
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Timeout, Pass
 LibTest/io/Link/renameSync_A02_t01: RuntimeError, Pass
@@ -375,35 +391,33 @@
 LibTest/io/Directory/watch_A02_t01: RuntimeError, Pass
 LibTest/io/FileSystemCreateEvent/isDirectory_A01_t03: RuntimeError, Pass
 LibTest/io/FileSystemCreateEvent/isDirectory_A01_t04: RuntimeError, Pass
-LibTest/io/FileSystemCreateEvent/isDirectory_A01_t05: RuntimeError, Pass
+LibTest/io/FileSystemCreateEvent/isDirectory_A01_t05: RuntimeError, Pass, Timeout
+LibTest/io/FileSystemCreateEvent/isDirectory_A01_t06: Timeout, Pass
 LibTest/io/FileSystemCreateEvent/type_A01_t01: RuntimeError, Pass
 LibTest/io/FileSystemCreateEvent/type_A01_t02: RuntimeError, Pass
-LibTest/io/FileSystemCreateEvent/type_A01_t03: RuntimeError, Pass
-LibTest/io/FileSystemDeleteEvent/isDirectory_A01_t01: RuntimeError
-LibTest/io/FileSystemDeleteEvent/isDirectory_A01_t02: RuntimeError
-LibTest/io/FileSystemDeleteEvent/isDirectory_A01_t03: RuntimeError
-LibTest/io/FileSystemDeleteEvent/isDirectory_A01_t04: RuntimeError
-LibTest/io/FileSystemDeleteEvent/isDirectory_A01_t05: RuntimeError
-LibTest/io/FileSystemDeleteEvent/path_A01_t01: RuntimeError
-LibTest/io/FileSystemDeleteEvent/path_A01_t02: RuntimeError
-LibTest/io/FileSystemDeleteEvent/path_A01_t03: RuntimeError
-LibTest/io/FileSystemDeleteEvent/type_A01_t01: RuntimeError
-LibTest/io/FileSystemDeleteEvent/type_A01_t02: RuntimeError
-LibTest/io/FileSystemDeleteEvent/type_A01_t03: RuntimeError
+LibTest/io/FileSystemCreateEvent/type_A01_t03: RuntimeError, Pass, Timeout
+LibTest/io/FileSystemDeleteEvent/isDirectory_A01_t01: RuntimeError, Timeout
+LibTest/io/FileSystemDeleteEvent/path_A01_t02: RuntimeError, Pass
+LibTest/io/FileSystemDeleteEvent/path_A01_t03: RuntimeError, Pass
+LibTest/io/FileSystemDeleteEvent/type_A01_t03: RuntimeError, Pass
 LibTest/io/FileSystemEntity/isWatchSupported_A01_t01: RuntimeError
-LibTest/io/FileSystemModifyEvent/contentChanged_A01_t01: Fail
-LibTest/io/FileSystemMoveEvent/destination_A01_t01: Fail
-LibTest/io/FileSystemMoveEvent/destination_A01_t02: Fail
-LibTest/io/FileSystemMoveEvent/destination_A01_t03: RuntimeError, Fail
-LibTest/io/FileSystemMoveEvent/isDirectory_A01_t01: Fail
-LibTest/io/FileSystemMoveEvent/isDirectory_A01_t02: Fail
-LibTest/io/FileSystemMoveEvent/isDirectory_A01_t03: Fail
-LibTest/io/FileSystemMoveEvent/path_A01_t01: Fail
-LibTest/io/FileSystemMoveEvent/path_A01_t02: Fail
-LibTest/io/FileSystemMoveEvent/path_A01_t03: Fail
-LibTest/io/FileSystemMoveEvent/type_A01_t01: Fail
-LibTest/io/FileSystemMoveEvent/type_A01_t02: Fail
-LibTest/io/FileSystemMoveEvent/type_A01_t03: Fail
+LibTest/io/FileSystemModifyEvent/contentChanged_A01_t01: Fail, Timeout
+LibTest/io/FileSystemModifyEvent/contentChanged_A01_t02: Timeout, Pass
+LibTest/io/FileSystemModifyEvent/isDirectory_A01_t01: Timeout, Pass
+LibTest/io/FileSystemModifyEvent/path_A01_t02: Timeout, Pass
+LibTest/io/FileSystemModifyEvent/type_A01_t01: Timeout, Pass
+LibTest/io/FileSystemMoveEvent/destination_A01_t01: Fail, Timeout
+LibTest/io/FileSystemMoveEvent/destination_A01_t02: Fail, Timeout
+LibTest/io/FileSystemMoveEvent/destination_A01_t03: RuntimeError, Fail, Timeout
+LibTest/io/FileSystemMoveEvent/isDirectory_A01_t01: Fail, Timeout
+LibTest/io/FileSystemMoveEvent/isDirectory_A01_t02: Fail, Timeout
+LibTest/io/FileSystemMoveEvent/isDirectory_A01_t03: Fail, Timeout
+LibTest/io/FileSystemMoveEvent/path_A01_t01: Fail, Timeout
+LibTest/io/FileSystemMoveEvent/path_A01_t02: Fail, Timeout
+LibTest/io/FileSystemMoveEvent/path_A01_t03: Fail, Timeout
+LibTest/io/FileSystemMoveEvent/type_A01_t01: Fail, Timeout
+LibTest/io/FileSystemMoveEvent/type_A01_t02: Fail, Timeout
+LibTest/io/FileSystemMoveEvent/type_A01_t03: Fail, Timeout
 LibTest/io/HttpClientRequest/contentLength_A02_t01: RuntimeError, Pass
 LibTest/io/HttpClientRequest/headers_A03_t01: RuntimeError, Pass
 LibTest/io/Link/stat_A01_t01: RuntimeError
@@ -523,6 +537,9 @@
 LibTest/math/atan_A01_t01: RuntimeError
 LibTest/math/cos_A01_t01: RuntimeError
 
+[ $runtime == vm && $system != macos ]
+LibTest/io/FileSystemDeleteEvent/isDirectory_A01_t07: Fail # Issue 35032
+
 [ $runtime == vm && $system != macos && ($compiler == dartk || $compiler == dartkb) ]
 LibTest/io/Directory/listSync_A01_t02: RuntimeError
 LibTest/io/Directory/listSync_A01_t03: RuntimeError
@@ -543,10 +560,12 @@
 Language/Mixins/Mixin_Application/syntax_t16: CompileTimeError
 Language/Statements/Assert/execution_t08: RuntimeError
 Language/Types/Function_Types/call_t01: RuntimeError
-LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l1_t03: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_FutureOr_l1_t04/none: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t08/none: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/class/static/class_typedef_l1_t04/none: DartkCrash
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t02: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/static/typedef_l1_t05/none: CompileTimeError
+LanguageFeatures/Simple-bounds/dynamic/typedef_l2_t02: RuntimeError
 LanguageFeatures/regression/33701_t01: MissingCompileTimeError
 LanguageFeatures/regression/34803_t01: DartkCrash
 LanguageFeatures/regression/34803_t02: DartkCrash
@@ -591,9 +610,11 @@
 LibTest/core/int/isOdd_A01_t01: RuntimeError
 LibTest/io/Cookie/Cookie_A01_t04: RuntimeError
 LibTest/io/Directory/watch_A01_t01: Fail, Pass
+LibTest/io/Directory/watch_A02_t01: Timeout
 LibTest/io/FileSystemCreateEvent/isDirectory_A01_t01: Fail, Pass
 LibTest/io/FileSystemCreateEvent/isDirectory_A01_t02: Fail, Pass
 LibTest/io/FileSystemCreateEvent/path_A01_t01: Fail, Pass
+LibTest/io/FileSystemEntity/identical_A01_t06: Pass, RuntimeError # Issue 183 (co19)
 LibTest/io/FileSystemModifyEvent/isDirectory_A01_t02: Fail
 LibTest/io/FileSystemModifyEvent/path_A01_t01: Fail
 LibTest/io/FileSystemModifyEvent/type_A01_t02: Fail
@@ -623,11 +644,11 @@
 LibTest/io/ProcessResult/stdout_A01_t02: RuntimeError
 LibTest/io/RandomAccessFile/writeByte_A01_t01: RuntimeError, Pass
 LibTest/io/RawDatagramSocket/any_A01_t04: RuntimeError, Pass
-LibTest/io/RawDatagramSocket/any_A01_t05: RuntimeError
-LibTest/io/RawDatagramSocket/any_A01_t06: RuntimeError
-LibTest/io/RawDatagramSocket/any_A02_t01: RuntimeError
-LibTest/io/RawDatagramSocket/any_A02_t02: RuntimeError
-LibTest/io/RawDatagramSocket/any_A02_t03: RuntimeError
+LibTest/io/RawDatagramSocket/any_A01_t05: RuntimeError, Pass
+LibTest/io/RawDatagramSocket/any_A01_t06: RuntimeError, Pass
+LibTest/io/RawDatagramSocket/any_A02_t01: RuntimeError, Pass
+LibTest/io/RawDatagramSocket/any_A02_t02: RuntimeError, Pass
+LibTest/io/RawDatagramSocket/any_A02_t03: RuntimeError, Pass
 LibTest/io/RawDatagramSocket/any_A02_t04: RuntimeError, Pass
 LibTest/io/RawDatagramSocket/asBroadcastStream_A01_t03: RuntimeError, Pass
 LibTest/io/RawDatagramSocket/asBroadcastStream_A02_t02: Timeout, Pass
@@ -865,9 +886,7 @@
 Language/Variables/constant_variable_t09: RuntimeError
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_l2_t05: CompileTimeError
 LanguageFeatures/Instantiate-to-bound/class/static/class_l2_t05/none: CompileTimeError
-LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t03: RuntimeError
-LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t05: RuntimeError
-LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t08: CompileTimeError
+LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t02: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t01: RuntimeError
 LibTest/async/Future/asStream_A01_t02: RuntimeError
 LibTest/async/Stream/Stream.fromFutures_A04_t02: RuntimeError
@@ -1004,7 +1023,6 @@
 LibTest/io/Directory/rename_A02_t01: RuntimeError
 LibTest/io/Directory/statSync_A01_t05: RuntimeError
 LibTest/io/Directory/stat_A01_t05: RuntimeError
-LibTest/io/File/absolute_A01_t01: RuntimeError
 LibTest/io/File/openRead_A01_t04: RuntimeError
 LibTest/io/File/openRead_A02_t01: RuntimeError
 LibTest/io/File/openSync_A01_t03: RuntimeError
@@ -1016,19 +1034,14 @@
 LibTest/io/FileStat/modeString_A01_t01: RuntimeError
 LibTest/io/FileStat/mode_A01_t01: RuntimeError
 LibTest/io/FileStat/modified_A01_t01: RuntimeError
-LibTest/io/FileSystemCreateEvent/isDirectory_A01_t06: RuntimeError
 LibTest/io/FileSystemCreateEvent/path_A01_t02: RuntimeError, Fail, Pass
-LibTest/io/FileSystemCreateEvent/path_A01_t03: RuntimeError, Fail, Pass
-LibTest/io/FileSystemDeleteEvent/isDirectory_A01_t06: RuntimeError
+LibTest/io/FileSystemCreateEvent/path_A01_t03: RuntimeError, Fail, Pass, Timeout
 LibTest/io/FileSystemEntity/isDirectorySync_A01_t03: RuntimeError
 LibTest/io/FileSystemEntity/isDirectory_A01_t03: RuntimeError
 LibTest/io/FileSystemEntity/isFileSync_A01_t03: RuntimeError
 LibTest/io/FileSystemEntity/isFile_A01_t01: RuntimeError
 LibTest/io/FileSystemEntity/isFile_A01_t03: RuntimeError
-LibTest/io/FileSystemModifyEvent/contentChanged_A01_t01: RuntimeError
-LibTest/io/FileSystemModifyEvent/isDirectory_A01_t02: RuntimeError
 LibTest/io/FileSystemModifyEvent/path_A01_t01: RuntimeError
-LibTest/io/FileSystemModifyEvent/type_A01_t02: RuntimeError
 LibTest/io/HttpClient/addCredentials_A03_t01: RuntimeError
 LibTest/io/HttpClient/addProxyCredentials_A03_t01: RuntimeError
 LibTest/io/HttpClient/authenticateProxy_A01_t01: RuntimeError
diff --git a/tests/compiler/dart2js/analyses/analysis_helper.dart b/tests/compiler/dart2js/analyses/analysis_helper.dart
index 76f4a89..cbfbbb8b 100644
--- a/tests/compiler/dart2js/analyses/analysis_helper.dart
+++ b/tests/compiler/dart2js/analyses/analysis_helper.dart
@@ -5,6 +5,7 @@
 import 'dart:convert' as json;
 import 'dart:io';
 
+import 'package:args/args.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
@@ -21,38 +22,65 @@
 import 'package:kernel/type_algebra.dart' as ir;
 import 'package:kernel/type_environment.dart' as ir;
 
+import '../helpers/args_helper.dart';
 import '../helpers/memory_compiler.dart';
 
-run(Uri entryPoint, String allowedListPath, List<String> analyzedPaths,
+main(List<String> args) {
+  ArgParser argParser = createArgParser();
+  ArgResults argResults = argParser.parse(args);
+
+  Uri entryPoint = getEntryPoint(argResults);
+  if (entryPoint == null) {
+    throw new ArgumentError("Missing entry point.");
+  }
+  Uri librariesSpecificationUri = getLibrariesSpec(argResults);
+  Uri packageConfig = getPackages(argResults);
+  List<String> options = getOptions(argResults);
+  run(entryPoint, null,
+      analyzedUrisFilter: (Uri uri) => uri.scheme != 'dart',
+      librariesSpecificationUri: librariesSpecificationUri,
+      packageConfig: packageConfig,
+      options: options);
+}
+
+run(Uri entryPoint, String allowedListPath,
     {Map<String, String> memorySourceFiles = const {},
+    Uri librariesSpecificationUri,
+    Uri packageConfig,
     bool verbose = false,
-    bool generate = false}) {
+    bool generate = false,
+    List<String> options = const <String>[],
+    bool analyzedUrisFilter(Uri uri)}) {
   asyncTest(() async {
-    Compiler compiler = await compilerFor(memorySourceFiles: memorySourceFiles);
+    Compiler compiler = await compilerFor(
+        memorySourceFiles: memorySourceFiles,
+        librariesSpecificationUri: librariesSpecificationUri,
+        packageConfig: packageConfig,
+        options: options);
     LoadedLibraries loadedLibraries =
         await compiler.libraryLoader.loadLibraries(entryPoint);
     new DynamicVisitor(compiler.reporter, loadedLibraries.component,
-            allowedListPath, analyzedPaths)
+            allowedListPath, analyzedUrisFilter)
         .run(verbose: verbose, generate: generate);
   });
 }
 
-class DynamicVisitor extends StaticTypeTraversalVisitor {
+class DynamicVisitor extends StaticTypeVisitor {
   final DiagnosticReporter reporter;
   final ir.Component component;
   final String _allowedListPath;
-  final List<String> analyzedPaths;
+  final bool Function(Uri uri) analyzedUrisFilter;
 
   Map _expectedJson = {};
   Map<String, Map<String, List<DiagnosticMessage>>> _actualMessages = {};
 
-  DynamicVisitor(
-      this.reporter, this.component, this._allowedListPath, this.analyzedPaths)
+  DynamicVisitor(this.reporter, this.component, this._allowedListPath,
+      this.analyzedUrisFilter)
       : super(new ir.TypeEnvironment(
             new ir.CoreTypes(component), new ir.ClassHierarchy(component)));
 
   void run({bool verbose = false, bool generate = false}) {
-    if (!generate) {
+    if (!generate && _allowedListPath != null) {
       File file = new File(_allowedListPath);
       if (file.existsSync()) {
         try {
@@ -63,7 +91,7 @@
       }
     }
     component.accept(this);
-    if (generate) {
+    if (generate && _allowedListPath != null) {
       Map<String, Map<String, int>> actualJson = {};
       _actualMessages.forEach(
           (String uri, Map<String, List<DiagnosticMessage>> actualMessagesMap) {
@@ -210,55 +238,50 @@
 
   ir.DartType visitNode(ir.Node node) {
     ir.DartType staticType = node?.accept(this);
-    assert(node is! ir.Expression ||
-        staticType == _getStaticTypeFromExpression(node));
+    assert(
+        node is! ir.Expression ||
+            staticType == _getStaticTypeFromExpression(node),
+        "Static type mismatch for ${node.runtimeType}: "
+        "Found ${staticType}, expected ${_getStaticTypeFromExpression(node)}.");
     return staticType;
   }
 
   @override
   Null visitLibrary(ir.Library node) {
-    for (String path in analyzedPaths) {
-      if ('${node.importUri}'.startsWith(path)) {
-        return super.visitLibrary(node);
+    if (analyzedUrisFilter != null) {
+      if (analyzedUrisFilter(node.importUri)) {
+        super.visitLibrary(node);
       }
+    } else {
+      super.visitLibrary(node);
     }
   }
 
   @override
-  ir.DartType visitPropertyGet(ir.PropertyGet node) {
-    ir.DartType receiverType = visitNode(node.receiver);
-    ir.DartType result = computePropertyGetType(node, receiverType);
-    receiverType = narrowInstanceReceiver(node.interfaceTarget, receiverType);
+  void handlePropertyGet(
+      ir.PropertyGet node, ir.DartType receiverType, ir.DartType resultType) {
     if (receiverType is ir.DynamicType) {
       reportError(node, "Dynamic access of '${node.name}'.");
     }
-    return result;
   }
 
   @override
-  ir.DartType visitPropertySet(ir.PropertySet node) {
-    ir.DartType receiverType = visitNode(node.receiver);
-    ir.DartType result = visitNode(node.value);
-    receiverType = narrowInstanceReceiver(node.interfaceTarget, receiverType);
+  void handlePropertySet(
+      ir.PropertySet node, ir.DartType receiverType, ir.DartType valueType) {
     if (receiverType is ir.DynamicType) {
       reportError(node, "Dynamic update to '${node.name}'.");
     }
-    return result;
   }
 
   @override
-  ir.DartType visitMethodInvocation(ir.MethodInvocation node) {
-    ir.DartType receiverType = visitNode(node.receiver);
-    ir.DartType result = computeMethodInvocationType(node, receiverType);
-    if (!isSpecialCasedBinaryOperator(node.interfaceTarget)) {
-      visitNodes(node.arguments.positional);
-      visitNodes(node.arguments.named);
-    }
-    receiverType = narrowInstanceReceiver(node.interfaceTarget, receiverType);
+  void handleMethodInvocation(
+      ir.MethodInvocation node,
+      ir.DartType receiverType,
+      ArgumentTypes argumentTypes,
+      ir.DartType returnType) {
     if (receiverType is ir.DynamicType) {
       reportError(node, "Dynamic invocation of '${node.name}'.");
     }
-    return result;
   }
 
   void reportError(ir.Node node, String message) {
diff --git a/tests/compiler/dart2js/analyses/api_allowed.json b/tests/compiler/dart2js/analyses/api_allowed.json
index 830ee49..ec57e7e 100644
--- a/tests/compiler/dart2js/analyses/api_allowed.json
+++ b/tests/compiler/dart2js/analyses/api_allowed.json
@@ -68,12 +68,6 @@
     "Dynamic invocation of 'call'.": 4,
     "Dynamic invocation of 'then'.": 1
   },
-  "org-dartlang-sdk:///sdk/lib/async/future.dart": {
-    "Dynamic invocation of 'call'.": 1
-  },
-  "org-dartlang-sdk:///sdk/lib/async/stream.dart": {
-    "Dynamic invocation of 'dart.async::_addError'.": 1
-  },
   "org-dartlang-sdk:///sdk/lib/async/async_error.dart": {
     "Dynamic invocation of 'call'.": 1
   },
@@ -90,10 +84,6 @@
     "Dynamic access of 'dart.collection::_element'.": 1,
     "Dynamic access of 'dart.collection::_first'.": 1
   },
-  "org-dartlang-sdk:///sdk/lib/collection/iterable.dart": {
-    "Dynamic access of 'length'.": 2,
-    "Dynamic invocation of '+'.": 2
-  },
   "org-dartlang-sdk:///sdk/lib/html/dart2js/html_dart2js.dart": {
     "Dynamic access of 'style'.": 1,
     "Dynamic access of 'left'.": 3,
@@ -219,66 +209,15 @@
     "Dynamic invocation of '-'.": 1,
     "Dynamic invocation of '>='.": 1
   },
-  "org-dartlang-sdk:///sdk/lib/core/date_time.dart": {
-    "Dynamic access of 'dart.core::_value'.": 1,
-    "Dynamic access of 'isUtc'.": 1
-  },
-  "org-dartlang-sdk:///sdk/lib/core/duration.dart": {
-    "Dynamic access of 'dart.core::_duration'.": 1
-  },
   "org-dartlang-sdk:///sdk/lib/core/errors.dart": {
-    "Dynamic access of 'length'.": 2,
-    "Dynamic invocation of '<'.": 2,
-    "Dynamic invocation of '~'.": 1,
-    "Dynamic invocation of '^'.": 1,
-    "Dynamic invocation of '&'.": 1,
-    "Dynamic invocation of '|'.": 1,
-    "Dynamic invocation of '>>'.": 1,
-    "Dynamic invocation of '<<'.": 1,
-    "Dynamic invocation of '+'.": 1,
-    "Dynamic invocation of 'unary-'.": 1,
-    "Dynamic invocation of '-'.": 1,
-    "Dynamic invocation of '*'.": 1,
-    "Dynamic invocation of '/'.": 1,
-    "Dynamic invocation of '~/'.": 1,
-    "Dynamic invocation of '>'.": 1,
-    "Dynamic invocation of '>='.": 1,
-    "Dynamic invocation of '<='.": 1,
-    "Dynamic invocation of '%'.": 1,
-    "Dynamic invocation of 'length'.": 1
-  },
-  "org-dartlang-sdk:///sdk/lib/core/exceptions.dart": {
-    "Dynamic access of 'length'.": 3,
-    "Dynamic invocation of 'codeUnitAt'.": 2,
-    "Dynamic invocation of 'substring'.": 1
-  },
-  "org-dartlang-sdk:///sdk/lib/core/uri.dart": {
-    "Dynamic access of 'isEmpty'.": 1,
-    "Dynamic invocation of 'startsWith'.": 1,
-    "Dynamic invocation of 'add'.": 1
-  },
-  "org-dartlang-sdk:///sdk/lib/math/point.dart": {
-    "Dynamic access of 'x'.": 1,
-    "Dynamic access of 'y'.": 1
-  },
-  "org-dartlang-sdk:///sdk/lib/math/rectangle.dart": {
-    "Dynamic access of 'left'.": 1,
-    "Dynamic access of 'top'.": 1,
-    "Dynamic access of 'right'.": 1,
-    "Dynamic access of 'bottom'.": 1
+    "Dynamic access of 'length'.": 2
   },
   "org-dartlang-sdk:///sdk/lib/_internal/js_runtime/lib/convert_patch.dart": {
     "Dynamic invocation of 'clear'.": 1
   },
-  "org-dartlang-sdk:///sdk/lib/convert/encoding.dart": {
-    "Dynamic invocation of 'write'.": 1
-  },
   "org-dartlang-sdk:///sdk/lib/convert/json.dart": {
     "Dynamic invocation of 'toJson'.": 1
   },
-  "org-dartlang-sdk:///sdk/lib/isolate/isolate.dart": {
-    "Dynamic invocation of '[]'.": 2
-  },
   "org-dartlang-sdk:///sdk/lib/_http/crypto.dart": {
     "Dynamic invocation of '+'.": 2,
     "Dynamic invocation of '&'.": 3,
diff --git a/tests/compiler/dart2js/analyses/api_dynamic_test.dart b/tests/compiler/dart2js/analyses/api_dynamic_test.dart
index bb1564a..e06471d 100644
--- a/tests/compiler/dart2js/analyses/api_dynamic_test.dart
+++ b/tests/compiler/dart2js/analyses/api_dynamic_test.dart
@@ -10,7 +10,8 @@
 main(List<String> args) {
   asyncTest(() async {
     await run(Uri.parse('memory:main.dart'),
-        'tests/compiler/dart2js/analyses/api_allowed.json', ['dart:'],
+        'tests/compiler/dart2js/analyses/api_allowed.json',
+        analyzedUrisFilter: (Uri uri) => uri.scheme == 'dart',
         memorySourceFiles: {'main.dart': 'main() {}'},
         verbose: args.contains('-v'),
         generate: args.contains('-g'));
diff --git a/tests/compiler/dart2js/analyses/dart2js_dynamic_test.dart b/tests/compiler/dart2js/analyses/dart2js_dynamic_test.dart
index 43ba39a..b65a57f 100644
--- a/tests/compiler/dart2js/analyses/dart2js_dynamic_test.dart
+++ b/tests/compiler/dart2js/analyses/dart2js_dynamic_test.dart
@@ -5,19 +5,29 @@
 import 'package:async_helper/async_helper.dart';
 import 'analysis_helper.dart';
 
+/// Filter function used to only analysis dart2js source code.
+bool dart2jsOnly(Uri uri) {
+  String text = '$uri';
+  for (String path in [
+    'package:compiler/',
+    'package:js_ast/',
+    'package:dart2js_info/',
+    'package:js_runtime/'
+  ]) {
+    if (text.startsWith(path)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 // TODO(johnniwinther): Remove unneeded dynamic accesses from dart2js source
 // code.
 main(List<String> args) {
   asyncTest(() async {
-    await run(
-        Uri.parse('package:compiler/src/dart2js.dart'),
+    await run(Uri.parse('package:compiler/src/dart2js.dart'),
         'tests/compiler/dart2js/analyses/dart2js_allowed.json',
-        [
-          'package:compiler/',
-          'package:js_ast/',
-          'package:dart2js_info/',
-          'package:js_runtime/'
-        ],
+        analyzedUrisFilter: dart2jsOnly,
         verbose: args.contains('-v'),
         generate: args.contains('-g'));
   });
diff --git a/tests/compiler/dart2js/analyses/static_type_visitor_test.dart b/tests/compiler/dart2js/analyses/static_type_visitor_test.dart
index 3a5fabe..09d8882 100644
--- a/tests/compiler/dart2js/analyses/static_type_visitor_test.dart
+++ b/tests/compiler/dart2js/analyses/static_type_visitor_test.dart
@@ -29,7 +29,7 @@
   });
 }
 
-class Visitor extends StaticTypeTraversalVisitor {
+class Visitor extends StaticTypeVisitor {
   Visitor(ir.Component component)
       : super(new ir.TypeEnvironment(
             new ir.CoreTypes(component), new ir.ClassHierarchy(component)));
diff --git a/tests/compiler/dart2js/closure/closure_test.dart b/tests/compiler/dart2js/closure/closure_test.dart
index e3ddbc7..3cc81e2 100644
--- a/tests/compiler/dart2js/closure/closure_test.dart
+++ b/tests/compiler/dart2js/closure/closure_test.dart
@@ -10,9 +10,9 @@
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/js_model/element_map.dart';
-import 'package:compiler/src/js_model/js_strategy.dart';
+import 'package:compiler/src/js_model/js_world.dart';
 import 'package:compiler/src/js_model/locals.dart';
-import 'package:compiler/src/universe/world_builder.dart';
+import 'package:compiler/src/universe/codegen_world_builder.dart';
 import 'package:expect/expect.dart';
 import '../equivalence/id_equivalence.dart';
 import '../equivalence/id_equivalence_helper.dart';
@@ -215,7 +215,7 @@
     } else {
       //Expect.isFalse(capturedScope.localIsUsedInTryOrSync(local));
     }
-    if (capturedScope.isBoxed(local)) {
+    if (capturedScope.isBoxedVariable(local)) {
       features.add('boxed');
     }
     if (capturedScope.context == local) {
diff --git a/tests/compiler/dart2js/codegen/equals_test.dart b/tests/compiler/dart2js/codegen/equals_test.dart
index 9395108..45bbf50 100644
--- a/tests/compiler/dart2js/codegen/equals_test.dart
+++ b/tests/compiler/dart2js/codegen/equals_test.dart
@@ -43,7 +43,7 @@
 """;
 
 // Comparable includes String and int, so can't be compared with `a == b` since
-// that will convert an operand to make `2 =="2"` true.
+// that will convert an operand to make `2 == "2"` true.
 const String TEST5 = r"""
 foo(Comparable a, Comparable b) {
   return a == b;
@@ -63,6 +63,17 @@
 }
 """;
 
+// StringBuffer uses `Object.==`, i.e. `identical`.  This can be lowered to `==`
+// because no operand will cause JavaScript conversions.
+const String TEST7 = r"""
+foo(StringBuffer a, StringBuffer b) {
+  return a == b;
+  // present: ' == '
+  // absent: '==='
+  // absent: 'eq'
+}
+""";
+
 main() {
   runTests() async {
     Future check(String test) {
@@ -75,6 +86,7 @@
     await check(TEST4);
     await check(TEST5);
     await check(TEST6);
+    await check(TEST7);
   }
 
   asyncTest(() async {
diff --git a/tests/compiler/dart2js/codegen/gvn_dynamic_field_get_test.dart b/tests/compiler/dart2js/codegen/gvn_dynamic_field_get_test.dart
index d908ebd..6695ad2 100644
--- a/tests/compiler/dart2js/codegen/gvn_dynamic_field_get_test.dart
+++ b/tests/compiler/dart2js/codegen/gvn_dynamic_field_get_test.dart
@@ -9,7 +9,7 @@
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/names.dart';
 import 'package:compiler/src/universe/selector.dart' show Selector;
-import 'package:compiler/src/world.dart';
+import 'package:compiler/src/js_model/js_world.dart';
 import 'package:expect/expect.dart';
 import '../helpers/compiler_helper.dart';
 import '../helpers/memory_compiler.dart';
@@ -34,7 +34,7 @@
         memorySourceFiles: {'main.dart': TEST},
         outputProvider: outputCollector);
     Compiler compiler = result.compiler;
-    ClosedWorldBase closedWorld = compiler.backendClosedWorldForTesting;
+    JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     var elementEnvironment = closedWorld.elementEnvironment;
 
     String generated = outputCollector.getOutput('', OutputType.js);
diff --git a/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart b/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
index 97b8230..e79c1f8 100644
--- a/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
+++ b/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
@@ -57,7 +57,7 @@
     // InputElement is native, so it should be in the mainOutputUnit.
     Expect.equals(mainOutputUnit, outputUnitForClass(inputElement));
 
-    var hunksToLoad = compiler.deferredLoadTask.hunksToLoad;
+    var hunksToLoad = closedWorld.outputUnitData.hunksToLoad;
 
     var hunksLib1 = hunksToLoad["lib1"];
     var hunksLib2 = hunksToLoad["lib2"];
diff --git a/tests/compiler/dart2js/deferred/load_mapping_test.dart b/tests/compiler/dart2js/deferred/load_mapping_test.dart
index 51ae1a8..6736599 100644
--- a/tests/compiler/dart2js/deferred/load_mapping_test.dart
+++ b/tests/compiler/dart2js/deferred/load_mapping_test.dart
@@ -5,6 +5,7 @@
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/compiler_new.dart';
+import 'package:compiler/src/world.dart';
 import '../helpers/memory_source_file_helper.dart';
 import '../helpers/memory_compiler.dart';
 
@@ -16,10 +17,12 @@
         options: ['--deferred-map=deferred_map.json'],
         outputProvider: collector);
     CompilerImpl compiler = result.compiler;
+    JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     // Ensure a mapping file is output.
     Expect.isNotNull(collector.getOutput("deferred_map.json", OutputType.info));
 
-    Map mapping = compiler.deferredLoadTask.computeDeferredMap();
+    Map mapping = closedWorld.outputUnitData
+        .computeDeferredMap(compiler.options, closedWorld.elementEnvironment);
     // Test structure of mapping.
     Expect.equals("<unnamed>", mapping["main.dart"]["name"]);
     Expect.equals(2, mapping["main.dart"]["imports"]["lib1"].length);
diff --git a/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart b/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
index 349532c..099c508 100644
--- a/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
+++ b/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
@@ -11,7 +11,7 @@
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/ir/util.dart';
 import 'package:compiler/src/js_model/element_map.dart';
-import 'package:compiler/src/js_model/js_strategy.dart';
+import 'package:compiler/src/js_model/js_world.dart';
 import 'package:expect/expect.dart';
 import '../equivalence/id_equivalence.dart';
 import '../equivalence/id_equivalence_helper.dart';
diff --git a/tests/compiler/dart2js/end_to_end/async_compiler_input_provider_test.dart b/tests/compiler/dart2js/end_to_end/async_compiler_input_provider_test.dart
index 39bbc85..ec404ff 100644
--- a/tests/compiler/dart2js/end_to_end/async_compiler_input_provider_test.dart
+++ b/tests/compiler/dart2js/end_to_end/async_compiler_input_provider_test.dart
@@ -46,13 +46,13 @@
   var entrypoint = Uri.parse("file:///main.dart");
 
   // Find the path to sdk/ in the repo relative to this script.
-  Uri libraryRoot = Uri.base.resolve('sdk/');
+  Uri librariesSpec = Uri.base.resolve('sdk/lib/libraries.json');
   Uri packageRoot = Uri.base.resolve('packages/');
   var platformDir =
       Uri.parse(nativeToUriPath(Platform.resolvedExecutable)).resolve('.');
   asyncTest(() => compiler.compile(
           entrypoint,
-          libraryRoot,
+          librariesSpec,
           packageRoot,
           provideInput,
           handleDiagnostic,
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 51df9a9..8c7624f 100644
--- a/tests/compiler/dart2js/end_to_end/exit_code_test.dart
+++ b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
@@ -189,8 +189,7 @@
     entry.compileFunc = compile;
 
     List<String> args = new List<String>.from(options)
-      // TODO(sigmund): convert to support the new CFE
-      ..add("--library-root=${Uri.base.resolve('sdk/')}")
+      ..add("--libraries-spec=${Uri.base.resolve('sdk/lib/libraries.json')}")
       ..add("tests/compiler/dart2js/end_to_end/data/exit_code_helper.dart");
     Future result = entry.internalMain(args);
     return result.catchError((e, s) {
diff --git a/tests/compiler/dart2js/end_to_end/library_env_test.dart b/tests/compiler/dart2js/end_to_end/library_env_test.dart
index f1084b5..e215c89 100644
--- a/tests/compiler/dart2js/end_to_end/library_env_test.dart
+++ b/tests/compiler/dart2js/end_to_end/library_env_test.dart
@@ -18,37 +18,32 @@
 
 import 'package:compiler/src/options.dart' show CompilerOptions;
 
+import 'package:compiler/src/commandline_options.dart';
+
 import 'package:compiler/src/io/source_file.dart' show Binary;
 
 import 'package:compiler/compiler_new.dart'
     show CompilerInput, CompilerDiagnostics, Input, InputKind;
 
-const String clientPlatform = r'''
-[dart-spec]
-spec: 3rd edition.
-
-[features]
-# No extra features
-
-[libraries]
-mock.client: mock1.dart
-mock.shared: mock3.dart
-collection: collection/collection.dart
-html: html/dart2js/html_dart2js.dart
-''';
-
-const String serverPlatform = r'''
-[dart-spec]
-spec: 3rd edition.
-
-[features]
-# No extra features
-
-[libraries]
-mock.server: mock2.dart
-mock.shared: mock3.dart
-collection: collection/collection.dart
-io: io/io.dart
+const String librariesJson = r'''
+{
+ "dart2js": {
+   "libraries": {
+    "mock.client": {"uri": "mock1.dart"},
+    "mock.shared": {"uri": "mock3.dart"},
+    "collection": {"uri": "collection/collection.dart"},
+    "html": {"uri": "html/dart2js/html_dart2js.dart"}
+   }
+ },
+ "dart2js_server": {
+   "libraries": {
+    "mock.server": {"uri": "mock2.dart"},
+    "mock.shared": {"uri": "mock3.dart"},
+    "collection": {"uri": "collection/collection.dart"},
+    "io": {"uri": "io/io.dart"}
+   }
+ }
+}
 ''';
 
 class DummyCompilerInput implements CompilerInput {
@@ -56,12 +51,8 @@
 
   Future<Input> readFromUri(Uri uri,
       {InputKind inputKind: InputKind.UTF8}) async {
-    if (uri.toString().endsWith("dart_client.platform")) {
-      return new Binary(uri, clientPlatform.codeUnits);
-    } else if (uri.toString().endsWith("dart_server.platform")) {
-      return new Binary(uri, serverPlatform.codeUnits);
-    } else if (uri.path.endsWith(".dill")) {
-      return new Binary(uri, new File.fromUri(uri).readAsBytesSync());
+    if (uri.path.endsWith("libraries.json")) {
+      return new Binary(uri, librariesJson.codeUnits);
     } else {
       throw "should not be needed $uri";
     }
@@ -86,7 +77,8 @@
             const DummyCompilerDiagnostics(),
             CompilerOptions.parse(
                 ['--platform-binaries=$platformDir']..addAll(options),
-                libraryRoot: Uri.base.resolve("sdk/"))
+                librariesSpecificationUri:
+                    Uri.base.resolve("sdk/lib/libraries.json"))
               ..environment = environment);
 }
 
@@ -108,7 +100,7 @@
   Expect.equals(null, compiler.fromEnvironment("dart.library.mock.server"));
   Expect.equals(null, compiler.fromEnvironment("dart.library.io"));
 
-  compiler = new CustomCompiler(['--categories=Server'], {});
+  compiler = new CustomCompiler([Flags.serverMode], {});
 
   await compiler.setupSdk();
 
diff --git a/tests/compiler/dart2js/end_to_end/output_type_test.dart b/tests/compiler/dart2js/end_to_end/output_type_test.dart
index 4217edc..aa4dcf1 100644
--- a/tests/compiler/dart2js/end_to_end/output_type_test.dart
+++ b/tests/compiler/dart2js/end_to_end/output_type_test.dart
@@ -32,6 +32,9 @@
         provider.createUri(name, extension, type), Platform.isWindows));
     return NullSink.outputProvider(name, extension, type);
   }
+
+  @override
+  BinaryOutputSink createBinarySink(Uri uri) => new NullBinarySink(uri);
 }
 
 CompileFunc oldCompileFunc;
@@ -39,7 +42,7 @@
 Future<Null> test(List<String> arguments, List<String> expectedOutput,
     {List<String> groupOutputs: const <String>[]}) async {
   List<String> options = new List<String>.from(arguments)
-    ..add("--library-root=${Uri.base.resolve('sdk/')}");
+    ..add("--libraries-spec=${Uri.base.resolve('sdk/lib/libraries.json')}");
   print('--------------------------------------------------------------------');
   print('dart2js ${options.join(' ')}');
   TestRandomAccessFileOutputProvider outputProvider;
diff --git a/tests/compiler/dart2js/end_to_end/platform_config_parser_test.dart b/tests/compiler/dart2js/end_to_end/platform_config_parser_test.dart
deleted file mode 100644
index c0b843e..0000000
--- a/tests/compiler/dart2js/end_to_end/platform_config_parser_test.dart
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "package:compiler/src/platform_configuration.dart";
-import "package:expect/expect.dart";
-
-/// Runs the parser on [input] and compares it with [expectedResult]
-///
-/// A '*' in [input] indicates that the parser will report an error at the
-/// given point (On [input] with the "*" removed).
-test(String input, [Map<String, Map<String, String>> expectedOutput]) {
-  int starIndex = input.indexOf("*");
-  String inputWithoutStar = input.replaceFirst("*", "");
-
-  parse() => parseIni(inputWithoutStar.codeUnits,
-      allowedSections: new Set.from(["AA", "BB"]));
-
-  if (starIndex != -1) {
-    Expect.equals(expectedOutput, null);
-    Expect.throws(parse, (dynamic e) {
-      Expect.isTrue(e is FormatException);
-      Expect.equals(starIndex, e.offset);
-      return e is FormatException;
-    });
-  } else {
-    Map<String, Map<String, String>> result = parse();
-    Expect.equals(expectedOutput.length, result.length);
-    expectedOutput.forEach((String name, Map<String, String> properties) {
-      Expect.isTrue(expectedOutput.containsKey(name), "Missing section $name");
-      Expect.mapEquals(expectedOutput[name], properties);
-    });
-  }
-}
-
-main() {
-  // Empty file.
-  test("""
-# Nothing here
-""", {});
-
-  // Text outside section.
-  test("""
-*aaa
-""");
-
-  // Malformed header.
-  test("""
-*[AABC
-name:value
-""");
-
-  // Text after header.
-  test("""
-[AABC]*abcde
-""");
-
-  // Empty section name.
-  test("""
-[*]
-""");
-
-  // Duplicate section name.
-  test("""
-[AA]
-[BB]
-[*AA]
-""");
-
-  // Unrecognized section name.
-  test("""
-[*CC]
-""");
-
-  // Empty property name.
-  test("""
-[AA]
-*:value
-name:value
-""");
-
-  // Ok.
-  test("""
-[AA]
-name:value
-[BB]
-name:value
-name2:value2
-""", {
-    "AA": {"name": "value"},
-    "BB": {"name": "value", "name2": "value2"}
-  });
-
-  // Ok, file not ending in newline.
-  test("""
-[AA]
-name:value""", {
-    "A": {"name": "value"}
-  });
-
-  // Ok, whitespace is trimmed away.
-  test("""
-[ AA ]
- name\t:  value """, {
-    "A": {"name": "value"}
-  });
-
-  // Duplicate property name.
-  test("""
-[AA]
-a:b
-b:c
-*a:c
-""");
-
-  // No ':' on property line.
-  test("""
-[AA]
-*name1
-name2:value
-""");
-}
diff --git a/tests/compiler/dart2js/end_to_end/user_crash_test.dart b/tests/compiler/dart2js/end_to_end/user_crash_test.dart
index 76d92cd..a17fbf2 100644
--- a/tests/compiler/dart2js/end_to_end/user_crash_test.dart
+++ b/tests/compiler/dart2js/end_to_end/user_crash_test.dart
@@ -25,23 +25,6 @@
         expectedExceptions: [
           EXCEPTION
         ]);
-    test(
-        'Throw in package discovery',
-        await run(packagesDiscoveryProvider: (_) {
-          throw EXCEPTION;
-        }),
-        expectedLines: [
-          'Uncaught exception in package discovery: $EXCEPTION',
-          null /* Stack trace*/
-        ],
-        expectedExceptions: [
-          EXCEPTION
-        ]);
-    test(
-        'new Future.error in package discovery',
-        await run(
-            packagesDiscoveryProvider: (_) => new Future.error(EXCEPTION)),
-        expectedExceptions: [EXCEPTION]);
 
     var cantReadFile =
         templateCantReadFile.withArguments(entryPoint, EXCEPTION);
@@ -82,16 +65,14 @@
 
 Future<RunResult> run(
     {Map<String, String> memorySourceFiles: const {'main.dart': 'main() {}'},
-    CompilerDiagnostics diagnostics,
-    PackagesDiscoveryProvider packagesDiscoveryProvider}) async {
+    CompilerDiagnostics diagnostics}) async {
   RunResult result = new RunResult();
   await runZoned(() async {
     try {
       await runCompiler(
           entryPoint: entryPoint,
           memorySourceFiles: memorySourceFiles,
-          diagnosticHandler: diagnostics,
-          packagesDiscoveryProvider: packagesDiscoveryProvider);
+          diagnosticHandler: diagnostics);
     } catch (e) {
       result.exceptions.add(e);
     }
diff --git a/tests/compiler/dart2js/generic_methods/world_test.dart b/tests/compiler/dart2js/generic_methods/world_test.dart
index 8578a79..13c9a72 100644
--- a/tests/compiler/dart2js/generic_methods/world_test.dart
+++ b/tests/compiler/dart2js/generic_methods/world_test.dart
@@ -5,7 +5,7 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/universe/call_structure.dart';
-import 'package:compiler/src/universe/world_builder.dart';
+import 'package:compiler/src/universe/codegen_world_builder.dart';
 import 'package:expect/expect.dart';
 
 import '../helpers/memory_compiler.dart';
diff --git a/tests/compiler/dart2js/helpers/args_helper.dart b/tests/compiler/dart2js/helpers/args_helper.dart
new file mode 100644
index 0000000..21f026a
--- /dev/null
+++ b/tests/compiler/dart2js/helpers/args_helper.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:args/args.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/filenames.dart';
+
+/// Creates an [ArgParser] that supports various dart2js command-line options.
+ArgParser createArgParser() {
+  ArgParser argParser = new ArgParser(allowTrailingOptions: true);
+  argParser.addFlag('fast-startup', defaultsTo: false);
+  argParser.addFlag('omit-implicit-checks', defaultsTo: false);
+  argParser.addFlag('minify', abbr: 'm', defaultsTo: false);
+  argParser.addFlag('trust-primitives', defaultsTo: false);
+  argParser.addFlag('verbose', abbr: 'v', defaultsTo: false);
+  argParser.addOption('libraries-spec');
+  argParser.addOption('packages');
+  return argParser;
+}
+
+/// Retrieves the entry point [Uri] from [argResults].
+Uri getEntryPoint(ArgResults argResults) {
+  Uri entryPoint;
+  if (argResults.rest.isNotEmpty) {
+    if (argResults.rest.length > 1) {
+      throw new ArgumentError(
+          'Extra arguments: ${argResults.rest.skip(1).join(" ")}');
+    }
+    entryPoint = Uri.base.resolve(nativeToUriPath(argResults.rest.single));
+  }
+  return entryPoint;
+}
+
+/// Retrieves the library root [Uri] from [argResults].
+Uri getLibrariesSpec(ArgResults argResults) {
+  if (!argResults.wasParsed('libraries-spec')) return null;
+  return Uri.base.resolve(nativeToUriPath(argResults['libraries-spec']));
+}
+
+/// Retrieves the packages config [Uri] from [argResults].
+Uri getPackages(ArgResults argResults) {
+  Uri packageConfig;
+  if (argResults.wasParsed('packages')) {
+    packageConfig = Uri.base.resolve(nativeToUriPath(argResults['packages']));
+  }
+  return packageConfig;
+}
+
+/// Retrieves the options from [argResults].
+List<String> getOptions(ArgResults argResults) {
+  List<String> options = <String>[];
+  if (argResults['fast-startup']) {
+    options.add(Flags.fastStartup);
+  }
+  if (argResults['omit-implicit-checks']) {
+    options.add(Flags.omitImplicitChecks);
+  }
+  if (argResults['minify']) {
+    options.add(Flags.minify);
+  }
+  if (argResults['trust-primitives']) {
+    options.add(Flags.trustPrimitives);
+  }
+  if (argResults['verbose']) {
+    options.add(Flags.verbose);
+  }
+  return options;
+}
diff --git a/tests/compiler/dart2js/helpers/memory_compiler.dart b/tests/compiler/dart2js/helpers/memory_compiler.dart
index c8f1708..079ac0b 100644
--- a/tests/compiler/dart2js/helpers/memory_compiler.dart
+++ b/tests/compiler/dart2js/helpers/memory_compiler.dart
@@ -8,12 +8,7 @@
 
 import 'package:compiler/compiler.dart' show DiagnosticHandler;
 import 'package:compiler/compiler_new.dart'
-    show
-        CompilationResult,
-        CompilerDiagnostics,
-        CompilerOutput,
-        Diagnostic,
-        PackagesDiscoveryProvider;
+    show CompilationResult, CompilerDiagnostics, CompilerOutput, Diagnostic;
 import 'package:compiler/src/common.dart';
 import 'package:compiler/src/diagnostics/messages.dart' show Message;
 import 'package:compiler/src/null_compiler_output.dart' show NullCompilerOutput;
@@ -77,9 +72,9 @@
     CompilerOutput outputProvider,
     List<String> options: const <String>[],
     bool showDiagnostics: true,
+    Uri librariesSpecificationUri,
     Uri packageRoot,
     Uri packageConfig,
-    PackagesDiscoveryProvider packagesDiscoveryProvider,
     void beforeRun(CompilerImpl compiler)}) async {
   if (entryPoint == null) {
     entryPoint = Uri.parse('memory:main.dart');
@@ -91,9 +86,9 @@
       outputProvider: outputProvider,
       options: options,
       showDiagnostics: showDiagnostics,
+      librariesSpecificationUri: librariesSpecificationUri,
       packageRoot: packageRoot,
-      packageConfig: packageConfig,
-      packagesDiscoveryProvider: packagesDiscoveryProvider);
+      packageConfig: packageConfig);
   if (beforeRun != null) {
     beforeRun(compiler);
   }
@@ -111,16 +106,14 @@
     CompilerOutput outputProvider,
     List<String> options: const <String>[],
     bool showDiagnostics: true,
+    Uri librariesSpecificationUri,
     Uri packageRoot,
-    Uri packageConfig,
-    PackagesDiscoveryProvider packagesDiscoveryProvider}) {
+    Uri packageConfig}) {
   retainDataForTesting = true;
-  Uri libraryRoot = Uri.base.resolve('sdk/');
+  librariesSpecificationUri ??= Uri.base.resolve('sdk/lib/libraries.json');
   Uri platformBinaries = computePlatformBinariesLocation();
 
-  if (packageRoot == null &&
-      packageConfig == null &&
-      packagesDiscoveryProvider == null) {
+  if (packageRoot == null && packageConfig == null) {
     if (Platform.packageRoot != null) {
       packageRoot = Uri.base.resolve(Platform.packageRoot);
     } else if (Platform.packageConfig != null) {
@@ -143,12 +136,12 @@
   }
 
   CompilerOptions compilerOptions = CompilerOptions.parse(options,
-      libraryRoot: libraryRoot, platformBinaries: platformBinaries)
+      librariesSpecificationUri: librariesSpecificationUri,
+      platformBinaries: platformBinaries)
     ..entryPoint = entryPoint
     ..packageRoot = packageRoot
     ..environment = {}
-    ..packageConfig = packageConfig
-    ..packagesDiscoveryProvider = packagesDiscoveryProvider;
+    ..packageConfig = packageConfig;
   compilerOptions.kernelInitializedCompilerState =
       kernelInitializedCompilerState;
   CompilerImpl compiler = new CompilerImpl(
diff --git a/tests/compiler/dart2js/helpers/output_collector.dart b/tests/compiler/dart2js/helpers/output_collector.dart
index a5c1cdb..e9ff37b 100644
--- a/tests/compiler/dart2js/helpers/output_collector.dart
+++ b/tests/compiler/dart2js/helpers/output_collector.dart
@@ -26,6 +26,24 @@
   }
 }
 
+class BufferedBinaryOutputSink implements BinaryOutputSink {
+  final Uri uri;
+
+  List<int> list = <int>[];
+
+  BufferedBinaryOutputSink(this.uri);
+
+  void write(List<int> buffer, [int start = 0, int end]) {
+    list.addAll(buffer.sublist(start, end));
+  }
+
+  void close() {}
+
+  String toString() {
+    return 'BufferedBinaryOutputSink($uri)';
+  }
+}
+
 class CloningOutputSink implements OutputSink {
   final List<OutputSink> sinks;
 
@@ -44,6 +62,7 @@
 
 class OutputCollector implements CompilerOutput {
   Map<OutputType, Map<String, BufferedOutputSink>> outputMap = {};
+  Map<Uri, BufferedBinaryOutputSink> binaryOutputMap = {};
 
   String getOutput(String name, OutputType type) {
     Map<String, BufferedOutputSink> sinkMap = outputMap[type];
@@ -60,8 +79,13 @@
     }
   }
 
+  BinaryOutputSink createBinarySink(Uri uri) {
+    return binaryOutputMap.putIfAbsent(
+        uri, () => new BufferedBinaryOutputSink(uri));
+  }
+
   /// `true` if any output has been collected.
-  bool get hasOutput => !outputMap.isEmpty;
+  bool get hasOutput => outputMap.isNotEmpty || binaryOutputMap.isNotEmpty;
 
   /// `true` if any output other than main output has been collected.
   bool get hasExtraOutput {
@@ -70,7 +94,7 @@
         if (name != '') return true;
       }
     }
-    return false;
+    return binaryOutputMap.isNotEmpty;
   }
 
   @override
@@ -79,4 +103,18 @@
         outputMap.putIfAbsent(type, () => {});
     return sinkMap.putIfAbsent(name, () => new BufferedOutputSink());
   }
+
+  Map<OutputType, Map<String, String>> clear() {
+    Map<OutputType, Map<String, String>> outputMapResult = {};
+    outputMap.forEach(
+        (OutputType outputType, Map<String, BufferedOutputSink> sinkMap) {
+      Map<String, String> sinkMapResult = outputMapResult[outputType] = {};
+      sinkMap.forEach((String name, BufferedOutputSink sink) {
+        sinkMapResult[name] = sink.toString();
+      });
+    });
+    outputMap.clear();
+    binaryOutputMap.clear();
+    return outputMapResult;
+  }
 }
diff --git a/tests/compiler/dart2js/helpers/text_helpers.dart b/tests/compiler/dart2js/helpers/text_helpers.dart
new file mode 100644
index 0000000..ce1254c
--- /dev/null
+++ b/tests/compiler/dart2js/helpers/text_helpers.dart
@@ -0,0 +1,46 @@
+// 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.
+
+/// Compares [text1] and [text2] line-by-line. If a mismatch is found, a diff
+/// of the [windowSize] lines before and after are printed and the mismatch line
+/// number is returned. If identical, nothing is printed and `null` is returned.
+int checkEqualContentAndShowDiff(String text1, String text2,
+    {int windowSize: 20}) {
+  List<String> lines1 = text1.split('\n');
+  List<String> lines2 = text2.split('\n');
+  for (int i = 0; i < lines1.length && i < lines2.length; i++) {
+    if (i >= lines1.length || i >= lines2.length || lines1[i] != lines2[i]) {
+      for (int j = i - windowSize; j < i + windowSize; j++) {
+        if (j < 0) continue;
+        String line1 = 0 <= j && j < lines1.length ? lines1[j] : null;
+        String line2 = 0 <= j && j < lines2.length ? lines2[j] : null;
+        if (line1 == line2) {
+          print('  $j $line1');
+        } else {
+          String text = line1 == null ? '<eof>' : line1;
+          String newText = line2 == null ? '<eof>' : line2;
+          print('- $j ${text}');
+          print('+ $j ${newText}');
+          if (text.length > 80 && newText.length > 80) {
+            assert(text != newText);
+            StringBuffer diff = new StringBuffer();
+            diff.write('  $j ');
+            for (int k = 0; k < text.length && k < newText.length; k++) {
+              int char1 = k < text.length ? text.codeUnitAt(k) : null;
+              int char2 = k < newText.length ? newText.codeUnitAt(k) : null;
+              if (char1 != char2) {
+                diff.write('^');
+              } else {
+                diff.write(' ');
+              }
+            }
+            print(diff);
+          }
+        }
+      }
+      return i;
+    }
+  }
+  return null;
+}
diff --git a/tests/compiler/dart2js/inference/callers_test.dart b/tests/compiler/dart2js/inference/callers_test.dart
index 8209b14..cbcd56c 100644
--- a/tests/compiler/dart2js/inference/callers_test.dart
+++ b/tests/compiler/dart2js/inference/callers_test.dart
@@ -11,7 +11,7 @@
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/inferrer/type_graph_inferrer.dart';
 import 'package:compiler/src/js_model/element_map.dart';
-import 'package:compiler/src/js_model/js_strategy.dart';
+import 'package:compiler/src/js_model/js_world.dart';
 import 'package:kernel/ast.dart' as ir;
 import '../equivalence/id_equivalence.dart';
 import '../equivalence/id_equivalence_helper.dart';
diff --git a/tests/compiler/dart2js/inference/inference_data_test.dart b/tests/compiler/dart2js/inference/inference_data_test.dart
index 396bd22..4f3d3e9 100644
--- a/tests/compiler/dart2js/inference/inference_data_test.dart
+++ b/tests/compiler/dart2js/inference/inference_data_test.dart
@@ -11,7 +11,7 @@
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/js_backend/inferred_data.dart';
 import 'package:compiler/src/js_model/element_map.dart';
-import 'package:compiler/src/js_model/js_strategy.dart';
+import 'package:compiler/src/js_model/js_world.dart';
 import 'package:kernel/ast.dart' as ir;
 import '../equivalence/id_equivalence.dart';
 import '../equivalence/id_equivalence_helper.dart';
diff --git a/tests/compiler/dart2js/inference/inference_test_helper.dart b/tests/compiler/dart2js/inference/inference_test_helper.dart
index 2fd448d..9ac41da 100644
--- a/tests/compiler/dart2js/inference/inference_test_helper.dart
+++ b/tests/compiler/dart2js/inference/inference_test_helper.dart
@@ -12,7 +12,7 @@
 import 'package:compiler/src/inferrer/typemasks/masks.dart';
 import 'package:compiler/src/types/types.dart';
 import 'package:compiler/src/js_model/element_map.dart';
-import 'package:compiler/src/js_model/js_strategy.dart';
+import 'package:compiler/src/js_model/js_world.dart';
 import 'package:compiler/src/js_model/locals.dart';
 import 'package:compiler/src/inferrer/builder_kernel.dart';
 import 'package:kernel/ast.dart' as ir;
diff --git a/tests/compiler/dart2js/inference/load_deferred_library_test.dart b/tests/compiler/dart2js/inference/load_deferred_library_test.dart
index ab87ab2..5ae532f 100644
--- a/tests/compiler/dart2js/inference/load_deferred_library_test.dart
+++ b/tests/compiler/dart2js/inference/load_deferred_library_test.dart
@@ -10,7 +10,7 @@
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/inferrer/typemasks/masks.dart';
 import 'package:compiler/src/js_model/element_map.dart';
-import 'package:compiler/src/js_model/js_strategy.dart';
+import 'package:compiler/src/js_model/js_world.dart';
 import 'package:compiler/src/types/abstract_value_domain.dart';
 import 'package:expect/expect.dart';
 import 'package:kernel/ast.dart' as ir;
diff --git a/tests/compiler/dart2js/inference/side_effects_test.dart b/tests/compiler/dart2js/inference/side_effects_test.dart
index 1ad86b8..4b04662 100644
--- a/tests/compiler/dart2js/inference/side_effects_test.dart
+++ b/tests/compiler/dart2js/inference/side_effects_test.dart
@@ -11,7 +11,7 @@
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/js_backend/inferred_data.dart';
 import 'package:compiler/src/js_model/element_map.dart';
-import 'package:compiler/src/js_model/js_strategy.dart';
+import 'package:compiler/src/js_model/js_world.dart';
 import 'package:kernel/ast.dart' as ir;
 import '../equivalence/id_equivalence.dart';
 import '../equivalence/id_equivalence_helper.dart';
diff --git a/tests/compiler/dart2js/inlining/inlining_test.dart b/tests/compiler/dart2js/inlining/inlining_test.dart
index 12d032b..b71d909 100644
--- a/tests/compiler/dart2js/inlining/inlining_test.dart
+++ b/tests/compiler/dart2js/inlining/inlining_test.dart
@@ -11,7 +11,7 @@
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/js_backend/backend.dart';
 import 'package:compiler/src/js_model/element_map.dart';
-import 'package:compiler/src/js_model/js_strategy.dart';
+import 'package:compiler/src/js_model/js_world.dart';
 import 'package:compiler/src/ssa/builder_kernel.dart' as kernel;
 import 'package:compiler/src/universe/world_impact.dart';
 import 'package:compiler/src/universe/use.dart';
diff --git a/tests/compiler/dart2js/jumps/jump_test.dart b/tests/compiler/dart2js/jumps/jump_test.dart
index c90e13c..ee33c6c 100644
--- a/tests/compiler/dart2js/jumps/jump_test.dart
+++ b/tests/compiler/dart2js/jumps/jump_test.dart
@@ -11,7 +11,7 @@
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/elements/jumps.dart';
 import 'package:compiler/src/js_model/element_map.dart';
-import 'package:compiler/src/js_model/js_strategy.dart';
+import 'package:compiler/src/js_model/js_world.dart';
 import 'package:compiler/src/js_model/locals.dart';
 import '../equivalence/id_equivalence.dart';
 import '../equivalence/id_equivalence_helper.dart';
diff --git a/tests/compiler/dart2js/model/class_set_test.dart b/tests/compiler/dart2js/model/class_set_test.dart
index 790a8a5..5ceb1e8 100644
--- a/tests/compiler/dart2js/model/class_set_test.dart
+++ b/tests/compiler/dart2js/model/class_set_test.dart
@@ -12,7 +12,6 @@
 import 'package:compiler/src/universe/class_set.dart';
 import 'package:compiler/src/util/enumset.dart';
 import 'package:compiler/src/world.dart';
-import 'package:front_end/src/fasta/util/link.dart' show Link;
 import '../helpers/type_test_helper.dart';
 
 void main() {
@@ -36,8 +35,8 @@
       ///    D   E F G
       ///
       class A {}
-      class C extends A {}
       class B extends A {}
+      class C extends A {}
       class D extends B {}
       class E extends C {}
       class F extends C {}
@@ -98,9 +97,9 @@
       return node != null ? node.cls : null;
     }
 
-    List<ClassEntity> classesOf(Link<ClassHierarchyNode> link) {
-      if (link == null) return null;
-      return link.map(classOf).toList();
+    List<ClassEntity> classesOf(Iterable<ClassHierarchyNode> list) {
+      if (list == null) return null;
+      return list.map(classOf).toList();
     }
 
     ClassEntity foundRoot = iterator.root.cls;
@@ -138,10 +137,8 @@
           world.classHierarchy.getClassHierarchyNode(G), ClassHierarchyNode.ALL)
       .iterator;
   checkState(G, currentNode: null, stack: null);
-  Expect.isNull(iterator.current);
   Expect.isTrue(iterator.moveNext());
   checkState(G, currentNode: G, stack: []);
-  Expect.equals(G, iterator.current);
   Expect.isFalse(iterator.moveNext());
   checkState(G, currentNode: null, stack: []);
   Expect.isNull(iterator.current);
@@ -151,71 +148,53 @@
           includeRoot: false)
       .iterator;
   checkState(G, currentNode: null, stack: null);
-  Expect.isNull(iterator.current);
   Expect.isFalse(iterator.moveNext());
   checkState(G, currentNode: null, stack: []);
-  Expect.isNull(iterator.current);
 
   iterator = new ClassHierarchyNodeIterable(
           world.classHierarchy.getClassHierarchyNode(C), ClassHierarchyNode.ALL)
       .iterator;
   checkState(C, currentNode: null, stack: null);
-  Expect.isNull(iterator.current);
   Expect.isTrue(iterator.moveNext());
-  checkState(C, currentNode: C, stack: [E, F, G]);
-  Expect.equals(C, iterator.current);
+  checkState(C, currentNode: C, stack: [G, F, E]);
   Expect.isTrue(iterator.moveNext());
-  checkState(C, currentNode: E, stack: [F, G]);
-  Expect.equals(E, iterator.current);
+  checkState(C, currentNode: E, stack: [G, F]);
   Expect.isTrue(iterator.moveNext());
   checkState(C, currentNode: F, stack: [G]);
-  Expect.equals(F, iterator.current);
   Expect.isTrue(iterator.moveNext());
   checkState(C, currentNode: G, stack: []);
-  Expect.equals(G, iterator.current);
   Expect.isFalse(iterator.moveNext());
   checkState(C, currentNode: null, stack: []);
-  Expect.isNull(iterator.current);
 
   iterator = new ClassHierarchyNodeIterable(
           world.classHierarchy.getClassHierarchyNode(D), ClassHierarchyNode.ALL)
       .iterator;
   checkState(D, currentNode: null, stack: null);
-  Expect.isNull(iterator.current);
   Expect.isTrue(iterator.moveNext());
   checkState(D, currentNode: D, stack: []);
-  Expect.equals(D, iterator.current);
   Expect.isFalse(iterator.moveNext());
   checkState(D, currentNode: null, stack: []);
-  Expect.isNull(iterator.current);
 
   iterator = new ClassHierarchyNodeIterable(
           world.classHierarchy.getClassHierarchyNode(B), ClassHierarchyNode.ALL)
       .iterator;
   checkState(B, currentNode: null, stack: null);
-  Expect.isNull(iterator.current);
   Expect.isTrue(iterator.moveNext());
   checkState(B, currentNode: B, stack: [D]);
-  Expect.equals(B, iterator.current);
   Expect.isTrue(iterator.moveNext());
   checkState(B, currentNode: D, stack: []);
-  Expect.equals(D, iterator.current);
   Expect.isFalse(iterator.moveNext());
   checkState(B, currentNode: null, stack: []);
-  Expect.isNull(iterator.current);
 
   iterator = new ClassHierarchyNodeIterable(
           world.classHierarchy.getClassHierarchyNode(B), ClassHierarchyNode.ALL,
           includeRoot: false)
       .iterator;
   checkState(B, currentNode: null, stack: null);
-  Expect.isNull(iterator.current);
   Expect.isTrue(iterator.moveNext());
   checkState(B, currentNode: D, stack: []);
-  Expect.equals(D, iterator.current);
   Expect.isFalse(iterator.moveNext());
   checkState(B, currentNode: null, stack: []);
-  Expect.isNull(iterator.current);
 
   iterator = new ClassHierarchyNodeIterable(
       world.classHierarchy.getClassHierarchyNode(B),
@@ -224,71 +203,51 @@
         Instantiation.UNINSTANTIATED
       ])).iterator;
   checkState(B, currentNode: null, stack: null);
-  Expect.isNull(iterator.current);
   Expect.isTrue(iterator.moveNext());
   checkState(B, currentNode: D, stack: []);
-  Expect.equals(D, iterator.current);
   Expect.isFalse(iterator.moveNext());
   checkState(B, currentNode: null, stack: []);
-  Expect.isNull(iterator.current);
 
   iterator = new ClassHierarchyNodeIterable(
           world.classHierarchy.getClassHierarchyNode(A), ClassHierarchyNode.ALL)
       .iterator;
   checkState(A, currentNode: null, stack: null);
-  Expect.isNull(iterator.current);
   Expect.isTrue(iterator.moveNext());
   checkState(A, currentNode: A, stack: [C, B]);
-  Expect.equals(A, iterator.current);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: C, stack: [E, F, G, B]);
-  Expect.equals(C, iterator.current);
+  checkState(A, currentNode: B, stack: [C, D]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: E, stack: [F, G, B]);
-  Expect.equals(E, iterator.current);
+  checkState(A, currentNode: D, stack: [C]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: F, stack: [G, B]);
-  Expect.equals(F, iterator.current);
+  checkState(A, currentNode: C, stack: [G, F, E]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: G, stack: [B]);
-  Expect.equals(G, iterator.current);
+  checkState(A, currentNode: E, stack: [G, F]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: B, stack: [D]);
-  Expect.equals(B, iterator.current);
+  checkState(A, currentNode: F, stack: [G]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: D, stack: []);
-  Expect.equals(D, iterator.current);
+  checkState(A, currentNode: G, stack: []);
   Expect.isFalse(iterator.moveNext());
   checkState(A, currentNode: null, stack: []);
-  Expect.isNull(iterator.current);
 
   iterator = new ClassHierarchyNodeIterable(
           world.classHierarchy.getClassHierarchyNode(A), ClassHierarchyNode.ALL,
           includeRoot: false)
       .iterator;
   checkState(A, currentNode: null, stack: null);
-  Expect.isNull(iterator.current);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: C, stack: [E, F, G, B]);
-  Expect.equals(C, iterator.current);
+  checkState(A, currentNode: B, stack: [C, D]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: E, stack: [F, G, B]);
-  Expect.equals(E, iterator.current);
+  checkState(A, currentNode: D, stack: [C]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: F, stack: [G, B]);
-  Expect.equals(F, iterator.current);
+  checkState(A, currentNode: C, stack: [G, F, E]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: G, stack: [B]);
-  Expect.equals(G, iterator.current);
+  checkState(A, currentNode: E, stack: [G, F]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: B, stack: [D]);
-  Expect.equals(B, iterator.current);
+  checkState(A, currentNode: F, stack: [G]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: D, stack: []);
-  Expect.equals(D, iterator.current);
+  checkState(A, currentNode: G, stack: []);
   Expect.isFalse(iterator.moveNext());
   checkState(A, currentNode: null, stack: []);
-  Expect.isNull(iterator.current);
 
   iterator = new ClassHierarchyNodeIterable(
       world.classHierarchy.getClassHierarchyNode(A),
@@ -297,28 +256,20 @@
         Instantiation.UNINSTANTIATED
       ])).iterator;
   checkState(A, currentNode: null, stack: null);
-  Expect.isNull(iterator.current);
   Expect.isTrue(iterator.moveNext());
   checkState(A, currentNode: A, stack: [C, B]);
-  Expect.equals(A, iterator.current);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: C, stack: [E, F, G, B]);
-  Expect.equals(C, iterator.current);
+  checkState(A, currentNode: D, stack: [C]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: E, stack: [F, G, B]);
-  Expect.equals(E, iterator.current);
+  checkState(A, currentNode: C, stack: [G, F, E]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: F, stack: [G, B]);
-  Expect.equals(F, iterator.current);
+  checkState(A, currentNode: E, stack: [G, F]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: G, stack: [B]);
-  Expect.equals(G, iterator.current);
+  checkState(A, currentNode: F, stack: [G]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: D, stack: []);
-  Expect.equals(D, iterator.current);
+  checkState(A, currentNode: G, stack: []);
   Expect.isFalse(iterator.moveNext());
   checkState(A, currentNode: null, stack: []);
-  Expect.isNull(iterator.current);
 
   iterator = new ClassHierarchyNodeIterable(
           world.classHierarchy.getClassHierarchyNode(A),
@@ -329,25 +280,18 @@
           includeRoot: false)
       .iterator;
   checkState(A, currentNode: null, stack: null);
-  Expect.isNull(iterator.current);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: C, stack: [E, F, G, B]);
-  Expect.equals(C, iterator.current);
+  checkState(A, currentNode: D, stack: [C]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: E, stack: [F, G, B]);
-  Expect.equals(E, iterator.current);
+  checkState(A, currentNode: C, stack: [G, F, E]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: F, stack: [G, B]);
-  Expect.equals(F, iterator.current);
+  checkState(A, currentNode: E, stack: [G, F]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: G, stack: [B]);
-  Expect.equals(G, iterator.current);
+  checkState(A, currentNode: F, stack: [G]);
   Expect.isTrue(iterator.moveNext());
-  checkState(A, currentNode: D, stack: []);
-  Expect.equals(D, iterator.current);
+  checkState(A, currentNode: G, stack: []);
   Expect.isFalse(iterator.moveNext());
   checkState(A, currentNode: null, stack: []);
-  Expect.isNull(iterator.current);
 }
 
 testForEach() async {
@@ -361,8 +305,8 @@
       ///         H I
       ///
       class A implements X {}
-      class C extends A {}
       class B extends A {}
+      class C extends A {}
       class D extends B {}
       class E extends C {}
       class F extends C implements B {}
@@ -421,12 +365,12 @@
         "Actual: $visited, expected: $expected\n$classSet");
   }
 
-  checkForEachSubclass(A, [A, B, D, C, G, F, I, H, E]);
+  checkForEachSubclass(A, [A, B, D, C, E, F, H, I, G]);
   checkForEachSubclass(B, [B, D]);
-  checkForEachSubclass(C, [C, G, F, I, H, E]);
+  checkForEachSubclass(C, [C, E, F, H, I, G]);
   checkForEachSubclass(D, [D]);
   checkForEachSubclass(E, [E]);
-  checkForEachSubclass(F, [F, I, H]);
+  checkForEachSubclass(F, [F, H, I]);
   checkForEachSubclass(G, [G]);
   checkForEachSubclass(H, [H]);
   checkForEachSubclass(I, [I]);
@@ -458,16 +402,16 @@
         "Actual: $visited, expected: $expected\n$classSet");
   }
 
-  checkForEachSubtype(A, [A, B, D, C, G, F, I, H, E]);
-  checkForEachSubtype(B, [B, D, F, I, H, G]);
-  checkForEachSubtype(C, [C, G, F, I, H, E]);
+  checkForEachSubtype(A, [A, B, D, C, E, F, H, I, G]);
+  checkForEachSubtype(B, [B, D, F, H, I, G]);
+  checkForEachSubtype(C, [C, E, F, H, I, G]);
   checkForEachSubtype(D, [D, G]);
   checkForEachSubtype(E, [E]);
-  checkForEachSubtype(F, [F, I, H]);
+  checkForEachSubtype(F, [F, H, I]);
   checkForEachSubtype(G, [G]);
   checkForEachSubtype(H, [H]);
   checkForEachSubtype(I, [I]);
-  checkForEachSubtype(X, [X, A, B, D, C, G, F, I, H, E]);
+  checkForEachSubtype(X, [X, A, B, D, C, E, F, H, I, G]);
 
   void checkForEach(ClassEntity cls, List<ClassEntity> expected,
       {ClassEntity stop,
@@ -507,30 +451,30 @@
         "Actual: $visited, expected: $expected\n$classSet");
   }
 
-  checkForEach(A, [A, B, D, C, G, F, I, H, E]);
+  checkForEach(A, [A, B, D, C, E, F, H, I, G]);
   checkForEach(A, [A], stop: A);
-  checkForEach(A, [A, B, C, G, F, I, H, E], skipSubclasses: [B]);
+  checkForEach(A, [A, B, C, E, F, H, I, G], skipSubclasses: [B]);
   checkForEach(A, [A, B, C], skipSubclasses: [B, C]);
-  checkForEach(A, [A, B, C, G], stop: G, skipSubclasses: [B]);
+  checkForEach(A, [A, B, C, E, F], stop: F, skipSubclasses: [B]);
 
-  checkForEach(B, [B, D, F, I, H, G], forEachSubtype: true);
+  checkForEach(B, [B, D, F, H, I, G], forEachSubtype: true);
   checkForEach(B, [B, D], stop: D, forEachSubtype: true);
   checkForEach(B, [B, D, F, G], skipSubclasses: [F], forEachSubtype: true);
-  checkForEach(B, [B, F, I, H, G], skipSubclasses: [B], forEachSubtype: true);
-  checkForEach(B, [B, D, F, I, H, G],
+  checkForEach(B, [B, F, H, I, G], skipSubclasses: [B], forEachSubtype: true);
+  checkForEach(B, [B, D, F, H, I, G],
       skipSubclasses: [D], forEachSubtype: true);
 
-  checkForEach(X, [X, A, B, D, C, G, F, I, H, E], forEachSubtype: true);
+  checkForEach(X, [X, A, B, D, C, E, F, H, I, G], forEachSubtype: true);
   checkForEach(X, [X, A, B, D], stop: D, forEachSubtype: true);
-  checkForEach(X, [X, A, B, D, C, G, F, E],
+  checkForEach(X, [X, A, B, D, C, E, F, G],
       skipSubclasses: [F], forEachSubtype: true);
-  checkForEach(X, [X, A, B, D, C, G, F, I, H, E],
+  checkForEach(X, [X, A, B, D, C, E, F, H, I, G],
       skipSubclasses: [X], forEachSubtype: true);
-  checkForEach(X, [X, A, B, D, C, G, F, I, H, E],
+  checkForEach(X, [X, A, B, D, C, E, F, H, I, G],
       skipSubclasses: [D], forEachSubtype: true);
-  checkForEach(X, [A, D, C, G, F, I, H, E],
+  checkForEach(X, [A, D, C, E, F, H, I, G],
       forEachSubtype: true, mask: ClassHierarchyNode.EXPLICITLY_INSTANTIATED);
-  checkForEach(X, [A, B, D, C, G, F, I, H, E],
+  checkForEach(X, [A, B, D, C, E, F, H, I, G],
       forEachSubtype: true, mask: ClassHierarchyNode.INSTANTIATED);
 
   void checkAny(ClassEntity cls, List<ClassEntity> expected,
@@ -566,21 +510,21 @@
         "Actual: $visited, expected: $expected\n$classSet");
   }
 
-  checkAny(A, [A, B, D, C, G, F, I, H, E], expectedResult: false);
+  checkAny(A, [A, B, D, C, E, F, H, I, G], expectedResult: false);
   checkAny(A, [A], find: A, expectedResult: true);
-  checkAny(A, [A, B, D, C, G, F, I], find: I, expectedResult: true);
+  checkAny(A, [A, B, D, C, E, F, H], find: H, expectedResult: true);
 
-  checkAny(B, [B, D, F, I, H, G], anySubtype: true, expectedResult: false);
-  checkAny(B, [B, D, F, I, H, G],
+  checkAny(B, [B, D, F, H, I, G], anySubtype: true, expectedResult: false);
+  checkAny(B, [B, D, F, H, I, G],
       find: A, anySubtype: true, expectedResult: false);
   checkAny(B, [B, D], find: D, anySubtype: true, expectedResult: true);
-  checkAny(B, [B, D, F, I], find: I, anySubtype: true, expectedResult: true);
+  checkAny(B, [B, D, F, H, I], find: I, anySubtype: true, expectedResult: true);
 
-  checkAny(X, [X, A, B, D, C, G, F, I, H, E],
+  checkAny(X, [X, A, B, D, C, E, F, H, I, G],
       anySubtype: true, expectedResult: false);
   checkAny(X, [X, A], find: A, anySubtype: true, expectedResult: true);
   checkAny(X, [X, A, B, D], find: D, anySubtype: true, expectedResult: true);
-  checkAny(X, [X, A, B, D, C, G, F, I],
+  checkAny(X, [X, A, B, D, C, E, F, H, I],
       find: I, anySubtype: true, expectedResult: true);
 }
 
diff --git a/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart b/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
index 64b6506..3b16a86 100644
--- a/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
+++ b/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
@@ -65,6 +65,8 @@
 
   MemoryEnvironment(this._environment, [this.env = const <String, String>{}]);
 
+  bool get checkCasts => true;
+
   @override
   String readFromEnvironment(String name) => env[name];
 
diff --git a/tests/compiler/dart2js/model/in_memory_split_test.dart b/tests/compiler/dart2js/model/in_memory_split_test.dart
deleted file mode 100644
index ab13b90..0000000
--- a/tests/compiler/dart2js/model/in_memory_split_test.dart
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:args/args.dart';
-import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/filenames.dart';
-import 'package:compiler/src/js_backend/inferred_data.dart';
-import 'package:compiler/src/js_model/js_strategy.dart';
-import 'package:compiler/src/serialization/serialization.dart';
-import 'package:compiler/src/types/types.dart';
-import 'package:expect/expect.dart';
-import 'package:front_end/src/fasta/kernel/utils.dart' as ir
-    show serializeComponent;
-import 'package:front_end/src/fasta/kernel/utils.dart';
-import 'package:kernel/ast.dart' as ir;
-import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
-import '../helpers/memory_compiler.dart';
-
-main(List<String> args) {
-  ArgParser argParser = new ArgParser(allowTrailingOptions: true);
-  argParser.addFlag('debug', abbr: 'd', defaultsTo: false);
-  argParser.addFlag('object', abbr: 'o', defaultsTo: false);
-  argParser.addFlag('kinds', abbr: 'k', defaultsTo: false);
-  ArgResults argResults = argParser.parse(args);
-
-  bool useObjectSink = argResults['object'] || argResults['debug'];
-  bool useDataKinds = argResults['kinds'] || argResults['debug'];
-
-  asyncTest(() async {
-    Uri entryPoint;
-    if (argResults.rest.isEmpty) {
-      entryPoint = Uri.base.resolve('samples-dev/swarm/swarm.dart');
-    } else {
-      entryPoint = Uri.base.resolve(nativeToUriPath(argResults.rest.last));
-    }
-
-    CompilationResult result = await runCompiler(
-        entryPoint: entryPoint,
-        beforeRun: (Compiler compiler) {
-          compiler.stopAfterTypeInference = true;
-        });
-    Expect.isTrue(result.isSuccess);
-    Compiler compiler = result.compiler;
-    GlobalTypeInferenceResults globalInferenceResults = cloneInferenceResults(
-        compiler, compiler.globalInference.resultsForTesting,
-        useObjectSink: useObjectSink, useDataKinds: useDataKinds);
-    compiler.generateJavaScriptCode(globalInferenceResults);
-  });
-}
-
-GlobalTypeInferenceResults cloneInferenceResults(
-    Compiler compiler, GlobalTypeInferenceResults results,
-    {bool useObjectSink: false, bool useDataKinds}) {
-  JsClosedWorld closedWorld = results.closedWorld;
-  InferredData inferredData = results.inferredData;
-  ir.Component component = closedWorld.elementMap.programEnv.mainComponent;
-  List<int> irData = ir.serializeComponent(component);
-
-  Function() getData;
-
-  DataSink sink;
-  if (useObjectSink) {
-    List data = [];
-    sink = new ObjectSink(data, useDataKinds: useDataKinds);
-    getData = () => data;
-  } else {
-    ByteSink byteSink = new ByteSink();
-    sink = new BinarySink(byteSink, useDataKinds: useDataKinds);
-    getData = () => byteSink.builder.takeBytes();
-  }
-  closedWorld.writeToDataSink(sink);
-  inferredData.writeToDataSink(sink);
-  results.writeToDataSink(sink);
-  sink.close();
-  var worldData = getData();
-  print('data size: ${worldData.length}');
-
-  ir.Component newComponent = new ir.Component();
-  new BinaryBuilder(irData).readComponent(newComponent);
-  DataSource source = useObjectSink
-      ? new ObjectSource(worldData, useDataKinds: useDataKinds)
-      : new BinarySourceImpl(worldData, useDataKinds: useDataKinds);
-  closedWorld = new JsClosedWorld.readFromDataSource(
-      compiler.options,
-      compiler.reporter,
-      compiler.environment,
-      compiler.abstractValueStrategy,
-      newComponent,
-      source);
-  inferredData = new InferredData.readFromDataSource(source, closedWorld);
-  results = new GlobalTypeInferenceResults.readFromDataSource(
-      source, closedWorld, inferredData);
-  return results;
-}
diff --git a/tests/compiler/dart2js/rti/rti_emission_test.dart b/tests/compiler/dart2js/rti/rti_emission_test.dart
index 5662705..ba12ff1 100644
--- a/tests/compiler/dart2js/rti/rti_emission_test.dart
+++ b/tests/compiler/dart2js/rti/rti_emission_test.dart
@@ -13,7 +13,7 @@
 import 'package:compiler/src/js_backend/runtime_types.dart';
 import 'package:compiler/src/js_emitter/model.dart';
 import 'package:compiler/src/js_model/element_map.dart';
-import 'package:compiler/src/js_model/js_strategy.dart';
+import 'package:compiler/src/js_model/js_world.dart';
 import 'package:kernel/ast.dart' as ir;
 import '../equivalence/id_equivalence.dart';
 import '../equivalence/id_equivalence_helper.dart';
diff --git a/tests/compiler/dart2js/rti/rti_need_test_helper.dart b/tests/compiler/dart2js/rti/rti_need_test_helper.dart
index aa6668b..29bbaa1 100644
--- a/tests/compiler/dart2js/rti/rti_need_test_helper.dart
+++ b/tests/compiler/dart2js/rti/rti_need_test_helper.dart
@@ -13,13 +13,13 @@
 import 'package:compiler/src/elements/types.dart';
 import 'package:compiler/src/ir/util.dart';
 import 'package:compiler/src/js_backend/runtime_types.dart';
-import 'package:compiler/src/js_model/js_strategy.dart';
+import 'package:compiler/src/js_model/js_world.dart';
 import 'package:compiler/src/js_model/element_map.dart';
 import 'package:compiler/src/kernel/element_map.dart';
 import 'package:compiler/src/kernel/kernel_strategy.dart';
 import 'package:compiler/src/universe/feature.dart';
+import 'package:compiler/src/universe/resolution_world_builder.dart';
 import 'package:compiler/src/universe/selector.dart';
-import 'package:compiler/src/universe/world_builder.dart';
 import 'package:kernel/ast.dart' as ir;
 import '../equivalence/check_helpers.dart';
 import '../equivalence/id_equivalence.dart';
diff --git a/tests/compiler/dart2js/serialization/data/constructor_name.dart b/tests/compiler/dart2js/serialization/data/constructor_name.dart
new file mode 100644
index 0000000..dc1e3b2
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/data/constructor_name.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Class1 {
+  var foo;
+  Class1.foo();
+}
+
+// TODO(johnniwinther): Uncomment this when #34965 is fixed:
+//class Class2 {
+//  var bar;
+//  factory Class2.bar() => null;
+//}
+
+main() {
+  new Class1.foo().foo;
+  //new Class2.bar().bar;
+}
diff --git a/tests/compiler/dart2js/serialization/data/continue.dart b/tests/compiler/dart2js/serialization/data/continue.dart
new file mode 100644
index 0000000..5d8c3ec
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/data/continue.dart
@@ -0,0 +1,15 @@
+// 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.
+
+main() {
+  continueInClosure();
+}
+
+void continueInClosure() {
+  () {
+    do {
+      continue;
+    } while (false);
+  }();
+}
diff --git a/tests/compiler/dart2js/serialization/data/deferred.dart b/tests/compiler/dart2js/serialization/data/deferred.dart
new file mode 100644
index 0000000..b0ea93c
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/data/deferred.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../libs/deferred_lib1.dart';
+import '../libs/deferred_lib2.dart' deferred as lib2;
+
+main() async {
+  C1.value;
+  print(const C(4));
+  () => print(const C(5));
+  await lib2.loadLibrary();
+  lib2.C2;
+  lib2.C3;
+  lib2.C4;
+  lib2.C5;
+  lib2.C6;
+  lib2.C7.value;
+}
diff --git a/tests/compiler/dart2js/serialization/data/jsinterop.dart b/tests/compiler/dart2js/serialization/data/jsinterop.dart
new file mode 100644
index 0000000..6996587
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/data/jsinterop.dart
@@ -0,0 +1,26 @@
+// 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.
+
+@JS()
+library lib;
+
+import 'package:js/js.dart';
+import 'package:meta/dart2js.dart';
+
+@JS()
+@anonymous
+class GenericClass<T> {
+  external factory GenericClass();
+
+  external set setter(value);
+}
+
+main() {
+  method();
+}
+
+@tryInline
+method() {
+  new GenericClass().setter = 42;
+}
diff --git a/tests/compiler/dart2js/serialization/data/labels.dart b/tests/compiler/dart2js/serialization/data/labels.dart
new file mode 100644
index 0000000..4ba9f05
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/data/labels.dart
@@ -0,0 +1,10 @@
+// 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.
+
+main() {
+  label:
+  {
+    break label;
+  }
+}
diff --git a/tests/compiler/dart2js/serialization/data/maps.dart b/tests/compiler/dart2js/serialization/data/maps.dart
new file mode 100644
index 0000000..ca45d28
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/data/maps.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+main() {
+  createMap();
+  createDictionary();
+  returnUnion(true);
+  returnUnion(false);
+}
+
+createMap() => {0: 1};
+
+createDictionary() => {'foo': 'bar'};
+
+returnUnion(bool b) => b ? createMap() : createDictionary();
diff --git a/tests/compiler/dart2js/serialization/data/switch.dart b/tests/compiler/dart2js/serialization/data/switch.dart
new file mode 100644
index 0000000..fc9bc83
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/data/switch.dart
@@ -0,0 +1,17 @@
+// 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.
+
+main() {
+  switchCaseWithContinue(null);
+}
+
+switchCaseWithContinue(e) {
+  switch (e) {
+    label:
+    case 0:
+      break;
+    case 1:
+      continue label;
+  }
+}
diff --git a/tests/compiler/dart2js/serialization/data/typedef.dart b/tests/compiler/dart2js/serialization/data/typedef.dart
new file mode 100644
index 0000000..01d991b
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/data/typedef.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+main() {
+  c;
+}
+
+typedef Typedef();
+
+const c = Typedef;
diff --git a/tests/compiler/dart2js/serialization/in_memory_split_test.dart b/tests/compiler/dart2js/serialization/in_memory_split_test.dart
new file mode 100644
index 0000000..33a7912
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/in_memory_split_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:args/args.dart';
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/serialization/strategies.dart';
+import 'serialization_test_helper.dart';
+import '../helpers/args_helper.dart';
+
+main(List<String> args) {
+  ArgParser argParser = createArgParser();
+  argParser.addFlag('debug', abbr: 'd', defaultsTo: false);
+  argParser.addFlag('object', abbr: 'o', defaultsTo: false);
+  argParser.addFlag('kinds', abbr: 'k', defaultsTo: false);
+
+  asyncTest(() async {
+    ArgResults argResults = argParser.parse(args);
+    bool useDataKinds = argResults['kinds'] || argResults['debug'];
+    SerializationStrategy strategy =
+        new BytesInMemorySerializationStrategy(useDataKinds: useDataKinds);
+    if (argResults['object'] || argResults['debug']) {
+      strategy =
+          new ObjectsInMemorySerializationStrategy(useDataKinds: useDataKinds);
+    }
+
+    Uri entryPoint = getEntryPoint(argResults) ??
+        Uri.base.resolve('samples-dev/swarm/swarm.dart');
+    Uri librariesSpecificationUri = getLibrariesSpec(argResults);
+    Uri packageConfig = getPackages(argResults);
+    List<String> options = getOptions(argResults);
+    await runTest(
+        entryPoint: entryPoint,
+        packageConfig: packageConfig,
+        librariesSpecificationUri: librariesSpecificationUri,
+        options: options,
+        strategy: strategy,
+        useDataKinds: useDataKinds);
+  });
+}
diff --git a/tests/compiler/dart2js/serialization/libs/deferred_lib1.dart b/tests/compiler/dart2js/serialization/libs/deferred_lib1.dart
new file mode 100644
index 0000000..361b0fd
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/libs/deferred_lib1.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library deferred_constants1_lib1;
+
+export 'deferred_lib3.dart' show C, C1;
diff --git a/tests/compiler/dart2js/serialization/libs/deferred_lib2.dart b/tests/compiler/dart2js/serialization/libs/deferred_lib2.dart
new file mode 100644
index 0000000..379239d
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/libs/deferred_lib2.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library deferred_constants1_lib2;
+
+export 'deferred_lib3.dart' show C2, C3, C4, C5, C6, C7;
diff --git a/tests/compiler/dart2js/serialization/libs/deferred_lib3.dart b/tests/compiler/dart2js/serialization/libs/deferred_lib3.dart
new file mode 100644
index 0000000..708a79a
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/libs/deferred_lib3.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library deferred_constants1_lib3;
+
+import 'dart:async';
+
+class C {
+  final value;
+
+  const C(this.value);
+}
+
+FutureOr<T> func<T>(@Deprecated('bar') foo) => null;
+
+/// ---------------------------------------------------------------------------
+/// Constant used from main: not deferred.
+/// ---------------------------------------------------------------------------
+
+const C1 = const C(1);
+
+/// ---------------------------------------------------------------------------
+/// Constant completely deferred.
+/// ---------------------------------------------------------------------------
+
+const C2 = C;
+
+/// ---------------------------------------------------------------------------
+/// Constant fields not used from main, but the constant value are: so the field
+/// and the constants are in different output units.
+/// ---------------------------------------------------------------------------
+
+const C3 = func;
+
+const C4 = const [1, 1.5, bool];
+
+/// ---------------------------------------------------------------------------
+/// Constant value used form a closure within main.
+/// ---------------------------------------------------------------------------
+
+const C5 = const {};
+
+/// ---------------------------------------------------------------------------
+/// Deferred constants, used after a deferred load.
+/// ---------------------------------------------------------------------------
+
+const FutureOr<int> Function(dynamic) C6 = func;
+
+const C7 = null;
diff --git a/tests/compiler/dart2js/serialization/on_disk_split_test.dart b/tests/compiler/dart2js/serialization/on_disk_split_test.dart
new file mode 100644
index 0000000..163efa5
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/on_disk_split_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/dart2js.dart';
+
+main(List<String> args) {
+  asyncTest(() async {
+    Directory dir = await Directory.systemTemp.createTemp('on_disk');
+    Uri dillUri = dir.uri.resolve('out.dill');
+    Uri outUri = dir.uri.resolve('out.js');
+    await internalMain([
+      'samples-dev/swarm/swarm.dart',
+      '--out=${dillUri}',
+      Flags.writeData,
+      Flags.verbose,
+    ]);
+    await internalMain([
+      '${dillUri}',
+      '--out=${outUri}',
+      Flags.readData,
+      Flags.verbose,
+    ]);
+    await dir.delete(recursive: true);
+  });
+}
diff --git a/tests/compiler/dart2js/serialization/serialization_test.dart b/tests/compiler/dart2js/serialization/serialization_test.dart
new file mode 100644
index 0000000..72af9ba
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/serialization_test.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/serialization/strategies.dart';
+import 'package:expect/expect.dart';
+import 'serialization_test_helper.dart';
+
+main(List<String> args) {
+  asyncTest(() async {
+    Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
+    Directory libDir = new Directory.fromUri(Platform.script.resolve('libs'));
+    await checkTests(dataDir, options: [], args: args, libDirectory: libDir);
+  });
+}
+
+Future checkTests(Directory dataDir,
+    {bool testStrongMode: true,
+    List<String> options: const <String>[],
+    List<String> args: const <String>[],
+    Directory libDirectory: null,
+    bool forUserLibrariesOnly: true,
+    int shards: 1,
+    int shardIndex: 0,
+    void onTest(Uri uri)}) async {
+  args = args.toList();
+  bool shouldContinue = args.remove('-c');
+  bool continued = false;
+  bool hasFailures = false;
+  SerializationStrategy strategy = const BytesInMemorySerializationStrategy();
+  if (args.remove('-d')) {
+    strategy = const ObjectsInMemorySerializationStrategy();
+  }
+
+  var relativeDir = dataDir.uri.path.replaceAll(Uri.base.path, '');
+  print('Data dir: ${relativeDir}');
+  List<FileSystemEntity> entities = dataDir.listSync();
+  if (shards > 1) {
+    int start = entities.length * shardIndex ~/ shards;
+    int end = entities.length * (shardIndex + 1) ~/ shards;
+    entities = entities.sublist(start, end);
+  }
+  int testCount = 0;
+  for (FileSystemEntity entity in entities) {
+    String name = entity.uri.pathSegments.last;
+    if (args.isNotEmpty && !args.contains(name) && !continued) continue;
+    if (shouldContinue) continued = true;
+    testCount++;
+    List<String> testOptions = options.toList();
+    if (onTest != null) {
+      onTest(entity.uri);
+    }
+    print('----------------------------------------------------------------');
+    print('Test file: ${entity.uri}');
+    // Pretend this is a dart2js_native test to allow use of 'native' keyword
+    // and import of private libraries.
+    String commonTestPath = 'sdk/tests/compiler';
+    Uri entryPoint =
+        Uri.parse('memory:$commonTestPath/dart2js_native/main.dart');
+    String mainCode = await new File.fromUri(entity.uri).readAsString();
+    Map<String, String> memorySourceFiles = {entryPoint.path: mainCode};
+
+    if (libDirectory != null) {
+      print('Supporting libraries:');
+      String filePrefix = name.substring(0, name.lastIndexOf('.'));
+      await for (FileSystemEntity libEntity in libDirectory.list()) {
+        String libFileName = libEntity.uri.pathSegments.last;
+        if (libFileName.startsWith(filePrefix)) {
+          print('    - libs/$libFileName');
+          Uri libFileUri =
+              Uri.parse('memory:$commonTestPath/libs/$libFileName');
+          String libCode = await new File.fromUri(libEntity.uri).readAsString();
+          memorySourceFiles[libFileUri.path] = libCode;
+        }
+      }
+    }
+
+    await runTest(
+        entryPoint: entryPoint,
+        memorySourceFiles: memorySourceFiles,
+        options: testOptions,
+        strategy: strategy);
+  }
+  Expect.isFalse(hasFailures, 'Errors found.');
+  Expect.isTrue(testCount > 0, "No files were tested.");
+}
diff --git a/tests/compiler/dart2js/serialization/serialization_test_helper.dart b/tests/compiler/dart2js/serialization/serialization_test_helper.dart
new file mode 100644
index 0000000..12be8dc
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/serialization_test_helper.dart
@@ -0,0 +1,115 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:compiler/compiler_new.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/serialization/strategies.dart';
+import 'package:compiler/src/types/types.dart';
+import 'package:expect/expect.dart';
+import 'package:kernel/ast.dart' as ir;
+import '../helpers/memory_compiler.dart';
+import '../helpers/text_helpers.dart';
+
+runTest(
+    {Uri entryPoint,
+    Map<String, String> memorySourceFiles: const <String, String>{},
+    Uri packageConfig,
+    Uri librariesSpecificationUri,
+    List<String> options,
+    SerializationStrategy strategy: const BytesInMemorySerializationStrategy(),
+    bool useDataKinds: false}) async {
+  OutputCollector collector1 = new OutputCollector();
+  CompilationResult result1 = await runCompiler(
+      entryPoint: entryPoint,
+      memorySourceFiles: memorySourceFiles,
+      packageConfig: packageConfig,
+      librariesSpecificationUri: librariesSpecificationUri,
+      options: options,
+      outputProvider: collector1,
+      beforeRun: (Compiler compiler) {
+        compiler.libraryLoader.forceSerialization = true;
+      });
+  Expect.isTrue(result1.isSuccess);
+
+  OutputCollector collector2 = new OutputCollector();
+  CompilationResult result = await runCompiler(
+      entryPoint: entryPoint,
+      memorySourceFiles: memorySourceFiles,
+      packageConfig: packageConfig,
+      librariesSpecificationUri: librariesSpecificationUri,
+      options: options,
+      outputProvider: collector2,
+      beforeRun: (Compiler compiler) {
+        compiler.libraryLoader.forceSerialization = true;
+        compiler.stopAfterTypeInference = true;
+      });
+  Expect.isTrue(result.isSuccess);
+  Compiler compiler = result.compiler;
+  GlobalTypeInferenceResults globalInferenceResults =
+      compiler.globalInference.resultsForTesting;
+  GlobalTypeInferenceResults newGlobalInferenceResults =
+      cloneInferenceResults(compiler, globalInferenceResults, strategy);
+
+  Map<OutputType, Map<String, String>> output = collector1.clear();
+
+  compiler.generateJavaScriptCode(newGlobalInferenceResults);
+  Map<OutputType, Map<String, String>> newOutput = collector2.clear();
+
+  Expect.setEquals(output.keys, newOutput.keys, "Output type mismatch.");
+
+  output.forEach((OutputType outputType, Map<String, String> fileMap) {
+    Map<String, String> newFileMap = newOutput[outputType];
+    Expect.setEquals(fileMap.keys, newFileMap.keys,
+        "File mismatch for output type $outputType.");
+
+    fileMap.forEach((String fileName, String code) {
+      String newCode = newFileMap[fileName];
+      int failureLine = checkEqualContentAndShowDiff(code, newCode);
+      Expect.isNull(
+          failureLine,
+          "Output mismatch at line $failureLine in "
+          "file '${fileName}' of type ${outputType}.");
+    });
+  });
+}
+
+GlobalTypeInferenceResults cloneInferenceResults(Compiler compiler,
+    GlobalTypeInferenceResults results, SerializationStrategy strategy) {
+  List<int> irData = strategy.serializeComponent(results);
+
+  List worldData = strategy.serializeData(results);
+  print('data size: ${worldData.length}');
+
+  ir.Component newComponent = strategy.deserializeComponent(irData);
+  GlobalTypeInferenceResults newResults = strategy.deserializeData(
+      compiler.options,
+      compiler.reporter,
+      compiler.environment,
+      compiler.abstractValueStrategy,
+      newComponent,
+      worldData);
+  List newWorldData = strategy.serializeData(newResults);
+  Expect.equals(worldData.length, newWorldData.length,
+      "Reserialization data length mismatch.");
+  for (int i = 0; i < worldData.length; i++) {
+    if (worldData[i] != newWorldData[i]) {
+      print('Reserialization data mismatch at offset $i:');
+      for (int j = i - 50; j < i + 50; j++) {
+        if (0 <= j && j <= worldData.length) {
+          String text;
+          if (worldData[j] == newWorldData[j]) {
+            text = '${worldData[j]}';
+          } else {
+            text = '${worldData[j]} <> ${newWorldData[j]}';
+          }
+          print('${j == i ? '> ' : '  '}$j: $text');
+        }
+      }
+      break;
+    }
+  }
+  Expect.listEquals(worldData, newWorldData);
+
+  return newResults;
+}
diff --git a/tests/compiler/dart2js/sourcemaps/d2js_validity_test.dart b/tests/compiler/dart2js/sourcemaps/d2js_validity_test.dart
index f724936..36ab917 100644
--- a/tests/compiler/dart2js/sourcemaps/d2js_validity_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/d2js_validity_test.dart
@@ -20,7 +20,7 @@
         Future<CompilationResult> result = entry.internalMain([
           mainFile,
           '-o${tmpDir.path}/out.js',
-          '--library-root=sdk',
+          '--libraries-spec=sdk/lib/libraries.json',
         ]);
         return result.then((CompilationResult result) {
           CompilerImpl compiler = result.compiler;
diff --git a/tests/compiler/dart2js/sourcemaps/deferred_d2js_validity_test.dart b/tests/compiler/dart2js/sourcemaps/deferred_d2js_validity_test.dart
index 321719b..12d983d 100644
--- a/tests/compiler/dart2js/sourcemaps/deferred_d2js_validity_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/deferred_d2js_validity_test.dart
@@ -19,7 +19,7 @@
         var result = entry.internalMain([
           file,
           '-o${tmpDir.path}/out.js',
-          '--library-root=sdk',
+          '--libraries-spec=sdk/lib/libraries.json',
         ]);
         return result.then((CompilationResult result) {
           CompilerImpl compiler = result.compiler;
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
index e17247a..7b45545 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
@@ -64,6 +64,10 @@
   OutputSink createOutputSink(String name, String extension, OutputType type) {
     return createSourceFileSink(name, extension, type);
   }
+
+  @override
+  BinaryOutputSink createBinarySink(Uri uri) =>
+      throw new UnsupportedError("OutputProvider.createBinarySink");
 }
 
 class CloningOutputProvider extends OutputProvider {
@@ -78,6 +82,10 @@
     return new CloningOutputSink(
         [output, createSourceFileSink(name, extension, type)]);
   }
+
+  @override
+  BinaryOutputSink createBinarySink(Uri uri) =>
+      throw new UnsupportedError("CloningOutputProvider.createBinarySink");
 }
 
 abstract class SourceFileManager {
diff --git a/tests/compiler/dart2js/sourcemaps/name_test.dart b/tests/compiler/dart2js/sourcemaps/name_test.dart
index f6648d8..b6ecce8 100644
--- a/tests/compiler/dart2js/sourcemaps/name_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/name_test.dart
@@ -11,7 +11,7 @@
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/io/kernel_source_information.dart';
-import 'package:compiler/src/js_model/js_strategy.dart';
+import 'package:compiler/src/js_model/js_world.dart';
 import '../helpers/memory_compiler.dart';
 
 const String SOURCE = '''
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart b/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
index deebbc3..5d4d3b7 100644
--- a/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
@@ -81,7 +81,7 @@
   return testStackTrace(test, config, (String input, String output) async {
     List<String> arguments = [
       '-o$output',
-      '--library-root=sdk',
+      '--libraries-spec=sdk/lib/libraries.json',
       '--packages=${Platform.packageConfig}',
       input,
     ]..addAll(options);
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 2e6c022..4facaed 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -92,7 +92,6 @@
 [ $compiler == dart2js && $runtime == d8 ]
 deferred_fail_and_retry_test: RuntimeError # Uses XHR in dart:html
 deferred_with_csp_nonce_test: RuntimeError # Uses dart:html
-unconditional_dartio_import_test: RuntimeError # Uses dart:io
 
 [ $compiler == dart2js && $runtime == ff && $system == windows ]
 consistent_index_error_string_test: Pass, Slow # Issue 25940
diff --git a/tests/compiler/dart2js_extra/js_interop_cast_test.dart b/tests/compiler/dart2js_extra/js_interop_cast_test.dart
new file mode 100644
index 0000000..28c018a
--- /dev/null
+++ b/tests/compiler/dart2js_extra/js_interop_cast_test.dart
@@ -0,0 +1,63 @@
+// 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.
+
+// Test that we don't crash on computing js-interop classes when metadata
+// constants contain implicit casts.
+//
+// We need the class hierarchy to perform the evaluation the implicit casts but
+// we also change the class hierarchy when we discover that a class is a
+// js-interop class. By mixing (valid) constants that contain implicit casts
+// with the @JS annotations that define classes to be js-interop, triggering
+// the use of the class hierarchy before all js-interop classes have been
+// registered, this test causes dart2js to crash with an assertion failure.
+
+@Constant(4)
+@JS()
+@Constant(5)
+library test;
+
+import 'package:js/js.dart';
+
+@Constant(-1)
+method() {}
+
+@Constant(0)
+@JS()
+@anonymous
+@Constant(1)
+class ClassA {
+  external factory ClassA();
+
+  @Constant(2)
+  external method();
+}
+
+class Constant {
+  final int field;
+
+  const Constant(dynamic value) : field = value;
+}
+
+@Constant(0)
+@JS()
+@anonymous
+@Constant(1)
+class ClassB {
+  external factory ClassB();
+
+  @Constant(2)
+  external method();
+}
+
+class ClassC {
+  method() {}
+}
+
+main() {
+  method();
+  dynamic c = new ClassC();
+  c.method();
+  new ClassA();
+  new ClassB();
+}
diff --git a/tests/corelib_2/bigint_test.dart b/tests/corelib_2/bigint_test.dart
index f4e9865..7ad5309 100644
--- a/tests/corelib_2/bigint_test.dart
+++ b/tests/corelib_2/bigint_test.dart
@@ -1031,38 +1031,38 @@
 
 main() {
   for (int i = 0; i < 8; i++) {
-    Expect.equals(BigInt.parse("1234567890123456789"), foo());
-    Expect.equals(BigInt.parse("12345678901234567890"), bar());
-    testModPow();
-    testModInverse();
-    testGcd();
-    testSmiOverflow();
-    testBigintAnd();
-    testBigintOr();
-    testBigintXor();
-    testBigintAdd();
-    testBigintSub();
-    testBigintMul();
-    testBigintTruncDiv();
-    testBigintDiv();
-    testBigintModulo();
-    testBigintModPow();
-    testBigintModInverse();
-    testBigintGcd();
-    testBigintNegate();
-    testShiftAmount();
-    testPow();
-    testToRadixString();
-    testToString();
-    testFromToInt();
-    testFromToDouble();
-    Expect.equals(BigInt.parse("12345678901234567890"),
-        BigInt.parse("12345678901234567890").abs());
-    Expect.equals(BigInt.parse("12345678901234567890"),
-        BigInt.parse("-12345678901234567890").abs());
-    var a = BigInt.parse("10000000000000000000");
-    var b = BigInt.parse("10000000000000000001");
-    Expect.equals(false, a.hashCode == b.hashCode);
-    Expect.equals(true, a.hashCode == (b - BigInt.one).hashCode);
+    Expect.equals(BigInt.parse("1234567890123456789"), foo()); /// 01: ok
+    Expect.equals(BigInt.parse("12345678901234567890"), bar()); /// 02: ok
+    testModPow(); /// 03: ok
+    testModInverse(); /// 04: ok
+    testGcd(); /// 05: ok
+    testSmiOverflow(); /// 06: ok
+    testBigintAnd(); /// 07: ok
+    testBigintOr(); /// 08: ok
+    testBigintXor(); /// 09: ok
+    testBigintAdd(); /// 10: ok
+    testBigintSub(); /// 11: ok
+    testBigintMul(); /// 12: ok
+    testBigintTruncDiv(); /// 12: ok
+    testBigintDiv(); /// 13: ok
+    testBigintModulo(); /// 14: ok
+    testBigintModPow(); /// 15: ok
+    testBigintModInverse(); /// 16: ok
+    testBigintGcd(); /// 17: ok
+    testBigintNegate(); /// 18: ok
+    testShiftAmount(); /// 19: ok
+    testPow(); /// 20: ok
+    testToRadixString(); /// 21: ok
+    testToString(); /// 22: ok
+    testFromToInt(); /// 23: ok
+    testFromToDouble(); /// 24: ok
+    Expect.equals(BigInt.parse("12345678901234567890"), /// 25: ok
+        BigInt.parse("12345678901234567890").abs()); /// 25: ok
+    Expect.equals(BigInt.parse("12345678901234567890"), /// 26: ok
+        BigInt.parse("-12345678901234567890").abs()); /// 26: ok
+    var a = BigInt.parse("10000000000000000000"); /// 27: ok
+    var b = BigInt.parse("10000000000000000001"); /// 27: ok
+    Expect.equals(false, a.hashCode == b.hashCode); /// 27: ok
+    Expect.equals(true, a.hashCode == (b - BigInt.one).hashCode); /// 27: ok
   }
 }
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 2723fd2..d705379 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -1,7 +1,6 @@
 # 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.
-maps_test: Skip # Maps class no longer exists
 
 [ $compiler == app_jitk ]
 symbol_operator_test/03: RuntimeError
@@ -115,9 +114,6 @@
 [ $fasta ]
 symbol_reserved_word_test/04: MissingCompileTimeError
 symbol_reserved_word_test/07: MissingCompileTimeError
-symbol_reserved_word_test/10: MissingCompileTimeError
-symbol_test/02: MissingCompileTimeError
-symbol_test/03: MissingCompileTimeError
 
 [ !$strong ]
 cast_test: SkipByDesign # Uses generic method parameters.
@@ -132,6 +128,9 @@
 [ $arch == x64 && $system == windows ]
 stopwatch_test: Skip # Flaky test due to expected performance behaviour.
 
+[ $builder_tag == obfuscated && $compiler == dartkp ]
+nsm_invocation_test: RuntimeError # Issue 35066
+
 [ $builder_tag == obfuscated && $runtime == dart_precompiled ]
 apply_generic_function_test: SkipByDesign # Function.apply with named args
 apply_test: Skip # Uses new Symbol via symbolMapToStringMap helper
@@ -282,6 +281,11 @@
 [ $compiler != dartk && $runtime == vm && $checked ]
 apply_test/01: RuntimeError
 
+[ $compiler != dartkb && $compiler != dartkp && $fasta ]
+symbol_reserved_word_test/10: MissingCompileTimeError
+symbol_test/02: MissingCompileTimeError
+symbol_test/03: MissingCompileTimeError
+
 [ $compiler == dartkp && $runtime == dart_precompiled && $strong ]
 iterable_fold_test/02: RuntimeError
 iterable_reduce_test/01: CompileTimeError # Issue 31533
@@ -566,7 +570,9 @@
 uri_test: Pass, Slow
 
 [ $compiler == dartkb || $compiler == dartkp ]
-bigint_test: Pass, Timeout # --no_intrinsify
+bigint_parse_radix_test: Pass, Slow # --no_intrinsify
+bigint_test/03: SkipSlow # --no_intrinsify
+bigint_test/15: SkipSlow # --no_intrinsify
 
 [ $compiler == precompiler || $runtime == vm && !$checked && !$strong ]
 int_parse_radix_test/badTypes: RuntimeError # wrong exception returned
diff --git a/tests/corelib_2/maps_test.dart b/tests/corelib_2/maps_test.dart
deleted file mode 100644
index 9183c23..0000000
--- a/tests/corelib_2/maps_test.dart
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (c) 2011, 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 maps_test;
-
-import "package:expect/expect.dart";
-import 'dart:collection';
-
-main() {
-  final key1 = "key1";
-  final key2 = "key2";
-  final key3 = "key3";
-  final key4 = "key4";
-  final key5 = "key5";
-  final key6 = "key6";
-  final key7 = "key7";
-  final key8 = "key8";
-
-  final value1 = 10;
-  final value2 = 20;
-  final value3 = 30;
-  final value4 = 40;
-  final value5 = 50;
-  final value6 = 60;
-  final value7 = 70;
-  final value8 = 80;
-
-  Map map = new Map();
-
-  map[key1] = value1;
-  map[key1] = value2;
-  Expect.equals(false, Maps.containsKey(map, key2));
-  Expect.equals(1, Maps.length(map));
-
-  map[key1] = value1;
-  // Add enough entries to make sure the table grows.
-  map[key2] = value2;
-  Expect.equals(2, Maps.length(map));
-  map[key3] = value3;
-  map[key4] = value4;
-  map[key5] = value5;
-  map[key6] = value6;
-  map[key7] = value7;
-  map[key8] = value8;
-  Expect.equals(8, Maps.length(map));
-
-  map.remove(key4);
-  Expect.equals(false, Maps.containsKey(map, key4));
-  Expect.equals(7, Maps.length(map));
-
-  // Test clearing the table.
-  Maps.clear(map);
-  Expect.equals(0, Maps.length(map));
-  Expect.equals(false, Maps.containsKey(map, key1));
-  Expect.equals(false, map.containsKey(key1));
-  Expect.equals(false, Maps.containsKey(map, key2));
-  Expect.equals(false, map.containsKey(key2));
-  Expect.equals(false, Maps.containsKey(map, key3));
-  Expect.equals(false, map.containsKey(key3));
-  Expect.equals(false, Maps.containsKey(map, key4));
-  Expect.equals(false, map.containsKey(key4));
-  Expect.equals(false, Maps.containsKey(map, key5));
-  Expect.equals(false, map.containsKey(key5));
-  Expect.equals(false, Maps.containsKey(map, key6));
-  Expect.equals(false, map.containsKey(key6));
-  Expect.equals(false, Maps.containsKey(map, key7));
-  Expect.equals(false, map.containsKey(key7));
-  Expect.equals(false, Maps.containsKey(map, key8));
-  Expect.equals(false, map.containsKey(key8));
-
-  // Test adding and removing again.
-  map[key1] = value1;
-  Expect.equals(1, Maps.length(map));
-  map[key2] = value2;
-  Expect.equals(2, Maps.length(map));
-  map[key3] = value3;
-  map.remove(key3);
-  Expect.equals(2, Maps.length(map));
-  map[key4] = value4;
-  map.remove(key4);
-  Expect.equals(2, Maps.length(map));
-  map[key5] = value5;
-  map.remove(key5);
-  Expect.equals(2, Maps.length(map));
-  map[key6] = value6;
-  map.remove(key6);
-  Expect.equals(2, Maps.length(map));
-  map[key7] = value7;
-  map.remove(key7);
-  Expect.equals(2, Maps.length(map));
-  map[key8] = value8;
-  map.remove(key8);
-  Expect.equals(2, Maps.length(map));
-
-  Expect.equals(true, Maps.containsKey(map, key1));
-  Expect.equals(true, Maps.containsValue(map, value1));
-
-  // Test Map.forEach.
-  Map other_map = new Map();
-  void testForEachMap(key, value) {
-    other_map[key] = value;
-  }
-
-  Maps.forEach(map, testForEachMap);
-  Expect.equals(true, other_map.containsKey(key1));
-  Expect.equals(true, other_map.containsKey(key2));
-  Expect.equals(true, other_map.containsValue(value1));
-  Expect.equals(true, other_map.containsValue(value2));
-  Expect.equals(2, Maps.length(other_map));
-
-  // Test Collection.values.
-  void testForEachCollection(value) {
-    other_map[value] = value;
-  }
-
-  Iterable values = Maps.getValues(map);
-  other_map = new Map();
-  values.forEach(testForEachCollection);
-  Expect.equals(true, !other_map.containsKey(key1));
-  Expect.equals(true, !other_map.containsKey(key2));
-  Expect.equals(true, !other_map.containsValue(key1));
-  Expect.equals(true, !other_map.containsValue(key2));
-  Expect.equals(true, other_map.containsKey(value1));
-  Expect.equals(true, other_map.containsKey(value2));
-  Expect.equals(true, other_map.containsValue(value1));
-  Expect.equals(true, other_map.containsValue(value2));
-  Expect.equals(2, other_map.length);
-  other_map.clear();
-
-  // Test Map.putIfAbsent.
-  map.clear();
-  Expect.equals(false, Maps.containsKey(map, key1));
-  Maps.putIfAbsent(map, key1, () => 10);
-  Expect.equals(true, map.containsKey(key1));
-  Expect.equals(10, map[key1]);
-  Expect.equals(10, Maps.putIfAbsent(map, key1, () => 11));
-}
diff --git a/tests/language_2/async_star_error_test.dart b/tests/language_2/async_star_error_test.dart
new file mode 100644
index 0000000..4bf2433
--- /dev/null
+++ b/tests/language_2/async_star_error_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "package:expect/async_minitest.dart";
+
+/// Tests for exceptions raised in async*
+main() {
+  test('async* with Stream.first should complete with an error', () async {
+    var expectedStack;
+    Stream<int> foo() async* {
+      try {
+        throw 'oops';
+      } catch (e, s) {
+        expectedStack = s;
+        try {
+          throw 'oops again!';
+        } catch (e2, _) {}
+        await new Future.error(e, s);
+      }
+      yield 42;
+    }
+
+    try {
+      await foo().first;
+      fail('should not get here, an error should be thrown');
+    } catch (e, s) {
+      expect(e, 'oops');
+      expect(s, expectedStack);
+    }
+  });
+}
diff --git a/tests/language_2/factory_and_instance_variable_test.dart b/tests/language_2/factory_and_instance_variable_test.dart
new file mode 100644
index 0000000..97f92f9
--- /dev/null
+++ b/tests/language_2/factory_and_instance_variable_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE.md file.
+
+abstract class A {
+  var bar;
+  factory A.bar() = B.bar;
+
+  get foo => bar;
+  static get baz => bar; //# 01: compile-time error
+}
+
+class B implements A {
+  var bar;
+  factory B.bar() => new C.bar();
+
+  get foo => bar;
+  static get baz => bar; //# 02: compile-time error
+
+  B() {}
+}
+
+class C extends B {
+  C.bar() {
+    bar = "foo";
+  }
+
+  static get baz => bar; //# 03: compile-time error
+}
+
+main() {
+  assert(new A.bar().foo == "foo");
+  assert(new B.bar().foo == "foo");
+  assert(new C.bar().foo == "foo");
+  assert(new A.bar().bar == "foo");
+  assert(new B.bar().bar == "foo");
+  assert(new C.bar().bar == "foo");
+}
diff --git a/tests/language_2/function_type_parameter_bound_object_test.dart b/tests/language_2/function_type_parameter_bound_object_test.dart
new file mode 100644
index 0000000..ba58f75
--- /dev/null
+++ b/tests/language_2/function_type_parameter_bound_object_test.dart
@@ -0,0 +1,17 @@
+// 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.
+
+Q hest<Q>(dynamic x) {
+  if (x is Q) return x;
+  return null;
+}
+
+Q Function<Q>(dynamic) pony = hest;
+Q Function<Q extends Object>(dynamic) zebra = hest;
+
+main() {
+  hest(42).fisk(); //# 01: runtime error
+  pony(42).fisk(); //# 02: runtime error
+  zebra(42).fisk(); //# 03: compile-time error
+}
diff --git a/tests/language_2/labeled_variable_declaration_test.dart b/tests/language_2/labeled_variable_declaration_test.dart
new file mode 100644
index 0000000..6dede5a
--- /dev/null
+++ b/tests/language_2/labeled_variable_declaration_test.dart
@@ -0,0 +1,10 @@
+// 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.
+
+main() {
+  L:
+  var x, y;
+  x = 42;
+  y = x;
+}
diff --git a/tests/language_2/language_2.status b/tests/language_2/language_2.status
index 5622608..4f4d666 100644
--- a/tests/language_2/language_2.status
+++ b/tests/language_2/language_2.status
@@ -54,7 +54,6 @@
 type_checks_in_factory_method_test: SkipByDesign # Requires checked mode.
 
 [ $fasta ]
-mixin_declaration/mixin_declaration_invalid_syntax_test/none: CompileTimeError # because mixin declarations get (invalid) forwarding constructors
 partial_instantiation_static_bounds_check_test/01: MissingCompileTimeError # Issue 34327
 partial_instantiation_static_bounds_check_test/02: MissingCompileTimeError # Issue 34327
 partial_instantiation_static_bounds_check_test/03: MissingCompileTimeError # Issue 34327
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index 5d74bcc..a1c001a 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -14,7 +14,6 @@
 additional_interface_adds_optional_args_test: CompileTimeError # Issue #30568
 cascaded_forwarding_stubs_test: CompileTimeError # Issue 34329
 config_import_corelib_test: CompileTimeError, StaticWarning, OK # failing-by-design: Will never pass, see Issue #34332
-conflicting_generic_interfaces_hierarchy_loop_infinite_test: Skip # Issue #34333 (loops forever)
 const_cast2_test/01: CompileTimeError # failing-by-design: Not a const expression, see Issue #34334
 const_cast2_test/none: CompileTimeError # failing-by-design: Not a const expression, see Issue #34334
 const_constructor3_test/04: MissingCompileTimeError # Side-effect of working around issue 33441 for int-to-double
@@ -98,10 +97,9 @@
 regress_30121_test: CompileTimeError # Issue 31087
 regress_30339_test: CompileTimeError
 regress_33479_test/01: Crash # Issue #33479
+set_literals/*: Skip
 setter3_test/01: CompileTimeError # Invalid test, see https://github.com/dart-lang/sdk/issues/33837
 setter3_test/02: CompileTimeError # Invalid test, see https://github.com/dart-lang/sdk/issues/33837
-string_split_test: CompileTimeError
-string_supertype_checked_test: CompileTimeError
 super_bound_closure_test/none: CompileTimeError
 super_no_such_method1_test: CompileTimeError # Invalid test, probably, see https://github.com/dart-lang/sdk/issues/33963
 super_no_such_method2_test: CompileTimeError # Invalid test, probably, see https://github.com/dart-lang/sdk/issues/33963
@@ -126,6 +124,9 @@
 vm/debug_break_vm_test/*: Skip
 vm/reflect_core_vm_test: CompileTimeError # Issue 33994
 vm/regress_27201_test: SkipByDesign # Loads bad library, so will always crash.
+vm/regression_32912_test/01: MissingCompileTimeError # Issue 32912
+vm/regression_32912_test/02: MissingCompileTimeError # Issue 32912
+vm/regression_32912_test/03: MissingCompileTimeError # Issue 32912
 void/return_future_future_or_void_async_error1_test/none: CompileTimeError # issue #34319
 void/return_future_or_future_or_void_sync_error2_test/none: CompileTimeError # issue #34319
 void/return_future_or_void_sync_error4_test/none: CompileTimeError # issue #34319
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index a99dd0f..a2102b3 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -46,6 +46,7 @@
 int64_literal_test/19: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 int64_literal_test/none: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
 issue23244_test: RuntimeError # Isolates - enum canonicalization - Issue 23244
+library_env_test/has_io_support: RuntimeError, OK # dart2js doesn't support io when compiling on --categories=Client
 library_env_test/has_mirror_support: RuntimeError, OK
 library_env_test/has_no_html_support: RuntimeError, OK
 list_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
@@ -59,6 +60,8 @@
 partial_tearoff_instantiation_test/07: Pass # for the wrong reason.
 partial_tearoff_instantiation_test/08: Pass # for the wrong reason.
 private_method_tearoff_test: RuntimeError
+set_literals/*: Skip
+type_constants_test/none: RuntimeError # Issue 35052
 vm/*: SkipByDesign # Tests for the VM.
 
 [ $compiler != dart2js ]
@@ -77,6 +80,8 @@
 override_field_test/02: Pass, Slow # TODO(kasperl): Please triage.
 
 [ $compiler == dart2js && $runtime == d8 ]
+conditional_import_string_test: SkipByDesign # No XHR in d8
+conditional_import_test: SkipByDesign # No XHR in d8
 implicit_creation/implicit_new_constructor_generic_test: Pass
 
 [ $compiler == dart2js && $runtime == d8 && !$checked ]
@@ -115,12 +120,6 @@
 [ $compiler == dart2js && $system == windows ]
 string_literals_test: Pass, RuntimeError # Failures on dart2js-win7-chrome-4-4-be and dart2js-win7-ie11ff-4-4-be
 
-[ $compiler == dart2js && $browser ]
-library_env_test/has_io_support: RuntimeError, OK # dart2js doesn't support io when compiling on --categories=Client
-
-[ $compiler == dart2js && !$browser ]
-library_env_test/has_no_io_support: RuntimeError, OK # dart2js supports io when using '--categories=all'.
-
 [ $compiler == dart2js && $checked ]
 covariant_subtyping_test: CompileTimeError
 
@@ -398,7 +397,6 @@
 covariant_subtyping_test: RuntimeError
 issue23244_test: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
 library_env_test/has_no_html_support: RuntimeError
-library_env_test/has_no_io_support: RuntimeError
 map_literal3_test/03: MissingCompileTimeError
 partial_tearoff_instantiation_test/05: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
 partial_tearoff_instantiation_test/06: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
@@ -591,8 +589,6 @@
 stacktrace_rethrow_error_test/none: RuntimeError # Issue 12698
 stacktrace_rethrow_error_test/withtraceparameter: RuntimeError # Issue 12698
 stacktrace_rethrow_nonerror_test: RuntimeError # Issue 12698
-string_split_test: CompileTimeError
-string_supertype_checked_test: CompileTimeError
 super_bound_closure_test/none: CompileTimeError
 super_call4_test/01: MissingCompileTimeError
 super_test: RuntimeError
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index ebdd2ea..feca149 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -25,14 +25,11 @@
 built_in_identifier_type_annotation_test/dynamic-list: RuntimeError # Issue 28816
 cascaded_forwarding_stubs_generic_test: RuntimeError
 cascaded_forwarding_stubs_test: CompileTimeError
-conflicting_generic_interfaces_hierarchy_loop_infinite_test: Skip # Crashes or times out
-conflicting_generic_interfaces_simple_test: MissingCompileTimeError
 const_cast2_test/01: CompileTimeError
 const_cast2_test/none: CompileTimeError
 const_constructor3_test/04: MissingCompileTimeError # Side-effect of working around issue 33441 for int-to-double
 const_constructor_mixin3_test/01: MissingCompileTimeError # Issue 33644
 const_constructor_mixin_test/01: MissingCompileTimeError # Issue 33644
-covariance_field_test/03: RuntimeError
 covariant_override/tear_off_type_test: RuntimeError # Issue 28395
 covariant_subtyping_with_mixin_test: CompileTimeError # Issue 34329
 deferred_load_library_wrong_args_test/01: MissingRuntimeError, RuntimeError # Issue 29920
@@ -101,6 +98,7 @@
 issue31596_test: CompileTimeError
 issue34498_test: MissingCompileTimeError # Issue 34500
 label_test: RuntimeError
+labeled_variable_declaration_test: RuntimeError
 large_class_declaration_test: Slow, Pass
 left_shift_test: RuntimeError # Ints and doubles are unified.
 mixin_declaration/mixin_declaration_factory_test/02: Crash
@@ -127,11 +125,10 @@
 regress_30121_test: CompileTimeError # Issue 31087
 regress_30339_test: CompileTimeError # As expected. Should we make this a multi test?
 regress_33479_test/01: Crash # Issue #33479
+set_literals/*: Skip
 setter3_test/01: CompileTimeError # Invalid test, see https://github.com/dart-lang/sdk/issues/33837
 setter3_test/02: CompileTimeError # Invalid test, see https://github.com/dart-lang/sdk/issues/33837
 stacktrace_test: RuntimeError # Issue 29920
-string_split_test: CompileTimeError
-string_supertype_checked_test: CompileTimeError
 super_bound_closure_test/none: CompileTimeError
 super_no_such_method1_test: CompileTimeError # Invalid test, probably, see https://github.com/dart-lang/sdk/issues/33963
 super_no_such_method2_test: CompileTimeError # Invalid test, probably, see https://github.com/dart-lang/sdk/issues/33963
@@ -231,7 +228,6 @@
 map_literal3_test/01: MissingCompileTimeError
 map_literal3_test/02: MissingCompileTimeError
 map_literal3_test/03: MissingCompileTimeError
-mixin_declaration/mixin_declaration_invalid_syntax_test/none: CompileTimeError
 mixin_declaration/mixin_declaration_subtype_test: RuntimeError
 mixin_illegal_super_use_test/01: MissingCompileTimeError
 mixin_illegal_super_use_test/04: MissingCompileTimeError
@@ -286,9 +282,8 @@
 regress_29405_test: CompileTimeError # Issue 31402 Error: A value of type '#lib2::Foo' can't be assigned to a variable of type '(#lib2::Foo) → void'.
 regress_30339_test: RuntimeError # Uncaught Expect.isTrue(false) fails.
 regress_30339_test: CompileTimeError
+set_literals/*: Skip
 setter_no_getter_test/01: CompileTimeError
-string_split_test: CompileTimeError # Issue 31616
-string_supertype_checked_test: CompileTimeError # Issue 31616
 super_bound_closure_test/none: CompileTimeError # Issue 31533
 super_call4_test/01: MissingCompileTimeError
 switch_bad_case_test/01: MissingCompileTimeError
@@ -346,8 +341,6 @@
 const_switch_test/02: RuntimeError # Issue 29920; Expect.equals(expected: <0>, actual: <0.0>) fails.
 const_switch_test/04: RuntimeError # Ints and doubles are unified.; Expect.equals(expected: <1>, actual: <1.0>) fails.
 constructor12_test: RuntimeError # Issue 29920; ReferenceError: JSArrayOfT is not defined
-covariance_field_test/04: RuntimeError
-covariance_field_test/05: RuntimeError
 ct_const_test: RuntimeError # Issue 2992; RangeError: Maximum call stack size exceeded
 custom_await_stack_trace_test: RuntimeError # Issue 29920; Uncaught Expect.equals(at index 0: Expected <Blah \x0ABloop\x0ABleep\x0A...>
 cyclic_type2_test: RuntimeError # Issue 29920; Uncaught ReferenceError: V is not defined
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 9bb75b0..cbbe9b5 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -130,8 +130,6 @@
 regress_29405_test: CompileTimeError
 regress_30339_test: CompileTimeError
 string_interpolation_and_buffer_test: RuntimeError
-string_split_test: CompileTimeError
-string_supertype_checked_test: CompileTimeError
 super_bound_closure_test/none: CompileTimeError
 super_test: RuntimeError
 type_alias_equality_test/03: RuntimeError # Issue 32783
@@ -171,8 +169,12 @@
 assertion_initializer_const_error2_test/cc08: MissingCompileTimeError
 assertion_initializer_const_error2_test/cc09: MissingCompileTimeError
 assertion_initializer_const_error2_test/cc10: MissingCompileTimeError
+async_await_syntax_test/e5: Crash # Assertion error: continuation.dart: Failed assertion: 'node.expression == null || node.expression is NullLiteral': is not true.
+async_await_syntax_test/e6: Crash # Assertion error: continuation.dart: Failed assertion: 'node.expression == null || node.expression is NullLiteral': is not true.
 const_cast1_test/02: MissingCompileTimeError
 const_constructor_nonconst_param_test/01: MissingCompileTimeError
+constructor5_test: CompileTimeError # Verification error
+constructor6_test: CompileTimeError # Verification error
 implicit_creation/implicit_const_not_default_values_test/e1: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e10: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e11: MissingCompileTimeError
@@ -193,10 +195,15 @@
 implicit_creation/implicit_const_not_default_values_test/e5: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e7: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e8: MissingCompileTimeError
+mixin_method_override_test/G4: Crash # Assertion error: mixin_full_resolution.dart': 'src.typeParameters.length == dst.typeParameters.length': is not true.
+set_literals/*: Skip
 vm/regress_33469_test/01: MissingCompileTimeError
 vm/regress_33469_test/02: MissingCompileTimeError
 vm/regress_33469_test/03: MissingCompileTimeError
 vm/regress_33469_test/04: MissingCompileTimeError
+vm/regression_32912_test/01: MissingCompileTimeError
+vm/regression_32912_test/02: MissingCompileTimeError
+vm/regression_32912_test/03: MissingCompileTimeError
 web_int_literals_test/*: SkipByDesign # Test applies only to JavaScript targets
 
 [ $fasta ]
@@ -234,6 +241,7 @@
 syntax_test/33: MissingCompileTimeError # Issue 29763 - low priority
 syntax_test/60: MissingCompileTimeError # Issue 30470
 syntax_test/61: MissingCompileTimeError # Issue 30470
+type_constants_test/04: MissingCompileTimeError # Issue 32557
 vm/debug_break_enabled_vm_test/01: CompileTimeError # KernelVM bug: Bad test using extended break syntax.
 vm/debug_break_enabled_vm_test/none: CompileTimeError # KernelVM bug: Bad test using extended break syntax.
 vm/regress_27201_test: CompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
@@ -316,6 +324,9 @@
 [ $compiler != dart2js && $compiler != dartdevk && $fasta ]
 const_native_factory_test: MissingCompileTimeError # Issue 29763
 
+[ $compiler != dart2js && $fasta ]
+type_constants_test/01: MissingCompileTimeError # Issue 32557
+
 [ $compiler == dartk && $runtime == vm && !$checked && $strong ]
 assertion_initializer_const_error2_test/cc01: MissingCompileTimeError # Not reporting failed assert() at compile time.
 assertion_initializer_const_error2_test/cc02: MissingCompileTimeError # Not reporting failed assert() at compile time.
@@ -336,11 +347,13 @@
 const_dynamic_type_literal_test/02: Pass
 map_literal3_test/01: Pass
 map_literal3_test/02: Pass
-vm/bool_check_stack_traces_test/01: RuntimeError # No support for line numbers in stacktraces
-vm/bool_check_stack_traces_test/none: RuntimeError # No support for line numbers in stacktraces
-vm/causal_async_exception_stack2_test: RuntimeError # No support for line numbers in stacktraces
-vm/causal_async_exception_stack_test: RuntimeError # No support for line numbers in stacktraces
-vm/regress_28325_test: RuntimeError # No support for line numbers in stacktraces
+vm/bool_check_stack_traces_test/02: Pass
+vm/causal_async_exception_stack2_test: RuntimeError # Please triage
+vm/causal_async_exception_stack_test: RuntimeError # Please triage
+
+[ $compiler != dartkb && $compiler != dartkp && $fasta ]
+vm/symbols_test/01: MissingCompileTimeError
+vm/symbols_test/03: MissingCompileTimeError
 
 [ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled && $strong ]
 external_test/13: Crash
@@ -597,8 +610,6 @@
 setter_no_getter_test/01: Pass, CompileTimeError # Issue 31533 (started passing after switching to batch-mode)
 stacktrace_demangle_ctors_test: RuntimeError
 string_interpolation_and_buffer_test: RuntimeError # Issue 31402 (Return and yield statements)
-string_split_test: CompileTimeError # Issue 31616
-string_supertype_checked_test: CompileTimeError # Issue 31616
 super_bound_closure_test/none: CompileTimeError # Issue 31533
 super_test: Fail, OK
 syntax_test/00: MissingCompileTimeError
@@ -721,8 +732,6 @@
 regress_29405_test: CompileTimeError
 regress_30339_test: CompileTimeError
 setter_no_getter_test/01: CompileTimeError
-string_split_test: CompileTimeError
-string_supertype_checked_test: CompileTimeError
 super_bound_closure_test/none: CompileTimeError
 try_catch_test/01: MissingCompileTimeError
 type_promotion_functions_test/02: CompileTimeError
@@ -985,7 +994,7 @@
 [ $mode == debug && ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
 enum_duplicate_test/02: Crash # Issue 34606
 enum_duplicate_test/none: Pass, Crash # Issue 34606
-enum_private_test/01: Crash # Issue 34606
+enum_private_test/01: Pass, Crash # Issue 34606
 enum_test: Crash # Issue 34606
 
 [ $mode == product && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
@@ -1065,7 +1074,7 @@
 deferred_not_loaded_check_test: RuntimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
 deferred_redirecting_factory_test: RuntimeError # KernelVM bug: Deferred loading kernel issue 30273.
 deferred_static_seperate_test: RuntimeError # KernelVM bug: Deferred loading kernel issue 30273.
-disassemble_test: Pass, Slow
+disassemble_test: Pass, Slow, Crash # dartbug.com/34971
 dynamic_prefix_core_test/none: CompileTimeError
 emit_const_fields_test: CompileTimeError # Issue 31533
 example_constructor_test: Fail, OK
@@ -1124,8 +1133,6 @@
 regress_29405_test: CompileTimeError # Issue 31402 (Invocation arguments)
 regress_30339_test: CompileTimeError # Issue 31402 (Variable declaration)
 string_interpolation_and_buffer_test: RuntimeError # Issue 31402 (Return and yield statements)
-string_split_test: CompileTimeError # Issue 31616
-string_supertype_checked_test: CompileTimeError # Issue 31616
 super_bound_closure_test/none: CompileTimeError # Issue 31533
 super_call4_test/01: MissingCompileTimeError
 super_test: Fail, OK
@@ -1980,6 +1987,11 @@
 async_star_test/04: Skip # Timeout
 async_star_test/05: Skip # Timeout
 async_star_test/none: Skip # Timeout
+type_constants_test/none: Skip # Deferred libraries and hot reload.
 
 [ $compiler == dartk || $compiler == dartkb || $compiler == dartkp ]
 generic_function_bounds_test: RuntimeError # Issue 32076
+
+[ $compiler == dartkb || $compiler == dartkp ]
+mock_writable_final_private_field_test: CompileTimeError # Test uses Symbol("_...") which is a compile-time error.
+vm/reflect_core_vm_test: CompileTimeError # Test uses Symbol("_...") which is a compile-time error.
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index 8bcfb7a4c..b696b0f 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -15,6 +15,10 @@
 assertion_initializer_const_error2_test/cc09: MissingCompileTimeError # Not reporting failed assert() at compile time.
 assertion_initializer_const_error2_test/cc10: MissingCompileTimeError # Not reporting failed assert() at compile time.
 assertion_initializer_const_error2_test/cc11: MissingCompileTimeError # Not reporting failed assert() at compile time.
+set_literals/*: Skip
+
+[ $runtime == vm ]
+set_literals/*: Skip
 
 [ $arch == arm64 && $runtime == vm ]
 closure_cycles_test: Pass, Slow
diff --git a/tests/language_2/set_literals/const_set_literal_test.dart b/tests/language_2/set_literals/const_set_literal_test.dart
new file mode 100644
index 0000000..4dc9eb0
--- /dev/null
+++ b/tests/language_2/set_literals/const_set_literal_test.dart
@@ -0,0 +1,127 @@
+// 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.
+
+// SharedOptions=--enable-experiment=set-literals
+
+import "package:expect/expect.dart";
+
+void main() {
+  test();
+}
+
+void test<S extends Set<num>, I extends Iterable<num>>() {
+  checkSet<T>(Object o, List elements) {
+    Expect.type<Set<T>>(o);
+    Set<T> set = o;
+    Expect.listEquals(elements, set.toList());
+    Expect.throws<Error>(set.clear);
+  }
+
+  // Various context types for literals.
+  Object setContext<T>(Set<T> object) => object;
+  Object iterableContext<T>(Iterable<T> object) => object;
+  Object foSetContext<T>(FutureOr<Set<T>> object) => object;
+  Object foIterableContext<T>(FutureOr<Set<T>> object) => object;
+  Object sContext(S object) => object;
+  Object iContext(I object) => object;
+
+  // Empty literal, no type arguments.
+  // No context.
+  Expect.type<Map<dynamic, dynamic>>(const {});
+  // Set context with no inferred type argument.
+  checkSet<dynamic>(setContext(const {}), []);
+  checkSet<dynamic>(iterableContext(const {}), []);
+  checkSet<dynamic>(foSetContext(const {}), []);
+  checkSet<dynamic>(foIterableContext(const {}), []);
+  // Specific set context.
+  checkSet<int>(setContext<int>(const {}), []);
+  checkSet<int>(iterableContext<int>(const {}), []);
+  checkSet<int>(foSetContext<int>(const {}), []);
+  checkSet<int>(foIterableContext<int>(const {}), []);
+  checkSet<num>(sContext(const {}), []);
+  checkSet<num>(iContext(const {}), []);
+
+  // Non-empty set literal, no type argument.
+  // No context.
+  checkSet<int>(const {1}, [1]);
+  checkSet<int>(const {3, 1, 2, 4, 1, 4}, [3, 1, 2, 4]);
+  // Set context with no inferred type argument.
+  checkSet<int>(setContext(const {1}), [1]);
+  checkSet<int>(iterableContext(const {1}), [1]);
+  checkSet<int>(foSetContext(const {1}), [1]);
+  checkSet<int>(foIterableContext(const {1}), [1]);
+  checkSet<int>(setContext(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<int>(iterableContext(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<int>(foSetContext(const {1}), [1]);
+  checkSet<int>(foIterableContext(const {1}), [1]);
+  // Specific set context.
+  checkSet<num>(setContext<num>(const {1}), [1]);
+  checkSet<num>(sContext(const {1}), [1]);
+  checkSet<num>(iterableContext<num>(const {1}), [1]);
+  checkSet<num>(iContext(const {1}), [1]);
+  checkSet<num>(foSetContext<num>(const {1}), [1]);
+  checkSet<num>(foIterableContext<num>(const {1}), [1]);
+  checkSet<num>(setContext<num>(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<num>(sContext(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<num>(iterableContext<num>(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<num>(iContext(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<num>(foSetContext<num>(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<num>(foIterableContext<num>(const {3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+
+  // Non-empty set literal with type argument.
+  checkSet<num>(const <num>{1}, [1]);
+  checkSet<num>(const <num>{3, 1, 2, 4, 1, 4}, [3, 1, 2, 4]);
+
+  // Integers, String and symbols work, even if they override ==.
+  checkSet<String>(const {"foo", "bar", "foo"}, ["foo", "bar"]);
+  checkSet<Symbol>(const {#foo, #bar, #foo}, [#foo, #bar]);
+  checkSet<Symbol>(const {#_foo, #_bar, #_foo}, [#_foo, #_bar]);
+  const object = Object();
+  checkSet<Object>(const {#foo, 1, "string", object, true},
+      [#foo, 1, "string", object, true]);
+
+  // Nested constant literals.
+  const Object o = {{2}};
+  Expect.type<Set<Set<int>>>(o);
+  Set<Set<int>> set = o;
+  Expect.equals(1, set.length);
+  Expect.equals(1, set.first.length);
+  Expect.equals(2, set.first.first);
+
+  const Object o2 = {{2}, <int>{}};
+  Expect.type<Set<Set<int>>>(o);
+  set = o2;
+  Expect.equals(2, set.length);
+  Expect.equals(1, set.first.length);
+  Expect.equals(2, set.first.first);
+
+  const Set<Set<int>> o3 = {{}};
+  Expect.equals(1, o3.length);
+  Expect.equals(0, o3.first.length);
+
+  const o4 = {{}};
+  Expect.type<Set<Map<dynamic, dynamic>>>(o4);
+  Expect.equals(1, o4.length);
+  Expect.equals(0, o4.first.length);
+
+  const o5 = {{1}, {}};  // Set<Object>
+  Expect.type<Set<Object>>(o5);
+  Expect.notType<Set<Set<Object>>>(o5);
+
+  // Adding an equal element later does nothing.
+  const o6 = {
+    Something(1, "a"),
+    Something(2, "a"),
+    Something(1, "b"),
+    Something(2, "b"),
+  };
+  Expect.equals("1:a,2:a", o6.toList().join(","));
+}
+
+class Something {
+  final int id;
+  final String name;
+  const Something(this.id, this.name);
+  String toString() => "$id:$name";
+}
diff --git a/tests/language_2/set_literals/invalid_set_literal_test.dart b/tests/language_2/set_literals/invalid_set_literal_test.dart
new file mode 100644
index 0000000..edce343
--- /dev/null
+++ b/tests/language_2/set_literals/invalid_set_literal_test.dart
@@ -0,0 +1,70 @@
+// 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.
+
+// SharedOptions=--enable-experiment=set-literals
+
+import "dart:collection" show LinkedHashSet;
+
+import "package:expect/expect.dart";
+
+const Object d = 3.5;
+
+void main()  var o //
+      = <int>{1: 1} //# 01: compile-time error
+      = <int, int, int>{} //# 02: compile-time error
+      = <int, int, int>{1} //# 03: compile-time error
+      = <int, int>{1} //# 04: compile-time error
+      = const <int, int, int>{} //# 05: compile-time error
+      = const <int, int, int>{1} //# 06: compile-time error
+      = const <int, int>{1} //# 07: compile-time error
+      = const {Duration(seconds: 0)} // Overrides ==. //# 08: compile-time error
+      = {4.2} // Overrides ==. //# 09: compile-time error
+      = {d} // Overrides ==. //# 10: compile-time error
+      = {,} //# 11: compile-time error
+      = {1,,} //# 12: compile-time error
+      = {1,,1} //# 13: compile-time error
+      ;
+  Expect.isNull(o); // Should be unreachable with a value.
+
+  Set<int> s //
+      = {"not int"} //# 14: compile-time error
+      = {4.2} //# 15: compile-time error
+      = {1: 1} //# 16: compile-time error
+      = {{}} //# 17: compile-time error
+      = <Object>{} // Exact type. //# 18: compile-time error
+      ;
+  Expect.isNull(s);
+
+  Set<Set<Object>> ss //
+      = {{1: 1}} //# 19: compile-time error
+      = {<int, int>{}} //# 20: compile-time error
+      = {<int>{1: 1}} //# 21: compile-time error
+      = const {ss} //# 22: compile-time error
+      ;
+  Expect.isNull(ss);
+
+  HashSet<int> hs //
+      = {} // Exact type is LinkedHashSet //# 23: compile-time error
+      ;
+  Expect.isNull(hs);
+
+  LinkedHashSet<int> lhs //
+      = const {} // exact type is Set //# 24: compile-time error
+      ;
+  Expect.isNull(lhs);
+
+  LinkedHashSet<LinkedHashSet<int>> lhs2 //
+      = {const {}} // exact type LHS<Set>. //# 25: compile-time error
+      ;
+  Expect.isNull(lhs2);
+
+  <T>(x) {
+    // Type constants are allowed, type variables are not.
+    var o //
+        = const {T} //# 26: compile-time error
+        = const {x} //# 27: compile-time error
+        ;
+    Expect.isNull(o);
+  }<int>(42);
+}
diff --git a/tests/language_2/set_literals/set_literal_test.dart b/tests/language_2/set_literals/set_literal_test.dart
new file mode 100644
index 0000000..03e9b0b
--- /dev/null
+++ b/tests/language_2/set_literals/set_literal_test.dart
@@ -0,0 +1,137 @@
+// 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.
+
+// SharedOptions=--enable-experiment=set-literals
+
+import "dart:collection" show LinkedHashSet;
+
+import "package:expect/expect.dart";
+
+void main() {
+  test();
+}
+
+void test<S extends Set<num>, I extends Iterable<num>>() {
+  checkSet<T>(Object o, List elements) {
+    Expect.type<LinkedHashSet<T>>(o);
+    Set<T> set = o;
+    Expect.listEquals(elements, set.toList());
+  }
+
+  Object setContext<T>(Set<T> object) => object;
+  Object iterableContext<T>(Iterable<T> object) => object;
+  Object foSetContext<T>(FutureOr<Set<T>> object) => object;
+  cbject foIterableContext<T>(FutureOr<Iterable<T>> object) => object;
+  Object sContext(S object) => object;
+  Object iContext(I object) => object;
+
+  // Empty literal, no type arguments.
+  // No context.
+  Expect.type<Map<dynamic, dynamic>>({});
+  // Set context with no inferred type argument.
+  checkSet<dynamic>(setContext({}), []);
+  checkSet<dynamic>(iterableContext({}), []);
+  checkSet<dynamic>(foSetContext({}), []);
+  checkSet<dynamic>(foIterableContext({}), []);
+  // Specific set context.
+  checkSet<int>(setContext<int>({}), []);
+  checkSet<int>(iterableContext<int>({}), []);
+  checkSet<int>(foSetContext<int>({}), []);
+  checkSet<int>(foIterableContext<int>({}), []);
+  checkSet<num>(sContext({}), []);
+  checkSet<num>(iContext({}), []);
+
+  // Non-empty set literal, no type argument.
+  // No context.
+  checkSet<int>({1}, [1]);
+  checkSet<int>({3, 1, 2, 4, 1, 4}, [3, 1, 2, 4]);
+  // Set context with no inferred type argument.
+  checkSet<int>(setContext({1}), [1]);
+  checkSet<int>(iterableContext({1}), [1]);
+  checkSet<int>(foSetContext({1}), [1]);
+  checkSet<int>(foIterableContext({1}), [1]);
+  checkSet<int>(setContext({3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<int>(iterableContext({3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<int>(foSetContext({3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<int>(foIterableContext({3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  // Specific set context.
+  checkSet<num>(setContext<num>({1}), [1]);
+  checkSet<num>(iterableContext<num>({1}), [1]);
+  checkSet<num>(foSetContext<num>({1}), [1]);
+  checkSet<num>(foIterableContext<num>({1}), [1]);
+  checkSet<num>(sContext({1}), [1]);
+  checkSet<num>(iContext({1}), [1]);
+  checkSet<num>(setContext<num>({3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<num>(iterableContext<num>({3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<num>(foSetContext<num>({3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<num>(foIterableContext<num>({3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<num>(sContext({3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+  checkSet<num>(iContext({3, 1, 2, 4, 1, 4}), [3, 1, 2, 4]);
+
+  // Non-empty set literal with type argument.
+  checkSet<num>(<num>{1}, [1]);
+  checkSet<num>(<num>{3, 1, 2, 4, 1, 4}, [3, 1, 2, 4]);
+
+  // Iteration order. Values are evaluated in first-added order.
+  var e1a = Equality(1, "a");
+  var e1b = Equality(1, "b");
+  var e2a = Equality(2, "a");
+  var e2b = Equality(2, "b");
+  var es = {e1a, e2b, e1b, e2a};
+  checkSet<Equality>(es, [e1a, e2b]);
+  Expect.equals("1:a,2:b", es.join(","));
+
+  // Evaluation order. All elements are evaluated, left to right.
+  var entries = <int>[];
+  T log<T>(T value, int entry) {
+    entries.add(entry);
+    return value;
+  }
+  checkSet<Equality>(
+      {log(e1a, 1), log(e2b, 2), log(e1b, 3), log(e2a, 4)}, [e1a, e2b]);
+  Expect.listEquals([1, 2, 3, 4], entries);
+
+  // Nested literals.
+  Object o = {{2}};
+  Expect.type<LinkedHashSet<LinkedHashSet<int>>>(o);
+  Set<Set<int>> set = o;
+  Expect.equals(1, set.length);
+  Expect.equals(1, set.first.length);
+  Expect.equals(2, set.first.first);
+
+  o = {{2}, <int>{}};
+  Expect.type<LinkedHashSet<LinkedHashSet<int>>>(o);
+  set = o;
+  Expect.equals(2, set.length);
+  Expect.equals(1, set.first.length);
+  Expect.equals(2, set.first.first);
+
+  set = {{}};
+  Expect.type<Set<Map<dynamic, dynamic>>>(set);
+  Expect.equals(1, set.length);
+  Expect.equals(0, set.first.length);
+
+  set = {{1}, {}};  // Set<Object>
+  Expect.type<Set<Object>>(x);
+  Expect.notType<Set<Set<Object>>>(x);
+
+  // Trailing comma.
+  Iterable<Object> i;
+  i = {1,};
+  Expect.type<Set<Object>>(i);
+  Expect.equals(1, i.length);
+
+  o = {1, 2, 3,};
+  Expect.type<Set<int>>(o);
+  Expect.equals(3, o.length);
+}
+
+class Equality {
+  final int id;
+  final String name;
+  const Equality(this.id, this.name);
+  int get hashCode => id;
+  bool operator==(Object other) => other is Equality && id = other.id;
+  String toString() => "$id:$name";
+}
diff --git a/tests/language_2/string_split_test.dart b/tests/language_2/string_split_test.dart
index 0cd4652..2517237 100644
--- a/tests/language_2/string_split_test.dart
+++ b/tests/language_2/string_split_test.dart
@@ -11,17 +11,17 @@
   bool noSuchMethod(Invocation im) => false; // To appease dartanalyzer.
 }
 
-class EvilIterator implements Iterator {
+class EvilIterator implements Iterator<Match> {
   bool moveNext() => true;
   EvilMatch get current => new EvilMatch();
 }
 
-class EvilIterable extends Iterable {
-  Iterator get iterator => new EvilIterator();
+class EvilIterable extends Iterable<Match> {
+  get iterator => new EvilIterator();
 }
 
 class EvilPattern implements Pattern {
-  Iterable allMatches(String s, [int start = 0]) => new EvilIterable();
+  allMatches(String s, [int start = 0]) => new EvilIterable();
   bool noSuchMethod(Invocation im) => false; // To appease dartanalyzer.
 }
 
diff --git a/tests/language_2/string_supertype_checked_test.dart b/tests/language_2/string_supertype_checked_test.dart
index 75a2a6b..016c757 100644
--- a/tests/language_2/string_supertype_checked_test.dart
+++ b/tests/language_2/string_supertype_checked_test.dart
@@ -7,12 +7,12 @@
 // This tests a bug in dart2js which caused the compiler to emit bad
 // type assertions for supertypes of String.
 
-class A implements Comparable {
+class A implements Comparable<A> {
   int value;
 
   A(this.value);
 
-  int compareTo(Comparable other) {
+  int compareTo(Object other) {
     A o = promote(other);
     return value.compareTo(o.value);
   }
diff --git a/tests/language_2/type_constants_test.dart b/tests/language_2/type_constants_test.dart
new file mode 100644
index 0000000..560e485
--- /dev/null
+++ b/tests/language_2/type_constants_test.dart
@@ -0,0 +1,82 @@
+// 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.
+
+// Test that the value of constant type literals are allowed as
+// constant map keys and case expressions, and the value of non-constant type
+// literals are not.
+
+import "dart:collection" deferred as prefix;
+
+main(args) {
+  testSwitch(args);
+  testMaps(args);
+}
+
+const Type numType = num;
+
+Type argumentType<T>() => T;
+
+void testSwitch<T extends MyType>(args) {
+  var types = [MyType, T, argumentType<MyType>(), argumentType<T>()];
+  for (int i = 0; i < types.length; i++) {
+    switch (types[i]) {
+      // Must be type literal or not override `==`.
+      case const MyType(): //# 01: compile-time error
+
+      // Must not be type variable.
+      case T: //# 02: compile-time error
+
+      // Must not be deferred type.
+      case prefix.HashSet: //# 03: compile-time error
+
+      // Constant type literals are valid.
+      case String:
+        throw "unreachable: String #$i";
+      case int:
+        throw "unreachable: int #$i";
+      case numType:
+        throw "unreachable: num #$i";
+      case MyType:
+        break;
+      default:
+        throw "unreachable: default #$i";
+    }
+  }
+}
+
+void testMaps<T extends MyType>(args) {
+  const map = {
+    // Must be type literal or not override `==`.
+    MyType(): 0, //# 04: compile-time error
+
+    // Must not be type variable.
+    T: 0, //# 05: compile-time error
+
+    // Must not be deferred.
+    prefix.HashSet: 0, //# 06: compile-time error
+
+    // Constant type literals are valid.
+    MyType: 0,
+    int: 1,
+    String: 2,
+    numType: 3,
+  };
+  if (map[MyType] != 0) throw "Map Error: ${MyType} as literal";
+  if (map[T] != 0) throw "Map Error: ${T} as type argument";
+  if (map[argumentType<MyType>()] != 0) {
+    throw "Map Error: ${argumentType<MyType>()} as type argument of literal";
+  }
+  if (map[argumentType<T>()] != 0) {
+    throw "Map Error: ${argumentType<T>()} as type argument of type variable";
+  }
+  if (map[num] != 3) throw "Map Error: ${num} -> ${map[num]}";
+}
+
+// An implementation of `Type` which overrides `==`,
+// but is not the value of a constant type literal.
+class MyType implements Type {
+  const MyType();
+  int get hashCode => 0;
+  bool operator ==(Object other) => identical(this, other);
+}
diff --git a/tests/language_2/vm/regression_32912_test.dart b/tests/language_2/vm/regression_32912_test.dart
new file mode 100644
index 0000000..2a63ff6
--- /dev/null
+++ b/tests/language_2/vm/regression_32912_test.dart
@@ -0,0 +1,23 @@
+// 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.
+
+dynamic _defaultCallback<T>(T t) => t;
+
+void bar<T>([dynamic Function(T) f = _defaultCallback]) {}  //# 01: compile-time error
+
+class C<T> {
+  // Should be statically rejected
+  foo([dynamic Function(T) f = _defaultCallback]) {}  //# 02: compile-time error
+
+  // Should be statically rejected
+  const C({this.callback = _defaultCallback});  //# 03: compile-time error
+
+  final dynamic Function(T) callback;  //# 03: continued
+}
+
+void main() {
+  bar<int>();                    //# 01: continued
+  print(new C<int>().foo());     //# 02: continued
+  print(new C<int>().callback);  //# 03: continued
+}
diff --git a/tests/language_2/vm/symbols_test.dart b/tests/language_2/vm/symbols_test.dart
new file mode 100644
index 0000000..15f9ed1
--- /dev/null
+++ b/tests/language_2/vm/symbols_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+void main() {
+  print(const Symbol(null));                                /// 01: compile-time error
+  print(const Symbol(r''));                                 /// 02: ok
+  Expect.isTrue(identical(const Symbol(r'foo'), #foo));     /// 03: ok
+  Expect.isTrue(identical(const Symbol(r'$foo'), #$foo));   /// 03: ok
+  Expect.isTrue(identical(const Symbol(r'$_'), #$_));       /// 03: ok
+  Expect.isTrue(identical(const Symbol(r'+'), #+));         /// 03: ok
+  Expect.isTrue(identical(const Symbol(r'[]='), #[]=));     /// 03: ok
+  Expect.isTrue(identical(const Symbol(r'_foo'), #_foo));   /// 03: compile-time error
+  Expect.isTrue(identical(const Symbol(r'_$'), #_$));       /// 03: compile-time error
+  Expect.isTrue(identical(const Symbol(r'_foo$'), #_foo$)); /// 03: compile-time error
+  print(const Symbol(r'_+'));                               /// 03: compile-time error
+}
diff --git a/tests/lib_2/mirrors/bad_argument_types_test.dart b/tests/lib_2/mirrors/bad_argument_types_test.dart
new file mode 100644
index 0000000..8063803
--- /dev/null
+++ b/tests/lib_2/mirrors/bad_argument_types_test.dart
@@ -0,0 +1,157 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+int foobar = 1;
+
+set foobaz(int x) {
+  foobar = x;
+}
+
+void foo(Map<String, String> m) {
+  print(m);
+  print(m['bar']);
+}
+
+void bar<T extends num>(T a) {
+  print(a);
+}
+
+class Foo {
+  Map<String, String> bork;
+  static Map<String, String> bark;
+  static set woof(Map<String, String> x) {
+    bark = x;
+  }
+
+  Foo(Map<String, String> m) {
+    print(m);
+  }
+
+  Foo.a();
+
+  static void baz(Map<String, String> m, {String bar}) {
+    print('baz');
+    print(m['bar']);
+    print(bar);
+  }
+
+  void bar(Map<String, String> m) {
+    print('bar');
+    print(m.runtimeType);
+  }
+}
+
+class FooBar<T extends num> {
+  T bar;
+  FooBar(this.bar) {
+    print(bar);
+  }
+
+  set barz(T x) {
+    bar = x;
+  }
+
+  factory FooBar.baz(T bar) {
+    print(bar);
+    return FooBar(bar);
+  }
+
+  void foobar<S>(T a, S b) {
+    print(a);
+    print(b);
+  }
+}
+
+void badClassStaticInvoke() {
+  Map<String, String> map = Map<String, String>();
+  map['bar'] = 'Hello world!';
+  final cm = reflectClass(Foo);
+  Expect.throwsTypeError(() => cm.invoke(#baz, [
+        map
+      ], {
+        #bar: {'boo': 'bah'}
+      }));
+}
+
+void badStaticInvoke() {
+  final ClosureMirror im = reflect(foo);
+  Expect.throwsTypeError(() => im.apply(['Hello world!']));
+}
+
+void badInstanceInvoke() {
+  final fooCls = Foo.a();
+  final im = reflect(fooCls);
+  Expect.throwsTypeError(() => im.invoke(#bar, ['Hello World!']));
+}
+
+void badConstructorInvoke() {
+  final cm = reflectClass(Foo);
+  Expect.throwsTypeError(() => cm.newInstance(Symbol(''), ['Hello World!']));
+}
+
+void badSetterInvoke() {
+  final fooCls = Foo.a();
+  final im = reflect(fooCls);
+  Expect.throwsTypeError(() => im.setField(#bork, 'Hello World!'));
+}
+
+void badStaticSetterInvoke() {
+  final cm = reflectClass(Foo);
+  Expect.throwsTypeError(() => cm.setField(#bark, 'Hello World!'));
+  Expect.throwsTypeError(() => cm.setField(#woof, 'Hello World!'));
+}
+
+void badGenericConstructorInvoke() {
+  final cm = reflectType(FooBar, [int]) as ClassMirror;
+  Expect.throwsTypeError(() => cm.newInstance(Symbol(''), ['Hello World!']));
+}
+
+void badGenericClassStaticInvoke() {
+  final cm = reflectType(FooBar, [int]) as ClassMirror;
+  final im = cm.newInstance(Symbol(''), [1]);
+  Expect.throwsTypeError(() => im.invoke(#foobar, ['Hello', 'World']));
+}
+
+void badGenericFactoryInvoke() {
+  final cm = reflectType(FooBar, [int]) as ClassMirror;
+  Expect.throwsTypeError(() => cm.newInstance(Symbol('baz'), ['Hello World!']));
+}
+
+void badGenericStaticInvoke() {
+  final ClosureMirror im = reflect(bar);
+  Expect.throwsTypeError(() => im.apply(['Hello world!']));
+}
+
+void badGenericSetterInvoke() {
+  final cm = reflectType(FooBar, [int]) as ClassMirror;
+  final im = cm.newInstance(Symbol(''), [0]);
+  Expect.throwsTypeError(() => im.setField(#bar, 'Hello world!'));
+  Expect.throwsTypeError(() => im.setField(#barz, 'Hello world!'));
+}
+
+void badLibrarySetterInvoke() {
+  final lm = currentMirrorSystem().findLibrary(Symbol(''));
+  Expect.throwsTypeError(() => lm.setField(#foobar, 'Foobaz'));
+  Expect.throwsTypeError(() => lm.setField(#foobaz, 'Foobaz'));
+}
+
+void main() {
+  badClassStaticInvoke();
+  badStaticInvoke();
+  badInstanceInvoke();
+  badConstructorInvoke();
+  badSetterInvoke();
+  badStaticSetterInvoke();
+  badGenericConstructorInvoke();
+  badGenericClassStaticInvoke();
+  badGenericFactoryInvoke();
+  badGenericStaticInvoke();
+  badGenericSetterInvoke();
+  badLibrarySetterInvoke();
+}
diff --git a/tests/standalone_2/fragmentation_test.dart b/tests/standalone_2/fragmentation_test.dart
index 27d7497..19d1d95 100644
--- a/tests/standalone_2/fragmentation_test.dart
+++ b/tests/standalone_2/fragmentation_test.dart
@@ -10,9 +10,12 @@
 // This test is deliberately CPU-light and so it can make a lot of
 // progress before the concurrent sweepers are done sweeping the heap.
 // In that time there is no freelist and so the issue does not arise.
-// VMOptions=--no_concurrent_sweep
-// VMOptions=--use_compactor_evacuating
-// VMOptions=--use_compactor_sliding
+// VMOptions=--no_concurrent_mark --no_concurrent_sweep
+// VMOptions=--no_concurrent_mark --concurrent_sweep
+// VMOptions=--no_concurrent_mark --use_compactor
+// VMOptions=--concurrent_mark --no_concurrent_sweep
+// VMOptions=--concurrent_mark --concurrent_sweep
+// VMOptions=--concurrent_mark --use_compactor
 
 main() {
   final List<List> arrays = [];
diff --git a/tests/standalone_2/io/dart_std_io_pipe_test.dart b/tests/standalone_2/io/dart_std_io_pipe_test.dart
index f897c2e..474e5a8 100644
--- a/tests/standalone_2/io/dart_std_io_pipe_test.dart
+++ b/tests/standalone_2/io/dart_std_io_pipe_test.dart
@@ -118,10 +118,10 @@
   }
 
   // Run the shell script.
-  test(shellScript.path, scriptFile.path, "0", false);
-  test(shellScript.path, scriptFile.path, "0", true);
-  test(shellScript.path, scriptFile.path, "1", false);
-  test(shellScript.path, scriptFile.path, "1", true);
-  test(shellScript.path, scriptFile.path, "2", false);
-  test(shellScript.path, scriptFile.path, "2", true);
+  test(shellScript.path, scriptFile.path, "0", false); //# 01: ok
+  test(shellScript.path, scriptFile.path, "0", true); //# 02: ok
+  test(shellScript.path, scriptFile.path, "1", false); //# 03: ok
+  test(shellScript.path, scriptFile.path, "1", true); //# 04: ok
+  test(shellScript.path, scriptFile.path, "2", false); //# 05: ok
+  test(shellScript.path, scriptFile.path, "2", true); //# 06: ok
 }
diff --git a/tests/standalone_2/io/file_lock_test.dart b/tests/standalone_2/io/file_lock_test.dart
index 413288c..f117223 100644
--- a/tests/standalone_2/io/file_lock_test.dart
+++ b/tests/standalone_2/io/file_lock_test.dart
@@ -22,6 +22,7 @@
     ..add(mode == FileLock.exclusive ? 'EXCLUSIVE' : 'SHARED')
     ..add('$start')
     ..add('$end');
+  var stacktrace = StackTrace.current;
   return Process
       .run(Platform.executable, arguments)
       .then((ProcessResult result) {
@@ -33,6 +34,8 @@
       print(result.stderr);
       print("  arguments:");
       print(arguments);
+      print("  call stack:");
+      print(stacktrace);
       Expect.fail('Client subprocess exit code: ${result.exitCode}');
     }
   });
diff --git a/tests/standalone_2/io/http_client_stays_alive_test.dart b/tests/standalone_2/io/http_client_stays_alive_test.dart
index efc9c43..8666bb8 100644
--- a/tests/standalone_2/io/http_client_stays_alive_test.dart
+++ b/tests/standalone_2/io/http_client_stays_alive_test.dart
@@ -18,6 +18,7 @@
 // within +/- 2 <= seconds.
 
 const SECONDS = 4;
+const SLACK = 60;
 
 List<String> packageOptions() {
   if (Platform.packageRoot != null) {
@@ -57,9 +58,9 @@
       // NOTE: There is a slight chance this will cause flakiness, but there is
       // no other good way of testing correctness of timing-dependent code
       // form the outside.
-      if (seconds < SECONDS || (SECONDS + 30) < seconds) {
+      if (seconds < SECONDS || (SECONDS + SLACK) < seconds) {
         throw "Child did exit within $seconds seconds, but expected it to take "
-            "roughly $SECONDS seconds.";
+            "roughly between $SECONDS and ${SECONDS + SLACK} seconds.";
       }
 
       asyncEnd();
diff --git a/tests/standalone_2/io/http_loopback_test.dart b/tests/standalone_2/io/http_loopback_test.dart
index 11e2b16..f2b9db6 100644
--- a/tests/standalone_2/io/http_loopback_test.dart
+++ b/tests/standalone_2/io/http_loopback_test.dart
@@ -19,18 +19,16 @@
 IPv4ToIPv6FailureTest() async {
   server = await RawServerSocket.bind(InternetAddress.loopbackIPv6, 0);
   server.listen(serverListen);
-  bool testFailure = false;
   try {
     client = await RawSocket.connect(InternetAddress.loopbackIPv4, server.port);
     await client.close();
-    testFailure = true;
+    Expect.fail('Unexpected connection to IPv6 server!');
   } on SocketException catch (e) {
     // We shouldn't be able to connect to the IPv6 loopback adapter using the
     // IPv4 loopback address.
   } catch (e) {
-    testFailure = true;
+    Expect.fail('Unexpected exception: $e');
   } finally {
-    Expect.equals(testFailure, false);
     await server.close();
   }
 }
@@ -38,18 +36,16 @@
 IPv6ToIPv4FailureTest() async {
   server = await RawServerSocket.bind(InternetAddress.loopbackIPv4, 0);
   server.listen(serverListen);
-  bool testFailure = false;
   try {
     client = await RawSocket.connect(InternetAddress.loopbackIPv6, server.port);
     await client.close();
-    testFailure = true;
+    Expect.fail('Unexpected connection to IPv4 server!');
   } on SocketException catch (e) {
     // We shouldn't be able to connect to the IPv4 loopback adapter using the
     // IPv6 loopback address.
   } catch (e) {
-    testFailure = true;
+    Expect.fail('Unexpected exception: $e');
   } finally {
-    Expect.equals(testFailure, false);
     await server.close();
   }
 }
diff --git a/tests/standalone_2/io/process_detached_test.dart b/tests/standalone_2/io/process_detached_test.dart
index 55aeb06..ee093b3 100644
--- a/tests/standalone_2/io/process_detached_test.dart
+++ b/tests/standalone_2/io/process_detached_test.dart
@@ -48,7 +48,7 @@
     process.stdin.flush().then((_) => process.stdin.close());
     var f1 = process.stdout.fold([], (p, e) => p..addAll(e));
     var f2 = process.stderr.fold([], (p, e) => p..addAll(e));
-    Future.wait([f1, f2]).then((values) {
+    return Future.wait([f1, f2]).then((values) {
       Expect.listEquals(values[0], message);
       Expect.listEquals(values[1], message);
     }).whenComplete(() {
diff --git a/tests/standalone_2/io/process_non_ascii_test.dart b/tests/standalone_2/io/process_non_ascii_test.dart
index f897f77..0f1a592 100644
--- a/tests/standalone_2/io/process_non_ascii_test.dart
+++ b/tests/standalone_2/io/process_non_ascii_test.dart
@@ -26,9 +26,11 @@
   var nonAsciiTxtFile = new File('${nonAsciiDir.path}/æøå.txt');
   nonAsciiTxtFile.writeAsStringSync('æøå');
   var script = nonAsciiFile.path;
-  Process
-      .run(executable, [script], workingDirectory: nonAsciiDir.path)
-      .then((result) {
+  // Note: we prevent this child process from using Crashpad handler because
+  // this introduces an issue with deleting the temporary directory.
+  Process.run(executable, [script],
+      workingDirectory: nonAsciiDir.path,
+      environment: {'DART_CRASHPAD_HANDLER': ''}).then((result) {
     Expect.equals(0, result.exitCode);
     tempDir.deleteSync(recursive: true);
     asyncEnd();
diff --git a/tests/standalone/io/raw_datagram_socket_test.dart b/tests/standalone_2/io/raw_datagram_socket_test.dart
similarity index 97%
rename from tests/standalone/io/raw_datagram_socket_test.dart
rename to tests/standalone_2/io/raw_datagram_socket_test.dart
index 3976c54..a933305 100644
--- a/tests/standalone/io/raw_datagram_socket_test.dart
+++ b/tests/standalone_2/io/raw_datagram_socket_test.dart
@@ -108,6 +108,12 @@
   test(InternetAddress.loopbackIPv4, 256, false);
   test(InternetAddress.loopbackIPv4, 0, false);
   test(InternetAddress.loopbackIPv4, null, false);
+
+  test(InternetAddress.loopbackIPv6, 1, true);
+  test(InternetAddress.loopbackIPv6, 255, true);
+  test(InternetAddress.loopbackIPv6, 256, false);
+  test(InternetAddress.loopbackIPv6, 0, false);
+  test(InternetAddress.loopbackIPv6, null, false);
 }
 
 testBroadcast() {
diff --git a/tests/standalone_2/io/regress_7679_test.dart b/tests/standalone_2/io/regress_7679_test.dart
index 63f11d3..3577a8b 100644
--- a/tests/standalone_2/io/regress_7679_test.dart
+++ b/tests/standalone_2/io/regress_7679_test.dart
@@ -35,9 +35,11 @@
 }
 """);
   String executable = new File(Platform.executable).resolveSymbolicLinksSync();
-  Process
-      .run(executable, ['script.dart'], workingDirectory: temp.path)
-      .then((result) {
+  // Note: we prevent this child process from using Crashpad handler because
+  // this introduces an issue with deleting the temporary directory.
+  Process.run(executable, ['script.dart'],
+      workingDirectory: temp.path,
+      environment: {'DART_CRASHPAD_HANDLER': ''}).then((result) {
     temp.deleteSync(recursive: true);
     Expect.equals(0, result.exitCode);
   });
diff --git a/tests/standalone_2/io/socket_ipv6_test.dart b/tests/standalone_2/io/socket_ipv6_test.dart
index 769506f..4fb14cd 100644
--- a/tests/standalone_2/io/socket_ipv6_test.dart
+++ b/tests/standalone_2/io/socket_ipv6_test.dart
@@ -130,6 +130,7 @@
 }
 
 main() async {
+  asyncStart();
   await testIPv6toIPv6(); //               //# 01: ok
   await testIPv4toIPv6(); //               //# 02: ok
   await testIPv4toIPv4(); //               //# 03: ok
@@ -138,4 +139,5 @@
 
   await retry(testIPv6toIPv4); //          //# 06: ok
   await retry(testIPv4toIPv6_IPV6Only); // //# 07: ok
+  asyncEnd();
 }
diff --git a/tests/standalone_2/io/socket_source_address_test.dart b/tests/standalone_2/io/socket_source_address_test.dart
index 236733a..82f5099 100644
--- a/tests/standalone_2/io/socket_source_address_test.dart
+++ b/tests/standalone_2/io/socket_source_address_test.dart
@@ -29,8 +29,13 @@
 
   var sourceAddress;
   asyncStart();
-  var server =
-      await ServerSocket.bind(InternetAddress.loopbackIPv4, freePort);
+  var server;
+  try {
+    server = await ServerSocket.bind(InternetAddress.loopbackIPv4, freePort);
+  } catch (e) {
+    asyncEnd();
+    rethrow;
+  }
   server.listen((_) {
     throw 'Unexpected connection from address $sourceAddress';
   }, onDone: () => asyncEnd());
diff --git a/tests/standalone_2/io/socket_upgrade_to_secure_test.dart b/tests/standalone_2/io/socket_upgrade_to_secure_test.dart
index 1b29455..13957ca 100644
--- a/tests/standalone_2/io/socket_upgrade_to_secure_test.dart
+++ b/tests/standalone_2/io/socket_upgrade_to_secure_test.dart
@@ -103,7 +103,7 @@
   }
 
   Future<RawSocket> runClient(Socket socket) {
-    var completer = new Completer();
+    Completer<RawSocket> completer = new Completer<RawSocket>();
     var dataReceived = <int>[];
     socket.listen((data) {
       dataReceived.addAll(data);
@@ -156,14 +156,14 @@
   Future<SecureSocket> connectClient(int port) {
     if (!handshakeBeforeSecure) {
       return Socket.connect(HOST, port).then((socket) {
-        var future;
+        Future<SecureSocket> future;
         if (hostnameInConnect) {
           future = SecureSocket.secure(socket, context: clientContext);
         } else {
           future =
               SecureSocket.secure(socket, host: HOST, context: clientContext);
         }
-        return future.then((secureSocket) {
+        return future.then<SecureSocket>((SecureSocket secureSocket) {
           socket.add([0]);
           return secureSocket;
         });
diff --git a/tests/standalone_2/standalone_2.status b/tests/standalone_2/standalone_2.status
index e78ae4d..095dc3e 100644
--- a/tests/standalone_2/standalone_2.status
+++ b/tests/standalone_2/standalone_2.status
@@ -123,7 +123,6 @@
 io/http_server_response_test: RuntimeError
 io/regress_10026_test: RuntimeError
 io/secure_socket_argument_test: CompileTimeError
-io/socket_upgrade_to_secure_test: RuntimeError
 io/web_socket_pipe_test: RuntimeError
 io/web_socket_protocol_processor_test: CompileTimeError
 io/zlib_test: RuntimeError
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index f880795..b1220e5 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -10,10 +10,12 @@
 # missing a section you need, please reach out to sigmund@ to see the best way
 # to add them.
 
+io/process_sync_test: Pass, Slow # Spawns synchronously subprocesses in sequence.
+
 [ $builder_tag == asan ]
 io/file_test: Fail # Issue 34724
 io/http_server_response_test: Fail # Issue 34724
-io/process_sync_test: Fail # Issue 34724 (child process)
+io/process_sync_test: Pass, Fail # https://github.com/dart-lang/sdk/issues/34724
 io/signals_test: Fail # Issue 34724
 io/test_extension_fail_test: Fail # Issue 32187
 
@@ -32,7 +34,6 @@
 io/platform_test: RuntimeError
 io/regress_10026_test: RuntimeError
 io/secure_socket_argument_test: CompileTimeError
-io/socket_upgrade_to_secure_test: RuntimeError
 io/test_extension_fail_test: RuntimeError
 io/test_extension_test: RuntimeError
 io/web_socket_pipe_test: RuntimeError
@@ -61,7 +62,6 @@
 [ $arch == x64 && $builder_tag == asan && $compiler == dartk ]
 io/file_test: Fail # Memory leak (issue 34724)
 io/http_server_response_test: Fail # Memory leak (issue 34724)
-io/process_sync_test: Pass, RuntimeError # Issue 34734
 io/signals_test: Pass, RuntimeError # Issue 34734
 io/test_extension_fail_test: Fail # Memory leak (issue 34724)
 
diff --git a/tools/VERSION b/tools/VERSION
index 5361581..c94d4b2 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -25,7 +25,7 @@
 #
 CHANNEL dev
 MAJOR 2
-MINOR 1
+MINOR 2
 PATCH 0
-PRERELEASE 9
-PRERELEASE_PATCH 4
+PRERELEASE 0
+PRERELEASE_PATCH 0
diff --git a/tools/addlatexhash.dart b/tools/addlatexhash.dart
index 118e4bc..21f8d52 100755
--- a/tools/addlatexhash.dart
+++ b/tools/addlatexhash.dart
@@ -11,9 +11,7 @@
 // hash listing file name as the third argument. From docs/language a
 // typical usage would be as follows:
 //
-//   dart
-//     --package-root=<build dir>/packages \
-//     ../../tools/addlatexhash.dart dartLangSpec.tex out.tex hash.txt
+// dart ../../tools/addlatexhash.dart dartLangSpec.tex out.tex hash.txt
 //
 // This will produce a normalized variant out.tex of the language
 // specification with hash values filled in, and a listing hash.txt of
@@ -207,7 +205,7 @@
 /// of its own, given the part of the RegExp that recognizes the
 /// command name, [cmdNameRE]
 lineCommandRE(cmdNameRE) =>
-    new RegExp(r"^\s*\\" + cmdNameRE + r"\s*\{.*\}\s*$");
+    new RegExp(r"^\s*\\" + cmdNameRE + r"\s*\{.*\}%?\s*$");
 
 final hashLabelStartRE = new RegExp(r"^\s*\\LMLabel\s*\{");
 final hashLabelEndRE = new RegExp(r"\}\s*$");
diff --git a/tools/approve_results.dart b/tools/approve_results.dart
new file mode 100755
index 0000000..75d54fb
--- /dev/null
+++ b/tools/approve_results.dart
@@ -0,0 +1,436 @@
+#!/usr/bin/env dart
+// 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.
+
+/// List tests whose results are different from the previously approved results,
+/// and ask whether to update the currently approved results, turning the bots
+/// green.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:math';
+
+import 'package:args/args.dart';
+import 'package:glob/glob.dart';
+
+import 'bots/results.dart';
+
+/// The bot names and named configurations are highly redundant if both are
+/// listed. This function returns a simplified named configuration that doesn't
+/// contain any aspects that's part of the bots name. This is used to get a more
+/// compact and readable output.
+String simplifyNamedConfiguration(String bot, String namedConfiguration) {
+  final botComponents = new Set<String>.from(bot.split("-"));
+  return namedConfiguration
+      .split("-")
+      .where((component) => !botComponents.contains(component))
+      .join("-");
+}
+
+/// Represents a test on a bot with the current result, the current approved
+/// result, and flakiness data.
+class Test implements Comparable {
+  final String bot;
+  final String name;
+  final Map<String, dynamic> resultData;
+  final Map<String, dynamic> approvedResultData;
+  final Map<String, dynamic> flakinessData;
+
+  Test(this.bot, this.name, this.resultData, this.approvedResultData,
+      this.flakinessData);
+
+  int compareTo(Object other) {
+    if (other is Test) {
+      if (bot.compareTo(other.bot) < 0) return -1;
+      if (other.bot.compareTo(bot) < 0) return 1;
+      if (configuration.compareTo(other.configuration) < 0) return -1;
+      if (other.configuration.compareTo(configuration) < 0) return 1;
+      if (name.compareTo(other.name) < 0) return -1;
+      if (other.name.compareTo(name) < 0) return 1;
+    }
+    return 0;
+  }
+
+  String get configuration => resultData["configuration"];
+  String get result => resultData["result"];
+  String get expected => resultData["expected"];
+  bool get matches => resultData["matches"];
+  String get approvedResult =>
+      approvedResultData != null ? approvedResultData["result"] : null;
+  bool get isApproved => result == approvedResult;
+  List<String> get flakyModes =>
+      flakinessData != null ? flakinessData["outcomes"].cast<String>() : null;
+  bool get isFlake => flakinessData != null && flakyModes.contains(result);
+}
+
+/// Loads the results file as as a map if the file exists, otherwise returns the
+/// empty map.
+Future<Map<String, Map<String, dynamic>>> loadResultsMapIfExists(
+        String path) async =>
+    await new File(path).exists()
+        ? loadResultsMap(path)
+        : <String, Map<String, dynamic>>{};
+
+/// Loads the results from the bot.
+Future<List<Test>> loadResultsFromBot(String bot, ArgResults options) async {
+  if (options["verbose"]) {
+    print("Loading $bot...");
+  }
+  // gsutil cp -r requires a destination directory, use a temporary one.
+  final tmpdir = await Directory.systemTemp.createTemp("approve_results.");
+  try {
+    // The 'latest' file contains the name of the latest build that we
+    // should download.
+    final build = await readFile(bot, "latest");
+
+    // Asynchronously download the latest build and the current approved
+    // results.
+    await Future.wait([
+      cpRecursiveGsutil(buildCloudPath(bot, build), tmpdir.path),
+      cpRecursiveGsutil(
+          "$approvedResultsStoragePath/$bot/approved_results.json",
+          "${tmpdir.path}/approved_results.json"),
+    ]);
+
+    // Check the build was properly downloaded.
+    final buildPath = "${tmpdir.path}/$build";
+    final buildDirectory = new Directory(buildPath);
+    if (!await buildDirectory.exists()) {
+      print("$bot: Build directory didn't exist");
+      return <Test>[];
+    }
+
+    // Load the run.json to find the named configuration.
+    final resultsFile = new File("$buildPath/results.json");
+    if (!await resultsFile.exists()) {
+      print("$bot: No results.json exists");
+      return <Test>[];
+    }
+
+    // Load the current results, the approved resutls, and the flakiness
+    // information.
+    final results = await loadResultsMapIfExists("$buildPath/results.json");
+    final flaky = await loadResultsMapIfExists("$buildPath/flaky.json");
+    final approvedResults =
+        await loadResultsMapIfExists("${tmpdir.path}/approved_results.json");
+
+    // Construct an object for every test containing its current result,
+    // what the last approved result was, and whether it's flaky.
+    final tests = <Test>[];
+    for (final key in results.keys) {
+      final result = results[key];
+      final approvedResult = approvedResults[key];
+      final flakiness = flaky[key];
+      final name = result["name"];
+      final test = new Test(bot, name, result, approvedResult, flakiness);
+      tests.add(test);
+    }
+    if (options["verbose"]) {
+      print("Loaded $bot (${tests.length} tests).");
+    }
+    return tests;
+  } finally {
+    // Always clean up the temporary directory when we don't need it.
+    await tmpdir.delete(recursive: true);
+  }
+}
+
+main(List<String> args) async {
+  final parser = new ArgParser();
+  parser.addMultiOption("bot",
+      abbr: "b",
+      help: "Select the bots matching the glob pattern [option is repeatable]",
+      splitCommas: false);
+  parser.addFlag("help", help: "Show the program usage.", negatable: false);
+  parser.addFlag("list",
+      abbr: "l", help: "List the available bots.", negatable: false);
+  parser.addFlag("no",
+      abbr: "n",
+      help: "Show changed results but don't approve.",
+      negatable: false);
+  parser.addFlag("verbose",
+      abbr: "v", help: "Describe asynchronous operations.", negatable: false);
+  parser.addFlag("yes",
+      abbr: "y", help: "Approve the results.", negatable: false);
+
+  final options = parser.parse(args);
+  if ((options["bot"].isEmpty && !options["list"]) || options["help"]) {
+    print("""
+Usage: approve_results.dart [OPTION]...
+List tests whose results are different from the previously approved results, and
+ask whether to update the currently approved results, turning the bots green.
+
+The options are as follows:
+
+${parser.usage}""");
+    return;
+  }
+
+  if (options["no"] && options["yes"]) {
+    stderr.writeln("The --no and --yes options are mutually incompatible");
+    exitCode = 1;
+    return;
+  }
+
+  // Load the list of bots according to the test matrix.
+  final testMatrixPath =
+      Platform.script.resolve("bots/test_matrix.json").toFilePath();
+  final testMatrix = jsonDecode(await new File(testMatrixPath).readAsString());
+  final builderConfigurations = testMatrix["builder_configurations"];
+  final testMatrixBots = <String>[];
+  for (final builderConfiguration in builderConfigurations) {
+    final steps = builderConfiguration["steps"];
+    // Only consider bots that use tools/test.py.
+    if (!steps.any((step) =>
+        step["script"] == null || step["script"] == "tools/test.py")) {
+      continue;
+    }
+    final builders = builderConfiguration["builders"].cast<String>();
+    testMatrixBots.addAll(builders);
+  }
+
+  // Load the list of bots that have data in cloud storage.
+  if (options["verbose"]) {
+    print("Loading list of bots...");
+  }
+  final botsWithData = (await listBots())
+      .where((bot) => !bot.endsWith("-try"))
+      .where((bot) => !bot.endsWith("-dev"))
+      .where((bot) => !bot.endsWith("-stable"));
+  if (options["verbose"]) {
+    print("Loaded list of bots.");
+  }
+
+  // The currently active bots are the bots both mentioned in the test matrix
+  // and that have results in cloud storage.
+  final allBots = new Set<String>.from(testMatrixBots)
+      .intersection(new Set<String>.from(botsWithData))
+      .toList()
+        ..sort();
+
+  // List the currently active bots if requested.
+  if (options["list"]) {
+    for (final bot in allBots) {
+      print(bot);
+    }
+    return;
+  }
+
+  // Select all the bots matching the glob patterns,
+  final bots = new Set<String>();
+  for (final botPattern in options["bot"]) {
+    final glob = new Glob(botPattern);
+    bool any = false;
+    for (final bot in allBots) {
+      if (glob.matches(bot)) {
+        bots.add(bot);
+        any = true;
+      }
+    }
+    if (!any) {
+      stderr.writeln("error: No bots matched pattern: $botPattern");
+      stderr.writeln("Try --list to get the list of bots, or --help for help");
+      exitCode = 1;
+      return;
+    }
+  }
+  for (final bot in bots) {
+    print("Selected bot: $bot");
+  }
+
+  // Load all the latest results for the selected bots, as well as flakiness
+  // data, and the set of currently approved results. Each bot's latest build
+  // is downloaded in parallel to make this phase faster.
+  final testListFutures = <Future>[];
+  for (final String bot in bots) {
+    testListFutures.add(loadResultsFromBot(bot, options));
+  }
+
+  // Collect all the tests from the synchronous downloads.
+  final tests = <Test>[];
+  for (final testList in await Future.wait(testListFutures)) {
+    tests.addAll(testList);
+  }
+  tests.sort();
+  print("");
+
+  // Compute statistics and the set of interesting tests.
+  final flakyTestsCount = tests.where((test) => test.isFlake).length;
+  final failingTestsCount =
+      tests.where((test) => !test.isFlake && !test.matches).length;
+  final unapprovedTests =
+      tests.where((test) => !test.isFlake && !test.isApproved).toList();
+  final fixedTests = unapprovedTests.where((test) => test.matches).toList();
+  final brokenTests = unapprovedTests.where((test) => !test.matches).toList();
+
+  // Find out which bots have multiple configurations.
+  final outcomes = new Set<String>();
+  final configurationsForBots = <String, Set<String>>{};
+  for (final test in tests) {
+    outcomes.add(test.result);
+    var configurationSet = configurationsForBots[test.bot];
+    if (configurationSet == null) {
+      configurationsForBots[test.bot] = configurationSet = new Set<String>();
+    }
+    configurationSet.add(test.configuration);
+  }
+
+  // Compute a nice displayed name for the bot and configuration. If the bot
+  // only has a single configuration, then only mention the bot. Otherwise,
+  // remove the redundant parts from configuration and present it compactly.
+  // This is needed to avoid the tables becoming way too large.
+  String getBotDisplayName(String bot, String configuration) {
+    if (configurationsForBots[bot].length == 1) {
+      return bot;
+    } else {
+      final simpleConfig = simplifyNamedConfiguration(bot, configuration);
+      return "$bot/$simpleConfig";
+    }
+  }
+
+  // Compute the width of the fields in the below tables.
+  final unapprovedBots = new Set<String>();
+  int longestBot = "BOT/CONFIG".length;
+  int longestTest = "TEST".length;
+  int longestResult = "RESULT".length;
+  for (final test in unapprovedTests) {
+    unapprovedBots.add(test.bot);
+    final botDisplayName = getBotDisplayName(test.bot, test.configuration);
+    longestBot = max(longestBot, botDisplayName.length);
+    if (!test.matches) {
+      longestTest = max(longestTest, test.name.length);
+      longestResult = max(longestResult, test.result.length);
+    }
+  }
+  longestTest = min(longestTest, 120); // Some tests names are extremely long.
+
+  // Table of lists that now succeed.
+  if (fixedTests.isNotEmpty) {
+    print("The following tests are now succeeding:\n");
+    print("${'BOT/CONFIG'.padRight(longestBot)}  "
+        "TEST");
+    for (final test in fixedTests) {
+      final botDisplayName = getBotDisplayName(test.bot, test.configuration);
+      print("${botDisplayName.padRight(longestBot)}  "
+          "${test.name}");
+    }
+    print("");
+  }
+
+  /// Table of lists that now fail.
+  if (brokenTests.isNotEmpty) {
+    print("The following tests are now failing:\n");
+    print("${'BOT'.padRight(longestBot)}  "
+        "${'TEST'.padRight(longestTest)}  "
+        "${'RESULT'.padRight(longestResult)}  "
+        "EXPECTED");
+    for (final test in brokenTests) {
+      final botDisplayName = getBotDisplayName(test.bot, test.configuration);
+      print("${botDisplayName.padRight(longestBot)}  "
+          "${test.name.padRight(longestTest)}  "
+          "${test.result.padRight(longestResult)}  "
+          "${test.expected}");
+    }
+    print("");
+  }
+
+  // Provide statistics on how well the bots are doing.
+  void statistic(int numerator, int denominator, String what) {
+    double percent = numerator / denominator * 100.0;
+    String percentString = percent.toStringAsFixed(2) + "%";
+    print("$numerator of $denominator $what ($percentString)");
+  }
+
+  statistic(failingTestsCount, tests.length, "tests are failing");
+  statistic(flakyTestsCount, tests.length, "tests are flaky");
+  statistic(
+      fixedTests.length, tests.length, "tests were fixed since last approval");
+  statistic(brokenTests.length, tests.length,
+      "tests were broken since last approval");
+
+  // Stop if there's nothing to do.
+  if (unapprovedBots.isEmpty) {
+    print("\nEvery test result has already been approved.");
+    return;
+  }
+
+  // Stop if this is a dry run.
+  if (options["no"]) {
+    if (unapprovedBots.length == 1) {
+      print("1 test has a changed result and needs approval");
+    } else {
+      print("${unapprovedBots.length} "
+          "tests have changed results and need approval");
+    }
+    return;
+  }
+
+  // Confirm the approval if run interactively.
+  if (!options["yes"]) {
+    print("");
+    print("Note: It is assumed bugs have been filed about the above failures "
+        "before they are approved here.");
+    if (brokenTests.isNotEmpty) {
+      final botPlural = bots.length == 1 ? "bot" : "bots";
+      print("Note: Approving the failures will turn the "
+          "$botPlural green on the next commit.");
+    }
+    while (true) {
+      stdout.write("Do you want to approve? (yes/no) [yes] ");
+      final line = stdin.readLineSync();
+      // End of file condition is considered no.
+      if (line == null) {
+        print("n");
+        return;
+      }
+      if (line.toLowerCase() == "n" || line.toLowerCase() == "no") {
+        return;
+      }
+      if (line == "" ||
+          line.toLowerCase() == "y" ||
+          line.toLowerCase() == "yes") {
+        break;
+      }
+    }
+  } else {
+    print("Note: It is assumed bugs have been filed about the above failures.");
+  }
+  print("");
+
+  // Update approved_results.json for each bot with unapproved changes.
+  final outDirectory =
+      await Directory.systemTemp.createTemp("approved_results.");
+  try {
+    final testsForBots = <String, List<Test>>{};
+    for (final test in tests) {
+      if (!testsForBots.containsKey(test.bot)) {
+        testsForBots[test.bot] = <Test>[test];
+      } else {
+        testsForBots[test.bot].add(test);
+      }
+    }
+    print("Uploading approved results...");
+    final futures = <Future>[];
+    for (final String bot in unapprovedBots) {
+      final testsList = testsForBots[bot];
+      final localPath = "${outDirectory.path}/$bot.json";
+      await new File(localPath).writeAsString(
+          testsList.map((test) => jsonEncode(test.resultData) + "\n").join(""));
+      final remotePath =
+          "$approvedResultsStoragePath/$bot/approved_results.json";
+      futures.add(cpGsutil(localPath, remotePath)
+          .then((_) => print("Uploaded approved results for $bot")));
+    }
+    await Future.wait(futures);
+    if (brokenTests.isNotEmpty) {
+      print(
+          "Successfully approved results, the next commit will turn bots green");
+    } else {
+      print("Successfully approved results");
+    }
+  } finally {
+    await outDirectory.delete(recursive: true);
+  }
+}
diff --git a/tools/bots/compare_results.dart b/tools/bots/compare_results.dart
index 9d69ba3..e475e4c 100755
--- a/tools/bots/compare_results.dart
+++ b/tools/bots/compare_results.dart
@@ -15,21 +15,26 @@
 import 'results.dart';
 
 class Result {
+  final String configuration;
   final String name;
   final String outcome;
   final String expectation;
   final bool matches;
   final bool flaked;
 
-  Result(this.name, this.outcome, this.expectation, this.matches, this.flaked);
+  Result(this.configuration, this.name, this.outcome, this.expectation,
+      this.matches, this.flaked);
 
   Result.fromMap(Map<String, dynamic> map, Map<String, dynamic> flakinessData)
-      : name = map["name"],
+      : configuration = map["configuration"],
+        name = map["name"],
         outcome = map["result"],
         expectation = map["expected"],
         matches = map["matches"],
         flaked = flakinessData != null &&
             flakinessData["outcomes"].contains(map["result"]);
+
+  String get key => "$name:$configuration";
 }
 
 class Event {
@@ -75,7 +80,8 @@
   bool judgement = false;
   bool beganSection = false;
   int count = options["count"] != null ? int.parse(options["count"]) : null;
-
+  final configurations =
+      events.map((event) => event.after.configuration).toSet();
   for (final event in events) {
     if (searchFor == "passing" &&
         (event.after.flaked || !event.after.matches)) {
@@ -101,7 +107,12 @@
     beganSection = true;
     final before = event.before;
     final after = event.after;
-    final name = event.after.name;
+    // The --flaky option is used to get a list of tests to deflake within a
+    // single named configuration. Therefore we can't right now always emit
+    // the configuration name, so only do it if there's more than one in the
+    // results being compared (that won't happen during deflaking.
+    final name =
+        configurations.length == 1 ? event.after.name : event.after.key;
     if (!after.flaked && !after.matches) {
       judgement = true;
     }
@@ -135,7 +146,7 @@
             "${before?.matches} ${after.matches} "
             "${before?.flaked} ${after.flaked}");
       } else {
-        print(event.after.name);
+        print(name);
       }
     }
   }
diff --git a/tools/bots/flutter/analyze_flutter.sh b/tools/bots/flutter/analyze_flutter.sh
index 4f752e5..c54f461 100755
--- a/tools/bots/flutter/analyze_flutter.sh
+++ b/tools/bots/flutter/analyze_flutter.sh
@@ -2,8 +2,8 @@
 # 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.
-#
-# Runs flutter's analyze tests with a locally built SDK.
+
+# Runs flutter's analyzer related tests with a locally built SDK.
 set -e
 
 dart=$(pwd)/tools/sdks/dart-sdk/bin/dart
@@ -15,8 +15,11 @@
 trap cleanup EXIT HUP INT QUIT TERM PIPE
 cd "$tmpdir"
 
-git clone --depth 1 -vv https://chromium.googlesource.com/external/github.com/flutter/flutter
+git clone -vv https://chromium.googlesource.com/external/github.com/flutter/flutter
+
 cd flutter
+
 bin/flutter config --no-analytics
 bin/flutter update-packages
-$dart dev/bots/analyze.dart --dart-sdk $sdk
\ No newline at end of file
+
+$dart dev/bots/analyze.dart --dart-sdk $sdk
diff --git a/tools/bots/results.dart b/tools/bots/results.dart
index fbc51e7..36b27f2 100644
--- a/tools/bots/results.dart
+++ b/tools/bots/results.dart
@@ -8,6 +8,98 @@
 import 'dart:convert';
 import 'dart:io';
 
+/// gsutil.py binary to use.
+const gsutil = "gsutil.py";
+
+/// Cloud storage location containing results.
+const testResultsStoragePath = "gs://dart-test-results/builders";
+
+/// Cloud storage location containing approved results.
+const approvedResultsStoragePath =
+    "gs://dart-test-results-approved-results/builders";
+
+/// Runs gsutil with the provided [arguments] and returns the standard output.
+/// Returns null if the requested URL didn't exist.
+Future<String> runGsutil(List<String> arguments) async {
+  final processResult = await Process.run(gsutil, arguments,
+      environment: {"DEPOT_TOOLS_UPDATE": "0"});
+  if (processResult.exitCode != 0) {
+    if (processResult.exitCode == 1 &&
+            processResult.stderr.contains("No URLs matched") ||
+        processResult.stderr.contains("One or more URLs matched no objects")) {
+      return null;
+    }
+    throw new Exception("Failed to run: $gsutil $arguments\n"
+        "exitCode: ${processResult.exitCode}\n"
+        "stdout:\n${processResult.stdout}\n"
+        "stderr:\n${processResult.stderr}");
+  }
+  return processResult.stdout;
+}
+
+/// Returns the contents of the provided cloud storage [path], or null if it
+/// didn't exist.
+Future<String> catGsutil(String path) => runGsutil(["cat", path]);
+
+/// Returns the files and directories in the provided cloud storage [directory],
+/// or null if it didn't exist.
+Future<Iterable<String>> lsGsutil(String directory) async {
+  final contents = await runGsutil(["ls", directory]);
+  if (contents == null) {
+    return null;
+  }
+  return LineSplitter.split(contents).map((String path) {
+    final elements = path.split("/");
+    if (elements[elements.length - 1].isEmpty) {
+      return elements[elements.length - 2];
+    } else {
+      return elements[elements.length - 1];
+    }
+  });
+}
+
+/// Copies a file to or from cloud storage.
+Future cpGsutil(String source, String destination) =>
+    runGsutil(["cp", source, destination]);
+
+/// Copies a directory recursively to or from cloud strorage.
+Future cpRecursiveGsutil(String source, String destination) =>
+    runGsutil(["-m", "cp", "-r", "-Z", source, destination]);
+
+/// Lists the bots in cloud storage.
+Future<Iterable<String>> listBots() => lsGsutil("$testResultsStoragePath");
+
+/// Returns the cloud storage path for the [bot].
+String botCloudPath(String bot) => "$testResultsStoragePath/$bot";
+
+/// Returns the cloud storage path to the [build] on the [bot].
+String buildCloudPath(String bot, String build) =>
+    "${botCloudPath(bot)}/$build";
+
+/// Returns the cloud storage path to the [file] inside the [bot]'s directory.
+String fileCloudPath(String bot, String file) => "${botCloudPath(bot)}/$file";
+
+/// Reads the contents of the [file] inside the [bot]'s cloud storage.
+Future<String> readFile(String bot, String file) =>
+    catGsutil(fileCloudPath(bot, file));
+
+/// Returns the cloud storage path to the [file] inside the [build] on the
+/// [bot].
+String buildFileCloudPath(String bot, String build, String file) =>
+    "${buildCloudPath(bot, build)}/$file";
+
+/// Reads the contents of the [file] inside the [build] in the [bot]'s cloud
+/// storage.
+Future<String> readBuildFile(String bot, String build, String file) =>
+    catGsutil(buildFileCloudPath(bot, build, file));
+
+List<Map<String, dynamic>> parseResults(String contents) {
+  return LineSplitter.split(contents)
+      .map(jsonDecode)
+      .toList()
+      .cast<Map<String, dynamic>>();
+}
+
 Future<List<Map<String, dynamic>>> loadResults(String path) async {
   final results = <Map<String, dynamic>>[];
   final lines = new File(path)
@@ -23,8 +115,17 @@
 
 Map<String, Map<String, dynamic>> createResultsMap(
         List<Map<String, dynamic>> results) =>
-    new Map<String, Map<String, dynamic>>.fromIterable(results,
-        key: (dynamic result) => (result as Map<String, dynamic>)['name']);
+    new Map<String, Map<String, dynamic>>.fromIterable(
+        results
+            // TODO: Temporarily discard results in the old flaky.json format
+            // This can be removed once every bot has run once after this commit
+            // has landed, purging all old flakiness information.
+            .where((result) => result["configuration"] != null),
+        key: (dynamic result) =>
+            "${result["configuration"]}:${result["name"]}");
+
+Map<String, Map<String, dynamic>> parseResultsMap(String contents) =>
+    createResultsMap(parseResults(contents));
 
 Future<Map<String, Map<String, dynamic>>> loadResultsMap(String path) async =>
     createResultsMap(await loadResults(path));
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 2ba6dbc..70fdc8d 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -78,6 +78,37 @@
       "xcodebuild/ReleaseX64/dart2js_platform.dill",
       "xcodebuild/ReleaseX64/dart2js_platform_strong.dill"
     ],
+    "fuzzer": [
+      "runtime/tools/dartfuzz/",
+      "out/DebugIA32/",
+      "out/DebugSIMARM/",
+      "out/DebugSIMARM64/",
+      "out/DebugSIMDBC/",
+      "out/DebugSIMDBC64/",
+      "out/DebugX64/",
+      "out/ProductX64/",
+      "out/ReleaseIA32/",
+      "out/ReleaseSIMARM/",
+      "out/ReleaseSIMARM64/",
+      "out/ReleaseSIMDBC/",
+      "out/ReleaseSIMDBC64/",
+      "out/ReleaseX64/",
+      "third_party/pkg/",
+      "third_party/pkg_tested/",
+      "third_party/observatory_pub_packages/packages/",
+      "tools/sdks/dart-sdk/",
+      "pkg/async_helper/",
+      "pkg/dart_internal/",
+      "pkg/expect/",
+      "pkg/front_end/",
+      "pkg/js/",
+      "pkg/kernel/",
+      "pkg/meta/",
+      "pkg/vm/",
+      "runtime/",
+      "sdk/",
+      ".packages"
+    ],
     "vm-kernel": [
       "out/DebugIA32/",
       "out/DebugSIMARM/",
@@ -88,6 +119,7 @@
       "out/ReleaseIA32/",
       "out/ReleaseSIMARM/",
       "out/ReleaseSIMARM64/",
+      "out/ReleaseXARM64/",
       "out/ReleaseSIMDBC64/",
       "out/ReleaseX64/",
       "xcodebuild/DebugIA32/",
@@ -268,7 +300,7 @@
     "dartk-win-(debug|release)-(ia32|x64)": { },
     "dartk-(linux|mac|win)-product-x64": { },
     "dartk-(linux|mac)-(debug|release)-simdbc64": { },
-    "dartk-linux-release-(simarm|simarm64)": { },
+    "dartk-linux-release-(arm64|simarm|simarm64)": { },
     "dartk-optcounter-linux-release-(ia32|x64)": {
       "options": {
         "builder-tag": "optimization_counter_threshold",
@@ -636,6 +668,27 @@
     },
     {
       "builders": [
+        "cross-vm-linux-release-arm64"
+      ],
+      "meta": {
+        "description": "This configuration is for the cross arm builders."
+      },
+      "steps": [
+        {
+          "name": "build dart",
+          "script": "tools/build.py",
+          "arguments": ["runtime_kernel"]
+        },
+        {
+          "name": "vm tests",
+          "arguments": ["-ndartk-${system}-${mode}-${arch}"],
+          "fileset": "vm-kernel",
+          "shards": 1
+        }
+      ]
+    },
+    {
+      "builders": [
         "app-kernel-linux-debug-x64",
         "app-kernel-linux-product-x64",
         "app-kernel-linux-release-x64"
@@ -833,8 +886,10 @@
         {
           "name": "vm tests",
           "arguments": [
-            "-ndartk-reload-${system}-${mode}-${arch}"]
-        }
+            "-ndartk-reload-${system}-${mode}-${arch}"],
+            "fileset": "vm-kernel",
+            "shards": 10
+          }
       ]
     },
     {
@@ -854,8 +909,10 @@
         {
           "name": "vm tests",
           "arguments": [
-            "-ndartk-reload-rollback-linux-${mode}-x64"]
-        }
+            "-ndartk-reload-rollback-linux-${mode}-x64"],
+            "fileset": "vm-kernel",
+            "shards": 10
+          }
       ]
     },
     {
@@ -898,9 +955,9 @@
           "name": "dart2js tests",
           "arguments": [
             "-ndart2js-hostasserts-linux-ia32-d8",
-            "--dart2js-batch"
+            "--dart2js-batch",
+            "--exclude_suite=observatory_ui"
           ],
-          "exclude_tests": ["observatory_ui"],
           "shards": 6,
           "fileset": "dart2js_hostasserts"
         },
@@ -918,25 +975,26 @@
           "name": "dart2js package tests",
           "arguments": [
             "-ndart2js-hostasserts-linux-ia32-d8",
-            "--dart2js-batch"
-          ],
-          "tests": ["pkg"]
+            "--dart2js-batch",
+            "pkg"
+          ]
         },
         {
           "name": "dart2js observatory-ui tests",
           "arguments": [
             "-ndart2js-hostasserts-linux-ia32-d8",
-            "--dart2js-batch"
-          ],
-          "tests": ["observatory_ui"]
+            "--dart2js-batch",
+            "observatory_ui"
+          ]
         },
         {
           "name": "dart2js extra tests",
           "arguments": [
             "-ndart2js-hostasserts-linux-ia32-d8",
-            "--dart2js-batch"
-          ],
-          "tests": ["dart2js_extra","dart2js_native"]
+            "--dart2js-batch",
+            "dart2js_extra",
+            "dart2js_native"
+          ]
         }
       ]
     },
@@ -965,9 +1023,9 @@
           "arguments": [
             "-ndart2js-${system}-${runtime}",
             "--dart2js-batch",
-            "--reset-browser-configuration"
+            "--reset-browser-configuration",
+            "--exclude_suite=observatory_ui"
           ],
-          "exclude_tests": ["observatory_ui"],
           "shards": 6,
           "fileset": "dart2js"
         },
@@ -987,27 +1045,28 @@
           "arguments": [
             "-ndart2js-${system}-${runtime}",
             "--dart2js-batch",
-            "--reset-browser-configuration"
-          ],
-          "tests": ["pkg"]
+            "--reset-browser-configuration",
+            "pkg"
+          ]
         },
         {
           "name": "dart2js observatory-ui tests",
           "arguments": [
             "-ndart2js-${system}-${runtime}",
             "--dart2js-batch",
-            "--reset-browser-configuration"
-          ],
-          "tests": ["observatory_ui"]
+            "--reset-browser-configuration",
+            "observatory_ui"
+          ]
         },
         {
           "name": "dart2js extra tests",
           "arguments": [
             "-ndart2js-${system}-${runtime}",
             "--dart2js-batch",
-            "--reset-browser-configuration"
-          ],
-          "tests": ["dart2js_extra","dart2js_native"]
+            "--reset-browser-configuration",
+            "dart2js_extra",
+            "dart2js_native"
+          ]
         }
       ]
     },
@@ -1036,9 +1095,9 @@
           "arguments": [
             "-ndart2js-faststartup-${system}-${runtime}",
             "--dart2js-batch",
-            "--reset-browser-configuration"
+            "--reset-browser-configuration",
+            "--exclude_suite=observatory_ui"
           ],
-          "exclude_tests": ["observatory_ui"],
           "shards": 6,
           "fileset": "dart2js"
         },
@@ -1058,27 +1117,28 @@
           "arguments": [
             "-ndart2js-faststartup-${system}-${runtime}",
             "--dart2js-batch",
-            "--reset-browser-configuration"
-          ],
-          "tests": ["pkg"]
+            "--reset-browser-configuration",
+            "pkg"
+          ]
         },
         {
           "name": "dart2js fast-startup observatory-ui tests",
           "arguments": [
             "-ndart2js-faststartup-${system}-${runtime}",
             "--dart2js-batch",
-            "--reset-browser-configuration"
-          ],
-          "tests": ["observatory_ui"]
+            "--reset-browser-configuration",
+            "observatory_ui"
+          ]
         },
         {
           "name": "dart2js fast-startup extra tests",
           "arguments": [
             "-ndart2js-faststartup-${system}-${runtime}",
             "--dart2js-batch",
-            "--reset-browser-configuration"
-          ],
-          "tests": ["dart2js_extra","dart2js_native"]
+            "--reset-browser-configuration",
+            "dart2js_extra",
+            "dart2js_native"
+          ]
         }
       ]
     },
@@ -1097,9 +1157,9 @@
           "name": "dart2js tests",
           "arguments": [
             "-ndart2js-minified-linux-d8",
-            "--dart2js-batch"
+            "--dart2js-batch",
+            "--exclude_suite=observatory_ui"
           ],
-          "exclude_tests": ["observatory_ui"],
           "shards": 6,
           "fileset": "dart2js"
         },
@@ -1107,9 +1167,9 @@
           "name": "dart2js fast-startup tests",
           "arguments": [
             "-ndart2js-minified-faststartup-linux-d8",
-            "--dart2js-batch"
+            "--dart2js-batch",
+            "--exclude_suite=observatory_ui"
           ],
-          "exclude_tests": ["observatory_ui"],
           "shards": 6,
           "fileset": "dart2js"
         },
@@ -1117,49 +1177,51 @@
           "name": "dart2js package tests",
           "arguments": [
             "-ndart2js-minified-linux-d8",
-            "--dart2js-batch"
-          ],
-          "tests": ["pkg"]
+            "--dart2js-batch",
+            "pkg"
+          ]
         },
         {
           "name": "dart2js observatory-ui tests",
           "arguments": [
             "-ndart2js-minified-linux-d8",
-            "--dart2js-batch"
-          ],
-          "tests": ["observatory_ui"]
+            "--dart2js-batch",
+            "observatory_ui"
+          ]
         },
         {
           "name": "dart2js extra tests",
           "arguments": [
             "-ndart2js-minified-linux-d8",
-            "--dart2js-batch"
-          ],
-          "tests": ["dart2js_extra","dart2js_native"]
+            "--dart2js-batch",
+            "dart2js_extra",
+            "dart2js_native"
+          ]
         },
         {
           "name": "dart2js fast-startup package tests",
           "arguments": [
             "-ndart2js-minified-faststartup-linux-d8",
-            "--dart2js-batch"
-          ],
-          "tests": ["pkg"]
+            "--dart2js-batch",
+            "pkg"
+          ]
         },
         {
           "name": "dart2js fast-startup observatory-ui tests",
           "arguments": [
             "-ndart2js-minified-faststartup-linux-d8",
-            "--dart2js-batch"
-          ],
-          "tests": ["observatory_ui"]
+            "--dart2js-batch",
+            "observatory_ui"
+          ]
         },
         {
           "name": "dart2js fast-startup extra tests",
           "arguments": [
             "-ndart2js-minified-faststartup-linux-d8",
-            "--dart2js-batch"
-          ],
-          "tests": ["dart2js_extra","dart2js_native"]
+            "--dart2js-batch",
+            "dart2js_extra",
+            "dart2js_native"
+          ]
         }
       ]
     },
@@ -1179,9 +1241,9 @@
           "arguments": [
             "-ndart2js-minified-csp-linux-chrome",
             "--dart2js-batch",
-            "--reset-browser-configuration"
+            "--reset-browser-configuration",
+            "--exclude_suite=observatory_ui"
           ],
-          "exclude_tests": ["observatory_ui"],
           "shards": 4,
           "fileset": "dart2js"
         },
@@ -1190,9 +1252,9 @@
           "arguments": [
             "-ndart2js-minified-faststartup-csp-linux-chrome",
             "--dart2js-batch",
-            "--reset-browser-configuration"
+            "--reset-browser-configuration",
+            "--exclude_suite=observatory_ui"
           ],
-          "exclude_tests": ["observatory_ui"],
           "shards": 4,
           "fileset": "dart2js"
         },
@@ -1201,53 +1263,55 @@
           "arguments": [
             "-ndart2js-minified-csp-linux-chrome",
             "--dart2js-batch",
-            "--reset-browser-configuration"
-          ],
-          "tests": ["pkg"]
+            "--reset-browser-configuration",
+            "pkg"
+          ]
         },
         {
           "name": "dart2js observatory-ui tests",
           "arguments": [
             "-ndart2js-minified-csp-linux-chrome",
             "--dart2js-batch",
-            "--reset-browser-configuration"
-          ],
-          "tests": ["observatory_ui"]
+            "--reset-browser-configuration",
+            "observatory_ui"
+          ]
         },
         {
           "name": "dart2js extra tests",
           "arguments": [
             "-ndart2js-minified-csp-linux-chrome",
-            "--dart2js-batch"
-          ],
-          "tests": ["dart2js_extra","dart2js_native"]
+            "--dart2js-batch",
+            "dart2js_extra",
+            "dart2js_native"
+          ]
         },
         {
           "name": "dart2js fast-startup package tests",
           "arguments": [
             "-ndart2js-minified-faststartup-csp-linux-chrome",
             "--dart2js-batch",
-            "--reset-browser-configuration"
-          ],
-          "tests": ["pkg"]
+            "--reset-browser-configuration",
+            "pkg"
+          ]
         },
         {
           "name": "dart2js fast-startup observatory-ui tests",
           "arguments": [
             "-ndart2js-minified-faststartup-csp-linux-chrome",
             "--dart2js-batch",
-            "--reset-browser-configuration"
-          ],
-          "tests": ["observatory_ui"]
+            "--reset-browser-configuration",
+            "observatory_ui"
+          ]
         },
         {
           "name": "dart2js fast-startup extra tests",
           "arguments": [
             "-ndart2js-minified-faststartup-csp-linux-chrome",
             "--dart2js-batch",
-            "--reset-browser-configuration"
-          ],
-          "tests": ["dart2js_extra","dart2js_native"]
+            "--reset-browser-configuration",
+            "dart2js_extra",
+            "dart2js_native"
+          ]
         }
       ]
     },
@@ -1615,14 +1679,16 @@
         {
           "name": "package unit tests",
           "arguments": [
-            "-nunittest-asserts-${system}"],
-          "tests": ["pkg"]
+            "-nunittest-asserts-${system}",
+            "pkg"
+          ]
         },
         {
           "name": "third_party pkg_tested unit tests",
           "arguments": [
-            "-nunittest-asserts-${system}"],
-          "tests": ["pkg_tested"]
+            "-nunittest-asserts-${system}",
+            "pkg_tested"
+          ]
         },
         {
           "name": "pub integration tests",
@@ -1726,9 +1792,11 @@
             "--isolates",
             "8",
             "--no-show-stats",
-            "--repeat",
-            "125"
-          ]
+            "--time",
+            "2700"
+          ],
+          "shards": 10,
+          "fileset": "fuzzer"
         }
       ]
     }
diff --git a/tools/bots/update_flakiness.dart b/tools/bots/update_flakiness.dart
index 89347f3..87c584b 100755
--- a/tools/bots/update_flakiness.dart
+++ b/tools/bots/update_flakiness.dart
@@ -39,9 +39,12 @@
   for (final path in parameters) {
     final results = await loadResults(path);
     for (final result in results) {
+      final String configuration = result["configuration"];
       final String name = result["name"];
+      final key = "$configuration:$name";
       final Map<String, dynamic> testData =
-          data.putIfAbsent(name, () => <String, dynamic>{});
+          data.putIfAbsent(key, () => <String, dynamic>{});
+      testData["configuration"] = configuration;
       testData["name"] = name;
       final outcomes = testData.putIfAbsent("outcomes", () => []);
       if (!outcomes.contains(result["result"])) {
@@ -56,9 +59,9 @@
   final sink = options["output"] != null
       ? new File(options["output"]).openWrite()
       : stdout;
-  final names = new List<String>.from(data.keys)..sort();
-  for (final name in names) {
-    final testData = data[name];
+  final keys = new List<String>.from(data.keys)..sort();
+  for (final key in keys) {
+    final testData = data[key];
     if (testData["outcomes"].length < 2) continue;
     sink.writeln(jsonEncode(testData));
   }
diff --git a/tools/buildtools/update.py b/tools/buildtools/update.py
index 1b38f4b..5cae6a8 100755
--- a/tools/buildtools/update.py
+++ b/tools/buildtools/update.py
@@ -110,9 +110,7 @@
     result = UpdateGNOnWindows()
     if result != 0:
       return result
-    # TODO(zra): Re-enable clang-format download when gs is fixed for the bots.
-    # return UpdateClangFormatOnWindows()
-    return 0
+    return UpdateClangFormatOnWindows()
   if Update() != 0:
     return 1
   return CopyClangFormat()
diff --git a/tools/dom/docs/docs.json b/tools/dom/docs/docs.json
index 8e2ba96..7055e99 100644
--- a/tools/dom/docs/docs.json
+++ b/tools/dom/docs/docs.json
@@ -1245,8 +1245,8 @@
           "   *",
           "   * ## Other resources",
           "   *",
-          "   * * [scrollByLines](http://docs.webplatform.org/wiki/dom/methods/scrollByLines)",
-          "   *   from WebPlatform.org.",
+          "   * * [Window.scrollByLines](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollByLines)",
+          "   *   from MDN.",
           "   */"
         ],
         "scrollByPages": [
@@ -1255,7 +1255,8 @@
           "   *",
           "   * ## Other resources",
           "   *",
-          "   * * [scrollByPages](http://docs.webplatform.org/wiki/dom/methods/scrollByPages) from WebPlatform.org.",
+          "   * * [Window.scrollByPages](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollByPages)",
+          "   *   from MDN.",
           "   */"
         ],
         "scrollEvent": [
@@ -1425,9 +1426,9 @@
           "   *",
           "   * ## Other resources",
           "   *",
-          "   * * [Using the fullscreen",
-          "   *   API](http://docs.webplatform.org/wiki/tutorials/using_the_full-screen_api)",
-          "   *   tutorial from WebPlatform.org.",
+          "   * * [Fullscreen",
+          "   *   API](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API)",
+          "   *   from MDN.",
           "   * * [Fullscreen specification](http://www.w3.org/TR/fullscreen/) from W3C.",
           "   */"
         ],
@@ -3404,8 +3405,8 @@
           "   *",
           "   * ## Other resources",
           "   *",
-          "   * * [innerHeight](http://docs.webplatform.org/wiki/css/cssom/properties/innerHeight)",
-          "   *   from WebPlatform.org.",
+          "   * * [Window.innerHeight](https://developer.mozilla.org/en-US/docs/Web/API/Window/innerHeight)",
+          "   *   from MDN.",
           "   */"
         ],
         "innerWidth": [
@@ -3414,8 +3415,8 @@
           "   *",
           "   * ## Other resources",
           "   *",
-          "   * * [innerWidth](http://docs.webplatform.org/wiki/css/cssom/properties/innerWidth)",
-          "   *   from WebPlatform.org.",
+          "   * * [Window.innerWidth](https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth)",
+          "   *   from MDN.",
           "   */"
         ],
         "localStorage": [
@@ -3494,8 +3495,8 @@
           "   *",
           "   * ## Other resources",
           "   *",
-          "   * * [Window name](http://docs.webplatform.org/wiki/html/attributes/name_(window))",
-          "   *   from WebPlatform.org.",
+          "   * * [Window.name](https://developer.mozilla.org/en-US/docs/Web/API/Window/name)",
+          "   *   from MDN.",
           "   */"
         ],
         "navigator": [
@@ -3523,7 +3524,7 @@
           "   *",
           "   * ## Other resources",
           "   *",
-          "   * * [offscreenBuffering](http://docs.webplatform.org/wiki/dom/properties/offscreenBuffering)",
+          "   * * [offscreenBuffering](https://webplatform.github.io/docs/dom/HTMLElement/offscreenBuffering/)",
           "   *   from WebPlatform.org.",
           "   */"
         ],
@@ -3709,8 +3710,8 @@
           "   *",
           "   * ## Other resources",
           "   *",
-          "   * * [outerHeight](http://docs.webplatform.org/wiki/css/cssom/properties/outerHeight)",
-          "   *   from WebPlatform.org.",
+          "   * * [Window.outerHeight](https://developer.mozilla.org/en-US/docs/Web/API/Window/outerHeight)",
+          "   *   from MDN.",
           "   */"
         ],
         "outerWidth": [
@@ -3719,8 +3720,8 @@
           "   *",
           "   * ## Other resources",
           "   *",
-          "   * * [outerWidth](http://docs.webplatform.org/wiki/css/cssom/properties/outerWidth)",
-          "   *   from WebPlatform.org.",
+          "   * * [Window.outerWidth](https://developer.mozilla.org/en-US/docs/Web/API/Window/outerWidth)",
+          "   *   from MDN.",
           "   */"
         ],
         "pagehideEvent": [
@@ -3820,8 +3821,8 @@
           "   *",
           "   * ## Other resources",
           "   *",
-          "   * * [Window resizeBy](http://docs.webplatform.org/wiki/dom/methods/resizeBy)",
-          "   *   from WebPlatform.org.",
+          "   * * [Window.resizeBy](https://developer.mozilla.org/en-US/docs/Web/API/Window/resizeBy)",
+          "   *   from MDN.",
           "   */"
         ],
         "resizeEvent": [
@@ -3838,8 +3839,8 @@
           "   *",
           "   * ## Other resources",
           "   *",
-          "   * * [Window resizeTo](http://docs.webplatform.org/wiki/dom/methods/resizeTo)",
-          "   *   from WebPlatform.org.",
+          "   * * [Window.resizeTo](https://developer.mozilla.org/en-US/docs/Web/API/Window/resizeTo)",
+          "   *   from MDN.",
           "   */"
         ],
         "screen": [
@@ -3901,8 +3902,8 @@
           "   *",
           "   * ## Other resources",
           "   *",
-          "   * * [Window scroll](http://docs.webplatform.org/wiki/dom/methods/scroll)",
-          "   *   from WebPlatform.org.",
+          "   * * [Window.scroll](https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll)",
+          "   *   from MDN.",
           "   */"
         ],
         "scrollbars": [
@@ -3922,8 +3923,8 @@
           "   *",
           "   * ## Other resources",
           "   *",
-          "   * * [Window scrollBy](http://docs.webplatform.org/wiki/dom/methods/scrollBy)",
-          "   *   from WebPlatform.org.",
+          "   * * [Window.scrollBy](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy)",
+          "   *   from MDN.",
           "   */"
         ],
         "scrollTo": [
@@ -3934,8 +3935,8 @@
           "   *",
           "   * ## Other resources",
           "   *",
-          "   * * [Window scrollTo](http://docs.webplatform.org/wiki/dom/methods/scrollTo)",
-          "   *   from WebPlatform.org.",
+          "   * * [Window.scrollTo](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo)",
+          "   *   from MDN.",
           "   */"
         ],
         "self": [
@@ -4211,7 +4212,7 @@
           "   * response.",
           "   *",
           "   * This value must be set before the request has been sent. See also the list",
-          "   * of [IANA Official MIME types](https://www.iana.org/assignments/media-types/media-types.xhtml)",
+          "   * of [IANA Official MIME types](https://www.iana.org/assignments/media-types/media-types.xhtml).",
           "   */"
         ],
         "readyState": [
diff --git a/tools/dom/dom.json b/tools/dom/dom.json
index 071dc8f..a63e560 100644
--- a/tools/dom/dom.json
+++ b/tools/dom/dom.json
@@ -7478,7 +7478,7 @@
         "comment": "http://dev.w3.org/csswg/cssom-view/#widl-Element-scrollIntoView-void-boolean-top"
       },
       "scrollIntoViewIfNeeded": {
-        "comment": "http://docs.webplatform.org/wiki/dom/methods/scrollIntoViewIfNeeded",
+        "comment": "https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded",
         "support_level": "nonstandard"
       },
       "scrollLeft": {},
@@ -31541,4 +31541,4 @@
     },
     "support_level": "nonstandard"
   }
-}
\ No newline at end of file
+}
diff --git a/tools/dom/src/EventStreamProvider.dart b/tools/dom/src/EventStreamProvider.dart
index 9ca2cf9..1732c71 100644
--- a/tools/dom/src/EventStreamProvider.dart
+++ b/tools/dom/src/EventStreamProvider.dart
@@ -31,7 +31,8 @@
    *
    * See also:
    *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   * * [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
+   *   from MDN.
    */
   Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
       new _EventStream<T>(e, _eventType, useCapture);
@@ -55,7 +56,8 @@
    *
    * See also:
    *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   * * [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
+   *   from MDN.
    */
   ElementStream<T> forElement(Element e, {bool useCapture: false}) {
     return new _ElementEventStreamImpl<T>(e, _eventType, useCapture);
@@ -73,7 +75,8 @@
    *
    * See also:
    *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   * * [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
+   *   from MDN.
    */
   ElementStream<T> _forElementList(ElementList<Element> e,
       {bool useCapture: false}) {
diff --git a/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate b/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
index e64c887..706bc06 100644
--- a/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
@@ -75,8 +75,8 @@
  * check out
  * [Use IndexedDB](http://www.dartlang.org/docs/tutorials/indexeddb/).
  *
- * [IndexedDB reference](http://docs.webplatform.org/wiki/apis/indexeddb)
- * provides wiki-style docs about indexedDB
+ * MDN provides [API
+ * documentation](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API).
  *
  * {@category Web}
  */
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 0b740f3..35bd16f 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -677,8 +677,10 @@
    *
    * See also:
    *
-   * * [CSS Inheritance and Cascade](http://docs.webplatform.org/wiki/tutorials/inheritance_and_cascade)
-   * * [Pseudo-elements](http://docs.webplatform.org/wiki/css/selectors/pseudo-elements)
+   * * [Cascade and Inheritance](https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS/Cascade_and_inheritance)
+   *   from MDN.
+   * * [Pseudo-elements](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements)
+   *   from MDN.
    */
   CssStyleDeclaration getComputedStyle([String pseudoElement]) {
     if (pseudoElement == null) {
@@ -859,8 +861,10 @@
    *
    * See also:
    *
-   * * [scrollIntoView](http://docs.webplatform.org/wiki/dom/methods/scrollIntoView)
-   * * [scrollIntoViewIfNeeded](http://docs.webplatform.org/wiki/dom/methods/scrollIntoViewIfNeeded)
+   * * [scrollIntoView](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView)
+   *   from MDN.
+   * * [scrollIntoViewIfNeeded](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded)
+   *   from MDN.
    */
   void scrollIntoView([ScrollAlignment alignment]) {
     var hasScrollIntoViewIfNeeded = true;
diff --git a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
index 6ad09ec..5c9f937 100644
--- a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
@@ -49,9 +49,9 @@
    *
    * ## Other resources
    *
-   * * [Using the fullscreen
-   *   API](http://docs.webplatform.org/wiki/tutorials/using_the_full-screen_api)
-   *   from WebPlatform.org.
+   * * [Fullscreen
+   *   API](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API)
+   *   from MDN.
    * * [Fullscreen specification](http://www.w3.org/TR/fullscreen/) from W3C.
    */
   @SupportedBrowser(SupportedBrowser.CHROME)
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index 6575f86..59d3c33 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -54,8 +54,6 @@
    *
    * * [Window.open](https://developer.mozilla.org/en-US/docs/Web/API/Window.open)
    *   from MDN.
-   * * [Window open](http://docs.webplatform.org/wiki/dom/methods/open)
-   *   from WebPlatform.org.
    */
   WindowBase open(String url, String name, [String options]) {
     if (options == null) {
diff --git a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
index 97b141a..c15f496 100644
--- a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
+++ b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
@@ -56,9 +56,6 @@
   /**
    * Creates a GET request for the specified [url].
    *
-   * The server response must be a `text/` mime type for this request to
-   * succeed.
-   *
    * This is similar to [request] but specialized for HTTP GET requests which
    * return text content.
    *
@@ -69,7 +66,7 @@
    *     var name = Uri.encodeQueryComponent('John');
    *     var id = Uri.encodeQueryComponent('42');
    *     HttpRequest.getString('users.json?name=$name&id=$id')
-   *       .then((HttpRequest resp) {
+   *       .then((String resp) {
    *         // Do something with the response.
    *     });
    *
@@ -86,8 +83,8 @@
   /**
    * Makes a server POST request with the specified data encoded as form data.
    *
-   * This is roughly the POST equivalent of getString. This method is similar
-   * to sending a FormData object with broader browser support but limited to
+   * This is roughly the POST equivalent of [getString]. This method is similar
+   * to sending a [FormData] object with broader browser support but limited to
    * String values.
    *
    * If [data] is supplied, the key/value pairs are URI encoded with
@@ -369,11 +366,11 @@
    * Specify the desired `url`, and `method` to use in making the request.
    *
    * By default the request is done asyncronously, with no user or password
-   * authentication information. If `async` is false, the request will be send
+   * authentication information. If `async` is false, the request will be sent
    * synchronously.
    *
    * Calling `open` again on a currently active request is equivalent to
-   * calling `abort`.
+   * calling [abort].
    *
    * Note: Most simple HTTP requests can be accomplished using the [getString],
    * [request], [requestCrossOrigin], or [postFormData] methods. Use of this
diff --git a/tools/linux_dist_support/debian/control b/tools/linux_dist_support/debian/control
index b484bd2..04484ab 100644
--- a/tools/linux_dist_support/debian/control
+++ b/tools/linux_dist_support/debian/control
@@ -1,5 +1,5 @@
 Source: dart
-Maintainer: Soren Gjesse <sgjesse@google.com>
+Maintainer: William Hesse <whesse@google.com>
 Section: misc
 Priority: optional
 Standards-Version: 3.9.2
@@ -7,6 +7,6 @@
 	python,
 
 Package: dart
-Architecture: amd64 i386 armhf armel
+Architecture: amd64
 Depends: ${shlibs:Depends}, ${misc:Depends}
 Description: Dart SDK
diff --git a/tools/test.dart b/tools/test.dart
new file mode 100755
index 0000000..5914e5f
--- /dev/null
+++ b/tools/test.dart
@@ -0,0 +1,275 @@
+#!/usr/bin/env dart
+// 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.
+
+// Run tests like on the given builder.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:args/args.dart';
+
+import 'bots/results.dart';
+
+const int deflakingCount = 5;
+
+/// Returns the operating system of a builder.
+String systemOfBuilder(String builder) {
+  return builder.split("-").firstWhere(
+      (component) => ["linux", "mac", "win"].contains(component),
+      orElse: () => null);
+}
+
+/// Returns the product mode of a builder.
+String modeOfBuilder(String builder) {
+  return builder.split("-").firstWhere(
+      (component) => ["debug", "product", "release"].contains(component),
+      orElse: () => null);
+}
+
+/// Returns the machine architecture of a builder.
+String archOfBuilder(String builder) {
+  return builder.split("-").firstWhere(
+      (component) => [
+            "arm",
+            "arm64",
+            "armsimdbc",
+            "armsimdbc64",
+            "ia32",
+            "simarm",
+            "simarm64",
+            "simdbc",
+            "simdbc64",
+            "x64",
+          ].contains(component),
+      orElse: () => null);
+}
+
+/// Returns the runtime environment of a builder.
+String runtimeOfBuilder(String builder) {
+  return builder.split("-").firstWhere(
+      (component) => ["chrome", "d8", "edge", "firefox", "ie11", "safari"]
+          .contains(component),
+      orElse: () => null);
+}
+
+/// Expands a variable in a test matrix step command.
+String expandVariable(String string, String variable, String value) {
+  return string.replaceAll("\${$variable}", value ?? "");
+}
+
+/// Expands all variables in a test matrix step command.
+String expandVariables(String string, String builder) {
+  string = expandVariable(string, "system", systemOfBuilder(builder));
+  string = expandVariable(string, "mode", modeOfBuilder(builder));
+  string = expandVariable(string, "arch", archOfBuilder(builder));
+  string = expandVariable(string, "runtime", runtimeOfBuilder(builder));
+  return string;
+}
+
+/// Locates the merge base between head and the [branch] on the given [remote].
+/// If a particular [commit] was requested, use that.
+Future<String> findMergeBase(
+    String commit, String remote, String branch) async {
+  if (commit != null) {
+    return commit;
+  }
+  final arguments = ["merge-base", "$remote/$branch", "HEAD"];
+  final result = await Process.run("git", arguments);
+  if (result.exitCode != 0) {
+    throw new Exception("Failed to run: git ${arguments.join(' ')}\n"
+        "stdout:\n${result.stdout}\n"
+        "stderr:\n${result.stderr}\n");
+  }
+  return LineSplitter.split(result.stdout).first;
+}
+
+/// Locates the build number of the [commit] on the [builder], or throws an
+/// exception if the builder hasn't built the commit.
+Future<int> buildNumberOfCommit(String builder, String commit) async {
+  final requestUrl = Uri.parse(
+      "https://cr-buildbucket.appspot.com/_ah/api/buildbucket/v1/search"
+      "?bucket=luci.dart.ci.sandbox"
+      "&tag=builder%3A$builder"
+      "&tag=buildset%3Acommit%2Fgit%2F$commit"
+      "&fields=builds(status%2Ctags%2Curl)");
+  final client = new HttpClient();
+  final request = await client.getUrl(requestUrl);
+  final response = await request.close();
+  final Map<String, dynamic> object = await response
+      .transform(new Utf8Decoder())
+      .transform(new JsonDecoder())
+      .first;
+  client.close();
+  final builds = object["builds"];
+  if (builds.isEmpty) {
+    throw new Exception("Builder $builder hasn't built commit $commit");
+  }
+  final build = builds.last;
+  final tags = (build["tags"] as List).cast<String>();
+  final buildAddressTag =
+      tags.firstWhere((tag) => tag.startsWith("build_address:"));
+  final buildAddress = buildAddressTag.substring("build_address:".length);
+  if (build["status"] != "COMPLETED") {
+    throw new Exception("Build $buildAddress isn't completed yet");
+  }
+  return int.parse(buildAddress.split("/").last);
+}
+
+void main(List<String> args) async {
+  final parser = new ArgParser();
+  parser.addOption("builder",
+      abbr: "b", help: "Run tests like on the given buider");
+  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.addOption("remote",
+      abbr: "R",
+      help: "Compare with this remote and git branch",
+      defaultsTo: "origin");
+  parser.addFlag("help", help: "Show the program usage.", negatable: false);
+
+  final options = parser.parse(args);
+  if (options["help"] || options["builder"] == null) {
+    print("""
+Usage: test.dart -b [BUILDER] [OPTION]...
+Run tests and compare with the results on the given builder.
+
+${parser.usage}""");
+    return;
+  }
+
+  final builder = options["builder"];
+
+  // Find out where the current HEAD branched.
+  final commit = await findMergeBase(
+      options["commit"], options["remote"], options["branch"]);
+  print("Base commit is $commit");
+
+  // Use the buildbucket API to search for builds of the right rcommit.
+  print("Finding build to compare with...");
+  final buildNumber = await buildNumberOfCommit(builder, commit);
+  print("Comparing with build $buildNumber on $builder");
+
+  final outDirectory = await Directory.systemTemp.createTemp("test.dart.");
+  try {
+    // Download the previous results and flakiness info from cloud storage.
+    print("Downloading previous results...");
+    await cpGsutil(
+        buildFileCloudPath(builder, buildNumber.toString(), "results.json"),
+        "${outDirectory.path}/previous.json");
+    await cpGsutil(
+        buildFileCloudPath(builder, buildNumber.toString(), "flaky.json"),
+        "${outDirectory.path}/flaky.json");
+    print("Downloaded previous results");
+
+    // Load the test matrix.
+    final scriptPath = Platform.script.toFilePath();
+    final testMatrixPath =
+        scriptPath.substring(0, scriptPath.length - "test.dart".length) +
+            "bots/test_matrix.json";
+    final testMatrix =
+        jsonDecode(await new File(testMatrixPath).readAsString());
+
+    // Find the appropriate test.py steps.
+    final buildersConfigurations = testMatrix["builder_configurations"];
+    final builderConfiguration = buildersConfigurations.firstWhere(
+        (builderConfiguration) =>
+            (builderConfiguration["builders"] as List).contains(builder));
+    final steps = (builderConfiguration["steps"] as List).cast<Map>();
+    final testSteps = steps
+        .where((step) =>
+            !step.containsKey("script") || step["script"] == "tools/test.py")
+        .toList();
+
+    // Run each step like the builder would, deflaking tests that need it.
+    final stepResultsPaths = <String>[];
+    for (int stepIndex = 0; stepIndex < testSteps.length; stepIndex++) {
+      // Run the test step.
+      final testStep = testSteps[stepIndex];
+      final stepName = testStep["name"];
+      final stepDirectory = new Directory("${outDirectory.path}/$stepIndex");
+      await stepDirectory.create();
+      final stepArguments = testStep["arguments"]
+          .map((argument) => expandVariables(argument, builder))
+          .toList()
+          .cast<String>();
+      final fullArguments = <String>[]
+        ..addAll(stepArguments)
+        ..addAll(
+            ["--output-directory=${stepDirectory.path}", "--write-results"])
+        ..addAll(options.rest);
+      print("$stepName: Running tests");
+      final testProcess = await Process.start("tools/test.py", fullArguments);
+      await testProcess.exitCode;
+      stepResultsPaths.add("${stepDirectory.path}/results.json");
+      // Find the list of tests to deflake.
+      final deflakeListOutput = await Process.run(Platform.resolvedExecutable, [
+        "tools/bots/compare_results.dart",
+        "--changed",
+        "--failing",
+        "--passing",
+        "--flakiness-data=${outDirectory.path}/flaky.json",
+        "${outDirectory.path}/previous.json",
+        "${stepDirectory.path}/results.json"
+      ]);
+      final deflakeListPath = "${stepDirectory.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("$stepName: Running deflaking iteration $i");
+        final deflakeDirectory = new Directory("${stepDirectory.path}/$i");
+        await deflakeDirectory.create();
+        final deflakeArguments = <String>[]
+          ..addAll(stepArguments)
+          ..addAll([
+            "--output-directory=${deflakeDirectory.path}",
+            "--write-results",
+            "--test-list=$deflakeListPath"
+          ])
+          ..addAll(options.rest);
+        final deflakeProcess =
+            await Process.start("tools/test.py", deflakeArguments);
+        await deflakeProcess.exitCode;
+        deflakingResultsPaths.add("${deflakeDirectory.path}/results.json");
+      }
+      // Update the flakiness information based on what we've learned.
+      print("$stepName: Updating flakiness information");
+      await Process.run(
+          "tools/bots/update_flakiness.dart",
+          [
+            "--input=${outDirectory.path}/flaky.json",
+            "--output=${outDirectory.path}/flaky.json",
+            "${stepDirectory.path}/results.json",
+          ]..addAll(deflakingResultsPaths));
+    }
+    // Collect all the results from all the steps.
+    await new File("${outDirectory.path}/results.json").writeAsString(
+        stepResultsPaths
+            .map((path) => new File(path).readAsStringSync())
+            .join(""));
+    // Write out the final comparison.
+    print("");
+    final compareOutput = await Process.run("tools/bots/compare_results.dart", [
+      "--human",
+      "--verbose",
+      "--changed",
+      "--failing",
+      "--passing",
+      "--flakiness-data=${outDirectory.path}/flaky.json",
+      "${outDirectory.path}/previous.json",
+      "${outDirectory.path}/results.json"
+    ]);
+    stdout.write(compareOutput.stdout);
+  } finally {
+    await outDirectory.delete(recursive: true);
+  }
+}
diff --git a/tools/testing/dart/browser_controller.dart b/tools/testing/dart/browser_controller.dart
index faa77d7..8b701a3 100644
--- a/tools/testing/dart/browser_controller.dart
+++ b/tools/testing/dart/browser_controller.dart
@@ -538,12 +538,24 @@
     });
   }
 
-  // Clears the recovery cache if the static resetBrowserConfiguration flag is
-  // set.
-  Future<bool> resetConfiguration() {
-    if (!Browser.resetBrowserConfiguration) return new Future.value(true);
-    var localAppData = Platform.environment['LOCALAPPDATA'];
+  // Clears the recovery cache and allows popups on localhost if the static
+  // resetBrowserConfiguration flag is set.
+  Future<bool> resetConfiguration() async {
+    if (!Browser.resetBrowserConfiguration) return true;
+    // todo(athom) Move this into the puppet configuration
+    var args = [
+      "add",
+      r"HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\New Windows\Allow",
+      "/v",
+      "127.0.0.1",
+      "/f"
+    ];
+    var result = await Process.run("reg", args);
+    if (result.exitCode != 0) {
+      _logEvent("Failed to override user popup blocker settings");
+    }
 
+    var localAppData = Platform.environment['LOCALAPPDATA'];
     Directory dir = new Directory("$localAppData\\Microsoft\\"
         "Internet Explorer\\Recovery");
     return dir.delete(recursive: true).then((_) {
@@ -1676,9 +1688,12 @@
         'stdout: ${result.stdout}\n'
         'stderr: ${result.stderr}');
   } else {
+    final gsutilScript = Platform.script
+        .resolve('../../../third_party/gsutil/gsutil.py')
+        .toFilePath();
     final storageUrl = 'gs://dart-temp-crash-archive/$screenshotName';
     final args = [
-      r'e:\b\depot_tools\gsutil.py',
+      gsutilScript,
       'cp',
       screenshotFile,
       storageUrl,
diff --git a/tools/testing/dart/command.dart b/tools/testing/dart/command.dart
index fecadb4..b91201d 100644
--- a/tools/testing/dart/command.dart
+++ b/tools/testing/dart/command.dart
@@ -351,6 +351,7 @@
   @override
   List<String> get batchArguments {
     return <String>[
+      '--enable-asserts',
       _compilerLocation.resolve("batch.dart").toFilePath(),
     ];
   }
diff --git a/tools/testing/dart/command_output.dart b/tools/testing/dart/command_output.dart
index d26a4dd..b4a0980 100644
--- a/tools/testing/dart/command_output.dart
+++ b/tools/testing/dart/command_output.dart
@@ -75,6 +75,10 @@
       // std::abort terminates with exit code 3 on Windows.
       if (exitCode == 3 || exitCode == browserCrashExitCode) return true;
 
+      // When VM is built with Crashpad support we get STATUS_FATAL_APP_EXIT
+      // for all crashes that Crashpad has intercepted.
+      if (exitCode == 0x40000015) return true;
+
       // If a program receives an uncaught system exception, the program
       // terminates with the exception code as exit code.
       // https://msdn.microsoft.com/en-us/library/cc704588.aspx lists status
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 159398e..8fe7756 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -1108,6 +1108,7 @@
     if (_configuration.useKernelBytecode) {
       args.add('--gen-bytecode');
       args.add('--drop-ast');
+      args.add('--emit-bytecode-source-positions');
     }
 
     return Command.vmKernelCompilation(dillFile, true, bootstrapDependencies(),
@@ -1166,7 +1167,7 @@
         Uri.base.resolveUri(new Uri.directory(tempDir)).resolve("out.dill");
     var outputFileName = output.toFilePath();
 
-    var compilerArguments = <String>[];
+    var compilerArguments = <String>['--verify'];
     if (_isLegacy) {
       compilerArguments.add("--legacy-mode");
     }
diff --git a/tools/testing/dart/configuration.dart b/tools/testing/dart/configuration.dart
index ab0a075..3568239 100644
--- a/tools/testing/dart/configuration.dart
+++ b/tools/testing/dart/configuration.dart
@@ -44,6 +44,7 @@
       this.writeTestOutcomeLog,
       this.writeResultLog,
       this.writeResults,
+      this.writeLogs,
       this.drtPath,
       this.chromePath,
       this.safariPath,
@@ -95,6 +96,7 @@
   final bool writeTestOutcomeLog;
   final bool writeResultLog;
   final bool writeResults;
+  final bool writeLogs;
   final bool printPassingStdout;
 
   Architecture get architecture => configuration.architecture;
diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart
index 6deef00..7ebecad 100644
--- a/tools/testing/dart/options.dart
+++ b/tools/testing/dart/options.dart
@@ -263,6 +263,11 @@
         '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',
+        hide: true),
+    new _Option.bool(
         'reset_browser_configuration',
         '''Browser specific reset of configuration.
 
@@ -351,6 +356,7 @@
     'tasks',
     'time',
     'verbose',
+    'write_logs',
     'write_debug_log',
     'write_test_outcome_log',
     'write_result_log',
@@ -686,6 +692,7 @@
                 writeTestOutcomeLog: data["write_test_outcome_log"] as bool,
                 writeResultLog: data["write_result_log"] as bool,
                 writeResults: data["write_results"] as bool,
+                writeLogs: data["write_logs"] as bool,
                 drtPath: data["drt"] as String,
                 chromePath: data["chrome"] as String,
                 safariPath: data["safari"] as String,
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index f995ea7..99dd4f9 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -244,6 +244,13 @@
         var arch = test.configuration.architecture.name;
         var archived = "binary.${mode}_${arch}_${binBaseName}";
         TestUtils.copyFile(new Path(binName), new Path(archived));
+        // On Windows also copy PDB file for the binary.
+        if (Platform.isWindows) {
+          final pdbPath = new Path("$binName.pdb");
+          if (new File(pdbPath.toNativePath()).existsSync()) {
+            TestUtils.copyFile(pdbPath, new Path("$archived.pdb"));
+          }
+        }
         archivedBinaries[binName] = archived;
       }
 
@@ -677,7 +684,23 @@
     [Formatter formatter = Formatter.normal]) {
   var lines = <String>[];
   var output = new OutputWriter(formatter, lines);
+  _writeFailureStatus(test, formatter, output);
+  _writeFailureOutput(test, formatter, output);
+  _writeFailureReproductionCommands(test, formatter, output);
+  return lines;
+}
 
+List<String> _buildFailureLog(TestCase test) {
+  final formatter = Formatter.normal;
+  final lines = <String>[];
+  final output = new OutputWriter(formatter, lines);
+  _writeFailureOutput(test, formatter, output);
+  _writeFailureReproductionCommands(test, formatter, output);
+  return lines;
+}
+
+void _writeFailureStatus(
+    TestCase test, Formatter formatter, OutputWriter output) {
   output.write('');
   output.write(formatter
       .failed('FAILED: ${test.configurationString} ${test.displayName}'));
@@ -685,7 +708,7 @@
   output.write('Expected: ${test.expectedOutcomes.join(" ")}');
   output.write('Actual: ${test.result}');
 
-  var ranAllCommands = test.commandOutputs.length == test.commands.length;
+  final ranAllCommands = test.commandOutputs.length == test.commands.length;
   if (!test.lastCommandOutput.hasTimedOut) {
     if (!ranAllCommands && !test.expectCompileError) {
       output.write('Unexpected compile error.');
@@ -701,7 +724,10 @@
       }
     }
   }
+}
 
+void _writeFailureOutput(
+    TestCase test, Formatter formatter, OutputWriter output) {
   for (var i = 0; i < test.commands.length; i++) {
     var command = test.commands[i];
     var commandOutput = test.commandOutputs[command];
@@ -712,7 +738,11 @@
     output.write(command.toString());
     commandOutput.describe(test.configuration.progress, output);
   }
+}
 
+void _writeFailureReproductionCommands(
+    TestCase test, Formatter formatter, OutputWriter output) {
+  final ranAllCommands = test.commandOutputs.length == test.commands.length;
   if (test.configuration.runtime.isBrowser && ranAllCommands) {
     // Additional command for rerunning the steps locally after the fact.
     output.section('To debug locally, run');
@@ -730,7 +760,6 @@
   arguments.add(test.displayName);
 
   output.write(arguments.map(escapeCommandLineArgument).join(' '));
-  return lines;
 }
 
 String _buildSummaryEnd(Formatter formatter, int failedTests) {
@@ -833,6 +862,7 @@
 class ResultWriter extends EventListener {
   final TestConfiguration _configuration;
   final List<Map> _results = [];
+  final List<Map> _logs = [];
   final String _outputDirectory;
   final Stopwatch _startStopwatch;
   final DateTime _startTime;
@@ -843,9 +873,13 @@
   void allTestsKnown() {
     // Write an empty result log file, that will be overwritten if any tests
     // are actually run, when the allDone event handler is invoked.
-    writeResultsFile([]);
+    writeOutputFile([], TestUtils.resultsFileName);
+    writeOutputFile([], TestUtils.logsFileName);
   }
 
+  String newlineTerminated(Iterable<String> lines) =>
+      lines.map((l) => l + '\n').join();
+
   void done(TestCase test) {
     if (_configuration != test.configuration) {
       throw new Exception("Two configurations in the same run. "
@@ -858,7 +892,7 @@
     Duration time =
         test.commandOutputs.values.fold(Duration.zero, (d, o) => d + o.time);
 
-    var record = {
+    final record = {
       "name": name,
       "configuration": _configuration.configuration.name,
       "suite": suite,
@@ -869,19 +903,28 @@
       "matches": test.realResult.canBeOutcomeOf(test.realExpected)
     };
     _results.add(record);
+    if (test.configuration.writeLogs && record['matches'] != true) {
+      final log = {
+        'name': name,
+        'configuration': record['configuration'],
+        'result': record['result'],
+        'log': newlineTerminated(_buildFailureLog(test))
+      };
+      _logs.add(log);
+    }
   }
 
   void allDone() {
-    writeResultsFile(_results);
+    writeOutputFile(_results, TestUtils.resultsFileName);
+    writeOutputFile(_logs, TestUtils.logsFileName);
     writeRunFile();
   }
 
-  void writeResultsFile(List<Map> results) {
+  void writeOutputFile(List<Map> results, String fileName) {
     if (_outputDirectory == null) return;
-    final path =
-        Uri.directory(_outputDirectory).resolve(TestUtils.resultsFileName);
-    String jsonLine(Map x) => jsonEncode(x) + '\n';
-    File.fromUri(path).writeAsStringSync(results.map(jsonLine).join());
+    final path = Uri.directory(_outputDirectory).resolve(fileName);
+    File.fromUri(path)
+        .writeAsStringSync(newlineTerminated(results.map(jsonEncode)));
   }
 
   void writeRunFile() {
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 96533ad..4a76a66 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -130,7 +130,7 @@
     };
     if (configuration.copyCoreDumps && Platform.isWindows) {
       _environmentOverrides['DART_CRASHPAD_HANDLER'] =
-          new Path(buildDir + '/crashpad_handler.exe').toNativePath();
+          new Path(buildDir + '/crashpad_handler.exe').absolute.toNativePath();
     }
   }
 
@@ -446,12 +446,13 @@
   VMTestSuite(TestConfiguration configuration)
       : dartDir = Repository.dir.toNativePath(),
         super(configuration, "vm", ["runtime/tests/vm/vm.status"]) {
+    var binarySuffix = Platform.operatingSystem == 'windows' ? '.exe' : '';
+
     // For running the tests we use the given '$runnerName' binary
-    targetRunnerPath = '$buildDir/run_vm_tests';
+    targetRunnerPath = '$buildDir/run_vm_tests$binarySuffix';
 
     // For listing the tests we use the '$runnerName.host' binary if it exists
     // and use '$runnerName' if it doesn't.
-    var binarySuffix = Platform.operatingSystem == 'windows' ? '.exe' : '';
     var hostBinary = '$targetRunnerPath.host$binarySuffix';
     if (new File(hostBinary).existsSync()) {
       hostRunnerPath = hostBinary;
@@ -484,8 +485,11 @@
   void _addTest(ExpectationSet testExpectations, String testName) {
     var args = configuration.standardOptions.toList();
     if (configuration.compilerConfiguration.previewDart2) {
+      final dfePath = new Path("$buildDir/gen/kernel-service.dart.snapshot")
+          .absolute
+          .toNativePath();
       // '--dfe' has to be the first argument for run_vm_test to pick it up.
-      args.insert(0, '--dfe=$buildDir/gen/kernel-service.dart.snapshot');
+      args.insert(0, '--dfe=$dfePath');
     }
 
     args.add(testName);
@@ -710,6 +714,11 @@
     // TestSuite.enqueueNewTestCase().
     if (_testListPossibleFilenames?.contains(filename) == false) return;
     bool match = false;
+    // Note: have to use Path instead of a filename for matching because
+    // on Windows we need to convert backward slashes to forward slashes.
+    // Our display test names (and filters) are given using forward slashes
+    // while filenames on Windows use backwards slashes.
+    final Path filePath = new Path(filename);
     for (var regex in configuration.selectors.values) {
       String pattern = regex.pattern;
       if (pattern.contains("/")) {
@@ -722,13 +731,12 @@
       if (pattern != regex.pattern) {
         regex = new RegExp(pattern);
       }
-      if (regex.hasMatch(filename)) match = true;
+      if (regex.hasMatch(filePath.toString())) match = true;
       if (match) break;
     }
     if (!match) return;
 
     if (!isTestFile(filename)) return;
-    Path filePath = new Path(filename);
 
     var optionsFromFile = readOptionsFromFile(new Uri.file(filename));
     CreateTest createTestCase = makeTestCaseCreator(optionsFromFile);
diff --git a/tools/testing/dart/utils.dart b/tools/testing/dart/utils.dart
index 35a2b1a..a8378cf 100644
--- a/tools/testing/dart/utils.dart
+++ b/tools/testing/dart/utils.dart
@@ -469,22 +469,26 @@
   /// file can be made visible in the waterfall UI.
   static const flakyFileName = ".flaky.log";
 
-  /// If test.py was invoked with '--write-test-outcome-log it will write
+  /// If test.py was invoked with '--write-test-outcome-log' it will write
   /// test outcomes to this file.
   static const testOutcomeFileName = ".test-outcome.log";
 
-  /// If test.py was invoked with '--write-result-log it will write
+  /// If test.py was invoked with '--write-result-log' it will write
   /// test outcomes to this file in the '--output-directory'.
   static const resultLogFileName = "result.log";
 
-  /// If test.py was invoked with '--write-results it will write
+  /// If test.py was invoked with '--write-results' it will write
   /// test outcomes to this file in the '--output-directory'.
   static const resultsFileName = "results.json";
 
-  /// If test.py was invoked with '--write-results it will write
+  /// If test.py was invoked with '--write-results' it will write
   /// data about this run of test.py to this file in the '--output-directory'.
   static const resultsInstanceFileName = "run.json";
 
+  /// If test.py was invoked with '--write-results' and '--write-logs", save
+  /// the stdout and stderr to this file in the '--output-directory'.
+  static const logsFileName = "logs.json";
+
   static void ensureExists(String filename, TestConfiguration configuration) {
     if (!configuration.listTests && !existsCache.doesFileExist(filename)) {
       throw "'$filename' does not exist";
diff --git a/tools/utils.py b/tools/utils.py
index c550045..ac9dcbf 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -779,11 +779,20 @@
     pass
 
   def __enter__(self):
+    print "INFO: Enabling coredump archiving into %s" % (WindowsCoreDumpEnabler.CRASHPAD_DB_FOLDER)
     os.environ['DART_CRASHPAD_CRASHES_DIR'] = WindowsCoreDumpEnabler.CRASHPAD_DB_FOLDER
 
   def __exit__(self, *_):
     del os.environ['DART_CRASHPAD_CRASHES_DIR']
 
+
+def TryUnlink(file):
+  try:
+    os.unlink(file)
+  except Exception as error:
+    print "ERROR: Failed to remove %s: %s" % (file, error)
+
+
 class BaseCoreDumpArchiver(object):
   """This class reads coredumps file written by UnexpectedCrashDumpArchiver
   into the current working directory and uploads all cores and binaries
@@ -799,9 +808,18 @@
     self._search_dir = search_dir
     self._output_directory = output_directory
 
+  def _safe_cleanup(self):
+    try:
+      return self._cleanup();
+    except Exception as error:
+      print "ERROR: Failure during cleanup: %s" % error
+      return False
+
   def __enter__(self):
+    print "INFO: Core dump archiving is activated"
+
     # Cleanup any stale files
-    if self._cleanup():
+    if self._safe_cleanup():
       print "WARNING: Found and removed stale coredumps"
 
   def __exit__(self, *_):
@@ -817,8 +835,20 @@
         sys.stdout.flush()
 
         self._archive(archive_crashes)
+      else:
+        print "INFO: No unexpected crashes recorded"
+        dumps = self._find_all_coredumps()
+        if dumps:
+          print "INFO: However there are %d core dumps found" % len(dumps)
+          for dump in dumps:
+            print "INFO:        -> %s" % dump
+          print
+    except Exception as error:
+      print "ERROR: Failed to archive crashes: %s" % error
+      raise
+
     finally:
-      self._cleanup()
+      self._safe_cleanup()
 
   def _archive(self, crashes):
     files = set()
@@ -830,16 +860,27 @@
         files.add(core)
       else:
         missing.append(crash)
-    if (self._output_directory is None
-        or os.environ.containsKey('BUILDBOT_BUILDERNAME')):
-      self._upload(files)
-    else:
-      # This is a sharded test run: copy the dump to the output_directory
+    if self._output_directory is not None and self._is_shard():
+      print (
+          "INFO: Copying collected dumps and binaries into output directory\n"
+          "INFO: They will be uploaded to isolate server. Look for \"isolated"
+          " out\" under the failed step on the build page.\n"
+          "INFO: For more information see runtime/docs/infra/coredumps.md")
       self._copy(files)
+    else:
+      print (
+          "INFO: Uploading collected dumps and binaries into Cloud Storage\n"
+          "INFO: Use `gsutil.py cp from-url to-path` to download them.\n"
+          "INFO: For more information see runtime/docs/infra/coredumps.md")
+      self._upload(files)
 
     if missing:
       self._report_missing_crashes(missing, throw=True)
 
+  # todo(athom): move the logic to decide where to copy core dumps into the recipes.
+  def _is_shard(self):
+    return 'BUILDBOT_BUILDERNAME' not in os.environ
+
   def _report_missing_crashes(self, missing, throw=True):
     missing_as_string = ', '.join([str(c) for c in missing])
     other_files = list(glob.glob(os.path.join(self._search_dir, '*')))
@@ -859,17 +900,24 @@
 
   def _tar(self, file):
     # Sanitize the name: actual cores follow 'core.%d' pattern, crashed
-    # binaries are copied next to cores and named 'binary.<binary_name>'.
+    # binaries are copied next to cores and named
+    # 'binary.<mode>_<arch>_<binary_name>'.
+    # This should match the code in testing/dart/test_progress.dart
     name = os.path.basename(file)
     (prefix, suffix) = name.split('.', 1)
-    if prefix == 'binary':
-      name = suffix
+    is_binary = prefix == 'binary'
+    if is_binary:
+      (mode, arch, binary_name) = suffix.split('_', 2)
+      name = binary_name
 
     tarname = '%s.tar.gz' % name
 
     # Compress the file.
     tar = tarfile.open(tarname, mode='w:gz')
     tar.add(file, arcname=name)
+    if is_binary and os.path.exists(file + '.pdb'):
+      # Also add a PDB file if there is one.
+      tar.add(file + '.pdb', arcname=name + '.pdb')
     tar.close()
     return tarname
 
@@ -894,9 +942,16 @@
       except Exception as error:
         print '!!! Failed to upload %s, error: %s' % (tarname, error)
 
-      os.unlink(tarname)
+      TryUnlink(tarname)
+
     print '--- Done ---\n'
 
+  def _find_all_coredumps(self):
+    """Return coredumps that were recorded (if supported by the platform).
+    This method will be overriden by concrete platform specific implementations.
+    """
+    return []
+
   def _find_unexpected_crashes(self):
     """Load coredumps file. Each line has the following format:
 
@@ -915,7 +970,8 @@
       found = True
     for binary in glob.glob(os.path.join(self._binaries_dir, 'binary.*')):
       found = True
-      os.unlink(binary)
+      TryUnlink(binary)
+
     return found
 
 class PosixCoreDumpArchiver(BaseCoreDumpArchiver):
@@ -926,10 +982,7 @@
     found = super(PosixCoreDumpArchiver, self)._cleanup()
     for core in glob.glob(os.path.join(self._search_dir, 'core.*')):
       found = True
-      try:
-        os.unlink(core)
-      except:
-        pass
+      TryUnlink(core)
     return found
 
   def _find_coredump_file(self, crash):
@@ -954,13 +1007,81 @@
         WindowsCoreDumpEnabler.DUMPS_FOLDER, output_directory)
     self._dumps_by_pid = None
 
+  # Find CDB.exe in the win_toolchain that we are using.
+  def _find_cdb(self):
+    win_toolchain_json_path = os.path.join(
+        DART_DIR, 'build', 'win_toolchain.json')
+    if not os.path.exists(win_toolchain_json_path):
+      return None
+
+    with open(win_toolchain_json_path, "r") as f:
+      win_toolchain_info = json.loads(f.read())
+
+    win_sdk_path = win_toolchain_info['win_sdk']
+
+    # We assume that we are running on 64-bit Windows.
+    # Note: x64 CDB can work with both X64 and IA32 dumps.
+    cdb_path = os.path.join(win_sdk_path, 'Debuggers', 'x64', 'cdb.exe')
+    if not os.path.exists(cdb_path):
+      return None
+
+    return cdb_path
+
+  CDBG_PROMPT_RE = re.compile(r'^\d+:\d+>')
+
+  def _dump_all_stacks(self):
+    # On Windows due to crashpad integration crashes do not produce any
+    # stacktraces. Dump stack traces from dumps Crashpad collected using
+    # CDB (if available).
+    cdb_path = self._find_cdb()
+    if cdb_path is None:
+      return
+
+    dumps = self._find_all_coredumps()
+    if not dumps:
+      return
+
+    print "### Collected %d crash dumps" % len(dumps)
+    for dump in dumps:
+      print
+      print "### Dumping stacks from %s using CDB" % dump
+      cdb_output = subprocess.check_output(
+          '"%s" -z "%s" -kqm -c "!uniqstack -b -v -p;qd"' % (cdb_path, dump),
+          stderr=subprocess.STDOUT)
+      # Extract output of uniqstack from the whole output of CDB.
+      output = False
+      for line in cdb_output.split('\n'):
+        if re.match(WindowsCoreDumpArchiver.CDBG_PROMPT_RE, line):
+          output = True
+        elif line.startswith("quit:"):
+          break
+        elif output:
+          print line
+    print
+    print "#############################################"
+    print
+
+
+  def __exit__(self, *args):
+    try:
+      self._dump_all_stacks()
+    except Exception as error:
+      print "ERROR: Unable to dump stacks from dumps: %s" % error
+
+    super(WindowsCoreDumpArchiver, self).__exit__(*args)
+
+
   def _cleanup(self):
     found = super(WindowsCoreDumpArchiver, self)._cleanup()
     for core in glob.glob(os.path.join(self._search_dir, '*')):
       found = True
-      os.unlink(core)
+      TryUnlink(core)
     return found
 
+  def _find_all_coredumps(self):
+    pattern = os.path.join(self._search_dir, '*.dmp')
+    return [core_filename for core_filename in glob.glob(pattern)]
+
   def _find_coredump_file(self, crash):
     if self._dumps_by_pid is None:
       # If this function is invoked the first time then look through the directory
diff --git a/utils/compiler/BUILD.gn b/utils/compiler/BUILD.gn
index d1614e3..f40512c 100644
--- a/utils/compiler/BUILD.gn
+++ b/utils/compiler/BUILD.gn
@@ -70,8 +70,7 @@
   main_dart = "$target_gen_dir/dart2js.dart"
   training_args = [
     "--packages=" + rebase_path("../../.packages"),
-    "--library-root=" + rebase_path("../../sdk"),
-    "--categories=all",
+    "--libraries-spec=" + rebase_path("../../sdk/lib/libraries.json"),
     rebase_path("$target_gen_dir/dart2js.dart"),
   ]
 }