Version 2.16.0-111.0.dev

Merge commit '78b7fc5ac19d6c6550438aa5ecdbd19983c69c91' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
index c60aa80..81a7644 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
@@ -1259,8 +1259,14 @@
 
   @override
   void handleCommentReference(
-      Token? newKeyword, Token? prefix, Token? period, Token token) {
-    listener?.handleCommentReference(newKeyword, prefix, period, token);
+      Token? newKeyword,
+      Token? firstToken,
+      Token? firstPeriod,
+      Token? secondToken,
+      Token? secondPeriod,
+      Token thirdToken) {
+    listener?.handleCommentReference(newKeyword, firstToken, firstPeriod,
+        secondToken, secondPeriod, thirdToken);
   }
 
   @override
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
index 332225f..be42436 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
@@ -1840,13 +1840,20 @@
 
   /// A single comment reference has been parsed.
   /// * [newKeyword] may be null.
-  /// * [prefix] and [period] are either both tokens or both `null`.
-  /// * [token] can be an identifier or an operator.
+  /// * [firstToken] and [firstPeriod] are either both tokens or both
+  ///   `null`.
+  /// * [secondToken] and [secondPeriod] are either both tokens or both `null`.
+  /// * [thirdToken] can be an identifier or an operator.
   ///
   /// This event is generated by the parser when the parser's
   /// `parseOneCommentReference` method is called.
   void handleCommentReference(
-      Token? newKeyword, Token? prefix, Token? period, Token token) {}
+      Token? newKeyword,
+      Token? firstToken,
+      Token? firstPeriod,
+      Token? secondToken,
+      Token? secondPeriod,
+      Token thirdToken) {}
 
   /// This event is generated by the parser when the parser's
   /// `parseOneCommentReference` method is called.
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
index fac9391..6ffcaf0 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -8355,26 +8355,33 @@
       newKeyword = token;
       token = token.next!;
     }
-    Token? prefix, period;
+    Token? firstToken, firstPeriod, secondToken, secondPeriod;
     if (token.isIdentifier && optional('.', token.next!)) {
-      prefix = token;
-      period = token.next!;
-      Token identifier = period.next!;
+      secondToken = token;
+      secondPeriod = token.next!;
+      if (secondPeriod.next!.isIdentifier &&
+          optional('.', secondPeriod.next!.next!)) {
+        firstToken = secondToken;
+        firstPeriod = secondPeriod;
+        secondToken = secondPeriod.next!;
+        secondPeriod = secondToken.next!;
+      }
+      Token identifier = secondPeriod.next!;
       if (identifier.kind == KEYWORD_TOKEN && optional('new', identifier)) {
         // Treat `new` after `.` is as an identifier so that it can represent an
         // unnamed constructor. This support is separate from the
         // constructor-tearoffs feature.
         rewriter.replaceTokenFollowing(
-            period,
+            secondPeriod,
             new StringToken(TokenType.IDENTIFIER, identifier.lexeme,
                 identifier.charOffset));
       }
-      token = period.next!;
+      token = secondPeriod.next!;
     }
     if (token.isEof) {
       // Recovery: Insert a synthetic identifier for code completion
       token = rewriter.insertSyntheticIdentifier(
-          period ?? newKeyword ?? syntheticPreviousToken(token));
+          secondPeriod ?? newKeyword ?? syntheticPreviousToken(token));
       if (begin == token.next!) {
         begin = token;
       }
@@ -8386,21 +8393,21 @@
     }
     if (token.isUserDefinableOperator) {
       if (token.next!.isEof) {
-        parseOneCommentReferenceRest(
-            begin, referenceOffset, newKeyword, prefix, period, token);
+        parseOneCommentReferenceRest(begin, referenceOffset, newKeyword,
+            firstToken, firstPeriod, secondToken, secondPeriod, token);
         return true;
       }
     } else {
       token = operatorKeyword ?? token;
       if (token.next!.isEof) {
         if (token.isIdentifier) {
-          parseOneCommentReferenceRest(
-              begin, referenceOffset, newKeyword, prefix, period, token);
+          parseOneCommentReferenceRest(begin, referenceOffset, newKeyword,
+              firstToken, firstPeriod, secondToken, secondPeriod, token);
           return true;
         }
         Keyword? keyword = token.keyword;
         if (newKeyword == null &&
-            prefix == null &&
+            secondToken == null &&
             (keyword == Keyword.THIS ||
                 keyword == Keyword.NULL ||
                 keyword == Keyword.TRUE ||
@@ -8421,8 +8428,10 @@
       Token begin,
       int referenceOffset,
       Token? newKeyword,
-      Token? prefix,
-      Token? period,
+      Token? firstToken,
+      Token? firstPeriod,
+      Token? secondToken,
+      Token? secondPeriod,
       Token identifierOrOperator) {
     // Adjust the token offsets to match the enclosing comment token.
     Token token = begin;
@@ -8431,8 +8440,8 @@
       token = token.next!;
     } while (!token.isEof);
 
-    listener.handleCommentReference(
-        newKeyword, prefix, period, identifierOrOperator);
+    listener.handleCommentReference(newKeyword, firstToken, firstPeriod,
+        secondToken, secondPeriod, identifierOrOperator);
   }
 
   /// Given that we have just found bracketed text within the given [comment],
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart
index e3b952f..9ce7dda 100644
--- a/pkg/analyzer/lib/src/dart/analysis/index.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -596,6 +596,8 @@
           return;
         }
       }
+    } else if (expression is PropertyAccess) {
+      // Nothing to do?
     } else {
       throw UnimplementedError('Unhandled CommentReference expression type: '
           '${expression.runtimeType}');
diff --git a/pkg/analyzer/lib/src/dart/resolver/comment_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/comment_reference_resolver.dart
new file mode 100644
index 0000000..e511df4
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/comment_reference_resolver.dart
@@ -0,0 +1,198 @@
+// 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 '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/ast/ast.dart';
+import 'package:analyzer/src/dart/element/type_provider.dart';
+import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+class CommentReferenceResolver {
+  final TypeProviderImpl _typeProvider;
+
+  final ResolverVisitor _resolver;
+
+  /// Helper for resolving properties on types.
+  final TypePropertyResolver _typePropertyResolver;
+
+  CommentReferenceResolver(this._typeProvider, this._resolver)
+      : _typePropertyResolver = _resolver.typePropertyResolver;
+
+  /// Resolves [commentReference].
+  void resolve(CommentReference commentReference) {
+    var expression = commentReference.expression;
+    if (expression is SimpleIdentifierImpl) {
+      _resolveSimpleIdentifierReference(expression,
+          hasNewKeyword: commentReference.newKeyword != null);
+    } else if (expression is PrefixedIdentifierImpl) {
+      _resolvePrefixedIdentifierReference(expression,
+          hasNewKeyword: commentReference.newKeyword != null);
+    } else if (expression is PropertyAccessImpl) {
+      _resolvePropertyAccessReference(expression,
+          hasNewKeyword: commentReference.newKeyword != null);
+    }
+  }
+
+  void _resolvePrefixedIdentifierReference(
+    PrefixedIdentifierImpl expression, {
+    required bool hasNewKeyword,
+  }) {
+    var prefix = expression.prefix;
+    var prefixElement = _resolveSimpleIdentifier(prefix);
+    prefix.staticElement = prefixElement;
+
+    if (prefixElement == null) {
+      return;
+    }
+
+    var name = expression.identifier;
+
+    if (prefixElement is PrefixElement) {
+      var prefixScope = prefixElement.scope;
+      var lookupResult = prefixScope.lookup(name.name);
+      var element = lookupResult.getter ?? lookupResult.setter;
+      element = _resolver.toLegacyElement(element);
+      name.staticElement = element;
+      return;
+    }
+
+    if (!hasNewKeyword) {
+      if (prefixElement is ClassElement) {
+        name.staticElement = prefixElement.getMethod(name.name) ??
+            prefixElement.getGetter(name.name) ??
+            prefixElement.getSetter(name.name) ??
+            prefixElement.getNamedConstructor(name.name);
+      } else if (prefixElement is ExtensionElement) {
+        name.staticElement = prefixElement.getMethod(name.name) ??
+            prefixElement.getGetter(name.name) ??
+            prefixElement.getSetter(name.name);
+      } else {
+        // TODO(brianwilkerson) Report this error.
+      }
+    } else if (prefixElement is ClassElement) {
+      var constructor = prefixElement.getNamedConstructor(name.name);
+      if (constructor == null) {
+        // TODO(brianwilkerson) Report this error.
+      } else {
+        name.staticElement = constructor;
+      }
+    } else {
+      // TODO(brianwilkerson) Report this error.
+    }
+  }
+
+  void _resolvePropertyAccessReference(
+    PropertyAccessImpl expression, {
+    required bool hasNewKeyword,
+  }) {
+    var target = expression.target;
+    if (target is! PrefixedIdentifierImpl) {
+      // A PropertyAccess with a target more complex than a
+      // [PrefixedIdentifier] is not a valid comment reference.
+      return;
+    }
+
+    var prefix = target.prefix;
+    var prefixElement = _resolveSimpleIdentifier(prefix);
+    prefix.staticElement = prefixElement;
+
+    if (prefixElement is! PrefixElement) {
+      // The only valid prefixElement is a PrefixElement; otherwise, this is
+      // not a comment reference.
+      return;
+    }
+
+    var name = target.identifier;
+    var prefixScope = prefixElement.scope;
+    var lookupResult = prefixScope.lookup(name.name);
+    var element = lookupResult.getter ?? lookupResult.setter;
+    element = _resolver.toLegacyElement(element);
+    name.staticElement = element;
+
+    var propertyName = expression.propertyName;
+    if (element is ClassElement) {
+      propertyName.staticElement = element.getMethod(propertyName.name) ??
+          element.getGetter(propertyName.name) ??
+          element.getSetter(propertyName.name) ??
+          element.getNamedConstructor(propertyName.name);
+    } else if (element is ExtensionElement) {
+      propertyName.staticElement = element.getMethod(propertyName.name) ??
+          element.getGetter(propertyName.name) ??
+          element.getSetter(propertyName.name);
+    }
+  }
+
+  /// Resolves the given simple [identifier] if possible.
+  ///
+  /// Returns the resolved element, or `null` if the identifier could not be
+  /// resolved. This does not record the results of the resolution.
+  Element? _resolveSimpleIdentifier(SimpleIdentifierImpl identifier) {
+    var lookupResult = identifier.scopeLookupResult!;
+
+    var element = _resolver.toLegacyElement(lookupResult.getter) ??
+        _resolver.toLegacyElement(lookupResult.setter);
+
+    if (element == null) {
+      InterfaceType enclosingType;
+      var enclosingClass = _resolver.enclosingClass;
+      if (enclosingClass != null) {
+        enclosingType = enclosingClass.thisType;
+      } else {
+        var enclosingExtension = _resolver.enclosingExtension;
+        if (enclosingExtension == null) {
+          return null;
+        }
+        var extendedType = enclosingExtension.extendedType
+            .resolveToBound(_typeProvider.objectType);
+        if (extendedType is InterfaceType) {
+          enclosingType = extendedType;
+        } else if (extendedType is FunctionType) {
+          enclosingType = _typeProvider.functionType;
+        } else {
+          return null;
+        }
+      }
+      var result = _typePropertyResolver.resolve(
+        receiver: null,
+        receiverType: enclosingType,
+        name: identifier.name,
+        propertyErrorEntity: identifier,
+        nameErrorEntity: identifier,
+      );
+      if (identifier.parent is CommentReference) {
+        // TODO(srawlins): Why is the setter preferred? This seems very flawed
+        // as it will only use the setter for a [SimpleIdentifier] comment
+        // reference, and not a [PrefixedIdentifier] or a [PropertyAccess].
+        element = result.setter;
+      }
+      element ??= result.getter;
+    }
+    return element;
+  }
+
+  void _resolveSimpleIdentifierReference(
+    SimpleIdentifierImpl expression, {
+    required bool hasNewKeyword,
+  }) {
+    var element = _resolveSimpleIdentifier(expression);
+    if (element == null) {
+      return;
+    }
+    expression.staticElement = element;
+    if (hasNewKeyword) {
+      if (element is ClassElement) {
+        var constructor = element.unnamedConstructor;
+        if (constructor == null) {
+          // TODO(brianwilkerson) Report this error.
+        } else {
+          expression.staticElement = constructor;
+        }
+      } else {
+        // TODO(brianwilkerson) Report this error.
+      }
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index dea89e7..17b6069 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -2668,13 +2668,26 @@
 
   @override
   void handleCommentReference(
-      Token? newKeyword, Token? prefix, Token? period, Token token) {
-    Identifier identifier = ast.simpleIdentifier(token);
-    if (prefix != null) {
-      identifier = ast.prefixedIdentifier(ast.simpleIdentifier(prefix), period!,
-          identifier as SimpleIdentifier);
+    Token? newKeyword,
+    Token? firstToken,
+    Token? firstPeriod,
+    Token? secondToken,
+    Token? secondPeriod,
+    Token thirdToken,
+  ) {
+    var identifier = ast.simpleIdentifier(thirdToken);
+    if (firstToken != null) {
+      var target = ast.prefixedIdentifier(ast.simpleIdentifier(firstToken),
+          firstPeriod!, ast.simpleIdentifier(secondToken!));
+      var expression = ast.propertyAccess(target, secondPeriod!, identifier);
+      push(ast.commentReference(newKeyword, expression));
+    } else if (secondToken != null) {
+      var expression = ast.prefixedIdentifier(
+          ast.simpleIdentifier(secondToken), secondPeriod!, identifier);
+      push(ast.commentReference(newKeyword, expression));
+    } else {
+      push(ast.commentReference(newKeyword, identifier));
     }
-    push(ast.commentReference(newKeyword, identifier));
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index e64547d..c430007 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -10,9 +10,9 @@
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
+import 'package:analyzer/src/dart/resolver/comment_reference_resolver.dart';
 import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
-import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/migratable_ast_info_provider.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -81,18 +81,17 @@
   /// The element for the library containing the compilation unit being visited.
   final LibraryElement _definingLibrary;
 
-  /// Helper for resolving properties on types.
-  final TypePropertyResolver _typePropertyResolver;
-
   final MethodInvocationResolver _methodInvocationResolver;
 
+  late final _commentReferenceResolver =
+      CommentReferenceResolver(_typeProvider, _resolver);
+
   /// Initialize a newly created visitor to work for the given [_resolver] to
   /// resolve the nodes in a compilation unit.
   ElementResolver(this._resolver,
       {MigratableAstInfoProvider migratableAstInfoProvider =
           const MigratableAstInfoProvider()})
       : _definingLibrary = _resolver.definingLibrary,
-        _typePropertyResolver = _resolver.typePropertyResolver,
         _methodInvocationResolver = MethodInvocationResolver(
           _resolver,
           migratableAstInfoProvider,
@@ -124,70 +123,8 @@
   }
 
   @override
-  void visitCommentReference(covariant CommentReferenceImpl node) {
-    var expression = node.expression;
-    if (expression is SimpleIdentifierImpl) {
-      var element = _resolveSimpleIdentifier(expression);
-      if (element == null) {
-        return;
-      }
-      expression.staticElement = element;
-      if (node.newKeyword != null) {
-        if (element is ClassElement) {
-          var constructor = element.unnamedConstructor;
-          if (constructor == null) {
-            // TODO(brianwilkerson) Report this error.
-          } else {
-            expression.staticElement = constructor;
-          }
-        } else {
-          // TODO(brianwilkerson) Report this error.
-        }
-      }
-    } else if (expression is PrefixedIdentifierImpl) {
-      var prefix = expression.prefix;
-      var prefixElement = _resolveSimpleIdentifier(prefix);
-      prefix.staticElement = prefixElement;
-
-      var name = expression.identifier;
-
-      if (prefixElement == null) {
-        return;
-      }
-
-      if (prefixElement is PrefixElement) {
-        var prefixScope = prefixElement.scope;
-        var lookupResult = prefixScope.lookup(name.name);
-        var element = lookupResult.getter ?? lookupResult.setter;
-        element = _resolver.toLegacyElement(element);
-        name.staticElement = element;
-        return;
-      }
-
-      if (node.newKeyword == null) {
-        if (prefixElement is ClassElement) {
-          name.staticElement = prefixElement.getMethod(name.name) ??
-              prefixElement.getGetter(name.name) ??
-              prefixElement.getSetter(name.name) ??
-              prefixElement.getNamedConstructor(name.name);
-        } else if (prefixElement is ExtensionElement) {
-          name.staticElement = prefixElement.getMethod(name.name) ??
-              prefixElement.getGetter(name.name) ??
-              prefixElement.getSetter(name.name);
-        } else {
-          // TODO(brianwilkerson) Report this error.
-        }
-      } else if (prefixElement is ClassElement) {
-        var constructor = prefixElement.getNamedConstructor(name.name);
-        if (constructor == null) {
-          // TODO(brianwilkerson) Report this error.
-        } else {
-          name.staticElement = constructor;
-        }
-      } else {
-        // TODO(brianwilkerson) Report this error.
-      }
-    }
+  void visitCommentReference(CommentReference node) {
+    _commentReferenceResolver.resolve(node);
   }
 
   @override
@@ -571,88 +508,6 @@
     _resolveAnnotations(node.metadata);
   }
 
-  /// Resolve the given simple [identifier] if possible. Return the element to
-  /// which it could be resolved, or `null` if it could not be resolved. This
-  /// does not record the results of the resolution.
-  Element? _resolveSimpleIdentifier(SimpleIdentifierImpl identifier) {
-    var lookupResult = identifier.scopeLookupResult!;
-
-    var element = lookupResult.getter;
-    element = _resolver.toLegacyElement(element);
-
-    if (element is PropertyAccessorElement && identifier.inSetterContext()) {
-      var setter = lookupResult.setter;
-      if (setter == null) {
-        //
-        // Check to see whether there might be a locally defined getter and
-        // an inherited setter.
-        //
-        var enclosingClass = _resolver.enclosingClass;
-        if (enclosingClass != null) {
-          var result = _typePropertyResolver.resolve(
-            receiver: null,
-            receiverType: enclosingClass.thisType,
-            name: identifier.name,
-            propertyErrorEntity: identifier,
-            nameErrorEntity: identifier,
-          );
-          setter = result.setter;
-        }
-      }
-      if (setter != null) {
-        setter = _resolver.toLegacyElement(setter);
-        element = setter;
-      }
-    } else if (element == null &&
-        (identifier.inSetterContext() ||
-            identifier.parent is CommentReference)) {
-      element = lookupResult.setter;
-      element = _resolver.toLegacyElement(element);
-    }
-    if (element == null) {
-      InterfaceType enclosingType;
-      var enclosingClass = _resolver.enclosingClass;
-      if (enclosingClass == null) {
-        var enclosingExtension = _resolver.enclosingExtension;
-        if (enclosingExtension == null) {
-          return null;
-        }
-        DartType extendedType =
-            _resolveTypeParameter(enclosingExtension.extendedType);
-        if (extendedType is InterfaceType) {
-          enclosingType = extendedType;
-        } else if (extendedType is FunctionType) {
-          enclosingType = _typeProvider.functionType;
-        } else {
-          return null;
-        }
-      } else {
-        enclosingType = enclosingClass.thisType;
-      }
-      if (element == null) {
-        var result = _typePropertyResolver.resolve(
-          receiver: null,
-          receiverType: enclosingType,
-          name: identifier.name,
-          propertyErrorEntity: identifier,
-          nameErrorEntity: identifier,
-        );
-        if (identifier.inSetterContext() ||
-            identifier.parent is CommentReference) {
-          element = result.setter;
-        }
-        element ??= result.getter;
-      }
-    }
-    return element;
-  }
-
-  /// If the given [type] is a type parameter, resolve it to the type that
-  /// should be used when looking up members. Otherwise, return the original
-  /// type.
-  DartType _resolveTypeParameter(DartType type) =>
-      type.resolveToBound(_typeProvider.objectType);
-
   /// Checks whether the given [expression] is a reference to a class. If it is
   /// then the element representing the class is returned, otherwise `null` is
   /// returned.
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 80eebe3..95f6e32 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -1253,7 +1253,7 @@
   @override
   void visitCommentReference(CommentReference node) {
     //
-    // We do not visit the identifier because it needs to be visited in the
+    // We do not visit the expression because it needs to be visited in the
     // context of the reference.
     //
     node.accept(elementResolver);
diff --git a/pkg/analyzer/test/src/dart/resolution/comment_test.dart b/pkg/analyzer/test/src/dart/resolution/comment_test.dart
index 7735e22..86a9a44 100644
--- a/pkg/analyzer/test/src/dart/resolution/comment_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/comment_test.dart
@@ -10,10 +10,240 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(CommentDriverResolutionTest);
+    defineReflectiveTests(CommentDriverResolution_PropertyAccessTest);
   });
 }
 
 @reflectiveTest
+class CommentDriverResolution_PropertyAccessTest
+    extends PubPackageResolutionTest {
+  test_class_constructor_named() async {
+    await assertNoErrorsInCode('''
+import '' as self;
+class A {
+  A.named();
+}
+
+/// [self.A.named]
+void f() {}
+''');
+
+    assertElement(findNode.simple('self.A.named'), findElement.prefix('self'));
+    assertElement(findNode.simple('A.named]'), findElement.class_('A'));
+    // TODO(srawlins): Set the type of named, and test it, here and below.
+    assertElement(findNode.simple('named]'), findElement.constructor('named'));
+  }
+
+  test_class_constructor_unnamedViaNew() async {
+    await assertNoErrorsInCode('''
+import '' as self;
+class A {
+  A();
+}
+
+/// [self.A.new]
+void f() {}
+''');
+
+    assertElement(findNode.simple('self.A.new'), findElement.prefix('self'));
+    assertElement(findNode.simple('A.new'), findElement.class_('A'));
+    assertElement(findNode.simple('new]'), findElement.unnamedConstructor('A'));
+  }
+
+  test_class_instanceGetter() async {
+    await assertNoErrorsInCode('''
+import '' as self;
+class A {
+  int get foo => 0;
+}
+
+/// [self.A.foo]
+void f() {}
+''');
+
+    assertElement(findNode.simple('self.A.foo'), findElement.prefix('self'));
+    assertElement(findNode.simple('A.foo'), findElement.class_('A'));
+    assertElement(findNode.simple('foo]'), findElement.getter('foo'));
+  }
+
+  test_class_instanceMethod() async {
+    await assertNoErrorsInCode('''
+import '' as self;
+class A {
+  void foo() {}
+}
+
+/// [self.A.foo]
+void f() {}
+''');
+
+    assertElement(findNode.simple('self.A.foo'), findElement.prefix('self'));
+    assertElement(findNode.simple('A.foo'), findElement.class_('A'));
+    assertElement(findNode.simple('foo]'), findElement.method('foo'));
+  }
+
+  test_class_instanceSetter() async {
+    await assertNoErrorsInCode('''
+import '' as self;
+class A {
+  set foo(int value) {}
+}
+
+/// [self.A.foo]
+void f() {}
+''');
+
+    assertElement(findNode.simple('self.A.foo'), findElement.prefix('self'));
+    assertElement(findNode.simple('A.foo'), findElement.class_('A'));
+    assertElement(findNode.simple('foo]'), findElement.setter('foo'));
+  }
+
+  test_class_staticGetter() async {
+    await assertNoErrorsInCode('''
+import '' as self;
+class A {
+  static int get foo => 0;
+}
+
+/// [self.A.foo]
+void f() {}
+''');
+
+    assertElement(findNode.simple('self.A.foo'), findElement.prefix('self'));
+    assertElement(findNode.simple('A.foo'), findElement.class_('A'));
+    assertElement(findNode.simple('foo]'), findElement.getter('foo'));
+  }
+
+  test_class_staticMethod() async {
+    await assertNoErrorsInCode('''
+import '' as self;
+class A {
+  static void foo() {}
+}
+
+/// [self.A.foo]
+void f() {}
+''');
+
+    assertElement(findNode.simple('self.A.foo'), findElement.prefix('self'));
+    assertElement(findNode.simple('A.foo'), findElement.class_('A'));
+    assertElement(findNode.simple('foo]'), findElement.method('foo'));
+  }
+
+  test_class_staticSetter() async {
+    await assertNoErrorsInCode('''
+import '' as self;
+class A {
+  static set foo(int value) {}
+}
+
+/// [self.A.foo]
+void f() {}
+''');
+
+    assertElement(findNode.simple('self.A.foo'), findElement.prefix('self'));
+    assertElement(findNode.simple('A.foo'), findElement.class_('A'));
+    assertElement(findNode.simple('foo]'), findElement.setter('foo'));
+  }
+
+  test_extension_instanceGetter() async {
+    await assertNoErrorsInCode('''
+import '' as self;
+extension E on int {
+  int get foo => 0;
+}
+
+/// [self.E.foo]
+void f() {}
+''');
+
+    assertElement(findNode.simple('self.E.foo'), findElement.prefix('self'));
+    assertElement(findNode.simple('E.foo'), findElement.extension_('E'));
+    assertElement(findNode.simple('foo]'), findElement.getter('foo'));
+  }
+
+  test_extension_instanceMethod() async {
+    await assertNoErrorsInCode('''
+import '' as self;
+extension E on int {
+  void foo() {}
+}
+
+/// [self.E.foo]
+void f() {}
+''');
+
+    assertElement(findNode.simple('self.E.foo'), findElement.prefix('self'));
+    assertElement(findNode.simple('E.foo'), findElement.extension_('E'));
+    assertElement(findNode.simple('foo]'), findElement.method('foo'));
+  }
+
+  test_extension_instanceSetter() async {
+    await assertNoErrorsInCode('''
+import '' as self;
+extension E on int {
+  set foo(int value) {}
+}
+
+/// [self.E.foo]
+void f() {}
+''');
+
+    assertElement(findNode.simple('self.E.foo'), findElement.prefix('self'));
+    assertElement(findNode.simple('E.foo'), findElement.extension_('E'));
+    assertElement(findNode.simple('foo]'), findElement.setter('foo'));
+  }
+
+  test_extension_staticGetter() async {
+    await assertNoErrorsInCode('''
+import '' as self;
+extension E on int {
+  static int get foo => 0;
+}
+
+/// [self.E.foo]
+void f() {}
+''');
+
+    assertElement(findNode.simple('self.E.foo'), findElement.prefix('self'));
+    assertElement(findNode.simple('E.foo'), findElement.extension_('E'));
+    assertElement(findNode.simple('foo]'), findElement.getter('foo'));
+  }
+
+  test_extension_staticMethod() async {
+    await assertNoErrorsInCode('''
+import '' as self;
+extension E on int {
+  static void foo() {}
+}
+
+/// [self.E.foo]
+void f() {}
+''');
+
+    assertElement(findNode.simple('self.E.foo'), findElement.prefix('self'));
+    assertElement(findNode.simple('E.foo'), findElement.extension_('E'));
+    assertElement(findNode.simple('foo]'), findElement.method('foo'));
+  }
+
+  test_extension_staticSetter() async {
+    await assertNoErrorsInCode('''
+import '' as self;
+extension E on int {
+  static set foo(int value) {}
+}
+
+/// [self.E.foo]
+void f() {}
+''');
+
+    assertElement(findNode.simple('self.E.foo'), findElement.prefix('self'));
+    assertElement(findNode.simple('E.foo'), findElement.extension_('E'));
+    assertElement(findNode.simple('foo]'), findElement.setter('foo'));
+  }
+}
+
+@reflectiveTest
 class CommentDriverResolutionTest extends PubPackageResolutionTest {
   test_newKeyword() async {
     await assertErrorsInCode('''
@@ -43,6 +273,37 @@
     );
   }
 
+  test_prefixedIdentifier_class_constructor_named() async {
+    // TODO(srawlins): Move PrefixedIdentifier tests into their own class, and
+    // improve coverage regarding getter/setter pairs, constructors, operators,
+    // and the 'new' keyword.
+    await assertNoErrorsInCode('''
+class A {
+  A.named();
+}
+
+/// [A.named]
+void f() {}
+''');
+
+    assertElement(findNode.simple('A.named]'), findElement.class_('A'));
+    assertElement(findNode.simple('named]'), findElement.constructor('named'));
+  }
+
+  test_prefixedIdentifier_class_constructor_unnamedViaNew() async {
+    await assertNoErrorsInCode('''
+class A {
+  A();
+}
+
+/// [A.new]
+void f() {}
+''');
+
+    assertElement(findNode.simple('A.new'), findElement.class_('A'));
+    assertElement(findNode.simple('new]'), findElement.unnamedConstructor('A'));
+  }
+
   test_prefixedIdentifier_class_instanceGetter() async {
     await assertNoErrorsInCode(r'''
 class A {
@@ -348,6 +609,21 @@
     assertElement(findNode.simple('p5]'), findElement.parameter('p5'));
   }
 
+  test_simpleIdentifier_extension_conflictingSetterAndGetter() async {
+    await assertNoErrorsInCode('''
+extension E1 on int {
+  int get foo => 0;
+}
+
+/// [foo]
+extension E2 on int {
+  set foo(int value) {}
+}
+''');
+
+    assertElement(findNode.simple('foo]'), findElement.setter('foo'));
+  }
+
   test_simpleIdentifier_parameter_functionTyped() async {
     await assertNoErrorsInCode(r'''
 /// [bar]
diff --git a/pkg/dartdev/test/analysis_server_test.dart b/pkg/dartdev/test/analysis_server_test.dart
index 9902dda..975eb86 100644
--- a/pkg/dartdev/test/analysis_server_test.dart
+++ b/pkg/dartdev/test/analysis_server_test.dart
@@ -21,7 +21,7 @@
       p = project();
     });
 
-    tearDown(() => p?.dispose());
+    tearDown(() async => await p?.dispose());
 
     test('can start', () async {
       AnalysisServer server = AnalysisServer(
diff --git a/pkg/dartdev/test/commands/analyze_test.dart b/pkg/dartdev/test/commands/analyze_test.dart
index 11613ef..60bbb1a 100644
--- a/pkg/dartdev/test/commands/analyze_test.dart
+++ b/pkg/dartdev/test/commands/analyze_test.dart
@@ -176,7 +176,7 @@
 
   setUp(() => p = null);
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   test('--help', () async {
     p = project();
@@ -201,7 +201,7 @@
   group('multiple items', () {
     TestProject secondProject;
 
-    tearDown(() => secondProject?.dispose());
+    tearDown(() async => await secondProject?.dispose());
 
     test('folder and file', () async {
       p = project(mainSrc: "int get foo => 'str';\n");
diff --git a/pkg/dartdev/test/commands/create_integration_test.dart b/pkg/dartdev/test/commands/create_integration_test.dart
index e4363a4..4856b47 100644
--- a/pkg/dartdev/test/commands/create_integration_test.dart
+++ b/pkg/dartdev/test/commands/create_integration_test.dart
@@ -18,7 +18,7 @@
 
   setUp(() => p = null);
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   // Create tests for each template.
   for (String templateId in CreateCommand.legalTemplateIds) {
diff --git a/pkg/dartdev/test/commands/create_test.dart b/pkg/dartdev/test/commands/create_test.dart
index 6978d98..899c7b0 100644
--- a/pkg/dartdev/test/commands/create_test.dart
+++ b/pkg/dartdev/test/commands/create_test.dart
@@ -21,7 +21,7 @@
 
   setUp(() => p = null);
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   test('--help', () async {
     p = project();
diff --git a/pkg/dartdev/test/commands/devtools_test.dart b/pkg/dartdev/test/commands/devtools_test.dart
index 656b8c6..e14ba0ac 100644
--- a/pkg/dartdev/test/commands/devtools_test.dart
+++ b/pkg/dartdev/test/commands/devtools_test.dart
@@ -16,7 +16,7 @@
 void devtools() {
   TestProject p;
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   test('--help', () async {
     p = project();
diff --git a/pkg/dartdev/test/commands/fix_test.dart b/pkg/dartdev/test/commands/fix_test.dart
index 1f0dd94..c6382f4 100644
--- a/pkg/dartdev/test/commands/fix_test.dart
+++ b/pkg/dartdev/test/commands/fix_test.dart
@@ -26,7 +26,7 @@
 
   setUp(() => p = null);
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   void assertResult({int exitCode = 0}) {
     String message;
diff --git a/pkg/dartdev/test/commands/flag_test.dart b/pkg/dartdev/test/commands/flag_test.dart
index b5aa76e..3feab2d 100644
--- a/pkg/dartdev/test/commands/flag_test.dart
+++ b/pkg/dartdev/test/commands/flag_test.dart
@@ -57,7 +57,7 @@
 void help() {
   TestProject p;
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   test('--help', () async {
     p = project();
diff --git a/pkg/dartdev/test/commands/format_test.dart b/pkg/dartdev/test/commands/format_test.dart
index 5331c6d..cf82970 100644
--- a/pkg/dartdev/test/commands/format_test.dart
+++ b/pkg/dartdev/test/commands/format_test.dart
@@ -16,7 +16,7 @@
 void format() {
   TestProject p;
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   test('--help', () async {
     p = project();
diff --git a/pkg/dartdev/test/commands/help_test.dart b/pkg/dartdev/test/commands/help_test.dart
index 2202b56..69f1f27 100644
--- a/pkg/dartdev/test/commands/help_test.dart
+++ b/pkg/dartdev/test/commands/help_test.dart
@@ -15,7 +15,7 @@
 void help() {
   TestProject p;
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   /// Commands not tested by the following loop.
   List<String> _commandsNotTested = <String>[
diff --git a/pkg/dartdev/test/commands/language_server_test.dart b/pkg/dartdev/test/commands/language_server_test.dart
index 1e7a46d..543aec9 100644
--- a/pkg/dartdev/test/commands/language_server_test.dart
+++ b/pkg/dartdev/test/commands/language_server_test.dart
@@ -24,10 +24,7 @@
   utils.TestProject project;
   Process process;
 
-  tearDown(() {
-    project?.dispose();
-    process?.kill();
-  });
+  tearDown(() async => await project?.dispose());
 
   Future runWithLsp(List<String> args) async {
     project = utils.project();
diff --git a/pkg/dartdev/test/commands/migrate_test.dart b/pkg/dartdev/test/commands/migrate_test.dart
index 68475ee..0b394ad 100644
--- a/pkg/dartdev/test/commands/migrate_test.dart
+++ b/pkg/dartdev/test/commands/migrate_test.dart
@@ -17,7 +17,7 @@
 
   TestProject p;
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   test('--help', () async {
     p = project();
diff --git a/pkg/dartdev/test/commands/pub_test.dart b/pkg/dartdev/test/commands/pub_test.dart
index 2eafe5e..f2486dd 100644
--- a/pkg/dartdev/test/commands/pub_test.dart
+++ b/pkg/dartdev/test/commands/pub_test.dart
@@ -15,7 +15,7 @@
 void pub() {
   TestProject p;
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   void _assertPubHelpInvoked(ProcessResult result) {
     expect(result, isNotNull);
diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart
index 1e9b3e0..f3174c7 100644
--- a/pkg/dartdev/test/commands/run_test.dart
+++ b/pkg/dartdev/test/commands/run_test.dart
@@ -23,7 +23,7 @@
 void run() {
   TestProject p;
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   test('--help', () async {
     p = project();
@@ -147,7 +147,7 @@
       expect(result.stdout, contains('FOO BAR [--arg1, arg2]'));
       expect(result.exitCode, 0);
     } finally {
-      bar.dispose();
+      await bar.dispose();
     }
   });
 
diff --git a/pkg/dartdev/test/commands/test_test.dart b/pkg/dartdev/test/commands/test_test.dart
index 634d2b9..7f758d3 100644
--- a/pkg/dartdev/test/commands/test_test.dart
+++ b/pkg/dartdev/test/commands/test_test.dart
@@ -19,7 +19,7 @@
 void defineTest(List<Experiment> experiments) {
   TestProject p;
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   test('--help', () async {
     p = project();
diff --git a/pkg/dartdev/test/core_test.dart b/pkg/dartdev/test/core_test.dart
index 5f49133..f9c8e29 100644
--- a/pkg/dartdev/test/core_test.dart
+++ b/pkg/dartdev/test/core_test.dart
@@ -105,7 +105,7 @@
 void _project() {
   TestProject p;
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   test('hasPubspecFile positive', () {
     p = project();
diff --git a/pkg/dartdev/test/fix_driver_test.dart b/pkg/dartdev/test/fix_driver_test.dart
index 35ec72a..8b71804 100644
--- a/pkg/dartdev/test/fix_driver_test.dart
+++ b/pkg/dartdev/test/fix_driver_test.dart
@@ -19,7 +19,7 @@
 
 void _driver() {
   TestProject p;
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   test('no fixes', () async {
     p = project(mainSrc: 'int get foo => 1;\n');
diff --git a/pkg/dartdev/test/load_from_dill_test.dart b/pkg/dartdev/test/load_from_dill_test.dart
index 633e7af..0412854 100644
--- a/pkg/dartdev/test/load_from_dill_test.dart
+++ b/pkg/dartdev/test/load_from_dill_test.dart
@@ -11,7 +11,7 @@
 void main() {
   TestProject p;
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   test("Fallback to dartdev.dill from dartdev.dart.snapshot for 'Hello World'",
       () async {
diff --git a/pkg/dartdev/test/no_such_file_test.dart b/pkg/dartdev/test/no_such_file_test.dart
index 9b2edc4..bf4eaa3 100644
--- a/pkg/dartdev/test/no_such_file_test.dart
+++ b/pkg/dartdev/test/no_such_file_test.dart
@@ -9,7 +9,7 @@
 void main() {
   TestProject p;
 
-  tearDown(() => p?.dispose());
+  tearDown(() async => await p?.dispose());
 
   test('Ensure parsing fails after encountering invalid file', () async {
     // Regression test for https://github.com/dart-lang/sdk/issues/43991
diff --git a/pkg/dartdev/test/utils.dart b/pkg/dartdev/test/utils.dart
index fe656a5..8f8147a 100644
--- a/pkg/dartdev/test/utils.dart
+++ b/pkg/dartdev/test/utils.dart
@@ -93,8 +93,9 @@
     file.deleteSync();
   }
 
-  void dispose() {
+  Future<void> dispose() async {
     _process?.kill();
+    await _process?.exitCode;
     _process = null;
     if (dir.existsSync()) {
       dir.deleteSync(recursive: true);
@@ -135,7 +136,8 @@
           ...arguments,
         ],
         workingDirectory: workingDir ?? dir.path,
-        environment: {if (logAnalytics) '_DARTDEV_LOG_ANALYTICS': 'true'});
+        environment: {if (logAnalytics) '_DARTDEV_LOG_ANALYTICS': 'true'})
+      ..then((p) => _process = p);
   }
 
   String _sdkRootPath;
diff --git a/pkg/front_end/lib/src/fasta/util/parser_ast_helper.dart b/pkg/front_end/lib/src/fasta/util/parser_ast_helper.dart
index 13348fd..b38e4ed 100644
--- a/pkg/front_end/lib/src/fasta/util/parser_ast_helper.dart
+++ b/pkg/front_end/lib/src/fasta/util/parser_ast_helper.dart
@@ -2552,13 +2552,20 @@
 
   @override
   void handleCommentReference(
-      Token? newKeyword, Token? prefix, Token? period, Token token) {
+      Token? newKeyword,
+      Token? firstToken,
+      Token? firstPeriod,
+      Token? secondToken,
+      Token? secondPeriod,
+      Token thirdToken) {
     CommentReferenceHandle data = new CommentReferenceHandle(
         ParserAstType.HANDLE,
         newKeyword: newKeyword,
-        prefix: prefix,
-        period: period,
-        token: token);
+        firstToken: firstToken,
+        firstPeriod: firstPeriod,
+        secondToken: secondToken,
+        secondPeriod: secondPeriod,
+        thirdToken: thirdToken);
     seen(data);
   }
 
@@ -7116,20 +7123,29 @@
 
 class CommentReferenceHandle extends ParserAstNode {
   final Token? newKeyword;
-  final Token? prefix;
-  final Token? period;
-  final Token token;
+  final Token? firstToken;
+  final Token? firstPeriod;
+  final Token? secondToken;
+  final Token? secondPeriod;
+  final Token thirdToken;
 
   CommentReferenceHandle(ParserAstType type,
-      {this.newKeyword, this.prefix, this.period, required this.token})
+      {this.newKeyword,
+      this.firstToken,
+      this.firstPeriod,
+      this.secondToken,
+      this.secondPeriod,
+      required this.thirdToken})
       : super("CommentReference", type);
 
   @override
   Map<String, Object?> get deprecatedArguments => {
         "newKeyword": newKeyword,
-        "prefix": prefix,
-        "period": period,
-        "token": token,
+        "firstToken": firstToken,
+        "firstPeriod": firstPeriod,
+        "secondToken": secondToken,
+        "secondPeriod": secondPeriod,
+        "thirdToken": thirdToken,
       };
 }
 
diff --git a/pkg/front_end/test/parser_test_listener.dart b/pkg/front_end/test/parser_test_listener.dart
index f90c7fa..b72f70d 100644
--- a/pkg/front_end/test/parser_test_listener.dart
+++ b/pkg/front_end/test/parser_test_listener.dart
@@ -2660,16 +2660,25 @@
 
   @override
   void handleCommentReference(
-      Token? newKeyword, Token? prefix, Token? period, Token token) {
+      Token? newKeyword,
+      Token? firstToken,
+      Token? firstPeriod,
+      Token? secondToken,
+      Token? secondPeriod,
+      Token thirdToken) {
     seen(newKeyword);
-    seen(prefix);
-    seen(period);
-    seen(token);
+    seen(firstToken);
+    seen(firstPeriod);
+    seen(secondToken);
+    seen(secondPeriod);
+    seen(thirdToken);
     doPrint('handleCommentReference('
         '$newKeyword, '
-        '$prefix, '
-        '$period, '
-        '$token)');
+        '$firstToken, '
+        '$firstPeriod, '
+        '$secondToken, '
+        '$secondPeriod, '
+        '$thirdToken)');
   }
 
   @override
diff --git a/pkg/front_end/test/parser_test_parser.dart b/pkg/front_end/test/parser_test_parser.dart
index 139220a..38d64e8 100644
--- a/pkg/front_end/test/parser_test_parser.dart
+++ b/pkg/front_end/test/parser_test_parser.dart
@@ -2494,19 +2494,30 @@
       Token begin,
       int referenceOffset,
       Token? newKeyword,
-      Token? prefix,
-      Token? period,
+      Token? firstToken,
+      Token? firstPeriod,
+      Token? secondToken,
+      Token? secondPeriod,
       Token identifierOrOperator) {
     doPrint('parseOneCommentReferenceRest('
         '$begin, '
         '$referenceOffset, '
         '$newKeyword, '
-        '$prefix, '
-        '$period, '
+        '$firstToken, '
+        '$firstPeriod, '
+        '$secondToken, '
+        '$secondPeriod, '
         '$identifierOrOperator)');
     indent++;
-    var result = super.parseOneCommentReferenceRest(begin, referenceOffset,
-        newKeyword, prefix, period, identifierOrOperator);
+    var result = super.parseOneCommentReferenceRest(
+        begin,
+        referenceOffset,
+        newKeyword,
+        firstToken,
+        firstPeriod,
+        secondToken,
+        secondPeriod,
+        identifierOrOperator);
     indent--;
     return result;
   }
diff --git a/runtime/bin/dartdev_isolate.cc b/runtime/bin/dartdev_isolate.cc
index 0f75c8e..4b9fe69 100644
--- a/runtime/bin/dartdev_isolate.cc
+++ b/runtime/bin/dartdev_isolate.cc
@@ -210,6 +210,7 @@
   flags.use_field_guards = true;
   flags.use_osr = true;
   flags.is_system_isolate = true;
+  flags.branch_coverage = false;
 
   char* error;
   Dart_Isolate dartdev_isolate = runner->create_isolate_(
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index e79e6c4..f37de2b 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -606,6 +606,7 @@
   bool null_safety;
   bool is_system_isolate;
   bool snapshot_is_dontneed_safe;
+  bool branch_coverage;
 } Dart_IsolateFlags;
 
 /**
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index 412cfbc..ee4f627 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -212,6 +212,7 @@
 rewind_optimized_out_test: SkipSlow # Timeout
 
 [ $arch == ia32 && $compiler == dartk ]
+*: Slow # Issue 47920, service tests are slow on IA32
 valid_source_locations_test: Skip # Issue 34736, too slow.
 
 [ $compiler == app_jitk && $system == linux ]
diff --git a/runtime/observatory_2/tests/service_2/service_2_kernel.status b/runtime/observatory_2/tests/service_2/service_2_kernel.status
index ac51da2..914b102 100644
--- a/runtime/observatory_2/tests/service_2/service_2_kernel.status
+++ b/runtime/observatory_2/tests/service_2/service_2_kernel.status
@@ -212,6 +212,7 @@
 rewind_optimized_out_test: SkipSlow # Timeout
 
 [ $arch == ia32 && $compiler == dartk ]
+*: Slow # Issue 47920, service tests are slow on IA32
 valid_source_locations_test: Skip # Issue 34736, too slow.
 
 [ $compiler == app_jitk && $system == linux ]
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index 30f1303..9abd6ee 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -56,7 +56,10 @@
     if (!is_android) {
       libs += [ "pthread" ]
     }
-    if (!is_mac && !is_ios) {
+
+    # Clang with libc++ does not require an explicit atomic library reference.
+    # (similar to https://github.com/flutter/buildroot/blob/master/build/config/compiler/BUILD.gn#L562)
+    if (!is_clang) {
       libs += [ "atomic" ]
     }
   }
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index a013cb2..a8e2f04 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -646,10 +646,6 @@
       case Token::kMUL:
         FALL_THROUGH;
       case Token::kDIV: {
-        if (op_kind == Token::kDIV &&
-            !FlowGraphCompiler::SupportsHardwareDivision()) {
-          return false;
-        }
         left_value = PrepareStaticOpInput(left_value, kDoubleCid, instr);
         right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
         replacement = new (Z) BinaryDoubleOpInstr(
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index e811039..3b8931c 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -765,32 +765,30 @@
 static void CompareDoubles(Assembler* assembler,
                            Label* normal_ir_body,
                            Condition true_condition) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    Label is_smi, double_op;
+  Label is_smi, double_op;
 
-    TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
-    // Both arguments are double, right operand is in R0.
+  TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
+  // Both arguments are double, right operand is in R0.
 
-    __ LoadDFromOffset(D1, R0, target::Double::value_offset() - kHeapObjectTag);
-    __ Bind(&double_op);
-    __ ldr(R0, Address(SP, 1 * target::kWordSize));  // Left argument.
-    __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
+  __ LoadDFromOffset(D1, R0, target::Double::value_offset() - kHeapObjectTag);
+  __ Bind(&double_op);
+  __ ldr(R0, Address(SP, 1 * target::kWordSize));  // Left argument.
+  __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
 
-    __ vcmpd(D0, D1);
-    __ vmstat();
-    __ LoadObject(R0, CastHandle<Object>(FalseObject()));
-    // Return false if D0 or D1 was NaN before checking true condition.
-    READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, VS));
-    __ LoadObject(R0, CastHandle<Object>(TrueObject()), true_condition);
-    __ Ret();
+  __ vcmpd(D0, D1);
+  __ vmstat();
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
+  // Return false if D0 or D1 was NaN before checking true condition.
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, VS));
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()), true_condition);
+  __ Ret();
 
-    __ Bind(&is_smi);  // Convert R0 to a double.
-    __ SmiUntag(R0);
-    __ vmovsr(S0, R0);
-    __ vcvtdi(D1, S0);
-    __ b(&double_op);  // Then do the comparison.
-    __ Bind(normal_ir_body);
-  }
+  __ Bind(&is_smi);  // Convert R0 to a double.
+  __ SmiUntag(R0);
+  __ vmovsr(S0, R0);
+  __ vcvtdi(D1, S0);
+  __ b(&double_op);  // Then do the comparison.
+  __ Bind(normal_ir_body);
 }
 
 void AsmIntrinsifier::Double_greaterThan(Assembler* assembler,
@@ -823,43 +821,41 @@
 static void DoubleArithmeticOperations(Assembler* assembler,
                                        Label* normal_ir_body,
                                        Token::Kind kind) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    Label is_smi, double_op;
+  Label is_smi, double_op;
 
-    TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
-    // Both arguments are double, right operand is in R0.
-    __ LoadDFromOffset(D1, R0, target::Double::value_offset() - kHeapObjectTag);
-    __ Bind(&double_op);
-    __ ldr(R0, Address(SP, 1 * target::kWordSize));  // Left argument.
-    __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
-    switch (kind) {
-      case Token::kADD:
-        __ vaddd(D0, D0, D1);
-        break;
-      case Token::kSUB:
-        __ vsubd(D0, D0, D1);
-        break;
-      case Token::kMUL:
-        __ vmuld(D0, D0, D1);
-        break;
-      case Token::kDIV:
-        __ vdivd(D0, D0, D1);
-        break;
-      default:
-        UNREACHABLE();
-    }
-    const Class& double_class = DoubleClass();
-    __ TryAllocate(double_class, normal_ir_body, Assembler::kFarJump, R0,
-                   R1);  // Result register.
-    __ StoreDToOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
-    __ Ret();
-    __ Bind(&is_smi);  // Convert R0 to a double.
-    __ SmiUntag(R0);
-    __ vmovsr(S0, R0);
-    __ vcvtdi(D1, S0);
-    __ b(&double_op);
-    __ Bind(normal_ir_body);
+  TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
+  // Both arguments are double, right operand is in R0.
+  __ LoadDFromOffset(D1, R0, target::Double::value_offset() - kHeapObjectTag);
+  __ Bind(&double_op);
+  __ ldr(R0, Address(SP, 1 * target::kWordSize));  // Left argument.
+  __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
+  switch (kind) {
+    case Token::kADD:
+      __ vaddd(D0, D0, D1);
+      break;
+    case Token::kSUB:
+      __ vsubd(D0, D0, D1);
+      break;
+    case Token::kMUL:
+      __ vmuld(D0, D0, D1);
+      break;
+    case Token::kDIV:
+      __ vdivd(D0, D0, D1);
+      break;
+    default:
+      UNREACHABLE();
   }
+  const Class& double_class = DoubleClass();
+  __ TryAllocate(double_class, normal_ir_body, Assembler::kFarJump, R0,
+                 R1);  // Result register.
+  __ StoreDToOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
+  __ Ret();
+  __ Bind(&is_smi);  // Convert R0 to a double.
+  __ SmiUntag(R0);
+  __ vmovsr(S0, R0);
+  __ vcvtdi(D1, S0);
+  __ b(&double_op);
+  __ Bind(normal_ir_body);
 }
 
 void AsmIntrinsifier::Double_add(Assembler* assembler, Label* normal_ir_body) {
@@ -881,123 +877,111 @@
 // Left is double, right is integer (Mint or Smi)
 void AsmIntrinsifier::Double_mulFromInteger(Assembler* assembler,
                                             Label* normal_ir_body) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    Label fall_through;
-    // Only smis allowed.
-    __ ldr(R0, Address(SP, 0 * target::kWordSize));
-    __ tst(R0, Operand(kSmiTagMask));
-    __ b(normal_ir_body, NE);
-    // Is Smi.
-    __ SmiUntag(R0);
-    __ vmovsr(S0, R0);
-    __ vcvtdi(D1, S0);
-    __ ldr(R0, Address(SP, 1 * target::kWordSize));
-    __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
-    __ vmuld(D0, D0, D1);
-    const Class& double_class = DoubleClass();
-    __ TryAllocate(double_class, normal_ir_body, Assembler::kFarJump, R0,
-                   R1);  // Result register.
-    __ StoreDToOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
-    __ Ret();
-    __ Bind(normal_ir_body);
-  }
+  Label fall_through;
+  // Only smis allowed.
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ tst(R0, Operand(kSmiTagMask));
+  __ b(normal_ir_body, NE);
+  // Is Smi.
+  __ SmiUntag(R0);
+  __ vmovsr(S0, R0);
+  __ vcvtdi(D1, S0);
+  __ ldr(R0, Address(SP, 1 * target::kWordSize));
+  __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
+  __ vmuld(D0, D0, D1);
+  const Class& double_class = DoubleClass();
+  __ TryAllocate(double_class, normal_ir_body, Assembler::kFarJump, R0,
+                 R1);  // Result register.
+  __ StoreDToOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
+  __ Ret();
+  __ Bind(normal_ir_body);
 }
 
 void AsmIntrinsifier::DoubleFromInteger(Assembler* assembler,
                                         Label* normal_ir_body) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    Label fall_through;
+  Label fall_through;
 
-    __ ldr(R0, Address(SP, 0 * target::kWordSize));
-    __ tst(R0, Operand(kSmiTagMask));
-    __ b(normal_ir_body, NE);
-    // Is Smi.
-    __ SmiUntag(R0);
-    __ vmovsr(S0, R0);
-    __ vcvtdi(D0, S0);
-    const Class& double_class = DoubleClass();
-    __ TryAllocate(double_class, normal_ir_body, Assembler::kFarJump, R0,
-                   R1);  // Result register.
-    __ StoreDToOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
-    __ Ret();
-    __ Bind(normal_ir_body);
-  }
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ tst(R0, Operand(kSmiTagMask));
+  __ b(normal_ir_body, NE);
+  // Is Smi.
+  __ SmiUntag(R0);
+  __ vmovsr(S0, R0);
+  __ vcvtdi(D0, S0);
+  const Class& double_class = DoubleClass();
+  __ TryAllocate(double_class, normal_ir_body, Assembler::kFarJump, R0,
+                 R1);  // Result register.
+  __ StoreDToOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
+  __ Ret();
+  __ Bind(normal_ir_body);
 }
 
 void AsmIntrinsifier::Double_getIsNaN(Assembler* assembler,
                                       Label* normal_ir_body) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ ldr(R0, Address(SP, 0 * target::kWordSize));
-    __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
-    __ vcmpd(D0, D0);
-    __ vmstat();
-    __ LoadObject(R0, CastHandle<Object>(FalseObject()), VC);
-    __ LoadObject(R0, CastHandle<Object>(TrueObject()), VS);
-    __ Ret();
-  }
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
+  __ vcmpd(D0, D0);
+  __ vmstat();
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()), VC);
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()), VS);
+  __ Ret();
 }
 
 void AsmIntrinsifier::Double_getIsInfinite(Assembler* assembler,
                                            Label* normal_ir_body) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ ldr(R0, Address(SP, 0 * target::kWordSize));
-    // R1 <- value[0:31], R2 <- value[32:63]
-    __ LoadFieldFromOffset(R1, R0, target::Double::value_offset());
-    __ LoadFieldFromOffset(R2, R0,
-                           target::Double::value_offset() + target::kWordSize);
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  // R1 <- value[0:31], R2 <- value[32:63]
+  __ LoadFieldFromOffset(R1, R0, target::Double::value_offset());
+  __ LoadFieldFromOffset(R2, R0,
+                         target::Double::value_offset() + target::kWordSize);
 
-    // If the low word isn't 0, then it isn't infinity.
-    __ cmp(R1, Operand(0));
-    __ LoadObject(R0, CastHandle<Object>(FalseObject()), NE);
-    READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));  // Return if NE.
+  // If the low word isn't 0, then it isn't infinity.
+  __ cmp(R1, Operand(0));
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()), NE);
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));  // Return if NE.
 
-    // Mask off the sign bit.
-    __ AndImmediate(R2, R2, 0x7FFFFFFF);
-    // Compare with +infinity.
-    __ CompareImmediate(R2, 0x7FF00000);
-    __ LoadObject(R0, CastHandle<Object>(FalseObject()), NE);
-    READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));
-    __ LoadObject(R0, CastHandle<Object>(TrueObject()));
-    __ Ret();
-  }
+  // Mask off the sign bit.
+  __ AndImmediate(R2, R2, 0x7FFFFFFF);
+  // Compare with +infinity.
+  __ CompareImmediate(R2, 0x7FF00000);
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()), NE);
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
+  __ Ret();
 }
 
 void AsmIntrinsifier::Double_getIsNegative(Assembler* assembler,
                                            Label* normal_ir_body) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    Label is_false, is_true, is_zero;
-    __ ldr(R0, Address(SP, 0 * target::kWordSize));
-    __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
-    __ vcmpdz(D0);
-    __ vmstat();
-    __ b(&is_false, VS);  // NaN -> false.
-    __ b(&is_zero, EQ);   // Check for negative zero.
-    __ b(&is_false, CS);  // >= 0 -> false.
+  Label is_false, is_true, is_zero;
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
+  __ vcmpdz(D0);
+  __ vmstat();
+  __ b(&is_false, VS);  // NaN -> false.
+  __ b(&is_zero, EQ);   // Check for negative zero.
+  __ b(&is_false, CS);  // >= 0 -> false.
 
-    __ Bind(&is_true);
-    __ LoadObject(R0, CastHandle<Object>(TrueObject()));
-    __ Ret();
+  __ Bind(&is_true);
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
+  __ Ret();
 
-    __ Bind(&is_false);
-    __ LoadObject(R0, CastHandle<Object>(FalseObject()));
-    __ Ret();
+  __ Bind(&is_false);
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
+  __ Ret();
 
-    __ Bind(&is_zero);
-    // Check for negative zero by looking at the sign bit.
-    __ vmovrrd(R0, R1, D0);  // R1:R0 <- D0, so sign bit is in bit 31 of R1.
-    __ mov(R1, Operand(R1, LSR, 31));
-    __ tst(R1, Operand(1));
-    __ b(&is_true, NE);  // Sign bit set.
-    __ b(&is_false);
-  }
+  __ Bind(&is_zero);
+  // Check for negative zero by looking at the sign bit.
+  __ vmovrrd(R0, R1, D0);  // R1:R0 <- D0, so sign bit is in bit 31 of R1.
+  __ mov(R1, Operand(R1, LSR, 31));
+  __ tst(R1, Operand(1));
+  __ b(&is_true, NE);  // Sign bit set.
+  __ b(&is_false);
 }
 
 void AsmIntrinsifier::Double_hashCode(Assembler* assembler,
                                       Label* normal_ir_body) {
   // TODO(dartbug.com/31174): Convert this to a graph intrinsic.
 
-  if (!TargetCPUFeatures::vfp_supported()) return;
-
   // Load double value and check that it isn't NaN, since ARM gives an
   // FPU exception if you try to convert NaN to an int.
   Label double_hash;
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index eee0fb3..a9a71ee 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -702,7 +702,6 @@
 }
 
 void Assembler::vmovsr(SRegister sn, Register rt, Condition cond) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(sn != kNoSRegister);
   ASSERT(rt != kNoRegister);
   ASSERT(rt != SP);
@@ -716,7 +715,6 @@
 }
 
 void Assembler::vmovrs(Register rt, SRegister sn, Condition cond) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(sn != kNoSRegister);
   ASSERT(rt != kNoRegister);
   ASSERT(rt != SP);
@@ -733,7 +731,6 @@
                         Register rt,
                         Register rt2,
                         Condition cond) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(sm != kNoSRegister);
   ASSERT(sm != S31);
   ASSERT(rt != kNoRegister);
@@ -755,7 +752,6 @@
                         Register rt2,
                         SRegister sm,
                         Condition cond) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(sm != kNoSRegister);
   ASSERT(sm != S31);
   ASSERT(rt != kNoRegister);
@@ -775,7 +771,6 @@
 }
 
 void Assembler::vmovdr(DRegister dn, int i, Register rt, Condition cond) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT((i == 0) || (i == 1));
   ASSERT(rt != kNoRegister);
   ASSERT(rt != SP);
@@ -793,7 +788,6 @@
                         Register rt,
                         Register rt2,
                         Condition cond) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(dm != kNoDRegister);
   ASSERT(rt != kNoRegister);
   ASSERT(rt != SP);
@@ -814,7 +808,6 @@
                         Register rt2,
                         DRegister dm,
                         Condition cond) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(dm != kNoDRegister);
   ASSERT(rt != kNoRegister);
   ASSERT(rt != SP);
@@ -833,7 +826,6 @@
 }
 
 void Assembler::vldrs(SRegister sd, Address ad, Condition cond) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(sd != kNoSRegister);
   ASSERT(cond != kNoCondition);
   int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | B27 |
@@ -844,7 +836,6 @@
 }
 
 void Assembler::vstrs(SRegister sd, Address ad, Condition cond) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(static_cast<Register>(ad.encoding_ & (0xf << kRnShift)) != PC);
   ASSERT(sd != kNoSRegister);
   ASSERT(cond != kNoCondition);
@@ -856,7 +847,6 @@
 }
 
 void Assembler::vldrd(DRegister dd, Address ad, Condition cond) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(dd != kNoDRegister);
   ASSERT(cond != kNoCondition);
   int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | B27 |
@@ -867,7 +857,6 @@
 }
 
 void Assembler::vstrd(DRegister dd, Address ad, Condition cond) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(static_cast<Register>(ad.encoding_ & (0xf << kRnShift)) != PC);
   ASSERT(dd != kNoDRegister);
   ASSERT(cond != kNoCondition);
@@ -884,7 +873,6 @@
                                  Register base,
                                  SRegister start,
                                  uint32_t count) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(base != kNoRegister);
   ASSERT(cond != kNoCondition);
   ASSERT(start != kNoSRegister);
@@ -904,7 +892,6 @@
                                  Register base,
                                  DRegister start,
                                  int32_t count) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(base != kNoRegister);
   ASSERT(cond != kNoCondition);
   ASSERT(start != kNoDRegister);
@@ -966,7 +953,6 @@
                            SRegister sd,
                            SRegister sn,
                            SRegister sm) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(sd != kNoSRegister);
   ASSERT(sn != kNoSRegister);
   ASSERT(sm != kNoSRegister);
@@ -986,7 +972,6 @@
                            DRegister dd,
                            DRegister dn,
                            DRegister dm) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(dd != kNoDRegister);
   ASSERT(dn != kNoDRegister);
   ASSERT(dm != kNoDRegister);
@@ -1149,7 +1134,6 @@
                           int32_t opcode,
                           SRegister sd,
                           DRegister dm) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(sd != kNoSRegister);
   ASSERT(dm != kNoDRegister);
   ASSERT(cond != kNoCondition);
@@ -1165,7 +1149,6 @@
                           int32_t opcode,
                           DRegister dd,
                           SRegister sm) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(dd != kNoDRegister);
   ASSERT(sm != kNoSRegister);
   ASSERT(cond != kNoCondition);
@@ -1234,7 +1217,6 @@
 }
 
 void Assembler::vmrs(Register rd, Condition cond) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(cond != kNoCondition);
   int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | B27 |
                      B26 | B25 | B23 | B22 | B21 | B20 | B16 |
@@ -2526,24 +2508,16 @@
   PushList(kAbiPreservedCpuRegs);
 
   const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg);
-  if (TargetCPUFeatures::vfp_supported()) {
     ASSERT(2 * kAbiPreservedFpuRegCount < 16);
     // Save FPU registers. 2 D registers per Q register.
     vstmd(DB_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
-  } else {
-    sub(SP, SP, Operand(kAbiPreservedFpuRegCount * kFpuRegisterSize));
-  }
 }
 
 void Assembler::PopNativeCalleeSavedRegisters() {
   const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg);
   // Restore C++ ABI callee-saved registers.
-  if (TargetCPUFeatures::vfp_supported()) {
-    // Restore FPU registers. 2 D registers per Q register.
-    vldmd(IA_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
-  } else {
-    AddImmediate(SP, kAbiPreservedFpuRegCount * kFpuRegisterSize);
-  }
+  // Restore FPU registers. 2 D registers per Q register.
+  vldmd(IA_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
   // Restore CPU registers.
   PopList(kAbiPreservedCpuRegs);
 }
@@ -3000,17 +2974,8 @@
                                 Register tmp1,
                                 Register tmp2,
                                 DRegister dtmp) {
-  if (TargetCPUFeatures::vfp_supported()) {
     LoadDFromOffset(dtmp, src, target::Double::value_offset() - kHeapObjectTag);
     StoreDToOffset(dtmp, dst, target::Double::value_offset() - kHeapObjectTag);
-  } else {
-    LoadFieldFromOffset(tmp1, src, target::Double::value_offset());
-    LoadFieldFromOffset(tmp2, src,
-                        target::Double::value_offset() + target::kWordSize);
-    StoreFieldToOffset(tmp1, dst, target::Double::value_offset());
-    StoreFieldToOffset(tmp2, dst,
-                       target::Double::value_offset() + target::kWordSize);
-  }
 }
 
 void Assembler::CopyFloat32x4Field(Register dst,
@@ -3215,7 +3180,6 @@
   if (TargetCPUFeatures::integer_division_supported()) {
     sdiv(result, left, right);
   } else {
-    ASSERT(TargetCPUFeatures::vfp_supported());
     SRegister stmpl = EvenSRegisterOf(tmpl);
     SRegister stmpr = EvenSRegisterOf(tmpr);
     vmovsr(stmpl, left);
@@ -3298,7 +3262,6 @@
   COMPILE_ASSERT((kDartVolatileCpuRegs & (1 << PP)) == 0);
 
   // Preserve all volatile FPU registers.
-  if (TargetCPUFeatures::vfp_supported()) {
     DRegister firstv = EvenDRegisterOf(kDartFirstVolatileFpuReg);
     DRegister lastv = OddDRegisterOf(kDartLastVolatileFpuReg);
     if ((lastv - firstv + 1) >= 16) {
@@ -3308,7 +3271,6 @@
     } else {
       vstmd(DB_W, SP, firstv, lastv - firstv + 1);
     }
-  }
 
   ReserveAlignedFrameSpace(frame_space);
 }
@@ -3318,9 +3280,7 @@
   // and ensure proper alignment of the stack frame.
   // We need to restore it before restoring registers.
   const intptr_t kPushedFpuRegisterSize =
-      TargetCPUFeatures::vfp_supported()
-          ? kDartVolatileFpuRegCount * kFpuRegisterSize
-          : 0;
+      kDartVolatileFpuRegCount * kFpuRegisterSize;
 
   COMPILE_ASSERT(PP < FP);
   COMPILE_ASSERT((kDartVolatileCpuRegs & (1 << PP)) == 0);
@@ -3331,7 +3291,6 @@
   AddImmediate(SP, FP, -kPushedRegistersSize);
 
   // Restore all volatile FPU registers.
-  if (TargetCPUFeatures::vfp_supported()) {
     DRegister firstv = EvenDRegisterOf(kDartFirstVolatileFpuReg);
     DRegister lastv = OddDRegisterOf(kDartLastVolatileFpuReg);
     if ((lastv - firstv + 1) >= 16) {
@@ -3341,7 +3300,6 @@
     } else {
       vldmd(IA_W, SP, firstv, lastv - firstv + 1);
     }
-  }
 
   // Restore volatile CPU registers.
   RESTORES_LR_FROM_FRAME(
diff --git a/runtime/vm/compiler/assembler/assembler_arm_test.cc b/runtime/vm/compiler/assembler/assembler_arm_test.cc
index f925d7c..64db0ae 100644
--- a/runtime/vm/compiler/assembler/assembler_arm_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm_test.cc
@@ -273,81 +273,68 @@
 }
 
 ASSEMBLER_TEST_GENERATE(Vmov, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ mov(R3, Operand(43));
-    __ mov(R1, Operand(41));
-    __ vmovsrr(S1, R1, R3);       // S1:S2 = 41:43
-    __ vmovs(S0, S2);             // S0 = S2, S0:S1 == 43:41
-    __ vmovd(D2, D0);             // D2 = D0, S4:S5 == 43:41
-    __ vmovrs(R3, S5);            // R3 = S5, R3 == 41
-    __ vmovrrs(R1, R2, S4);       // R1:R2 = S4:S5, R1:R2 == 43:41
-    __ vmovdrr(D3, R3, R2);       // D3 = R3:R2, S6:S7 == 41:41
-    __ vmovdr(D3, 1, R1);         // D3[1] == S7 = R1, S6:S7 == 41:43
-    __ vmovrrd(R0, R1, D3);       // R0:R1 = D3, R0:R1 == 41:43
-    __ sub(R0, R1, Operand(R0));  // 43-41
-  }
+  __ mov(R3, Operand(43));
+  __ mov(R1, Operand(41));
+  __ vmovsrr(S1, R1, R3);       // S1:S2 = 41:43
+  __ vmovs(S0, S2);             // S0 = S2, S0:S1 == 43:41
+  __ vmovd(D2, D0);             // D2 = D0, S4:S5 == 43:41
+  __ vmovrs(R3, S5);            // R3 = S5, R3 == 41
+  __ vmovrrs(R1, R2, S4);       // R1:R2 = S4:S5, R1:R2 == 43:41
+  __ vmovdrr(D3, R3, R2);       // D3 = R3:R2, S6:S7 == 41:41
+  __ vmovdr(D3, 1, R1);         // D3[1] == S7 = R1, S6:S7 == 41:43
+  __ vmovrrd(R0, R1, D3);       // R0:R1 = D3, R0:R1 == 41:43
+  __ sub(R0, R1, Operand(R0));  // 43-41
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vmov, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef int (*Vmov)() DART_UNUSED;
-    EXPECT_EQ(2, EXECUTE_TEST_CODE_INT32(Vmov, test->entry()));
-  }
+  typedef int (*Vmov)() DART_UNUSED;
+  EXPECT_EQ(2, EXECUTE_TEST_CODE_INT32(Vmov, test->entry()));
 }
 
 ASSEMBLER_TEST_GENERATE(SingleVLoadStore, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ LoadImmediate(R0, bit_cast<int32_t, float>(12.3f));
-    __ mov(R2, Operand(SP));
-    __ str(R0, Address(SP, (-target::kWordSize * 30), Address::PreIndex));
-    __ vldrs(S0, Address(R2, (-target::kWordSize * 30)));
-    __ vadds(S0, S0, S0);
-    __ vstrs(S0, Address(R2, (-target::kWordSize * 30)));
-    __ ldr(R0, Address(SP, (target::kWordSize * 30), Address::PostIndex));
-  }
+  __ LoadImmediate(R0, bit_cast<int32_t, float>(12.3f));
+  __ mov(R2, Operand(SP));
+  __ str(R0, Address(SP, (-target::kWordSize * 30), Address::PreIndex));
+  __ vldrs(S0, Address(R2, (-target::kWordSize * 30)));
+  __ vadds(S0, S0, S0);
+  __ vstrs(S0, Address(R2, (-target::kWordSize * 30)));
+  __ ldr(R0, Address(SP, (target::kWordSize * 30), Address::PostIndex));
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(SingleVLoadStore, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef float (*SingleVLoadStore)() DART_UNUSED;
-    float res = EXECUTE_TEST_CODE_FLOAT(SingleVLoadStore, test->entry());
-    EXPECT_FLOAT_EQ(2 * 12.3f, res, 0.001f);
-  }
+  typedef float (*SingleVLoadStore)() DART_UNUSED;
+  float res = EXECUTE_TEST_CODE_FLOAT(SingleVLoadStore, test->entry());
+  EXPECT_FLOAT_EQ(2 * 12.3f, res, 0.001f);
 }
 
 ASSEMBLER_TEST_GENERATE(SingleVShiftLoadStore, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ LoadImmediate(R0, bit_cast<int32_t, float>(12.3f));
-    __ mov(R2, Operand(SP));
-    // Expressing __str(R0, Address(SP, (-kWordSize * 32), Address::PreIndex));
-    // as:
-    __ mov(R1, Operand(target::kWordSize));
-    __ str(R0, Address(SP, R1, LSL, 5, Address::NegPreIndex));
-    __ vldrs(S0, Address(R2, (-target::kWordSize * 32)));
-    __ vadds(S0, S0, S0);
-    __ vstrs(S0, Address(R2, (-target::kWordSize * 32)));
-    // Expressing __ldr(R0, Address(SP, (kWordSize * 32), Address::PostIndex));
-    // as:
-    __ ldr(R0, Address(SP, R1, LSL, 5, Address::PostIndex));
-  }
+  __ LoadImmediate(R0, bit_cast<int32_t, float>(12.3f));
+  __ mov(R2, Operand(SP));
+  // Expressing __str(R0, Address(SP, (-kWordSize * 32), Address::PreIndex));
+  // as:
+  __ mov(R1, Operand(target::kWordSize));
+  __ str(R0, Address(SP, R1, LSL, 5, Address::NegPreIndex));
+  __ vldrs(S0, Address(R2, (-target::kWordSize * 32)));
+  __ vadds(S0, S0, S0);
+  __ vstrs(S0, Address(R2, (-target::kWordSize * 32)));
+  // Expressing __ldr(R0, Address(SP, (kWordSize * 32), Address::PostIndex));
+  // as:
+  __ ldr(R0, Address(SP, R1, LSL, 5, Address::PostIndex));
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(SingleVShiftLoadStore, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef float (*SingleVLoadStore)() DART_UNUSED;
-    float res = EXECUTE_TEST_CODE_FLOAT(SingleVLoadStore, test->entry());
-    EXPECT_FLOAT_EQ(2 * 12.3f, res, 0.001f);
-  }
+  typedef float (*SingleVLoadStore)() DART_UNUSED;
+  float res = EXECUTE_TEST_CODE_FLOAT(SingleVLoadStore, test->entry());
+  EXPECT_FLOAT_EQ(2 * 12.3f, res, 0.001f);
 }
 
 ASSEMBLER_TEST_GENERATE(DoubleVLoadStore, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
     int64_t value = bit_cast<int64_t, double>(12.3);
     __ LoadImmediate(R0, Utils::Low32Bits(value));
     __ LoadImmediate(R1, Utils::High32Bits(value));
@@ -359,69 +346,57 @@
     __ vstrd(D0, Address(R2, (-target::kWordSize * 30)));
     __ ldr(R1, Address(R2, (-target::kWordSize * 29)));
     __ ldr(R0, Address(SP, (target::kWordSize * 30), Address::PostIndex));
-  }
-  __ Ret();
+    __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(DoubleVLoadStore, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef double (*DoubleVLoadStore)() DART_UNUSED;
-    float res = EXECUTE_TEST_CODE_DOUBLE(DoubleVLoadStore, test->entry());
-    EXPECT_FLOAT_EQ(2 * 12.3f, res, 0.001f);
-  }
+  typedef double (*DoubleVLoadStore)() DART_UNUSED;
+  float res = EXECUTE_TEST_CODE_DOUBLE(DoubleVLoadStore, test->entry());
+  EXPECT_FLOAT_EQ(2 * 12.3f, res, 0.001f);
 }
 
 ASSEMBLER_TEST_GENERATE(SingleFPOperations, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ LoadSImmediate(S0, 12.3f);
-    __ LoadSImmediate(S1, 3.4f);
-    __ vnegs(S0, S0);      // -12.3f
-    __ vabss(S0, S0);      // 12.3f
-    __ vadds(S0, S0, S1);  // 15.7f
-    __ vmuls(S0, S0, S1);  // 53.38f
-    __ vsubs(S0, S0, S1);  // 49.98f
-    __ vdivs(S0, S0, S1);  // 14.7f
-    __ vsqrts(S0, S0);     // 3.8340579f
-  }
+  __ LoadSImmediate(S0, 12.3f);
+  __ LoadSImmediate(S1, 3.4f);
+  __ vnegs(S0, S0);      // -12.3f
+  __ vabss(S0, S0);      // 12.3f
+  __ vadds(S0, S0, S1);  // 15.7f
+  __ vmuls(S0, S0, S1);  // 53.38f
+  __ vsubs(S0, S0, S1);  // 49.98f
+  __ vdivs(S0, S0, S1);  // 14.7f
+  __ vsqrts(S0, S0);     // 3.8340579f
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(SingleFPOperations, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef float (*SingleFPOperations)() DART_UNUSED;
-    float res = EXECUTE_TEST_CODE_FLOAT(SingleFPOperations, test->entry());
-    EXPECT_FLOAT_EQ(3.8340579f, res, 0.001f);
-  }
+  typedef float (*SingleFPOperations)() DART_UNUSED;
+  float res = EXECUTE_TEST_CODE_FLOAT(SingleFPOperations, test->entry());
+  EXPECT_FLOAT_EQ(3.8340579f, res, 0.001f);
 }
 
 ASSEMBLER_TEST_GENERATE(DoubleFPOperations, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ LoadDImmediate(D0, 12.3, R0);
-    __ LoadDImmediate(D1, 3.4, R0);
-    __ vnegd(D0, D0);      // -12.3
-    __ vabsd(D0, D0);      // 12.3
-    __ vaddd(D0, D0, D1);  // 15.7
-    __ vmuld(D0, D0, D1);  // 53.38
-    __ vsubd(D0, D0, D1);  // 49.98
-    __ vdivd(D0, D0, D1);  // 14.7
-    __ vsqrtd(D0, D0);     // 3.8340579
-  }
+  __ LoadDImmediate(D0, 12.3, R0);
+  __ LoadDImmediate(D1, 3.4, R0);
+  __ vnegd(D0, D0);      // -12.3
+  __ vabsd(D0, D0);      // 12.3
+  __ vaddd(D0, D0, D1);  // 15.7
+  __ vmuld(D0, D0, D1);  // 53.38
+  __ vsubd(D0, D0, D1);  // 49.98
+  __ vdivd(D0, D0, D1);  // 14.7
+  __ vsqrtd(D0, D0);     // 3.8340579
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(DoubleFPOperations, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef double (*DoubleFPOperations)() DART_UNUSED;
-    double res = EXECUTE_TEST_CODE_DOUBLE(DoubleFPOperations, test->entry());
-    EXPECT_FLOAT_EQ(3.8340579, res, 0.001);
-  }
+  typedef double (*DoubleFPOperations)() DART_UNUSED;
+  double res = EXECUTE_TEST_CODE_DOUBLE(DoubleFPOperations, test->entry());
+  EXPECT_FLOAT_EQ(3.8340579, res, 0.001);
 }
 
 ASSEMBLER_TEST_GENERATE(DoubleSqrtNeg, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
     // Check that sqrt of a negative double gives NaN.
     __ LoadDImmediate(D1, -1.0, R0);
     __ vsqrtd(D0, D1);
@@ -429,161 +404,128 @@
     __ vmstat();
     __ mov(R0, Operand(1), VS);
     __ mov(R0, Operand(0), VC);
-  }
-  __ Ret();
+    __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(DoubleSqrtNeg, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef int (*DoubleSqrtNeg)() DART_UNUSED;
-    EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(DoubleSqrtNeg, test->entry()));
-  }
+  typedef int (*DoubleSqrtNeg)() DART_UNUSED;
+  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(DoubleSqrtNeg, test->entry()));
 }
 
 ASSEMBLER_TEST_GENERATE(IntToDoubleConversion, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ mov(R3, Operand(6));
-    __ vmovsr(S3, R3);
-    __ vcvtdi(D0, S3);
-  }
+  __ mov(R3, Operand(6));
+  __ vmovsr(S3, R3);
+  __ vcvtdi(D0, S3);
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(IntToDoubleConversion, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef double (*IntToDoubleConversionCode)() DART_UNUSED;
-    double res =
-        EXECUTE_TEST_CODE_DOUBLE(IntToDoubleConversionCode, test->entry());
-    EXPECT_FLOAT_EQ(6.0, res, 0.001);
-  }
+  typedef double (*IntToDoubleConversionCode)() DART_UNUSED;
+  double res =
+      EXECUTE_TEST_CODE_DOUBLE(IntToDoubleConversionCode, test->entry());
+  EXPECT_FLOAT_EQ(6.0, res, 0.001);
 }
 
 ASSEMBLER_TEST_GENERATE(LongToDoubleConversion, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    int64_t value = 60000000000LL;
-    __ LoadImmediate(R0, Utils::Low32Bits(value));
-    __ LoadImmediate(R1, Utils::High32Bits(value));
-    __ vmovsr(S0, R0);
-    __ vmovsr(S2, R1);
-    __ vcvtdu(D0, S0);
-    __ vcvtdi(D1, S2);
-    __ LoadDImmediate(D2, 1.0 * (1LL << 32), R0);
-    __ vmlad(D0, D1, D2);
-  }
+  int64_t value = 60000000000LL;
+  __ LoadImmediate(R0, Utils::Low32Bits(value));
+  __ LoadImmediate(R1, Utils::High32Bits(value));
+  __ vmovsr(S0, R0);
+  __ vmovsr(S2, R1);
+  __ vcvtdu(D0, S0);
+  __ vcvtdi(D1, S2);
+  __ LoadDImmediate(D2, 1.0 * (1LL << 32), R0);
+  __ vmlad(D0, D1, D2);
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(LongToDoubleConversion, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef double (*LongToDoubleConversionCode)() DART_UNUSED;
-    double res =
-        EXECUTE_TEST_CODE_DOUBLE(LongToDoubleConversionCode, test->entry());
-    EXPECT_FLOAT_EQ(60000000000.0, res, 0.001);
-  }
+  typedef double (*LongToDoubleConversionCode)() DART_UNUSED;
+  double res =
+      EXECUTE_TEST_CODE_DOUBLE(LongToDoubleConversionCode, test->entry());
+  EXPECT_FLOAT_EQ(60000000000.0, res, 0.001);
 }
 
 ASSEMBLER_TEST_GENERATE(IntToFloatConversion, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ mov(R3, Operand(6));
-    __ vmovsr(S3, R3);
-    __ vcvtsi(S0, S3);
-  }
+  __ mov(R3, Operand(6));
+  __ vmovsr(S3, R3);
+  __ vcvtsi(S0, S3);
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(IntToFloatConversion, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef float (*IntToFloatConversionCode)() DART_UNUSED;
-    float res =
-        EXECUTE_TEST_CODE_FLOAT(IntToFloatConversionCode, test->entry());
-    EXPECT_FLOAT_EQ(6.0, res, 0.001);
-  }
+  typedef float (*IntToFloatConversionCode)() DART_UNUSED;
+  float res = EXECUTE_TEST_CODE_FLOAT(IntToFloatConversionCode, test->entry());
+  EXPECT_FLOAT_EQ(6.0, res, 0.001);
 }
 
 ASSEMBLER_TEST_GENERATE(FloatToIntConversion, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ vcvtis(S1, S0);
-    __ vmovrs(R0, S1);
-  }
+  __ vcvtis(S1, S0);
+  __ vmovrs(R0, S1);
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(FloatToIntConversion, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef int (*FloatToIntConversion)(float arg) DART_UNUSED;
-    EXPECT_EQ(12, EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion, test->entry(),
-                                            12.8f));
-    EXPECT_EQ(INT32_MIN, EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion,
-                                                   test->entry(), -FLT_MAX));
-    EXPECT_EQ(INT32_MAX, EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion,
-                                                   test->entry(), FLT_MAX));
-  }
+  typedef int (*FloatToIntConversion)(float arg) DART_UNUSED;
+  EXPECT_EQ(12, EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion, test->entry(),
+                                          12.8f));
+  EXPECT_EQ(INT32_MIN, EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion,
+                                                 test->entry(), -FLT_MAX));
+  EXPECT_EQ(INT32_MAX, EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion,
+                                                 test->entry(), FLT_MAX));
 }
 
 ASSEMBLER_TEST_GENERATE(DoubleToIntConversion, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ vcvtid(S0, D0);
-    __ vmovrs(R0, S0);
-  }
+  __ vcvtid(S0, D0);
+  __ vmovrs(R0, S0);
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(DoubleToIntConversion, test) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef int (*DoubleToIntConversion)(double arg) DART_UNUSED;
-    EXPECT(test != NULL);
-    EXPECT_EQ(12, EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion,
-                                            test->entry(), 12.8));
-    EXPECT_EQ(INT32_MIN, EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion,
-                                                   test->entry(), -DBL_MAX));
-    EXPECT_EQ(INT32_MAX, EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion,
-                                                   test->entry(), DBL_MAX));
-  }
+  typedef int (*DoubleToIntConversion)(double arg) DART_UNUSED;
+  EXPECT(test != NULL);
+  EXPECT_EQ(12, EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion, test->entry(),
+                                          12.8));
+  EXPECT_EQ(INT32_MIN, EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion,
+                                                 test->entry(), -DBL_MAX));
+  EXPECT_EQ(INT32_MAX, EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion,
+                                                 test->entry(), DBL_MAX));
 }
 
 ASSEMBLER_TEST_GENERATE(FloatToDoubleConversion, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ LoadSImmediate(S2, 12.8f);
-    __ vcvtds(D0, S2);
-  }
+  __ LoadSImmediate(S2, 12.8f);
+  __ vcvtds(D0, S2);
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(FloatToDoubleConversion, test) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef double (*FloatToDoubleConversionCode)() DART_UNUSED;
-    EXPECT(test != NULL);
-    double res =
-        EXECUTE_TEST_CODE_DOUBLE(FloatToDoubleConversionCode, test->entry());
-    EXPECT_FLOAT_EQ(12.8, res, 0.001);
-  }
+  typedef double (*FloatToDoubleConversionCode)() DART_UNUSED;
+  EXPECT(test != NULL);
+  double res =
+      EXECUTE_TEST_CODE_DOUBLE(FloatToDoubleConversionCode, test->entry());
+  EXPECT_FLOAT_EQ(12.8, res, 0.001);
 }
 
 ASSEMBLER_TEST_GENERATE(DoubleToFloatConversion, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ LoadDImmediate(D1, 12.8, R0);
-    __ vcvtsd(S0, D1);
-  }
+  __ LoadDImmediate(D1, 12.8, R0);
+  __ vcvtsd(S0, D1);
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(DoubleToFloatConversion, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef float (*DoubleToFloatConversionCode)() DART_UNUSED;
-    float res =
-        EXECUTE_TEST_CODE_FLOAT(DoubleToFloatConversionCode, test->entry());
-    EXPECT_FLOAT_EQ(12.8, res, 0.001);
-  }
+  typedef float (*DoubleToFloatConversionCode)() DART_UNUSED;
+  float res =
+      EXECUTE_TEST_CODE_FLOAT(DoubleToFloatConversionCode, test->entry());
+  EXPECT_FLOAT_EQ(12.8, res, 0.001);
 }
 
 ASSEMBLER_TEST_GENERATE(FloatCompare, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
     // Test 12.3f vs 12.5f.
     __ LoadSImmediate(S0, 12.3f);
     __ LoadSImmediate(S1, 12.5f);
@@ -605,21 +547,17 @@
     __ vmstat();
     // Error if not unordered (not Nan).
     __ add(R0, R0, Operand(16), VC);
-  }
-  // R0 is 0 if all tests passed.
-  __ Ret();
+    // R0 is 0 if all tests passed.
+    __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(FloatCompare, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef int (*FloatCompare)() DART_UNUSED;
-    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(FloatCompare, test->entry()));
-  }
+  typedef int (*FloatCompare)() DART_UNUSED;
+  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(FloatCompare, test->entry()));
 }
 
 ASSEMBLER_TEST_GENERATE(DoubleCompare, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
     // Test 12.3 vs 12.5.
     __ LoadDImmediate(D0, 12.3, R1);
     __ LoadDImmediate(D1, 12.5, R1);
@@ -641,17 +579,14 @@
     __ vmstat();
     // Error if not unordered (not Nan).
     __ add(R0, R0, Operand(16), VC);
-  }
-  // R0 is 0 if all tests passed.
-  __ Ret();
+    // R0 is 0 if all tests passed.
+    __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(DoubleCompare, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef int (*DoubleCompare)() DART_UNUSED;
-    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(DoubleCompare, test->entry()));
-  }
+  typedef int (*DoubleCompare)() DART_UNUSED;
+  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(DoubleCompare, test->entry()));
 }
 
 ASSEMBLER_TEST_GENERATE(Loop, assembler) {
@@ -976,28 +911,24 @@
 }
 
 ASSEMBLER_TEST_GENERATE(QuotientRemainder, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ vmovsr(S2, R0);
-    __ vmovsr(S4, R2);
-    __ vcvtdi(D1, S2);
-    __ vcvtdi(D2, S4);
-    __ vdivd(D0, D1, D2);
-    __ vcvtid(S0, D0);
-    __ vmovrs(R1, S0);       // r1 = r0/r2
-    __ mls(R0, R1, R2, R0);  // r0 = r0 - r1*r2
-  }
+  __ vmovsr(S2, R0);
+  __ vmovsr(S4, R2);
+  __ vcvtdi(D1, S2);
+  __ vcvtdi(D2, S4);
+  __ vdivd(D0, D1, D2);
+  __ vcvtid(S0, D0);
+  __ vmovrs(R1, S0);       // r1 = r0/r2
+  __ mls(R0, R1, R2, R0);  // r0 = r0 - r1*r2
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(QuotientRemainder, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef int64_t (*QuotientRemainder)(int64_t dividend, int64_t divisor)
-        DART_UNUSED;
-    EXPECT_EQ(0x1000400000da8LL,
-              EXECUTE_TEST_CODE_INT64_LL(QuotientRemainder, test->entry(),
-                                         0x12345678, 0x1234));
-  }
+  typedef int64_t (*QuotientRemainder)(int64_t dividend, int64_t divisor)
+      DART_UNUSED;
+  EXPECT_EQ(0x1000400000da8LL,
+            EXECUTE_TEST_CODE_INT64_LL(QuotientRemainder, test->entry(),
+                                       0x12345678, 0x1234));
 }
 
 ASSEMBLER_TEST_GENERATE(Multiply64To64, assembler) {
@@ -1437,332 +1368,308 @@
 
 // Make sure we can store and reload the D registers using vstmd and vldmd
 ASSEMBLER_TEST_GENERATE(VstmdVldmd, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ LoadDImmediate(D0, 0.0, R0);
-    __ LoadDImmediate(D1, 1.0, R0);
-    __ LoadDImmediate(D2, 2.0, R0);
-    __ LoadDImmediate(D3, 3.0, R0);
-    __ LoadDImmediate(D4, 4.0, R0);
-    __ vstmd(DB_W, SP, D0, 5);  // Push D0 - D4 onto the stack, dec SP
-    __ LoadDImmediate(D0, 0.0, R0);
-    __ LoadDImmediate(D1, 0.0, R0);
-    __ LoadDImmediate(D2, 0.0, R0);
-    __ LoadDImmediate(D3, 0.0, R0);
-    __ LoadDImmediate(D4, 0.0, R0);
-    __ vldmd(IA_W, SP, D0, 5);  // Pop stack into D0 - D4, inc SP
+  __ LoadDImmediate(D0, 0.0, R0);
+  __ LoadDImmediate(D1, 1.0, R0);
+  __ LoadDImmediate(D2, 2.0, R0);
+  __ LoadDImmediate(D3, 3.0, R0);
+  __ LoadDImmediate(D4, 4.0, R0);
+  __ vstmd(DB_W, SP, D0, 5);  // Push D0 - D4 onto the stack, dec SP
+  __ LoadDImmediate(D0, 0.0, R0);
+  __ LoadDImmediate(D1, 0.0, R0);
+  __ LoadDImmediate(D2, 0.0, R0);
+  __ LoadDImmediate(D3, 0.0, R0);
+  __ LoadDImmediate(D4, 0.0, R0);
+  __ vldmd(IA_W, SP, D0, 5);  // Pop stack into D0 - D4, inc SP
 
-    // Load success value into R0
-    __ mov(R0, Operand(42));
+  // Load success value into R0
+  __ mov(R0, Operand(42));
 
-    // Check that 4.0 is back in D4
-    __ LoadDImmediate(D5, 4.0, R1);
-    __ vcmpd(D4, D5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
+  // Check that 4.0 is back in D4
+  __ LoadDImmediate(D5, 4.0, R1);
+  __ vcmpd(D4, D5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
 
-    // Check that 3.0 is back in D3
-    __ LoadDImmediate(D5, 3.0, R1);
-    __ vcmpd(D3, D5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
+  // Check that 3.0 is back in D3
+  __ LoadDImmediate(D5, 3.0, R1);
+  __ vcmpd(D3, D5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
 
-    // Check that 2.0 is back in D2
-    __ LoadDImmediate(D5, 2.0, R1);
-    __ vcmpd(D2, D5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
+  // Check that 2.0 is back in D2
+  __ LoadDImmediate(D5, 2.0, R1);
+  __ vcmpd(D2, D5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
 
-    // Check that 1.0 is back in D1
-    __ LoadDImmediate(D5, 1.0, R1);
-    __ vcmpd(D1, D5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
-  }
+  // Check that 1.0 is back in D1
+  __ LoadDImmediate(D5, 1.0, R1);
+  __ vcmpd(D1, D5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VstmdVldmd, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef int (*Tst)() DART_UNUSED;
-    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
-  }
+  typedef int (*Tst)() DART_UNUSED;
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
 }
 
 // Make sure we can store and reload the S registers using vstms and vldms
 ASSEMBLER_TEST_GENERATE(VstmsVldms, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ LoadSImmediate(S0, 0.0);
-    __ LoadSImmediate(S1, 1.0);
-    __ LoadSImmediate(S2, 2.0);
-    __ LoadSImmediate(S3, 3.0);
-    __ LoadSImmediate(S4, 4.0);
-    __ vstms(DB_W, SP, S0, S4);  // Push S0 - S4 onto the stack, dec SP
-    __ LoadSImmediate(S0, 0.0);
-    __ LoadSImmediate(S1, 0.0);
-    __ LoadSImmediate(S2, 0.0);
-    __ LoadSImmediate(S3, 0.0);
-    __ LoadSImmediate(S4, 0.0);
-    __ vldms(IA_W, SP, S0, S4);  // Pop stack into S0 - S4, inc SP
+  __ LoadSImmediate(S0, 0.0);
+  __ LoadSImmediate(S1, 1.0);
+  __ LoadSImmediate(S2, 2.0);
+  __ LoadSImmediate(S3, 3.0);
+  __ LoadSImmediate(S4, 4.0);
+  __ vstms(DB_W, SP, S0, S4);  // Push S0 - S4 onto the stack, dec SP
+  __ LoadSImmediate(S0, 0.0);
+  __ LoadSImmediate(S1, 0.0);
+  __ LoadSImmediate(S2, 0.0);
+  __ LoadSImmediate(S3, 0.0);
+  __ LoadSImmediate(S4, 0.0);
+  __ vldms(IA_W, SP, S0, S4);  // Pop stack into S0 - S4, inc SP
 
-    // Load success value into R0
-    __ mov(R0, Operand(42));
+  // Load success value into R0
+  __ mov(R0, Operand(42));
 
-    // Check that 4.0 is back in S4
-    __ LoadSImmediate(S5, 4.0);
-    __ vcmps(S4, S5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
+  // Check that 4.0 is back in S4
+  __ LoadSImmediate(S5, 4.0);
+  __ vcmps(S4, S5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
 
-    // Check that 3.0 is back in S3
-    __ LoadSImmediate(S5, 3.0);
-    __ vcmps(S3, S5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
+  // Check that 3.0 is back in S3
+  __ LoadSImmediate(S5, 3.0);
+  __ vcmps(S3, S5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
 
-    // Check that 2.0 is back in S2
-    __ LoadSImmediate(S5, 2.0);
-    __ vcmps(S2, S5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
+  // Check that 2.0 is back in S2
+  __ LoadSImmediate(S5, 2.0);
+  __ vcmps(S2, S5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
 
-    // Check that 1.0 is back in S1
-    __ LoadSImmediate(S5, 1.0);
-    __ vcmps(S1, S5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
-  }
+  // Check that 1.0 is back in S1
+  __ LoadSImmediate(S5, 1.0);
+  __ vcmps(S1, S5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VstmsVldms, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef int (*Tst)() DART_UNUSED;
-    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
-  }
+  typedef int (*Tst)() DART_UNUSED;
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
 }
 
 // Make sure we can start somewhere other than D0
 ASSEMBLER_TEST_GENERATE(VstmdVldmd1, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ LoadDImmediate(D1, 1.0, R0);
-    __ LoadDImmediate(D2, 2.0, R0);
-    __ LoadDImmediate(D3, 3.0, R0);
-    __ LoadDImmediate(D4, 4.0, R0);
-    __ vstmd(DB_W, SP, D1, 4);  // Push D1 - D4 onto the stack, dec SP
-    __ LoadDImmediate(D1, 0.0, R0);
-    __ LoadDImmediate(D2, 0.0, R0);
-    __ LoadDImmediate(D3, 0.0, R0);
-    __ LoadDImmediate(D4, 0.0, R0);
-    __ vldmd(IA_W, SP, D1, 4);  // Pop stack into D1 - D4, inc SP
+  __ LoadDImmediate(D1, 1.0, R0);
+  __ LoadDImmediate(D2, 2.0, R0);
+  __ LoadDImmediate(D3, 3.0, R0);
+  __ LoadDImmediate(D4, 4.0, R0);
+  __ vstmd(DB_W, SP, D1, 4);  // Push D1 - D4 onto the stack, dec SP
+  __ LoadDImmediate(D1, 0.0, R0);
+  __ LoadDImmediate(D2, 0.0, R0);
+  __ LoadDImmediate(D3, 0.0, R0);
+  __ LoadDImmediate(D4, 0.0, R0);
+  __ vldmd(IA_W, SP, D1, 4);  // Pop stack into D1 - D4, inc SP
 
-    // Load success value into R0
-    __ mov(R0, Operand(42));
+  // Load success value into R0
+  __ mov(R0, Operand(42));
 
-    // Check that 4.0 is back in D4
-    __ LoadDImmediate(D5, 4.0, R1);
-    __ vcmpd(D4, D5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
+  // Check that 4.0 is back in D4
+  __ LoadDImmediate(D5, 4.0, R1);
+  __ vcmpd(D4, D5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
 
-    // Check that 3.0 is back in D3
-    __ LoadDImmediate(D5, 3.0, R1);
-    __ vcmpd(D3, D5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
+  // Check that 3.0 is back in D3
+  __ LoadDImmediate(D5, 3.0, R1);
+  __ vcmpd(D3, D5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
 
-    // Check that 2.0 is back in D2
-    __ LoadDImmediate(D5, 2.0, R1);
-    __ vcmpd(D2, D5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
+  // Check that 2.0 is back in D2
+  __ LoadDImmediate(D5, 2.0, R1);
+  __ vcmpd(D2, D5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
 
-    // Check that 1.0 is back in D1
-    __ LoadDImmediate(D5, 1.0, R1);
-    __ vcmpd(D1, D5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
-  }
+  // Check that 1.0 is back in D1
+  __ LoadDImmediate(D5, 1.0, R1);
+  __ vcmpd(D1, D5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VstmdVldmd1, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef int (*Tst)() DART_UNUSED;
-    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
-  }
+  typedef int (*Tst)() DART_UNUSED;
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
 }
 
 // Make sure we can start somewhere other than S0
 ASSEMBLER_TEST_GENERATE(VstmsVldms1, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ LoadSImmediate(S1, 1.0);
-    __ LoadSImmediate(S2, 2.0);
-    __ LoadSImmediate(S3, 3.0);
-    __ LoadSImmediate(S4, 4.0);
-    __ vstms(DB_W, SP, S1, S4);  // Push S0 - S4 onto the stack, dec SP
-    __ LoadSImmediate(S1, 0.0);
-    __ LoadSImmediate(S2, 0.0);
-    __ LoadSImmediate(S3, 0.0);
-    __ LoadSImmediate(S4, 0.0);
-    __ vldms(IA_W, SP, S1, S4);  // Pop stack into S0 - S4, inc SP
+  __ LoadSImmediate(S1, 1.0);
+  __ LoadSImmediate(S2, 2.0);
+  __ LoadSImmediate(S3, 3.0);
+  __ LoadSImmediate(S4, 4.0);
+  __ vstms(DB_W, SP, S1, S4);  // Push S0 - S4 onto the stack, dec SP
+  __ LoadSImmediate(S1, 0.0);
+  __ LoadSImmediate(S2, 0.0);
+  __ LoadSImmediate(S3, 0.0);
+  __ LoadSImmediate(S4, 0.0);
+  __ vldms(IA_W, SP, S1, S4);  // Pop stack into S0 - S4, inc SP
 
-    // Load success value into R0
-    __ mov(R0, Operand(42));
+  // Load success value into R0
+  __ mov(R0, Operand(42));
 
-    // Check that 4.0 is back in S4
-    __ LoadSImmediate(S5, 4.0);
-    __ vcmps(S4, S5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
+  // Check that 4.0 is back in S4
+  __ LoadSImmediate(S5, 4.0);
+  __ vcmps(S4, S5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
 
-    // Check that 3.0 is back in S3
-    __ LoadSImmediate(S5, 3.0);
-    __ vcmps(S3, S5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
+  // Check that 3.0 is back in S3
+  __ LoadSImmediate(S5, 3.0);
+  __ vcmps(S3, S5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
 
-    // Check that 2.0 is back in S2
-    __ LoadSImmediate(S5, 2.0);
-    __ vcmps(S2, S5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
+  // Check that 2.0 is back in S2
+  __ LoadSImmediate(S5, 2.0);
+  __ vcmps(S2, S5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
 
-    // Check that 1.0 is back in S1
-    __ LoadSImmediate(S5, 1.0);
-    __ vcmps(S1, S5);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
-  }
+  // Check that 1.0 is back in S1
+  __ LoadSImmediate(S5, 1.0);
+  __ vcmps(S1, S5);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VstmsVldms1, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef int (*Tst)() DART_UNUSED;
-    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
-  }
+  typedef int (*Tst)() DART_UNUSED;
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
 }
 
 // Make sure we can store the D registers using vstmd and
 // load them into a different set using vldmd
 ASSEMBLER_TEST_GENERATE(VstmdVldmd_off, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    // Save used callee-saved FPU registers.
-    __ vstmd(DB_W, SP, D8, 3);
-    __ LoadDImmediate(D0, 0.0, R0);
-    __ LoadDImmediate(D1, 1.0, R0);
-    __ LoadDImmediate(D2, 2.0, R0);
-    __ LoadDImmediate(D3, 3.0, R0);
-    __ LoadDImmediate(D4, 4.0, R0);
-    __ LoadDImmediate(D5, 5.0, R0);
-    __ vstmd(DB_W, SP, D0, 5);  // Push D0 - D4 onto the stack, dec SP
-    __ vldmd(IA_W, SP, D5, 5);  // Pop stack into D5 - D9, inc SP
+  // Save used callee-saved FPU registers.
+  __ vstmd(DB_W, SP, D8, 3);
+  __ LoadDImmediate(D0, 0.0, R0);
+  __ LoadDImmediate(D1, 1.0, R0);
+  __ LoadDImmediate(D2, 2.0, R0);
+  __ LoadDImmediate(D3, 3.0, R0);
+  __ LoadDImmediate(D4, 4.0, R0);
+  __ LoadDImmediate(D5, 5.0, R0);
+  __ vstmd(DB_W, SP, D0, 5);  // Push D0 - D4 onto the stack, dec SP
+  __ vldmd(IA_W, SP, D5, 5);  // Pop stack into D5 - D9, inc SP
 
-    // Load success value into R0
-    __ mov(R0, Operand(42));
+  // Load success value into R0
+  __ mov(R0, Operand(42));
 
-    // Check that 4.0 is in D9
-    __ LoadDImmediate(D10, 4.0, R1);
-    __ vcmpd(D9, D10);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
+  // Check that 4.0 is in D9
+  __ LoadDImmediate(D10, 4.0, R1);
+  __ vcmpd(D9, D10);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
 
-    // Check that 3.0 is in D8
-    __ LoadDImmediate(D10, 3.0, R1);
-    __ vcmpd(D8, D10);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
+  // Check that 3.0 is in D8
+  __ LoadDImmediate(D10, 3.0, R1);
+  __ vcmpd(D8, D10);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
 
-    // Check that 2.0 is in D7
-    __ LoadDImmediate(D10, 2.0, R1);
-    __ vcmpd(D7, D10);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
+  // Check that 2.0 is in D7
+  __ LoadDImmediate(D10, 2.0, R1);
+  __ vcmpd(D7, D10);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
 
-    // Check that 1.0 is in D6
-    __ LoadDImmediate(D10, 1.0, R1);
-    __ vcmpd(D6, D10);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
+  // Check that 1.0 is in D6
+  __ LoadDImmediate(D10, 1.0, R1);
+  __ vcmpd(D6, D10);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
 
-    // Check that 0.0 is in D5
-    __ LoadDImmediate(D10, 0.0, R1);
-    __ vcmpd(D5, D10);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
+  // Check that 0.0 is in D5
+  __ LoadDImmediate(D10, 0.0, R1);
+  __ vcmpd(D5, D10);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
 
-    // Restore used callee-saved FPU registers.
-    __ vldmd(IA_W, SP, D8, 3);
-  }
+  // Restore used callee-saved FPU registers.
+  __ vldmd(IA_W, SP, D8, 3);
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VstmdVldmd_off, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef int (*Tst)() DART_UNUSED;
-    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
-  }
+  typedef int (*Tst)() DART_UNUSED;
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
 }
 
 // Make sure we can start somewhere other than S0
 ASSEMBLER_TEST_GENERATE(VstmsVldms_off, assembler) {
-  if (TargetCPUFeatures::vfp_supported()) {
-    __ LoadSImmediate(S0, 0.0);
-    __ LoadSImmediate(S1, 1.0);
-    __ LoadSImmediate(S2, 2.0);
-    __ LoadSImmediate(S3, 3.0);
-    __ LoadSImmediate(S4, 4.0);
-    __ LoadSImmediate(S5, 5.0);
-    __ vstms(DB_W, SP, S0, S4);  // Push S0 - S4 onto the stack, dec SP
-    __ vldms(IA_W, SP, S5, S9);  // Pop stack into S5 - S9, inc SP
+  __ LoadSImmediate(S0, 0.0);
+  __ LoadSImmediate(S1, 1.0);
+  __ LoadSImmediate(S2, 2.0);
+  __ LoadSImmediate(S3, 3.0);
+  __ LoadSImmediate(S4, 4.0);
+  __ LoadSImmediate(S5, 5.0);
+  __ vstms(DB_W, SP, S0, S4);  // Push S0 - S4 onto the stack, dec SP
+  __ vldms(IA_W, SP, S5, S9);  // Pop stack into S5 - S9, inc SP
 
-    // Load success value into R0
-    __ mov(R0, Operand(42));
+  // Load success value into R0
+  __ mov(R0, Operand(42));
 
-    // Check that 4.0 is in S9
-    __ LoadSImmediate(S10, 4.0);
-    __ vcmps(S9, S10);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
+  // Check that 4.0 is in S9
+  __ LoadSImmediate(S10, 4.0);
+  __ vcmps(S9, S10);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
 
-    // Check that 3.0 is in S8
-    __ LoadSImmediate(S10, 3.0);
-    __ vcmps(S8, S10);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
+  // Check that 3.0 is in S8
+  __ LoadSImmediate(S10, 3.0);
+  __ vcmps(S8, S10);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
 
-    // Check that 2.0 is in S7
-    __ LoadSImmediate(S10, 2.0);
-    __ vcmps(S7, S10);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
+  // Check that 2.0 is in S7
+  __ LoadSImmediate(S10, 2.0);
+  __ vcmps(S7, S10);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
 
-    // Check that 1.0 is back in S6
-    __ LoadSImmediate(S10, 1.0);
-    __ vcmps(S6, S10);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
+  // Check that 1.0 is back in S6
+  __ LoadSImmediate(S10, 1.0);
+  __ vcmps(S6, S10);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
 
-    // Check that 0.0 is back in S5
-    __ LoadSImmediate(S10, 0.0);
-    __ vcmps(S5, S10);
-    __ vmstat();
-    __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
-  }
+  // Check that 0.0 is back in S5
+  __ LoadSImmediate(S10, 0.0);
+  __ vcmps(S5, S10);
+  __ vmstat();
+  __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
   __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VstmsVldms_off, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::vfp_supported()) {
-    typedef int (*Tst)() DART_UNUSED;
-    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
-  }
+  typedef int (*Tst)() DART_UNUSED;
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
 }
 
 //                                          3         2         1         0
@@ -1942,11 +1849,9 @@
   HostCPUFeatures::set_integer_division_supported(orig);
   __ Ret();
 #else
-  if (TargetCPUFeatures::can_divide()) {
-    __ mov(R0, Operand(27));
-    __ mov(R1, Operand(9));
-    __ IntegerDivide(R0, R0, R1, D0, D1);
-  }
+  __ mov(R0, Operand(27));
+  __ mov(R1, Operand(9));
+  __ IntegerDivide(R0, R0, R1, D0, D1);
   __ Ret();
 #endif
 }
@@ -1956,36 +1861,28 @@
 #if defined(USING_SIMULATOR)
   bool orig = TargetCPUFeatures::integer_division_supported();
   HostCPUFeatures::set_integer_division_supported(true);
-  if (TargetCPUFeatures::can_divide()) {
-    typedef int (*Tst)() DART_UNUSED;
-    EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
-  }
+  typedef int (*Tst)() DART_UNUSED;
+  EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
   HostCPUFeatures::set_integer_division_supported(orig);
 #else
-  if (TargetCPUFeatures::can_divide()) {
-    typedef int (*Tst)() DART_UNUSED;
-    EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
-  }
+  typedef int (*Tst)() DART_UNUSED;
+  EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
 #endif
 }
 
 ASSEMBLER_TEST_GENERATE(IntDiv_unsupported, assembler) {
 #if defined(USING_SIMULATOR)
-  if (TargetCPUFeatures::can_divide()) {
     bool orig = TargetCPUFeatures::integer_division_supported();
     HostCPUFeatures::set_integer_division_supported(false);
     __ mov(R0, Operand(27));
     __ mov(R1, Operand(9));
     __ IntegerDivide(R0, R0, R1, D0, D1);
     HostCPUFeatures::set_integer_division_supported(orig);
-  }
   __ Ret();
 #else
-  if (TargetCPUFeatures::can_divide()) {
-    __ mov(R0, Operand(27));
-    __ mov(R1, Operand(9));
-    __ IntegerDivide(R0, R0, R1, D0, D1);
-  }
+  __ mov(R0, Operand(27));
+  __ mov(R1, Operand(9));
+  __ IntegerDivide(R0, R0, R1, D0, D1);
   __ Ret();
 #endif
 }
@@ -1995,16 +1892,12 @@
 #if defined(USING_SIMULATOR)
   bool orig = TargetCPUFeatures::integer_division_supported();
   HostCPUFeatures::set_integer_division_supported(false);
-  if (TargetCPUFeatures::can_divide()) {
-    typedef int (*Tst)() DART_UNUSED;
-    EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
-  }
+  typedef int (*Tst)() DART_UNUSED;
+  EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
   HostCPUFeatures::set_integer_division_supported(orig);
 #else
-  if (TargetCPUFeatures::can_divide()) {
-    typedef int (*Tst)() DART_UNUSED;
-    EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
-  }
+  typedef int (*Tst)() DART_UNUSED;
+  EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
 #endif
 }
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 7bf8100..975e431 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -471,7 +471,6 @@
 
   static bool SupportsUnboxedDoubles();
   static bool SupportsUnboxedSimd128();
-  static bool SupportsHardwareDivision();
   static bool CanConvertInt64ToDouble();
 
   // Accessors.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 3402cb2..d95dd98 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -66,17 +66,13 @@
 }
 
 bool FlowGraphCompiler::SupportsUnboxedDoubles() {
-  return TargetCPUFeatures::vfp_supported() && FLAG_unbox_doubles;
+  return FLAG_unbox_doubles;
 }
 
 bool FlowGraphCompiler::SupportsUnboxedSimd128() {
   return TargetCPUFeatures::neon_supported() && FLAG_enable_simd_inline;
 }
 
-bool FlowGraphCompiler::SupportsHardwareDivision() {
-  return TargetCPUFeatures::can_divide();
-}
-
 bool FlowGraphCompiler::CanConvertInt64ToDouble() {
   // ARM does not have a short instruction sequence for converting int64 to
   // double.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index d7e4d14..abad72a 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -73,10 +73,6 @@
   return true;
 }
 
-bool FlowGraphCompiler::SupportsHardwareDivision() {
-  return true;
-}
-
 void FlowGraphCompiler::EnterIntrinsicMode() {
   ASSERT(!intrinsic_mode());
   intrinsic_mode_ = true;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index d613572..1daf4c0 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -48,10 +48,6 @@
   return FLAG_enable_simd_inline;
 }
 
-bool FlowGraphCompiler::SupportsHardwareDivision() {
-  return true;
-}
-
 bool FlowGraphCompiler::CanConvertInt64ToDouble() {
   return true;
 }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 03922aa..91cc786 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -70,10 +70,6 @@
   return FLAG_enable_simd_inline;
 }
 
-bool FlowGraphCompiler::SupportsHardwareDivision() {
-  return true;
-}
-
 bool FlowGraphCompiler::CanConvertInt64ToDouble() {
   return true;
 }
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 3e956fe..d15b079 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -4139,7 +4139,6 @@
       break;
     }
     case Token::kTRUNCDIV: {
-      ASSERT(TargetCPUFeatures::can_divide());
       if (RangeUtils::CanBeZero(right_range())) {
         // Handle divide by zero in runtime.
         __ cmp(right, compiler::Operand(0));
@@ -4161,7 +4160,6 @@
       break;
     }
     case Token::kMOD: {
-      ASSERT(TargetCPUFeatures::can_divide());
       if (RangeUtils::CanBeZero(right_range())) {
         // Handle divide by zero in runtime.
         __ cmp(right, compiler::Operand(0));
@@ -6229,7 +6227,6 @@
   compiler::Label* deopt =
       compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
 
-  ASSERT(TargetCPUFeatures::can_divide());
   const Register left = locs()->in(0).reg();
   const Register right = locs()->in(1).reg();
   ASSERT(locs()->out(0).IsPairLocation());
diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h
index dd01b09..56c5604 100644
--- a/runtime/vm/compiler/backend/locations.h
+++ b/runtime/vm/compiler/backend/locations.h
@@ -597,15 +597,9 @@
       Add(Location::RegisterLocation(reg));
     }
 
-#if defined(TARGET_ARCH_ARM)
-    if (TargetCPUFeatures::vfp_supported()) {
-#endif
       for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) {
         Add(Location::FpuRegisterLocation(static_cast<FpuRegister>(i)));
       }
-#if defined(TARGET_ARCH_ARM)
-    }
-#endif
   }
 
   void AddAllArgumentRegisters() {
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 90d1657..c6325a5 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -539,7 +539,6 @@
       }
       break;
     case Token::kDIV:
-      if (!FlowGraphCompiler::SupportsHardwareDivision()) return false;
       if (ShouldSpecializeForDouble(binary_feedback) ||
           binary_feedback.OperandsAre(kSmiCid)) {
         operands_type = kDoubleCid;
@@ -593,7 +592,6 @@
       break;
     case Token::kMOD:
     case Token::kTRUNCDIV:
-      if (!FlowGraphCompiler::SupportsHardwareDivision()) return false;
       if (binary_feedback.OperandsAre(kSmiCid)) {
         if (call->ic_data()->HasDeoptReason(ICData::kDeoptBinarySmiOp)) {
           return false;
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index ccdc992..314505e 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -364,7 +364,7 @@
           intptr_t argument_count;
           instructions += BuildArguments(
               &argument_names, &argument_count,
-              /* positional_parameter_count = */ NULL);  // read arguments.
+              /* positional_parameter_count = */ nullptr);  // read arguments.
           argument_count += 1;
 
           Class& parent_klass = GetSuperOrDie();
@@ -390,7 +390,7 @@
           intptr_t argument_count;
           instructions += BuildArguments(
               &argument_names, &argument_count,
-              /* positional_parameter_count = */ NULL);  // read arguments.
+              /* positional_parameter_count = */ nullptr);  // read arguments.
           argument_count += 1;
 
           const Function& target = Function::ZoneHandle(
@@ -487,7 +487,7 @@
     ASSERT(yield_continuations().is_empty() || !dart_function.IsGeneric());
 
     LocalVariable* fn_type_args = parsed_function()->function_type_arguments();
-    ASSERT(fn_type_args != NULL && closure != NULL);
+    ASSERT(fn_type_args != nullptr && closure != nullptr);
 
     if (dart_function.IsGeneric()) {
       prologue += LoadLocal(fn_type_args);
@@ -527,7 +527,8 @@
 
   // Prepend an entry corresponding to normal entry to the function.
   yield_continuations().InsertAt(
-      0, YieldContinuation(new (Z) DropTempsInstr(0, NULL), kInvalidTryIndex));
+      0,
+      YieldContinuation(new (Z) DropTempsInstr(0, nullptr), kInvalidTryIndex));
   yield_continuations()[0].entry->LinkTo(body.entry);
 
   // Load :await_jump_var into a temporary.
@@ -648,7 +649,7 @@
         ASSERT((function.HasOptionalParameters() &&
                 raw_parameter.owner() == scope) ||
                (!function.HasOptionalParameters() &&
-                raw_parameter.owner() == NULL));
+                raw_parameter.owner() == nullptr));
         ASSERT(!raw_parameter.is_captured());
 
         // Copy the parameter from the stack to the context.
@@ -1017,7 +1018,7 @@
       break;
   }
   UNREACHABLE();
-  return NULL;
+  return nullptr;
 }
 
 void StreamingFlowGraphBuilder::ParseKernelASTFunction() {
@@ -1239,52 +1240,52 @@
   return Fragment();
 }
 
-Fragment StreamingFlowGraphBuilder::BuildStatement() {
+Fragment StreamingFlowGraphBuilder::BuildStatement(TokenPosition* position) {
   intptr_t offset = ReaderOffset();
   Tag tag = ReadTag();  // read tag.
   switch (tag) {
     case kExpressionStatement:
-      return BuildExpressionStatement();
+      return BuildExpressionStatement(position);
     case kBlock:
-      return BuildBlock();
+      return BuildBlock(position);
     case kEmptyStatement:
       return BuildEmptyStatement();
     case kAssertBlock:
-      return BuildAssertBlock();
+      return BuildAssertBlock(position);
     case kAssertStatement:
-      return BuildAssertStatement();
+      return BuildAssertStatement(position);
     case kLabeledStatement:
-      return BuildLabeledStatement();
+      return BuildLabeledStatement(position);
     case kBreakStatement:
-      return BuildBreakStatement();
+      return BuildBreakStatement(position);
     case kWhileStatement:
-      return BuildWhileStatement();
+      return BuildWhileStatement(position);
     case kDoStatement:
-      return BuildDoStatement();
+      return BuildDoStatement(position);
     case kForStatement:
-      return BuildForStatement();
+      return BuildForStatement(position);
     case kForInStatement:
-      return BuildForInStatement(false);
+      return BuildForInStatement(false, position);
     case kAsyncForInStatement:
-      return BuildForInStatement(true);
+      return BuildForInStatement(true, position);
     case kSwitchStatement:
-      return BuildSwitchStatement();
+      return BuildSwitchStatement(position);
     case kContinueSwitchStatement:
-      return BuildContinueSwitchStatement();
+      return BuildContinueSwitchStatement(position);
     case kIfStatement:
-      return BuildIfStatement();
+      return BuildIfStatement(position);
     case kReturnStatement:
-      return BuildReturnStatement();
+      return BuildReturnStatement(position);
     case kTryCatch:
-      return BuildTryCatch();
+      return BuildTryCatch(position);
     case kTryFinally:
-      return BuildTryFinally();
+      return BuildTryFinally(position);
     case kYieldStatement:
-      return BuildYieldStatement();
+      return BuildYieldStatement(position);
     case kVariableDeclaration:
-      return BuildVariableDeclaration();
+      return BuildVariableDeclaration(position);
     case kFunctionDeclaration:
-      return BuildFunctionDeclaration(offset);
+      return BuildFunctionDeclaration(offset, position);
     default:
       ReportUnexpectedTag("statement", tag);
       UNREACHABLE();
@@ -1294,7 +1295,7 @@
 
 void StreamingFlowGraphBuilder::ReportUnexpectedTag(const char* variant,
                                                     Tag tag) {
-  if ((flow_graph_builder_ == NULL) || (parsed_function() == NULL)) {
+  if ((flow_graph_builder_ == nullptr) || (parsed_function() == nullptr)) {
     KernelReaderHelper::ReportUnexpectedTag(variant, tag);
   } else {
     H.ReportError(script_, TokenPosition::kNoSource,
@@ -1974,7 +1975,7 @@
                                                    intptr_t* argument_count,
                                                    intptr_t* positional_count) {
   intptr_t dummy;
-  if (argument_count == NULL) argument_count = &dummy;
+  if (argument_count == nullptr) argument_count = &dummy;
   *argument_count = ReadUInt();  // read arguments count.
 
   // List of types.
@@ -1982,7 +1983,7 @@
 
   {
     AlternativeReadingScope _(&reader_);
-    if (positional_count == NULL) positional_count = &dummy;
+    if (positional_count == nullptr) positional_count = &dummy;
     *positional_count = ReadListLength();  // read length of expression list
   }
   return BuildArgumentsFromActualArguments(argument_names);
@@ -2000,14 +2001,14 @@
 
   // List of named.
   list_length = ReadListLength();  // read list length.
-  if (argument_names != NULL && list_length > 0) {
+  if (argument_names != nullptr && list_length > 0) {
     *argument_names = Array::New(list_length, Heap::kOld);
   }
   for (intptr_t i = 0; i < list_length; ++i) {
     String& name =
         H.DartSymbolObfuscate(ReadStringReference());  // read ith name index.
     instructions += BuildExpression();                 // read ith expression.
-    if (argument_names != NULL) {
+    if (argument_names != nullptr) {
       argument_names->SetAt(i, name);
     }
   }
@@ -2021,7 +2022,7 @@
   // [NoSuchMethodError]s) and only emit [InvalidExpression]s in very special
   // situations (e.g. an invalid annotation).
   TokenPosition pos = ReadPosition();
-  if (position != NULL) *position = pos;
+  if (position != nullptr) *position = pos;
   const String& message = H.DartString(ReadStringReference());
   Tag tag = ReadTag();  // read (first part of) expression.
   if (tag == kSomething) {
@@ -2129,7 +2130,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildVariableSet(TokenPosition* p) {
   TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   intptr_t variable_kernel_position = ReadUInt();  // read kernel position.
   ReadUInt();  // read relative variable index.
@@ -2139,7 +2140,7 @@
 Fragment StreamingFlowGraphBuilder::BuildVariableSet(uint8_t payload,
                                                      TokenPosition* p) {
   TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   intptr_t variable_kernel_position = ReadUInt();  // read kernel position.
   return BuildVariableSetImpl(position, variable_kernel_position);
@@ -2629,7 +2630,7 @@
 Fragment StreamingFlowGraphBuilder::BuildSuperPropertyGet(TokenPosition* p) {
   const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
   const TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   const InferredTypeMetadata result_type =
       inferred_type_metadata_helper_.GetInferredType(offset);
@@ -2705,7 +2706,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildSuperPropertySet(TokenPosition* p) {
   const TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   Class& klass = GetSuperOrDie();
 
@@ -2772,7 +2773,7 @@
   const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
 
   TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   const InferredTypeMetadata result_type =
       inferred_type_metadata_helper_.GetInferredType(offset);
@@ -2836,7 +2837,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildStaticSet(TokenPosition* p) {
   TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   NameIndex target = ReadCanonicalNameReference();  // read target_reference.
   ASSERT(H.IsSetter(target));
@@ -2885,7 +2886,7 @@
   const bool is_invariant = (flags & kInstanceInvocationFlagInvariant) != 0;
 
   const TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   const DirectCallMetadata direct_call =
       direct_call_metadata_helper_.GetDirectTargetForMethodInvocation(offset);
@@ -2908,7 +2909,7 @@
   Fragment instructions;
 
   intptr_t type_args_len = 0;
-  LocalVariable* type_arguments_temp = NULL;
+  LocalVariable* type_arguments_temp = nullptr;
   {
     AlternativeReadingScope alt(&reader_);
     SkipExpression();                         // skip receiver
@@ -2950,8 +2951,8 @@
     ASSERT(type_args_len == 0);
     // "==" or "!=" with null on either side.
     instructions +=
-        BuildArguments(NULL /* named */, NULL /* arg count */,
-                       NULL /* positional arg count */);  // read arguments.
+        BuildArguments(nullptr /* named */, nullptr /* arg count */,
+                       nullptr /* positional arg count */);  // read arguments.
     SkipInterfaceMemberNameReference();  // read interface_target_reference.
     Token::Kind strict_cmp_kind =
         token_kind == Token::kEQ ? Token::kEQ_STRICT : Token::kNE_STRICT;
@@ -2959,11 +2960,11 @@
            StrictCompare(position, strict_cmp_kind, /*number_check = */ true);
   }
 
-  LocalVariable* receiver_temp = NULL;
+  LocalVariable* receiver_temp = nullptr;
   if (direct_call.check_receiver_for_null_) {
     // Duplicate receiver for CheckNull before it is consumed by PushArgument.
     receiver_temp = MakeTemporary();
-    if (type_arguments_temp != NULL) {
+    if (type_arguments_temp != nullptr) {
       // If call has type arguments then push them before pushing the receiver.
       // The stack will contain:
       //
@@ -3049,10 +3050,10 @@
   }
 
   // Drop temporaries preserving result on the top of the stack.
-  ASSERT((receiver_temp != NULL) || (type_arguments_temp == NULL));
-  if (receiver_temp != NULL) {
-    const intptr_t num_temps =
-        (receiver_temp != NULL ? 1 : 0) + (type_arguments_temp != NULL ? 1 : 0);
+  ASSERT((receiver_temp != nullptr) || (type_arguments_temp == nullptr));
+  if (receiver_temp != nullptr) {
+    const intptr_t num_temps = (receiver_temp != nullptr ? 1 : 0) +
+                               (type_arguments_temp != nullptr ? 1 : 0);
     instructions += DropTempsPreserveTop(num_temps);
   }
 
@@ -3259,7 +3260,7 @@
     TokenPosition* p) {
   const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
   const TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   const InferredTypeMetadata result_type =
       inferred_type_metadata_helper_.GetInferredType(offset);
@@ -3383,7 +3384,7 @@
     intptr_t argument_count;
     instructions += BuildArguments(
         &argument_names, &argument_count,
-        /* positional_argument_count = */ NULL);  // read arguments.
+        /* positional_argument_count = */ nullptr);  // read arguments.
     ++argument_count;                             // include receiver
     SkipInterfaceMemberNameReference();           // interfaceTargetReference
     return instructions +
@@ -3397,7 +3398,7 @@
 Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) {
   const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
   TokenPosition position = ReadPosition();     // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   const InferredTypeMetadata result_type =
       inferred_type_metadata_helper_.GetInferredType(offset);
@@ -3425,7 +3426,7 @@
   }
 
   Fragment instructions;
-  LocalVariable* instance_variable = NULL;
+  LocalVariable* instance_variable = nullptr;
 
   const bool special_case_unchecked_cast =
       klass.IsTopLevel() && (klass.library() == Library::InternalLibrary()) &&
@@ -3483,11 +3484,11 @@
 
   Array& argument_names = Array::ZoneHandle(Z);
   instructions +=
-      BuildArguments(&argument_names, NULL /* arg count */,
-                     NULL /* positional arg count */);  // read arguments.
+      BuildArguments(&argument_names, nullptr /* arg count */,
+                     nullptr /* positional arg count */);  // read arguments.
   ASSERT(!special_case ||
          target.AreValidArguments(type_args_len, argument_count, argument_names,
-                                  NULL));
+                                  nullptr));
 
   // Special case identical(x, y) call.
   // TODO(27590) consider moving this into the inliner and force inline it
@@ -3514,7 +3515,7 @@
 Fragment StreamingFlowGraphBuilder::BuildConstructorInvocation(
     TokenPosition* p) {
   TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   NameIndex kernel_name =
       ReadCanonicalNameReference();  // read target_reference.
@@ -3555,18 +3556,18 @@
   intptr_t argument_count;
   instructions += BuildArguments(
       &argument_names, &argument_count,
-      /* positional_argument_count = */ NULL);  // read arguments.
+      /* positional_argument_count = */ nullptr);  // read arguments.
 
   const Function& target = Function::ZoneHandle(
       Z, H.LookupConstructorByKernelConstructor(klass, kernel_name));
   ++argument_count;
   instructions += StaticCall(position, target, argument_count, argument_names,
-                             ICData::kStatic, /* result_type = */ NULL);
+                             ICData::kStatic, /* result_type = */ nullptr);
   return instructions + Drop();
 }
 
 Fragment StreamingFlowGraphBuilder::BuildNot(TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
+  if (position != nullptr) *position = TokenPosition::kNoSource;
 
   TokenPosition operand_position = TokenPosition::kNoSource;
   Fragment instructions =
@@ -3664,7 +3665,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildLogicalExpression(
     TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
+  if (position != nullptr) *position = TokenPosition::kNoSource;
 
   TestFragment exits;
   exits.true_successor_addresses = new TestFragment::SuccessorAddressArray(2);
@@ -3701,7 +3702,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildConditionalExpression(
     TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
+  if (position != nullptr) *position = TokenPosition::kNoSource;
 
   TestFragment condition = TranslateConditionForControl();  // read condition.
 
@@ -3817,7 +3818,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildIsExpression(TokenPosition* p) {
   TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   if (translation_helper_.info().kernel_binary_version() >= 38) {
     // We do not use the library mode for the type test, which is indicated by
@@ -3870,7 +3871,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildAsExpression(TokenPosition* p) {
   TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   const uint8_t flags = ReadFlags();  // read flags.
   const bool is_type_error = (flags & kAsExpressionFlagTypeError) != 0;
@@ -3894,7 +3895,7 @@
 }
 
 Fragment StreamingFlowGraphBuilder::BuildTypeLiteral(TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
+  if (position != nullptr) *position = TokenPosition::kNoSource;
 
   const AbstractType& type = T.BuildType();  // read type.
   Fragment instructions;
@@ -3918,14 +3919,14 @@
 
 Fragment StreamingFlowGraphBuilder::BuildThisExpression(
     TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
+  if (position != nullptr) *position = TokenPosition::kNoSource;
 
   return LoadLocal(parsed_function()->receiver_var());
 }
 
 Fragment StreamingFlowGraphBuilder::BuildRethrow(TokenPosition* p) {
   TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   Fragment instructions = DebugStepCheck(position);
   instructions += LoadLocal(catch_block()->exception_var());
@@ -3937,7 +3938,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildThrow(TokenPosition* p) {
   TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   Fragment instructions;
 
@@ -3954,7 +3955,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildListLiteral(TokenPosition* p) {
   TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   const TypeArguments& type_arguments = T.BuildTypeArguments(1);  // read type.
   intptr_t length = ReadListLength();  // read list length.
@@ -4000,7 +4001,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildMapLiteral(TokenPosition* p) {
   TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+  if (p != nullptr) *p = position;
 
   const TypeArguments& type_arguments =
       T.BuildTypeArguments(2);  // read key_type and value_type.
@@ -4057,8 +4058,8 @@
 Fragment StreamingFlowGraphBuilder::BuildLet(TokenPosition* p) {
   const TokenPosition position = ReadPosition();  // read position.
   if (p != nullptr) *p = position;
-  Fragment instructions = BuildVariableDeclaration();  // read variable.
-  instructions += BuildExpression();                   // read body.
+  Fragment instructions = BuildVariableDeclaration(nullptr);  // read variable.
+  instructions += BuildExpression();                          // read body.
   return instructions;
 }
 
@@ -4082,7 +4083,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildBigIntLiteral(
     TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
+  if (position != nullptr) *position = TokenPosition::kNoSource;
 
   const String& value =
       H.DartString(ReadStringReference());  // read index into string table.
@@ -4097,7 +4098,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildStringLiteral(
     TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
+  if (position != nullptr) *position = TokenPosition::kNoSource;
 
   return Constant(H.DartSymbolPlain(
       ReadStringReference()));  // read index into string table.
@@ -4105,7 +4106,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildIntLiteral(uint8_t payload,
                                                     TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
+  if (position != nullptr) *position = TokenPosition::kNoSource;
 
   int64_t value = static_cast<int32_t>(payload) - SpecializedIntLiteralBias;
   return IntConstant(value);
@@ -4113,7 +4114,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildIntLiteral(bool is_negative,
                                                     TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
+  if (position != nullptr) *position = TokenPosition::kNoSource;
 
   int64_t value = is_negative ? -static_cast<int64_t>(ReadUInt())
                               : ReadUInt();  // read value.
@@ -4122,7 +4123,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildDoubleLiteral(
     TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
+  if (position != nullptr) *position = TokenPosition::kNoSource;
 
   Double& constant = Double::ZoneHandle(
       Z, Double::NewCanonical(ReadDouble()));  // read double.
@@ -4131,20 +4132,20 @@
 
 Fragment StreamingFlowGraphBuilder::BuildBoolLiteral(bool value,
                                                      TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
+  if (position != nullptr) *position = TokenPosition::kNoSource;
 
   return Constant(Bool::Get(value));
 }
 
 Fragment StreamingFlowGraphBuilder::BuildNullLiteral(TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
+  if (position != nullptr) *position = TokenPosition::kNoSource;
 
   return Constant(Instance::ZoneHandle(Z, Instance::null()));
 }
 
 Fragment StreamingFlowGraphBuilder::BuildFutureNullValue(
     TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
+  if (position != nullptr) *position = TokenPosition::kNoSource;
   const Class& future = Class::Handle(Z, IG->object_store()->future_class());
   ASSERT(!future.IsNull());
   const auto& error = future.EnsureIsFinalized(thread());
@@ -4177,7 +4178,7 @@
 
 Fragment StreamingFlowGraphBuilder::BuildPartialTearoffInstantiation(
     TokenPosition* position) {
-  if (position != NULL) *position = TokenPosition::kNoSource;
+  if (position != nullptr) *position = TokenPosition::kNoSource;
 
   // Create a copy of the closure.
 
@@ -4264,20 +4265,24 @@
   return instructions;
 }
 
-Fragment StreamingFlowGraphBuilder::BuildExpressionStatement() {
-  Fragment instructions = BuildExpression();  // read expression.
+Fragment StreamingFlowGraphBuilder::BuildExpressionStatement(
+    TokenPosition* position) {
+  Fragment instructions = BuildExpression(position);  // read expression.
   instructions += Drop();
   return instructions;
 }
 
-Fragment StreamingFlowGraphBuilder::BuildBlock() {
+Fragment StreamingFlowGraphBuilder::BuildBlock(TokenPosition* position) {
   intptr_t offset = ReaderOffset() - 1;  // Include the tag.
 
   Fragment instructions;
 
   instructions += EnterScope(offset);
-  ReadPosition();                           // read file offset.
+  const TokenPosition pos = ReadPosition();  // read file offset.
+  if (position != nullptr) *position = pos;
+
   ReadPosition();                           // read file end offset.
+
   intptr_t list_length = ReadListLength();  // read number of statements.
   for (intptr_t i = 0; i < list_length; ++i) {
     if (instructions.is_open()) {
@@ -4295,7 +4300,7 @@
   return Fragment();
 }
 
-Fragment StreamingFlowGraphBuilder::BuildAssertBlock() {
+Fragment StreamingFlowGraphBuilder::BuildAssertBlock(TokenPosition* position) {
   if (!IG->asserts()) {
     SkipStatementList();
     return Fragment();
@@ -4309,7 +4314,8 @@
   intptr_t list_length = ReadListLength();  // read number of statements.
   for (intptr_t i = 0; i < list_length; ++i) {
     if (instructions.is_open()) {
-      instructions += BuildStatement();  // read ith statement.
+      // read ith statement.
+      instructions += BuildStatement(i == 0 ? position : nullptr);
     } else {
       SkipStatement();  // read ith statement.
     }
@@ -4319,7 +4325,8 @@
   return instructions;
 }
 
-Fragment StreamingFlowGraphBuilder::BuildAssertStatement() {
+Fragment StreamingFlowGraphBuilder::BuildAssertStatement(
+    TokenPosition* position) {
   if (!IG->asserts()) {
     SetOffset(ReaderOffset() - 1);  // Include the tag.
     SkipStatement();                // read this statement.
@@ -4337,7 +4344,7 @@
   //
   // The call to `_AssertionError._evaluateAssertion()` will take care of both
   // and returns a boolean.
-  instructions += BuildExpression();  // read condition.
+  instructions += BuildExpression(position);  // read condition.
 
   const TokenPosition condition_start_offset =
       ReadPosition();  // read condition start offset.
@@ -4382,7 +4389,8 @@
   return Fragment(instructions.entry, then);
 }
 
-Fragment StreamingFlowGraphBuilder::BuildLabeledStatement() {
+Fragment StreamingFlowGraphBuilder::BuildLabeledStatement(
+    TokenPosition* position) {
   // There can be serveral cases:
   //
   //   * the body contains a break
@@ -4395,7 +4403,7 @@
   //    traversed.
 
   BreakableBlock block(flow_graph_builder_);
-  Fragment instructions = BuildStatement();  // read body.
+  Fragment instructions = BuildStatement(position);  // read body.
   if (block.HadJumper()) {
     if (instructions.is_open()) {
       instructions += Goto(block.destination());
@@ -4406,11 +4414,14 @@
   }
 }
 
-Fragment StreamingFlowGraphBuilder::BuildBreakStatement() {
-  TokenPosition position = ReadPosition();  // read position.
+Fragment StreamingFlowGraphBuilder::BuildBreakStatement(
+    TokenPosition* position) {
+  const TokenPosition pos = ReadPosition();  // read position.
+  if (position != nullptr) *position = pos;
+
   intptr_t target_index = ReadUInt();       // read target index.
 
-  TryFinallyBlock* outer_finally = NULL;
+  TryFinallyBlock* outer_finally = nullptr;
   intptr_t target_context_depth = -1;
   JoinEntryInstr* destination = breakable_block()->BreakDestination(
       target_index, &outer_finally, &target_context_depth);
@@ -4418,8 +4429,8 @@
   Fragment instructions;
   // Break statement should pause before manipulation of context, which
   // will possibly cause debugger having incorrect context object.
-  if (NeedsDebugStepCheck(parsed_function()->function(), position)) {
-    instructions += DebugStepCheck(position);
+  if (NeedsDebugStepCheck(parsed_function()->function(), pos)) {
+    instructions += DebugStepCheck(pos);
   }
   instructions +=
       TranslateFinallyFinalizers(outer_finally, target_context_depth);
@@ -4429,10 +4440,13 @@
   return instructions;
 }
 
-Fragment StreamingFlowGraphBuilder::BuildWhileStatement() {
+Fragment StreamingFlowGraphBuilder::BuildWhileStatement(
+    TokenPosition* position) {
   ASSERT(block_expression_depth() == 0);  // no while in block-expr
   loop_depth_inc();
-  const TokenPosition position = ReadPosition();            // read position.
+  const TokenPosition pos = ReadPosition();  // read position.
+  if (position != nullptr) *position = pos;
+
   TestFragment condition = TranslateConditionForControl();  // read condition.
   const Fragment body = BuildStatement();                   // read body
 
@@ -4446,7 +4460,7 @@
 
     Fragment loop(join);
     ASSERT(B->GetStackDepth() == 0);
-    loop += CheckStackOverflow(position);
+    loop += CheckStackOverflow(pos);
     loop.current->LinkTo(condition.entry);
 
     entry = Goto(join).entry;
@@ -4458,11 +4472,13 @@
   return Fragment(entry, condition.CreateFalseSuccessor(flow_graph_builder_));
 }
 
-Fragment StreamingFlowGraphBuilder::BuildDoStatement() {
+Fragment StreamingFlowGraphBuilder::BuildDoStatement(TokenPosition* position) {
   ASSERT(block_expression_depth() == 0);  // no do-while in block-expr
   loop_depth_inc();
-  const TokenPosition position = ReadPosition();  // read position.
-  Fragment body = BuildStatement();               // read body.
+  const TokenPosition pos = ReadPosition();  // read position.
+  if (position != nullptr) *position = pos;
+
+  Fragment body = BuildStatement();  // read body.
 
   if (body.is_closed()) {
     SkipExpression();  // read condition.
@@ -4475,7 +4491,7 @@
   JoinEntryInstr* join = BuildJoinEntry();
   Fragment loop(join);
   ASSERT(B->GetStackDepth() == 0);
-  loop += CheckStackOverflow(position);
+  loop += CheckStackOverflow(pos);
   loop += body;
   loop <<= condition.entry;
 
@@ -4487,10 +4503,11 @@
       condition.CreateFalseSuccessor(flow_graph_builder_));
 }
 
-Fragment StreamingFlowGraphBuilder::BuildForStatement() {
+Fragment StreamingFlowGraphBuilder::BuildForStatement(TokenPosition* position) {
   intptr_t offset = ReaderOffset() - 1;  // Include the tag.
 
-  const TokenPosition position = ReadPosition();  // read position.
+  const TokenPosition pos = ReadPosition();  // read position.
+  if (position != nullptr) *position = pos;
 
   Fragment declarations;
 
@@ -4501,7 +4518,7 @@
 
   intptr_t list_length = ReadListLength();  // read number of variables.
   for (intptr_t i = 0; i < list_length; ++i) {
-    declarations += BuildVariableDeclaration();  // read ith variable.
+    declarations += BuildVariableDeclaration(nullptr);  // read ith variable.
   }
 
   Tag tag = ReadTag();  // Read first part of condition.
@@ -4543,7 +4560,7 @@
     body += Goto(join);
 
     Fragment loop(join);
-    loop += CheckStackOverflow(position);  // may have non-empty stack
+    loop += CheckStackOverflow(pos);  // may have non-empty stack
     if (condition.entry != nullptr) {
       loop <<= condition.entry;
     } else {
@@ -4566,10 +4583,14 @@
   return loop;
 }
 
-Fragment StreamingFlowGraphBuilder::BuildForInStatement(bool async) {
+Fragment StreamingFlowGraphBuilder::BuildForInStatement(
+    bool async,
+    TokenPosition* position) {
   intptr_t offset = ReaderOffset() - 1;  // Include the tag.
 
-  const TokenPosition position = ReadPosition();  // read position.
+  const TokenPosition pos = ReadPosition();  // read position.
+  if (position != nullptr) *position = pos;
+
   TokenPosition body_position = ReadPosition();   // read body position.
   intptr_t variable_kernel_position = ReaderOffset() + data_program_offset_;
   SkipVariableDeclaration();  // read variable.
@@ -4613,7 +4634,7 @@
     body += Goto(join);
 
     Fragment loop(join);
-    loop += CheckStackOverflow(position);  // may have non-empty stack
+    loop += CheckStackOverflow(pos);  // may have non-empty stack
     loop += condition;
   } else {
     instructions += condition;
@@ -4624,8 +4645,11 @@
   return Fragment(instructions.entry, loop_exit);
 }
 
-Fragment StreamingFlowGraphBuilder::BuildSwitchStatement() {
-  ReadPosition();  // read position.
+Fragment StreamingFlowGraphBuilder::BuildSwitchStatement(
+    TokenPosition* position) {
+  const TokenPosition pos = ReadPosition();  // read position.
+  if (position != nullptr) *position = pos;
+
   // We need the number of cases. So start by getting that, then go back.
   intptr_t offset = ReaderOffset();
   SkipExpression();                   // temporarily skip condition
@@ -4663,7 +4687,7 @@
     Fragment& body_fragment = body_fragments[i] =
         BuildStatement();  // read body.
 
-    if (body_fragment.entry == NULL) {
+    if (body_fragment.entry == nullptr) {
       // Make a NOP in order to ensure linking works properly.
       body_fragment = NullConstant();
       body_fragment += Drop();
@@ -4750,7 +4774,7 @@
         current_instructions += body_fragments[i];
       }
     } else {
-      JoinEntryInstr* body_join = NULL;
+      JoinEntryInstr* body_join = nullptr;
       if (block.HadJumper(i)) {
         body_join = block.DestinationDirect(i);
         body_fragments[i] = Fragment(body_join) + body_fragments[i];
@@ -4760,19 +4784,19 @@
         TargetEntryInstr* then;
         TargetEntryInstr* otherwise;
 
-        TokenPosition position = ReadPosition();  // read jth position.
+        const TokenPosition pos = ReadPosition();  // read jth position.
         current_instructions += Constant(
             Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression()));
         current_instructions += LoadLocal(scopes()->switch_variable);
         current_instructions +=
-            InstanceCall(position, Symbols::EqualOperator(), Token::kEQ,
+            InstanceCall(pos, Symbols::EqualOperator(), Token::kEQ,
                          /*argument_count=*/2,
                          /*checked_argument_count=*/2);
         current_instructions += BranchIfTrue(&then, &otherwise, false);
 
         Fragment then_fragment(then);
 
-        if (body_join != NULL) {
+        if (body_join != nullptr) {
           // There are several branches to the body, so we will make a goto to
           // the join block (the real body has already been prepended with a
           // join instruction).
@@ -4816,11 +4840,14 @@
   return Fragment(head_instructions.entry, current_instructions.current);
 }
 
-Fragment StreamingFlowGraphBuilder::BuildContinueSwitchStatement() {
-  TokenPosition position = ReadPosition();  // read position.
+Fragment StreamingFlowGraphBuilder::BuildContinueSwitchStatement(
+    TokenPosition* position) {
+  const TokenPosition pos = ReadPosition();  // read position.
+  if (position != nullptr) *position = pos;
+
   intptr_t target_index = ReadUInt();       // read target index.
 
-  TryFinallyBlock* outer_finally = NULL;
+  TryFinallyBlock* outer_finally = nullptr;
   intptr_t target_context_depth = -1;
   JoinEntryInstr* entry = switch_block()->Destination(
       target_index, &outer_finally, &target_context_depth);
@@ -4829,16 +4856,17 @@
   instructions +=
       TranslateFinallyFinalizers(outer_finally, target_context_depth);
   if (instructions.is_open()) {
-    if (NeedsDebugStepCheck(parsed_function()->function(), position)) {
-      instructions += DebugStepCheck(position);
+    if (NeedsDebugStepCheck(parsed_function()->function(), pos)) {
+      instructions += DebugStepCheck(pos);
     }
     instructions += Goto(entry);
   }
   return instructions;
 }
 
-Fragment StreamingFlowGraphBuilder::BuildIfStatement() {
-  ReadPosition();  // read position.
+Fragment StreamingFlowGraphBuilder::BuildIfStatement(TokenPosition* position) {
+  const TokenPosition pos = ReadPosition();  // read position.
+  if (position != nullptr) *position = pos;
 
   TestFragment condition = TranslateConditionForControl();
 
@@ -4865,11 +4893,14 @@
   }
 }
 
-Fragment StreamingFlowGraphBuilder::BuildReturnStatement() {
-  TokenPosition position = ReadPosition();  // read position.
-  Tag tag = ReadTag();                      // read first part of expression.
+Fragment StreamingFlowGraphBuilder::BuildReturnStatement(
+    TokenPosition* position) {
+  const TokenPosition pos = ReadPosition();  // read position.
+  if (position != nullptr) *position = pos;
 
-  bool inside_try_finally = try_finally_block() != NULL;
+  Tag tag = ReadTag();  // read first part of expression.
+
+  bool inside_try_finally = try_finally_block() != nullptr;
 
   Fragment instructions = tag == kNothing
                               ? NullConstant()
@@ -4881,10 +4912,10 @@
           scopes()->finally_return_variable;
       ASSERT(finally_return_variable != nullptr);
       const Function& function = parsed_function()->function();
-      if (NeedsDebugStepCheck(function, position)) {
-        instructions += DebugStepCheck(position);
+      if (NeedsDebugStepCheck(function, pos)) {
+        instructions += DebugStepCheck(pos);
       }
-      instructions += StoreLocal(position, finally_return_variable);
+      instructions += StoreLocal(pos, finally_return_variable);
       instructions += Drop();
       const intptr_t target_context_depth =
           finally_return_variable->is_captured()
@@ -4901,7 +4932,7 @@
         B->context_depth_ = saved_context_depth;
       }
     } else {
-      instructions += Return(position);
+      instructions += Return(pos);
     }
   } else {
     Pop();
@@ -4910,7 +4941,7 @@
   return instructions;
 }
 
-Fragment StreamingFlowGraphBuilder::BuildTryCatch() {
+Fragment StreamingFlowGraphBuilder::BuildTryCatch(TokenPosition* position) {
   ASSERT(block_expression_depth() == 0);  // no try-catch in block-expr
   InlineBailout("kernel::FlowgraphBuilder::VisitTryCatch");
 
@@ -4922,7 +4953,7 @@
   try_depth_inc();
   {
     TryCatchBlock block(flow_graph_builder_, try_handler_index);
-    try_body += BuildStatement();  // read body.
+    try_body += BuildStatement(position);  // read body.
     try_body += Goto(after_try);
   }
   try_depth_dec();
@@ -4945,7 +4976,7 @@
   // Fill in the body of the catch.
   for (intptr_t i = 0; i < catch_count; ++i) {
     intptr_t catch_offset = ReaderOffset();          // Catch has no tag.
-    TokenPosition position = ReadPosition();         // read position.
+    TokenPosition pos = ReadPosition();              // read position.
     const AbstractType& type_guard = T.BuildType();  // read guard.
     handler_types.SetAt(i, type_guard);
 
@@ -5002,9 +5033,9 @@
 
       catch_body += Constant(type_guard);
 
-      catch_body += InstanceCall(
-          position, Library::PrivateCoreLibName(Symbols::_instanceOf()),
-          Token::kIS, 4);
+      catch_body +=
+          InstanceCall(pos, Library::PrivateCoreLibName(Symbols::_instanceOf()),
+                       Token::kIS, 4);
 
       TargetEntryInstr* catch_entry;
       TargetEntryInstr* next_catch_entry;
@@ -5031,7 +5062,7 @@
   return Fragment(try_body.entry, after_try);
 }
 
-Fragment StreamingFlowGraphBuilder::BuildTryFinally() {
+Fragment StreamingFlowGraphBuilder::BuildTryFinally(TokenPosition* position) {
   ASSERT(block_expression_depth() == 0);  // no try-finally in block-expr
   // Note on streaming:
   // We only stream this TryFinally if we can stream everything inside it,
@@ -5076,7 +5107,7 @@
   {
     TryFinallyBlock tfb(flow_graph_builder_, finalizer_offset);
     TryCatchBlock tcb(flow_graph_builder_, try_handler_index);
-    try_body += BuildStatement();  // read body.
+    try_body += BuildStatement(position);  // read body.
   }
   try_depth_dec();
 
@@ -5115,10 +5146,12 @@
   return Fragment(try_body.entry, after_try);
 }
 
-Fragment StreamingFlowGraphBuilder::BuildYieldStatement() {
-  TokenPosition position = ReadPosition();  // read position.
-  uint8_t flags = ReadByte();               // read flags.
+Fragment StreamingFlowGraphBuilder::BuildYieldStatement(
+    TokenPosition* position) {
+  const TokenPosition pos = ReadPosition();  // read position.
+  if (position != nullptr) *position = pos;
 
+  uint8_t flags = ReadByte();          // read flags.
   ASSERT(flags == kNativeYieldFlags);  // Must have been desugared.
 
   // Setup yield/continue point:
@@ -5145,11 +5178,11 @@
       StoreLocal(TokenPosition::kNoSource, scopes()->yield_context_variable);
   instructions += Drop();
   instructions += BuildExpression();  // read expression.
-  instructions += Return(position, new_yield_pos);
+  instructions += Return(pos, new_yield_pos);
 
   // Note: DropTempsInstr serves as an anchor instruction. It will not
   // be linked into the resulting graph.
-  DropTempsInstr* anchor = new (Z) DropTempsInstr(0, NULL);
+  DropTempsInstr* anchor = new (Z) DropTempsInstr(0, nullptr);
   yield_continuations().Add(YieldContinuation(anchor, CurrentTryIndex()));
 
   Fragment continuation(instructions.entry, anchor);
@@ -5189,7 +5222,7 @@
     rethrow += LoadLocal(exception_var);
     rethrow += LoadLocal(stack_trace_var);
 
-    rethrow += RethrowException(position, kInvalidTryIndex);
+    rethrow += RethrowException(pos, kInvalidTryIndex);
     Drop();
 
     // Set current to the end of the no_error branch.
@@ -5199,7 +5232,8 @@
   return continuation;
 }
 
-Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration() {
+Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration(
+    TokenPosition* position) {
   intptr_t kernel_position_no_tag = ReaderOffset() + data_program_offset_;
   LocalVariable* variable = LookupVariable(kernel_position_no_tag);
 
@@ -5233,6 +5267,7 @@
   const TokenPosition debug_position = helper.equals_position_.IsReal()
                                            ? helper.equals_position_
                                            : helper.position_;
+  if (position != nullptr) *position = helper.position_;
   if (NeedsDebugStepCheck(stack(), debug_position)) {
     instructions = DebugStepCheck(debug_position) + instructions;
   }
@@ -5241,8 +5276,12 @@
   return instructions;
 }
 
-Fragment StreamingFlowGraphBuilder::BuildFunctionDeclaration(intptr_t offset) {
-  TokenPosition position = ReadPosition();
+Fragment StreamingFlowGraphBuilder::BuildFunctionDeclaration(
+    intptr_t offset,
+    TokenPosition* position) {
+  const TokenPosition pos = ReadPosition();
+  if (position != nullptr) *position = pos;
+
   const intptr_t variable_offset = ReaderOffset() + data_program_offset_;
 
   // Read variable declaration.
@@ -5271,10 +5310,10 @@
 
   helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);
 
-  Fragment instructions = DebugStepCheck(position);
-  instructions += BuildFunctionNode(position, helper.name_index_,
+  Fragment instructions = DebugStepCheck(pos);
+  instructions += BuildFunctionNode(pos, helper.name_index_,
                                     has_valid_annotation, has_pragma, offset);
-  instructions += StoreLocal(position, LookupVariable(variable_offset));
+  instructions += StoreLocal(pos, LookupVariable(variable_offset));
   instructions += Drop();
   return instructions;
 }
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 47ed58b..ddfabe2 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -68,8 +68,8 @@
   Fragment BuildInitializers(const Class& parent_class);
   FlowGraph* BuildGraphOfFunction(bool constructor);
 
-  Fragment BuildExpression(TokenPosition* position = NULL);
-  Fragment BuildStatement();
+  Fragment BuildExpression(TokenPosition* position = nullptr);
+  Fragment BuildStatement(TokenPosition* position = nullptr);
 
   // Kernel offset:
   //   start of function expression -> end of function body statement
@@ -178,7 +178,7 @@
                       intptr_t argument_count,
                       const Array& argument_names,
                       ICData::RebindRule rebind_rule,
-                      const InferredTypeMetadata* result_type = NULL,
+                      const InferredTypeMetadata* result_type = nullptr,
                       intptr_t type_args_len = 0,
                       bool use_unchecked_entry = false);
   Fragment InstanceCall(TokenPosition position,
@@ -333,26 +333,26 @@
   Fragment BuildLibraryPrefixAction(TokenPosition* position,
                                     const String& selector);
 
-  Fragment BuildExpressionStatement();
-  Fragment BuildBlock();
+  Fragment BuildExpressionStatement(TokenPosition* position);
+  Fragment BuildBlock(TokenPosition* position);
   Fragment BuildEmptyStatement();
-  Fragment BuildAssertBlock();
-  Fragment BuildAssertStatement();
-  Fragment BuildLabeledStatement();
-  Fragment BuildBreakStatement();
-  Fragment BuildWhileStatement();
-  Fragment BuildDoStatement();
-  Fragment BuildForStatement();
-  Fragment BuildForInStatement(bool async);
-  Fragment BuildSwitchStatement();
-  Fragment BuildContinueSwitchStatement();
-  Fragment BuildIfStatement();
-  Fragment BuildReturnStatement();
-  Fragment BuildTryCatch();
-  Fragment BuildTryFinally();
-  Fragment BuildYieldStatement();
-  Fragment BuildVariableDeclaration();
-  Fragment BuildFunctionDeclaration(intptr_t offset);
+  Fragment BuildAssertBlock(TokenPosition* position);
+  Fragment BuildAssertStatement(TokenPosition* position);
+  Fragment BuildLabeledStatement(TokenPosition* position);
+  Fragment BuildBreakStatement(TokenPosition* position);
+  Fragment BuildWhileStatement(TokenPosition* position);
+  Fragment BuildDoStatement(TokenPosition* position);
+  Fragment BuildForStatement(TokenPosition* position);
+  Fragment BuildForInStatement(bool async, TokenPosition* position);
+  Fragment BuildSwitchStatement(TokenPosition* position);
+  Fragment BuildContinueSwitchStatement(TokenPosition* position);
+  Fragment BuildIfStatement(TokenPosition* position);
+  Fragment BuildReturnStatement(TokenPosition* position);
+  Fragment BuildTryCatch(TokenPosition* position);
+  Fragment BuildTryFinally(TokenPosition* position);
+  Fragment BuildYieldStatement(TokenPosition* position);
+  Fragment BuildVariableDeclaration(TokenPosition* position);
+  Fragment BuildFunctionDeclaration(intptr_t offset, TokenPosition* position);
   Fragment BuildFunctionNode(TokenPosition parent_position,
                              StringIndex name_index,
                              bool has_valid_annotation,
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index a0da87b..18abb34 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -966,20 +966,10 @@
 }
 
 bool GraphIntrinsifier::Build_Integer_mod(FlowGraph* flow_graph) {
-#if defined(TARGET_ARCH_ARM)
-  if (!TargetCPUFeatures::can_divide()) {
-    return false;
-  }
-#endif
   return BuildBinarySmiOp(flow_graph, Token::kMOD);
 }
 
 bool GraphIntrinsifier::Build_Integer_truncDivide(FlowGraph* flow_graph) {
-#if defined(TARGET_ARCH_ARM)
-  if (!TargetCPUFeatures::can_divide()) {
-    return false;
-  }
-#endif
   return BuildBinarySmiOp(flow_graph, Token::kTRUNCDIV);
 }
 
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index bec292f..c4d5c98 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -1072,12 +1072,6 @@
 #undef EMIT_BOX_ALLOCATION
 
 void StubCodeCompiler::GenerateBoxDoubleStub(Assembler* assembler) {
-#if defined(TARGET_ARCH_ARM)
-  if (!TargetCPUFeatures::vfp_supported()) {
-    __ Breakpoint();
-    return;
-  }
-#endif  // defined(TARGET_ARCH_ARM)
   Label call_runtime;
   if (!FLAG_use_slow_path && FLAG_inline_alloc) {
     __ TryAllocate(compiler::DoubleClass(), &call_runtime,
@@ -1100,12 +1094,6 @@
 }
 
 void StubCodeCompiler::GenerateDoubleToIntegerStub(Assembler* assembler) {
-#if defined(TARGET_ARCH_ARM)
-  if (!TargetCPUFeatures::vfp_supported()) {
-    __ Breakpoint();
-    return;
-  }
-#endif  // defined(TARGET_ARCH_ARM)
   __ EnterStubFrame();
   __ StoreUnboxedDouble(DoubleToIntegerStubABI::kInputReg, THR,
                         target::Thread::unboxed_double_runtime_arg_offset());
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index 859643a..e31e943 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -161,13 +161,6 @@
     intptr_t self_code_stub_offset_from_thread,
     bool allow_return,
     std::function<void()> perform_runtime_call) {
-  // If the target CPU does not support VFP the caller should always use the
-  // non-FPU stub.
-  if (save_fpu_registers && !TargetCPUFeatures::vfp_supported()) {
-    __ Breakpoint();
-    return;
-  }
-
   // We want the saved registers to appear like part of the caller's frame, so
   // we push them before calling EnterStubFrame.
   RegisterSet all_registers;
@@ -825,7 +818,6 @@
     }
   }
 
-  if (TargetCPUFeatures::vfp_supported()) {
     ASSERT(kFpuRegisterSize == 4 * target::kWordSize);
     if (kNumberOfDRegisters > 16) {
       __ vstmd(DB_W, SP, D16, kNumberOfDRegisters - 16);
@@ -833,9 +825,6 @@
     } else {
       __ vstmd(DB_W, SP, D0, kNumberOfDRegisters);
     }
-  } else {
-    __ AddImmediate(SP, -kNumberOfFpuRegisters * kFpuRegisterSize);
-  }
 
   __ mov(R0, Operand(SP));  // Pass address of saved registers block.
   bool is_lazy =
diff --git a/runtime/vm/cpu_arm.cc b/runtime/vm/cpu_arm.cc
index 6d300fb..284b62d 100644
--- a/runtime/vm/cpu_arm.cc
+++ b/runtime/vm/cpu_arm.cc
@@ -49,7 +49,6 @@
 
 namespace dart {
 
-DEFINE_FLAG(bool, use_vfp, true, "Use vfp instructions if supported");
 DEFINE_FLAG(bool, use_neon, true, "Use neon instructions if supported");
 DEFINE_FLAG(bool,
             use_integer_division,
@@ -104,7 +103,6 @@
 }
 
 bool HostCPUFeatures::integer_division_supported_ = false;
-bool HostCPUFeatures::vfp_supported_ = false;
 bool HostCPUFeatures::neon_supported_ = false;
 bool HostCPUFeatures::hardfp_supported_ = false;
 const char* HostCPUFeatures::hardware_ = NULL;
@@ -121,7 +119,6 @@
   hardware_ = "";
   // When the VM is targetted to ARMv7, pretend that the CPU is ARMv7 even if
   // the CPU is actually AArch64.
-  vfp_supported_ = FLAG_use_vfp;
   integer_division_supported_ = FLAG_use_integer_division;
   neon_supported_ = FLAG_use_neon;
   hardfp_supported_ = false;
@@ -151,15 +148,6 @@
 #endif
   }
 
-#if defined(DART_RUN_IN_QEMU_ARMv7)
-  vfp_supported_ = true;
-#else
-  // Has floating point unit.
-  vfp_supported_ =
-      (CpuInfo::FieldContains(kCpuInfoFeatures, "vfp") || is_arm64) &&
-      FLAG_use_vfp;
-#endif
-
   // Has integer division.
   // Special cases:
   // - Qualcomm Krait CPUs (QCT APQ8064) in Nexus 4 and 7 incorrectly report
@@ -198,7 +186,7 @@
   }
   neon_supported_ =
       (CpuInfo::FieldContains(kCpuInfoFeatures, "neon") || is_arm64) &&
-      FLAG_use_vfp && FLAG_use_neon;
+      FLAG_use_neon;
 
 // Use the cross-compiler's predefined macros to determine whether we should
 // use the hard or soft float ABI.
@@ -232,8 +220,7 @@
   hardware_ = CpuInfo::GetCpuModel();
 
   integer_division_supported_ = FLAG_use_integer_division;
-  vfp_supported_ = FLAG_use_vfp;
-  neon_supported_ = FLAG_use_vfp && FLAG_use_neon;
+  neon_supported_ = FLAG_use_neon;
   hardfp_supported_ = FLAG_sim_use_hardfp;
 #if defined(DEBUG)
   initialized_ = true;
diff --git a/runtime/vm/cpu_arm.h b/runtime/vm/cpu_arm.h
index 2eaf4aa..0729a02 100644
--- a/runtime/vm/cpu_arm.h
+++ b/runtime/vm/cpu_arm.h
@@ -34,10 +34,6 @@
     DEBUG_ASSERT(initialized_);
     return integer_division_supported_;
   }
-  static bool vfp_supported() {
-    DEBUG_ASSERT(initialized_);
-    return vfp_supported_;
-  }
   static bool neon_supported() {
     DEBUG_ASSERT(initialized_);
     return neon_supported_;
@@ -56,10 +52,6 @@
     DEBUG_ASSERT(initialized_);
     integer_division_supported_ = supported;
   }
-  static void set_vfp_supported(bool supported) {
-    DEBUG_ASSERT(initialized_);
-    vfp_supported_ = supported;
-  }
   static void set_neon_supported(bool supported) {
     DEBUG_ASSERT(initialized_);
     neon_supported_ = supported;
@@ -69,7 +61,6 @@
  private:
   static const char* hardware_;
   static bool integer_division_supported_;
-  static bool vfp_supported_;
   static bool neon_supported_;
   static bool hardfp_supported_;
   static intptr_t store_pc_read_offset_;
@@ -86,10 +77,6 @@
   static bool integer_division_supported() {
     return HostCPUFeatures::integer_division_supported();
   }
-  static bool vfp_supported() { return HostCPUFeatures::vfp_supported(); }
-  static bool can_divide() {
-    return integer_division_supported() || vfp_supported();
-  }
   static bool neon_supported() { return HostCPUFeatures::neon_supported(); }
   static bool hardfp_supported() { return HostCPUFeatures::hardfp_supported(); }
   static const char* hardware() { return HostCPUFeatures::hardware(); }
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index e18e2a3..1379bfa 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -1173,6 +1173,8 @@
       ADD_ISOLATE_GROUP_FLAG(use_field_guards, use_field_guards,
                              FLAG_use_field_guards);
       ADD_ISOLATE_GROUP_FLAG(use_osr, use_osr, FLAG_use_osr);
+      ADD_ISOLATE_GROUP_FLAG(branch_coverage, branch_coverage,
+                             FLAG_branch_coverage);
     }
 
 // Generated code must match the host architecture and ABI.
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 426bb94..02cbfa3 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -8121,6 +8121,64 @@
   EXPECT(Dart_CloseNativePort(port_id2));
 }
 
+static const intptr_t kSendLength = 16;
+
+static void NewNativePort_ExternalTypedData(Dart_Port dest_port_id,
+                                            Dart_CObject* message) {
+  // Gets a send port message.
+  EXPECT_NOTNULL(message);
+  EXPECT_EQ(Dart_CObject_kTypedData, message->type);
+  EXPECT_EQ(Dart_TypedData_kUint8, message->value.as_typed_data.type);
+  EXPECT_EQ(kSendLength, message->value.as_typed_data.length);
+  for (intptr_t i = 0; i < kSendLength; i++) {
+    EXPECT_EQ((0x41 + i), message->value.as_typed_data.values[i]);
+  }
+}
+
+static void FinalizeTypedData(void* isolate_callback_data, void* peer) {
+  delete[] reinterpret_cast<int8_t*>(peer);
+}
+
+TEST_CASE(DartAPI_NativePortPostExternalTypedData) {
+  int8_t* extTypedData = new int8_t[kSendLength];
+  for (int i = 0; i < kSendLength; i++) {
+    extTypedData[i] = 0x41 + i;
+  }
+  const char* kScriptChars =
+      "import 'dart:typed_data';\n"
+      "import 'dart:isolate';\n"
+      "void callPort(SendPort port, Uint8List data) {\n"
+      "  port.send(data);\n"
+      "}\n";
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  Dart_EnterScope();
+
+  Dart_Port port_id =
+      Dart_NewNativePort("Port123", NewNativePort_ExternalTypedData, true);
+
+  Dart_Handle send_port = Dart_NewSendPort(port_id);
+  EXPECT_VALID(send_port);
+
+  Dart_Handle extdata = Dart_NewExternalTypedDataWithFinalizer(
+      Dart_TypedData_kUint8, extTypedData, kSendLength, extTypedData,
+      kSendLength, FinalizeTypedData);
+  EXPECT_VALID(extdata);
+
+  // Test first port.
+  Dart_Handle dart_args[2];
+  dart_args[0] = send_port;
+  dart_args[1] = extdata;
+  Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 2, dart_args);
+  EXPECT_VALID(result);
+  result = Dart_RunLoop();
+  EXPECT_VALID(result);
+
+  Dart_ExitScope();
+
+  // Delete the native ports.
+  EXPECT(Dart_CloseNativePort(port_id));
+}
+
 static void NewNativePort_nativeReceiveNull(Dart_Port dest_port_id,
                                             Dart_CObject* message) {
   EXPECT_NOTNULL(message);
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index edf42f7..8af317a 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -246,6 +246,7 @@
   D(support_rr, bool, false, "Support running within RR.")                     \
   P(verify_entry_points, bool, false,                                          \
     "Throw API error on invalid member access throuh native API. See "         \
-    "entry_point_pragma.md")
+    "entry_point_pragma.md")                                                   \
+  C(branch_coverage, false, false, bool, false, "Enable branch coverage")
 
 #endif  // RUNTIME_VM_FLAG_LIST_H_
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index d79de5c..1048e4e 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -163,7 +163,9 @@
     load_vmservice_library, false)                                             \
   V(NONPRODUCT, use_osr, UseOsr, use_osr, FLAG_use_osr)                        \
   V(NONPRODUCT, snapshot_is_dontneed_safe, SnapshotIsDontNeedSafe,             \
-    snapshot_is_dontneed_safe, false)
+    snapshot_is_dontneed_safe, false)                                          \
+  V(NONPRODUCT, branch_coverage, BranchCoverage, branch_coverage,              \
+    FLAG_branch_coverage)
 
 #define BOOL_ISOLATE_FLAG_LIST_DEFAULT_GETTER(V)                               \
   V(PRODUCT, copy_parent_code, CopyParentCode, copy_parent_code, false)        \
@@ -796,7 +798,8 @@
   V(Obfuscate)                                                                 \
   V(UseFieldGuards)                                                            \
   V(UseOsr)                                                                    \
-  V(SnapshotIsDontNeedSafe)
+  V(SnapshotIsDontNeedSafe)                                                    \
+  V(BranchCoverage)
 
   // Isolate group specific flags.
   enum FlagBits {
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 6b52eae..8dd8013 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -916,25 +916,21 @@
 
 // Accessors for VFP register state.
 DART_FORCE_INLINE void Simulator::set_sregister(SRegister reg, float value) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT((reg >= 0) && (reg < kNumberOfSRegisters));
   sregisters_[reg] = bit_cast<int32_t, float>(value);
 }
 
 DART_FORCE_INLINE float Simulator::get_sregister(SRegister reg) const {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT((reg >= 0) && (reg < kNumberOfSRegisters));
   return bit_cast<float, int32_t>(sregisters_[reg]);
 }
 
 DART_FORCE_INLINE void Simulator::set_dregister(DRegister reg, double value) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT((reg >= 0) && (reg < kNumberOfDRegisters));
   dregisters_[reg] = bit_cast<int64_t, double>(value);
 }
 
 DART_FORCE_INLINE double Simulator::get_dregister(DRegister reg) const {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT((reg >= 0) && (reg < kNumberOfDRegisters));
   return bit_cast<double, int64_t>(dregisters_[reg]);
 }
@@ -958,25 +954,21 @@
 }
 
 void Simulator::set_sregister_bits(SRegister reg, int32_t value) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT((reg >= 0) && (reg < kNumberOfSRegisters));
   sregisters_[reg] = value;
 }
 
 int32_t Simulator::get_sregister_bits(SRegister reg) const {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT((reg >= 0) && (reg < kNumberOfSRegisters));
   return sregisters_[reg];
 }
 
 void Simulator::set_dregister_bits(DRegister reg, int64_t value) {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT((reg >= 0) && (reg < kNumberOfDRegisters));
   dregisters_[reg] = value;
 }
 
 int64_t Simulator::get_dregister_bits(DRegister reg) const {
-  ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT((reg >= 0) && (reg < kNumberOfDRegisters));
   return dregisters_[reg];
 }
@@ -1500,7 +1492,6 @@
         set_register(R3, icount_);
         set_register(IP, icount_);
         set_register(LR, icount_);
-        if (TargetCPUFeatures::vfp_supported()) {
           double zap_dvalue = static_cast<double>(icount_);
           // Do not zap D0, as it may contain a float result.
           for (int i = D1; i <= D7; i++) {
@@ -1513,7 +1504,6 @@
             set_dregister(static_cast<DRegister>(i), zap_dvalue);
           }
 #endif
-        }
 
         // Return.
         set_pc(saved_lr);
@@ -3519,7 +3509,6 @@
 
   // Setup parameters.
   if (fp_args) {
-    ASSERT(TargetCPUFeatures::vfp_supported());
     set_sregister(S0, bit_cast<float, int32_t>(parameter0));
     set_sregister(S1, bit_cast<float, int32_t>(parameter1));
     set_sregister(S2, bit_cast<float, int32_t>(parameter2));
@@ -3569,7 +3558,6 @@
   double d14_val = 0.0;
   double d15_val = 0.0;
 
-  if (TargetCPUFeatures::vfp_supported()) {
     d8_val = get_dregister(D8);
     d9_val = get_dregister(D9);
     d10_val = get_dregister(D10);
@@ -3578,7 +3566,6 @@
     d13_val = get_dregister(D13);
     d14_val = get_dregister(D14);
     d15_val = get_dregister(D15);
-  }
 
   // Setup the callee-saved registers with a known value. To be able to check
   // that they are preserved properly across dart execution.
@@ -3595,7 +3582,6 @@
   set_register(R11, callee_saved_value);
 
   double callee_saved_dvalue = 0.0;
-  if (TargetCPUFeatures::vfp_supported()) {
     callee_saved_dvalue = static_cast<double>(icount_);
     set_dregister(D8, callee_saved_dvalue);
     set_dregister(D9, callee_saved_dvalue);
@@ -3605,7 +3591,6 @@
     set_dregister(D13, callee_saved_dvalue);
     set_dregister(D14, callee_saved_dvalue);
     set_dregister(D15, callee_saved_dvalue);
-  }
 
   // Start the simulation
   Execute();
@@ -3622,7 +3607,6 @@
   ASSERT(callee_saved_value == get_register(R10));
   ASSERT(callee_saved_value == get_register(R11));
 
-  if (TargetCPUFeatures::vfp_supported()) {
     ASSERT(callee_saved_dvalue == get_dregister(D8));
     ASSERT(callee_saved_dvalue == get_dregister(D9));
     ASSERT(callee_saved_dvalue == get_dregister(D10));
@@ -3631,7 +3615,6 @@
     ASSERT(callee_saved_dvalue == get_dregister(D13));
     ASSERT(callee_saved_dvalue == get_dregister(D14));
     ASSERT(callee_saved_dvalue == get_dregister(D15));
-  }
 
   // Restore callee-saved registers with the original value.
   set_register(R4, r4_val);
@@ -3645,7 +3628,6 @@
   set_register(R10, r10_val);
   set_register(R11, r11_val);
 
-  if (TargetCPUFeatures::vfp_supported()) {
     set_dregister(D8, d8_val);
     set_dregister(D9, d9_val);
     set_dregister(D10, d10_val);
@@ -3654,13 +3636,11 @@
     set_dregister(D13, d13_val);
     set_dregister(D14, d14_val);
     set_dregister(D15, d15_val);
-  }
 
   // Restore the SP register and return R1:R0.
   set_register(SP, sp_before_call);
   int64_t return_value;
   if (fp_return) {
-    ASSERT(TargetCPUFeatures::vfp_supported());
     return_value = bit_cast<int64_t, double>(get_dregister(D0));
   } else {
     return_value = Utils::LowHighTo64Bits(get_register(R0), get_register(R1));
diff --git a/tools/VERSION b/tools/VERSION
index 07ad55c..6049f42 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 110
+PRERELEASE 111
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/flutter/analyze_flutter_gallery.sh b/tools/bots/flutter/analyze_flutter_gallery.sh
new file mode 100755
index 0000000..38dd5f7
--- /dev/null
+++ b/tools/bots/flutter/analyze_flutter_gallery.sh
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+# 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.
+
+# Analyze Dart code in the flutter/gallery repo.
+
+set -ex
+
+checkout=$(pwd)
+dart=$checkout/out/ReleaseX64/dart-sdk/bin/dart
+sdk=$checkout/out/ReleaseX64/dart-sdk
+tmpdir=$(mktemp -d)
+cleanup() {
+  rm -rf "$tmpdir"
+}
+trap cleanup EXIT HUP INT QUIT TERM PIPE
+cd "$tmpdir"
+
+# install flutter
+git clone --single-branch -vv https://github.com/flutter/flutter
+export PATH="$PATH":"$tmpdir/flutter/bin"
+flutter --version
+
+git clone --single-branch -vv \
+  https://dart.googlesource.com/external/github.com/flutter/gallery
+
+cd gallery
+
+# analyze
+echo Analyzing...
+
+flutter packages get
+$dart analyze --fatal-infos
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 7a644b3..a2b07417 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -3753,6 +3753,10 @@
         {
           "name": "analyze flutter/plugins",
           "script": "tools/bots/flutter/analyze_flutter_plugins.sh"
+        },
+        {
+          "name": "analyze flutter/gallery",
+          "script": "tools/bots/flutter/analyze_flutter_gallery.sh"
         }
       ]
     },