Version 2.15.0-16.0.dev

Merge commit 'fc4d4144fb0503cc4bebb46cc478ef7a9538fced' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index b41bf1d..e70c308 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -206,7 +206,7 @@
     },
     {
       "name": "dart2js_info",
-      "rootUri": "../third_party/pkg/dart2js_info",
+      "rootUri": "../pkg/dart2js_info",
       "packageUri": "lib/",
       "languageVersion": "2.3"
     },
diff --git a/.packages b/.packages
index 3b46619..b22e6a2 100644
--- a/.packages
+++ b/.packages
@@ -29,7 +29,7 @@
 convert:third_party/pkg/convert/lib
 crypto:third_party/pkg/crypto/lib
 csslib:third_party/pkg/csslib/lib
-dart2js_info:third_party/pkg/dart2js_info/lib
+dart2js_info:pkg/dart2js_info/lib
 dart2js_runtime_metrics:pkg/dart2js_runtime_metrics/lib
 dart2js_tools:pkg/dart2js_tools/lib
 dart2native:pkg/dart2native/lib
diff --git a/DEPS b/DEPS
index 4134666..0656dad 100644
--- a/DEPS
+++ b/DEPS
@@ -90,7 +90,6 @@
   "convert_rev": "e063fdca4bebffecbb5e6aa5525995120982d9ce",
   "crypto_rev": "b5024e4de2b1c474dd558bef593ddbf0bfade152",
   "csslib_rev": "e411d862fd8cc50415c1badf2632e017373b3f47",
-  "dart2js_info_rev" : "e0acfeb5affdf94c53067e68bd836adf589628fd",
 
   # Note: Updates to dart_style have to be coordinated with the infrastructure
   # team so that the internal formatter in `tools/sdks/dart-sdk/bin/dartfmt`
@@ -348,8 +347,6 @@
       Var("dart_git") + "csslib.git" + "@" + Var("csslib_rev"),
   Var("dart_root") + "/third_party/pkg_tested/dart_style":
       Var("dart_git") + "dart_style.git" + "@" + Var("dart_style_rev"),
-  Var("dart_root") + "/third_party/pkg/dart2js_info":
-      Var("dart_git") + "dart2js_info.git" + "@" + Var("dart2js_info_rev"),
   Var("dart_root") + "/third_party/pkg/dartdoc":
       Var("dart_git") + "dartdoc.git" + "@" + Var("dartdoc_rev"),
   Var("dart_root") + "/third_party/pkg/ffi":
diff --git a/pkg/compiler/pubspec.yaml b/pkg/compiler/pubspec.yaml
index ada6b1e..dbdaec6 100644
--- a/pkg/compiler/pubspec.yaml
+++ b/pkg/compiler/pubspec.yaml
@@ -62,6 +62,8 @@
     path: ../kernel
   meta:
     path: ../meta
+  dart2js_info:
+    path: ../dart2js_info
 
   # Packages brought in via DEPS
   args:
@@ -76,8 +78,6 @@
     path: ../../third_party/pkg/convert
   crypto:
     path: ../../third_party/pkg/crypto
-  dart2js_info:
-    path: ../../third_party/pkg/dart2js_info
   fixnum:
     path: ../../third_party/pkg/fixnum
   http_parser:
diff --git a/pkg/compiler/test/analyses/dart2js_allowed.json b/pkg/compiler/test/analyses/dart2js_allowed.json
index 9048e82..242faa0 100644
--- a/pkg/compiler/test/analyses/dart2js_allowed.json
+++ b/pkg/compiler/test/analyses/dart2js_allowed.json
@@ -170,13 +170,13 @@
     "Dynamic invocation of '>='.": 1,
     "Dynamic invocation of 'codeUnitAt'.": 1
   },
-  "third_party/pkg/dart2js_info/lib/json_info_codec.dart": {
+  "pkg/dart2js_info/lib/json_info_codec.dart": {
     "Dynamic invocation of '[]'.": 11,
     "Dynamic invocation of 'forEach'.": 2,
     "Dynamic invocation of 'map'.": 2,
     "Dynamic invocation of 'compareTo'.": 1
   },
-  "third_party/pkg/dart2js_info/lib/binary_serialization.dart": {
+  "pkg/dart2js_info/lib/binary_serialization.dart": {
     "Dynamic invocation of 'cast'.": 1
   },
   "pkg/compiler/lib/src/universe/side_effects.dart": {
@@ -209,11 +209,11 @@
     "Dynamic invocation of '[]'.": 9,
     "Dynamic invocation of 'toStatement'.": 3
   },
-  "third_party/pkg/dart2js_info/lib/src/util.dart": {
+  "pkg/dart2js_info/lib/src/util.dart": {
     "Dynamic access of 'name'.": 1,
     "Dynamic invocation of '-'.": 1
   },
-  "third_party/pkg/dart2js_info/lib/src/binary/sink.dart": {
+  "pkg/dart2js_info/lib/src/binary/sink.dart": {
     "Dynamic access of 'index'.": 1
   },
   "pkg/compiler/lib/src/inferrer/type_graph_nodes.dart": {
diff --git a/pkg/dart2js_info/test/binary_serialization_test.dart b/pkg/dart2js_info/test/binary_serialization_test.dart
index e38f3cb..116003e 100644
--- a/pkg/dart2js_info/test/binary_serialization_test.dart
+++ b/pkg/dart2js_info/test/binary_serialization_test.dart
@@ -10,7 +10,7 @@
 import 'package:test/test.dart';
 
 class ByteSink implements Sink<List<int>> {
-  BytesBuilder builder = new BytesBuilder();
+  BytesBuilder builder = BytesBuilder();
 
   add(List<int> data) => builder.add(data);
   close() {}
@@ -19,19 +19,20 @@
 main() {
   group('json to proto conversion with deferred files', () {
     test('hello_world_deferred', () {
-      var helloWorld = new File(
-          'test/hello_world_deferred/hello_world_deferred.js.info.json');
+      var uri = Platform.script.resolve(
+          'hello_world_deferred/hello_world_deferred.js.info.json');
+      var helloWorld = File.fromUri(uri);
       var contents = helloWorld.readAsStringSync();
       var json = jsonDecode(contents);
-      var info = new AllInfoJsonCodec().decode(json);
+      var info = AllInfoJsonCodec().decode(json);
 
-      var sink = new ByteSink();
+      var sink = ByteSink();
       binary.encode(info, sink);
       var info2 = binary.decode(sink.builder.toBytes());
-      var json2 = new AllInfoJsonCodec().encode(info2);
+      var json2 = AllInfoJsonCodec().encode(info2);
 
-      info.program.toJsonDuration = new Duration(milliseconds: 0);
-      var json1 = new AllInfoJsonCodec().encode(info);
+      info.program.toJsonDuration = Duration(milliseconds: 0);
+      var json1 = AllInfoJsonCodec().encode(info);
       var contents1 = const JsonEncoder.withIndent("  ").convert(json1);
       var contents2 = const JsonEncoder.withIndent("  ").convert(json2);
       expect(contents1 == contents2, isTrue);
diff --git a/pkg/dart2js_info/test/json_to_proto_deferred_test.dart b/pkg/dart2js_info/test/json_to_proto_deferred_test.dart
index 0f1eaf2..70d7681 100644
--- a/pkg/dart2js_info/test/json_to_proto_deferred_test.dart
+++ b/pkg/dart2js_info/test/json_to_proto_deferred_test.dart
@@ -12,11 +12,12 @@
 main() {
   group('json to proto conversion with deferred files', () {
     test('hello_world_deferred', () {
-      final helloWorld = new File(
-          'test/hello_world_deferred/hello_world_deferred.js.info.json');
+      var uri = Platform.script.resolve(
+          'hello_world_deferred/hello_world_deferred.js.info.json');
+      final helloWorld = File.fromUri(uri);
       final json = jsonDecode(helloWorld.readAsStringSync());
-      final decoded = new AllInfoJsonCodec().decode(json);
-      final proto = new AllInfoProtoCodec().encode(decoded);
+      final decoded = AllInfoJsonCodec().decode(json);
+      final proto = AllInfoProtoCodec().encode(decoded);
 
       expect(proto.deferredImports, hasLength(1));
       final libraryImports = proto.deferredImports.first;
diff --git a/pkg/dart2js_info/test/json_to_proto_test.dart b/pkg/dart2js_info/test/json_to_proto_test.dart
index 609532b..735b2d7 100644
--- a/pkg/dart2js_info/test/json_to_proto_test.dart
+++ b/pkg/dart2js_info/test/json_to_proto_test.dart
@@ -13,28 +13,32 @@
 main() {
   group('json to proto conversion', () {
     test('hello_world', () {
-      final helloWorld = new File('test/hello_world/hello_world.js.info.json');
+      var uri = Platform.script.resolve(
+          'hello_world/hello_world.js.info.json');
+      final helloWorld = File.fromUri(uri);
       final json = jsonDecode(helloWorld.readAsStringSync());
-      final decoded = new AllInfoJsonCodec().decode(json);
-      final proto = new AllInfoProtoCodec().encode(decoded);
+      final decoded = AllInfoJsonCodec().decode(json);
+      final proto = AllInfoProtoCodec().encode(decoded);
 
       expect(proto.program.entrypointId, isNotNull);
       expect(proto.program.size, 10324);
       expect(proto.program.compilationMoment.toInt(),
           DateTime.parse("2017-04-17 09:46:41.661617").microsecondsSinceEpoch);
       expect(proto.program.toProtoDuration.toInt(),
-          new Duration(milliseconds: 4).inMicroseconds);
+          Duration(milliseconds: 4).inMicroseconds);
       expect(proto.program.dumpInfoDuration.toInt(),
-          new Duration(milliseconds: 0).inMicroseconds);
+          Duration(milliseconds: 0).inMicroseconds);
       expect(proto.program.noSuchMethodEnabled, isFalse);
       expect(proto.program.minified, isFalse);
     });
 
     test('has proper id format', () {
-      final helloWorld = new File('test/hello_world/hello_world.js.info.json');
+      var uri = Platform.script.resolve(
+          'hello_world/hello_world.js.info.json');
+      final helloWorld = File.fromUri(uri);
       final json = jsonDecode(helloWorld.readAsStringSync());
-      final decoded = new AllInfoJsonCodec().decode(json);
-      final proto = new AllInfoProtoCodec().encode(decoded);
+      final decoded = AllInfoJsonCodec().decode(json);
+      final proto = AllInfoProtoCodec().encode(decoded);
 
       final expectedPrefixes = <InfoKind, String>{};
       for (final kind in InfoKind.values) {
diff --git a/pkg/dart2js_info/test/parse_test.dart b/pkg/dart2js_info/test/parse_test.dart
index 1e6b382..ae71615 100644
--- a/pkg/dart2js_info/test/parse_test.dart
+++ b/pkg/dart2js_info/test/parse_test.dart
@@ -11,9 +11,11 @@
 main() {
   group('parse', () {
     test('hello_world', () {
-      var helloWorld = new File('test/hello_world/hello_world.js.info.json');
+      var uri =
+          Platform.script.resolve('hello_world/hello_world.js.info.json');
+      var helloWorld = File.fromUri(uri);
       var json = jsonDecode(helloWorld.readAsStringSync());
-      var decoded = new AllInfoJsonCodec().decode(json);
+      var decoded = AllInfoJsonCodec().decode(json);
 
       var program = decoded.program;
       expect(program, isNotNull);
diff --git a/pkg/dartdev/test/commands/flag_test.dart b/pkg/dartdev/test/commands/flag_test.dart
index 5d9d0ab..da055db 100644
--- a/pkg/dartdev/test/commands/flag_test.dart
+++ b/pkg/dartdev/test/commands/flag_test.dart
@@ -37,8 +37,8 @@
       if (command.argParser != null) {
         if (command.name != 'help' &&
             command.name != 'format' &&
-            command.name != 'migrate' &&
-            command.name != 'pub') {
+            command.name != 'pub' &&
+            command.name != 'test') {
           expect(command.argParser.usageLineLength,
               stdout.hasTerminal ? stdout.terminalColumns : null);
         } else if (command.name == 'pub') {
@@ -97,6 +97,22 @@
         contains('The following options are only used for VM development'));
   });
 
+  test('print Dart CLI help on usage error', () {
+    p = project();
+    var result = p.runSync(['---help']);
+    expect(result.exitCode, 255);
+    expect(result.stdout, contains(DartdevRunner.dartdevDescription));
+    expect(result.stderr, isEmpty);
+  });
+
+  test('print VM help on usage error when --disable-dart-dev is provided', () {
+    p = project();
+    var result = p.runSync(['---help', '--disable-dart-dev']);
+    expect(result.exitCode, 255);
+    expect(result.stdout, isNot(contains(DartdevRunner.dartdevDescription)));
+    expect(result.stderr, isEmpty);
+  });
+
   test('help', () {
     p = project();
     var result = p.runSync(['help']);
diff --git a/pkg/dds/lib/src/devtools/devtools_client.dart b/pkg/dds/lib/src/devtools/devtools_client.dart
index 8bc3564..e5ec54e 100644
--- a/pkg/dds/lib/src/devtools/devtools_client.dart
+++ b/pkg/dds/lib/src/devtools/devtools_client.dart
@@ -4,12 +4,11 @@
 
 import 'dart:async';
 
+import 'package:devtools_shared/devtools_server.dart';
 import 'package:json_rpc_2/src/server.dart' as json_rpc;
 import 'package:sse/src/server/sse_handler.dart';
 import 'package:stream_channel/stream_channel.dart';
 
-import 'server_api.dart';
-
 class LoggingMiddlewareSink<S> implements StreamSink<S> {
   LoggingMiddlewareSink(this.sink);
 
diff --git a/pkg/dds/lib/src/devtools/devtools_handler.dart b/pkg/dds/lib/src/devtools/devtools_handler.dart
index 87c4fa6..3b55bfb 100644
--- a/pkg/dds/lib/src/devtools/devtools_handler.dart
+++ b/pkg/dds/lib/src/devtools/devtools_handler.dart
@@ -5,13 +5,13 @@
 import 'dart:async';
 
 import 'package:dds/src/constants.dart';
+import 'package:devtools_shared/devtools_server.dart';
 import 'package:shelf/shelf.dart';
 import 'package:shelf_static/shelf_static.dart';
 import 'package:sse/server/sse_handler.dart';
 
 import '../dds_impl.dart';
 import 'devtools_client.dart';
-import 'server_api.dart';
 
 /// Returns a [Handler] which handles serving DevTools and the DevTools server
 /// API under $DDS_URI/devtools/.
diff --git a/pkg/dds/lib/src/devtools/file_system.dart b/pkg/dds/lib/src/devtools/file_system.dart
deleted file mode 100644
index d5d6c6a..0000000
--- a/pkg/dds/lib/src/devtools/file_system.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO(bkonyi): remove once package:devtools_server_api is available
-// See https://github.com/flutter/devtools/issues/2958.
-
-import 'dart:convert';
-import 'dart:io';
-
-import 'package:path/path.dart' as path;
-
-import 'usage.dart';
-
-class LocalFileSystem {
-  static String _userHomeDir() {
-    final String envKey =
-        Platform.operatingSystem == 'windows' ? 'APPDATA' : 'HOME';
-    final String? value = Platform.environment[envKey];
-    return value == null ? '.' : value;
-  }
-
-  /// Returns the path to the DevTools storage directory.
-  static String devToolsDir() {
-    return path.join(_userHomeDir(), '.flutter-devtools');
-  }
-
-  /// Moves the .devtools file to ~/.flutter-devtools/.devtools if the .devtools file
-  /// exists in the user's home directory.
-  static void maybeMoveLegacyDevToolsStore() {
-    final file = File(path.join(_userHomeDir(), DevToolsUsage.storeName));
-    if (file.existsSync()) {
-      ensureDevToolsDirectory();
-      file.copySync(path.join(devToolsDir(), DevToolsUsage.storeName));
-      file.deleteSync();
-    }
-  }
-
-  /// Creates the ~/.flutter-devtools directory if it does not already exist.
-  static void ensureDevToolsDirectory() {
-    Directory('${LocalFileSystem.devToolsDir()}').createSync();
-  }
-
-  /// Returns a DevTools file from the given path.
-  ///
-  /// Only files within ~/.flutter-devtools/ can be accessed.
-  static File? devToolsFileFromPath(String pathFromDevToolsDir) {
-    if (pathFromDevToolsDir.contains('..')) {
-      // The passed in path should not be able to walk up the directory tree
-      // outside of the ~/.flutter-devtools/ directory.
-      return null;
-    }
-    ensureDevToolsDirectory();
-    final file = File(path.join(devToolsDir(), pathFromDevToolsDir));
-    if (!file.existsSync()) {
-      return null;
-    }
-    return file;
-  }
-
-  /// Returns a DevTools file from the given path as encoded json.
-  ///
-  /// Only files within ~/.flutter-devtools/ can be accessed.
-  static String? devToolsFileAsJson(String pathFromDevToolsDir) {
-    final file = devToolsFileFromPath(pathFromDevToolsDir);
-    if (file == null) return null;
-
-    final fileName = path.basename(file.path);
-    if (!fileName.endsWith('.json')) return null;
-
-    final content = file.readAsStringSync();
-    final json = jsonDecode(content);
-    json['lastModifiedTime'] = file.lastModifiedSync().toString();
-    return jsonEncode(json);
-  }
-
-  /// Whether the flutter store file exists.
-  static bool flutterStoreExists() {
-    final flutterStore = File('${_userHomeDir()}/.flutter');
-    return flutterStore.existsSync();
-  }
-}
diff --git a/pkg/dds/lib/src/devtools/server_api.dart b/pkg/dds/lib/src/devtools/server_api.dart
deleted file mode 100644
index 5f21a03..0000000
--- a/pkg/dds/lib/src/devtools/server_api.dart
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO(bkonyi): remove once package:devtools_server_api is available
-// See https://github.com/flutter/devtools/issues/2958.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io';
-
-import 'package:devtools_shared/devtools_shared.dart';
-import 'package:shelf/shelf.dart' as shelf;
-
-import 'file_system.dart';
-import 'usage.dart';
-
-/// The DevTools server API.
-///
-/// This defines endpoints that serve all requests that come in over api/.
-class ServerApi {
-  static const errorNoActiveSurvey = 'ERROR: setActiveSurvey not called.';
-
-  /// Determines whether or not [request] is an API call.
-  static bool canHandle(shelf.Request request) {
-    return request.url.path.startsWith(apiPrefix);
-  }
-
-  /// Handles all requests.
-  ///
-  /// To override an API call, pass in a subclass of [ServerApi].
-  static FutureOr<shelf.Response> handle(
-    shelf.Request request, [
-    ServerApi? api,
-  ]) {
-    api ??= ServerApi();
-    switch (request.url.path) {
-      // ----- Flutter Tool GA store. -----
-      case apiGetFlutterGAEnabled:
-        // Is Analytics collection enabled?
-        return api.getCompleted(
-          request,
-          json.encode(FlutterUsage.doesStoreExist ? _usage!.enabled : null),
-        );
-      case apiGetFlutterGAClientId:
-        // Flutter Tool GA clientId - ONLY get Flutter's clientId if enabled is
-        // true.
-        return (FlutterUsage.doesStoreExist)
-            ? api.getCompleted(
-                request,
-                json.encode(_usage!.enabled ? _usage!.clientId : null),
-              )
-            : api.getCompleted(
-                request,
-                json.encode(null),
-              );
-
-      // ----- DevTools GA store. -----
-
-      case apiResetDevTools:
-        _devToolsUsage.reset();
-        return api.getCompleted(request, json.encode(true));
-      case apiGetDevToolsFirstRun:
-        // Has DevTools been run first time? To bring up welcome screen.
-        return api.getCompleted(
-          request,
-          json.encode(_devToolsUsage.isFirstRun),
-        );
-      case apiGetDevToolsEnabled:
-        // Is DevTools Analytics collection enabled?
-        return api.getCompleted(request, json.encode(_devToolsUsage.enabled));
-      case apiSetDevToolsEnabled:
-        // Enable or disable DevTools analytics collection.
-        final queryParams = request.requestedUri.queryParameters;
-        if (queryParams.containsKey(devToolsEnabledPropertyName)) {
-          _devToolsUsage.enabled =
-              json.decode(queryParams[devToolsEnabledPropertyName]!);
-        }
-        return api.setCompleted(request, json.encode(_devToolsUsage.enabled));
-
-      // ----- DevTools survey store. -----
-
-      case apiSetActiveSurvey:
-        // Assume failure.
-        bool result = false;
-
-        // Set the active survey used to store subsequent apiGetSurveyActionTaken,
-        // apiSetSurveyActionTaken, apiGetSurveyShownCount, and
-        // apiIncrementSurveyShownCount calls.
-        final queryParams = request.requestedUri.queryParameters;
-        if (queryParams.keys.length == 1 &&
-            queryParams.containsKey(activeSurveyName)) {
-          final String theSurveyName = queryParams[activeSurveyName]!;
-
-          // Set the current activeSurvey.
-          _devToolsUsage.activeSurvey = theSurveyName;
-          result = true;
-        }
-
-        return api.getCompleted(request, json.encode(result));
-      case apiGetSurveyActionTaken:
-        // Request setActiveSurvey has not been requested.
-        if (_devToolsUsage.activeSurvey == null) {
-          return api.badRequest('$errorNoActiveSurvey '
-              '- $apiGetSurveyActionTaken');
-        }
-        // SurveyActionTaken has the survey been acted upon (taken or dismissed)
-        return api.getCompleted(
-          request,
-          json.encode(_devToolsUsage.surveyActionTaken),
-        );
-      // TODO(terry): remove the query param logic for this request.
-      // setSurveyActionTaken should only be called with the value of true, so
-      // we can remove the extra complexity.
-      case apiSetSurveyActionTaken:
-        // Request setActiveSurvey has not been requested.
-        if (_devToolsUsage.activeSurvey == null) {
-          return api.badRequest('$errorNoActiveSurvey '
-              '- $apiSetSurveyActionTaken');
-        }
-        // Set the SurveyActionTaken.
-        // Has the survey been taken or dismissed..
-        final queryParams = request.requestedUri.queryParameters;
-        if (queryParams.containsKey(surveyActionTakenPropertyName)) {
-          _devToolsUsage.surveyActionTaken =
-              json.decode(queryParams[surveyActionTakenPropertyName]!);
-        }
-        return api.setCompleted(
-          request,
-          json.encode(_devToolsUsage.surveyActionTaken),
-        );
-      case apiGetSurveyShownCount:
-        // Request setActiveSurvey has not been requested.
-        if (_devToolsUsage.activeSurvey == null) {
-          return api.badRequest('$errorNoActiveSurvey '
-              '- $apiGetSurveyShownCount');
-        }
-        // SurveyShownCount how many times have we asked to take survey.
-        return api.getCompleted(
-          request,
-          json.encode(_devToolsUsage.surveyShownCount),
-        );
-      case apiIncrementSurveyShownCount:
-        // Request setActiveSurvey has not been requested.
-        if (_devToolsUsage.activeSurvey == null) {
-          return api.badRequest('$errorNoActiveSurvey '
-              '- $apiIncrementSurveyShownCount');
-        }
-        // Increment the SurveyShownCount, we've asked about the survey.
-        _devToolsUsage.incrementSurveyShownCount();
-        return api.getCompleted(
-          request,
-          json.encode(_devToolsUsage.surveyShownCount),
-        );
-      case apiGetBaseAppSizeFile:
-        final queryParams = request.requestedUri.queryParameters;
-        if (queryParams.containsKey(baseAppSizeFilePropertyName)) {
-          final filePath = queryParams[baseAppSizeFilePropertyName]!;
-          final fileJson = LocalFileSystem.devToolsFileAsJson(filePath);
-          if (fileJson == null) {
-            return api.badRequest('No JSON file available at $filePath.');
-          }
-          return api.getCompleted(request, fileJson);
-        }
-        return api.badRequest('Request for base app size file does not '
-            'contain a query parameter with the expected key: '
-            '$baseAppSizeFilePropertyName');
-      case apiGetTestAppSizeFile:
-        final queryParams = request.requestedUri.queryParameters;
-        if (queryParams.containsKey(testAppSizeFilePropertyName)) {
-          final filePath = queryParams[testAppSizeFilePropertyName]!;
-          final fileJson = LocalFileSystem.devToolsFileAsJson(filePath);
-          if (fileJson == null) {
-            return api.badRequest('No JSON file available at $filePath.');
-          }
-          return api.getCompleted(request, fileJson);
-        }
-        return api.badRequest('Request for test app size file does not '
-            'contain a query parameter with the expected key: '
-            '$testAppSizeFilePropertyName');
-      default:
-        return api.notImplemented(request);
-    }
-  }
-
-  // Accessing Flutter usage file e.g., ~/.flutter.
-  // NOTE: Only access the file if it exists otherwise Flutter Tool hasn't yet
-  //       been run.
-  static final FlutterUsage? _usage =
-      FlutterUsage.doesStoreExist ? FlutterUsage() : null;
-
-  // Accessing DevTools usage file e.g., ~/.devtools
-  static final DevToolsUsage _devToolsUsage = DevToolsUsage();
-
-  static DevToolsUsage get devToolsPreferences => _devToolsUsage;
-
-  /// Logs a page view in the DevTools server.
-  ///
-  /// In the open-source version of DevTools, Google Analytics handles this
-  /// without any need to involve the server.
-  FutureOr<shelf.Response> logScreenView(shelf.Request request) =>
-      notImplemented(request);
-
-  /// Return the value of the property.
-  FutureOr<shelf.Response> getCompleted(shelf.Request request, String value) =>
-      shelf.Response.ok('$value');
-
-  /// Return the value of the property after the property value has been set.
-  FutureOr<shelf.Response> setCompleted(shelf.Request request, String value) =>
-      shelf.Response.ok('$value');
-
-  /// A [shelf.Response] for API calls that encountered a request problem e.g.,
-  /// setActiveSurvey not called.
-  ///
-  /// This is a 400 Bad Request response.
-  FutureOr<shelf.Response> badRequest([String? logError]) {
-    if (logError != null) print(logError);
-    return shelf.Response(HttpStatus.badRequest);
-  }
-
-  /// A [shelf.Response] for API calls that have not been implemented in this
-  /// server.
-  ///
-  /// This is a no-op 204 No Content response because returning 404 Not Found
-  /// creates unnecessary noise in the console.
-  FutureOr<shelf.Response> notImplemented(shelf.Request request) =>
-      shelf.Response(HttpStatus.noContent);
-}
diff --git a/pkg/dds/lib/src/devtools/usage.dart b/pkg/dds/lib/src/devtools/usage.dart
deleted file mode 100644
index 8e61b90..0000000
--- a/pkg/dds/lib/src/devtools/usage.dart
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO(bkonyi): remove once package:devtools_server_api is available
-// See https://github.com/flutter/devtools/issues/2958.
-
-import 'dart:convert';
-import 'dart:io';
-
-import 'package:path/path.dart' as path;
-import 'package:usage/usage_io.dart';
-
-import 'file_system.dart';
-
-/// Access the file '~/.flutter'.
-class FlutterUsage {
-  /// Create a new Usage instance; [versionOverride] and [configDirOverride] are
-  /// used for testing.
-  FlutterUsage({
-    String settingsName = 'flutter',
-    String? versionOverride,
-    String? configDirOverride,
-  }) {
-    _analytics = AnalyticsIO('', settingsName, '');
-  }
-
-  late Analytics _analytics;
-
-  /// Does the .flutter store exist?
-  static bool get doesStoreExist {
-    return LocalFileSystem.flutterStoreExists();
-  }
-
-  bool get isFirstRun => _analytics.firstRun;
-
-  bool get enabled => _analytics.enabled;
-
-  set enabled(bool value) => _analytics.enabled = value;
-
-  String get clientId => _analytics.clientId;
-}
-
-// Access the DevTools on disk store (~/.devtools/.devtools).
-class DevToolsUsage {
-  /// Create a new Usage instance; [versionOverride] and [configDirOverride] are
-  /// used for testing.
-  DevToolsUsage({
-    String? versionOverride,
-    String? configDirOverride,
-  }) {
-    LocalFileSystem.maybeMoveLegacyDevToolsStore();
-    properties = IOPersistentProperties(
-      storeName,
-      documentDirPath: LocalFileSystem.devToolsDir(),
-    );
-  }
-
-  static const storeName = '.devtools';
-
-  /// The activeSurvey is the property name of a top-level property
-  /// existing or created in the file ~/.devtools
-  /// If the property doesn't exist it is created with default survey values:
-  ///
-  ///   properties[activeSurvey]['surveyActionTaken'] = false;
-  ///   properties[activeSurvey]['surveyShownCount'] = 0;
-  ///
-  /// It is a requirement that the API apiSetActiveSurvey must be called before
-  /// calling any survey method on DevToolsUsage (addSurvey, rewriteActiveSurvey,
-  /// surveyShownCount, incrementSurveyShownCount, or surveyActionTaken).
-  String? _activeSurvey;
-
-  late IOPersistentProperties properties;
-
-  static const _surveyActionTaken = 'surveyActionTaken';
-  static const _surveyShownCount = 'surveyShownCount';
-
-  void reset() {
-    properties.remove('firstRun');
-    properties['enabled'] = false;
-  }
-
-  bool get isFirstRun {
-    properties['firstRun'] = properties['firstRun'] == null;
-    return properties['firstRun'];
-  }
-
-  bool get enabled {
-    if (properties['enabled'] == null) {
-      properties['enabled'] = false;
-    }
-
-    return properties['enabled'];
-  }
-
-  set enabled(bool? value) {
-    properties['enabled'] = value;
-    return properties['enabled'];
-  }
-
-  bool surveyNameExists(String? surveyName) => properties[surveyName] != null;
-
-  void _addSurvey(String? surveyName) {
-    assert(activeSurvey == surveyName);
-    rewriteActiveSurvey(false, 0);
-  }
-
-  String? get activeSurvey => _activeSurvey;
-
-  set activeSurvey(String? surveyName) {
-    _activeSurvey = surveyName;
-
-    if (!surveyNameExists(activeSurvey)) {
-      // Create the survey if property is non-existent in ~/.devtools
-      _addSurvey(activeSurvey);
-    }
-  }
-
-  /// Need to rewrite the entire survey structure for property to be persisted.
-  void rewriteActiveSurvey(bool? actionTaken, int? shownCount) {
-    properties[activeSurvey] = {
-      _surveyActionTaken: actionTaken,
-      _surveyShownCount: shownCount,
-    };
-  }
-
-  int? get surveyShownCount {
-    final prop = properties[activeSurvey];
-    if (prop[_surveyShownCount] == null) {
-      rewriteActiveSurvey(prop[_surveyActionTaken], 0);
-    }
-    return properties[activeSurvey][_surveyShownCount];
-  }
-
-  void incrementSurveyShownCount() {
-    surveyShownCount; // Ensure surveyShownCount has been initialized.
-    final prop = properties[activeSurvey];
-    rewriteActiveSurvey(prop[_surveyActionTaken], prop[_surveyShownCount] + 1);
-  }
-
-  bool get surveyActionTaken {
-    return properties[activeSurvey][_surveyActionTaken] == true;
-  }
-
-  set surveyActionTaken(bool? value) {
-    final prop = properties[activeSurvey];
-    rewriteActiveSurvey(value, prop[_surveyShownCount]);
-  }
-}
-
-abstract class PersistentProperties {
-  PersistentProperties(this.name);
-
-  final String name;
-
-  dynamic operator [](String key);
-
-  void operator []=(String key, dynamic value);
-
-  /// Re-read settings from the backing store.
-  ///
-  /// May be a no-op on some platforms.
-  void syncSettings();
-}
-
-const JsonEncoder _jsonEncoder = JsonEncoder.withIndent('  ');
-
-class IOPersistentProperties extends PersistentProperties {
-  IOPersistentProperties(
-    String name, {
-    String? documentDirPath,
-  }) : super(name) {
-    final String fileName = name.replaceAll(' ', '_');
-    documentDirPath ??= LocalFileSystem.devToolsDir();
-    _file = File(path.join(documentDirPath, fileName));
-    if (!_file.existsSync()) {
-      _file.createSync(recursive: true);
-    }
-    syncSettings();
-  }
-
-  IOPersistentProperties.fromFile(File file) : super(path.basename(file.path)) {
-    _file = file;
-    if (!_file.existsSync()) {
-      _file.createSync(recursive: true);
-    }
-    syncSettings();
-  }
-
-  late File _file;
-
-  Map? _map;
-
-  @override
-  dynamic operator [](String? key) => _map![key];
-
-  @override
-  void operator []=(String? key, dynamic value) {
-    if (value == null && !_map!.containsKey(key)) return;
-    if (_map![key] == value) return;
-
-    if (value == null) {
-      _map!.remove(key);
-    } else {
-      _map![key] = value;
-    }
-
-    try {
-      _file.writeAsStringSync(_jsonEncoder.convert(_map) + '\n');
-    } catch (_) {}
-  }
-
-  @override
-  void syncSettings() {
-    try {
-      String contents = _file.readAsStringSync();
-      if (contents.isEmpty) contents = '{}';
-      _map = jsonDecode(contents);
-    } catch (_) {
-      _map = {};
-    }
-  }
-
-  void remove(String propertyName) {
-    _map!.remove(propertyName);
-  }
-}
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index 9bdb587..d9b8b92 100644
--- a/pkg/dds/pubspec.yaml
+++ b/pkg/dds/pubspec.yaml
@@ -25,7 +25,6 @@
   shelf_web_socket: ^1.0.0
   sse: ^4.0.0
   stream_channel: ^2.0.0
-  usage: ^4.0.0
   vm_service: ^7.0.0
   web_socket_channel: ^2.0.0
 
diff --git a/pkg/nnbd_migration/lib/src/edge_origin.dart b/pkg/nnbd_migration/lib/src/edge_origin.dart
index ea9e4b1..91bb299 100644
--- a/pkg/nnbd_migration/lib/src/edge_origin.dart
+++ b/pkg/nnbd_migration/lib/src/edge_origin.dart
@@ -71,7 +71,7 @@
 
   @override
   String get description =>
-      "annotated with an Angular annotation indicating nullability";
+      'annotated with an Angular annotation indicating nullability';
 
   @override
   EdgeOriginKind get kind => EdgeOriginKind.angularAnnotation;
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 8386f5a..a196360 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -134,6 +134,7 @@
 dds/test/dap/integration/*: Slow, Pass
 
 [ $runtime != vm ]
+dart2js_info/test/*: SkipByDesign # Only meant to run on vm
 dds/test/*: SkipByDesign # Only meant to run on vm
 dev_compiler/test/options/*: SkipByDesign
 front_end/test/hot_reload_e2e_test: Skip
diff --git a/runtime/bin/dartdev_isolate.cc b/runtime/bin/dartdev_isolate.cc
index 468ef64..62701b7 100644
--- a/runtime/bin/dartdev_isolate.cc
+++ b/runtime/bin/dartdev_isolate.cc
@@ -36,6 +36,7 @@
 DartDevIsolate::DartDevRunner DartDevIsolate::runner_ =
     DartDevIsolate::DartDevRunner();
 bool DartDevIsolate::should_run_dart_dev_ = false;
+bool DartDevIsolate::print_usage_error_ = false;
 Monitor* DartDevIsolate::DartDevRunner::monitor_ = new Monitor();
 DartDevIsolate::DartDev_Result DartDevIsolate::DartDevRunner::result_ =
     DartDevIsolate::DartDev_Result_Unknown;
@@ -98,6 +99,13 @@
   package_config_override_ = packages_file;
   script_ = script;
 
+  // We've encountered an error during preliminary argument parsing so we'll
+  // output the standard help message and exit with an error code.
+  if (print_usage_error_) {
+    dart_options_->Reset();
+    dart_options_->AddArgument("--help");
+  }
+
   MonitorLocker locker(monitor_);
   int result = Thread::Start("DartDev Runner", RunCallback,
                              reinterpret_cast<uword>(this));
@@ -170,7 +178,9 @@
 
       // If we're given a non-zero exit code, DartDev is signaling for us to
       // shutdown.
-      Process::SetGlobalExitCode(dartdev_exit_code);
+      int32_t exit_code =
+          print_usage_error_ ? kErrorExitCode : dartdev_exit_code;
+      Process::SetGlobalExitCode(exit_code);
 
       // If DartDev hasn't signaled for us to do anything else, we can assume
       // there's nothing else for the VM to run and that we can exit.
diff --git a/runtime/bin/dartdev_isolate.h b/runtime/bin/dartdev_isolate.h
index a25664c..a6382f6 100644
--- a/runtime/bin/dartdev_isolate.h
+++ b/runtime/bin/dartdev_isolate.h
@@ -39,6 +39,11 @@
     should_run_dart_dev_ = enable;
   }
 
+  static void PrintUsageErrorOnRun() {
+    set_should_run_dart_dev(true);
+    print_usage_error_ = true;
+  }
+
   static bool should_run_dart_dev() { return should_run_dart_dev_; }
 
   // Attempts to find the path of the DartDev kernel file.
@@ -95,6 +100,7 @@
 
   static DartDevRunner runner_;
   static bool should_run_dart_dev_;
+  static bool print_usage_error_;
 
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(DartDevIsolate);
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index a288a79..234fa62 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -1157,6 +1157,8 @@
         }
         Platform::Exit(0);
       } else {
+        // This usage error case will only be invoked when
+        // Options::disable_dart_dev() is false.
         Options::PrintUsage();
         Platform::Exit(kErrorExitCode);
       }
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index a3fb4e1..44386ec 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -526,24 +526,40 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
   }
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  else if (!Options::disable_dart_dev() &&  // NOLINT
-           ((Options::help_option() && !Options::verbose_option()) ||
-            (argc == 1))) {
-    DartDevIsolate::set_should_run_dart_dev(true);
-    // Let DartDev handle the default help message.
-    dart_options->AddArgument("help");
-    return true;
-  } else if (!Options::disable_dart_dev() &&
-             (enable_dartdev_analytics || disable_dartdev_analytics)) {
-    // The analytics flags are a special case as we don't have a target script
-    // or DartDev command but we still want to launch DartDev.
-    DartDevIsolate::set_should_run_dart_dev(true);
-    dart_options->AddArgument(enable_dartdev_analytics ? "--enable-analytics"
-                                                       : "--disable-analytics");
-    return true;
+  else if (!Options::disable_dart_dev()) {  // NOLINT
+    // Handles following invocation arguments:
+    //   - dart help
+    //   - dart --help
+    //   - dart
+    if (((Options::help_option() && !Options::verbose_option()) ||
+         (argc == 1))) {
+      DartDevIsolate::set_should_run_dart_dev(true);
+      // Let DartDev handle the default help message.
+      dart_options->AddArgument("help");
+      return true;
+    }
+    // Handles cases where only analytics flags are provided. We need to start
+    // the DartDev isolate to set this state.
+    else if (enable_dartdev_analytics || disable_dartdev_analytics) {  // NOLINT
+      // The analytics flags are a special case as we don't have a target script
+      // or DartDev command but we still want to launch DartDev.
+      DartDevIsolate::set_should_run_dart_dev(true);
+      dart_options->AddArgument(enable_dartdev_analytics
+                                    ? "--enable-analytics"
+                                    : "--disable-analytics");
+      return true;
+    }
+    // Let the VM handle '--version' and '--help --disable-dart-dev'.
+    // Otherwise, we'll launch the DartDev isolate to print its help message
+    // and set an error exit code.
+    else if (!Options::help_option() && !Options::version_option()) {  // NOLINT
+      DartDevIsolate::PrintUsageErrorOnRun();
+      return true;
+    }
+    return false;
   }
-
-#endif    // !defined(DART_PRECOMPILED_RUNTIME)
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  // Handle argument parsing errors.
   else {  // NOLINT
     return false;
   }
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index 9513513..ccd8144 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -109,7 +109,8 @@
   // vm/cc tests to randomly time out due to inability to shut service-isolate
   // down.
   // Issue(https://dartbug.com/37741):
-  if (strcmp(run_filter, "DartAPI_InvokeVMServiceMethod") != 0) {
+  if ((strcmp(run_filter, "DartAPI_InvokeVMServiceMethod") != 0) &&
+      (strcmp(run_filter, "DartAPI_InvokeVMServiceMethod_Loop") != 0)) {
     return nullptr;
   }
 
diff --git a/runtime/tests/vm/dart/regress_46798_test.dart b/runtime/tests/vm/dart/regress_46798_test.dart
new file mode 100644
index 0000000..1e82ffc
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_46798_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/46798.
+// Verifies that compiler can handle LoadIndexed from AllocateObject.
+
+// VMOptions=--deterministic --optimization_counter_threshold=100
+
+import 'package:expect/expect.dart';
+
+bool foo(Object other) => other is String && other.codeUnitAt(0) == 5;
+
+int x = 0;
+
+void bar(bool cond) {
+  if (cond || foo(MapEntry<int, int>(1, 1))) {
+    ++x;
+  }
+}
+
+void main() {
+  for (int i = 0; i < 1000; ++i) foo('abc');
+  for (int i = 0; i < 1000; ++i) bar(false);
+  Expect.equals(0, x);
+}
diff --git a/runtime/tests/vm/dart_2/regress_46798_test.dart b/runtime/tests/vm/dart_2/regress_46798_test.dart
new file mode 100644
index 0000000..1c226d8
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_46798_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.9
+
+// Regression test for https://github.com/dart-lang/sdk/issues/46798.
+// Verifies that compiler can handle LoadIndexed from AllocateObject.
+
+// VMOptions=--deterministic --optimization_counter_threshold=100
+
+import 'package:expect/expect.dart';
+
+bool foo(Object other) => other is String && other.codeUnitAt(0) == 5;
+
+int x = 0;
+
+void bar(bool cond) {
+  if (cond || foo(MapEntry<int, int>(1, 1))) {
+    ++x;
+  }
+}
+
+void main() {
+  for (int i = 0; i < 1000; ++i) foo('abc');
+  for (int i = 0; i < 1000; ++i) bar(false);
+  Expect.equals(0, x);
+}
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index eeb6d41..ac06355 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -244,7 +244,7 @@
 
 // Class Id predicates.
 
-bool IsInternalOnlyId(intptr_t index);
+bool IsInternalOnlyClassId(intptr_t index);
 bool IsErrorClassId(intptr_t index);
 bool IsNumberClassId(intptr_t index);
 bool IsIntegerClassId(intptr_t index);
@@ -272,18 +272,15 @@
 COMPILE_ASSERT(kFirstInternalOnlyCid == kObjectCid + 1);
 COMPILE_ASSERT(kInstanceCid == kLastInternalOnlyCid + 1);
 
-// Checks that the cids in CLASS_LIST_INTERNAL_ONLY come after kObjectCid.
-// Use with COMPILE_ASSERT where code assumes that Object immediately precedes
-// the other internal-only cids, so it can be adjusted if this changes.
-constexpr bool ObjectComesBeforeOtherInternalOnlyClasses() {
-  return kFirstInternalOnlyCid == kObjectCid + 1;
-}
-
 // Returns true for any class id that either does not correspond to a real
 // class, like kIllegalCid or kForwardingCorpse, or that is internal to the VM
 // and should not be exposed directly to user code.
-inline bool IsInternalOnlyId(intptr_t index) {
-  COMPILE_ASSERT(ObjectComesBeforeOtherInternalOnlyClasses());
+inline bool IsInternalOnlyClassId(intptr_t index) {
+  // Fix the condition below if these become non-contiguous.
+  COMPILE_ASSERT(kIllegalCid + 1 == kFreeListElement &&
+                 kIllegalCid + 2 == kForwardingCorpse &&
+                 kIllegalCid + 3 == kObjectCid &&
+                 kIllegalCid + 4 == kFirstInternalOnlyCid);
   return index <= kLastInternalOnlyCid;
 }
 
@@ -293,8 +290,9 @@
                  kLanguageErrorCid == kErrorCid + 2 &&
                  kUnhandledExceptionCid == kErrorCid + 3 &&
                  kUnwindErrorCid == kErrorCid + 4 &&
+                 // Change if needed for detecting a new error added at the end.
                  kLastInternalOnlyCid == kUnwindErrorCid);
-  return (index >= kErrorCid && index <= kLastInternalOnlyCid);
+  return (index >= kErrorCid && index <= kUnwindErrorCid);
 }
 
 inline bool IsNumberClassId(intptr_t index) {
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index d1f3df1..a1c58c0 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -39,7 +39,7 @@
         calloc(capacity_, sizeof(RelaxedAtomic<intptr_t>)));
     // The following cids don't have a corresponding class object in Dart code.
     // We therefore need to initialize them eagerly.
-    COMPILE_ASSERT(ObjectComesBeforeOtherInternalOnlyClasses());
+    COMPILE_ASSERT(kFirstInternalOnlyCid == kObjectCid + 1);
     for (intptr_t i = kObjectCid; i <= kLastInternalOnlyCid; i++) {
       table[i] = vm_shared_class_table->SizeAt(i);
     }
@@ -106,7 +106,7 @@
         static_cast<ClassPtr*>(calloc(capacity_, sizeof(ClassPtr)));
     // The following cids don't have a corresponding class object in Dart code.
     // We therefore need to initialize them eagerly.
-    COMPILE_ASSERT(ObjectComesBeforeOtherInternalOnlyClasses());
+    COMPILE_ASSERT(kFirstInternalOnlyCid == kObjectCid + 1);
     for (intptr_t i = kObjectCid; i <= kLastInternalOnlyCid; i++) {
       table[i] = vm_class_table->At(i);
     }
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index ad6fa8a..d85727d 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -2074,7 +2074,11 @@
               slot = &store->slot();
             } else if (use->instruction()->IsLoadIndexed() ||
                        use->instruction()->IsStoreIndexed()) {
-              ASSERT(alloc->IsArrayAllocation());
+              if (!alloc->IsArrayAllocation()) {
+                // Non-array allocations can be accessed with LoadIndexed
+                // and StoreIndex in the unreachable code.
+                continue;
+              }
               if (alloc->IsAllocateTypedData()) {
                 // Typed data payload elements are unboxed and initialized to
                 // zero, so don't forward a tagged null value.
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index f6650b2..42a9839 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -821,7 +821,7 @@
 
     // VM-internal objects don't have a compile-type. Return dynamic-type
     // in this case.
-    if (IsInternalOnlyId(cid_) || cid_ == kTypeArgumentsCid) {
+    if (IsInternalOnlyClassId(cid_) || cid_ == kTypeArgumentsCid) {
       type_ = &Object::dynamic_type();
       return type_;
     }
diff --git a/runtime/vm/compiler/cha.cc b/runtime/vm/compiler/cha.cc
index 2668918..06888b6 100644
--- a/runtime/vm/compiler/cha.cc
+++ b/runtime/vm/compiler/cha.cc
@@ -32,7 +32,7 @@
 
 bool CHA::HasSubclasses(const Class& cls) {
   ASSERT(!cls.IsNull());
-  ASSERT(!IsInternalOnlyId(cls.id()));
+  ASSERT(!IsInternalOnlyClassId(cls.id()));
   // Can't track dependencies for classes on the VM heap since those are
   // read-only.
   // TODO(fschneider): Enable tracking of CHA dependent code for VM heap
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index a3e59b2..6a4d13e 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -90,6 +90,91 @@
   DISALLOW_COPY_AND_ASSIGN(ReadOnlyHandles);
 };
 
+class DartInitializationState {
+ public:
+  enum class InitializationState {
+    kUnInitialized = 0,
+    kInitializing = 1,
+    kInitialized = 2,
+    kCleaningup = 3,
+  };
+
+  DartInitializationState()
+      : state_(InitializationState::kUnInitialized),
+        in_use_(false),
+        lock_(nullptr) {
+    lock_ = new Monitor();
+  }
+  ~DartInitializationState() {}
+
+  bool SetInitializing() {
+    MonitorLocker ml(lock_);
+    if (state_ != InitializationState::kUnInitialized || in_use_) {
+      return false;
+    }
+    state_ = InitializationState::kInitializing;
+    return true;
+  }
+
+  void ResetInitializing() {
+    MonitorLocker ml(lock_);
+    ASSERT((state_ == InitializationState::kInitializing) && !in_use_);
+    state_ = InitializationState::kUnInitialized;
+  }
+
+  void SetInitialized() {
+    MonitorLocker ml(lock_);
+    ASSERT((state_ == InitializationState::kInitializing) && !in_use_);
+    state_ = InitializationState::kInitialized;
+  }
+
+  bool IsInitialized() const {
+    MonitorLocker ml(lock_);
+    return (state_ == InitializationState::kInitialized);
+  }
+
+  bool SetCleaningup() {
+    MonitorLocker ml(lock_);
+    if (state_ != InitializationState::kInitialized) {
+      return false;
+    }
+    state_ = InitializationState::kCleaningup;
+    return true;
+  }
+
+  void SetUnInitialized() {
+    MonitorLocker ml(lock_);
+    ASSERT(state_ == InitializationState::kCleaningup);
+    while (in_use_) {
+      ml.Wait();
+    }
+    state_ = InitializationState::kUnInitialized;
+  }
+
+  bool SetInUse() {
+    MonitorLocker ml(lock_);
+    if (state_ != InitializationState::kInitialized) {
+      return false;
+    }
+    in_use_ = true;
+    return true;
+  }
+
+  void ResetInUse() {
+    MonitorLocker ml(lock_);
+    ASSERT((state_ == InitializationState::kInitialized) ||
+           (state_ == InitializationState::kCleaningup));
+    in_use_ = false;
+    ml.NotifyAll();
+  }
+
+ private:
+  InitializationState state_;
+  bool in_use_;
+  Monitor* lock_;
+};
+static DartInitializationState init_state_;
+
 static void CheckOffsets() {
 #if !defined(IS_SIMARM_X64)
   // These offsets are embedded in precompiled instructions. We need the
@@ -180,26 +265,29 @@
 #endif  // !defined(IS_SIMARM_X64)
 }
 
-char* Dart::Init(const uint8_t* vm_isolate_snapshot,
-                 const uint8_t* instructions_snapshot,
-                 Dart_IsolateGroupCreateCallback create_group,
-                 Dart_InitializeIsolateCallback initialize_isolate,
-                 Dart_IsolateShutdownCallback shutdown,
-                 Dart_IsolateCleanupCallback cleanup,
-                 Dart_IsolateGroupCleanupCallback cleanup_group,
-                 Dart_ThreadExitCallback thread_exit,
-                 Dart_FileOpenCallback file_open,
-                 Dart_FileReadCallback file_read,
-                 Dart_FileWriteCallback file_write,
-                 Dart_FileCloseCallback file_close,
-                 Dart_EntropySource entropy_source,
-                 Dart_GetVMServiceAssetsArchive get_service_assets,
-                 bool start_kernel_isolate,
-                 Dart_CodeObserver* observer) {
+char* Dart::DartInit(const uint8_t* vm_isolate_snapshot,
+                     const uint8_t* instructions_snapshot,
+                     Dart_IsolateGroupCreateCallback create_group,
+                     Dart_InitializeIsolateCallback initialize_isolate,
+                     Dart_IsolateShutdownCallback shutdown,
+                     Dart_IsolateCleanupCallback cleanup,
+                     Dart_IsolateGroupCleanupCallback cleanup_group,
+                     Dart_ThreadExitCallback thread_exit,
+                     Dart_FileOpenCallback file_open,
+                     Dart_FileReadCallback file_read,
+                     Dart_FileWriteCallback file_write,
+                     Dart_FileCloseCallback file_close,
+                     Dart_EntropySource entropy_source,
+                     Dart_GetVMServiceAssetsArchive get_service_assets,
+                     bool start_kernel_isolate,
+                     Dart_CodeObserver* observer) {
   CheckOffsets();
-  // TODO(iposva): Fix race condition here.
-  if (vm_isolate_ != NULL || !Flags::Initialized()) {
-    return Utils::StrDup("VM already initialized or flags not initialized.");
+
+  if (!Flags::Initialized()) {
+    return Utils::StrDup("VM initialization failed-VM Flags not initialized.");
+  }
+  if (vm_isolate_ != NULL) {
+    return Utils::StrDup("VM initialization is in an inconsistent state.");
   }
 
   const Snapshot* snapshot = nullptr;
@@ -439,6 +527,41 @@
   return NULL;
 }
 
+char* Dart::Init(const uint8_t* vm_isolate_snapshot,
+                 const uint8_t* instructions_snapshot,
+                 Dart_IsolateGroupCreateCallback create_group,
+                 Dart_InitializeIsolateCallback initialize_isolate,
+                 Dart_IsolateShutdownCallback shutdown,
+                 Dart_IsolateCleanupCallback cleanup,
+                 Dart_IsolateGroupCleanupCallback cleanup_group,
+                 Dart_ThreadExitCallback thread_exit,
+                 Dart_FileOpenCallback file_open,
+                 Dart_FileReadCallback file_read,
+                 Dart_FileWriteCallback file_write,
+                 Dart_FileCloseCallback file_close,
+                 Dart_EntropySource entropy_source,
+                 Dart_GetVMServiceAssetsArchive get_service_assets,
+                 bool start_kernel_isolate,
+                 Dart_CodeObserver* observer) {
+  if (!init_state_.SetInitializing()) {
+    return Utils::StrDup(
+        "Bad VM initialization state, "
+        "already initialized or "
+        "multiple threads initializing the VM.");
+  }
+  char* retval = DartInit(vm_isolate_snapshot, instructions_snapshot,
+                          create_group, initialize_isolate, shutdown, cleanup,
+                          cleanup_group, thread_exit, file_open, file_read,
+                          file_write, file_close, entropy_source,
+                          get_service_assets, start_kernel_isolate, observer);
+  if (retval != NULL) {
+    init_state_.ResetInitializing();
+    return retval;
+  }
+  init_state_.SetInitialized();
+  return NULL;
+}
+
 static void DumpAliveIsolates(intptr_t num_attempts,
                               bool only_aplication_isolates) {
   IsolateGroup::ForEach([&](IsolateGroup* group) {
@@ -501,9 +624,10 @@
 
 char* Dart::Cleanup() {
   ASSERT(Isolate::Current() == NULL);
-  if (vm_isolate_ == NULL) {
+  if (!init_state_.SetCleaningup()) {
     return Utils::StrDup("VM already terminated.");
   }
+  ASSERT(vm_isolate_ != NULL);
 
   if (FLAG_trace_shutdown) {
     OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Starting shutdown\n",
@@ -592,6 +716,7 @@
     OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleting thread pool\n",
                  UptimeMillis());
   }
+  init_state_.SetUnInitialized();
   thread_pool_->Shutdown();
   delete thread_pool_;
   thread_pool_ = NULL;
@@ -681,6 +806,18 @@
   return NULL;
 }
 
+bool Dart::IsInitialized() {
+  return init_state_.IsInitialized();
+}
+
+bool Dart::SetActiveApiCall() {
+  return init_state_.SetInUse();
+}
+
+void Dart::ResetActiveApiCall() {
+  init_state_.ResetInUse();
+}
+
 Isolate* Dart::CreateIsolate(const char* name_prefix,
                              const Dart_IsolateFlags& api_flags,
                              IsolateGroup* isolate_group) {
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index b0776be..c22f1f0 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -9,6 +9,8 @@
 #include "include/dart_tools_api.h"
 #include "vm/allocation.h"
 #include "vm/isolate.h"
+#include "vm/lockers.h"
+#include "vm/os_thread.h"
 #include "vm/snapshot.h"
 
 namespace dart {
@@ -48,6 +50,13 @@
   // (caller owns error message and has to free it).
   static char* Cleanup();
 
+  // Returns true if the VM is initialized.
+  static bool IsInitialized();
+
+  // Used to Indicate that a Dart API call is active.
+  static bool SetActiveApiCall();
+  static void ResetActiveApiCall();
+
   static Isolate* CreateIsolate(const char* name_prefix,
                                 const Dart_IsolateFlags& api_flags,
                                 IsolateGroup* isolate_group);
@@ -149,6 +158,23 @@
   static Dart_GCEventCallback gc_event_callback() { return gc_event_callback_; }
 
  private:
+  static char* DartInit(const uint8_t* vm_snapshot_data,
+                        const uint8_t* vm_snapshot_instructions,
+                        Dart_IsolateGroupCreateCallback create_group,
+                        Dart_InitializeIsolateCallback initialize_isolate,
+                        Dart_IsolateShutdownCallback shutdown,
+                        Dart_IsolateCleanupCallback cleanup,
+                        Dart_IsolateGroupCleanupCallback cleanup_group,
+                        Dart_ThreadExitCallback thread_exit,
+                        Dart_FileOpenCallback file_open,
+                        Dart_FileReadCallback file_read,
+                        Dart_FileWriteCallback file_write,
+                        Dart_FileCloseCallback file_close,
+                        Dart_EntropySource entropy_source,
+                        Dart_GetVMServiceAssetsArchive get_service_assets,
+                        bool start_kernel_isolate,
+                        Dart_CodeObserver* observer);
+
   static constexpr const char* kVmIsolateName = "vm-isolate";
 
   static void WaitForIsolateShutdown();
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 8acd172..00061db 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -6324,54 +6324,57 @@
   if (type > Dart_Timeline_Event_Flow_End) {
     return;
   }
+  if (!Dart::SetActiveApiCall()) {
+    return;
+  }
   TimelineStream* stream = Timeline::GetEmbedderStream();
   ASSERT(stream != NULL);
   TimelineEvent* event = stream->StartEvent();
-  if (event == NULL) {
-    return;
+  if (event != NULL) {
+    switch (type) {
+      case Dart_Timeline_Event_Begin:
+        event->Begin(label, timestamp0);
+        break;
+      case Dart_Timeline_Event_End:
+        event->End(label, timestamp0);
+        break;
+      case Dart_Timeline_Event_Instant:
+        event->Instant(label, timestamp0);
+        break;
+      case Dart_Timeline_Event_Duration:
+        event->Duration(label, timestamp0, timestamp1_or_async_id);
+        break;
+      case Dart_Timeline_Event_Async_Begin:
+        event->AsyncBegin(label, timestamp1_or_async_id, timestamp0);
+        break;
+      case Dart_Timeline_Event_Async_End:
+        event->AsyncEnd(label, timestamp1_or_async_id, timestamp0);
+        break;
+      case Dart_Timeline_Event_Async_Instant:
+        event->AsyncInstant(label, timestamp1_or_async_id, timestamp0);
+        break;
+      case Dart_Timeline_Event_Counter:
+        event->Counter(label, timestamp0);
+        break;
+      case Dart_Timeline_Event_Flow_Begin:
+        event->FlowBegin(label, timestamp1_or_async_id, timestamp0);
+        break;
+      case Dart_Timeline_Event_Flow_Step:
+        event->FlowStep(label, timestamp1_or_async_id, timestamp0);
+        break;
+      case Dart_Timeline_Event_Flow_End:
+        event->FlowEnd(label, timestamp1_or_async_id, timestamp0);
+        break;
+      default:
+        FATAL("Unknown Dart_Timeline_Event_Type");
+    }
+    event->SetNumArguments(argument_count);
+    for (intptr_t i = 0; i < argument_count; i++) {
+      event->CopyArgument(i, argument_names[i], argument_values[i]);
+    }
+    event->Complete();
   }
-  switch (type) {
-    case Dart_Timeline_Event_Begin:
-      event->Begin(label, timestamp0);
-      break;
-    case Dart_Timeline_Event_End:
-      event->End(label, timestamp0);
-      break;
-    case Dart_Timeline_Event_Instant:
-      event->Instant(label, timestamp0);
-      break;
-    case Dart_Timeline_Event_Duration:
-      event->Duration(label, timestamp0, timestamp1_or_async_id);
-      break;
-    case Dart_Timeline_Event_Async_Begin:
-      event->AsyncBegin(label, timestamp1_or_async_id, timestamp0);
-      break;
-    case Dart_Timeline_Event_Async_End:
-      event->AsyncEnd(label, timestamp1_or_async_id, timestamp0);
-      break;
-    case Dart_Timeline_Event_Async_Instant:
-      event->AsyncInstant(label, timestamp1_or_async_id, timestamp0);
-      break;
-    case Dart_Timeline_Event_Counter:
-      event->Counter(label, timestamp0);
-      break;
-    case Dart_Timeline_Event_Flow_Begin:
-      event->FlowBegin(label, timestamp1_or_async_id, timestamp0);
-      break;
-    case Dart_Timeline_Event_Flow_Step:
-      event->FlowStep(label, timestamp1_or_async_id, timestamp0);
-      break;
-    case Dart_Timeline_Event_Flow_End:
-      event->FlowEnd(label, timestamp1_or_async_id, timestamp0);
-      break;
-    default:
-      FATAL("Unknown Dart_Timeline_Event_Type");
-  }
-  event->SetNumArguments(argument_count);
-  for (intptr_t i = 0; i < argument_count; i++) {
-    event->CopyArgument(i, argument_names[i], argument_values[i]);
-  }
-  event->Complete();
+  Dart::ResetActiveApiCall();
 #endif
 }
 
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index 59ce2aa..bd5d3e9 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -212,7 +212,7 @@
 
   // Returns true if the handle holds a Dart Instance.
   static bool IsInstance(Dart_Handle handle) {
-    return !IsInternalOnlyId(ClassId(handle));
+    return !IsInternalOnlyClassId(ClassId(handle));
   }
 
   // Returns true if the handle is non-dangling.
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index b61e6c2..5b0bc2b 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -24,6 +24,7 @@
 namespace dart {
 
 DECLARE_FLAG(bool, verify_acquired_data);
+DECLARE_FLAG(bool, complete_timeline);
 
 #ifndef PRODUCT
 
@@ -9305,13 +9306,13 @@
 
 TEST_CASE(DartAPI_InvokeVMServiceMethod) {
   char buffer[1024];
-  snprintf(buffer, sizeof(buffer),
-           R"({
-               "jsonrpc": 2.0,
-               "id": "foo",
-               "method": "getVM",
-               "params": { }
-              })");
+  Utils::SNPrint(buffer, sizeof(buffer),
+                 R"({
+                  "jsonrpc": 2.0,
+                  "id": "foo",
+                  "method": "getVM",
+                  "params": { }
+                 })");
   uint8_t* response_json = nullptr;
   intptr_t response_json_length = 0;
   char* error = nullptr;
@@ -9361,6 +9362,151 @@
   EXPECT(result == Dart_True());
 }
 
+static Monitor* loop_test_lock = new Monitor();
+static bool loop_test_exit = false;
+static bool loop_reset_count = false;
+
+#if !defined(PRODUCT)
+static void InvokeServiceMessages(uword param) {
+  char buffer[1024];
+  Utils::SNPrint(buffer, sizeof(buffer),
+                 R"({
+                  "jsonrpc": 2.0,
+                  "id": "foo",
+                  "method": "getVM",
+                  "params": { }
+                 })");
+  uint8_t* response_json = nullptr;
+  intptr_t response_json_length = 0;
+  char* error = nullptr;
+  uint32_t count = 0;
+  do {
+    error = nullptr;
+    response_json = nullptr;
+    response_json_length = 0;
+    const bool success = Dart_InvokeVMServiceMethod(
+        reinterpret_cast<uint8_t*>(buffer), strlen(buffer), &response_json,
+        &response_json_length, &error);
+    if (success) {
+      MonitorLocker ml(loop_test_lock);
+      EXPECT(error == nullptr);
+      free(response_json);
+      if (count == 10) {
+        loop_test_exit = true;
+        ml.Notify();
+      }
+      count++;
+    }
+  } while (count < 100);
+  free(error);
+}
+
+TEST_CASE(DartAPI_InvokeVMServiceMethod_Loop) {
+  MonitorLocker ml(loop_test_lock);
+  loop_test_exit = false;
+  loop_reset_count = false;
+  OSThread::Start("InvokeServiceMessages", InvokeServiceMessages, 0);
+  while (!loop_test_exit) {
+    ml.Wait();
+  }
+}
+#endif  // !defined(PRODUCT)
+
+static void HandleResponse(Dart_Port dest_port_id, Dart_CObject* message) {
+  printf("Response received\n");
+}
+
+static void CreateNativePorts(uword param) {
+  uint32_t count = 0;
+  do {
+    const Dart_Port port_id = Dart_NewNativePort("tst", &HandleResponse, false);
+    if (port_id != ILLEGAL_PORT) {
+      Dart_CloseNativePort(port_id);
+      MonitorLocker ml(loop_test_lock);
+      if (count == 10) {
+        loop_test_exit = true;
+        ml.Notify();
+      }
+      count++;
+    }
+  } while (count < 100);
+}
+
+TEST_CASE(DartAPI_NativePort_Loop) {
+  MonitorLocker ml(loop_test_lock);
+  loop_test_exit = false;
+  loop_reset_count = false;
+  OSThread::Start("NativePort", CreateNativePorts, 0);
+  while (!loop_test_exit) {
+    ml.Wait();
+  }
+}
+
+#if !defined(PRODUCT)
+static void CreateTimelineEvents(uword param) {
+  {
+    MonitorLocker ml(loop_test_lock);
+    loop_test_exit = true;
+    ml.Notify();
+  }
+  do {
+    Dart_TimelineEvent("T1", 0, 1, Dart_Timeline_Event_Begin, 0, NULL, NULL);
+    Dart_TimelineEvent("T1", 0, 9, Dart_Timeline_Event_End, 0, NULL, NULL);
+    Dart_TimelineEvent("T2", 0, 1, Dart_Timeline_Event_Instant, 0, NULL, NULL);
+    Dart_TimelineEvent("T3", 0, 2, Dart_Timeline_Event_Duration, 0, NULL, NULL);
+    Dart_TimelineEvent("T4", 0, 3, Dart_Timeline_Event_Async_Begin, 0, NULL,
+                       NULL);
+    Dart_TimelineEvent("T4", 9, 3, Dart_Timeline_Event_Async_End, 0, NULL,
+                       NULL);
+    Dart_TimelineEvent("T5", 1, 4, Dart_Timeline_Event_Async_Instant, 0, NULL,
+                       NULL);
+    Dart_TimelineEvent("T7", 1, 4, Dart_Timeline_Event_Counter, 0, NULL, NULL);
+    Dart_TimelineEvent("T8", 1, 4, Dart_Timeline_Event_Flow_Begin, 0, NULL,
+                       NULL);
+    Dart_TimelineEvent("T8", 1, 4, Dart_Timeline_Event_Flow_Step, 0, NULL,
+                       NULL);
+    Dart_TimelineEvent("T8", 1, 4, Dart_Timeline_Event_Flow_End, 0, NULL, NULL);
+  } while (true);
+}
+
+UNIT_TEST_CASE(DartAPI_TimelineEvents_Loop) {
+  EXPECT(Dart_SetVMFlags(TesterState::argc, TesterState::argv) == nullptr);
+  FLAG_complete_timeline = true;
+  Dart_InitializeParams params;
+  memset(&params, 0, sizeof(Dart_InitializeParams));
+  params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
+  params.vm_snapshot_data = TesterState::vm_snapshot_data;
+  params.create_group = TesterState::create_callback;
+  params.shutdown_isolate = TesterState::shutdown_callback;
+  params.cleanup_group = TesterState::group_cleanup_callback;
+  params.start_kernel_isolate = true;
+  char* result = nullptr;
+
+  result = Dart_Initialize(&params);
+  EXPECT(result == nullptr);
+  {
+    MonitorLocker ml(loop_test_lock);
+    loop_test_exit = false;
+    loop_reset_count = false;
+    OSThread::Start("TimelineEvents", CreateTimelineEvents, 0);
+    while (!loop_test_exit) {
+      printf("VM waiting for notification\n");
+      ml.Wait();
+    }
+    loop_test_exit = false;
+  }
+  result = Dart_Cleanup();
+  EXPECT(result == nullptr);
+  for (intptr_t i = 0; i < 50; i++) {
+    EXPECT(Dart_SetVMFlags(TesterState::argc, TesterState::argv) == nullptr);
+    result = Dart_Initialize(&params);
+    EXPECT(result == nullptr);
+    result = Dart_Cleanup();
+    EXPECT(result == nullptr);
+  }
+}
+#endif  // !defined(PRODUCT)
+
 static intptr_t EchoInt(double x) {
   return x;
 }
diff --git a/runtime/vm/heap/verifier.cc b/runtime/vm/heap/verifier.cc
index 095fc6f..71ea299 100644
--- a/runtime/vm/heap/verifier.cc
+++ b/runtime/vm/heap/verifier.cc
@@ -117,7 +117,7 @@
   // Therefore we disable the handle verification here.
   const bool old_verify_flag = FLAG_verify_handles;
   FLAG_verify_handles = false;
-  if (!IsInternalOnlyId(obj->GetClassId()) &&
+  if (!IsInternalOnlyClassId(obj->GetClassId()) &&
       (obj->GetClassId() != kTypeArgumentsCid)) {
     if (obj->untag()->IsCanonical()) {
       instanceHandle_ ^= obj;
diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc
index 132ac95..07a2fec 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -82,6 +82,9 @@
                  CURRENT_FUNC);
     return ILLEGAL_PORT;
   }
+  if (!Dart::SetActiveApiCall()) {
+    return ILLEGAL_PORT;
+  }
   // Start the native port without a current isolate.
   IsolateLeaveScope saver(Isolate::Current());
 
@@ -89,6 +92,7 @@
   Dart_Port port_id = PortMap::CreatePort(nmh);
   PortMap::SetPortState(port_id, PortMap::kLivePort);
   nmh->Run(Dart::thread_pool(), NULL, NULL, 0);
+  Dart::ResetActiveApiCall();
   return port_id;
 }
 
@@ -112,6 +116,11 @@
   ASSERT(isolate == nullptr || !isolate->is_service_isolate());
   IsolateLeaveScope saver(isolate);
 
+  if (!Dart::IsInitialized()) {
+    *error = ::dart::Utils::StrDup("VM Service is not active.");
+    return false;
+  }
+
   // We only allow one isolate reload at a time.  If this turns out to be on the
   // critical path, we can change it to have a global datastructure which is
   // mapping the reply ports to receive buffers.
@@ -155,9 +164,21 @@
   if (ServiceIsolate::SendServiceRpc(request_json, request_json_length, port,
                                      error)) {
     // We posted successfully and expect the vm-service to send the reply, so
-    // we will wait for it now.
-    auto wait_result = monitor.Wait();
-    ASSERT(wait_result == Monitor::kNotified);
+    // we will wait for it now. Since the service isolate could have shutdown
+    // after we sent the message we make sure to wake up periodically and
+    // check to see if the service isolate has shutdown.
+    do {
+      auto wait_result = monitor.Wait(1000); /* milliseconds */
+      if (wait_result == Monitor::kNotified) {
+        break;
+      }
+      if (!ServiceIsolate::IsRunning()) {
+        // Service Isolate has shutdown while we were waiting for a reply,
+        // We will not get a reply anymore, cleanup and return an error.
+        Dart_CloseNativePort(port);
+        return false;
+      }
+    } while (true);
 
     // The caller takes ownership of the data.
     *response_json = result_bytes;
@@ -235,7 +256,10 @@
 
 DART_EXPORT void* Dart_ExecuteInternalCommand(const char* command, void* arg) {
   if (strcmp(command, "gc-on-nth-allocation") == 0) {
-    TransitionNativeToVM _(Thread::Current());
+    Thread* const thread = Thread::Current();
+    Isolate* isolate = (thread == NULL) ? NULL : thread->isolate();
+    CHECK_ISOLATE(isolate);
+    TransitionNativeToVM _(thread);
     intptr_t argument = reinterpret_cast<intptr_t>(arg);
     ASSERT(argument > 0);
     IsolateGroup::Current()->heap()->CollectOnNthAllocation(argument);
@@ -243,7 +267,10 @@
 
   } else if (strcmp(command, "gc-now") == 0) {
     ASSERT(arg == nullptr);  // Don't pass an argument to this command.
-    TransitionNativeToVM _(Thread::Current());
+    Thread* const thread = Thread::Current();
+    Isolate* isolate = (thread == NULL) ? NULL : thread->isolate();
+    CHECK_ISOLATE(isolate);
+    TransitionNativeToVM _(thread);
     IsolateGroup::Current()->heap()->CollectAllGarbage();
     return nullptr;
 
@@ -255,6 +282,7 @@
 
   } else if (strcmp(command, "is-mutator-in-native") == 0) {
     Isolate* const isolate = reinterpret_cast<Isolate*>(arg);
+    CHECK_ISOLATE(isolate);
     if (isolate->mutator_thread()->execution_state_cross_thread_for_testing() ==
         Thread::kThreadInNative) {
       return arg;
@@ -265,7 +293,9 @@
   } else if (strcmp(command, "run-in-safepoint-and-rw-code") == 0) {
     const RunInSafepointAndRWCodeArgs* const args =
         reinterpret_cast<RunInSafepointAndRWCodeArgs*>(arg);
-    Thread::EnterIsolateAsHelper(args->isolate, Thread::TaskKind::kUnknownTask);
+    Isolate* const isolate = args->isolate;
+    CHECK_ISOLATE(isolate);
+    Thread::EnterIsolateAsHelper(isolate, Thread::TaskKind::kUnknownTask);
     Thread* const thread = Thread::Current();
     {
       GcSafepointOperationScope scope(thread);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 50cd146..a716109 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -2952,7 +2952,7 @@
   result.set_num_type_arguments_unsafe(0);
   result.set_num_native_fields(0);
   result.set_state_bits(0);
-  if (IsInternalOnlyId(FakeObject::kClassId) ||
+  if (IsInternalOnlyClassId(FakeObject::kClassId) ||
       (FakeObject::kClassId == kTypeArgumentsCid)) {
     // VM internal classes are done. There is no finalization needed or
     // possible in this case.
@@ -4465,7 +4465,7 @@
     const Array& arguments,
     const TypeArguments& type_arguments) const {
   ASSERT(Thread::Current()->IsMutatorThread());
-  if (IsInternalOnlyId(id()) || (id() == kTypeArgumentsCid)) {
+  if (IsInternalOnlyClassId(id()) || (id() == kTypeArgumentsCid)) {
     const Instance& exception = Instance::Handle(String::New(
         "Expressions can be evaluated only with regular Dart instances"));
     const Instance& stacktrace = Instance::Handle();
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index f169091..40e55a83 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -24,7 +24,7 @@
 static bool IsUserClass(intptr_t cid) {
   if (cid == kContextCid) return true;
   if (cid == kTypeArgumentsCid) return false;
-  return !IsInternalOnlyId(cid);
+  return !IsInternalOnlyClassId(cid);
 }
 
 // The state of a pre-order, depth-first traversal of an object graph.
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 71e0b48..6112fa7 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -2786,7 +2786,7 @@
         isStatic = false;
       }
       if (!cls.IsTopLevel() &&
-          (IsInternalOnlyId(cls.id()) || cls.id() == kTypeArgumentsCid)) {
+          (IsInternalOnlyClassId(cls.id()) || cls.id() == kTypeArgumentsCid)) {
         js->PrintError(
             kInvalidParams,
             "Expressions can be evaluated only with regular Dart instances");
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index acc453f..418aa3a 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -188,11 +188,14 @@
   request.value.as_array.length = ARRAY_SIZE(request_array);
   ServiceIsolate::WaitForServiceIsolateStartup();
   Dart_Port service_port = ServiceIsolate::Port();
-
-  const bool success = Dart_PostCObject(service_port, &request);
-
-  if (!success && error != nullptr) {
-    if (service_port == ILLEGAL_PORT) {
+  bool success = false;
+  if (service_port != ILLEGAL_PORT) {
+    success = Dart_PostCObject(service_port, &request);
+    if (!success && error != nullptr) {
+      *error = Utils::StrDup("Was unable to post message to service isolate.");
+    }
+  } else {
+    if (error != nullptr) {
       if (startup_failure_reason_ != nullptr) {
         *error = OS::SCreate(/*zone=*/nullptr,
                              "Service isolate failed to start up: %s.",
@@ -200,11 +203,8 @@
       } else {
         *error = Utils::StrDup("No service isolate port was found.");
       }
-    } else {
-      *error = Utils::StrDup("Was unable to post message to service isolate.");
     }
   }
-
   return success;
 }
 
@@ -318,6 +318,8 @@
   MonitorLocker ml(monitor_);
   ASSERT(state_ == kStarted || state_ == kStopping);
   state_ = kStopped;
+  port_ = ILLEGAL_PORT;
+  isolate_ = nullptr;
   ml.NotifyAll();
 }
 
@@ -332,6 +334,7 @@
   MonitorLocker ml(monitor_);
   ASSERT(state_ == kStarting);
   state_ = kStopped;
+  port_ = ILLEGAL_PORT;
   startup_failure_reason_ = error;
   ml.NotifyAll();
 }
diff --git a/runtime/vm/tagged_pointer.h b/runtime/vm/tagged_pointer.h
index 4265b03..19444ff 100644
--- a/runtime/vm/tagged_pointer.h
+++ b/runtime/vm/tagged_pointer.h
@@ -109,7 +109,7 @@
   bool IsStringInstance() const { return IsStringClassId(GetClassId()); }
   bool IsRawNull() const { return GetClassId() == kNullCid; }
   bool IsDartInstance() const {
-    return (!IsHeapObject() || !IsInternalOnlyId(GetClassId()));
+    return (!IsHeapObject() || !IsInternalOnlyClassId(GetClassId()));
   }
   bool IsFreeListElement() const {
     return ((GetClassId() == kFreeListElement));
diff --git a/tools/VERSION b/tools/VERSION
index 61d8e8a..f6002f4 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 15
+PRERELEASE 16
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index a3a6e36..9e2fefe 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -3341,6 +3341,15 @@
           ]
         },
         {
+          "name": "analyze pkg/nnbd_migration",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
+          "arguments": [
+            "analyze",
+            "--fatal-infos",
+            "pkg/nnbd_migration"
+          ]
+        },
+        {
           "name": "analyze pkg/smith",
           "script": "out/ReleaseX64/dart-sdk/bin/dart",
           "arguments": [
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index c8ff6b3..20a25ed 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -2002,7 +2002,7 @@
                 '  $RENAME$METADATA$MODIFIERS$TYPE $NAME($PARAMS) => '\
                 'js_util.callMethod(this, \'$JSNAME\', [$ARGS]);\n'
                 if CanUseStaticExtensions(self._interface_name, self._generate_static_extensions) else
-                '  $RENAME$METADATA$MODIFIERS$TYPE $NAME($PARAMS) native;\n',
+                '\n  $RENAME$METADATA$MODIFIERS$TYPE $NAME($PARAMS) native;\n',
                 RENAME=self._RenamingAnnotation(info.declared_name, html_name),
                 METADATA=self._Metadata(
                     info.type_name, info.declared_name,
diff --git a/tools/dom/templates/dart2js_static_extension_impl.darttemplate b/tools/dom/templates/dart2js_static_extension_impl.darttemplate
index e2b3c61..5501eee 100644
--- a/tools/dom/templates/dart2js_static_extension_impl.darttemplate
+++ b/tools/dom/templates/dart2js_static_extension_impl.darttemplate
@@ -1,10 +1,11 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
 part of $LIBRARYNAME;
 
-$(ANNOTATIONS)@sealed$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$MIXINS$IMPLEMENTS { $!CLASSMEMBERS }
+//todo: add @sealed annotation
+$(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$MIXINS$IMPLEMENTS { $!CLASSMEMBERS }
 
 extension $(CLASSNAME)Extension on $CLASSNAME {
 $!EXTENSIONMEMBERS
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 1559461..d1e9e6b 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -52,6 +52,7 @@
     getNativeInterceptor,
     setDispatchProperty;
 import 'dart:_foreign_helper' show JS, JS_INTERCEPTOR_CONSTANT;
+import 'dart:js_util' as js_util;
 
 export 'dart:_internal' show HttpStatus;
 export 'dart:html_common' show promiseToFuture;
diff --git a/tools/generate_package_config.dart b/tools/generate_package_config.dart
index 1664201..882c827 100644
--- a/tools/generate_package_config.dart
+++ b/tools/generate_package_config.dart
@@ -62,8 +62,6 @@
     packageDirectory('third_party/pkg/webdev/frontend_server_client'),
     packageDirectory('tools/package_deps'),
   ];
-  // TODO(sigmund): remove this when dart2js_info's new location is used.
-  packageDirs.remove(packageDirectory(p.join('pkg', 'dart2js_info')));
 
   var cfePackageDirs = [
     packageDirectory('pkg/front_end/testcases/'),