Version 2.12.0-282.0.dev

Merge commit '91be638a56a811b46da88093b16408cea045bbe8' into 'dev'
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index fdde79c..d2fad8a 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -11,8 +11,6 @@
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart' as lsp;
-import 'package:analysis_server/lsp_protocol/protocol_special.dart'
-    show ErrorOr, Either2, Either4;
 import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/lsp/constants.dart' as lsp;
 import 'package:analysis_server/src/lsp/constants.dart';
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index ae5b920..923e178 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -454,33 +454,10 @@
     }
 
     // Prepare bytes of the unlinked bundle - existing or new.
-    // TODO(migration): should not be nullable
-    List<int>? bytes;
-    {
-      bytes = _fsState._byteStore.get(_unlinkedKey!);
-      if (bytes == null || bytes.isEmpty) {
-        CompilationUnit unit = parse();
-        _fsState._logger.run('Create unlinked for $path', () {
-          var unlinkedUnit = serializeAstUnlinked2(unit);
-          var definedNames = computeDefinedNames(unit);
-          var referencedNames = computeReferencedNames(unit).toList();
-          var subtypedNames = computeSubtypedNames(unit).toList();
-          bytes = AnalysisDriverUnlinkedUnitBuilder(
-            unit2: unlinkedUnit,
-            definedTopLevelNames: definedNames.topLevelNames.toList(),
-            definedClassMemberNames: definedNames.classMemberNames.toList(),
-            referencedNames: referencedNames,
-            subtypedNames: subtypedNames,
-          ).toBuffer();
-          _fsState._byteStore.put(_unlinkedKey!, bytes!);
-          counterUnlinkedBytes += bytes!.length;
-          counterUnlinkedLinkedBytes += bytes!.length;
-        });
-      }
-    }
+    var bytes = _getUnlinkedBytes();
 
     // Read the unlinked bundle.
-    _driverUnlinkedUnit = AnalysisDriverUnlinkedUnit.fromBuffer(bytes!);
+    _driverUnlinkedUnit = AnalysisDriverUnlinkedUnit.fromBuffer(bytes);
     _unlinked2 = _driverUnlinkedUnit!.unit2;
     _lineInfo = LineInfo(_unlinked2!.lineStarts);
 
@@ -585,6 +562,33 @@
     return _fsState.getFileForUri(absoluteUri);
   }
 
+  /// Return the bytes of the unlinked summary - existing or new.
+  List<int> _getUnlinkedBytes() {
+    var bytes = _fsState._byteStore.get(_unlinkedKey!);
+    if (bytes != null && bytes.isNotEmpty) {
+      return bytes;
+    }
+
+    var unit = parse();
+    return _fsState._logger.run('Create unlinked for $path', () {
+      var unlinkedUnit = serializeAstUnlinked2(unit);
+      var definedNames = computeDefinedNames(unit);
+      var referencedNames = computeReferencedNames(unit).toList();
+      var subtypedNames = computeSubtypedNames(unit).toList();
+      var bytes = AnalysisDriverUnlinkedUnitBuilder(
+        unit2: unlinkedUnit,
+        definedTopLevelNames: definedNames.topLevelNames.toList(),
+        definedClassMemberNames: definedNames.classMemberNames.toList(),
+        referencedNames: referencedNames,
+        subtypedNames: subtypedNames,
+      ).toBuffer();
+      _fsState._byteStore.put(_unlinkedKey!, bytes);
+      counterUnlinkedBytes += bytes.length;
+      counterUnlinkedLinkedBytes += bytes.length;
+      return bytes;
+    });
+  }
+
   /// Invalidate any data that depends on the current unlinked data of the file,
   /// because [refresh] is going to recompute the unlinked data.
   void _invalidateCurrentUnresolvedData() {
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 4f10340..9cc80b8 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -20,7 +20,6 @@
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 
 /// Instances of the class `ConstantVerifier` traverse an AST structure looking
 /// for additional errors and warnings not covered by the parser and resolver.
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 672647e..4f7bd29 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -4,12 +4,10 @@
 
 import 'dart:collection';
 
-import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -19,8 +17,6 @@
 import 'package:analyzer/src/dart/constant/from_environment_evaluator.dart';
 import 'package:analyzer/src/dart/constant/has_type_parameter_reference.dart';
 import 'package:analyzer/src/dart/constant/potentially_constant.dart';
-import 'package:analyzer/src/dart/constant/utilities.dart';
-import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
@@ -28,8 +24,6 @@
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/engine.dart'
-    show AnalysisEngine, RecordingErrorListener;
 import 'package:analyzer/src/task/api/model.dart';
 
 /// Helper class encapsulating the methods for evaluating constants and
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 54a847a..17860e4 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -31,7 +31,6 @@
 import 'package:analyzer/src/dart/resolver/scope.dart'
     show Namespace, NamespaceBuilder;
 import 'package:analyzer/src/dart/resolver/variance.dart';
-import 'package:analyzer/src/generated/constant.dart' show EvaluationResultImpl;
 import 'package:analyzer/src/generated/element_type_provider.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisOptionsImpl;
diff --git a/pkg/analyzer/lib/src/error/ignore_validator.dart b/pkg/analyzer/lib/src/error/ignore_validator.dart
index 5014a7e..0d02ce8 100644
--- a/pkg/analyzer/lib/src/error/ignore_validator.dart
+++ b/pkg/analyzer/lib/src/error/ignore_validator.dart
@@ -5,7 +5,6 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/source/line_info.dart';
-import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index faa2ee3..922128a 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -8,8 +8,6 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/engine.dart' show RecordingErrorListener;
 import 'package:analyzer/src/generated/source.dart' show Source;
 
 export 'package:analyzer/dart/analysis/declared_variables.dart';
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index ef73ade..99e3884 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -4,9 +4,6 @@
 
 library analyzer.parser;
 
-import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart'
-    as fasta;
-import 'package:_fe_analyzer_shared/src/parser/member_kind.dart' as fasta;
 import 'package:_fe_analyzer_shared/src/parser/parser.dart' as fasta;
 import 'package:_fe_analyzer_shared/src/parser/type_info.dart' as fasta;
 import 'package:analyzer/dart/analysis/features.dart';
diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
index 7db4ea0..f700ddd 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -7,7 +7,6 @@
 import 'package:analyzer/src/dart/element/class_hierarchy.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
-import 'package:analyzer/src/generated/source.dart' show Source;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/test_utilities/mock_sdk_elements.dart';
 
diff --git a/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart b/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
index 5a1d3c3..507ea06 100644
--- a/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
+++ b/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
@@ -6,7 +6,6 @@
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/generated/source.dart';
 
 /// The name and location of a diagnostic name in an ignore comment.
 class DiagnosticName {
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index 89c4c7c..5e0e60d 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -19,7 +19,6 @@
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
-import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index 8bd1850..59a0a74 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -25,7 +25,6 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
-import 'package:analyzer/src/dart/error/lint_codes.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 57914fd..36ae705 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -4,7 +4,6 @@
 
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart' show TokenType;
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
diff --git a/pkg/analyzer/lib/src/workspace/bazel.dart b/pkg/analyzer/lib/src/workspace/bazel.dart
index b7fdff1..b6eda24 100644
--- a/pkg/analyzer/lib/src/workspace/bazel.dart
+++ b/pkg/analyzer/lib/src/workspace/bazel.dart
@@ -8,7 +8,6 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
diff --git a/pkg/analyzer/lib/src/workspace/gn.dart b/pkg/analyzer/lib/src/workspace/gn.dart
index 070c7cd..b1accc8 100644
--- a/pkg/analyzer/lib/src/workspace/gn.dart
+++ b/pkg/analyzer/lib/src/workspace/gn.dart
@@ -6,7 +6,6 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/packages.dart';
-import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
diff --git a/pkg/analyzer/lib/src/workspace/package_build.dart b/pkg/analyzer/lib/src/workspace/package_build.dart
index df4e821..5b49691 100644
--- a/pkg/analyzer/lib/src/workspace/package_build.dart
+++ b/pkg/analyzer/lib/src/workspace/package_build.dart
@@ -6,7 +6,6 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/packages.dart';
-import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index bca7fa6..a559a08 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -15,11 +15,11 @@
   crypto: ^3.0.0-nullsafety.0
   glob: ^2.0.0-nullsafety.0
   meta: ^1.3.0-nullsafety.6
-  package_config: ^1.0.0
+  package_config: ^2.0.0-nullsafety.0
   path: ^1.8.0-nullsafety.3
   pub_semver: ^2.0.0-nullsafety.0
   source_span: ^1.8.0-nullsafety.4
-  watcher: ^0.9.6
+  watcher: ^1.0.0-nullsafety.0
   yaml: ^3.0.0-nullsafety.0
 dev_dependencies:
   analyzer_utilities:
diff --git a/pkg/analyzer/test/dart/analysis/from_environment_evaluator_test.dart b/pkg/analyzer/test/dart/analysis/from_environment_evaluator_test.dart
index f73cbf8..44891cf 100644
--- a/pkg/analyzer/test/dart/analysis/from_environment_evaluator_test.dart
+++ b/pkg/analyzer/test/dart/analysis/from_environment_evaluator_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/constant/from_environment_evaluator.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 0784b9c..e3a6c6a 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/src/generated/java_engine_io.dart';
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
diff --git a/pkg/analyzer/test/generated/class_member_parser_test.dart b/pkg/analyzer/test/generated/class_member_parser_test.dart
index f45c248..25467ad 100644
--- a/pkg/analyzer/test/generated/class_member_parser_test.dart
+++ b/pkg/analyzer/test/generated/class_member_parser_test.dart
@@ -2,12 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:_fe_analyzer_shared/src/scanner/errors.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/generated/error_parser_test.dart b/pkg/analyzer/test/generated/error_parser_test.dart
index 235f297..4889978 100644
--- a/pkg/analyzer/test/generated/error_parser_test.dart
+++ b/pkg/analyzer/test/generated/error_parser_test.dart
@@ -2,13 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:_fe_analyzer_shared/src/scanner/errors.dart';
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/generated/expression_parser_test.dart b/pkg/analyzer/test/generated/expression_parser_test.dart
index b721f79..4dbc53b 100644
--- a/pkg/analyzer/test/generated/expression_parser_test.dart
+++ b/pkg/analyzer/test/generated/expression_parser_test.dart
@@ -4,7 +4,6 @@
 
 import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
     show AbstractScanner;
-import 'package:_fe_analyzer_shared/src/scanner/errors.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -12,7 +11,6 @@
     show InstanceCreationExpressionImpl;
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:pub_semver/src/version.dart';
 import 'package:test/test.dart';
diff --git a/pkg/analyzer/test/generated/parser_test_base.dart b/pkg/analyzer/test/generated/parser_test_base.dart
index 323d52e..b8699be 100644
--- a/pkg/analyzer/test/generated/parser_test_base.dart
+++ b/pkg/analyzer/test/generated/parser_test_base.dart
@@ -20,7 +20,6 @@
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/fasta/ast_builder.dart';
-import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:analyzer/src/generated/parser.dart' as analyzer;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index 939b23e..dab2ec5 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -10,7 +10,6 @@
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/string_source.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:test/test.dart';
diff --git a/pkg/analyzer/test/generated/simple_parser_test.dart b/pkg/analyzer/test/generated/simple_parser_test.dart
index e8b9023..5bdc51f 100644
--- a/pkg/analyzer/test/generated/simple_parser_test.dart
+++ b/pkg/analyzer/test/generated/simple_parser_test.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/source/analysis_options_provider_test.dart b/pkg/analyzer/test/source/analysis_options_provider_test.dart
index ae41532..cd96e3e 100644
--- a/pkg/analyzer/test/source/analysis_options_provider_test.dart
+++ b/pkg/analyzer/test/source/analysis_options_provider_test.dart
@@ -7,7 +7,6 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
-import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/util/yaml.dart';
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index 5f911df..0483996 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -9,7 +9,6 @@
 import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/context/source.dart';
 import 'package:analyzer/src/dart/error/lint_codes.dart';
-import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart
index c262ddd..23722e1 100644
--- a/pkg/analyzer/test/src/dart/analysis/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -12,7 +12,6 @@
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/analysis/status.dart';
-import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index 13f4be9..d96d07f 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -15,7 +15,6 @@
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/library_graph.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisOptions, AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analyzer/test/src/dart/ast/parse_base.dart b/pkg/analyzer/test/src/dart/ast/parse_base.dart
index 4e8f64e..75dd688 100644
--- a/pkg/analyzer/test/src/dart/ast/parse_base.dart
+++ b/pkg/analyzer/test/src/dart/ast/parse_base.dart
@@ -4,7 +4,6 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 4cfa035..d45c744 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
diff --git a/pkg/analyzer/test/src/dart/constant/utilities_test.dart b/pkg/analyzer/test/src/dart/constant/utilities_test.dart
index c8c64b8..d546744 100644
--- a/pkg/analyzer/test/src/dart/constant/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/utilities_test.dart
@@ -9,7 +9,6 @@
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index 65c8cdf..28d8657 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -6,7 +6,6 @@
 import 'package:analyzer/src/dart/micro/cider_byte_store.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/lint/registry.dart';
-import 'package:matcher/matcher.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
index a5be3c1..7c699c7 100644
--- a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test/test.dart';
diff --git a/pkg/analyzer/test/src/diagnostics/ambiguous_import_test.dart b/pkg/analyzer/test/src/diagnostics/ambiguous_import_test.dart
index 01e301c..cb20c6d 100644
--- a/pkg/analyzer/test/src/diagnostics/ambiguous_import_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/ambiguous_import_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/analysis/results.dart';
-import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:matcher/src/core_matchers.dart';
 import 'package:test_api/src/frontend/expect.dart';
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_to_const_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_to_const_test.dart
index 9a30b49..89c7c7f 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_to_const_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_to_const_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_to_final_local_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_to_final_local_test.dart
index 7c95b50..0ce29b5 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_to_final_local_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_to_final_local_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/src/diagnostics/cast_to_non_type_test.dart b/pkg/analyzer/test/src/diagnostics/cast_to_non_type_test.dart
index 78747bc..185861a 100644
--- a/pkg/analyzer/test/src/diagnostics/cast_to_non_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/cast_to_non_type_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart b/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart
index c6f1e03..f46212a 100644
--- a/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/src/diagnostics/label_in_outer_scope_test.dart b/pkg/analyzer/test/src/diagnostics/label_in_outer_scope_test.dart
index 7fa6830..2c1f3cf 100644
--- a/pkg/analyzer/test/src/diagnostics/label_in_outer_scope_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/label_in_outer_scope_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/src/diagnostics/label_undefined_test.dart b/pkg/analyzer/test/src/diagnostics/label_undefined_test.dart
index 7918d11..c89d139 100644
--- a/pkg/analyzer/test/src/diagnostics/label_undefined_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/label_undefined_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_class_boolean_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_class_boolean_test.dart
index 58f17ba..46a6ecd 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_class_boolean_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_class_boolean_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_class_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_class_test.dart
index 025eb5f..8c78d5c 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_class_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_class_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index c855dc4..3dcdf8e 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -9,10 +9,7 @@
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/source/error_processor.dart';
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
-import 'package:analyzer/src/analysis_options/error/option_codes.dart';
-import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/lint/linter.dart';
diff --git a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
index 9cfd890..d4ef9bf 100644
--- a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
@@ -42,7 +42,7 @@
 export 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
 export '../api_prototype/compiler_options.dart'
-    show parseExperimentalFlags, parseExperimentalArguments;
+    show parseExperimentalFlags, parseExperimentalArguments, Verbosity;
 
 export '../api_prototype/experimental_flags.dart'
     show ExperimentalFlag, parseExperimentalFlag;
diff --git a/runtime/docs/pragmas.md b/runtime/docs/pragmas.md
index 3895806..0211a75 100644
--- a/runtime/docs/pragmas.md
+++ b/runtime/docs/pragmas.md
@@ -11,6 +11,16 @@
 | `vm:prefer-inline` | [Inline a function or method when possible](compiler/pragmas_recognized_by_compiler.md#requesting-a-function-be-inlined) |
 | `vm:notify-debugger-on-exception` | Marks a function that catches exceptions, making the VM treat any caught exception as if they were uncaught. This can be used to notify an attached debugger during debugging, without pausing the app during regular execution. |
 
+## Unsafe pragmas for general use
+
+These pragmas are available for use in third-party code but are potentially
+unsafe. The use of these pragmas is discouraged unless the developer fully
+understands potential repercussions.
+
+| Pragma | Meaning |
+| --- | --- |
+| `vm:unsafe:no-interrupts` | Removes all `CheckStackOverflow` instructions from the optimized version of the marked function, which disables stack overflow checking and interruption within that function. This pragma exists mainly for performance evaluation and should not be used in a general-purpose code, because VM relies on these checks for OOB message delivery and GC scheduling. |
+
 ## Pragmas for internal use
 
 These pragmas can cause unsound behavior if used incorrectly and therefore are only allowed within the core SDK libraries.
diff --git a/runtime/observatory/tests/service/pause_on_unhandled_exceptions_catcherror_test.dart b/runtime/observatory/tests/service/pause_on_unhandled_exceptions_catcherror_test.dart
new file mode 100644
index 0000000..b8c96cb
--- /dev/null
+++ b/runtime/observatory/tests/service/pause_on_unhandled_exceptions_catcherror_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression: https://github.com/dart-lang/sdk/issues/37953
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+Future<void> throwAsync() async {
+  await Future.delayed(const Duration(milliseconds: 100));
+  throw 'Throw from throwAsync!';
+}
+
+testeeMain() async {
+  await throwAsync().then((v) {
+    print('Hello from then()!');
+  }).catchError((e, st) {
+    print('Caught in catchError: $e!');
+  });
+}
+
+var tests = <IsolateTest>[
+  // We shouldn't get any debugger breaks before exit as all exceptions are
+  // caught (via `Future.catchError()`).
+  hasStoppedAtExit,
+];
+
+main(args) => runIsolateTests(args, tests,
+    pause_on_unhandled_exceptions: true,
+    pause_on_exit: true,
+    testeeConcurrent: testeeMain,
+    extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index 4fc37a9..0be2c2e5 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -13,7 +13,6 @@
 eval_internal_class_test: SkipByDesign # No incremental compiler available.
 eval_regression_flutter20255_test: SkipByDesign # No incremental compiler available.
 eval_test: SkipByDesign # No incremental compiler available.
-evaluate_activation_in_method_class_test: RuntimeError # Issue 35505
 evaluate_activation_test: SkipByDesign # No incremental compiler available.
 evaluate_async_closure_test: SkipByDesign # No incremental compiler available.
 evaluate_class_type_parameters_test: SkipByDesign # No incremental compiler available.
@@ -33,7 +32,6 @@
 [ $compiler == dartk ]
 bad_reload_test: RuntimeError # Issue 34025
 coverage_optimized_function_test: Pass, Slow
-evaluate_activation_in_method_class_test: RuntimeError # Issue 35505
 evaluate_activation_test/instance: RuntimeError # http://dartbug.com/20047
 evaluate_activation_test/scope: RuntimeError # http://dartbug.com/20047
 get_source_report_test: RuntimeError # Should pass again when constant evaluation is relanded, see http://dartbug.com/36600
diff --git a/runtime/observatory_2/tests/service_2/pause_on_unhandled_exceptions_catcherror_test.dart b/runtime/observatory_2/tests/service_2/pause_on_unhandled_exceptions_catcherror_test.dart
new file mode 100644
index 0000000..b8c96cb
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/pause_on_unhandled_exceptions_catcherror_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression: https://github.com/dart-lang/sdk/issues/37953
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+Future<void> throwAsync() async {
+  await Future.delayed(const Duration(milliseconds: 100));
+  throw 'Throw from throwAsync!';
+}
+
+testeeMain() async {
+  await throwAsync().then((v) {
+    print('Hello from then()!');
+  }).catchError((e, st) {
+    print('Caught in catchError: $e!');
+  });
+}
+
+var tests = <IsolateTest>[
+  // We shouldn't get any debugger breaks before exit as all exceptions are
+  // caught (via `Future.catchError()`).
+  hasStoppedAtExit,
+];
+
+main(args) => runIsolateTests(args, tests,
+    pause_on_unhandled_exceptions: true,
+    pause_on_exit: true,
+    testeeConcurrent: testeeMain,
+    extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory_2/tests/service_2/service_2_kernel.status b/runtime/observatory_2/tests/service_2/service_2_kernel.status
index aea3d74..fda49e7 100644
--- a/runtime/observatory_2/tests/service_2/service_2_kernel.status
+++ b/runtime/observatory_2/tests/service_2/service_2_kernel.status
@@ -13,7 +13,6 @@
 eval_internal_class_test: SkipByDesign # No incremental compiler available.
 eval_regression_flutter20255_test: SkipByDesign # No incremental compiler available.
 eval_test: SkipByDesign # No incremental compiler available.
-evaluate_activation_in_method_class_test: RuntimeError # Issue 35505
 evaluate_activation_test: SkipByDesign # No incremental compiler available.
 evaluate_async_closure_test: SkipByDesign # No incremental compiler available.
 evaluate_class_type_parameters_test: SkipByDesign # No incremental compiler available.
@@ -33,7 +32,6 @@
 [ $compiler == dartk ]
 bad_reload_test: RuntimeError # Issue 34025
 coverage_optimized_function_test: Pass, Slow
-evaluate_activation_in_method_class_test: RuntimeError # Issue 35505
 evaluate_activation_test/instance: RuntimeError # http://dartbug.com/20047
 evaluate_activation_test/scope: RuntimeError # http://dartbug.com/20047
 get_source_report_test: RuntimeError # Should pass again when constant evaluation is relanded, see http://dartbug.com/36600
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 79b6a6b..407304e 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -712,6 +712,16 @@
 // Undefine math.h definition which clashes with our condition names.
 #undef OVERFLOW
 
+// Include IL printer functionality into non-PRODUCT builds or in all AOT
+// compiler builds or when forced.
+#if !defined(PRODUCT) || defined(DART_PRECOMPILER) ||                          \
+    defined(FORCE_INCLUDE_DISASSEMBLER)
+#if defined(DART_PRECOMPILED_RUNTIME) && defined(PRODUCT)
+#error Requested to include IL printer into PRODUCT AOT runtime
+#endif
+#define INCLUDE_IL_PRINTER 1
+#endif
+
 }  // namespace dart
 
 #endif  // RUNTIME_PLATFORM_GLOBALS_H_
diff --git a/runtime/vm/code_comments.cc b/runtime/vm/code_comments.cc
index d1344d3..061e356 100644
--- a/runtime/vm/code_comments.cc
+++ b/runtime/vm/code_comments.cc
@@ -1,14 +1,19 @@
 // Copyright (c) 2019, 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.
-#if !defined(DART_PRECOMPILED_RUNTIME) &&                                      \
-    (!defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER))
+#include "vm/globals.h"  // For INCLUDE_IL_PRINTER
+#if defined(INCLUDE_IL_PRINTER)
 
 #include "vm/code_comments.h"
+#if !defined(DART_PRECOMPILED_RUNTIME)
+#include "vm/compiler/assembler/assembler.h"
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+#include "vm/object.h"
 
 namespace dart {
 
-const Code::Comments& CreateCommentsFrom(compiler::Assembler* assembler) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+const CodeComments& CreateCommentsFrom(compiler::Assembler* assembler) {
   const auto& comments = assembler->comments();
   Code::Comments& result = Code::Comments::New(comments.length());
 
@@ -19,7 +24,7 @@
 
   return result;
 }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 }  // namespace dart
-#endif  // !defined(DART_PRECOMPILED_RUNTIME) &&                               \
-        // (!defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER))
+#endif  // defined(INCLUDE_IL_PRINTER)
diff --git a/runtime/vm/code_comments.h b/runtime/vm/code_comments.h
index 18f0e75..3ba5194 100644
--- a/runtime/vm/code_comments.h
+++ b/runtime/vm/code_comments.h
@@ -5,41 +5,31 @@
 #ifndef RUNTIME_VM_CODE_COMMENTS_H_
 #define RUNTIME_VM_CODE_COMMENTS_H_
 
-#if !defined(DART_PRECOMPILED_RUNTIME) &&                                      \
-    (!defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER))
-
-#include "vm/code_observers.h"
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/object.h"
+#include "vm/globals.h"  // For INCLUDE_IL_PRINTER
+#if defined(INCLUDE_IL_PRINTER)
 
 namespace dart {
 
-class CodeCommentsWrapper final : public CodeComments {
+// An abstract representation of comments associated with the given code
+// object. We assume that comments are sorted by PCOffset.
+class CodeComments {
  public:
-  explicit CodeCommentsWrapper(const Code::Comments& comments)
-      : comments_(comments), string_(String::Handle()) {}
+  CodeComments() = default;
+  virtual ~CodeComments() = default;
 
-  intptr_t Length() const override { return comments_.Length(); }
-
-  intptr_t PCOffsetAt(intptr_t i) const override {
-    return comments_.PCOffsetAt(i);
-  }
-
-  const char* CommentAt(intptr_t i) const override {
-    string_ = comments_.CommentAt(i);
-    return string_.ToCString();
-  }
-
- private:
-  const Code::Comments& comments_;
-  String& string_;
+  virtual intptr_t Length() const = 0;
+  virtual intptr_t PCOffsetAt(intptr_t index) const = 0;
+  virtual const char* CommentAt(intptr_t index) const = 0;
 };
 
-const Code::Comments& CreateCommentsFrom(compiler::Assembler* assembler);
-
+#if !defined(DART_PRECOMPILED_RUNTIME)
+namespace compiler {
+class Assembler;
+}
+const CodeComments& CreateCommentsFrom(compiler::Assembler* assembler);
+#endif
 
 }  // namespace dart
 
-#endif  // !defined(DART_PRECOMPILED_RUNTIME) &&                               \
-        // (!defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER))
+#endif  // defined(INCLUDE_IL_PRINTER)
 #endif  // RUNTIME_VM_CODE_COMMENTS_H_
diff --git a/runtime/vm/code_observers.h b/runtime/vm/code_observers.h
index c76f5f5..d116d59 100644
--- a/runtime/vm/code_observers.h
+++ b/runtime/vm/code_observers.h
@@ -10,25 +10,10 @@
 
 #include "include/dart_api.h"
 
+#if !defined(PRODUCT)
 namespace dart {
 
-#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
-
-// An abstract representation of comments associated with the given code
-// object. We assume that comments are sorted by PCOffset.
-class CodeComments : public ValueObject {
- public:
-  CodeComments() = default;
-  virtual ~CodeComments() = default;
-
-  virtual intptr_t Length() const = 0;
-  virtual intptr_t PCOffsetAt(intptr_t index) const = 0;
-  virtual const char* CommentAt(intptr_t index) const = 0;
-};
-
-#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
-
-#if !defined(PRODUCT)
+class CodeComments;
 
 // Object observing code creation events. Used by external profilers and
 // debuggers to map address ranges to function names.
@@ -86,8 +71,7 @@
   static CodeObserver** observers_;
 };
 
-#endif  // !defined(PRODUCT)
-
 }  // namespace dart
+#endif  // !defined(PRODUCT)
 
 #endif  // RUNTIME_VM_CODE_OBSERVERS_H_
diff --git a/runtime/vm/compiler/api/print_filter.cc b/runtime/vm/compiler/api/print_filter.cc
index ee2a06f..be9762c 100644
--- a/runtime/vm/compiler/api/print_filter.cc
+++ b/runtime/vm/compiler/api/print_filter.cc
@@ -1,7 +1,8 @@
 // Copyright (c) 2020, 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.
-#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+#include "platform/globals.h"  // For INCLUDE_IL_PRINTER
+#if defined(INCLUDE_IL_PRINTER)
 
 #include "vm/compiler/api/print_filter.h"
 
@@ -67,4 +68,4 @@
 
 }  // namespace dart
 
-#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+#endif  // defined(INCLUDE_IL_PRINTER)
diff --git a/runtime/vm/compiler/api/print_filter.h b/runtime/vm/compiler/api/print_filter.h
index 1eea14a..604fa9c 100644
--- a/runtime/vm/compiler/api/print_filter.h
+++ b/runtime/vm/compiler/api/print_filter.h
@@ -4,7 +4,10 @@
 
 #ifndef RUNTIME_VM_COMPILER_API_PRINT_FILTER_H_
 #define RUNTIME_VM_COMPILER_API_PRINT_FILTER_H_
-#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+
+#include "platform/globals.h"  // For INCLUDE_IL_PRINTER
+
+#if defined(INCLUDE_IL_PRINTER)
 
 #include "platform/allocation.h"
 
@@ -23,5 +26,5 @@
 
 }  // namespace dart
 
-#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+#endif  // defined(INCLUDE_IL_PRINTER)
 #endif  // RUNTIME_VM_COMPILER_API_PRINT_FILTER_H_
diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc
index fdbe05c..78ae30b 100644
--- a/runtime/vm/compiler/assembler/disassembler.cc
+++ b/runtime/vm/compiler/assembler/disassembler.cc
@@ -6,6 +6,7 @@
 
 #include "platform/text_buffer.h"
 #include "platform/unaligned.h"
+#include "vm/code_comments.h"
 #include "vm/code_patcher.h"
 #include "vm/dart_entry.h"
 #include "vm/deopt_instructions.h"
@@ -161,7 +162,7 @@
                                uword end,
                                DisassemblyFormatter* formatter,
                                const Code& code,
-                               const Code::Comments* comments) {
+                               const CodeComments* comments) {
   if (comments == nullptr) {
     comments = code.IsNull() ? &Code::Comments::New(0) : &code.comments();
   }
@@ -177,9 +178,7 @@
     const intptr_t old_comment_finger = comment_finger;
     while (comment_finger < comments->Length() &&
            comments->PCOffsetAt(comment_finger) <= offset) {
-      formatter->Print(
-          "        ;; %s\n",
-          String::Handle(comments->CommentAt(comment_finger)).ToCString());
+      formatter->Print("        ;; %s\n", comments->CommentAt(comment_finger));
       comment_finger++;
     }
     if (old_comment_finger != comment_finger && !code.IsNull()) {
diff --git a/runtime/vm/compiler/assembler/disassembler.h b/runtime/vm/compiler/assembler/disassembler.h
index dde4e49..77ad2ce 100644
--- a/runtime/vm/compiler/assembler/disassembler.h
+++ b/runtime/vm/compiler/assembler/disassembler.h
@@ -17,8 +17,9 @@
 namespace dart {
 
 // Forward declaration.
-class MemoryRegion;
+class CodeComments;
 class JSONArray;
+class MemoryRegion;
 
 // Disassembly formatter interface, which consumes the
 // disassembled instructions in any desired form.
@@ -122,7 +123,7 @@
                           uword end,
                           DisassemblyFormatter* formatter,
                           const Code& code,
-                          const Code::Comments* comments = nullptr);
+                          const CodeComments* comments = nullptr);
 
   static void Disassemble(uword start,
                           uword end,
@@ -133,7 +134,7 @@
   static void Disassemble(uword start,
                           uword end,
                           DisassemblyFormatter* formatter,
-                          const Code::Comments* comments) {
+                          const CodeComments* comments) {
     Disassemble(start, end, formatter, Code::Handle(), comments);
   }
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 92f23a4..7005c7b 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -1547,15 +1547,12 @@
 }
 
 void FlowGraphCompiler::EmitComment(Instruction* instr) {
-  if (!FLAG_support_il_printer || !FLAG_support_disassembler) {
-    return;
-  }
-#ifndef PRODUCT
+#if defined(INCLUDE_IL_PRINTER)
   char buffer[256];
   BufferFormatter f(buffer, sizeof(buffer));
   instr->PrintTo(&f);
   assembler()->Comment("%s", buffer);
-#endif
+#endif  // defined(INCLUDE_IL_PRINTER)
 }
 
 bool FlowGraphCompiler::NeedsEdgeCounter(BlockEntryInstr* block) {
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 169949e..0266392 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -146,9 +146,9 @@
   void SetReachingType(CompileType* type);
   void RefineReachingType(CompileType* type);
 
-#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+#if defined(INCLUDE_IL_PRINTER)
   void PrintTo(BaseTextBuffer* f) const;
-#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+#endif  // defined(INCLUDE_IL_PRINTER)
 
   SExpression* ToSExpression(FlowGraphSerializer* s) const;
 
@@ -560,18 +560,14 @@
   DECLARE_INSTRUCTION_NO_BACKEND(type)                                         \
   DECLARE_COMPARISON_METHODS
 
-#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+#if defined(INCLUDE_IL_PRINTER)
 #define PRINT_TO_SUPPORT virtual void PrintTo(BaseTextBuffer* f) const;
-#else
-#define PRINT_TO_SUPPORT
-#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
-
-#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 #define PRINT_OPERANDS_TO_SUPPORT                                              \
   virtual void PrintOperandsTo(BaseTextBuffer* f) const;
 #else
+#define PRINT_TO_SUPPORT
 #define PRINT_OPERANDS_TO_SUPPORT
-#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+#endif  // defined(INCLUDE_IL_PRINTER)
 
 #define TO_S_EXPRESSION_SUPPORT                                                \
   virtual SExpression* ToSExpression(FlowGraphSerializer* s) const;
@@ -934,10 +930,8 @@
 
   // Printing support.
   const char* ToCString() const;
-#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
-  virtual void PrintTo(BaseTextBuffer* f) const;
-  virtual void PrintOperandsTo(BaseTextBuffer* f) const;
-#endif
+  PRINT_TO_SUPPORT
+  PRINT_OPERANDS_TO_SUPPORT
   virtual SExpression* ToSExpression(FlowGraphSerializer* s) const;
   virtual void AddOperandsToSExpression(SExpList* sexp,
                                         FlowGraphSerializer* s) const;
@@ -2397,7 +2391,7 @@
     type_ = type;
   }
 
-#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+#if defined(INCLUDE_IL_PRINTER)
   const char* TypeAsCString() const {
     return HasType() ? type_->ToCString() : "";
   }
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index 79b93d5..981a536 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -14,8 +14,7 @@
 
 namespace dart {
 
-#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
-
+#if defined(INCLUDE_IL_PRINTER)
 DEFINE_FLAG(bool,
             display_sorted_ic_data,
             false,
@@ -1238,7 +1237,7 @@
   return Thread::Current()->zone()->MakeCopyOfString(buffer);
 }
 
-#else  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+#else  // defined(INCLUDE_IL_PRINTER)
 
 const char* Instruction::ToCString() const {
   return DebugName();
@@ -1276,6 +1275,6 @@
   return false;
 }
 
-#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+#endif  // defined(INCLUDE_IL_PRINTER)
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index 573bc43..03d3c39 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -4225,7 +4225,17 @@
   }
 }
 
+// Returns true if function is marked with vm:unsafe:no-interrupts pragma.
+static bool IsMarkedWithNoInterrupts(const Function& function) {
+  Object& options = Object::Handle();
+  return Library::FindPragma(dart::Thread::Current(),
+                             /*only_core=*/false, function,
+                             Symbols::vm_unsafe_no_interrupts(), &options);
+}
+
 void CheckStackOverflowElimination::EliminateStackOverflow(FlowGraph* graph) {
+  const bool should_remove_all = IsMarkedWithNoInterrupts(graph->function());
+
   CheckStackOverflowInstr* first_stack_overflow_instr = NULL;
   for (BlockIterator block_it = graph->reverse_postorder_iterator();
        !block_it.Done(); block_it.Advance()) {
@@ -4235,6 +4245,11 @@
       Instruction* current = it.Current();
 
       if (CheckStackOverflowInstr* instr = current->AsCheckStackOverflow()) {
+        if (should_remove_all) {
+          it.RemoveCurrentFromGraph();
+          continue;
+        }
+
         if (first_stack_overflow_instr == NULL) {
           first_stack_overflow_instr = instr;
           ASSERT(!first_stack_overflow_instr->in_loop());
diff --git a/runtime/vm/compiler/backend/redundancy_elimination_test.cc b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
index 859888f..65b6b80 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination_test.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
@@ -1350,6 +1350,27 @@
   EXPECT(call->Receiver()->definition() == allocate);
 }
 
+ISOLATE_UNIT_TEST_CASE(CheckStackOverflowElimination_NoInterruptsPragma) {
+  const char* kScript = R"(
+    @pragma('vm:unsafe:no-interrupts')
+    void test() {
+      for (int i = 0; i < 10; i++) {
+      }
+    }
+  )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  const auto& function = Function::Handle(GetFunction(root_library, "test"));
+
+  TestPipeline pipeline(function, CompilerPass::kAOT);
+  auto flow_graph = pipeline.RunPasses({});
+  for (auto block : flow_graph->postorder()) {
+    for (auto instr : block->instructions()) {
+      EXPECT_PROPERTY(instr, !it.IsCheckStackOverflow());
+    }
+  }
+}
+
 #endif  // !defined(TARGET_ARCH_IA32)
 
 }  // namespace dart
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 51975f3..dc6463f 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -706,13 +706,8 @@
 
 ObjectPtr ActivationFrame::GetAsyncAwaiter(
     CallerClosureFinder* caller_closure_finder) {
-  if (!function_.IsNull() &&
+  if (fp() != 0 && !function_.IsNull() &&
       (function_.IsAsyncClosure() || function_.IsAsyncGenClosure())) {
-    // This is only possible for frames that are active on the stack.
-    if (fp() == 0) {
-      return Object::null();
-    }
-
     // Look up caller's closure on the stack.
     ObjectPtr* last_caller_obj = reinterpret_cast<ObjectPtr*>(GetCallerSp());
     Closure& closure = Closure::Handle();
@@ -768,6 +763,23 @@
     }
     try_index = handlers.OuterTryIndex(try_index);
   }
+  // Async functions might have indirect exception handlers in the form of
+  // `Future.catchError`. Check the Closure's _FutureListeners.
+  if (fp() != 0 && is_async) {
+    CallerClosureFinder caller_closure_finder(Thread::Current()->zone());
+    ObjectPtr* last_caller_obj = reinterpret_cast<ObjectPtr*>(GetCallerSp());
+    Closure& closure = Closure::Handle(
+        StackTraceUtils::FindClosureInFrame(last_caller_obj, function()));
+    if (!caller_closure_finder.IsRunningAsync(closure)) {
+      return false;
+    }
+    Object& futureOrListener =
+        Object::Handle(caller_closure_finder.GetAsyncFuture(closure));
+    futureOrListener =
+        caller_closure_finder.GetFutureFutureListener(futureOrListener);
+    return caller_closure_finder.HasCatchError(futureOrListener);
+  }
+
   return false;
 }
 
@@ -986,6 +998,11 @@
   intptr_t num_parameters = function().num_fixed_parameters();
   ASSERT(0 <= index && index < num_parameters);
 
+  // fp will be a nullptr if the frame isn't active on the stack.
+  if (fp() == 0) {
+    return Object::null();
+  }
+
   if (function().NumOptionalParameters() > 0) {
     // If the function has optional parameters, the first positional parameter
     // can be in a number of places in the caller's frame depending on how many
@@ -1000,9 +1017,12 @@
   }
 }
 
-ObjectPtr ActivationFrame::GetClosure() {
+ClosurePtr ActivationFrame::GetClosure() {
   ASSERT(function().IsClosureFunction());
-  return GetParameter(0);
+  Object& param = Object::Handle(GetParameter(0));
+  ASSERT(param.IsInstance());
+  ASSERT(Instance::Cast(param).IsClosure());
+  return Closure::Cast(param).ptr();
 }
 
 ObjectPtr ActivationFrame::GetStackVar(VariableIndex variable_index) {
@@ -1975,7 +1995,6 @@
 
     deopt_frame = DeoptimizeToArray(thread, frame, code);
     bool found_async_awaiter = false;
-    bool abort_attempt_to_navigate_through_sync_async = false;
     for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
          it.Advance()) {
       inlined_code = it.code();
@@ -2008,7 +2027,7 @@
     }
 
     // Break out of outer loop.
-    if (found_async_awaiter || abort_attempt_to_navigate_through_sync_async) {
+    if (found_async_awaiter) {
       break;
     }
   }
@@ -3764,9 +3783,7 @@
   bpt = location->breakpoints();
   while (bpt != NULL) {
     if (bpt->IsPerClosure()) {
-      Object& closure = Object::Handle(top_frame->GetClosure());
-      ASSERT(closure.IsInstance());
-      ASSERT(Instance::Cast(closure).IsClosure());
+      Closure& closure = Closure::Handle(top_frame->GetClosure());
       if (closure.ptr() == bpt->closure()) {
         return bpt;
       }
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index 653c38b..382eff6 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -317,7 +317,7 @@
 
   ArrayPtr GetLocalVariables();
   ObjectPtr GetParameter(intptr_t index);
-  ObjectPtr GetClosure();
+  ClosurePtr GetClosure();
   ObjectPtr GetReceiver();
 
   const Context& GetSavedCurrentContext();
diff --git a/runtime/vm/dwarf.cc b/runtime/vm/dwarf.cc
index beee2d1..a818df9 100644
--- a/runtime/vm/dwarf.cc
+++ b/runtime/vm/dwarf.cc
@@ -4,6 +4,7 @@
 
 #include "vm/dwarf.h"
 
+#include "vm/code_comments.h"
 #include "vm/code_descriptors.h"
 #include "vm/elf.h"
 #include "vm/image_snapshot.h"
@@ -13,6 +14,11 @@
 
 #if defined(DART_PRECOMPILER)
 
+DEFINE_FLAG(charp,
+            write_code_comments_as_synthetic_source_to,
+            nullptr,
+            "Print comments associated with instructions into the given file");
+
 class DwarfPosition {
  public:
   DwarfPosition(int32_t line, int32_t column) : line_(line), column_(column) {
@@ -506,6 +512,212 @@
   stream->uleb128(0);  // End of children.
 }
 
+// Helper class for tracking state of DWARF registers and emitting
+// line number program commands to set these registers to the right
+// state.
+class LineNumberProgramWriter {
+ public:
+  explicit LineNumberProgramWriter(DwarfWriteStream* stream)
+      : stream_(stream) {}
+
+  void SetFile(intptr_t file) {
+    if (file != file_) {
+      stream_->u1(Dwarf::DW_LNS_set_file);
+      stream_->uleb128(file);
+      file_ = file;
+    }
+  }
+
+  void SetLine(intptr_t line) {
+    if (line != line_) {
+      stream_->u1(Dwarf::DW_LNS_advance_line);
+      stream_->sleb128(line - line_);
+      line_ = line;
+    }
+  }
+
+  void SetColumn(intptr_t column) {
+    if (column != column_) {
+      stream_->u1(Dwarf::DW_LNS_set_column);
+      stream_->uleb128(column);
+      column_ = column;
+    }
+  }
+
+  void SetPCOffset(const char* asm_name, intptr_t pc_offset) {
+    if (asm_name_ == nullptr) {
+      auto const instr_size = 1 + compiler::target::kWordSize;
+      stream_->u1(0);           // This is an extended opcode
+      stream_->u1(instr_size);  // that is 5 or 9 bytes long
+      stream_->u1(Dwarf::DW_LNE_set_address);
+      stream_->OffsetFromSymbol(asm_name, pc_offset);
+    } else {
+      // Emit LNP row if the address register has been updated to a
+      // non-zero value (dartbug.com/41756).
+      stream_->u1(Dwarf::DW_LNS_copy);
+      stream_->u1(Dwarf::DW_LNS_advance_pc);
+      stream_->DistanceBetweenSymbolOffsets(asm_name, pc_offset, asm_name_,
+                                            pc_offset_);
+    }
+    asm_name_ = asm_name;
+    pc_offset_ = pc_offset;
+  }
+
+ private:
+  DwarfWriteStream* const stream_;
+  // The initial values for the line number program state machine registers
+  // according to the DWARF standard.
+  intptr_t pc_offset_ = 0;
+  intptr_t file_ = 1;
+  intptr_t line_ = 1;
+  intptr_t column_ = 0;
+
+  // Other info not stored in the state machine registers.
+  const char* asm_name_ = nullptr;
+};
+
+void Dwarf::WriteSyntheticLineNumberProgram(LineNumberProgramWriter* writer) {
+  // We emit it last after all other scripts.
+  const intptr_t comments_file_index = scripts_.length() + 1;
+
+  auto file_open = Dart::file_open_callback();
+  auto file_write = Dart::file_write_callback();
+  auto file_close = Dart::file_close_callback();
+  if ((file_open == nullptr) || (file_write == nullptr) ||
+      (file_close == nullptr)) {
+    return;
+  }
+
+  TextBuffer comments_buffer(128 * KB);
+
+  auto comments_file = file_open(
+      FLAG_write_code_comments_as_synthetic_source_to, /*write=*/true);
+  if (comments_file == nullptr) {
+    OS::PrintErr("Failed to open file %s\n",
+                 FLAG_write_code_comments_as_synthetic_source_to);
+    return;
+  }
+
+  intptr_t current_line = 0;
+
+  writer->SetFile(comments_file_index);
+
+  for (intptr_t i = 0; i < codes_.length(); i++) {
+    const Code& code = *(codes_[i]);
+    auto const asm_name = code_to_name_.LookupValue(&code);
+    ASSERT(asm_name != nullptr);
+
+    auto& comments = code.comments();
+    for (intptr_t i = 0, len = comments.Length(); i < len;) {
+      intptr_t current_pc_offset = comments.PCOffsetAt(i);
+      writer->SetPCOffset(asm_name, current_pc_offset);
+      while (i < len && current_pc_offset == comments.PCOffsetAt(i)) {
+        comments_buffer.AddString(comments.CommentAt(i));
+        comments_buffer.AddChar('\n');
+        current_line++;
+        i++;
+      }
+
+      writer->SetLine(current_line);
+    }
+  }
+
+  file_write(comments_buffer.buffer(), comments_buffer.length(), comments_file);
+  file_close(comments_file);
+}
+
+void Dwarf::WriteLineNumberProgramFromCodeSourceMaps(
+    LineNumberProgramWriter* writer) {
+  Function& root_function = Function::Handle(zone_);
+  Script& script = Script::Handle(zone_);
+  CodeSourceMap& map = CodeSourceMap::Handle(zone_);
+  Array& functions = Array::Handle(zone_);
+  GrowableArray<const Function*> function_stack(zone_, 8);
+  GrowableArray<DwarfPosition> token_positions(zone_, 8);
+
+  for (intptr_t i = 0; i < codes_.length(); i++) {
+    const Code& code = *(codes_[i]);
+    auto const asm_name = code_to_name_.LookupValue(&code);
+    ASSERT(asm_name != nullptr);
+
+    map = code.code_source_map();
+    if (map.IsNull()) {
+      continue;
+    }
+    root_function = code.function();
+    functions = code.inlined_id_to_function();
+
+    NoSafepointScope no_safepoint;
+    ReadStream code_map_stream(map.Data(), map.Length());
+
+    function_stack.Clear();
+    token_positions.Clear();
+
+    int32_t current_pc_offset = 0;
+    function_stack.Add(&root_function);
+    token_positions.Add(kNoDwarfPositionInfo);
+
+    while (code_map_stream.PendingBytes() > 0) {
+      int32_t arg1;
+      int32_t arg2 = -1;
+      const uint8_t opcode =
+          CodeSourceMapOps::Read(&code_map_stream, &arg1, &arg2);
+      switch (opcode) {
+        case CodeSourceMapOps::kChangePosition: {
+          const DwarfPosition& old_pos =
+              token_positions[token_positions.length() - 1];
+          token_positions[token_positions.length() - 1] = DwarfPosition(
+              Utils::AddWithWrapAround(old_pos.line(), arg1), arg2);
+          break;
+        }
+        case CodeSourceMapOps::kAdvancePC: {
+          current_pc_offset += arg1;
+
+          const Function& function = *(function_stack.Last());
+          script = function.script();
+          intptr_t file = LookupScript(script);
+
+          // 1. Update LNP file.
+          writer->SetFile(file);
+
+          // 2. Update LNP line.
+          // The DWARF standard uses 0 to denote missing line or column
+          // information.
+          writer->SetLine(token_positions.Last().line() < 0
+                              ? 0
+                              : token_positions.Last().line());
+          writer->SetColumn(token_positions.Last().column() < 0
+                                ? 0
+                                : token_positions.Last().column());
+
+          writer->SetPCOffset(asm_name, current_pc_offset);
+          break;
+        }
+        case CodeSourceMapOps::kPushFunction: {
+          auto child_func =
+              &Function::Handle(zone_, Function::RawCast(functions.At(arg1)));
+          function_stack.Add(child_func);
+          token_positions.Add(kNoDwarfPositionInfo);
+          break;
+        }
+        case CodeSourceMapOps::kPopFunction: {
+          // We never pop the root function.
+          ASSERT(function_stack.length() > 1);
+          ASSERT(token_positions.length() > 1);
+          function_stack.RemoveLast();
+          token_positions.RemoveLast();
+          break;
+        }
+        case CodeSourceMapOps::kNullCheck: {
+          break;
+        }
+        default:
+          UNREACHABLE();
+      }
+    }
+  }
+}
+
 void Dwarf::WriteLineNumberProgram(DwarfWriteStream* stream) {
   // 6.2.4 The Line Number Program Header
 
@@ -559,141 +771,21 @@
     stream->uleb128(0);        // File modification time.
     stream->uleb128(0);        // File length.
   }
+  if (FLAG_write_code_comments_as_synthetic_source_to != nullptr) {
+    stream->string(FLAG_write_code_comments_as_synthetic_source_to);  // NOLINT
+    stream->uleb128(0);  // Include directory index.
+    stream->uleb128(0);  // File modification time.
+    stream->uleb128(0);  // File length.
+  }
   stream->u1(0);  // End of file names.
   stream->SetSize(lineheader_size_fixup, lineheader_prefix, lineheader_start);
 
   // 6.2.5 The Line Number Program
-
-  // The initial values for the line number program state machine registers
-  // according to the DWARF standard.
-  intptr_t previous_pc_offset = 0;
-  intptr_t previous_file = 1;
-  intptr_t previous_line = 1;
-  intptr_t previous_column = 0;
-  // Other info not stored in the state machine registers.
-  const char* previous_asm_name = nullptr;
-
-  Function& root_function = Function::Handle(zone_);
-  Script& script = Script::Handle(zone_);
-  CodeSourceMap& map = CodeSourceMap::Handle(zone_);
-  Array& functions = Array::Handle(zone_);
-  GrowableArray<const Function*> function_stack(zone_, 8);
-  GrowableArray<DwarfPosition> token_positions(zone_, 8);
-
-  for (intptr_t i = 0; i < codes_.length(); i++) {
-    const Code& code = *(codes_[i]);
-    auto const asm_name = code_to_name_.LookupValue(&code);
-    ASSERT(asm_name != nullptr);
-
-    map = code.code_source_map();
-    if (map.IsNull()) {
-      continue;
-    }
-    root_function = code.function();
-    functions = code.inlined_id_to_function();
-
-    NoSafepointScope no_safepoint;
-    ReadStream code_map_stream(map.Data(), map.Length());
-
-    function_stack.Clear();
-    token_positions.Clear();
-
-    int32_t current_pc_offset = 0;
-    function_stack.Add(&root_function);
-    token_positions.Add(kNoDwarfPositionInfo);
-
-    while (code_map_stream.PendingBytes() > 0) {
-      int32_t arg1;
-      int32_t arg2 = -1;
-      const uint8_t opcode =
-          CodeSourceMapOps::Read(&code_map_stream, &arg1, &arg2);
-      switch (opcode) {
-        case CodeSourceMapOps::kChangePosition: {
-          const DwarfPosition& old_pos =
-              token_positions[token_positions.length() - 1];
-          token_positions[token_positions.length() - 1] = DwarfPosition(
-              Utils::AddWithWrapAround(old_pos.line(), arg1), arg2);
-          break;
-        }
-        case CodeSourceMapOps::kAdvancePC: {
-          current_pc_offset += arg1;
-
-          const Function& function = *(function_stack.Last());
-          script = function.script();
-          intptr_t file = LookupScript(script);
-
-          // 1. Update LNP file.
-          if (file != previous_file) {
-            stream->u1(DW_LNS_set_file);
-            stream->uleb128(file);
-            previous_file = file;
-          }
-
-          // 2. Update LNP line.
-          // The DWARF standard uses 0 to denote missing line or column
-          // information.
-          const intptr_t line = token_positions.Last().line() < 0
-                                    ? 0
-                                    : token_positions.Last().line();
-          const intptr_t column = token_positions.Last().column() < 0
-                                      ? 0
-                                      : token_positions.Last().column();
-          if (line != previous_line) {
-            stream->u1(DW_LNS_advance_line);
-            stream->sleb128(line - previous_line);
-            previous_line = line;
-          }
-          if (column != previous_column) {
-            stream->u1(DW_LNS_set_column);
-            stream->uleb128(column);
-            previous_column = column;
-          }
-
-          // 3. Emit LNP row if the address register has been updated to a
-          // non-zero value (dartbug.com/41756).
-          if (previous_asm_name != nullptr) {
-            stream->u1(DW_LNS_copy);
-          }
-
-          // 4. Update LNP pc.
-          if (previous_asm_name == nullptr) {
-            auto const instr_size = 1 + compiler::target::kWordSize;
-            stream->u1(0);           // This is an extended opcode
-            stream->u1(instr_size);  // that is 5 or 9 bytes long
-            stream->u1(DW_LNE_set_address);
-            stream->OffsetFromSymbol(asm_name, current_pc_offset);
-          } else {
-            stream->u1(DW_LNS_advance_pc);
-            stream->DistanceBetweenSymbolOffsets(asm_name, current_pc_offset,
-                                                 previous_asm_name,
-                                                 previous_pc_offset);
-          }
-          previous_asm_name = asm_name;
-          previous_pc_offset = current_pc_offset;
-          break;
-        }
-        case CodeSourceMapOps::kPushFunction: {
-          const Function& child_func =
-              Function::Handle(zone_, Function::RawCast(functions.At(arg1)));
-          function_stack.Add(&child_func);
-          token_positions.Add(kNoDwarfPositionInfo);
-          break;
-        }
-        case CodeSourceMapOps::kPopFunction: {
-          // We never pop the root function.
-          ASSERT(function_stack.length() > 1);
-          ASSERT(token_positions.length() > 1);
-          function_stack.RemoveLast();
-          token_positions.RemoveLast();
-          break;
-        }
-        case CodeSourceMapOps::kNullCheck: {
-          break;
-        }
-        default:
-          UNREACHABLE();
-      }
-    }
+  LineNumberProgramWriter lnp_writer(stream);
+  if (FLAG_write_code_comments_as_synthetic_source_to != nullptr) {
+    WriteSyntheticLineNumberProgram(&lnp_writer);
+  } else {
+    WriteLineNumberProgramFromCodeSourceMaps(&lnp_writer);
   }
 
   // Advance pc to end of the compilation unit if not already there.
@@ -703,16 +795,7 @@
     const intptr_t last_pc_offset = last_code.Size();
     const char* last_asm_name = code_to_name_.LookupValue(&last_code);
     ASSERT(last_asm_name != nullptr);
-
-    stream->u1(DW_LNS_advance_pc);
-    if (previous_asm_name != nullptr) {
-      stream->DistanceBetweenSymbolOffsets(
-          last_asm_name, last_pc_offset, previous_asm_name, previous_pc_offset);
-    } else {
-      // No LNP entries (e.g., only stub code).
-      ASSERT(previous_pc_offset == 0);
-      stream->uleb128(last_pc_offset);
-    }
+    lnp_writer.SetPCOffset(last_asm_name, last_pc_offset);
   }
 
   // End of contiguous machine code.
diff --git a/runtime/vm/dwarf.h b/runtime/vm/dwarf.h
index b66788e..ccf9c83 100644
--- a/runtime/vm/dwarf.h
+++ b/runtime/vm/dwarf.h
@@ -16,6 +16,7 @@
 #ifdef DART_PRECOMPILER
 
 class InliningNode;
+class LineNumberProgramWriter;
 
 struct ScriptIndexPair {
   // Typedefs needed for the DirectChainedHashMap template.
@@ -250,6 +251,8 @@
   void WriteLineNumberProgram(DwarfWriteStream* stream);
 
  private:
+  friend class LineNumberProgramWriter;
+
   static const intptr_t DW_TAG_compile_unit = 0x11;
   static const intptr_t DW_TAG_inlined_subroutine = 0x1d;
   static const intptr_t DW_TAG_subprogram = 0x2e;
@@ -307,6 +310,10 @@
                          const char* root_code_name,
                          const Script& parent_script);
 
+  void WriteSyntheticLineNumberProgram(LineNumberProgramWriter* writer);
+  void WriteLineNumberProgramFromCodeSourceMaps(
+      LineNumberProgramWriter* writer);
+
   const char* Deobfuscate(const char* cstr);
   static Trie<const char>* CreateReverseObfuscationTrie(Zone* zone);
 
diff --git a/runtime/vm/ffi_callback_trampolines.cc b/runtime/vm/ffi_callback_trampolines.cc
index 169d8f8..25057e0 100644
--- a/runtime/vm/ffi_callback_trampolines.cc
+++ b/runtime/vm/ffi_callback_trampolines.cc
@@ -73,13 +73,12 @@
     ASSERT(!Thread::Current()->IsAtSafepoint());
     if (CodeObservers::AreActive()) {
       const auto& comments = CreateCommentsFrom(&assembler);
-      CodeCommentsWrapper wrapper(comments);
       CodeObservers::NotifyAll(name,
                                /*base=*/memory->start(),
                                /*prologue_offset=*/0,
                                /*size=*/assembler.CodeSize(),
                                /*optimized=*/false,  // not really relevant
-                               &wrapper);
+                               &comments);
     }
 #endif
 #if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 2f15546..f6c90bf 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -45,6 +45,12 @@
   R(support_disassembler, false, bool, true, "Support the disassembler.")
 #endif
 
+#if defined(INCLUDE_IL_PRINTER)
+constexpr bool FLAG_support_il_printer = true;
+#else
+constexpr bool FLAG_support_il_printer = false;
+#endif  // defined(INCLUDE_IL_PRINTER)
+
 // List of VM-global (i.e. non-isolate specific) flags.
 //
 // The value used for those flags at snapshot generation time needs to be the
@@ -92,8 +98,7 @@
     "Run optimizing compilation in background")                                \
   P(check_token_positions, bool, false,                                        \
     "Check validity of token positions while compiling flow graphs")           \
-  R(code_comments, false, bool, false,                                         \
-    "Include comments into code and disassembly.")                             \
+  P(code_comments, bool, false, "Include comments into code and disassembly.") \
   P(collect_code, bool, false, "Attempt to GC infrequently used code.")        \
   P(collect_dynamic_function_names, bool, true,                                \
     "Collects all dynamic function names to identify unique targets")          \
@@ -197,7 +202,6 @@
     "well).")                                                                  \
   P(show_invisible_frames, bool, false,                                        \
     "Show invisible frames in stack traces.")                                  \
-  R(support_il_printer, false, bool, true, "Support the IL printer.")          \
   D(trace_cha, bool, false, "Trace CHA operations")                            \
   R(trace_field_guards, false, bool, false, "Trace changes in field's cids.")  \
   D(trace_ic, bool, false, "Trace IC handling")                                \
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index d98aa2d..415bbfa 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -16057,6 +16057,7 @@
 }
 #endif
 
+#if defined(INCLUDE_IL_PRINTER)
 Code::Comments& Code::Comments::New(intptr_t count) {
   Comments* comments;
   if (count < 0 || count > (kIntptrMax / kNumberOfEntries)) {
@@ -16091,15 +16092,18 @@
                   Smi::Handle(Smi::New(pc)));
 }
 
-StringPtr Code::Comments::CommentAt(intptr_t idx) const {
-  return String::RawCast(comments_.At(idx * kNumberOfEntries + kCommentEntry));
+const char* Code::Comments::CommentAt(intptr_t idx) const {
+  string_ ^= comments_.At(idx * kNumberOfEntries + kCommentEntry);
+  return string_.ToCString();
 }
 
 void Code::Comments::SetCommentAt(intptr_t idx, const String& comment) {
   comments_.SetAt(idx * kNumberOfEntries + kCommentEntry, comment);
 }
 
-Code::Comments::Comments(const Array& comments) : comments_(comments) {}
+Code::Comments::Comments(const Array& comments)
+    : comments_(comments), string_(String::Handle()) {}
+#endif  // defined(INCLUDE_IL_PRINTER)
 
 const char* Code::EntryKindToCString(EntryKind kind) {
   switch (kind) {
@@ -16368,23 +16372,67 @@
 #endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 }
 
-const Code::Comments& Code::comments() const {
+#if defined(INCLUDE_IL_PRINTER)
 #if defined(PRODUCT)
-  Comments* comments = new Code::Comments(Array::Handle());
-#else
-  Comments* comments = new Code::Comments(Array::Handle(untag()->comments()));
+// In PRODUCT builds we don't have space in Code object to store code comments
+// so we move them into malloced heap (and leak them). This functionality
+// is only indended to be used in AOT compiler so leaking is fine.
+class MallocCodeComments final : public CodeComments {
+ public:
+  explicit MallocCodeComments(const CodeComments& comments)
+      : length_(comments.Length()), comments_(new Comment[comments.Length()]) {
+    for (intptr_t i = 0; i < length_; i++) {
+      comments_[i].pc_offset = comments.PCOffsetAt(i);
+      comments_[i].comment =
+          Utils::CreateCStringUniquePtr(strdup(comments.CommentAt(i)));
+    }
+  }
+
+  intptr_t Length() const override { return length_; }
+
+  intptr_t PCOffsetAt(intptr_t i) const override {
+    return comments_[i].pc_offset;
+  }
+
+  const char* CommentAt(intptr_t i) const override {
+    return comments_[i].comment.get();
+  }
+
+ private:
+  struct Comment {
+    intptr_t pc_offset;
+    Utils::CStringUniquePtr comment{nullptr, std::free};
+  };
+
+  intptr_t length_;
+  std::unique_ptr<Comment[]> comments_;
+};
 #endif
-  return *comments;
+
+const CodeComments& Code::comments() const {
+#if defined(PRODUCT)
+  auto comments =
+      static_cast<CodeComments*>(Thread::Current()->heap()->GetPeer(ptr()));
+  return (comments != nullptr) ? *comments : Code::Comments::New(0);
+#else
+  return *new Code::Comments(Array::Handle(untag()->comments()));
+#endif
 }
 
-void Code::set_comments(const Code::Comments& comments) const {
-#if defined(PRODUCT)
-  UNREACHABLE();
+void Code::set_comments(const CodeComments& comments) const {
+#if !defined(PRODUCT)
+  auto& wrapper = static_cast<const Code::Comments&>(comments);
+  ASSERT(wrapper.comments_.IsOld());
+  untag()->set_comments(wrapper.comments_.ptr());
 #else
-  ASSERT(comments.comments_.IsOld());
-  untag()->set_comments(comments.comments_.ptr());
+  if (FLAG_code_comments && comments.Length() > 0) {
+    Thread::Current()->heap()->SetPeer(ptr(), new MallocCodeComments(comments));
+  } else {
+    Thread::Current()->heap()->SetPeer(ptr(), nullptr);
+  }
 #endif
 }
+#endif  // defined(INCLUDE_IL_PRINTER)
 
 void Code::SetPrologueOffset(intptr_t offset) const {
 #if defined(PRODUCT)
@@ -16436,7 +16484,9 @@
     result.set_is_optimized(false);
     result.set_is_force_optimized(false);
     result.set_is_alive(false);
-    NOT_IN_PRODUCT(result.set_comments(Comments::New(0)));
+#if defined(INCLUDE_IL_PRINTER)
+    result.set_comments(Comments::New(0));
+#endif
     NOT_IN_PRODUCT(result.set_compile_timestamp(0));
     result.set_pc_descriptors(Object::empty_descriptors());
     result.set_compressed_stackmaps(Object::empty_compressed_stackmaps());
@@ -16603,9 +16653,12 @@
     CPU::FlushICache(instrs.PayloadStart(), instrs.Size());
   }
 
+#if defined(INCLUDE_IL_PRINTER)
+  code.set_comments(CreateCommentsFrom(assembler));
+#endif  // defined(INCLUDE_IL_PRINTER)
+
 #ifndef PRODUCT
   code.set_compile_timestamp(OS::GetCurrentMonotonicMicros());
-  code.set_comments(CreateCommentsFrom(assembler));
   if (assembler->prologue_offset() >= 0) {
     code.SetPrologueOffset(assembler->prologue_offset());
   } else {
@@ -16656,10 +16709,9 @@
   ASSERT(!Thread::Current()->IsAtSafepoint());
   if (CodeObservers::AreActive()) {
     const auto& instrs = Instructions::Handle(code.instructions());
-    CodeCommentsWrapper comments_wrapper(code.comments());
     CodeObservers::NotifyAll(name, instrs.PayloadStart(),
                              code.GetPrologueOffset(), instrs.Size(), optimized,
-                             &comments_wrapper);
+                             &code.comments());
   }
 #endif
 }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 0b8e4ad..6449bf2 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -18,6 +18,7 @@
 #include "platform/thread_sanitizer.h"
 #include "platform/utils.h"
 #include "vm/bitmap.h"
+#include "vm/code_comments.h"
 #include "vm/code_entry_kind.h"
 #include "vm/compiler/assembler/object_pool_builder.h"
 #include "vm/compiler/method_recognizer.h"
@@ -6181,17 +6182,18 @@
 
   void Disassemble(DisassemblyFormatter* formatter = NULL) const;
 
-  class Comments : public ZoneAllocated {
+#if defined(INCLUDE_IL_PRINTER)
+  class Comments : public ZoneAllocated, public CodeComments {
    public:
     static Comments& New(intptr_t count);
 
-    intptr_t Length() const;
+    intptr_t Length() const override;
 
     void SetPCOffsetAt(intptr_t idx, intptr_t pc_offset);
     void SetCommentAt(intptr_t idx, const String& comment);
 
-    intptr_t PCOffsetAt(intptr_t idx) const;
-    StringPtr CommentAt(intptr_t idx) const;
+    intptr_t PCOffsetAt(intptr_t idx) const override;
+    const char* CommentAt(intptr_t idx) const override;
 
    private:
     explicit Comments(const Array& comments);
@@ -6204,14 +6206,16 @@
     };
 
     const Array& comments_;
+    String& string_;
 
     friend class Code;
 
     DISALLOW_COPY_AND_ASSIGN(Comments);
   };
 
-  const Comments& comments() const;
-  void set_comments(const Comments& comments) const;
+  const CodeComments& comments() const;
+  void set_comments(const CodeComments& comments) const;
+#endif  // defined(INCLUDE_IL_PRINTER)
 
   ObjectPtr return_address_metadata() const {
 #if defined(PRODUCT)
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index fcca4f7..9cbb507 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -22,6 +22,7 @@
 
 #include "platform/memory_sanitizer.h"
 #include "platform/utils.h"
+#include "vm/code_comments.h"
 #include "vm/code_observers.h"
 #include "vm/dart.h"
 #include "vm/flags.h"
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 9c93470..94e3f38 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -3009,17 +3009,25 @@
 // Currently checks only that all optimized frames have kDeoptIndex
 // and unoptimized code has the kDeoptAfter.
 void DeoptimizeFunctionsOnStack() {
-  DartFrameIterator iterator(Thread::Current(),
-                             StackFrameIterator::kNoCrossThreadIteration);
-  StackFrame* frame = iterator.NextFrame();
-  Code& optimized_code = Code::Handle();
-  while (frame != NULL) {
-    optimized_code = frame->LookupDartCode();
-    if (optimized_code.is_optimized() && !optimized_code.is_force_optimized()) {
-      DeoptimizeAt(optimized_code, frame);
+  auto isolate_group = IsolateGroup::Current();
+  isolate_group->RunWithStoppedMutators([&]() {
+    auto current = isolate_group->thread_registry()->active_list();
+    Code& optimized_code = Code::Handle();
+    while (current != nullptr) {
+      DartFrameIterator iterator(
+          current, StackFrameIterator::kAllowCrossThreadIteration);
+      StackFrame* frame = iterator.NextFrame();
+      while (frame != NULL) {
+        optimized_code = frame->LookupDartCode();
+        if (optimized_code.is_optimized() &&
+            !optimized_code.is_force_optimized()) {
+          DeoptimizeAt(optimized_code, frame);
+        }
+        frame = iterator.NextFrame();
+      }
+      current = current->next();
     }
-    frame = iterator.NextFrame();
-  }
+  });
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index 18aebc1..e392260 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -146,37 +146,17 @@
 ClosurePtr CallerClosureFinder::GetCallerInFutureImpl(const Object& future) {
   ASSERT(!future.IsNull());
   ASSERT(future.GetClassId() == future_impl_class.id());
-
   // Since this function is recursive, we have to keep a local ref.
-  auto& listener = Object::Handle(
-      Instance::Cast(future).GetField(future_result_or_listeners_field));
-  if (listener.GetClassId() != future_listener_class.id()) {
+  auto& listener = Object::Handle(GetFutureFutureListener(future));
+  if (listener.IsNull()) {
     return Closure::null();
   }
-
-  callback_ = GetCallerInFutureListener(listener);
-  if (callback_.IsInstance() && !callback_.IsNull()) {
-    return Closure::Cast(callback_).ptr();
-  }
-
-  callback_ = Instance::Cast(listener).GetField(callback_field);
-  // This happens for e.g.: await f().catchError(..);
-  if (callback_.IsNull()) {
-    return Closure::null();
-  }
-  ASSERT(callback_.IsClosure());
-
-  return Closure::Cast(callback_).ptr();
-}
-
-ClosurePtr CallerClosureFinder::FindCallerInAsyncClosure(
-    const Context& receiver_context) {
-  future_ = receiver_context.At(Context::kAsyncFutureIndex);
-  return GetCallerInFutureImpl(future_);
+  return GetCallerInFutureListener(listener);
 }
 
 ClosurePtr CallerClosureFinder::FindCallerInAsyncGenClosure(
     const Context& receiver_context) {
+  // Get the async* _StreamController.
   context_entry_ = receiver_context.At(Context::kControllerIndex);
   ASSERT(context_entry_.IsInstance());
   ASSERT(context_entry_.GetClassId() ==
@@ -187,13 +167,14 @@
   ASSERT(!controller_.IsNull());
   ASSERT(controller_.GetClassId() == async_stream_controller_class.id());
 
+  // Get the _StreamController._state field.
   state_ = Instance::Cast(controller_).GetField(state_field);
   ASSERT(state_.IsSmi());
   if (Smi::Cast(state_).Value() != k_StreamController__STATE_SUBSCRIBED) {
     return Closure::null();
   }
 
-  // _StreamController._varData
+  // Get the _StreamController._varData field.
   var_data_ = Instance::Cast(controller_).GetField(var_data_field);
   ASSERT(var_data_.GetClassId() == controller_subscription_class.id());
 
@@ -228,36 +209,35 @@
 
 ClosurePtr CallerClosureFinder::GetCallerInFutureListener(
     const Object& future_listener) {
-  ASSERT(future_listener.GetClassId() == future_listener_class.id());
+  auto value = GetFutureListenerState(future_listener);
 
-  state_ =
-      Instance::Cast(future_listener).GetField(future_listener_state_field);
-
-  auto value = Smi::Cast(state_).Value();
   // If the _FutureListener is a `then`, `catchError`, or `whenComplete`
   // listener, follow the Future being completed, `result`, instead of the
   // dangling whenComplete `callback`.
   if (value == k_FutureListener_stateThen ||
       value == k_FutureListener_stateCatchError ||
       value == k_FutureListener_stateWhenComplete) {
-    future_ =
-        Instance::Cast(future_listener).GetField(future_listener_result_field);
+    future_ = GetFutureListenerResult(future_listener);
     return GetCallerInFutureImpl(future_);
   }
 
-  return Closure::null();
+  // If no chained futures, fall back on _FutureListener.callback.
+  return GetFutureListenerCallback(future_listener);
 }
 
 ClosurePtr CallerClosureFinder::FindCaller(const Closure& receiver_closure) {
   receiver_function_ = receiver_closure.function();
   receiver_context_ = receiver_closure.context();
 
-  if (receiver_function_.IsAsyncClosure()) {
-    return FindCallerInAsyncClosure(receiver_context_);
-  }
   if (receiver_function_.IsAsyncGenClosure()) {
     return FindCallerInAsyncGenClosure(receiver_context_);
   }
+
+  if (receiver_function_.IsAsyncClosure()) {
+    future_ = receiver_context_.At(Context::kAsyncFutureIndex);
+    return GetCallerInFutureImpl(future_);
+  }
+
   if (receiver_function_.IsLocalFunction()) {
     parent_function_ = receiver_function_.parent_function();
     if (parent_function_.recognized_kind() ==
@@ -265,6 +245,7 @@
       context_entry_ = receiver_context_.At(Context::kFutureTimeoutFutureIndex);
       return GetCallerInFutureImpl(context_entry_);
     }
+
     if (parent_function_.recognized_kind() == MethodRecognizer::kFutureWait) {
       receiver_context_ = receiver_context_.parent();
       ASSERT(!receiver_context_.IsNull());
@@ -276,6 +257,60 @@
   return Closure::null();
 }
 
+ObjectPtr CallerClosureFinder::GetAsyncFuture(const Closure& receiver_closure) {
+  // Closure -> Context -> _Future.
+  receiver_context_ = receiver_closure.context();
+  return receiver_context_.At(Context::kAsyncFutureIndex);
+}
+
+ObjectPtr CallerClosureFinder::GetFutureFutureListener(const Object& future) {
+  ASSERT(future.GetClassId() == future_impl_class.id());
+  auto& listener = Object::Handle(
+      Instance::Cast(future).GetField(future_result_or_listeners_field));
+  // This field can either hold a _FutureListener, Future, or the Future result.
+  if (listener.GetClassId() != future_listener_class.id()) {
+    return Closure::null();
+  }
+  return listener.ptr();
+}
+
+intptr_t CallerClosureFinder::GetFutureListenerState(
+    const Object& future_listener) {
+  ASSERT(future_listener.GetClassId() == future_listener_class.id());
+  state_ =
+      Instance::Cast(future_listener).GetField(future_listener_state_field);
+  return Smi::Cast(state_).Value();
+}
+
+ClosurePtr CallerClosureFinder::GetFutureListenerCallback(
+    const Object& future_listener) {
+  ASSERT(future_listener.GetClassId() == future_listener_class.id());
+  return Closure::RawCast(
+      Instance::Cast(future_listener).GetField(callback_field));
+}
+
+ObjectPtr CallerClosureFinder::GetFutureListenerResult(
+    const Object& future_listener) {
+  ASSERT(future_listener.GetClassId() == future_listener_class.id());
+  return Instance::Cast(future_listener).GetField(future_listener_result_field);
+}
+
+bool CallerClosureFinder::HasCatchError(const Object& future_listener) {
+  ASSERT(future_listener.GetClassId() == future_listener_class.id());
+  listener_ = future_listener.ptr();
+  Object& result = Object::Handle();
+  // Iterate through any `.then()` chain.
+  while (!listener_.IsNull()) {
+    if (GetFutureListenerState(listener_) == k_FutureListener_stateCatchError) {
+      return true;
+    }
+    result = GetFutureListenerResult(listener_);
+    RELEASE_ASSERT(!result.IsNull());
+    listener_ = GetFutureFutureListener(result);
+  }
+  return false;
+}
+
 bool CallerClosureFinder::IsRunningAsync(const Closure& receiver_closure) {
   auto zone = Thread::Current()->zone();
 
diff --git a/runtime/vm/stack_trace.h b/runtime/vm/stack_trace.h
index 2074673..a08221f 100644
--- a/runtime/vm/stack_trace.h
+++ b/runtime/vm/stack_trace.h
@@ -19,16 +19,40 @@
  public:
   explicit CallerClosureFinder(Zone* zone);
 
+  // Recursively follow any `_FutureListener.result`.
+  // If no `result`, then return (bottom) `_FutureListener.callback`
   ClosurePtr GetCallerInFutureImpl(const Object& future_);
 
+  // Get caller closure from _FutureListener.
+  // Returns closure found either via the `result` Future, or the `callback`.
   ClosurePtr GetCallerInFutureListener(const Object& future_listener);
 
-  ClosurePtr FindCallerInAsyncClosure(const Context& receiver_context);
-
+  // Find caller closure from an async* function receiver context.
+  // Returns either the `onData` or the Future awaiter.
   ClosurePtr FindCallerInAsyncGenClosure(const Context& receiver_context);
 
+  // Find caller closure from a function receiver closure.
+  // For async* functions, async functions, `Future.timeout` and `Future.wait`,
+  // we can do this by finding and following their awaited Futures.
   ClosurePtr FindCaller(const Closure& receiver_closure);
 
+  // Finds the awaited Future from an async function receiver closure.
+  ObjectPtr GetAsyncFuture(const Closure& receiver_closure);
+
+  // Get sdk/lib/async/future_impl.dart:_FutureListener.state.
+  intptr_t GetFutureListenerState(const Object& future_listener);
+
+  // Get sdk/lib/async/future_impl.dart:_FutureListener.callback.
+  ClosurePtr GetFutureListenerCallback(const Object& future_listener);
+
+  // Get sdk/lib/async/future_impl.dart:_FutureListener.result.
+  ObjectPtr GetFutureListenerResult(const Object& future_listener);
+
+  // Get sdk/lib/async/future_impl.dart:_Future._resultOrListeners.
+  ObjectPtr GetFutureFutureListener(const Object& future);
+
+  bool HasCatchError(const Object& future_listener);
+
   static bool IsRunningAsync(const Closure& receiver_closure);
 
  private:
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index b9d33eb..3784362 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -498,7 +498,8 @@
   V(vm_recognized, "vm:recognized")                                            \
   V(vm_trace_entrypoints, "vm:testing.unsafe.trace-entrypoints-fn")            \
   V(vm_procedure_attributes_metadata, "vm.procedure-attributes.metadata")      \
-  V(vm_ffi_struct_fields, "vm:ffi:struct-fields")
+  V(vm_ffi_struct_fields, "vm:ffi:struct-fields")                              \
+  V(vm_unsafe_no_interrupts, "vm:unsafe:no-interrupts")
 
 // Contains a list of frequently used strings in a canonicalized form. This
 // list is kept in the vm_isolate in order to share the copy across isolates
diff --git a/runtime/vm/thread_registry.h b/runtime/vm/thread_registry.h
index c45103e..4a32f5f 100644
--- a/runtime/vm/thread_registry.h
+++ b/runtime/vm/thread_registry.h
@@ -59,6 +59,7 @@
   friend class SafepointHandler;
   friend class Scavenger;
   friend class WeakCodeReferences;
+  friend void DeoptimizeFunctionsOnStack();
   DISALLOW_COPY_AND_ASSIGN(ThreadRegistry);
 };
 
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index a9f2b80..5f9117b 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -187,18 +187,18 @@
 
 class _Future<T> implements Future<T> {
   /// Initial state, waiting for a result. In this state, the
-  /// [resultOrListeners] field holds a single-linked list of
+  /// [_resultOrListeners] field holds a single-linked list of
   /// [_FutureListener] listeners.
   static const int _stateIncomplete = 0;
 
   /// Pending completion. Set when completed using [_asyncComplete] or
   /// [_asyncCompleteError]. It is an error to try to complete it again.
-  /// [resultOrListeners] holds listeners.
+  /// [_resultOrListeners] holds listeners.
   static const int _statePendingComplete = 1;
 
   /// The future has been chained to another future. The result of that
   /// other future becomes the result of this future as well.
-  /// [resultOrListeners] contains the source future.
+  /// [_resultOrListeners] contains the source future.
   static const int _stateChained = 2;
 
   /// The future has been completed with a value result.
@@ -226,7 +226,7 @@
   /// Listeners are only remembered while the future is not yet complete,
   /// and it is not chained to another future.
   ///
-  /// The future is another future that his future is chained to. This future
+  /// The future is another future that this future is chained to. This future
   /// is waiting for the other future to complete, and when it does, this future
   /// will complete with the same result.
   /// All listeners are forwarded to the other future.
@@ -767,6 +767,7 @@
           return;
         }
       }
+
       _Future result = listener.result;
       listeners = result._removeListeners();
       if (!listenerHasError) {
diff --git a/tools/VERSION b/tools/VERSION
index cdb882a..b2a510b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 12
 PATCH 0
-PRERELEASE 281
+PRERELEASE 282
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/utils/bazel/kernel_worker.dart b/utils/bazel/kernel_worker.dart
index ebbfbe5..96f1e9a 100644
--- a/utils/bazel/kernel_worker.dart
+++ b/utils/bazel/kernel_worker.dart
@@ -147,7 +147,13 @@
       help: 'Enable a language experiment when invoking the CFE.')
   ..addMultiOption('define', abbr: 'D')
   ..addFlag('verbose', defaultsTo: false)
-  ..addFlag('sound-null-safety', defaultsTo: false);
+  ..addFlag('sound-null-safety', defaultsTo: false)
+  ..addOption('verbosity',
+      defaultsTo: fe.Verbosity.defaultValue,
+      help: 'Sets the verbosity level used for filtering messages during '
+          'compilation.',
+      allowed: fe.Verbosity.allowedValues,
+      allowedHelp: fe.Verbosity.allowedValuesHelp);
 
 class ComputeKernelResult {
   final bool succeeded;
@@ -257,6 +263,7 @@
   bool recordUsedInputs = parsedArgs["used-inputs"] != null;
   var environmentDefines = _parseEnvironmentDefines(parsedArgs['define']);
   var verbose = parsedArgs['verbose'] as bool;
+  var verbosity = fe.Verbosity.parseArgument(parsedArgs['verbosity']);
 
   if (parsedArgs['use-incremental-compiler']) {
     usingIncrementalCompiler = true;
@@ -321,7 +328,9 @@
   }
 
   void onDiagnostic(fe.DiagnosticMessage message) {
-    fe.printDiagnosticMessage(message, out.writeln);
+    if (fe.Verbosity.shouldPrint(verbosity, message)) {
+      fe.printDiagnosticMessage(message, out.writeln);
+    }
     if (message.severity == fe.Severity.error) {
       succeeded = false;
     }