Version 2.16.0-22.0.dev

Merge commit '0cad0e722483310a995732b44cc83c5689f9f7c9' into 'dev'
diff --git a/pkg/dds/lib/src/dap/isolate_manager.dart b/pkg/dds/lib/src/dap/isolate_manager.dart
index 47a8dde..6e00463 100644
--- a/pkg/dds/lib/src/dap/isolate_manager.dart
+++ b/pkg/dds/lib/src/dap/isolate_manager.dart
@@ -594,7 +594,10 @@
       return;
     }
 
-    await service.setExceptionPauseMode(isolate.id!, _exceptionPauseMode);
+    await service.setIsolatePauseMode(
+      isolate.id!,
+      exceptionPauseMode: _exceptionPauseMode,
+    );
   }
 
   /// Calls setLibraryDebuggable for all libraries in the given isolate based
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index bafc2dc..e575eae 100644
--- a/pkg/dds/pubspec.yaml
+++ b/pkg/dds/pubspec.yaml
@@ -25,7 +25,7 @@
   shelf_web_socket: ^1.0.0
   sse: ^4.0.0
   stream_channel: ^2.0.0
-  vm_service: ^7.2.0
+  vm_service: ^7.5.0
   web_socket_channel: ^2.0.0
 
 dev_dependencies:
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index 50d973c..760c9d9 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,5 +1,10 @@
 # Changelog
 
+## 7.5.0
+- Update to version `3.53` of the spec.
+- Added `setIsolatePauseMode` RPC.
+- Deprecated `setExceptionPauseMode` in favor of `setIsolatePauseMode`.
+
 ## 7.4.0
 - Update to version `3.52` of the spec.
 - Added `lookupResolvedPackageUris` and `lookupPackageUris` RPCs and `UriList`
diff --git a/pkg/vm_service/java/.gitignore b/pkg/vm_service/java/.gitignore
index 817e983..a54ba8c 100644
--- a/pkg/vm_service/java/.gitignore
+++ b/pkg/vm_service/java/.gitignore
@@ -36,6 +36,7 @@
 src/org/dartlang/vm/service/consumer/ResumeConsumer.java
 src/org/dartlang/vm/service/consumer/SetExceptionPauseModeConsumer.java
 src/org/dartlang/vm/service/consumer/SetFlagConsumer.java
+src/org/dartlang/vm/service/consumer/SetIsolatePauseModeConsumer.java
 src/org/dartlang/vm/service/consumer/SetLibraryDebuggableConsumer.java
 src/org/dartlang/vm/service/consumer/SetNameConsumer.java
 src/org/dartlang/vm/service/consumer/SetTraceClassAllocationConsumer.java
diff --git a/pkg/vm_service/java/version.properties b/pkg/vm_service/java/version.properties
index 8ae6998..b8e9261a 100644
--- a/pkg/vm_service/java/version.properties
+++ b/pkg/vm_service/java/version.properties
@@ -1 +1 @@
-version=3.52
+version=3.53
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index 51958bd..278e6cf 100644
--- a/pkg/vm_service/lib/src/vm_service.dart
+++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -26,7 +26,7 @@
         HeapSnapshotObjectNoData,
         HeapSnapshotObjectNullData;
 
-const String vmServiceVersion = '3.52.0';
+const String vmServiceVersion = '3.53.0';
 
 /// @optional
 const String optional = 'optional';
@@ -236,6 +236,7 @@
   'resume': const ['Success'],
   'setBreakpointState': const ['Breakpoint'],
   'setExceptionPauseMode': const ['Success'],
+  'setIsolatePauseMode': const ['Success'],
   'setFlag': const ['Success', 'Error'],
   'setLibraryDebuggable': const ['Success'],
   'setName': const ['Success'],
@@ -1078,9 +1079,34 @@
   ///
   /// This method will throw a [SentinelException] in the case a [Sentinel] is
   /// returned.
+  @Deprecated('Use setIsolatePauseMode instead')
   Future<Success> setExceptionPauseMode(
       String isolateId, /*ExceptionPauseMode*/ String mode);
 
+  /// The `setIsolatePauseMode` RPC is used to control if or when an isolate
+  /// will pause due to a change in execution state.
+  ///
+  /// The `shouldPauseOnExit` parameter specify whether the target isolate
+  /// should pause on exit.
+  ///
+  /// The `setExceptionPauseMode` RPC is used to control if an isolate pauses
+  /// when an exception is thrown.
+  ///
+  /// mode | meaning
+  /// ---- | -------
+  /// None | Do not pause isolate on thrown exceptions
+  /// Unhandled | Pause isolate on unhandled exceptions
+  /// All  | Pause isolate on all thrown exceptions
+  ///
+  /// If `isolateId` refers to an isolate which has exited, then the `Collected`
+  /// [Sentinel] is returned.
+  ///
+  /// This method will throw a [SentinelException] in the case a [Sentinel] is
+  /// returned.
+  Future<Success> setIsolatePauseMode(String isolateId,
+      {/*ExceptionPauseMode*/ String? exceptionPauseMode,
+      bool? shouldPauseOnExit});
+
   /// The `setFlag` RPC is used to set a VM flag at runtime. Returns an error if
   /// the named flag does not exist, the flag may not be set at runtime, or the
   /// value is of the wrong type for the flag.
@@ -1101,6 +1127,7 @@
   /// provided value. If set to false when the profiler is already running, the
   /// profiler will be stopped but may not free its sample buffer depending on
   /// platform limitations.
+  /// - Isolate pause settings will only be applied to newly spawned isolates.
   ///
   /// See [Success].
   ///
@@ -1549,11 +1576,19 @@
           );
           break;
         case 'setExceptionPauseMode':
+          // ignore: deprecated_member_use_from_same_package
           response = await _serviceImplementation.setExceptionPauseMode(
             params!['isolateId'],
             params['mode'],
           );
           break;
+        case 'setIsolatePauseMode':
+          response = await _serviceImplementation.setIsolatePauseMode(
+            params!['isolateId'],
+            exceptionPauseMode: params['exceptionPauseMode'],
+            shouldPauseOnExit: params['shouldPauseOnExit'],
+          );
+          break;
         case 'setFlag':
           response = await _serviceImplementation.setFlag(
             params!['name'],
@@ -2081,12 +2116,24 @@
         'enable': enable
       });
 
+  @Deprecated('Use setIsolatePauseMode instead')
   @override
   Future<Success> setExceptionPauseMode(
           String isolateId, /*ExceptionPauseMode*/ String mode) =>
       _call('setExceptionPauseMode', {'isolateId': isolateId, 'mode': mode});
 
   @override
+  Future<Success> setIsolatePauseMode(String isolateId,
+          {/*ExceptionPauseMode*/ String? exceptionPauseMode,
+          bool? shouldPauseOnExit}) =>
+      _call('setIsolatePauseMode', {
+        'isolateId': isolateId,
+        if (exceptionPauseMode != null)
+          'exceptionPauseMode': exceptionPauseMode,
+        if (shouldPauseOnExit != null) 'shouldPauseOnExit': shouldPauseOnExit,
+      });
+
+  @override
   Future<Response> setFlag(String name, String value) =>
       _call('setFlag', {'name': name, 'value': value});
 
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 2984592..8bd5ed5 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -3,7 +3,7 @@
   A library to communicate with a service implementing the Dart VM
   service protocol.
 
-version: 7.4.0
+version: 7.5.0
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_service
 
diff --git a/pkg/vm_service/test/common/test_helper.dart b/pkg/vm_service/test/common/test_helper.dart
index 585722f..8bf30b8 100644
--- a/pkg/vm_service/test/common/test_helper.dart
+++ b/pkg/vm_service/test/common/test_helper.dart
@@ -277,7 +277,6 @@
         vm = await vmServiceConnectUri(serviceWebsocketAddress);
         print('Done loading VM');
         isolate = await getFirstIsolate(vm);
-        print('Got first isolate');
       });
     });
 
@@ -335,14 +334,12 @@
       if (event.kind == EventKind.kIsolateRunnable) {
         print(event.isolate!.name);
         vm = await service.getVM();
-        //assert(vmIsolates.isNotEmpty);
         await subscription.cancel();
         await service.streamCancel(EventStreams.kIsolate);
         completer!.complete(event.isolate!);
         completer = null;
       }
     });
-
     await service.streamListen(EventStreams.kIsolate);
 
     // The isolate may have started before we subscribed.
diff --git a/pkg/vm_service/test/pause_on_exceptions_legacy_test.dart b/pkg/vm_service/test/pause_on_exceptions_legacy_test.dart
new file mode 100644
index 0000000..21ff3a8
--- /dev/null
+++ b/pkg/vm_service/test/pause_on_exceptions_legacy_test.dart
@@ -0,0 +1,112 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/test_helper.dart';
+
+doThrow() {
+  throw "TheException"; // Line 13.
+}
+
+doCaught() {
+  try {
+    doThrow();
+  } catch (e) {
+    return "end of doCaught";
+  }
+}
+
+doUncaught() {
+  doThrow();
+  return "end of doUncaught";
+}
+
+final tests = <IsolateTest>[
+  (VmService service, IsolateRef isolateRef) async {
+    final isolate = await service.getIsolate(isolateRef.id!);
+    final lib = await service.getObject(isolateRef.id!, isolate.rootLib!.id!);
+
+    Completer? onPaused;
+    Completer? onResume;
+
+    final stream = service.onDebugEvent;
+    final subscription = stream.listen((Event event) {
+      print("Event $event");
+      if (event.kind == EventKind.kPauseException) {
+        if (onPaused == null) throw "Unexpected pause event $event";
+        final t = onPaused;
+        onPaused = null;
+        t!.complete(event);
+      }
+      if (event.kind == EventKind.kResume) {
+        if (onResume == null) throw "Unexpected resume event $event";
+        final t = onResume;
+        onResume = null;
+        t!.complete(event);
+      }
+    });
+    await service.streamListen(EventStreams.kDebug);
+
+    test(String pauseMode, String expression, bool shouldPause,
+        bool shouldBeCaught) async {
+      print("Evaluating $expression with pause on $pauseMode exception");
+
+      // ignore: deprecated_member_use_from_same_package
+      await service.setExceptionPauseMode(isolate.id!, pauseMode);
+
+      late Completer t;
+      if (shouldPause) {
+        t = Completer();
+        onPaused = t;
+      }
+      final fres = service.evaluate(isolate.id!, lib.id!, expression);
+      if (shouldPause) {
+        await t.future;
+
+        final stack = await service.getStack(isolate.id!);
+        expect(stack.frames![0].function!.name, 'doThrow');
+
+        t = Completer();
+        onResume = t;
+        await service.resume(isolate.id!);
+        await t.future;
+      }
+
+      dynamic res = await fres;
+      if (shouldBeCaught) {
+        expect(res is InstanceRef, true);
+        expect(res.kind, 'String');
+        expect(res.valueAsString, equals("end of doCaught"));
+      } else {
+        print(res.json);
+        expect(res is ErrorRef, true);
+        res = await service.getObject(isolate.id!, res.id!);
+        expect(res is Error, true);
+        expect(res.exception.kind, 'String');
+        expect(res.exception.valueAsString, equals("TheException"));
+      }
+    }
+
+    await test("All", "doCaught()", true, true);
+    await test("All", "doUncaught()", true, false);
+
+    await test("Unhandled", "doCaught()", false, true);
+    await test("Unhandled", "doUncaught()", true, false);
+
+    await test("None", "doCaught()", false, true);
+    await test("None", "doUncaught()", false, false);
+
+    await subscription.cancel();
+  },
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'pause_on_exceptions_test.dart',
+    );
diff --git a/pkg/vm_service/test/pause_on_exceptions_test.dart b/pkg/vm_service/test/pause_on_exceptions_test.dart
new file mode 100644
index 0000000..9da7dfc
--- /dev/null
+++ b/pkg/vm_service/test/pause_on_exceptions_test.dart
@@ -0,0 +1,112 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/test_helper.dart';
+
+doThrow() {
+  throw "TheException"; // Line 13.
+}
+
+doCaught() {
+  try {
+    doThrow();
+  } catch (e) {
+    return "end of doCaught";
+  }
+}
+
+doUncaught() {
+  doThrow();
+  return "end of doUncaught";
+}
+
+final tests = <IsolateTest>[
+  (VmService service, IsolateRef isolateRef) async {
+    final isolate = await service.getIsolate(isolateRef.id!);
+    final lib = await service.getObject(isolateRef.id!, isolate.rootLib!.id!);
+
+    Completer? onPaused;
+    Completer? onResume;
+
+    final stream = service.onDebugEvent;
+    final subscription = stream.listen((Event event) {
+      print("Event $event");
+      if (event.kind == EventKind.kPauseException) {
+        if (onPaused == null) throw "Unexpected pause event $event";
+        final t = onPaused;
+        onPaused = null;
+        t!.complete(event);
+      }
+      if (event.kind == EventKind.kResume) {
+        if (onResume == null) throw "Unexpected resume event $event";
+        final t = onResume;
+        onResume = null;
+        t!.complete(event);
+      }
+    });
+    await service.streamListen(EventStreams.kDebug);
+
+    test(String pauseMode, String expression, bool shouldPause,
+        bool shouldBeCaught) async {
+      print("Evaluating $expression with pause on $pauseMode exception");
+
+      await service.setIsolatePauseMode(isolate.id!,
+          exceptionPauseMode: pauseMode);
+
+      late Completer t;
+      if (shouldPause) {
+        t = Completer();
+        onPaused = t;
+      }
+      final fres = service.evaluate(isolate.id!, lib.id!, expression);
+      if (shouldPause) {
+        await t.future;
+
+        final stack = await service.getStack(isolate.id!);
+        expect(stack.frames![0].function!.name, 'doThrow');
+
+        t = Completer();
+        onResume = t;
+        await service.resume(isolate.id!);
+        await t.future;
+      }
+
+      dynamic res = await fres;
+      if (shouldBeCaught) {
+        expect(res is InstanceRef, true);
+        expect(res.kind, 'String');
+        expect(res.valueAsString, equals("end of doCaught"));
+      } else {
+        print(res.json);
+        expect(res is ErrorRef, true);
+        res = await service.getObject(isolate.id!, res.id!);
+        expect(res is Error, true);
+        expect(res.exception.kind, 'String');
+        expect(res.exception.valueAsString, equals("TheException"));
+      }
+    }
+
+    await test("All", "doCaught()", true, true);
+    await test("All", "doUncaught()", true, false);
+
+    await test("Unhandled", "doCaught()", false, true);
+    await test("Unhandled", "doUncaught()", true, false);
+
+    await test("None", "doCaught()", false, true);
+    await test("None", "doUncaught()", false, false);
+
+    await subscription.cancel();
+  },
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'pause_on_exceptions_test.dart',
+    );
diff --git a/pkg/vm_service/test/should_pause_on_exit_test.dart b/pkg/vm_service/test/should_pause_on_exit_test.dart
new file mode 100644
index 0000000..575530c
--- /dev/null
+++ b/pkg/vm_service/test/should_pause_on_exit_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/test_helper.dart';
+
+void testMain() {
+  print('Hello world!');
+}
+
+Future<bool> shouldPauseOnExit(VmService service, IsolateRef isolateRef) async {
+  final isolate = await service.getIsolate(isolateRef.id!);
+  return isolate.pauseOnExit!;
+}
+
+final tests = <IsolateTest>[
+  (VmService service, IsolateRef isolateRef) async {
+    await service.setIsolatePauseMode(isolateRef.id!, shouldPauseOnExit: false);
+    expect(await shouldPauseOnExit(service, isolateRef), false);
+    final completer = Completer<void>();
+
+    final stream = service.onDebugEvent;
+    final subscription = stream.listen((Event event) {
+      if (event.kind == EventKind.kPauseExit) {
+        completer.complete();
+      }
+    });
+    await service.streamListen(EventStreams.kDebug);
+
+    await service.setIsolatePauseMode(isolateRef.id!, shouldPauseOnExit: true);
+    expect(await shouldPauseOnExit(service, isolateRef), true);
+    await service.resume(isolateRef.id!);
+    await completer.future;
+    await service.resume(isolateRef.id!);
+    await subscription.cancel();
+  },
+];
+
+void main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'should_pause_on_exit_test.dart',
+      pause_on_start: true,
+      pause_on_exit: true,
+      testeeConcurrent: testMain,
+    );
diff --git a/pkg/vm_service/tool/common/parser.dart b/pkg/vm_service/tool/common/parser.dart
index 08d3709..233320a 100644
--- a/pkg/vm_service/tool/common/parser.dart
+++ b/pkg/vm_service/tool/common/parser.dart
@@ -167,6 +167,23 @@
         .trim();
   }
 
+  String? consumeString() {
+    StringBuffer buf = StringBuffer();
+    String startQuotation = advance()!.text!;
+    if (startQuotation != '"' && startQuotation != "'") {
+      return null;
+    }
+    while (peek()!.text != startQuotation) {
+      Token t = advance()!;
+      if (t.text == null) {
+        throw FormatException('Reached EOF');
+      }
+      buf.write('${t.text} ');
+    }
+    advance();
+    return buf.toString().trim();
+  }
+
   void validate(bool result, String message) {
     if (!result) throw 'expected ${message}';
   }
diff --git a/pkg/vm_service/tool/dart/generate_dart.dart b/pkg/vm_service/tool/dart/generate_dart.dart
index 844b1ff..4f2eb16 100644
--- a/pkg/vm_service/tool/dart/generate_dart.dart
+++ b/pkg/vm_service/tool/dart/generate_dart.dart
@@ -725,6 +725,9 @@
             }
             return result;
           };
+          if (m.deprecated) {
+            gen.writeln("// ignore: deprecated_member_use_from_same_package");
+          }
           gen.write("response = await _serviceImplementation.${m.name}(");
           // Positional args
           m.args.where((arg) => !arg.optional).forEach((MethodArg arg) {
@@ -1130,6 +1133,8 @@
   final String? docs;
 
   MemberType returnType = MemberType();
+  bool get deprecated => deprecationMessage != null;
+  String? deprecationMessage;
   List<MethodArg> args = [];
 
   Method(this.name, String definition, [this.docs]) {
@@ -1196,6 +1201,9 @@
       }
       if (_docs.isNotEmpty) gen.writeDocs(_docs);
     }
+    if (deprecated) {
+      gen.writeln("@Deprecated('$deprecationMessage')");
+    }
     if (withOverrides) gen.writeln('@override');
     gen.write('Future<${returnType.name}> ${name}(');
     bool startedOptional = false;
@@ -2128,7 +2136,12 @@
   void parseInto(Method method) {
     // method is return type, name, (, args )
     // args is type name, [optional], comma
-
+    if (peek()?.text?.startsWith('@deprecated') ?? false) {
+      advance();
+      expect('(');
+      method.deprecationMessage = consumeString()!;
+      expect(')');
+    }
     method.returnType.parse(this, isReturnType: true);
 
     Token t = expectName();
diff --git a/pkg/vm_service/tool/java/generate_java.dart b/pkg/vm_service/tool/java/generate_java.dart
index 9ef243d..c80a481 100644
--- a/pkg/vm_service/tool/java/generate_java.dart
+++ b/pkg/vm_service/tool/java/generate_java.dart
@@ -496,6 +496,7 @@
   final String? docs;
 
   MemberType returnType = MemberType();
+  bool deprecated = false;
   List<MethodArg> args = [];
 
   Method(this.name, String definition, [this.docs]) {
@@ -606,7 +607,7 @@
         }
       }
       writer.addLine('request("$name", params, consumer);');
-    }, javadoc: javadoc.toString());
+    }, javadoc: javadoc.toString(), isDeprecated: deprecated);
   }
 
   void _parse(Token? token) {
@@ -647,6 +648,13 @@
     // method is return type, name, (, args )
     // args is type name, [optional], comma
 
+    if (peek()?.text?.startsWith('@deprecated') ?? false) {
+      advance();
+      expect('(');
+      consumeString();
+      expect(')');
+      method.deprecated = true;
+    }
     method.returnType.parse(this);
 
     Token t = expectName();
diff --git a/pkg/vm_service/tool/java/src_gen_java.dart b/pkg/vm_service/tool/java/src_gen_java.dart
index b67c203..a2e62e5 100644
--- a/pkg/vm_service/tool/java/src_gen_java.dart
+++ b/pkg/vm_service/tool/java/src_gen_java.dart
@@ -214,6 +214,7 @@
     String? modifiers = 'public',
     String? returnType = 'void',
     bool isOverride = false,
+    bool isDeprecated = false,
   }) {
     var methodDecl = StringBuffer();
     if (javadoc != null && javadoc.isNotEmpty) {
@@ -223,6 +224,9 @@
           .forEach((line) => methodDecl.writeln('   * $line'.trimRight()));
       methodDecl.writeln('   */');
     }
+    if (isDeprecated) {
+      methodDecl.writeln('  @Deprecated');
+    }
     if (isOverride) {
       methodDecl.writeln('  @Override');
     }
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index 4ad1d93..7b1f275 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
     final result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], 'Version');
     expect(result['major'], 3);
-    expect(result['minor'], 52);
+    expect(result['minor'], 53);
     expect(result['_privateMajor'], 0);
     expect(result['_privateMinor'], 0);
   },
diff --git a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
index 12ffc1c..e9c87c9 100644
--- a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
     final result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], equals('Version'));
     expect(result['major'], equals(3));
-    expect(result['minor'], equals(52));
+    expect(result['minor'], equals(53));
     expect(result['_privateMajor'], equals(0));
     expect(result['_privateMinor'], equals(0));
   },
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 1dbf213..6decb04 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -132,6 +132,20 @@
   }
 }
 
+Representation FlowGraph::UnboxedFieldRepresentationOf(const Field& field) {
+  switch (field.UnboxedFieldCid()) {
+    case kDoubleCid:
+      return kUnboxedDouble;
+    case kFloat32x4Cid:
+      return kUnboxedFloat32x4;
+    case kFloat64x2Cid:
+      return kUnboxedFloat64x2;
+    default:
+      RELEASE_ASSERT(field.is_non_nullable_integer());
+      return kUnboxedInt64;
+  }
+}
+
 void FlowGraph::ReplaceCurrentInstruction(ForwardInstructionIterator* iterator,
                                           Instruction* current,
                                           Instruction* replacement) {
diff --git a/runtime/vm/compiler/backend/flow_graph.h b/runtime/vm/compiler/backend/flow_graph.h
index 2c82c13..815b361 100644
--- a/runtime/vm/compiler/backend/flow_graph.h
+++ b/runtime/vm/compiler/backend/flow_graph.h
@@ -157,6 +157,8 @@
 
   static Representation ReturnRepresentationOf(const Function& function);
 
+  static Representation UnboxedFieldRepresentationOf(const Field& field);
+
   // The number of variables (or boxes) inside the functions frame - meaning
   // below the frame pointer.  This does not include the expression stack.
   intptr_t num_stack_locals() const {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 88106b2..ca16d66 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -203,6 +203,30 @@
   ArchSpecificInitialization();
 }
 
+bool FlowGraphCompiler::IsUnboxedField(const Field& field) {
+  // The `field.is_non_nullable_integer()` is set in the kernel loader and can
+  // only be set if we consume a AOT kernel (annotated with inferred types).
+  ASSERT(!field.is_non_nullable_integer() || FLAG_precompiled_mode);
+  const bool valid_class =
+      ((SupportsUnboxedDoubles() && (field.guarded_cid() == kDoubleCid)) ||
+       (SupportsUnboxedSimd128() && (field.guarded_cid() == kFloat32x4Cid)) ||
+       (SupportsUnboxedSimd128() && (field.guarded_cid() == kFloat64x2Cid)) ||
+       field.is_non_nullable_integer());
+  return field.is_unboxing_candidate() && !field.is_nullable() && valid_class;
+}
+
+bool FlowGraphCompiler::IsPotentialUnboxedField(const Field& field) {
+  if (FLAG_precompiled_mode) {
+    // kernel_loader.cc:ReadInferredType sets the guarded cid for fields based
+    // on inferred types from TFA (if available). The guarded cid is therefore
+    // proven to be correct.
+    return IsUnboxedField(field);
+  }
+  return field.is_unboxing_candidate() &&
+         (FlowGraphCompiler::IsUnboxedField(field) ||
+          (field.guarded_cid() == kIllegalCid));
+}
+
 void FlowGraphCompiler::InitCompiler() {
   compressed_stackmaps_builder_ =
       new (zone()) CompressedStackMapsBuilder(zone());
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index e195a18..5d9b0ad 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -465,6 +465,9 @@
   static bool SupportsHardwareDivision();
   static bool CanConvertInt64ToDouble();
 
+  static bool IsUnboxedField(const Field& field);
+  static bool IsPotentialUnboxedField(const Field& field);
+
   // Accessors.
   compiler::Assembler* assembler() const { return assembler_; }
   const ParsedFunction& parsed_function() const { return parsed_function_; }
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 4ca03ed..e901f3b 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -894,17 +894,17 @@
 
 bool LoadFieldInstr::IsUnboxedDartFieldLoad() const {
   return slot().representation() == kTagged && slot().IsDartField() &&
-         slot().IsUnboxed();
+         FlowGraphCompiler::IsUnboxedField(slot().field());
 }
 
 bool LoadFieldInstr::IsPotentialUnboxedDartFieldLoad() const {
   return slot().representation() == kTagged && slot().IsDartField() &&
-         slot().IsPotentialUnboxed();
+         FlowGraphCompiler::IsPotentialUnboxedField(slot().field());
 }
 
 Representation LoadFieldInstr::representation() const {
   if (IsUnboxedDartFieldLoad() && CompilerState::Current().is_optimizing()) {
-    return slot().UnboxedRepresentation();
+    return FlowGraph::UnboxedFieldRepresentationOf(slot().field());
   }
   return slot().representation();
 }
@@ -963,12 +963,12 @@
 
 bool StoreInstanceFieldInstr::IsUnboxedDartFieldStore() const {
   return slot().representation() == kTagged && slot().IsDartField() &&
-         slot().IsUnboxed();
+         FlowGraphCompiler::IsUnboxedField(slot().field());
 }
 
 bool StoreInstanceFieldInstr::IsPotentialUnboxedDartFieldStore() const {
   return slot().representation() == kTagged && slot().IsDartField() &&
-         slot().IsPotentialUnboxed();
+         FlowGraphCompiler::IsPotentialUnboxedField(slot().field());
 }
 
 Representation StoreInstanceFieldInstr::RequiredInputRepresentation(
@@ -979,7 +979,7 @@
     return kTagged;
   }
   if (IsUnboxedDartFieldStore() && CompilerState::Current().is_optimizing()) {
-    return slot().UnboxedRepresentation();
+    return FlowGraph::UnboxedFieldRepresentationOf(slot().field());
   }
   return slot().representation();
 }
@@ -6181,7 +6181,7 @@
 }
 
 bool Utf8ScanInstr::IsScanFlagsUnboxed() const {
-  return scan_flags_field_.IsUnboxed();
+  return FlowGraphCompiler::IsUnboxedField(scan_flags_field_.field());
 }
 
 InvokeMathCFunctionInstr::InvokeMathCFunctionInstr(
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index 75afb9a..b4b9920 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -331,58 +331,6 @@
   return SlotCache::Instance(thread).Canonicalize(slot);
 }
 
-FieldGuardState::FieldGuardState(const Field& field)
-    : state_(GuardedCidBits::encode(field.guarded_cid()) |
-             IsNonNullableIntegerBit::encode(field.is_non_nullable_integer()) |
-             IsUnboxingCandidateBit::encode(field.is_unboxing_candidate()) |
-             IsNullableBit::encode(field.is_nullable())) {}
-
-bool FieldGuardState::IsUnboxed() const {
-  ASSERT(!is_non_nullable_integer() || FLAG_precompiled_mode);
-  const bool valid_class = ((FlowGraphCompiler::SupportsUnboxedDoubles() &&
-                             (guarded_cid() == kDoubleCid)) ||
-                            (FlowGraphCompiler::SupportsUnboxedSimd128() &&
-                             (guarded_cid() == kFloat32x4Cid)) ||
-                            (FlowGraphCompiler::SupportsUnboxedSimd128() &&
-                             (guarded_cid() == kFloat64x2Cid)) ||
-                            is_non_nullable_integer());
-  return is_unboxing_candidate() && !is_nullable() && valid_class;
-}
-
-bool FieldGuardState::IsPotentialUnboxed() const {
-  if (FLAG_precompiled_mode) {
-    // kernel_loader.cc:ReadInferredType sets the guarded cid for fields based
-    // on inferred types from TFA (if available). The guarded cid is therefore
-    // proven to be correct.
-    return IsUnboxed();
-  }
-
-  return is_unboxing_candidate() &&
-         (IsUnboxed() || (guarded_cid() == kIllegalCid));
-}
-
-bool Slot::IsUnboxed() const {
-  return field_guard_state().IsUnboxed();
-}
-
-bool Slot::IsPotentialUnboxed() const {
-  return field_guard_state().IsPotentialUnboxed();
-}
-
-Representation Slot::UnboxedRepresentation() const {
-  switch (field_guard_state().guarded_cid()) {
-    case kDoubleCid:
-      return kUnboxedDouble;
-    case kFloat32x4Cid:
-      return kUnboxedFloat32x4;
-    case kFloat64x2Cid:
-      return kUnboxedFloat64x2;
-    default:
-      RELEASE_ASSERT(field_guard_state().is_non_nullable_integer());
-      return kUnboxedInt64;
-  }
-}
-
 const Slot& Slot::Get(const Field& field,
                       const ParsedFunction* parsed_function) {
   Thread* thread = Thread::Current();
@@ -406,18 +354,16 @@
     is_nullable = false;
   }
 
-  FieldGuardState field_guard_state(field);
-
   bool used_guarded_state = false;
-  if (field_guard_state.guarded_cid() != kIllegalCid &&
-      field_guard_state.guarded_cid() != kDynamicCid) {
+  if (field.guarded_cid() != kIllegalCid &&
+      field.guarded_cid() != kDynamicCid) {
     // Use guarded state if it is more precise then what we already have.
     if (nullable_cid == kDynamicCid) {
-      nullable_cid = field_guard_state.guarded_cid();
+      nullable_cid = field.guarded_cid();
       used_guarded_state = true;
     }
 
-    if (is_nullable && !field_guard_state.is_nullable()) {
+    if (is_nullable && !field.is_nullable()) {
       is_nullable = false;
       used_guarded_state = true;
     }
@@ -431,10 +377,10 @@
     used_guarded_state = false;
   }
 
-  if (field_guard_state.is_non_nullable_integer()) {
+  if (field.is_non_nullable_integer()) {
     ASSERT(FLAG_precompiled_mode);
     is_nullable = false;
-    if (field_guard_state.IsUnboxed()) {
+    if (FlowGraphCompiler::IsUnboxedField(field)) {
       rep = kUnboxedInt64;
     }
   }
@@ -451,7 +397,7 @@
           IsSentinelVisibleBit::encode(field.is_late() && field.is_final() &&
                                        !field.has_initializer()),
       nullable_cid, compiler::target::Field::OffsetOf(field), &field, &type,
-      rep, field_guard_state));
+      rep));
 
   // If properties of this slot were based on the guarded state make sure
   // to add the field to the list of guarded fields. Note that during background
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index 88c1dd8..a31e9a9 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -166,35 +166,6 @@
   NONNULLABLE_BOXED_NATIVE_SLOTS_LIST(V)                                       \
   UNBOXED_NATIVE_SLOTS_LIST(V)
 
-class FieldGuardState {
- public:
-  FieldGuardState() : state_(0) {}
-  explicit FieldGuardState(const Field& field);
-
-  intptr_t guarded_cid() const { return GuardedCidBits::decode(state_); }
-  bool is_non_nullable_integer() const {
-    return IsNonNullableIntegerBit::decode(state_);
-  }
-  bool is_unboxing_candidate() const {
-    return IsUnboxingCandidateBit::decode(state_);
-  }
-  bool is_nullable() const { return IsNullableBit::decode(state_); }
-
-  bool IsUnboxed() const;
-  bool IsPotentialUnboxed() const;
-
- private:
-  using GuardedCidBits = BitField<int32_t, ClassIdTagType, 0, 16>;
-  using IsNonNullableIntegerBit =
-      BitField<int32_t, bool, GuardedCidBits::kNextBit, 1>;
-  using IsUnboxingCandidateBit =
-      BitField<int32_t, bool, IsNonNullableIntegerBit::kNextBit, 1>;
-  using IsNullableBit =
-      BitField<int32_t, bool, IsUnboxingCandidateBit::kNextBit, 1>;
-
-  const int32_t state_;
-};
-
 // Slot is an abstraction that describes an readable (and possibly writeable)
 // location within an object.
 //
@@ -327,10 +298,6 @@
     return kind() == Kind::kCapturedVariable || kind() == Kind::kContext_parent;
   }
 
-  bool IsUnboxed() const;
-  bool IsPotentialUnboxed() const;
-  Representation UnboxedRepresentation() const;
-
  private:
   friend class FlowGraphDeserializer;  // For GetNativeSlot.
 
@@ -340,14 +307,12 @@
        intptr_t offset_in_bytes,
        const void* data,
        const AbstractType* static_type,
-       Representation representation,
-       const FieldGuardState& field_guard_state = FieldGuardState())
+       Representation representation)
       : kind_(kind),
         flags_(bits),
         cid_(cid),
         offset_in_bytes_(offset_in_bytes),
         representation_(representation),
-        field_guard_state_(field_guard_state),
         data_(data),
         static_type_(static_type) {}
 
@@ -358,8 +323,7 @@
              other.offset_in_bytes_,
              other.data_,
              other.static_type_,
-             other.representation_,
-             other.field_guard_state_) {}
+             other.representation_) {}
 
   using IsImmutableBit = BitField<int8_t, bool, 0, 1>;
   using IsNullableBit = BitField<int8_t, bool, IsImmutableBit::kNextBit, 1>;
@@ -378,10 +342,6 @@
   static AcqRelAtomic<Slot*> native_fields_;
   static const Slot& GetNativeSlot(Kind kind);
 
-  const FieldGuardState& field_guard_state() const {
-    return field_guard_state_;
-  }
-
   const Kind kind_;
   const int8_t flags_;        // is_immutable, is_nullable
   const ClassIdTagType cid_;  // Concrete cid of a value or kDynamicCid.
@@ -389,8 +349,6 @@
   const intptr_t offset_in_bytes_;
   const Representation representation_;
 
-  const FieldGuardState field_guard_state_;
-
   // Kind dependent data:
   //   - name as a Dart String object for local variables;
   //   - name as a C string for native slots;
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index a0da87b..85ed2b5 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -1050,8 +1050,7 @@
   // [Intrinsifier::CanIntrinsifyFieldAccessor])
   auto zone = flow_graph->zone();
   const auto& function = flow_graph->function();
-  ASSERT(
-      Intrinsifier::CanIntrinsifyFieldAccessor(flow_graph->parsed_function()));
+  ASSERT(Intrinsifier::CanIntrinsifyFieldAccessor(function));
 
   auto& field = Field::Handle(zone, function.accessor_field());
   if (CompilerState::Current().should_clone_fields()) {
@@ -1073,10 +1072,12 @@
 
   // We only support cases where we do not have to create a box (whose
   // allocation could fail).
-  ASSERT(function.HasUnboxedReturnValue() || !slot.IsUnboxed());
+  ASSERT(function.HasUnboxedReturnValue() ||
+         !FlowGraphCompiler::IsUnboxedField(field));
 
   // We might need to unbox the field value before returning.
-  if (function.HasUnboxedReturnValue() && !slot.IsUnboxed()) {
+  if (function.HasUnboxedReturnValue() &&
+      !FlowGraphCompiler::IsUnboxedField(field)) {
     ASSERT(FLAG_precompiled_mode);
     field_value = builder.AddUnboxInstr(
         FlowGraph::ReturnRepresentationOf(flow_graph->function()),
@@ -1092,19 +1093,21 @@
   // [Intrinsifier::CanIntrinsifyFieldAccessor])
   auto zone = flow_graph->zone();
   const auto& function = flow_graph->function();
-  ASSERT(
-      Intrinsifier::CanIntrinsifyFieldAccessor(flow_graph->parsed_function()));
+  ASSERT(Intrinsifier::CanIntrinsifyFieldAccessor(function));
 
   auto& field = Field::Handle(zone, function.accessor_field());
   if (CompilerState::Current().should_clone_fields()) {
     field = field.CloneFromOriginal();
   }
   ASSERT(field.is_instance() && !field.is_final());
-  const auto& slot = Slot::Get(field, &flow_graph->parsed_function());
-  ASSERT(!function.HasUnboxedParameters() || slot.IsUnboxed());
+  ASSERT(!function.HasUnboxedParameters() ||
+         FlowGraphCompiler::IsUnboxedField(field));
 
-  const auto barrier_mode =
-      slot.IsUnboxed() ? kNoStoreBarrier : kEmitStoreBarrier;
+  const auto& slot = Slot::Get(field, &flow_graph->parsed_function());
+
+  const auto barrier_mode = FlowGraphCompiler::IsUnboxedField(field)
+                                ? kNoStoreBarrier
+                                : kEmitStoreBarrier;
 
   flow_graph->CreateCommonConstants();
   GraphEntryInstr* graph_entry = flow_graph->graph_entry();
@@ -1115,13 +1118,14 @@
   auto value = builder.AddParameter(1, /*with_frame=*/false);
   VerifyParameterIsBoxed(&builder, 0);
 
-  if (!function.HasUnboxedParameters() && slot.IsUnboxed()) {
+  if (!function.HasUnboxedParameters() &&
+      FlowGraphCompiler::IsUnboxedField(field)) {
     // We do not support storing to possibly guarded fields in JIT in graph
     // intrinsics.
     ASSERT(FLAG_precompiled_mode);
-    value =
-        builder.AddUnboxInstr(slot.UnboxedRepresentation(), new Value(value),
-                              /*is_checked=*/true);
+    value = builder.AddUnboxInstr(
+        FlowGraph::UnboxedFieldRepresentationOf(field), new Value(value),
+        /*is_checked=*/true);
   }
 
   builder.AddInstruction(new (zone) StoreInstanceFieldInstr(
diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc
index 4ba80d9f..f343f73 100644
--- a/runtime/vm/compiler/intrinsifier.cc
+++ b/runtime/vm/compiler/intrinsifier.cc
@@ -25,9 +25,7 @@
 
 namespace compiler {
 
-bool Intrinsifier::CanIntrinsify(const ParsedFunction& parsed_function) {
-  const Function& function = parsed_function.function();
-
+bool Intrinsifier::CanIntrinsify(const Function& function) {
   if (FLAG_trace_intrinsifier) {
     THR_Print("CanIntrinsify %s ->", function.ToQualifiedCString());
   }
@@ -47,8 +45,7 @@
     }
     return false;
   }
-  if (!function.is_intrinsic() &&
-      !CanIntrinsifyFieldAccessor(parsed_function)) {
+  if (!function.is_intrinsic() && !CanIntrinsifyFieldAccessor(function)) {
     if (FLAG_trace_intrinsifier) {
       THR_Print("No, not intrinsic function.\n");
     }
@@ -76,10 +73,7 @@
   return true;
 }
 
-bool Intrinsifier::CanIntrinsifyFieldAccessor(
-    const ParsedFunction& parsed_function) {
-  const Function& function = parsed_function.function();
-
+bool Intrinsifier::CanIntrinsifyFieldAccessor(const Function& function) {
   const bool is_getter = function.IsImplicitGetterFunction();
   const bool is_setter = function.IsImplicitSetterFunction();
   if (!is_getter && !is_setter) return false;
@@ -103,13 +97,11 @@
   // We only graph intrinsify implicit instance getters/setter for now.
   if (!field.is_instance()) return false;
 
-  const auto& slot = Slot::Get(field, &parsed_function);
-
   if (is_getter) {
     // We don't support complex getter cases.
     if (field.is_late() || field.needs_load_guard()) return false;
 
-    if (slot.IsPotentialUnboxed()) {
+    if (FlowGraphCompiler::IsPotentialUnboxedField(field)) {
       if (function.HasUnboxedReturnValue()) {
         // In AOT mode: Unboxed fields contain the unboxed value and can be
         // returned in unboxed form.
@@ -144,7 +136,7 @@
     // avoid the need for boxing (which we cannot do in the intrinsic).
     if (function.HasUnboxedParameters()) {
       ASSERT(FLAG_precompiled_mode);
-      if (!slot.IsUnboxed()) {
+      if (!FlowGraphCompiler::IsUnboxedField(field)) {
         return false;
       }
     }
@@ -261,7 +253,8 @@
 // Returns true if fall-through code can be omitted.
 bool Intrinsifier::Intrinsify(const ParsedFunction& parsed_function,
                               FlowGraphCompiler* compiler) {
-  if (!CanIntrinsify(parsed_function)) {
+  const Function& function = parsed_function.function();
+  if (!CanIntrinsify(function)) {
     return false;
   }
 
@@ -269,7 +262,6 @@
     return compiler->intrinsic_slow_path_label()->IsUnused();
   }
 
-  const Function& function = parsed_function.function();
 #if !defined(HASH_IN_OBJECT_HEADER)
   // These two are more complicated on 32 bit platforms, where the
   // identity hash is not stored in the header of the object.  We
diff --git a/runtime/vm/compiler/intrinsifier.h b/runtime/vm/compiler/intrinsifier.h
index 681b606..835f73f 100644
--- a/runtime/vm/compiler/intrinsifier.h
+++ b/runtime/vm/compiler/intrinsifier.h
@@ -35,8 +35,8 @@
 
  private:
   friend class GraphIntrinsifier;  // For CanIntrinsifyFieldAccessor.
-  static bool CanIntrinsify(const ParsedFunction& parsed_function);
-  static bool CanIntrinsifyFieldAccessor(const ParsedFunction& parsed_function);
+  static bool CanIntrinsify(const Function& function);
+  static bool CanIntrinsifyFieldAccessor(const Function& function);
 };
 
 }  // namespace compiler
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index b7576a4..dba5444 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -5145,6 +5145,44 @@
   PrintSuccess(js);
 }
 
+static const MethodParameter* const set_isolate_pause_mode_params[] = {
+    ISOLATE_PARAMETER,
+    new EnumParameter("exceptionPauseMode", false, exception_pause_mode_names),
+    new BoolParameter("shouldPauseOnExit", false),
+    nullptr,
+};
+
+static void SetIsolatePauseMode(Thread* thread, JSONStream* js) {
+  bool state_changed = false;
+  const char* exception_pause_mode = js->LookupParam("exceptionPauseMode");
+  if (exception_pause_mode != nullptr) {
+    Dart_ExceptionPauseInfo info =
+        EnumMapper(exception_pause_mode, exception_pause_mode_names,
+                   exception_pause_mode_values);
+    if (info == kInvalidExceptionPauseInfo) {
+      PrintInvalidParamError(js, "exceptionPauseMode");
+      return;
+    }
+    Isolate* isolate = thread->isolate();
+    isolate->debugger()->SetExceptionPauseInfo(info);
+    state_changed = true;
+  }
+
+  const char* pause_isolate_on_exit = js->LookupParam("shouldPauseOnExit");
+  if (pause_isolate_on_exit != nullptr) {
+    bool enable = BoolParameter::Parse(pause_isolate_on_exit, false);
+    thread->isolate()->message_handler()->set_should_pause_on_exit(enable);
+    state_changed = true;
+  }
+
+  if (state_changed && Service::debug_stream.enabled()) {
+    ServiceEvent event(thread->isolate(),
+                       ServiceEvent::kDebuggerSettingsUpdate);
+    Service::HandleEvent(&event);
+  }
+  PrintSuccess(js);
+}
+
 static const MethodParameter* const set_breakpoint_state_params[] = {
     ISOLATE_PARAMETER,
     new IdParameter("breakpointId", true),
@@ -5561,6 +5599,8 @@
     set_breakpoint_state_params },
   { "setExceptionPauseMode", SetExceptionPauseMode,
     set_exception_pause_mode_params },
+  { "setIsolatePauseMode", SetIsolatePauseMode,
+    set_isolate_pause_mode_params },
   { "setFlag", SetFlag,
     set_flags_params },
   { "setLibraryDebuggable", SetLibraryDebuggable,
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index d519124..59e9e24 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -15,7 +15,7 @@
 namespace dart {
 
 #define SERVICE_PROTOCOL_MAJOR_VERSION 3
-#define SERVICE_PROTOCOL_MINOR_VERSION 52
+#define SERVICE_PROTOCOL_MINOR_VERSION 53
 
 class Array;
 class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index ba4add1..0865d15 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.52
+# Dart VM Service Protocol 3.53
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.52_ of the Dart VM Service Protocol. This
+This document describes of _version 3.53_ of the Dart VM Service Protocol. This
 protocol is used to communicate with a running Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
@@ -1378,6 +1378,7 @@
 ### setExceptionPauseMode
 
 ```
+@deprecated('Use setIsolatePauseMode instead')
 Success|Sentinel setExceptionPauseMode(string isolateId,
                                        ExceptionPauseMode mode)
 ```
@@ -1394,6 +1395,31 @@
 If _isolateId_ refers to an isolate which has exited, then the
 _Collected_ [Sentinel](#sentinel) is returned.
 
+### setIsolatePauseMode
+
+```
+Success|Sentinel setIsolatePauseMode(string isolateId,
+                                     ExceptionPauseMode exceptionPauseMode [optional],
+                                     bool shouldPauseOnExit [optional])
+```
+
+The _setIsolatePauseMode_ RPC is used to control if or when an isolate will
+pause due to a change in execution state.
+
+The _shouldPauseOnExit_ parameter specify whether the target isolate should pause on exit.
+
+The _setExceptionPauseMode_ RPC is used to control if an isolate pauses when
+an exception is thrown.
+
+mode | meaning
+---- | -------
+None | Do not pause isolate on thrown exceptions
+Unhandled | Pause isolate on unhandled exceptions
+All  | Pause isolate on all thrown exceptions
+
+If _isolateId_ refers to an isolate which has exited, then the
+_Collected_ [Sentinel](#sentinel) is returned.
+
 ### setFlag
 
 ```
@@ -1420,6 +1446,7 @@
    provided value. If set to false when the profiler is already running, the
    profiler will be stopped but may not free its sample buffer depending on
    platform limitations.
+ * Isolate pause settings will only be applied to newly spawned isolates.
 
 See [Success](#success).
 
@@ -4235,4 +4262,5 @@
 3.50 | Added `returnType`, `parameters`, and `typeParameters` to `@Instance`, and `implicit` to `@Function`. Added `Parameter` type.
 3.51 | Added optional `reportLines` parameter to `getSourceReport` RPC.
 3.52 | Added `lookupResolvedPackageUris` and `lookupPackageUris` RPCs and `UriList` type.
+3.53 | Added `setIsolatePauseMode` RPC.
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
index 6ff9de7..c5881ab 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
@@ -17,7 +17,6 @@
     show
         AssertionErrorImpl,
         BooleanConversionAssertionError,
-        CastErrorImpl,
         DartIterator,
         DeferredNotLoadedError,
         TypeErrorImpl,
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
index c32af9b..3fc8f51 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
@@ -699,15 +699,6 @@
   String toString() => _message;
 }
 
-/// Thrown by the 'as' operator if the cast isn't valid.
-class CastErrorImpl extends Error implements CastError, TypeError {
-  final String _message;
-
-  CastErrorImpl(this._message);
-
-  String toString() => _message;
-}
-
 class FallThroughErrorImplementation extends FallThroughError {
   String toString() => "Switch case fall-through.";
 }
diff --git a/sdk/lib/io/overrides.dart b/sdk/lib/io/overrides.dart
index 65e7acf..c97e84d 100644
--- a/sdk/lib/io/overrides.dart
+++ b/sdk/lib/io/overrides.dart
@@ -90,7 +90,12 @@
       // ServerSocket
       Future<ServerSocket> Function(dynamic, int,
               {int backlog, bool v6Only, bool shared})?
-          serverSocketBind}) {
+          serverSocketBind,
+
+      // Standard Streams
+      Stdin Function()? stdin,
+      Stdout Function()? stdout,
+      Stdout Function()? stderr}) {
     IOOverrides overrides = new _IOOverridesScope(
       // Directory
       createDirectory,
@@ -124,6 +129,11 @@
 
       // ServerSocket
       serverSocketBind,
+
+      // Standard streams
+      stdin,
+      stdout,
+      stderr,
     );
     return _asyncRunZoned<R>(body, zoneValues: {_ioOverridesToken: overrides});
   }
@@ -286,6 +296,32 @@
     return ServerSocket._bind(address, port,
         backlog: backlog, v6Only: v6Only, shared: shared);
   }
+
+  // Standard streams
+
+  /// The standard input stream of data read by this program.
+  ///
+  /// When this override is installed, this getter overrides the behavior of
+  /// the top-level `stdin` getter.
+  Stdin get stdin {
+    return _stdin;
+  }
+
+  /// The standard output stream of data written by this program.
+  ///
+  /// When this override is installed, this getter overrides the behavior of
+  /// the top-level `stdout` getter.
+  Stdout get stdout {
+    return _stdout;
+  }
+
+  /// The standard output stream of errors written by this program.
+  ///
+  /// When this override is installed, this getter overrides the behavior of
+  /// the top-level `stderr` getter.
+  Stdout get stderr {
+    return _stderr;
+  }
 }
 
 class _IOOverridesScope extends IOOverrides {
@@ -327,6 +363,11 @@
   Future<ServerSocket> Function(dynamic, int,
       {int backlog, bool v6Only, bool shared})? _serverSocketBind;
 
+  // Standard streams
+  Stdin Function()? _stdin;
+  Stdout Function()? _stdout;
+  Stdout Function()? _stderr;
+
   _IOOverridesScope(
     // Directory
     this._createDirectory,
@@ -360,6 +401,11 @@
 
     // ServerSocket
     this._serverSocketBind,
+
+    // Standard streams
+    this._stdin,
+    this._stdout,
+    this._stderr,
   );
 
   // Directory
@@ -514,4 +560,21 @@
     return super.serverSocketBind(address, port,
         backlog: backlog, v6Only: v6Only, shared: shared);
   }
+
+  // Standard streams
+
+  @override
+  Stdin get stdin {
+    return _stdin?.call() ?? _previous?.stdin ?? super.stdin;
+  }
+
+  @override
+  Stdout get stdout {
+    return _stdout?.call() ?? _previous?.stdout ?? super.stdout;
+  }
+
+  @override
+  Stdout get stderr {
+    return _stderr?.call() ?? _previous?.stderr ?? super.stderr;
+  }
 }
diff --git a/sdk/lib/io/stdio.dart b/sdk/lib/io/stdio.dart
index 0ea8448..42b7bc2 100644
--- a/sdk/lib/io/stdio.dart
+++ b/sdk/lib/io/stdio.dart
@@ -362,9 +362,9 @@
   String toString() => "StdioType: $name";
 }
 
-Stdin? _stdin;
-Stdout? _stdout;
-Stdout? _stderr;
+final Stdin _stdin = _StdIOUtils._getStdioInputStream(_stdinFD);
+final Stdout _stdout = _StdIOUtils._getStdioOutputStream(_stdoutFD);
+final Stdout _stderr = _StdIOUtils._getStdioOutputStream(_stderrFD);
 
 // These may be set to different values by the embedder by calling
 // _setStdioFDs when initializing dart:io.
@@ -381,7 +381,7 @@
 
 /// The standard input stream of data read by this program.
 Stdin get stdin {
-  return _stdin ??= _StdIOUtils._getStdioInputStream(_stdinFD);
+  return IOOverrides.current?.stdin ?? _stdin;
 }
 
 /// The standard output stream of data written by this program.
@@ -390,7 +390,7 @@
 /// result in an unhandled asynchronous error unless there is an error handler
 /// on `done`.
 Stdout get stdout {
-  return _stdout ??= _StdIOUtils._getStdioOutputStream(_stdoutFD);
+  return IOOverrides.current?.stdout ?? _stdout;
 }
 
 /// The standard output stream of errors written by this program.
@@ -399,7 +399,7 @@
 /// result in an unhandled asynchronous error unless there is an error handler
 /// on `done`.
 Stdout get stderr {
-  return _stderr ??= _StdIOUtils._getStdioOutputStream(_stderrFD);
+  return IOOverrides.current?.stderr ?? _stderr;
 }
 
 /// Whether a stream is attached to a file, pipe, terminal, or
diff --git a/tests/standalone/io/io_override_test.dart b/tests/standalone/io/io_override_test.dart
index 03c41af..fb8c780 100644
--- a/tests/standalone/io/io_override_test.dart
+++ b/tests/standalone/io/io_override_test.dart
@@ -175,7 +175,30 @@
   throw "";
 }
 
+class StdinMock extends Stream<List<int>> implements Stdin {
+  bool echoMode = false;
+  bool lineMode = false;
+  bool get hasTerminal => throw "";
+  bool get supportsAnsiEscapes => throw "";
+
+  int readByteSync() => throw "";
+  String readLineSync(
+          {Encoding encoding = systemEncoding, bool retainNewlines = false}) =>
+      throw "";
+  StreamSubscription<List<int>> listen(void onData(List<int> event)?,
+      {Function? onError, void onDone()?, bool? cancelOnError}) {
+    throw "";
+  }
+}
+
+class StdoutMock implements Stdout {
+  Never noSuchMethod(Invocation i) => throw "";
+}
+
 Future<Null> ioOverridesRunTest() async {
+  StdoutMock stdoutMock = StdoutMock();
+  StdoutMock stderrMock = StdoutMock();
+
   Future<Null> f = IOOverrides.runZoned(
     () async {
       Expect.isTrue(new Directory("directory") is DirectoryMock);
@@ -197,6 +220,9 @@
       asyncExpectThrows(() async => await Socket.connect(null, 0));
       asyncExpectThrows(() async => await Socket.startConnect(null, 0));
       asyncExpectThrows(() async => await ServerSocket.bind(null, 0));
+      Expect.isTrue(stdin is StdinMock);
+      Expect.identical(stdout, stdoutMock);
+      Expect.identical(stderr, stderrMock);
     },
     createDirectory: DirectoryMock.createDirectory,
     getCurrentDirectory: DirectoryMock.getCurrent,
@@ -215,6 +241,9 @@
     socketConnect: socketConnect,
     socketStartConnect: socketStartConnect,
     serverSocketBind: serverSocketBind,
+    stdin: () => StdinMock(),
+    stdout: () => stdoutMock,
+    stderr: () => stderrMock,
   );
   Expect.isFalse(new Directory("directory") is DirectoryMock);
   Expect.isTrue(new Directory("directory") is Directory);
diff --git a/tests/standalone_2/io/io_override_test.dart b/tests/standalone_2/io/io_override_test.dart
index 54f0eb4..5ac4160 100644
--- a/tests/standalone_2/io/io_override_test.dart
+++ b/tests/standalone_2/io/io_override_test.dart
@@ -175,7 +175,30 @@
   return null;
 }
 
+class StdinMock extends Stream<List<int>> implements Stdin {
+  bool echoMode = false;
+  bool lineMode = false;
+  bool get hasTerminal => throw "";
+  bool get supportsAnsiEscapes => throw "";
+
+  int readByteSync() => throw "";
+  String readLineSync(
+          {Encoding encoding = systemEncoding, bool retainNewlines = false}) =>
+      throw "";
+  StreamSubscription<List<int>> listen(void onData(List<int> event),
+      {Function onError, void onDone(), bool cancelOnError}) {
+    throw "";
+  }
+}
+
+class StdoutMock implements Stdout {
+  void noSuchMethod(Invocation i) => throw "";
+}
+
 Future<Null> ioOverridesRunTest() async {
+  StdoutMock stdoutMock = StdoutMock();
+  StdoutMock stderrMock = StdoutMock();
+
   Future<Null> f = IOOverrides.runZoned(
     () async {
       Expect.isTrue(new Directory("directory") is DirectoryMock);
@@ -196,6 +219,9 @@
       Expect.isNull(Socket.connect(null, 0));
       Expect.isNull(Socket.startConnect(null, 0));
       Expect.isNull(ServerSocket.bind(null, 0));
+      Expect.isTrue(stdin is StdinMock);
+      Expect.identical(stdout, stdoutMock);
+      Expect.identical(stderr, stderrMock);
     },
     createDirectory: DirectoryMock.createDirectory,
     getCurrentDirectory: DirectoryMock.getCurrent,
@@ -214,6 +240,9 @@
     socketConnect: socketConnect,
     socketStartConnect: socketStartConnect,
     serverSocketBind: serverSocketBind,
+    stdin: () => StdinMock(),
+    stdout: () => stdoutMock,
+    stderr: () => stderrMock,
   );
   Expect.isFalse(new Directory("directory") is DirectoryMock);
   Expect.isTrue(new Directory("directory") is Directory);
diff --git a/tools/VERSION b/tools/VERSION
index 26d24bd..70b8be2 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 21
+PRERELEASE 22
 PRERELEASE_PATCH 0
\ No newline at end of file