Version 2.16.0-118.0.dev

Merge commit '8784f9682db022d5ed59ae3108db6bfd999aa0b9' into 'dev'
diff --git a/BUILD.gn b/BUILD.gn
index 338f5ec..ad09ed8 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -50,16 +50,6 @@
     "utils/kernel-service:kernel-service",
   ]
 
-  # We do not support AOT on ia32 and should therefore cannot provide native
-  # snapshot tooling.
-  if (dart_target_arch != "ia32") {
-    if (is_product) {
-      deps += [ "runtime/bin:analyze_snapshot_product" ]
-    } else {
-      deps += [ "runtime/bin:analyze_snapshot" ]
-    }
-  }
-
   # TODO(bkonyi): this dep causes a segfault on Android XARM_X64 builds.
   # See issue #41776.
   if (dart_target_arch != "arm") {
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api.dart
new file mode 100644
index 0000000..5d5c262
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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';
+
+part 'api/builders.dart';
+part 'api/code.dart';
+part 'api/introspection.dart';
+part 'api/macros.dart';
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
new file mode 100644
index 0000000..74bf73c
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
@@ -0,0 +1,159 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 '../api.dart';
+
+/// The base interface used to add declarations to the program as well
+/// as augment existing ones.
+abstract class Builder {}
+
+/// The api used by [Macro]s to contribute new type declarations to the
+/// current library, and get [TypeAnnotation]s from runtime [Type] objects.
+abstract class TypeBuilder implements Builder {
+  /// Adds a new type declaration to the surrounding library.
+  void declareType(DeclarationCode typeDeclaration);
+}
+
+/// The interface to resolve a [TypeAnnotation] to a [StaticType].
+///
+/// The [StaticType]s can be compared against other [StaticType]s to see how
+/// they relate to each other.
+///
+/// This api is only available to the declaration and definition phases of
+/// macro expansion.
+abstract class TypeResolver {
+  /// Resolves [typeAnnotation] to a [StaticType].
+  ///
+  /// Throws an error if the type annotation cannot be resolved. This should
+  /// only happen in the case of incomplete or invalid programs, but macros
+  /// may be asked to run in this state during the development cycle. It is
+  /// helpful for users if macros provide a best effort implementation in that
+  /// case or handle the error in a useful way.
+  Future<StaticType> resolve(TypeAnnotation typeAnnotation);
+}
+
+/// The api used to introspect on a [ClassDeclaration].
+///
+/// Available in the declaration and definition phases, but limited in the
+/// declaration phase to immediately annotated [ClassDeclaration]s. This is
+/// done by limiting the access to the [TypeDeclarationResolver] to the
+/// definition phase.
+abstract class ClassIntrospector {
+  /// The fields available for [clazz].
+  ///
+  /// This may be incomplete if in the declaration phase and additional macros
+  /// are going to run on this class.
+  Future<List<FieldDeclaration>> fieldsOf(ClassDeclaration clazz);
+
+  /// The methods available so far for the current class.
+  ///
+  /// This may be incomplete if additional declaration macros are running on
+  /// this class.
+  Future<List<MethodDeclaration>> methodsOf(ClassDeclaration clazz);
+
+  /// The constructors available so far for the current class.
+  ///
+  /// This may be incomplete if additional declaration macros are running on
+  /// this class.
+  Future<List<ConstructorDeclaration>> constructorsOf(ClassDeclaration clazz);
+
+  /// The class that is directly extended via an `extends` clause.
+  Future<ClassDeclaration?> superclassOf(ClassDeclaration clazz);
+
+  /// All of the classes that are mixed in with `with` clauses.
+  Future<List<ClassDeclaration>> mixinsOf(ClassDeclaration clazz);
+
+  /// All of the classes that are implemented with an `implements` clause.
+  Future<List<ClassDeclaration>> interfacesOf(ClassDeclaration clazz);
+}
+
+/// The api used by [Macro]s to contribute new (non-type)
+/// declarations to the current library.
+///
+/// Can also be used to do subtype checks on types.
+abstract class DeclarationBuilder
+    implements Builder, TypeResolver, ClassIntrospector {
+  /// Adds a new regular declaration to the surrounding library.
+  ///
+  /// Note that type declarations are not supported.
+  void declareInLibrary(DeclarationCode declaration);
+}
+
+/// The api used by [Macro]s to contribute new members to a class.
+abstract class ClassMemberDeclarationBuilder implements DeclarationBuilder {
+  /// Adds a new declaration to the surrounding class.
+  void declareInClass(DeclarationCode declaration);
+}
+
+/// The api used by [Macro]s to reflect on the currently available
+/// members, superclass, and mixins for a given [ClassDeclaration]
+abstract class ClassDeclarationBuilder
+    implements ClassMemberDeclarationBuilder, ClassIntrospector {}
+
+/// The interface used by [Macro]s to resolve any [NamedStaticType] to its
+/// declaration.
+///
+/// Only available in the definition phase of macro expansion.
+abstract class TypeDeclarationResolver {
+  /// Resolves a [NamedStaticType] to its [TypeDeclaration].
+  Future<TypeDeclaration> declarationOf(NamedStaticType annotation);
+}
+
+/// The base class for builders in the definition phase. These can convert
+/// any [TypeAnnotation] into its corresponding [TypeDeclaration], and also
+/// reflect more deeply on those.
+abstract class DefinitionBuilder
+    implements
+        Builder,
+        TypeResolver,
+        ClassIntrospector,
+        TypeDeclarationResolver {}
+
+/// The apis used by [Macro]s that run on classes, to fill in the definitions
+/// of any external declarations within that class.
+abstract class ClassDefinitionBuilder implements DefinitionBuilder {
+  /// Retrieve a [VariableDefinitionBuilder] for a field by [name].
+  ///
+  /// Throws an [ArgumentError] if there is no field by that name.
+  VariableDefinitionBuilder buildField(String name);
+
+  /// Retrieve a [FunctionDefinitionBuilder] for a method by [name].
+  ///
+  /// Throws an [ArgumentError] if there is no method by that name.
+  FunctionDefinitionBuilder buildMethod(String name);
+
+  /// Retrieve a [ConstructorDefinitionBuilder] for a constructor by [name].
+  ///
+  /// Throws an [ArgumentError] if there is no constructor by that name.
+  ConstructorDefinitionBuilder buildConstructor(String name);
+}
+
+/// The apis used by [Macro]s to define the body of a constructor
+/// or wrap the body of an existing constructor with additional statements.
+abstract class ConstructorDefinitionBuilder implements DefinitionBuilder {
+  /// Augments an existing constructor body with [body].
+  ///
+  /// TODO: Link the library augmentations proposal to describe the semantics.
+  void augment({FunctionBodyCode? body, List<Code>? initializers});
+}
+
+/// The apis used by [Macro]s to augment functions or methods.
+abstract class FunctionDefinitionBuilder implements DefinitionBuilder {
+  /// Augments the function.
+  ///
+  /// TODO: Link the library augmentations proposal to describe the semantics.
+  void augment(FunctionBodyCode body);
+}
+
+/// The api used by [Macro]s to augment a top level variable or instance field.
+abstract class VariableDefinitionBuilder implements DefinitionBuilder {
+  /// Augments the field.
+  ///
+  /// TODO: Link the library augmentations proposal to describe the semantics.
+  void augment({
+    DeclarationCode? getter,
+    DeclarationCode? setter,
+    ExpressionCode? initializer,
+  });
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart
new file mode 100644
index 0000000..89f169f
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 '../api.dart';
+
+/// The base class representing an arbitrary chunk of Dart code, which may or
+/// may not be syntactically or semantically valid yet.
+class Code {
+  /// All the chunks of [Code] or raw [String]s that comprise this [Code]
+  /// object.
+  final List<Object> parts;
+
+  Code.fromString(String code) : parts = [code];
+
+  Code.fromParts(this.parts);
+}
+
+/// A piece of code representing a syntactically valid declaration.
+class DeclarationCode extends Code {
+  DeclarationCode.fromString(String code) : super.fromString(code);
+
+  DeclarationCode.fromParts(List<Object> parts) : super.fromParts(parts);
+}
+
+/// A piece of code representing a syntactically valid element.
+///
+/// Should not include any trailing commas,
+class ElementCode extends Code {
+  ElementCode.fromString(String code) : super.fromString(code);
+
+  ElementCode.fromParts(List<Object> parts) : super.fromParts(parts);
+}
+
+/// A piece of code representing a syntactically valid expression.
+class ExpressionCode extends Code {
+  ExpressionCode.fromString(String code) : super.fromString(code);
+
+  ExpressionCode.fromParts(List<Object> parts) : super.fromParts(parts);
+}
+
+/// A piece of code representing a syntactically valid function body.
+///
+/// This includes any and all code after the parameter list of a function,
+/// including modifiers like `async`.
+///
+/// Both arrow and block function bodies are allowed.
+class FunctionBodyCode extends Code {
+  FunctionBodyCode.fromString(String code) : super.fromString(code);
+
+  FunctionBodyCode.fromParts(List<Object> parts) : super.fromParts(parts);
+}
+
+/// A piece of code representing a syntactically valid identifier.
+class IdentifierCode extends Code {
+  IdentifierCode.fromString(String code) : super.fromString(code);
+
+  IdentifierCode.fromParts(List<Object> parts) : super.fromParts(parts);
+}
+
+/// A piece of code identifying a named argument.
+///
+/// This should not include any trailing commas.
+class NamedArgumentCode extends Code {
+  NamedArgumentCode.fromString(String code) : super.fromString(code);
+
+  NamedArgumentCode.fromParts(List<Object> parts) : super.fromParts(parts);
+}
+
+/// A piece of code identifying a syntactically valid function parameter.
+///
+/// This should not include any trailing commas, but may include modifiers
+/// such as `required`, and default values.
+///
+/// There is no distinction here made between named and positional parameters,
+/// nor between optional or required parameters. It is the job of the user to
+/// construct and combine these together in a way that creates valid parameter
+/// lists.
+class ParameterCode extends Code {
+  ParameterCode.fromString(String code) : super.fromString(code);
+
+  ParameterCode.fromParts(List<Object> parts) : super.fromParts(parts);
+}
+
+/// A piece of code representing a syntactically valid statement.
+///
+/// Should always end with a semicolon.
+class StatementCode extends Code {
+  StatementCode.fromString(String code) : super.fromString(code);
+
+  StatementCode.fromParts(List<Object> parts) : super.fromParts(parts);
+}
+
+extension Join<T extends Code> on List<T> {
+  /// Joins all the items in [this] with [separator], and returns
+  /// a new list.
+  List<Code> joinAsCode(String separator) => [
+        for (int i = 0; i < length - 1; i++) ...[
+          this[i],
+          new Code.fromString(separator),
+        ],
+        last,
+      ];
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
new file mode 100644
index 0000000..e892296
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
@@ -0,0 +1,192 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 '../api.dart';
+
+/// The base class for an unresolved reference to a type.
+///
+/// See the subtypes [FunctionTypeAnnotation] and [NamedTypeAnnotation].
+abstract class TypeAnnotation {
+  /// Whether or not the type annotation is explicitly nullable (contains a
+  /// trailing `?`)
+  bool get isNullable;
+
+  /// A [Code] object representation of this type annotation.
+  Code get code;
+}
+
+/// The base class for function type declarations.
+abstract class FunctionTypeAnnotation implements TypeAnnotation {
+  /// The return type of this function.
+  TypeAnnotation get returnType;
+
+  /// The positional parameters for this function.
+  Iterable<ParameterDeclaration> get positionalParameters;
+
+  /// The named parameters for this function.
+  Iterable<ParameterDeclaration> get namedParameters;
+
+  /// The type parameters for this function.
+  Iterable<TypeParameterDeclaration> get typeParameters;
+}
+
+/// An unresolved reference to a type.
+///
+/// These can be resolved to a [TypeDeclaration] using the `builder` classes
+/// depending on the phase a macro is running in.
+abstract class NamedTypeAnnotation implements TypeAnnotation {
+  /// The name of the type as it exists in the type annotation.
+  String get name;
+
+  /// The type arguments, if applicable.
+  Iterable<TypeAnnotation> get typeArguments;
+}
+
+/// The interface representing a resolved type.
+///
+/// Resolved types understand exactly what type they represent, and can be
+/// compared to other static types.
+abstract class StaticType {
+  /// Returns true if this is a subtype of [other].
+  Future<bool> isSubtypeOf(StaticType other);
+
+  /// Returns true if this is an identical type to [other].
+  Future<bool> isExactly(StaticType other);
+}
+
+/// A subtype of [StaticType] representing types that can be resolved by name
+/// to a concrete declaration.
+abstract class NamedStaticType implements StaticType {
+  String get name;
+}
+
+/// The base class for all declarations.
+abstract class Declaration {
+  /// The name of this declaration.
+  String get name;
+}
+
+/// A declaration that defines a new type in the program.
+abstract class TypeDeclaration implements Declaration {
+  /// The type parameters defined for this type declaration.
+  Iterable<TypeParameterDeclaration> get typeParameters;
+
+  /// Create a static type representing this type with [typeArguments].
+  ///
+  /// If [isNullable] is `true`, then this type will behave as if it has a
+  /// trailing `?`.
+  ///
+  /// Throws an exception if the type could not be instantiated, typically due
+  /// to one of the type arguments not matching the bounds of the corresponding
+  /// type parameter.
+  Future<StaticType> instantiate(
+      {required List<StaticType> typeArguments, required bool isNullable});
+}
+
+/// Class (and enum) introspection information.
+///
+/// Information about fields, methods, and constructors must be retrieved from
+/// the `builder` objects.
+abstract class ClassDeclaration implements TypeDeclaration {
+  /// Whether this class has an `abstract` modifier.
+  bool get isAbstract;
+
+  /// Whether this class has an `external` modifier.
+  bool get isExternal;
+
+  /// The `extends` type annotation, if present.
+  TypeAnnotation? get superclass;
+
+  /// All the `implements` type annotations.
+  Iterable<TypeAnnotation> get interfaces;
+
+  /// All the `with` type annotations.
+  Iterable<TypeAnnotation> get mixins;
+
+  /// All the type arguments, if applicable.
+  Iterable<TypeParameterDeclaration> get typeParameters;
+}
+
+/// Function introspection information.
+abstract class FunctionDeclaration implements Declaration {
+  /// Whether this function has an `abstract` modifier.
+  bool get isAbstract;
+
+  /// Whether this function has an `external` modifier.
+  bool get isExternal;
+
+  /// Whether this function is actually a getter.
+  bool get isGetter;
+
+  /// Whether this function is actually a setter.
+  bool get isSetter;
+
+  /// The return type of this function.
+  TypeAnnotation get returnType;
+
+  /// The positional parameters for this function.
+  Iterable<ParameterDeclaration> get positionalParameters;
+
+  /// The named parameters for this function.
+  Iterable<ParameterDeclaration> get namedParameters;
+
+  /// The type parameters for this function.
+  Iterable<TypeParameterDeclaration> get typeParameters;
+}
+
+/// Method introspection information.
+abstract class MethodDeclaration implements FunctionDeclaration {
+  /// The class that defines this method.
+  TypeAnnotation get definingClass;
+}
+
+/// Constructor introspection information.
+abstract class ConstructorDeclaration implements MethodDeclaration {
+  /// Whether or not this is a factory constructor.
+  bool get isFactory;
+}
+
+/// Variable introspection information.
+abstract class VariableDeclaration implements Declaration {
+  /// Whether this function has an `abstract` modifier.
+  bool get isAbstract;
+
+  /// Whether this function has an `external` modifier.
+  bool get isExternal;
+
+  /// The type of this field.
+  TypeAnnotation get type;
+
+  /// A [Code] object representing the initializer for this field, if present.
+  Code? get initializer;
+}
+
+/// Field introspection information ..
+abstract class FieldDeclaration implements VariableDeclaration {
+  /// The class that defines this method.
+  TypeAnnotation get definingClass;
+}
+
+/// Parameter introspection information.
+abstract class ParameterDeclaration implements Declaration {
+  /// The type of this parameter.
+  TypeAnnotation get type;
+
+  /// Whether or not this is a named parameter.
+  bool get isNamed;
+
+  /// Whether or not this parameter is either a non-optional positional
+  /// parameter or an optional parameter with the `required` keyword.
+  bool get isRequired;
+
+  /// A [Code] object representing the default value for this parameter, if
+  /// present. Can be used to copy default values to other parameters.
+  Code? get defaultValue;
+}
+
+/// Type parameter introspection information.
+abstract class TypeParameterDeclaration implements Declaration {
+  /// The bounds for this type parameter, if it has any.
+  TypeAnnotation? get bounds;
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/macros.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/macros.dart
new file mode 100644
index 0000000..7685589a
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/macros.dart
@@ -0,0 +1,139 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 '../api.dart';
+
+/// The marker interface for all types of macros.
+abstract class Macro {}
+
+/// The interface for [Macro]s that can be applied to any top level function,
+/// instance method, or static method, and wants to contribute new type
+/// declarations to the program.
+abstract class FunctionTypesMacro implements Macro {
+  FutureOr<void> buildTypesForFunction(
+      FunctionDeclaration function, TypeBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any top level function,
+/// instance method, or static method, and wants to contribute new non-type
+/// declarations to the program.
+abstract class FunctionDeclarationsMacro implements Macro {
+  FutureOr<void> buildDeclarationsForFunction(
+      FunctionDeclaration function, DeclarationBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any top level function,
+/// instance method, or static method, and wants to augment the function
+/// definition.
+abstract class FunctionDefinitionMacro implements Macro {
+  FutureOr<void> buildDefinitionForFunction(
+      FunctionDeclaration function, FunctionDefinitionBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any top level variable or
+/// instance field, and wants to contribute new type declarations to the
+/// program.
+abstract class VariableTypesMacro implements Macro {
+  FutureOr<void> buildTypesForVariable(
+      VariableDeclaration variable, TypeBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any top level variable or
+/// instance field and wants to contribute new non-type declarations to the
+/// program.
+abstract class VariableDeclarationsMacro implements Macro {
+  FutureOr<void> buildDeclarationsForVariable(
+      VariableDeclaration variable, DeclarationBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any top level variable
+/// or instance field, and wants to augment the variable definition.
+abstract class VariableDefinitionMacro implements Macro {
+  FutureOr<void> buildDefinitionForFunction(
+      VariableDeclaration variable, VariableDefinitionBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any class, and wants to
+/// contribute new type declarations to the program.
+abstract class ClassTypesMacro implements Macro {
+  FutureOr<void> buildTypesForClass(
+      ClassDeclaration clazz, TypeBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any class, and wants to
+/// contribute new non-type declarations to the program.
+abstract class ClassDeclarationsMacro implements Macro {
+  FutureOr<void> buildDeclarationsForClass(
+      ClassDeclaration clazz, ClassDeclarationBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any class, and wants to
+/// augment the definitions of members on the class.
+abstract class ClassDefinitionMacro implements Macro {
+  FutureOr<void> buildDefinitionForClass(
+      ClassDeclaration clazz, ClassDefinitionBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any field, and wants to
+/// contribute new type declarations to the program.
+abstract class FieldTypesMacro implements Macro {
+  FutureOr<void> buildTypesForField(
+      FieldDeclaration field, TypeBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any field, and wants to
+/// contribute new type declarations to the program.
+abstract class FieldDeclarationsMacro implements Macro {
+  FutureOr<void> buildTypesForField(
+      FieldDeclaration field, ClassMemberDeclarationBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any field, and wants to
+/// augment the field definition.
+abstract class FieldDefinitionsMacro implements Macro {
+  FutureOr<void> buildDefinitionForField(
+      FieldDeclaration field, VariableDefinitionBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any method, and wants to
+/// contribute new type declarations to the program.
+abstract class MethodTypesMacro implements Macro {
+  FutureOr<void> buildTypesForMethod(
+      MethodDeclaration method, TypeBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any method, and wants to
+/// contribute new non-type declarations to the program.
+abstract class MethodDeclarationDeclarationsMacro implements Macro {
+  FutureOr<void> buildDeclarationsForMethod(
+      MethodDeclaration method, ClassMemberDeclarationBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any method, and wants to
+/// augment the function definition.
+abstract class MethodDefinitionMacro implements Macro {
+  FutureOr<void> buildDefinitionForMethod(
+      MethodDeclaration method, FunctionDefinitionBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any constructor, and wants
+/// to contribute new type declarations to the program.
+abstract class ConstructorTypesMacro implements Macro {
+  FutureOr<void> buildTypesForConstructor(
+      ConstructorDeclaration method, TypeBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any constructors, and
+/// wants to contribute new non-type declarations to the program.
+abstract class ConstructorDeclarationDeclarationsMacro implements Macro {
+  FutureOr<void> buildDeclarationsForConstructor(
+      ConstructorDeclaration method, ClassMemberDeclarationBuilder builder);
+}
+
+/// The interface for [Macro]s that can be applied to any constructor, and wants
+/// to augment the function definition.
+abstract class ConstructorDefinitionMacro implements Macro {
+  FutureOr<void> buildDefinitionForConstructor(
+      ConstructorDeclaration method, ConstructorDefinitionBuilder builder);
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
new file mode 100644
index 0000000..0d4e878
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
@@ -0,0 +1,115 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 'api.dart';
+
+/// The interface used by Dart language implementations, in order to load
+/// and execute macros, as well as produce library augmentations from those
+/// macro applications.
+///
+/// This class more clearly defines the role of a Dart language implementation
+/// during macro discovery and expansion, and unifies how augmentation libraries
+/// are produced.
+abstract class MacroExecutor {
+  /// Invoked when an implementation discovers a new macro definition in a
+  /// [library] with [name], and prepares this executor to run the macro.
+  ///
+  /// May be invoked more than once for the same macro, which will cause the
+  /// macro to be re-loaded. Previous [MacroClassIdentifier]s and
+  /// [MacroInstanceIdentifier]s given for this macro will be invalid after
+  /// that point and should be discarded.
+  ///
+  /// Throws an exception if the macro fails to load.
+  Future<MacroClassIdentifier> loadMacro(Uri library, String name);
+
+  /// Creates an instance of [macroClass] in the executor, and returns an
+  /// identifier for that instance.
+  ///
+  /// Throws an exception if an instance is not created.
+  Future<MacroInstanceIdentifier> instantiateMacro(
+      MacroClassIdentifier macroClass, String constructor, Arguments arguments);
+
+  /// Runs the type phase for [macro] on a given [declaration].
+  ///
+  /// Throws an exception if there is an error executing the macro.
+  Future<MacroExecutionResult> executeTypesPhase(
+      MacroInstanceIdentifier macro, Declaration declaration);
+
+  /// Runs the declarations phase for [macro] on a given [declaration].
+  ///
+  /// Throws an exception if there is an error executing the macro.
+  Future<MacroExecutionResult> executeDeclarationsPhase(
+      MacroInstanceIdentifier macro,
+      Declaration declaration,
+      TypeResolver typeResolver,
+      ClassIntrospector classIntrospector);
+
+  /// Runs the definitions phase for [macro] on a given [declaration].
+  ///
+  /// Throws an exception if there is an error executing the macro.
+  Future<MacroExecutionResult> executeDefinitionsPhase(
+      MacroInstanceIdentifier macro,
+      Declaration declaration,
+      TypeResolver typeResolver,
+      ClassIntrospector classIntrospector,
+      TypeDeclarationResolver typeDeclarationResolver);
+
+  /// Combines multiple [MacroExecutionResult]s into a single library
+  /// augmentation file, and returns a [String] representing that file.
+  Future<String> buildAugmentationLibrary(
+      Iterable<MacroExecutionResult> macroResults);
+
+  /// Tell the executor to shut down and clean up any resources it may have
+  /// allocated.
+  void close();
+}
+
+/// The arguments passed to a macro constructor.
+///
+/// All argument instances must be of type [Code] or a built-in value type that
+/// is serializable (num, bool, String, null, etc).
+class Arguments {
+  final List<Object?> positional;
+
+  final Map<String, Object?> named;
+
+  Arguments(this.positional, this.named);
+}
+
+/// An opaque identifier for a macro class, retrieved by
+/// [MacroExecutor.loadMacro].
+///
+/// Used to execute or reload this macro in the future.
+abstract class MacroClassIdentifier {}
+
+/// An opaque identifier for an instance of a macro class, retrieved by
+/// [MacroExecutor.instantiateMacro].
+///
+/// Used to execute or reload this macro in the future.
+abstract class MacroInstanceIdentifier {}
+
+/// A summary of the results of running a macro in a given phase.
+///
+/// All modifications are expressed in terms of library augmentation
+/// declarations.
+abstract class MacroExecutionResult {
+  /// Any library imports that should be added to support the code used in
+  /// the augmentations.
+  Iterable<DeclarationCode> get imports;
+
+  /// Any augmentations that should be applied as a result of executing a macro.
+  Iterable<DeclarationCode> get augmentations;
+}
+
+/// Each of the different macro execution phases.
+enum Phase {
+  /// Only new types are added in this phase.
+  types,
+
+  /// New non-type declarations are added in this phase.
+  declarations,
+
+  /// This phase allows augmenting existing declarations.
+  definitions,
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart
new file mode 100644
index 0000000..d6476af
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart
@@ -0,0 +1,137 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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:isolate';
+import 'dart:mirrors';
+
+import 'isolate_mirrors_impl.dart';
+import 'protocol.dart';
+import '../executor.dart';
+import '../api.dart';
+
+/// A [MacroExecutor] implementation which relies on [IsolateMirror.loadUri]
+/// in order to load macros libraries.
+///
+/// All actual work happens in a separate [Isolate], and this class serves as
+/// a bridge between that isolate and the language frontends.
+class IsolateMirrorMacroExecutor implements MacroExecutor {
+  /// The actual isolate doing macro loading and execution.
+  final Isolate _macroIsolate;
+
+  /// The channel used to send requests to the [_macroIsolate].
+  final SendPort _sendPort;
+
+  /// The stream of responses from the [_macroIsolate].
+  final Stream<GenericResponse> _responseStream;
+
+  /// A map of response completers by request id.
+  final _responseCompleters = <int, Completer<GenericResponse>>{};
+
+  /// A function that should be invoked when shutting down this executor
+  /// to perform any necessary cleanup.
+  final void Function() _onClose;
+
+  IsolateMirrorMacroExecutor._(
+      this._macroIsolate, this._sendPort, this._responseStream, this._onClose) {
+    _responseStream.listen((event) {
+      Completer<GenericResponse>? completer =
+          _responseCompleters.remove(event.requestId);
+      if (completer == null) {
+        throw new StateError(
+            'Got a response for an unrecognized request id ${event.requestId}');
+      }
+      completer.complete(event);
+    });
+  }
+
+  /// Initialize an [IsolateMirrorMacroExecutor] and return it once ready.
+  ///
+  /// Spawns the macro isolate and sets up a communication channel.
+  static Future<MacroExecutor> start() async {
+    ReceivePort receivePort = new ReceivePort();
+    Completer<SendPort> sendPortCompleter = new Completer<SendPort>();
+    StreamController<GenericResponse> responseStreamController =
+        new StreamController<GenericResponse>(sync: true);
+    receivePort.listen((message) {
+      if (!sendPortCompleter.isCompleted) {
+        sendPortCompleter.complete(message as SendPort);
+      } else {
+        responseStreamController.add(message as GenericResponse);
+      }
+    }).onDone(responseStreamController.close);
+    Isolate macroIsolate = await Isolate.spawn(spawn, receivePort.sendPort);
+
+    return new IsolateMirrorMacroExecutor._(
+        macroIsolate,
+        await sendPortCompleter.future,
+        responseStreamController.stream,
+        receivePort.close);
+  }
+
+  @override
+  Future<String> buildAugmentationLibrary(
+      Iterable<MacroExecutionResult> macroResults) {
+    // TODO: implement buildAugmentationLibrary
+    throw new UnimplementedError();
+  }
+
+  @override
+  void close() {
+    _onClose();
+    _macroIsolate.kill();
+  }
+
+  @override
+  Future<MacroExecutionResult> executeDeclarationsPhase(
+      MacroInstanceIdentifier macro,
+      Declaration declaration,
+      TypeResolver typeResolver,
+      ClassIntrospector classIntrospector) {
+    // TODO: implement executeDeclarationsPhase
+    throw new UnimplementedError();
+  }
+
+  @override
+  Future<MacroExecutionResult> executeDefinitionsPhase(
+          MacroInstanceIdentifier macro,
+          Declaration declaration,
+          TypeResolver typeResolver,
+          ClassIntrospector classIntrospector,
+          TypeDeclarationResolver typeDeclarationResolver) =>
+      _sendRequest(new ExecuteDefinitionsPhaseRequest(macro, declaration,
+          typeResolver, classIntrospector, typeDeclarationResolver));
+
+  @override
+  Future<MacroExecutionResult> executeTypesPhase(
+      MacroInstanceIdentifier macro, Declaration declaration) {
+    // TODO: implement executeTypesPhase
+    throw new UnimplementedError();
+  }
+
+  @override
+  Future<MacroInstanceIdentifier> instantiateMacro(
+          MacroClassIdentifier macroClass,
+          String constructor,
+          Arguments arguments) =>
+      _sendRequest(
+          new InstantiateMacroRequest(macroClass, constructor, arguments));
+
+  @override
+  Future<MacroClassIdentifier> loadMacro(Uri library, String name) =>
+      _sendRequest(new LoadMacroRequest(library, name));
+
+  /// Sends a request and returns the response, casting it to the expected
+  /// type.
+  Future<T> _sendRequest<T>(Request request) async {
+    _sendPort.send(request);
+    Completer<GenericResponse<T>> completer =
+        new Completer<GenericResponse<T>>();
+    _responseCompleters[request.id] = completer;
+    GenericResponse<T> response = await completer.future;
+    T? result = response.response;
+    if (result != null) return result;
+    throw response.error!;
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_impl.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_impl.dart
new file mode 100644
index 0000000..3cf24a5
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_impl.dart
@@ -0,0 +1,255 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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:isolate';
+import 'dart:mirrors';
+
+import 'protocol.dart';
+import '../executor.dart';
+import '../api.dart';
+
+/// Spawns a new isolate for loading and executing macros.
+void spawn(SendPort sendPort) {
+  ReceivePort receivePort = new ReceivePort();
+  sendPort.send(receivePort.sendPort);
+  receivePort.listen((message) async {
+    if (message is LoadMacroRequest) {
+      GenericResponse<MacroClassIdentifier> response =
+          await _loadMacro(message);
+      sendPort.send(response);
+    } else if (message is InstantiateMacroRequest) {
+      GenericResponse<MacroInstanceIdentifier> response =
+          await _instantiateMacro(message);
+      sendPort.send(response);
+    } else if (message is ExecuteDefinitionsPhaseRequest) {
+      GenericResponse<MacroExecutionResult> response =
+          await _executeDefinitionsPhase(message);
+      sendPort.send(response);
+    } else {
+      throw new StateError('Unrecognized event type $message');
+    }
+  });
+}
+
+/// Maps macro identifiers to class mirrors.
+final _macroClasses = <_MacroClassIdentifier, ClassMirror>{};
+
+/// Handles [LoadMacroRequest]s.
+Future<GenericResponse<MacroClassIdentifier>> _loadMacro(
+    LoadMacroRequest request) async {
+  try {
+    _MacroClassIdentifier identifier =
+        new _MacroClassIdentifier(request.library, request.name);
+    if (_macroClasses.containsKey(identifier)) {
+      throw new UnsupportedError(
+          'Reloading macros is not supported by this implementation');
+    }
+    LibraryMirror libMirror =
+        await currentMirrorSystem().isolate.loadUri(request.library);
+    ClassMirror macroClass =
+        libMirror.declarations[new Symbol(request.name)] as ClassMirror;
+    _macroClasses[identifier] = macroClass;
+    return new GenericResponse(response: identifier, requestId: request.id);
+  } catch (e) {
+    return new GenericResponse(error: e, requestId: request.id);
+  }
+}
+
+/// Maps macro instance identifiers to instances.
+final _macroInstances = <_MacroInstanceIdentifier, Macro>{};
+
+/// Handles [InstantiateMacroRequest]s.
+Future<GenericResponse<MacroInstanceIdentifier>> _instantiateMacro(
+    InstantiateMacroRequest request) async {
+  try {
+    ClassMirror? clazz = _macroClasses[request.macroClass];
+    if (clazz == null) {
+      throw new ArgumentError('Unrecognized macro class ${request.macroClass}');
+    }
+    Macro instance = clazz.newInstance(
+        new Symbol(request.constructorName), request.arguments.positional, {
+      for (MapEntry<String, Object?> entry in request.arguments.named.entries)
+        new Symbol(entry.key): entry.value,
+    }).reflectee as Macro;
+    _MacroInstanceIdentifier identifier = new _MacroInstanceIdentifier();
+    _macroInstances[identifier] = instance;
+    return new GenericResponse<MacroInstanceIdentifier>(
+        response: identifier, requestId: request.id);
+  } catch (e) {
+    return new GenericResponse(error: e, requestId: request.id);
+  }
+}
+
+Future<GenericResponse<MacroExecutionResult>> _executeDefinitionsPhase(
+    ExecuteDefinitionsPhaseRequest request) async {
+  try {
+    Macro? instance = _macroInstances[request.macro];
+    if (instance == null) {
+      throw new StateError('Unrecognized macro instance ${request.macro}\n'
+          'Known instances: $_macroInstances)');
+    }
+    Declaration declaration = request.declaration;
+    if (instance is FunctionDefinitionMacro &&
+        declaration is FunctionDeclaration) {
+      _FunctionDefinitionBuilder builder = new _FunctionDefinitionBuilder(
+          declaration,
+          request.typeResolver,
+          request.typeDeclarationResolver,
+          request.classIntrospector);
+      await instance.buildDefinitionForFunction(declaration, builder);
+      return new GenericResponse(
+          response: builder.result, requestId: request.id);
+    } else {
+      throw new UnsupportedError(
+          ('Only FunctionDefinitionMacros are supported currently'));
+    }
+  } catch (e) {
+    return new GenericResponse(error: e, requestId: request.id);
+  }
+}
+
+/// Our implementation of [MacroClassIdentifier].
+class _MacroClassIdentifier implements MacroClassIdentifier {
+  final String id;
+
+  _MacroClassIdentifier(Uri library, String name) : id = '$library#$name';
+
+  operator ==(other) => other is _MacroClassIdentifier && id == other.id;
+
+  int get hashCode => id.hashCode;
+}
+
+/// Our implementation of [MacroInstanceIdentifier].
+class _MacroInstanceIdentifier implements MacroInstanceIdentifier {
+  static int _next = 0;
+
+  final int id;
+
+  _MacroInstanceIdentifier() : id = _next++;
+
+  operator ==(other) => other is _MacroInstanceIdentifier && id == other.id;
+
+  int get hashCode => id;
+}
+
+/// Our implementation of [MacroExecutionResult].
+class _MacroExecutionResult implements MacroExecutionResult {
+  @override
+  final List<DeclarationCode> augmentations = <DeclarationCode>[];
+
+  @override
+  final List<DeclarationCode> imports = <DeclarationCode>[];
+}
+
+/// Custom implementation of [FunctionDefinitionBuilder].
+class _FunctionDefinitionBuilder implements FunctionDefinitionBuilder {
+  final TypeResolver typeResolver;
+  final TypeDeclarationResolver typeDeclarationResolver;
+  final ClassIntrospector classIntrospector;
+
+  /// The declaration this is a builder for.
+  final FunctionDeclaration declaration;
+
+  /// The final result, will be built up over `augment` calls.
+  final _MacroExecutionResult result = new _MacroExecutionResult();
+
+  _FunctionDefinitionBuilder(this.declaration, this.typeResolver,
+      this.typeDeclarationResolver, this.classIntrospector);
+
+  @override
+  void augment(FunctionBodyCode body) {
+    result.augmentations.add(new DeclarationCode.fromParts([
+      'augment ',
+      declaration.returnType.code,
+      ' ',
+      declaration.name,
+      if (declaration.typeParameters.isNotEmpty) ...[
+        '<',
+        for (TypeParameterDeclaration typeParam
+            in declaration.typeParameters) ...[
+          typeParam.name,
+          if (typeParam.bounds != null) ...['extends ', typeParam.bounds!.code],
+          if (typeParam != declaration.typeParameters.last) ', ',
+        ],
+        '>',
+      ],
+      '(',
+      for (ParameterDeclaration positionalRequired
+          in declaration.positionalParameters.where((p) => p.isRequired)) ...[
+        new ParameterCode.fromParts([
+          positionalRequired.type.code,
+          ' ',
+          positionalRequired.name,
+        ]),
+        ', '
+      ],
+      if (declaration.positionalParameters.any((p) => !p.isRequired)) ...[
+        '[',
+        for (ParameterDeclaration positionalOptional in declaration
+            .positionalParameters
+            .where((p) => !p.isRequired)) ...[
+          new ParameterCode.fromParts([
+            positionalOptional.type.code,
+            ' ',
+            positionalOptional.name,
+          ]),
+          ', ',
+        ],
+        ']',
+      ],
+      if (declaration.namedParameters.isNotEmpty) ...[
+        '{',
+        for (ParameterDeclaration named in declaration.namedParameters) ...[
+          new ParameterCode.fromParts([
+            if (named.isRequired) 'required ',
+            named.type.code,
+            ' ',
+            named.name,
+            if (named.defaultValue != null) ...[
+              ' = ',
+              named.defaultValue!,
+            ],
+          ]),
+          ', ',
+        ],
+        '}',
+      ],
+      ') ',
+      body,
+    ]));
+  }
+
+  @override
+  Future<List<ConstructorDeclaration>> constructorsOf(ClassDeclaration clazz) =>
+      classIntrospector.constructorsOf(clazz);
+
+  @override
+  Future<List<FieldDeclaration>> fieldsOf(ClassDeclaration clazz) =>
+      classIntrospector.fieldsOf(clazz);
+
+  @override
+  Future<List<ClassDeclaration>> interfacesOf(ClassDeclaration clazz) =>
+      classIntrospector.interfacesOf(clazz);
+
+  @override
+  Future<List<MethodDeclaration>> methodsOf(ClassDeclaration clazz) =>
+      classIntrospector.methodsOf(clazz);
+
+  @override
+  Future<List<ClassDeclaration>> mixinsOf(ClassDeclaration clazz) =>
+      classIntrospector.mixinsOf(clazz);
+
+  @override
+  Future<TypeDeclaration> declarationOf(NamedStaticType annotation) =>
+      typeDeclarationResolver.declarationOf(annotation);
+
+  @override
+  Future<ClassDeclaration?> superclassOf(ClassDeclaration clazz) =>
+      classIntrospector.superclassOf(clazz);
+
+  @override
+  Future<StaticType> resolve(TypeAnnotation typeAnnotation) =>
+      typeResolver.resolve(typeAnnotation);
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/protocol.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/protocol.dart
new file mode 100644
index 0000000..96a2724
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/protocol.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Defines the objects used for communication between the macro executor and
+/// the isolate doing the work of macro loading and execution.
+library protocol;
+
+import '../executor.dart';
+import '../api.dart';
+
+/// Base class all requests extend, provides a unique id for each request.
+class Request {
+  final int id;
+
+  Request() : id = _next++;
+
+  static int _next = 0;
+}
+
+/// A generic response object that is either an instance of [T] or an error.
+class GenericResponse<T> {
+  final T? response;
+  final Object? error;
+  final int requestId;
+
+  GenericResponse({this.response, this.error, required this.requestId})
+      : assert(response != null || error != null),
+        assert(response == null || error == null);
+}
+
+/// A request to load a macro in this isolate.
+class LoadMacroRequest extends Request {
+  final Uri library;
+  final String name;
+
+  LoadMacroRequest(this.library, this.name);
+}
+
+/// A request to instantiate a macro instance.
+class InstantiateMacroRequest extends Request {
+  final MacroClassIdentifier macroClass;
+  final String constructorName;
+  final Arguments arguments;
+
+  InstantiateMacroRequest(
+      this.macroClass, this.constructorName, this.arguments);
+}
+
+/// A request to execute a macro on a particular declaration in the definition
+/// phase.
+class ExecuteDefinitionsPhaseRequest extends Request {
+  final MacroInstanceIdentifier macro;
+  final Declaration declaration;
+  final TypeResolver typeResolver;
+  final ClassIntrospector classIntrospector;
+  final TypeDeclarationResolver typeDeclarationResolver;
+
+  ExecuteDefinitionsPhaseRequest(this.macro, this.declaration,
+      this.typeResolver, this.classIntrospector, this.typeDeclarationResolver);
+}
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart
new file mode 100644
index 0000000..48ca97b
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart
@@ -0,0 +1,147 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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:_fe_analyzer_shared/src/macros/api.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart';
+
+import 'package:test/fake.dart';
+import 'package:test/test.dart';
+
+void main() {
+  late MacroExecutor executor;
+
+  setUp(() async {
+    executor = await IsolateMirrorMacroExecutor.start();
+  });
+
+  tearDown(() {
+    executor.close();
+  });
+
+  test('can load macros and create instances', () async {
+    var clazzId = await executor.loadMacro(
+        // Tests run from the root of the repo.
+        File('pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart')
+            .absolute
+            .uri,
+        'SimpleMacro');
+    expect(clazzId, isNotNull, reason: 'Can load a macro.');
+
+    var instanceId =
+        await executor.instantiateMacro(clazzId, '', Arguments([], {}));
+    expect(instanceId, isNotNull,
+        reason: 'Can create an instance with no arguments.');
+
+    instanceId =
+        await executor.instantiateMacro(clazzId, '', Arguments([1, 2], {}));
+    expect(instanceId, isNotNull,
+        reason: 'Can create an instance with positional arguments.');
+
+    instanceId = await executor.instantiateMacro(
+        clazzId, 'named', Arguments([], {'x': 1, 'y': 2}));
+    expect(instanceId, isNotNull,
+        reason: 'Can create an instance with named arguments.');
+
+    var definitionResult = await executor.executeDefinitionsPhase(
+        instanceId,
+        _FunctionDeclaration(
+          isAbstract: false,
+          isExternal: false,
+          isGetter: false,
+          isSetter: false,
+          name: 'foo',
+          namedParameters: [],
+          positionalParameters: [],
+          returnType:
+              _TypeAnnotation(Code.fromString('String'), isNullable: false),
+          typeParameters: [],
+        ),
+        _FakeTypeResolver(),
+        _FakeClassIntrospector(),
+        _FakeTypeDeclarationResolver());
+    expect(definitionResult.augmentations, hasLength(1));
+    expect(definitionResult.augmentations.first.debugString().toString(),
+        equalsIgnoringWhitespace('''
+            augment String foo() {
+              print('x: 1, y: 2');
+              return augment super();
+            }'''));
+  });
+}
+
+class _FakeClassIntrospector with Fake implements ClassIntrospector {}
+
+class _FakeTypeResolver with Fake implements TypeResolver {}
+
+class _FakeTypeDeclarationResolver
+    with Fake
+    implements TypeDeclarationResolver {}
+
+class _FunctionDeclaration implements FunctionDeclaration {
+  @override
+  final bool isAbstract;
+
+  @override
+  final bool isExternal;
+
+  @override
+  final bool isGetter;
+
+  @override
+  final bool isSetter;
+
+  @override
+  final String name;
+
+  @override
+  final Iterable<ParameterDeclaration> namedParameters;
+
+  @override
+  final Iterable<ParameterDeclaration> positionalParameters;
+
+  @override
+  final TypeAnnotation returnType;
+
+  @override
+  final Iterable<TypeParameterDeclaration> typeParameters;
+
+  _FunctionDeclaration({
+    required this.isAbstract,
+    required this.isExternal,
+    required this.isGetter,
+    required this.isSetter,
+    required this.name,
+    required this.namedParameters,
+    required this.positionalParameters,
+    required this.returnType,
+    required this.typeParameters,
+  });
+}
+
+class _TypeAnnotation implements TypeAnnotation {
+  @override
+  final Code code;
+
+  @override
+  final bool isNullable;
+
+  _TypeAnnotation(this.code, {required this.isNullable});
+}
+
+extension _ on Code {
+  StringBuffer debugString([StringBuffer? buffer]) {
+    buffer ??= StringBuffer();
+    for (var part in parts) {
+      if (part is Code) {
+        part.debugString(buffer);
+      } else {
+        buffer.write(part.toString());
+      }
+    }
+    return buffer;
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart
new file mode 100644
index 0000000..b95da0b
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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:_fe_analyzer_shared/src/macros/api.dart';
+
+/// A very simple macro that annotates functions (or getters) with no arguments
+/// and adds a print statement to the top of them.
+class SimpleMacro implements FunctionDefinitionMacro {
+  final int? x;
+  final int? y;
+
+  SimpleMacro([this.x, this.y]);
+
+  SimpleMacro.named({this.x, this.y});
+
+  @override
+  FutureOr<void> buildDefinitionForFunction(
+      FunctionDeclaration method, FunctionDefinitionBuilder builder) {
+    if (method.namedParameters
+        .followedBy(method.positionalParameters)
+        .isNotEmpty) {
+      throw ArgumentError(
+          'This macro can only be run on functions with no arguments!');
+    }
+    builder.augment(FunctionBodyCode.fromString('''{
+      print('x: $x, y: $y');
+      return augment super();
+    }'''));
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
index aa75988..3b4f5f2 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
@@ -7,10 +7,10 @@
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
-import 'package:analysis_server/src/utilities/extensions/element.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/applicable_extensions.dart';
 
 /// A contributor that produces suggestions based on the members of an
 /// extension.
@@ -115,21 +115,21 @@
 
   void _addExtensionMembers(List<ExtensionElement> extensions,
       CompletionSuggestionKind? kind, DartType type) {
-    var containingLibrary = request.libraryElement;
-    var typeSystem = containingLibrary.typeSystem;
-    for (var extension in extensions) {
-      var extendedType =
-          extension.resolvedExtendedType(containingLibrary, type);
-      if (extendedType != null && typeSystem.isSubtypeOf(type, extendedType)) {
-        var inheritanceDistance = 0.0;
-        if (type is InterfaceType && extendedType is InterfaceType) {
-          inheritanceDistance = memberBuilder.request.featureComputer
-              .inheritanceDistanceFeature(type.element, extendedType.element);
-        }
-        // TODO(brianwilkerson) We might want to apply the substitution to the
-        //  members of the extension for display purposes.
-        _addInstanceMembers(extension, kind, inheritanceDistance);
+    var applicableExtensions = extensions.applicableTo(
+      targetLibrary: request.libraryElement,
+      targetType: type,
+    );
+    for (var instantiatedExtension in applicableExtensions) {
+      var extendedType = instantiatedExtension.extendedType;
+      var inheritanceDistance = 0.0;
+      if (type is InterfaceType && extendedType is InterfaceType) {
+        inheritanceDistance = memberBuilder.request.featureComputer
+            .inheritanceDistanceFeature(type.element, extendedType.element);
       }
+      // TODO(brianwilkerson) We might want to apply the substitution to the
+      //  members of the extension for display purposes.
+      _addInstanceMembers(
+          instantiatedExtension.extension, kind, inheritanceDistance);
     }
   }
 
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart b/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
index 12c65d0..98cc241 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
@@ -153,11 +153,12 @@
         continue;
       }
       foundImport = true;
-      var instantiatedExtensions = ApplicableExtensions(
-        targetLibrary: libraryElement,
-        targetType: targetType,
-        memberName: memberName,
-      ).instantiate(importedLibrary.exportedExtensions);
+      var instantiatedExtensions = importedLibrary.exportedExtensions
+          .hasMemberWithBaseName(memberName)
+          .applicableTo(
+            targetLibrary: libraryElement,
+            targetType: targetType,
+          );
       for (var instantiatedExtension in instantiatedExtensions) {
         // If the import has a combinator that needs to be updated, then offer
         // to update it.
@@ -454,11 +455,12 @@
 
   @override
   Future<void> compute(ChangeBuilder builder) async {
-    var instantiatedExtensions = ApplicableExtensions(
-      targetLibrary: libraryElement,
-      targetType: targetType,
-      memberName: memberName,
-    ).instantiate(library.exportedExtensions);
+    var instantiatedExtensions = library.exportedExtensions
+        .hasMemberWithBaseName(memberName)
+        .applicableTo(
+          targetLibrary: libraryElement,
+          targetType: targetType,
+        );
     if (instantiatedExtensions.isNotEmpty) {
       await builder.addDartFileEdit(file, (builder) {
         _uriText = builder.importLibrary(library.source.uri);
diff --git a/pkg/analysis_server/lib/src/utilities/extensions/element.dart b/pkg/analysis_server/lib/src/utilities/extensions/element.dart
index 33e7498..1bc51b1 100644
--- a/pkg/analysis_server/lib/src/utilities/extensions/element.dart
+++ b/pkg/analysis_server/lib/src/utilities/extensions/element.dart
@@ -3,10 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/generic_inferrer.dart';
-import 'package:analyzer/src/dart/element/type_algebra.dart';
-import 'package:analyzer/src/dart/element/type_system.dart';
 
 extension ClassElementExtensions on ClassElement {
   /// Return `true` if this element represents the class `Iterable` from
@@ -59,35 +55,6 @@
   }
 }
 
-extension ExtensionElementExtensions on ExtensionElement {
-  /// Use the [type] of the object being extended in the [library] to compute
-  /// the actual type extended by this [extension]. Return the computed type,
-  /// or `null` if the type can't be computed.
-  /// TODO(scheglov) share with analyzer
-  DartType? resolvedExtendedType(LibraryElement library, DartType type) {
-    final typeParameters = this.typeParameters;
-    var inferrer =
-        GenericInferrer(library.typeSystem as TypeSystemImpl, typeParameters);
-    inferrer.constrainArgument(
-      type,
-      extendedType,
-      'extendedType',
-    );
-    var typeArguments = inferrer.infer(typeParameters,
-        failAtError: true, genericMetadataIsEnabled: true);
-    if (typeArguments == null) {
-      return null;
-    }
-    var substitution = Substitution.fromPairs(
-      typeParameters,
-      typeArguments,
-    );
-    return substitution.substituteType(
-      extendedType,
-    );
-  }
-}
-
 extension LibraryElementExtensions on LibraryElement {
   /// Return all extensions exported from this library.
   Iterable<ExtensionElement> get exportedExtensions {
diff --git a/pkg/analyzer/lib/src/dart/resolver/applicable_extensions.dart b/pkg/analyzer/lib/src/dart/resolver/applicable_extensions.dart
index 95d2c81..478c884 100644
--- a/pkg/analyzer/lib/src/dart/resolver/applicable_extensions.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/applicable_extensions.dart
@@ -10,139 +10,18 @@
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
-import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/resolution_result.dart';
 
-/// Extensions that can be applied, within the [targetLibrary], to the
-/// [targetType], and that define a member with the base [memberName].
-class ApplicableExtensions {
-  final LibraryElementImpl targetLibrary;
-  final DartType targetType;
-  final String memberName;
-
-  ApplicableExtensions({
-    required LibraryElement targetLibrary,
-    required this.targetType,
-    required this.memberName,
-  }) : targetLibrary = targetLibrary as LibraryElementImpl;
-
-  bool get _genericMetadataIsEnabled {
-    return targetLibrary.featureSet.isEnabled(
-      Feature.generic_metadata,
-    );
-  }
-
-  TypeSystemImpl get _typeSystem {
-    return targetLibrary.typeSystem;
-  }
-
-  /// Return [extensions] that match the configuration.
-  List<InstantiatedExtension> instantiate(
-    Iterable<ExtensionElement> extensions,
-  ) {
-    if (identical(targetType, NeverTypeImpl.instance)) {
-      return const <InstantiatedExtension>[];
-    }
-
-    var instantiatedExtensions = <InstantiatedExtension>[];
-
-    var candidates = _withMember(extensions);
-    for (var candidate in candidates) {
-      var extension = candidate.extension;
-
-      var freshTypes = getFreshTypeParameters(extension.typeParameters);
-      var freshTypeParameters = freshTypes.freshTypeParameters;
-      var rawExtendedType = freshTypes.substitute(extension.extendedType);
-
-      var inferrer = GenericInferrer(_typeSystem, freshTypeParameters);
-      inferrer.constrainArgument(
-        targetType,
-        rawExtendedType,
-        'extendedType',
-      );
-      var typeArguments = inferrer.infer(
-        freshTypeParameters,
-        failAtError: true,
-        genericMetadataIsEnabled: _genericMetadataIsEnabled,
-      );
-      if (typeArguments == null) {
-        continue;
-      }
-
-      var substitution = Substitution.fromPairs(
-        extension.typeParameters,
-        typeArguments,
-      );
-      var extendedType = substitution.substituteType(
-        extension.extendedType,
-      );
-
-      if (!_typeSystem.isSubtypeOf(targetType, extendedType)) {
-        continue;
-      }
-
-      instantiatedExtensions.add(
-        InstantiatedExtension(candidate, substitution, extendedType),
-      );
-    }
-
-    return instantiatedExtensions;
-  }
-
-  /// Return [extensions] that define a member with the [memberName].
-  List<_CandidateExtension> _withMember(
-    Iterable<ExtensionElement> extensions,
-  ) {
-    var result = <_CandidateExtension>[];
-    for (var extension in extensions) {
-      for (var field in extension.fields) {
-        if (field.name == memberName) {
-          result.add(
-            _CandidateExtension(
-              extension,
-              getter: field.getter,
-              setter: field.setter,
-            ),
-          );
-          break;
-        }
-      }
-      if (memberName == '[]') {
-        ExecutableElement? getter;
-        ExecutableElement? setter;
-        for (var method in extension.methods) {
-          if (method.name == '[]') {
-            getter = method;
-          } else if (method.name == '[]=') {
-            setter = method;
-          }
-        }
-        if (getter != null || setter != null) {
-          result.add(
-            _CandidateExtension(extension, getter: getter, setter: setter),
-          );
-        }
-      } else {
-        for (var method in extension.methods) {
-          if (method.name == memberName) {
-            result.add(
-              _CandidateExtension(extension, getter: method),
-            );
-            break;
-          }
-        }
-      }
-    }
-    return result;
-  }
-}
-
-class InstantiatedExtension {
-  final _CandidateExtension candidate;
+class InstantiatedExtensionWithMember {
+  final _NotInstantiatedExtensionWithMember candidate;
   final MapSubstitution substitution;
   final DartType extendedType;
 
-  InstantiatedExtension(this.candidate, this.substitution, this.extendedType);
+  InstantiatedExtensionWithMember(
+    this.candidate,
+    this.substitution,
+    this.extendedType,
+  );
 
   ResolutionResult get asResolutionResult {
     return ResolutionResult(getter: getter, setter: setter);
@@ -167,11 +46,191 @@
   }
 }
 
-class _CandidateExtension {
+class InstantiatedExtensionWithoutMember {
   final ExtensionElement extension;
+  final MapSubstitution substitution;
+  final DartType extendedType;
+
+  InstantiatedExtensionWithoutMember(
+    this.extension,
+    this.substitution,
+    this.extendedType,
+  );
+}
+
+abstract class _NotInstantiatedExtension<R> {
+  final ExtensionElement extension;
+
+  _NotInstantiatedExtension(this.extension);
+
+  R instantiate({
+    required MapSubstitution substitution,
+    required DartType extendedType,
+  });
+}
+
+class _NotInstantiatedExtensionWithMember
+    extends _NotInstantiatedExtension<InstantiatedExtensionWithMember> {
   final ExecutableElement? getter;
   final ExecutableElement? setter;
 
-  _CandidateExtension(this.extension, {this.getter, this.setter})
-      : assert(getter != null || setter != null);
+  _NotInstantiatedExtensionWithMember(ExtensionElement extension,
+      {this.getter, this.setter})
+      : assert(getter != null || setter != null),
+        super(extension);
+
+  @override
+  InstantiatedExtensionWithMember instantiate({
+    required MapSubstitution substitution,
+    required DartType extendedType,
+  }) {
+    return InstantiatedExtensionWithMember(this, substitution, extendedType);
+  }
+}
+
+/// [_NotInstantiatedExtension] for any [ExtensionElement].
+class _NotInstantiatedExtensionWithoutMember
+    extends _NotInstantiatedExtension<InstantiatedExtensionWithoutMember> {
+  _NotInstantiatedExtensionWithoutMember(ExtensionElement extension)
+      : super(extension);
+
+  @override
+  InstantiatedExtensionWithoutMember instantiate({
+    required MapSubstitution substitution,
+    required DartType extendedType,
+  }) {
+    return InstantiatedExtensionWithoutMember(
+        extension, substitution, extendedType);
+  }
+}
+
+extension ExtensionsExtensions on Iterable<ExtensionElement> {
+  List<_NotInstantiatedExtensionWithMember> hasMemberWithBaseName(
+    String baseName,
+  ) {
+    var result = <_NotInstantiatedExtensionWithMember>[];
+    for (var extension in this) {
+      if (baseName == '[]') {
+        ExecutableElement? getter;
+        ExecutableElement? setter;
+        for (var method in extension.methods) {
+          if (method.name == '[]') {
+            getter = method;
+          } else if (method.name == '[]=') {
+            setter = method;
+          }
+        }
+        if (getter != null || setter != null) {
+          result.add(
+            _NotInstantiatedExtensionWithMember(
+              extension,
+              getter: getter,
+              setter: setter,
+            ),
+          );
+        }
+      } else {
+        for (var field in extension.fields) {
+          if (field.name == baseName) {
+            result.add(
+              _NotInstantiatedExtensionWithMember(
+                extension,
+                getter: field.getter,
+                setter: field.setter,
+              ),
+            );
+            break;
+          }
+        }
+        for (var method in extension.methods) {
+          if (method.name == baseName) {
+            result.add(
+              _NotInstantiatedExtensionWithMember(
+                extension,
+                getter: method,
+              ),
+            );
+            break;
+          }
+        }
+      }
+    }
+    return result;
+  }
+
+  /// Extensions that can be applied, within [targetLibrary], to [targetType].
+  List<InstantiatedExtensionWithoutMember> applicableTo({
+    required LibraryElement targetLibrary,
+    required DartType targetType,
+  }) {
+    return map((e) => _NotInstantiatedExtensionWithoutMember(e)).applicableTo(
+      targetLibrary: targetLibrary,
+      targetType: targetType,
+    );
+  }
+}
+
+extension NotInstantiatedExtensionsExtensions<R>
+    on Iterable<_NotInstantiatedExtension<R>> {
+  /// Extensions that can be applied, within [targetLibrary], to [targetType].
+  List<R> applicableTo({
+    required LibraryElement targetLibrary,
+    required DartType targetType,
+  }) {
+    if (identical(targetType, NeverTypeImpl.instance)) {
+      return <R>[];
+    }
+
+    targetLibrary as LibraryElementImpl;
+    var typeSystem = targetLibrary.typeSystem;
+    var genericMetadataIsEnabled = targetLibrary.featureSet.isEnabled(
+      Feature.generic_metadata,
+    );
+
+    var instantiated = <R>[];
+
+    for (var notInstantiated in this) {
+      var extension = notInstantiated.extension;
+
+      var freshTypes = getFreshTypeParameters(extension.typeParameters);
+      var freshTypeParameters = freshTypes.freshTypeParameters;
+      var rawExtendedType = freshTypes.substitute(extension.extendedType);
+
+      var inferrer = GenericInferrer(typeSystem, freshTypeParameters);
+      inferrer.constrainArgument(
+        targetType,
+        rawExtendedType,
+        'extendedType',
+      );
+      var typeArguments = inferrer.infer(
+        freshTypeParameters,
+        failAtError: true,
+        genericMetadataIsEnabled: genericMetadataIsEnabled,
+      );
+      if (typeArguments == null) {
+        continue;
+      }
+
+      var substitution = Substitution.fromPairs(
+        extension.typeParameters,
+        typeArguments,
+      );
+      var extendedType = substitution.substituteType(
+        extension.extendedType,
+      );
+
+      if (!typeSystem.isSubtypeOf(targetType, extendedType)) {
+        continue;
+      }
+
+      instantiated.add(
+        notInstantiated.instantiate(
+          substitution: substitution,
+          extendedType: extendedType,
+        ),
+      );
+    }
+
+    return instantiated;
+  }
 }
diff --git a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
index a166ff7..517ff5c 100644
--- a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
@@ -54,11 +54,12 @@
     SyntacticEntity nameEntity,
     String name,
   ) {
-    var extensions = ApplicableExtensions(
-      targetLibrary: _resolver.definingLibrary,
-      targetType: type,
-      memberName: name,
-    ).instantiate(_resolver.definingLibrary.accessibleExtensions);
+    var extensions = _resolver.definingLibrary.accessibleExtensions
+        .hasMemberWithBaseName(name)
+        .applicableTo(
+          targetLibrary: _resolver.definingLibrary,
+          targetType: type,
+        );
 
     if (extensions.isEmpty) {
       return ResolutionResult.none;
@@ -267,10 +268,11 @@
 
   /// Return either the most specific extension, or a list of the extensions
   /// that are ambiguous.
-  Either2<InstantiatedExtension, List<InstantiatedExtension>>
-      _chooseMostSpecific(List<InstantiatedExtension> extensions) {
-    InstantiatedExtension? bestSoFar;
-    var noneMoreSpecific = <InstantiatedExtension>[];
+  Either2<InstantiatedExtensionWithMember,
+          List<InstantiatedExtensionWithMember>>
+      _chooseMostSpecific(List<InstantiatedExtensionWithMember> extensions) {
+    InstantiatedExtensionWithMember? bestSoFar;
+    var noneMoreSpecific = <InstantiatedExtensionWithMember>[];
     for (var candidate in extensions) {
       if (noneMoreSpecific.isNotEmpty) {
         var isMostSpecific = true;
@@ -369,7 +371,8 @@
   }
 
   /// Return `true` is [e1] is more specific than [e2].
-  bool _isMoreSpecific(InstantiatedExtension e1, InstantiatedExtension e2) {
+  bool _isMoreSpecific(
+      InstantiatedExtensionWithMember e1, InstantiatedExtensionWithMember e2) {
     // 1. The latter extension is declared in a platform library, and the
     //    former extension is not.
     // 2. They are both declared in platform libraries, or both declared in
diff --git a/pkg/dds/lib/src/dap/adapters/mixins.dart b/pkg/dds/lib/src/dap/adapters/mixins.dart
index b9f307f..53de6fc 100644
--- a/pkg/dds/lib/src/dap/adapters/mixins.dart
+++ b/pkg/dds/lib/src/dap/adapters/mixins.dart
@@ -160,7 +160,7 @@
     final completer = Completer<Uri>();
     late final StreamSubscription<FileSystemEvent> vmServiceInfoFileWatcher;
 
-    Uri? tryParseServiceInfoFile(FileSystemEvent event) {
+    void tryParseServiceInfoFile(FileSystemEvent event) {
       final uri = _readVmServiceInfoFile(logger, vmServiceInfoFile);
       if (uri != null && !completer.isCompleted) {
         vmServiceInfoFileWatcher.cancel();
@@ -200,6 +200,7 @@
       // It's possible we tried to read the file before it was completely
       // written so ignore and try again on the next event.
       logger?.call('Ignoring error parsing vm-service-info file: $e');
+      return null;
     }
   }
 }
diff --git a/pkg/dds/lib/src/dap/isolate_manager.dart b/pkg/dds/lib/src/dap/isolate_manager.dart
index cbf2087..9fb0adf 100644
--- a/pkg/dds/lib/src/dap/isolate_manager.dart
+++ b/pkg/dds/lib/src/dap/isolate_manager.dart
@@ -375,6 +375,7 @@
         'Debugger failed to evaluate breakpoint $type "$expression": $e\n',
       );
     }
+    return null;
   }
 
   void _handleExit(vm.Event event) {
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index a132ce2..81e6368 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -47,6 +47,7 @@
 anyone
 ap
 api
+apis
 app
 apparently
 applicable
@@ -73,6 +74,11 @@
 atom
 atoms
 attributes
+augment
+augmentation
+augmentations
+augmenting
+augments
 auto
 automagically
 auxiliary
@@ -140,6 +146,7 @@
 breadcrumbs
 brevity
 brianwilkerson
+bridge
 bs
 bsd
 bslash
@@ -225,15 +232,18 @@
 combinator
 combine2
 combiner
+communication
 compared
 compares
 compilations
+completers
 completes
 complicating
 component's
 comprehensive
 compressed
 compression
+comprise
 concat
 concatenate
 concerned
@@ -252,6 +262,7 @@
 containers
 continuations
 contra
+contribute
 convention
 coordinated
 coordinating
@@ -310,6 +321,7 @@
 deeply
 def
 defaulting
+definitions
 degrades
 degree
 del
@@ -353,6 +365,7 @@
 disallow
 disambiguating
 disambiguator
+discovers
 disjoint
 dispatched
 distribute
@@ -420,6 +433,7 @@
 estimate
 eval
 execute
+executor
 exhausted
 existence
 existentially
@@ -643,10 +657,14 @@
 interval
 intervals
 intl
+introspect
+introspection
+introspector
 ints
 invariants
 io
 is64
+isolate
 isolated
 issuecomment
 issuing
@@ -661,6 +679,7 @@
 java
 jenkins
 jensj
+job
 johnniwinther
 js
 json
@@ -672,6 +691,7 @@
 kallentu
 kernel's
 kernel2kernel
+kill
 klass
 kmillikin
 kotlin
@@ -707,6 +727,7 @@
 libs
 lifted
 lifter
+limiting
 linearized
 linebreak
 linter
@@ -948,6 +969,7 @@
 preexisting
 premark
 preorder
+prepares
 preprocess
 presented
 presubmit
@@ -966,10 +988,12 @@
 promo
 proof
 prop
+proposal
 propose
 proposed
 proto
 protobuf
+protocol
 ps
 pulled
 pure
@@ -1048,6 +1072,7 @@
 reexports
 ref
 reflect
+reflectee
 reflective
 reg
 regis
@@ -1063,6 +1088,8 @@
 relaxes
 released
 relink
+reload
+reloading
 remapped
 remedy
 removal
@@ -1079,11 +1106,14 @@
 repo
 repositories
 repurposed
+requests
 requirement
 res
 residue
 resource
 respond
+response
+responses
 restoring
 restriction
 resumed
@@ -1131,11 +1161,13 @@
 separators
 sequencing
 sequential
+serializable
 serializables
 serializer
 serializers
 serve
 server
+serves
 service
 session
 setable
@@ -1154,6 +1186,8 @@
 shr
 shrinking
 shru
+shut
+shutting
 si
 sibling
 siblings
@@ -1186,6 +1220,8 @@
 sourcemap
 spaced
 sparse
+spawn
+spawns
 spec
 spec'ed
 specialization
@@ -1384,6 +1420,7 @@
 unifiable
 unification
 unifier
+unifies
 unify
 uninstantiable
 uninstantiated
@@ -1456,6 +1493,7 @@
 w
 waiting
 wanting
+wants
 waste
 wasted
 watch
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 273a109..8b3999a 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -238,7 +238,6 @@
 source_set("dart_api") {
   public_configs = [ ":dart_public_config" ]
   sources = [
-    "include/analyze_snapshot_api.h",
     "include/dart_api.h",
     "include/dart_api_dl.c",
     "include/dart_api_dl.h",
@@ -286,11 +285,9 @@
   public_configs = [ ":dart_public_config" ]
   sources = [
     "$target_gen_dir/version.cc",
-    "include/analyze_snapshot_api.h",
     "include/dart_api.h",
     "include/dart_native_api.h",
     "include/dart_tools_api.h",
-    "vm/analyze_snapshot_api_impl.cc",
     "vm/dart_api_impl.cc",
     "vm/native_api_impl.cc",
     "vm/version.h",
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 04e73a2..ea7d40d 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -880,45 +880,6 @@
   extra_deps += [ ":elf_loader_product" ]
 }
 
-dart_executable("analyze_snapshot") {
-  extra_configs = [ "..:dart_precompiled_runtime_config" ]
-  extra_deps = [
-    "..:libdart_precompiled_runtime",
-    "../platform:libdart_platform_precompiled_runtime",
-  ]
-
-  extra_sources = [
-    "analyze_snapshot.cc",
-    "builtin.cc",
-    "loader.cc",
-    "loader.h",
-  ]
-
-  if (dart_runtime_mode == "release") {
-    extra_deps += [ ":elf_loader_product" ]
-  } else {
-    extra_deps += [ ":elf_loader" ]
-  }
-}
-
-dart_executable("analyze_snapshot_product") {
-  use_product_mode = true
-  extra_configs = [ "..:dart_precompiled_runtime_config" ]
-  extra_deps = [
-    "..:libdart_precompiled_runtime_product",
-    "../platform:libdart_platform_precompiled_runtime_product",
-  ]
-
-  extra_sources = [
-    "analyze_snapshot.cc",
-    "builtin.cc",
-    "loader.cc",
-    "loader.h",
-  ]
-
-  extra_deps += [ ":elf_loader_product" ]
-}
-
 executable("process_test") {
   sources = [ "process_test.cc" ]
 }
diff --git a/runtime/bin/analyze_snapshot.cc b/runtime/bin/analyze_snapshot.cc
deleted file mode 100644
index 9bf6202..0000000
--- a/runtime/bin/analyze_snapshot.cc
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for 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/elf_loader.h"
-#include "bin/error_exit.h"
-#include "bin/file.h"
-
-#include "bin/options.h"
-#include "bin/platform.h"
-
-#include "include/analyze_snapshot_api.h"
-
-namespace dart {
-namespace bin {
-
-#define STRING_OPTIONS_LIST(V) V(out, out_path)
-
-#define BOOL_OPTIONS_LIST(V)                                                   \
-  V(help, help)                                                                \
-  V(version, version)
-
-#define STRING_OPTION_DEFINITION(flag, variable)                               \
-  static const char* variable = nullptr;                                       \
-  DEFINE_STRING_OPTION(flag, variable)
-STRING_OPTIONS_LIST(STRING_OPTION_DEFINITION)
-#undef STRING_OPTION_DEFINITION
-
-#define BOOL_OPTION_DEFINITION(flag, variable)                                 \
-  static bool variable = false;                                                \
-  DEFINE_BOOL_OPTION(flag, variable)
-BOOL_OPTIONS_LIST(BOOL_OPTION_DEFINITION)
-#undef BOOL_OPTION_DEFINITION
-
-// clang-format off
-static void PrintUsage() {
-  Syslog::PrintErr(
-"Usage: analyze_snapshot [<vm-flags>] [<options>] <snapshot_data>            \n"
-"                                                                            \n"
-"Common options:                                                             \n"
-"--help                                                                      \n"
-"  Display this message.                                                     \n"
-"--version                                                                   \n"
-"  Print the SDK version.                                                    \n"
-"--out                                                                       \n"
-"  Path to generate the analysis results JSON.                               \n"
-"                                                                            \n"
-"If omitting [<vm-flags>] the VM parsing the snapshot is created with the    \n"
-"following default flags:                                                    \n"
-"--enable_mirrors=false                                                      \n"
-"--background_compilation                                                    \n"
-"--lazy_async_stacks                                                         \n"
-"--precompilation                                                            \n"
-"                                                                            \n"
-"\n");
-}
-// clang-format on
-
-const uint8_t* vm_snapshot_data = nullptr;
-const uint8_t* vm_snapshot_instructions = nullptr;
-const uint8_t* vm_isolate_data = nullptr;
-const uint8_t* vm_isolate_instructions = nullptr;
-
-// Parse out the command line arguments. Returns -1 if the arguments
-// are incorrect, 0 otherwise.
-static int ParseArguments(int argc,
-                          char** argv,
-                          CommandLineOptions* vm_options,
-                          CommandLineOptions* inputs) {
-  // Skip the binary name.
-  int i = 1;
-
-  // Parse out the vm options.
-  while ((i < argc) && OptionProcessor::IsValidShortFlag(argv[i])) {
-    if (OptionProcessor::TryProcess(argv[i], vm_options)) {
-      i += 1;
-      continue;
-    }
-    vm_options->AddArgument(argv[i]);
-    i += 1;
-  }
-
-  // Parse out the kernel inputs.
-  while (i < argc) {
-    inputs->AddArgument(argv[i]);
-    i++;
-  }
-
-  if (help) {
-    PrintUsage();
-    Platform::Exit(0);
-  } else if (version) {
-    Syslog::PrintErr("Dart SDK version: %s\n", Dart_VersionString());
-    Platform::Exit(0);
-  }
-
-  // Verify consistency of arguments.
-  if (inputs->count() < 1) {
-    Syslog::PrintErr("At least one input is required\n");
-    return -1;
-  }
-
-  if (out_path == nullptr) {
-    Syslog::PrintErr(
-        "Please specify an output path for analysis with the --out flag.\n\n");
-    return -1;
-  }
-
-  return 0;
-}
-
-PRINTF_ATTRIBUTE(1, 2) static void PrintErrAndExit(const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  Syslog::VPrintErr(format, args);
-  va_end(args);
-
-  Dart_ExitScope();
-  Dart_ShutdownIsolate();
-  exit(kErrorExitCode);
-}
-
-static File* OpenFile(const char* filename) {
-  File* file = File::Open(nullptr, filename, File::kWriteTruncate);
-  if (file == nullptr) {
-    PrintErrAndExit("Error: Unable to write file: %s\n\n", filename);
-  }
-  return file;
-}
-
-static void WriteFile(const char* filename,
-                      const char* buffer,
-                      const intptr_t size) {
-  File* file = OpenFile(filename);
-  RefCntReleaseScope<File> rs(file);
-  if (!file->WriteFully(buffer, size)) {
-    PrintErrAndExit("Error: Unable to write file: %s\n\n", filename);
-  }
-}
-
-int RunAnalyzer(int argc, char** argv) {
-  // Constant mirrors gen_snapshot binary, subject to change.
-  const int EXTRA_VM_ARGUMENTS = 7;
-  CommandLineOptions vm_options(argc + EXTRA_VM_ARGUMENTS);
-  CommandLineOptions inputs(argc);
-  // Parse command line arguments.
-  if (ParseArguments(argc, argv, &vm_options, &inputs) < 0) {
-    PrintUsage();
-    return kErrorExitCode;
-  }
-
-  // Initialize VM with default flags if none are provided.
-  // TODO(#47924): Implement auto-parsing of flags from the snapshot file.
-  if (vm_options.count() == 0) {
-    vm_options.AddArgument("--enable_mirrors=false");
-    vm_options.AddArgument("--background_compilation");
-    vm_options.AddArgument("--lazy_async_stacks");
-    vm_options.AddArgument("--precompilation");
-  }
-
-  char* error = Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
-  if (error != nullptr) {
-    Syslog::PrintErr("Setting VM flags failed: %s\n", error);
-    free(error);
-    return kErrorExitCode;
-  }
-
-  // Dart_LoadELF will crash on nonexistant file non-gracefully
-  // even though it should return `nullptr`.
-  File* const file =
-      File::Open(/*namespc=*/nullptr, inputs.GetArgument(0), File::kRead);
-  if (file == nullptr) {
-    Syslog::PrintErr("Snapshot file does not exist\n");
-    return kErrorExitCode;
-  }
-  file->Release();
-
-  const char* loader_error = nullptr;
-  Dart_LoadedElf* loaded_elf = Dart_LoadELF(
-      inputs.GetArgument(0), 0, &loader_error, &vm_snapshot_data,
-      &vm_snapshot_instructions, &vm_isolate_data, &vm_isolate_instructions);
-
-  if (loaded_elf == nullptr) {
-    Syslog::PrintErr("Failure calling Dart_LoadELF:\n%s\n", loader_error);
-    return kErrorExitCode;
-  }
-
-  // Begin initialization
-  Dart_InitializeParams init_params = {};
-  memset(&init_params, 0, sizeof(init_params));
-  init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
-  init_params.vm_snapshot_data = vm_snapshot_data;
-  init_params.vm_snapshot_instructions = vm_snapshot_instructions;
-
-  init_params.file_open = DartUtils::OpenFile;
-  init_params.file_read = DartUtils::ReadFile;
-  init_params.file_write = DartUtils::WriteFile;
-  init_params.file_close = DartUtils::CloseFile;
-  init_params.entropy_source = DartUtils::EntropySource;
-
-  error = Dart_Initialize(&init_params);
-  if (error != nullptr) {
-    Syslog::PrintErr("VM initialization failed: %s\n", error);
-    free(error);
-    return kErrorExitCode;
-  }
-
-  auto isolate_group_data = std::unique_ptr<IsolateGroupData>(
-      new IsolateGroupData(nullptr, nullptr, nullptr, false));
-
-  Dart_IsolateFlags isolate_flags;
-  Dart_IsolateFlagsInitialize(&isolate_flags);
-  // Null safety can be determined from the snapshot itself
-  isolate_flags.null_safety =
-      Dart_DetectNullSafety(nullptr, nullptr, nullptr, vm_snapshot_data,
-                            vm_snapshot_instructions, nullptr, -1);
-
-  Dart_CreateIsolateGroup(nullptr, nullptr, vm_isolate_data,
-                          vm_isolate_instructions, &isolate_flags,
-                          isolate_group_data.get(),
-                          /*isolate_data=*/nullptr, &error);
-
-  if (error != nullptr) {
-    Syslog::PrintErr("Dart_CreateIsolateGroup Error: %s\n", error);
-    free(error);
-    return kErrorExitCode;
-  }
-
-  dart::snapshot_analyzer::Dart_SnapshotAnalyzerInformation info = {
-      vm_snapshot_data, vm_snapshot_instructions, vm_isolate_data,
-      vm_isolate_instructions};
-
-  char* out = NULL;
-  intptr_t out_len = 0;
-
-  Dart_EnterScope();
-  Dart_DumpSnapshotInformationAsJson(&out, &out_len, &info);
-  WriteFile(out_path, out, out_len);
-  // Since ownership of the JSON buffer is ours, free before we exit.
-  free(out);
-  Dart_ExitScope();
-  Dart_ShutdownIsolate();
-  return 0;
-}
-}  // namespace bin
-}  // namespace dart
-int main(int argc, char** argv) {
-  return dart::bin::RunAnalyzer(argc, argv);
-}
diff --git a/runtime/include/analyze_snapshot_api.h b/runtime/include/analyze_snapshot_api.h
deleted file mode 100644
index e02f461..0000000
--- a/runtime/include/analyze_snapshot_api.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
- * for 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_INCLUDE_ANALYZE_SNAPSHOT_API_H_
-#define RUNTIME_INCLUDE_ANALYZE_SNAPSHOT_API_H_
-
-#include <stdint.h>
-
-namespace dart {
-namespace snapshot_analyzer {
-typedef struct {
-  const uint8_t* vm_snapshot_data;
-  const uint8_t* vm_snapshot_instructions;
-  const uint8_t* vm_isolate_data;
-  const uint8_t* vm_isolate_instructions;
-} Dart_SnapshotAnalyzerInformation;
-
-void Dart_DumpSnapshotInformationAsJson(char** buffer,
-                                        intptr_t* buffer_length,
-                                        Dart_SnapshotAnalyzerInformation* info);
-}  // namespace snapshot_analyzer
-}  // namespace dart
-
-#endif  // RUNTIME_INCLUDE_ANALYZE_SNAPSHOT_API_H_
diff --git a/runtime/tests/vm/dart/analyze_snapshot_binary_test.dart b/runtime/tests/vm/dart/analyze_snapshot_binary_test.dart
deleted file mode 100644
index 1cec0b7..0000000
--- a/runtime/tests/vm/dart/analyze_snapshot_binary_test.dart
+++ /dev/null
@@ -1,300 +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:convert';
-import 'dart:io';
-import 'dart:async';
-
-import 'package:expect/expect.dart';
-import 'package:native_stack_traces/elf.dart';
-import 'package:path/path.dart' as path;
-
-import 'use_flag_test_helper.dart';
-
-// Used to ensure we don't have multiple equivalent calls to test.
-final _seenDescriptions = <String>{};
-
-Future<void> testAOT(String dillPath,
-    {bool useAsm = false,
-    bool forceDrops = false,
-    bool useDispatch = true,
-    bool stripUtil = false, // Note: forced true if useAsm.
-    bool stripFlag = false,
-    bool disassemble = false}) async {
-  if (const bool.fromEnvironment('dart.vm.product') && disassemble) {
-    Expect.isFalse(disassemble, 'no use of disassembler in PRODUCT mode');
-  }
-
-  final analyzeSnapshot = path.join(
-      buildDir,
-      bool.fromEnvironment('dart.vm.product')
-          ? 'analyze_snapshot_product'
-          : 'analyze_snapshot');
-
-  // For assembly, we can't test the sizes of the snapshot sections, since we
-  // don't have a Mach-O reader for Mac snapshots and for ELF, the assembler
-  // merges the text/data sections and the VM/isolate section symbols may not
-  // have length information. Thus, we force external stripping so we can test
-  // the approximate size of the stripped snapshot.
-  if (useAsm) {
-    stripUtil = true;
-  }
-
-  final descriptionBuilder = StringBuffer()..write(useAsm ? 'assembly' : 'elf');
-  if (forceDrops) {
-    descriptionBuilder.write('-dropped');
-  }
-  if (!useDispatch) {
-    descriptionBuilder.write('-nodispatch');
-  }
-  if (stripFlag) {
-    descriptionBuilder.write('-intstrip');
-  }
-  if (stripUtil) {
-    descriptionBuilder.write('-extstrip');
-  }
-  if (disassemble) {
-    descriptionBuilder.write('-disassembled');
-  }
-
-  final description = descriptionBuilder.toString();
-  Expect.isTrue(_seenDescriptions.add(description),
-      "test configuration $description would be run multiple times");
-
-  await withTempDir('analyze_snapshot_binary-$description',
-      (String tempDir) async {
-    // Generate the snapshot
-    final snapshotPath = path.join(tempDir, 'test.snap');
-    final commonSnapshotArgs = [
-      if (stripFlag) '--strip', //  gen_snapshot specific and not a VM flag.
-      if (forceDrops) ...[
-        '--dwarf-stack-traces',
-        '--no-retain-function-objects',
-        '--no-retain-code-objects'
-      ],
-      useDispatch ? '--use-table-dispatch' : '--no-use-table-dispatch',
-      if (disassemble) '--disassemble', // Not defined in PRODUCT mode.
-      dillPath,
-    ];
-
-    if (useAsm) {
-      final assemblyPath = path.join(tempDir, 'test.S');
-
-      await run(genSnapshot, <String>[
-        '--snapshot-kind=app-aot-assembly',
-        '--assembly=$assemblyPath',
-        ...commonSnapshotArgs,
-      ]);
-
-      await assembleSnapshot(assemblyPath, snapshotPath);
-    } else {
-      await run(genSnapshot, <String>[
-        '--snapshot-kind=app-aot-elf',
-        '--elf=$snapshotPath',
-        ...commonSnapshotArgs,
-      ]);
-    }
-
-    print("Snapshot generated at $snapshotPath.");
-
-    // May not be ELF, but another format.
-    final elf = Elf.fromFile(snapshotPath);
-    if (!useAsm) {
-      Expect.isNotNull(elf);
-    }
-
-    if (elf != null) {
-      // Verify some ELF file format parameters.
-      final textSections = elf.namedSections(".text");
-      Expect.isNotEmpty(textSections);
-      Expect.isTrue(
-          textSections.length <= 2, "More text sections than expected");
-      final dataSections = elf.namedSections(".rodata");
-      Expect.isNotEmpty(dataSections);
-      Expect.isTrue(
-          dataSections.length <= 2, "More data sections than expected");
-    }
-
-    final analyzerOutputPath = path.join(tempDir, 'analyze_test.json');
-
-    // This will throw if exit code is not 0.
-    await run(analyzeSnapshot, <String>[
-      '--out=$analyzerOutputPath',
-      '$snapshotPath',
-    ]);
-
-    final analyzerJsonBytes = await readFile(analyzerOutputPath);
-    final analyzerJson = json.decode(analyzerJsonBytes);
-    Expect.isFalse(analyzerJson.isEmpty);
-    Expect.isTrue(analyzerJson.keys
-        .toSet()
-        .containsAll(['snapshot_data', 'class_table', 'object_pool']));
-  });
-}
-
-Match? matchComplete(RegExp regexp, String line) {
-  Match? match = regexp.firstMatch(line);
-  if (match == null) return match;
-  if (match.start != 0 || match.end != line.length) return null;
-  return match;
-}
-
-// All fields of "Raw..." classes defined in "raw_object.h" must be included in
-// the giant macro in "raw_object_fields.cc". This function attempts to check
-// that with some basic regexes.
-testMacros() async {
-  const String className = "([a-z0-9A-Z]+)";
-  const String rawClass = "Raw$className";
-  const String fieldName = "([a-z0-9A-Z_]+)";
-
-  final Map<String, Set<String>> fields = {};
-
-  final String rawObjectFieldsPath =
-      path.join(sdkDir, 'runtime', 'vm', 'raw_object_fields.cc');
-  final RegExp fieldEntry = RegExp(" *F\\($className, $fieldName\\) *\\\\?");
-
-  await for (String line in File(rawObjectFieldsPath)
-      .openRead()
-      .cast<List<int>>()
-      .transform(utf8.decoder)
-      .transform(LineSplitter())) {
-    Match? match = matchComplete(fieldEntry, line);
-    if (match != null) {
-      fields
-          .putIfAbsent(match.group(1)!, () => Set<String>())
-          .add(match.group(2)!);
-    }
-  }
-
-  final RegExp classStart = RegExp("class $rawClass : public $rawClass {");
-  final RegExp classEnd = RegExp("}");
-  final RegExp field = RegExp("  $rawClass. +$fieldName;.*");
-
-  final String rawObjectPath =
-      path.join(sdkDir, 'runtime', 'vm', 'raw_object.h');
-
-  String? currentClass;
-  bool hasMissingFields = false;
-  await for (String line in File(rawObjectPath)
-      .openRead()
-      .cast<List<int>>()
-      .transform(utf8.decoder)
-      .transform(LineSplitter())) {
-    Match? match = matchComplete(classStart, line);
-    if (match != null) {
-      currentClass = match.group(1);
-      continue;
-    }
-    match = matchComplete(classEnd, line);
-    if (match != null) {
-      currentClass = null;
-      continue;
-    }
-    match = matchComplete(field, line);
-    if (match != null && currentClass != null) {
-      if (fields[currentClass] == null) {
-        hasMissingFields = true;
-        print("$currentClass is missing entirely.");
-        continue;
-      }
-      if (!fields[currentClass]!.contains(match.group(2)!)) {
-        hasMissingFields = true;
-        print("$currentClass is missing ${match.group(2)!}.");
-      }
-    }
-  }
-
-  if (hasMissingFields) {
-    Expect.fail("$rawObjectFieldsPath is missing some fields. "
-        "Please update it to match $rawObjectPath.");
-  }
-}
-
-main() async {
-  void printSkip(String description) =>
-      print('Skipping $description for ${path.basename(buildDir)} '
-              'on ${Platform.operatingSystem}' +
-          (clangBuildToolsDir == null ? ' without //buildtools' : ''));
-
-  // We don't have access to the SDK on Android.
-  if (Platform.isAndroid) {
-    printSkip('all tests');
-    return;
-  }
-
-  await testMacros();
-
-  await withTempDir('analyze_snapshot_binary', (String tempDir) async {
-    // We only need to generate the dill file once for all JIT tests.
-    final _thisTestPath = path.join(sdkDir, 'runtime', 'tests', 'vm', 'dart',
-        'analyze_snapshot_binary_test.dart');
-
-    // We only need to generate the dill file once for all AOT tests.
-    final aotDillPath = path.join(tempDir, 'aot_test.dill');
-    await run(genKernel, <String>[
-      '--aot',
-      '--platform',
-      platformDill,
-      ...Platform.executableArguments.where((arg) =>
-          arg.startsWith('--enable-experiment=') ||
-          arg == '--sound-null-safety' ||
-          arg == '--no-sound-null-safety'),
-      '-o',
-      aotDillPath,
-      _thisTestPath
-    ]);
-
-    // Just as a reminder for AOT tests:
-    // * If useAsm is true, then stripUtil is forced (as the assembler may add
-    //   extra information that needs stripping), so no need to specify
-    //   stripUtil for useAsm tests.
-
-    // Test unstripped ELF generation directly.
-    await testAOT(aotDillPath);
-    await testAOT(aotDillPath, forceDrops: true);
-    await testAOT(aotDillPath, forceDrops: true, useDispatch: false);
-
-    // Test flag-stripped ELF generation.
-    await testAOT(aotDillPath, stripFlag: true);
-
-    // Since we can't force disassembler support after the fact when running
-    // in PRODUCT mode, skip any --disassemble tests. Do these tests last as
-    // they have lots of output and so the log will be truncated.
-    if (!const bool.fromEnvironment('dart.vm.product')) {
-      // Regression test for dartbug.com/41149.
-      await testAOT(aotDillPath, disassemble: true);
-    }
-
-    // We neither generate assembly nor have a stripping utility on Windows.
-    if (Platform.isWindows) {
-      printSkip('external stripping and assembly tests');
-      return;
-    }
-
-    // The native strip utility on Mac OS X doesn't recognize ELF files.
-    if (Platform.isMacOS && clangBuildToolsDir == null) {
-      printSkip('ELF external stripping test');
-    } else {
-      // Test unstripped ELF generation that is then externally stripped.
-      await testAOT(aotDillPath, stripUtil: true);
-    }
-
-    // TODO(sstrickl): Currently we can't assemble for SIMARM64 on MacOSX.
-    // For example, the test runner still uses blobs for
-    // dartkp-mac-*-simarm64. Change assembleSnapshot and remove this check
-    // when we can.
-    if (Platform.isMacOS && buildDir.endsWith('SIMARM64')) {
-      printSkip('assembly tests');
-      return;
-    }
-    // Test unstripped assembly generation that is then externally stripped.
-    await testAOT(aotDillPath, useAsm: true);
-    // Test stripped assembly generation that is then externally stripped.
-    await testAOT(aotDillPath, useAsm: true, stripFlag: true);
-  });
-}
-
-Future<String> readFile(String file) {
-  return new File(file).readAsString();
-}
diff --git a/runtime/tests/vm/dart/regress_flutter66765_test.dart b/runtime/tests/vm/dart/regress_flutter66765_test.dart
new file mode 100644
index 0000000..c47c966
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_flutter66765_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for https://github.com/flutter/flutter/issues/66765
+// Verifies that AOT compiler doesn't crash on a particular flow graph.
+
+class TutorialBloc {
+  TutorialBloc();
+
+  Stream<TutorialStates> mapEventToState(TutorialEvents event) async* {
+    switch (event.action) {
+      default:
+        yield TutorialInitState();
+    }
+  }
+}
+
+enum TutorialAction { dummyData }
+
+class TutorialEvents {
+  final TutorialAction action;
+  const TutorialEvents(this.action);
+}
+
+abstract class TutorialStates {}
+
+class TutorialInitState extends TutorialStates {}
+
+List<dynamic> l = [TutorialBloc()];
+
+void main() async {
+  if (l.length > 1) {
+    l[0].mapEventToState(42);
+  }
+}
diff --git a/runtime/tests/vm/dart_2/analyze_snapshot_binary_test.dart b/runtime/tests/vm/dart_2/analyze_snapshot_binary_test.dart
deleted file mode 100644
index 48f91fb..0000000
--- a/runtime/tests/vm/dart_2/analyze_snapshot_binary_test.dart
+++ /dev/null
@@ -1,300 +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.
-
-// @dart = 2.9
-
-import 'dart:convert';
-import 'dart:io';
-import 'dart:async';
-
-import 'package:expect/expect.dart';
-import 'package:native_stack_traces/elf.dart';
-import 'package:path/path.dart' as path;
-
-import 'use_flag_test_helper.dart';
-
-// Used to ensure we don't have multiple equivalent calls to test.
-final _seenDescriptions = <String>{};
-
-Future<void> testAOT(String dillPath,
-    {bool useAsm = false,
-    bool forceDrops = false,
-    bool useDispatch = true,
-    bool stripUtil = false, // Note: forced true if useAsm.
-    bool stripFlag = false,
-    bool disassemble = false}) async {
-  if (const bool.fromEnvironment('dart.vm.product') && disassemble) {
-    Expect.isFalse(disassemble, 'no use of disassembler in PRODUCT mode');
-  }
-
-  final analyzeSnapshot = path.join(
-      buildDir,
-      bool.fromEnvironment('dart.vm.product')
-          ? 'analyze_snapshot_product'
-          : 'analyze_snapshot');
-
-  // For assembly, we can't test the sizes of the snapshot sections, since we
-  // don't have a Mach-O reader for Mac snapshots and for ELF, the assembler
-  // merges the text/data sections and the VM/isolate section symbols may not
-  // have length information. Thus, we force external stripping so we can test
-  // the approximate size of the stripped snapshot.
-  if (useAsm) {
-    stripUtil = true;
-  }
-
-  final descriptionBuilder = StringBuffer()..write(useAsm ? 'assembly' : 'elf');
-  if (forceDrops) {
-    descriptionBuilder.write('-dropped');
-  }
-  if (!useDispatch) {
-    descriptionBuilder.write('-nodispatch');
-  }
-  if (stripFlag) {
-    descriptionBuilder.write('-intstrip');
-  }
-  if (stripUtil) {
-    descriptionBuilder.write('-extstrip');
-  }
-  if (disassemble) {
-    descriptionBuilder.write('-disassembled');
-  }
-
-  final description = descriptionBuilder.toString();
-  Expect.isTrue(_seenDescriptions.add(description),
-      "test configuration $description would be run multiple times");
-
-  await withTempDir('analyze_snapshot_binary-$description',
-      (String tempDir) async {
-    // Generate the snapshot
-    final snapshotPath = path.join(tempDir, 'test.snap');
-    final commonSnapshotArgs = [
-      if (stripFlag) '--strip', //  gen_snapshot specific and not a VM flag.
-      if (forceDrops) ...[
-        '--dwarf-stack-traces',
-        '--no-retain-function-objects',
-        '--no-retain-code-objects'
-      ],
-      useDispatch ? '--use-table-dispatch' : '--no-use-table-dispatch',
-      if (disassemble) '--disassemble', // Not defined in PRODUCT mode.
-      dillPath,
-    ];
-
-    if (useAsm) {
-      final assemblyPath = path.join(tempDir, 'test.S');
-
-      await run(genSnapshot, <String>[
-        '--snapshot-kind=app-aot-assembly',
-        '--assembly=$assemblyPath',
-        ...commonSnapshotArgs,
-      ]);
-
-      await assembleSnapshot(assemblyPath, snapshotPath);
-    } else {
-      await run(genSnapshot, <String>[
-        '--snapshot-kind=app-aot-elf',
-        '--elf=$snapshotPath',
-        ...commonSnapshotArgs,
-      ]);
-    }
-
-    print("Snapshot generated at $snapshotPath.");
-
-    // May not be ELF, but another format.
-    final elf = Elf.fromFile(snapshotPath);
-    if (!useAsm) {
-      Expect.isNotNull(elf);
-    }
-
-    if (elf != null) {
-      // Verify some ELF file format parameters.
-      final textSections = elf.namedSections(".text");
-      Expect.isNotEmpty(textSections);
-      Expect.isTrue(
-          textSections.length <= 2, "More text sections than expected");
-      final dataSections = elf.namedSections(".rodata");
-      Expect.isNotEmpty(dataSections);
-      Expect.isTrue(
-          dataSections.length <= 2, "More data sections than expected");
-    }
-
-    final analyzerOutputPath = path.join(tempDir, 'analyze_test.json');
-
-    // This will throw if exit code is not 0.
-    await run(analyzeSnapshot, <String>[
-      '--out=$analyzerOutputPath',
-      '$snapshotPath',
-    ]);
-
-    final analyzerJsonBytes = await readFile(analyzerOutputPath);
-    final analyzerJson = json.decode(analyzerJsonBytes);
-    Expect.isFalse(analyzerJson.isEmpty);
-    Expect.isTrue(analyzerJson.keys
-        .toSet()
-        .containsAll(['snapshot_data', 'class_table', 'object_pool']));
-  });
-}
-
-Match matchComplete(RegExp regexp, String line) {
-  Match match = regexp.firstMatch(line);
-  if (match == null) return match;
-  if (match.start != 0 || match.end != line.length) return null;
-  return match;
-}
-
-// All fields of "Raw..." classes defined in "raw_object.h" must be included in
-// the giant macro in "raw_object_fields.cc". This function attempts to check
-// that with some basic regexes.
-testMacros() async {
-  const String className = "([a-z0-9A-Z]+)";
-  const String rawClass = "Raw$className";
-  const String fieldName = "([a-z0-9A-Z_]+)";
-
-  final Map<String, Set<String>> fields = {};
-
-  final String rawObjectFieldsPath =
-      path.join(sdkDir, 'runtime', 'vm', 'raw_object_fields.cc');
-  final RegExp fieldEntry = RegExp(" *F\\($className, $fieldName\\) *\\\\?");
-
-  await for (String line in File(rawObjectFieldsPath)
-      .openRead()
-      .cast<List<int>>()
-      .transform(utf8.decoder)
-      .transform(LineSplitter())) {
-    Match match = matchComplete(fieldEntry, line);
-    if (match != null) {
-      fields
-          .putIfAbsent(match.group(1), () => Set<String>())
-          .add(match.group(2));
-    }
-  }
-
-  final RegExp classStart = RegExp("class $rawClass : public $rawClass {");
-  final RegExp classEnd = RegExp("}");
-  final RegExp field = RegExp("  $rawClass. +$fieldName;.*");
-
-  final String rawObjectPath =
-      path.join(sdkDir, 'runtime', 'vm', 'raw_object.h');
-
-  String currentClass;
-  bool hasMissingFields = false;
-  await for (String line in File(rawObjectPath)
-      .openRead()
-      .cast<List<int>>()
-      .transform(utf8.decoder)
-      .transform(LineSplitter())) {
-    Match match = matchComplete(classStart, line);
-    if (match != null) {
-      currentClass = match.group(1);
-      continue;
-    }
-
-    match = matchComplete(classEnd, line);
-    if (match != null) {
-      currentClass = null;
-      continue;
-    }
-
-    match = matchComplete(field, line);
-    if (match != null && currentClass != null) {
-      if (fields[currentClass] == null) {
-        hasMissingFields = true;
-        print("$currentClass is missing entirely.");
-        continue;
-      }
-      if (!fields[currentClass].contains(match.group(2))) {
-        hasMissingFields = true;
-        print("$currentClass is missing ${match.group(2)}.");
-      }
-    }
-  }
-
-  if (hasMissingFields) {
-    Expect.fail("$rawObjectFieldsPath is missing some fields. "
-        "Please update it to match $rawObjectPath.");
-  }
-}
-
-main() async {
-  void printSkip(String description) =>
-      print('Skipping $description for ${path.basename(buildDir)} '
-              'on ${Platform.operatingSystem}' +
-          (clangBuildToolsDir == null ? ' without //buildtools' : ''));
-
-  // We don't have access to the SDK on Android.
-  if (Platform.isAndroid) {
-    printSkip('all tests');
-    return;
-  }
-
-  await testMacros();
-
-  await withTempDir('analyze_snapshot_binary', (String tempDir) async {
-    // We only need to generate the dill file once for all JIT tests.
-    final _thisTestPath = path.join(sdkDir, 'runtime', 'tests', 'vm', 'dart_2',
-        'analyze_snapshot_binary_test.dart');
-
-    // We only need to generate the dill file once for all AOT tests.
-    final aotDillPath = path.join(tempDir, 'aot_test.dill');
-    await run(genKernel, <String>[
-      '--aot',
-      '--platform',
-      platformDill,
-      '-o',
-      aotDillPath,
-      _thisTestPath
-    ]);
-
-    // Just as a reminder for AOT tests:
-    // * If useAsm is true, then stripUtil is forced (as the assembler may add
-    //   extra information that needs stripping), so no need to specify
-    //   stripUtil for useAsm tests.
-
-    // Test unstripped ELF generation directly.
-    await testAOT(aotDillPath);
-    await testAOT(aotDillPath, forceDrops: true);
-    await testAOT(aotDillPath, forceDrops: true, useDispatch: false);
-
-    // Test flag-stripped ELF generation.
-    await testAOT(aotDillPath, stripFlag: true);
-
-    // Since we can't force disassembler support after the fact when running
-    // in PRODUCT mode, skip any --disassemble tests. Do these tests last as
-    // they have lots of output and so the log will be truncated.
-    if (!const bool.fromEnvironment('dart.vm.product')) {
-      // Regression test for dartbug.com/41149.
-      await testAOT(aotDillPath, disassemble: true);
-    }
-
-    // We neither generate assembly nor have a stripping utility on Windows.
-    if (Platform.isWindows) {
-      printSkip('external stripping and assembly tests');
-      return;
-    }
-
-    // The native strip utility on Mac OS X doesn't recognize ELF files.
-    if (Platform.isMacOS && clangBuildToolsDir == null) {
-      printSkip('ELF external stripping test');
-    } else {
-      // Test unstripped ELF generation that is then externally stripped.
-      await testAOT(aotDillPath, stripUtil: true);
-    }
-
-    // TODO(sstrickl): Currently we can't assemble for SIMARM64 on MacOSX.
-    // For example, the test runner still uses blobs for
-    // dartkp-mac-*-simarm64. Change assembleSnapshot and remove this check
-    // when we can.
-    if (Platform.isMacOS && buildDir.endsWith('SIMARM64')) {
-      printSkip('assembly tests');
-      return;
-    }
-    // Test unstripped assembly generation that is then externally stripped.
-    await testAOT(aotDillPath, useAsm: true);
-    // Test stripped assembly generation that is then externally stripped.
-    await testAOT(aotDillPath, useAsm: true, stripFlag: true);
-  });
-}
-
-Future<String> readFile(String file) {
-  return new File(file).readAsString();
-}
diff --git a/runtime/tests/vm/dart_2/regress_flutter66765_test.dart b/runtime/tests/vm/dart_2/regress_flutter66765_test.dart
new file mode 100644
index 0000000..af3337c
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_flutter66765_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.9
+
+// Regression test for https://github.com/flutter/flutter/issues/66765
+// Verifies that AOT compiler doesn't crash on a particular flow graph.
+
+class TutorialBloc {
+  TutorialBloc();
+
+  Stream<TutorialStates> mapEventToState(TutorialEvents event) async* {
+    switch (event.action) {
+      default:
+        yield TutorialInitState();
+    }
+  }
+}
+
+enum TutorialAction { dummyData }
+
+class TutorialEvents {
+  final TutorialAction action;
+  const TutorialEvents(this.action);
+}
+
+abstract class TutorialStates {}
+
+class TutorialInitState extends TutorialStates {}
+
+List<dynamic> l = [TutorialBloc()];
+
+void main() async {
+  if (l.length > 1) {
+    l[0].mapEventToState(42);
+  }
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 5e342f3..f4bc06c 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -37,9 +37,7 @@
 dart_2/stack_overflow_shared_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
 
 [ $arch == ia32 ]
-dart/analyze_snapshot_binary_test: SkipByDesign # No IA32 support.
 dart/disassemble_aot_test: SkipByDesign # IA32 does not support AOT.
-dart_2/analyze_snapshot_binary_test: SkipByDesign # No IA32 support.
 dart_2/disassemble_aot_test: SkipByDesign # IA32 does not support AOT.
 
 [ $builder_tag == asan ]
diff --git a/runtime/vm/analyze_snapshot_api_impl.cc b/runtime/vm/analyze_snapshot_api_impl.cc
deleted file mode 100644
index ef73e76..0000000
--- a/runtime/vm/analyze_snapshot_api_impl.cc
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for 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 "include/analyze_snapshot_api.h"
-#include "vm/dart_api_impl.h"
-#include "vm/json_writer.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
-#include "vm/thread.h"
-
-namespace dart {
-namespace snapshot_analyzer {
-void DumpClassTable(Thread* thread, dart::JSONWriter* js) {
-  auto class_table = thread->isolate_group()->class_table();
-
-  Class& cls = Class::Handle();
-  String& name = String::Handle();
-  js->OpenArray("class_table");
-
-  for (intptr_t i = 1; i < class_table->NumCids(); i++) {
-    if (!class_table->HasValidClassAt(i)) {
-      continue;
-    }
-    cls = class_table->At(i);
-    if (!cls.IsNull()) {
-      name = cls.Name();
-      js->OpenObject();
-      js->PrintProperty("id", i);
-      js->PrintProperty("name", name.ToCString());
-
-      // Note: Some meta info is stripped from the snapshot, it's important
-      // to check every field for NULL to avoid segfaults.
-      const Library& library = Library::Handle(cls.library());
-      if (!library.IsNull()) {
-        String& lib_name = String::Handle();
-        lib_name = String::NewFormatted(
-            Heap::kOld, "%s%s", String::Handle(library.url()).ToCString(),
-            String::Handle(library.private_key()).ToCString());
-        js->PrintProperty("library", lib_name.ToCString());
-      }
-
-      const AbstractType& super_type = AbstractType::Handle(cls.super_type());
-      if (super_type.IsNull()) {
-      } else {
-        const String& super_name = String::Handle(super_type.Name());
-        js->PrintProperty("super_class", super_name.ToCString());
-      }
-
-      const Array& interfaces_array = Array::Handle(cls.interfaces());
-      if (!interfaces_array.IsNull()) {
-        if (interfaces_array.Length() > 0) {
-          js->OpenArray("interfaces");
-          AbstractType& interface = AbstractType::Handle();
-          intptr_t len = interfaces_array.Length();
-          for (intptr_t i = 0; i < len; i++) {
-            interface ^= interfaces_array.At(i);
-            js->PrintValue(interface.ToCString());
-          }
-          js->CloseArray();
-        }
-      }
-      const Array& functions_array = Array::Handle(cls.functions());
-      if (!functions_array.IsNull()) {
-        if (functions_array.Length() > 0) {
-          js->OpenArray("functions");
-          Function& function = Function::Handle();
-          intptr_t len = functions_array.Length();
-          for (intptr_t i = 0; i < len; i++) {
-            function ^= functions_array.At(i);
-            if (function.IsNull() || !function.HasCode()) {
-              continue;
-            }
-            const Code& code = Code::Handle(function.CurrentCode());
-            intptr_t size = code.Size();
-
-            // Note: Some entry points here will be pointing to the VM
-            // instructions buffer.
-
-            // Note: code_entry will contain the address in the memory
-            // In order to resolve it to a relative offset in the instructions
-            // buffer we need to pick the base address and substract it from
-            // the entry point address.
-            auto code_entry = code.EntryPoint();
-            // On different architectures the type of the underlying
-            // dart::uword can result in an unsigned long long vs unsigned long
-            // mismatch.
-            uint64_t code_addr = static_cast<uint64_t>(code_entry);
-            js->OpenObject();
-            js->PrintProperty("name", function.ToCString());
-            js->PrintfProperty("code_entry", "0x%" PRIx64 "", code_addr);
-            js->PrintProperty("size", size);
-            js->CloseObject();
-          }
-          js->CloseArray();
-        }
-      }
-      const Array& fields_array = Array::Handle(cls.fields());
-      if (fields_array.IsNull()) {
-      } else {
-        if (fields_array.Length() > 0) {
-          js->OpenArray("fields");
-          Field& field = Field::Handle();
-          for (intptr_t i = 0; i < fields_array.Length(); i++) {
-            field ^= fields_array.At(i);
-            js->PrintValue(field.ToCString());
-          }
-          js->CloseArray();
-        }
-      }
-    }
-    js->CloseObject();
-  }
-  js->CloseArray();
-}
-void DumpObjectPool(Thread* thread, dart::JSONWriter* js) {
-  js->OpenArray("object_pool");
-
-  auto pool_ptr = thread->isolate_group()->object_store()->global_object_pool();
-  const auto& pool = ObjectPool::Handle(ObjectPool::RawCast(pool_ptr));
-  for (intptr_t i = 0; i < pool.Length(); i++) {
-    auto type = pool.TypeAt(i);
-    // Only interested in tagged objects.
-    // All these checks are required otherwise ToCString() will segfault.
-    if (type != ObjectPool::EntryType::kTaggedObject) {
-      continue;
-    }
-
-    auto entry = pool.ObjectAt(i);
-    if (!entry.IsHeapObject()) {
-      continue;
-    }
-
-    intptr_t cid = entry.GetClassId();
-
-    switch (cid) {
-      case kOneByteStringCid: {
-        js->OpenObject();
-        js->PrintProperty("type", "kOneByteString");
-        js->PrintProperty("id", i);
-        js->PrintProperty("offset", pool.element_offset(i));
-        js->PrintProperty("value", Object::Handle(entry).ToCString());
-        js->CloseObject();
-        break;
-      }
-      case kTwoByteStringCid: {
-        // TODO(#47924): Add support.
-        break;
-      }
-      default:
-        // TODO(#47924): Investigate other types of objects to parse.
-        break;
-    }
-  }
-  js->CloseArray();
-}
-// TODO(#47924): Add processing of the entires in the dispatch table.
-// Below is an example skeleton
-// void DumpDispatchTable(dart::Thread* thread) {
-//   auto dispatch = thread->isolate_group()->dispatch_table();
-//   auto length = dispatch->length();
-// We must unbias the array entries so we don't crash on null access.
-//   auto entries = dispatch->ArrayOrigin() - DispatchTable::OriginElement();
-//   for (intptr_t i = 0; i < length; i++) {
-//     OS::Print("0x%lx at %ld\n", entries[i], i);
-//   }
-// }
-
-void Dart_DumpSnapshotInformationAsJson(
-    char** buffer,
-    intptr_t* buffer_length,
-    Dart_SnapshotAnalyzerInformation* info) {
-  Thread* thread = Thread::Current();
-  DARTSCOPE(thread);
-  JSONWriter js;
-  // Open empty object so output is valid/parsable JSON.
-  js.OpenObject();
-  js.OpenObject("snapshot_data");
-  // Base addreses of the snapshot data, useful to calculate relative offsets.
-  js.PrintfProperty("vm_data", "%p", info->vm_snapshot_data);
-  js.PrintfProperty("vm_instructions", "%p", info->vm_snapshot_instructions);
-  js.PrintfProperty("isolate_data", "%p", info->vm_isolate_data);
-  js.PrintfProperty("isolate_instructions", "%p",
-                    info->vm_isolate_instructions);
-  js.CloseObject();
-
-  {
-    // Debug builds assert that our thread has a lock before accessing
-    // vm internal fields.
-    SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
-    DumpClassTable(thread, &js);
-    DumpObjectPool(thread, &js);
-  }
-
-  // Close our empty object.
-  js.CloseObject();
-
-  // Give ownership to caller.
-  js.Steal(buffer, buffer_length);
-}
-}  // namespace snapshot_analyzer
-}  // namespace dart
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index cd7dcb5..878bcec 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -1299,12 +1299,15 @@
   // TODO(fschneider): Implement a faster way to get the block of an
   // instruction.
   Instruction* result = previous();
-  ASSERT(result != nullptr);
-  while (!result->IsBlockEntry()) {
+  while ((result != nullptr) && !result->IsBlockEntry()) {
     result = result->previous();
-    ASSERT(result != nullptr);
   }
-  return result->AsBlockEntry();
+  // InlineExitCollector::RemoveUnreachableExits may call
+  // Instruction::GetBlock on instructions which are not properly linked
+  // to the flow graph (as collected exits may belong to unreachable
+  // fragments), so this code should gracefully handle the absence of
+  // BlockEntry.
+  return (result != nullptr) ? result->AsBlockEntry() : nullptr;
 }
 
 void ForwardInstructionIterator::RemoveCurrentFromGraph() {
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 1124ea1..00d4adf 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -28,11 +28,16 @@
 }
 
 Fragment& Fragment::operator+=(const Fragment& other) {
-  if (entry == NULL) {
+  if (entry == nullptr) {
     entry = other.entry;
     current = other.current;
-  } else if (current != NULL && other.entry != NULL) {
-    current->LinkTo(other.entry);
+  } else if (other.entry != nullptr) {
+    if (current != nullptr) {
+      current->LinkTo(other.entry);
+    }
+    // Although [other.entry] could be unreachable (if this fragment is
+    // closed), there could be a yield continuation point in the middle of
+    // [other] fragment so [other.current] is still reachable.
     current = other.current;
   }
   return *this;
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index f5a7544..2b4fa76 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -26,7 +26,6 @@
   dart_stripped_binary = "dart"
   dart_precompiled_runtime_stripped_binary = "dart_precompiled_runtime_product"
   gen_snapshot_stripped_binary = "gen_snapshot_product"
-  analyze_snapshot_binary = "analyze_snapshot_product"
 }
 
 # The directory layout of the SDK is as follows:
@@ -331,15 +330,6 @@
   ]
 }
 
-copy("copy_analyze_snapshot") {
-  visibility = [ ":group_dart2native" ]
-  deps = [ "../runtime/bin:analyze_snapshot_product" ]
-  src_dir =
-      get_label_info("../runtime/bin:analyze_snapshot_product", "root_out_dir")
-  sources = [ "$src_dir/${analyze_snapshot_binary}${executable_suffix}" ]
-  outputs = [ "$root_out_dir/$dart_sdk_output/bin/utils/analyze_snapshot${executable_suffix}" ]
-}
-
 copy("copy_vm_platform_strong_product") {
   visibility = [ ":group_dart2native" ]
   deps = [ "../runtime/vm:vm_platform_product" ]
@@ -359,7 +349,6 @@
 
 group("group_dart2native") {
   deps = [
-    ":copy_analyze_snapshot",
     ":copy_dartaotruntime",
     ":copy_gen_kernel_snapshot",
     ":copy_gen_snapshot",
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 448b653..3298b08 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -7061,6 +7061,14 @@
     setProperty('font-weight', value, '');
   }
 
+  /** Gets the value of "gap" */
+  String get gap => getPropertyValue('gap');
+
+  /** Sets the value of "gap" */
+  set gap(String value) {
+    setProperty('gap', value, '');
+  }
+
   /** Gets the value of "grid" */
   String get grid => getPropertyValue('grid');
 
@@ -7117,6 +7125,14 @@
     setProperty('grid-column-end', value, '');
   }
 
+  /** Gets the value of "grid-column-gap" */
+  String get gridColumnGap => getPropertyValue('grid-column-gap');
+
+  /** Sets the value of "grid-column-gap" */
+  set gridColumnGap(String value) {
+    setProperty('grid-column-gap', value, '');
+  }
+
   /** Gets the value of "grid-column-start" */
   String get gridColumnStart => getPropertyValue('grid-column-start');
 
@@ -7141,6 +7157,14 @@
     setProperty('grid-row-end', value, '');
   }
 
+  /** Gets the value of "grid-row-gap" */
+  String get gridRowGap => getPropertyValue('grid-row-gap');
+
+  /** Sets the value of "grid-row-gap" */
+  set gridRowGap(String value) {
+    setProperty('grid-row-gap', value, '');
+  }
+
   /** Gets the value of "grid-row-start" */
   String get gridRowStart => getPropertyValue('grid-row-start');
 
@@ -7997,6 +8021,14 @@
     setProperty('right', value, '');
   }
 
+  /** Gets the value of "row-gap" */
+  String get rowGap => getPropertyValue('row-gap');
+
+  /** Sets the value of "row-gap" */
+  set rowGap(String value) {
+    setProperty('row-gap', value, '');
+  }
+
   /** Gets the value of "rtl-ordering" */
   String get rtlOrdering => getPropertyValue('rtl-ordering');
 
diff --git a/tools/VERSION b/tools/VERSION
index d08d4df..ceb61c5 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 117
+PRERELEASE 118
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/dom/scripts/CSSPropertyNames.in b/tools/dom/scripts/CSSPropertyNames.in
index 39b49ad..cf59dca 100644
--- a/tools/dom/scripts/CSSPropertyNames.in
+++ b/tools/dom/scripts/CSSPropertyNames.in
@@ -288,7 +288,8 @@
 -webkit-column-break-inside
 -webkit-column-count
 column-fill
--webkit-column-gap
+column-gap
+-webkit-column-gap alias_for=column-gap
 -webkit-column-rule
 -webkit-column-rule-color
 -webkit-column-rule-style
@@ -321,12 +322,14 @@
 justify-content
 -webkit-justify-content alias_for=justify-content
 -webkit-font-size-delta
+gap
 grid-auto-columns
 grid-auto-flow
 grid-auto-rows
 grid-area
 grid-column
 grid-column-end
+grid-column-gap
 grid-column-start
 grid
 grid-template
@@ -334,6 +337,7 @@
 grid-template-rows
 grid-row
 grid-row-end
+grid-row-gap
 grid-row-start
 grid-template-areas
 -webkit-highlight
@@ -387,6 +391,7 @@
 -webkit-perspective-origin-x
 -webkit-perspective-origin-y
 -webkit-print-color-adjust
+row-gap
 -webkit-rtl-ordering
 -webkit-ruby-position
 -webkit-text-combine
diff --git a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
index 914faca..a81ff5a 100644
--- a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
@@ -3139,6 +3139,15 @@
     setProperty('font-weight', value, '');
   }
 
+  /** Gets the value of "gap" */
+  String get gap =>
+    getPropertyValue('gap');
+
+  /** Sets the value of "gap" */
+  set gap(String value) {
+    setProperty('gap', value, '');
+  }
+
   /** Gets the value of "grid" */
   String get grid =>
     getPropertyValue('grid');
@@ -3202,6 +3211,15 @@
     setProperty('grid-column-end', value, '');
   }
 
+  /** Gets the value of "grid-column-gap" */
+  String get gridColumnGap =>
+    getPropertyValue('grid-column-gap');
+
+  /** Sets the value of "grid-column-gap" */
+  set gridColumnGap(String value) {
+    setProperty('grid-column-gap', value, '');
+  }
+
   /** Gets the value of "grid-column-start" */
   String get gridColumnStart =>
     getPropertyValue('grid-column-start');
@@ -3229,6 +3247,15 @@
     setProperty('grid-row-end', value, '');
   }
 
+  /** Gets the value of "grid-row-gap" */
+  String get gridRowGap =>
+    getPropertyValue('grid-row-gap');
+
+  /** Sets the value of "grid-row-gap" */
+  set gridRowGap(String value) {
+    setProperty('grid-row-gap', value, '');
+  }
+
   /** Gets the value of "grid-row-start" */
   String get gridRowStart =>
     getPropertyValue('grid-row-start');
@@ -4192,6 +4219,15 @@
     setProperty('right', value, '');
   }
 
+  /** Gets the value of "row-gap" */
+  String get rowGap =>
+    getPropertyValue('row-gap');
+
+  /** Sets the value of "row-gap" */
+  set rowGap(String value) {
+    setProperty('row-gap', value, '');
+  }
+
   /** Gets the value of "rtl-ordering" */
   String get rtlOrdering =>
     getPropertyValue('rtl-ordering');
diff --git a/tools/gn.py b/tools/gn.py
index 32a6953..fe4718d 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -269,8 +269,6 @@
             'exe.stripped/dart_precompiled_runtime_product')
         gn_args['gen_snapshot_stripped_binary'] = (
             'exe.stripped/gen_snapshot_product')
-        gn_args['analyze_snapshot_binary'] = (
-            'exe.stripped/analyze_snapshot_product')
 
     # Setup the user-defined sysroot.
     if UseSysroot(args, gn_args):