Version 2.13.0-195.0.dev

Merge commit 'a8590a287ec2e76b8c4155149d9a681df892767b' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4028c90..51cf065 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,48 @@
 
 ### Language
 
+*   **Type aliases** [Non-function type aliases][]: Type aliases (names for
+    types introduced via the `typedef` keyword) were previously restricted
+    to only introduce names for function types.  In this release, we
+    remove this restriction and allow type aliases to name any kind of type.
+
+    ```dart
+    import 'dart:convert';
+
+    typedef JsonMap = Map<String, dynamic>;
+
+    JsonMap parseJsonMap(String input) => json.decode(input) as JsonMap;
+    ```
+
+    In addition to being usable as type annotations, type aliases that name
+    class types can now also be used anywhere that the underlying class could be
+    used, allowing type aliases to be used to safely rename existing classes.
+
+    ```dart
+    class NewClassName<T> {
+       NewClassName.create(T x);
+       static NewClassName<T> mkOne<T>(T x) => NewClassName<T>.create(x);
+     }
+    @Deprecated("Use NewClassName instead")
+    typedef OldClassName<T> = NewClassName<T>;
+
+    class LegacyClass extends OldClassName<int> {
+      LegacyClass() : super.create(3);
+    }
+    OldClassName<int> legacyCode() {
+      var one = OldClassName.create(1);
+      var two = OldClassName.mkOne(2);
+      return LegacyClass();
+    }
+    ```
+
+    The new type alias feature is only available as part of the 2.13 [language
+    version](https://dart.dev/guides/language/evolution).  To use this feature,
+    you must set the lower bound on the sdk constraint for your package to 2.13
+    or greater.
+
+    [Non-function type aliases]: https://github.com/dart-lang/language/blob/master/accepted/2.13/nonfunction-type-aliases/feature-specification.md
+
 ### Core libraries
 
 #### `dart:collection`
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index fb78fb5..47d5d33 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -19,8 +19,7 @@
 }
 
 @reflectiveTest
-class AnalysisHoverTest extends AbstractAnalysisTest
-    with WithNonFunctionTypeAliasesMixin {
+class AnalysisHoverTest extends AbstractAnalysisTest {
   Future<HoverInformation> prepareHover(String search) {
     var offset = findOffset(search);
     return prepareHoverAt(offset);
diff --git a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
index 8650731..7bab497 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
@@ -23,8 +23,7 @@
 }
 
 @reflectiveTest
-class AnalysisNotificationHighlightsTest extends HighlightsTestSupport
-    with WithNonFunctionTypeAliasesMixin {
+class AnalysisNotificationHighlightsTest extends HighlightsTestSupport {
   Future<void> test_ANNOTATION_hasArguments() async {
     addTestFile('''
 class AAA {
diff --git a/pkg/analysis_server/test/analysis/notification_navigation_test.dart b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
index 8e52073..c99d007 100644
--- a/pkg/analysis_server/test/analysis/notification_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
@@ -21,8 +21,7 @@
   });
 }
 
-class AbstractNavigationTest extends AbstractAnalysisTest
-    with WithNonFunctionTypeAliasesMixin {
+class AbstractNavigationTest extends AbstractAnalysisTest {
   List<NavigationRegion> regions;
   List<NavigationTarget> targets;
   List<String> targetFiles;
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index f2f5cf8..ab75d6b 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -238,15 +238,3 @@
     return serverChannel.sendRequest(request, throwOnError: throwOnError);
   }
 }
-
-mixin WithNonFunctionTypeAliasesMixin on AbstractAnalysisTest {
-  @override
-  void createProject({Map<String, String> packageRoots}) {
-    addAnalysisOptionsFile('''
-analyzer:
-  enable-experiment:
-    - nonfunction-type-aliases
-''');
-    super.createProject(packageRoots: packageRoots);
-  }
-}
diff --git a/pkg/analysis_server/test/search/element_references_test.dart b/pkg/analysis_server/test/search/element_references_test.dart
index fba332c..1049186 100644
--- a/pkg/analysis_server/test/search/element_references_test.dart
+++ b/pkg/analysis_server/test/search/element_references_test.dart
@@ -9,13 +9,11 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../analysis_abstract.dart';
 import 'abstract_search_domain.dart';
 
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ElementReferencesTest);
-    defineReflectiveTests(ElementReferencesWithNonFunctionTypeAliasesTest);
   });
 }
 
@@ -23,8 +21,6 @@
 class ElementReferencesTest extends AbstractSearchDomainTest {
   Element searchElement;
 
-  bool get hasNonFunctionTypeAliases => false;
-
   void assertHasRef(SearchResultKind kind, String search, bool isPotential) {
     assertHasResult(kind, search);
     expect(result.isPotential, isPotential);
@@ -876,54 +872,11 @@
 }
 ''');
     await findElementReferences('F =', false);
-    expect(
-      searchElement.kind,
-      hasNonFunctionTypeAliases
-          ? ElementKind.TYPE_ALIAS
-          : ElementKind.FUNCTION_TYPE_ALIAS,
-    );
+    expect(searchElement.kind, ElementKind.TYPE_ALIAS);
     expect(results, hasLength(1));
     assertHasResult(SearchResultKind.REFERENCE, 'F f');
   }
 
-  Future<void> test_typeReference_typeAlias_legacy() async {
-    addTestFile('''
-typedef F();
-main(F f) {
-}
-''');
-    await findElementReferences('F()', false);
-    expect(
-      searchElement.kind,
-      hasNonFunctionTypeAliases
-          ? ElementKind.TYPE_ALIAS
-          : ElementKind.FUNCTION_TYPE_ALIAS,
-    );
-    expect(results, hasLength(1));
-    assertHasResult(SearchResultKind.REFERENCE, 'F f');
-  }
-
-  Future<void> test_typeReference_typeVariable() async {
-    addTestFile('''
-class A<T> {
-  T f;
-  T m() => null;
-}
-''');
-    await findElementReferences('T> {', false);
-    expect(searchElement.kind, ElementKind.TYPE_PARAMETER);
-    expect(results, hasLength(2));
-    assertHasResult(SearchResultKind.REFERENCE, 'T f;');
-    assertHasResult(SearchResultKind.REFERENCE, 'T m()');
-  }
-}
-
-@reflectiveTest
-class ElementReferencesWithNonFunctionTypeAliasesTest
-    extends ElementReferencesTest with WithNonFunctionTypeAliasesMixin {
-  @override
-  bool get hasNonFunctionTypeAliases => true;
-
   Future<void> test_typeReference_typeAlias_interfaceType() async {
     addTestFile('''
 typedef A<T> = Map<int, T>;
@@ -941,4 +894,30 @@
     expect(searchElement.kind, ElementKind.CLASS);
     assertHasResult(SearchResultKind.REFERENCE, 'int,');
   }
+
+  Future<void> test_typeReference_typeAlias_legacy() async {
+    addTestFile('''
+typedef F();
+main(F f) {
+}
+''');
+    await findElementReferences('F()', false);
+    expect(searchElement.kind, ElementKind.TYPE_ALIAS);
+    expect(results, hasLength(1));
+    assertHasResult(SearchResultKind.REFERENCE, 'F f');
+  }
+
+  Future<void> test_typeReference_typeVariable() async {
+    addTestFile('''
+class A<T> {
+  T f;
+  T m() => null;
+}
+''');
+    await findElementReferences('T> {', false);
+    expect(searchElement.kind, ElementKind.TYPE_PARAMETER);
+    expect(results, hasLength(2));
+    assertHasResult(SearchResultKind.REFERENCE, 'T f;');
+    assertHasResult(SearchResultKind.REFERENCE, 'T m()');
+  }
 }
diff --git a/pkg/analysis_server/test/search/top_level_declarations_test.dart b/pkg/analysis_server/test/search/top_level_declarations_test.dart
index 7cda6cf..37a7cf8 100644
--- a/pkg/analysis_server/test/search/top_level_declarations_test.dart
+++ b/pkg/analysis_server/test/search/top_level_declarations_test.dart
@@ -80,8 +80,8 @@
     await findTopLevelDeclarations('^[A-F]\$');
     assertHasDeclaration(ElementKind.CLASS, 'A');
     assertHasDeclaration(ElementKind.CLASS, 'B');
-    assertHasDeclaration(ElementKind.FUNCTION_TYPE_ALIAS, 'C');
-    assertHasDeclaration(ElementKind.FUNCTION_TYPE_ALIAS, 'D');
+    assertHasDeclaration(ElementKind.TYPE_ALIAS, 'C');
+    assertHasDeclaration(ElementKind.TYPE_ALIAS, 'D');
     assertHasDeclaration(ElementKind.FUNCTION, 'E');
     assertHasDeclaration(ElementKind.TOP_LEVEL_VARIABLE, 'F');
     assertNoDeclaration(ElementKind.CLASS, 'ABC');
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
index 5d7c6ec..74cac9d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
@@ -152,7 +152,7 @@
     isExpired: IsExpired.nonfunction_type_aliases,
     documentation: 'Type aliases define a <type>, not just a <functionType>',
     experimentalReleaseVersion: null,
-    releaseVersion: null,
+    releaseVersion: Version.parse('2.13.0'),
   );
 
   static final set_literals = ExperimentalFeature(
@@ -231,7 +231,7 @@
   static const bool non_nullable = true;
 
   /// Default state of the experiment "nonfunction-type-aliases"
-  static const bool nonfunction_type_aliases = false;
+  static const bool nonfunction_type_aliases = true;
 
   /// Default state of the experiment "set-literals"
   static const bool set_literals = true;
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
index e7d11dc..f774c07 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
@@ -87,7 +87,7 @@
   ExperimentalFlag.extensionTypes: false,
   ExperimentalFlag.genericMetadata: false,
   ExperimentalFlag.nonNullable: true,
-  ExperimentalFlag.nonfunctionTypeAliases: false,
+  ExperimentalFlag.nonfunctionTypeAliases: true,
   ExperimentalFlag.setLiterals: true,
   ExperimentalFlag.spreadCollections: true,
   ExperimentalFlag.tripleShift: false,
diff --git a/runtime/vm/closure_functions_cache.cc b/runtime/vm/closure_functions_cache.cc
index e70d6ce..ff62680 100644
--- a/runtime/vm/closure_functions_cache.cc
+++ b/runtime/vm/closure_functions_cache.cc
@@ -172,7 +172,7 @@
   const auto& closures =
       GrowableObjectArray::Handle(zone, object_store->closure_functions());
 
-  {
+  if (!thread->IsInStoppedMutatorsScope()) {
     // The empty read locker scope will implicitly issue an acquire memory
     // fence, which means any closure functions added so far will be visible and
     // iterated further down.
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 1a9d77d..206aad7 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -6965,12 +6965,14 @@
     bool non_main_isolates_alive = false;
     {
       SafepointOperationScope safepoint(thread);
-      group->ForEachIsolate([&](Isolate* isolate) {
-        if (isolate != main_isolate) {
-          Isolate::KillIfExists(isolate, Isolate::kKillMsg);
-          non_main_isolates_alive = true;
-        }
-      });
+      group->ForEachIsolate(
+          [&](Isolate* isolate) {
+            if (isolate != main_isolate) {
+              Isolate::KillIfExists(isolate, Isolate::kKillMsg);
+              non_main_isolates_alive = true;
+            }
+          },
+          /*at_safepoint=*/true);
       if (!non_main_isolates_alive) {
         break;
       }
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index d057516..592a7e5 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -460,27 +460,31 @@
 }
 
 bool GroupDebugger::HasCodeBreakpointInFunction(const Function& func) {
-  SafepointReadRwLocker sl(Thread::Current(), code_breakpoints_lock());
-  CodeBreakpoint* cbpt = code_breakpoints_;
-  while (cbpt != NULL) {
-    if (func.ptr() == cbpt->function()) {
-      return true;
+  auto thread = Thread::Current();
+  return RunUnderReadLockIfNeeded(thread, code_breakpoints_lock(), [&]() {
+    CodeBreakpoint* cbpt = code_breakpoints_;
+    while (cbpt != NULL) {
+      if (func.ptr() == cbpt->function()) {
+        return true;
+      }
+      cbpt = cbpt->next_;
     }
-    cbpt = cbpt->next_;
-  }
-  return false;
+    return false;
+  });
 }
 
 bool GroupDebugger::HasBreakpointInCode(const Code& code) {
-  SafepointReadRwLocker sl(Thread::Current(), code_breakpoints_lock());
-  CodeBreakpoint* cbpt = code_breakpoints_;
-  while (cbpt != NULL) {
-    if (code.ptr() == cbpt->code_) {
-      return true;
+  auto thread = Thread::Current();
+  return RunUnderReadLockIfNeeded(thread, code_breakpoints_lock(), [&]() {
+    CodeBreakpoint* cbpt = code_breakpoints_;
+    while (cbpt != NULL) {
+      if (code.ptr() == cbpt->code_) {
+        return true;
+      }
+      cbpt = cbpt->next_;
     }
-    cbpt = cbpt->next_;
-  }
-  return false;
+    return false;
+  });
 }
 
 void Debugger::PrintBreakpointsToJSONArray(JSONArray* jsarr) const {
@@ -3211,7 +3215,12 @@
 
   // Going through BreakpointLocations of all isolates and debuggers looking
   // for those that can be resolved and added code breakpoints at now.
-  SafepointReadRwLocker sl(thread, breakpoint_locations_lock());
+  //
+  // The check below is used instead of breakpoint_locations_lock acquisition.
+  // We don't need to acquire the lock if always run with stopped mutators.
+  // We can't acquire the lock if we run with stopped mutators as that could
+  // result in deadlock.
+  RELEASE_ASSERT(thread->IsInStoppedMutatorsScope());
   for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
     BreakpointLocation* location = breakpoint_locations_.At(i);
     if (EnsureLocationIsInFunction(zone, function, location)) {
@@ -3700,20 +3709,34 @@
   single_stepping_set_.Remove(debugger);
 }
 
-bool GroupDebugger::HasBreakpoint(Thread* thread, const Function& function) {
-  {
-    // Check if function has any breakpoints.
-    SafepointReadRwLocker sl(thread, breakpoint_locations_lock());
-    Script& script = Script::Handle(thread->zone());
-    for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
-      BreakpointLocation* location = breakpoint_locations_.At(i);
-      script = location->script();
-      if (FunctionOverlaps(function, script, location->token_pos(),
-                           location->end_token_pos())) {
-        return true;
-      }
-    }
+bool GroupDebugger::RunUnderReadLockIfNeededCallable(Thread* thread,
+                                                     SafepointRwLock* rw_lock,
+                                                     BoolCallable* callable) {
+  if (thread->IsInStoppedMutatorsScope()) {
+    return callable->Call();
   }
+
+  SafepointReadRwLocker sl(thread, rw_lock);
+  return callable->Call();
+}
+
+bool GroupDebugger::HasBreakpoint(Thread* thread, const Function& function) {
+  if (RunUnderReadLockIfNeeded(thread, breakpoint_locations_lock(), [&]() {
+        // Check if function has any breakpoints.
+        Script& script = Script::Handle(thread->zone());
+        for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
+          BreakpointLocation* location = breakpoint_locations_.At(i);
+          script = location->script();
+          if (FunctionOverlaps(function, script, location->token_pos(),
+                               location->end_token_pos())) {
+            return true;
+          }
+        }
+        return false;
+      })) {
+    return true;
+  }
+
   // TODO(aam): do we have to iterate over both code breakpoints and
   // breakpoint locations? Wouldn't be sufficient to iterate over only
   // one list? Could you have a CodeBreakpoint without corresponding
@@ -3726,11 +3749,10 @@
 }
 
 bool GroupDebugger::IsDebugging(Thread* thread, const Function& function) {
-  {
-    SafepointReadRwLocker sl(thread, single_stepping_set_lock());
-    if (!single_stepping_set_.IsEmpty()) {
-      return true;
-    }
+  if (!RunUnderReadLockIfNeeded(thread, single_stepping_set_lock(), [&]() {
+        return single_stepping_set_.IsEmpty();
+      })) {
+    return true;
   }
   return HasBreakpoint(thread, function);
 }
@@ -3983,6 +4005,9 @@
   }
 
   if (FLAG_verbose_debug) {
+    // Lock is needed for CodeBreakpoint::ToCString().
+    SafepointReadRwLocker sl(Thread::Current(),
+                             group_debugger()->code_breakpoints_lock());
     OS::PrintErr(">>> hit %" Pd
                  " %s"
                  " (func %s token %s address %#" Px " offset %#" Px ")\n",
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index bad3a2b..bd2d0de 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -557,6 +557,28 @@
   }
 };
 
+class BoolCallable : public ValueObject {
+ public:
+  BoolCallable() {}
+  virtual ~BoolCallable() {}
+
+  virtual bool Call() = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BoolCallable);
+};
+
+template <typename T>
+class LambdaBoolCallable : public BoolCallable {
+ public:
+  explicit LambdaBoolCallable(T& lambda) : lambda_(lambda) {}
+  bool Call() { return lambda_(); }
+
+ private:
+  T& lambda_;
+  DISALLOW_COPY_AND_ASSIGN(LambdaBoolCallable);
+};
+
 class GroupDebugger {
  public:
   explicit GroupDebugger(IsolateGroup* isolate_group);
@@ -597,6 +619,10 @@
 
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
 
+  SafepointRwLock* code_breakpoints_lock() {
+    return code_breakpoints_lock_.get();
+  }
+
   SafepointRwLock* breakpoint_locations_lock() {
     return breakpoint_locations_lock_.get();
   }
@@ -608,6 +634,18 @@
   void UnregisterSingleSteppingDebugger(Thread* thread,
                                         const Debugger* debugger);
 
+  bool RunUnderReadLockIfNeededCallable(Thread* thread,
+                                        SafepointRwLock* rw_lock,
+                                        BoolCallable* callable);
+
+  template <typename T>
+  bool RunUnderReadLockIfNeeded(Thread* thread,
+                                SafepointRwLock* rw_lock,
+                                T function) {
+    LambdaBoolCallable<T> callable(function);
+    return RunUnderReadLockIfNeededCallable(thread, rw_lock, &callable);
+  }
+
   // Returns [true] if there is at least one breakpoint set in function or code.
   // Checks for both user-defined and internal temporary breakpoints.
   bool HasBreakpoint(Thread* thread, const Function& function);
@@ -628,9 +666,6 @@
   std::unique_ptr<SafepointRwLock> single_stepping_set_lock_;
   DebuggerSet single_stepping_set_;
 
-  SafepointRwLock* code_breakpoints_lock() {
-    return code_breakpoints_lock_.get();
-  }
   void RemoveUnlinkedCodeBreakpoints();
   void RegisterCodeBreakpoint(CodeBreakpoint* bpt);
 
diff --git a/runtime/vm/experimental_features.cc b/runtime/vm/experimental_features.cc
index e341195..57eb309 100644
--- a/runtime/vm/experimental_features.cc
+++ b/runtime/vm/experimental_features.cc
@@ -18,7 +18,7 @@
 
 bool GetExperimentalFeatureDefault(ExperimentalFeature feature) {
   constexpr bool kFeatureValues[] = {
-      true, true, true, true, true, true,
+      true, true, true, true, true, true, true,
   };
   ASSERT(static_cast<size_t>(feature) < ARRAY_SIZE(kFeatureValues));
   return kFeatureValues[static_cast<int>(feature)];
@@ -26,9 +26,10 @@
 
 const char* GetExperimentalFeatureName(ExperimentalFeature feature) {
   constexpr const char* kFeatureNames[] = {
-      "non-nullable",         "extension-methods",
-      "constant-update-2018", "control-flow-collections",
-      "set-literals",         "spread-collections",
+      "nonfunction-type-aliases", "non-nullable",
+      "extension-methods",        "constant-update-2018",
+      "control-flow-collections", "set-literals",
+      "spread-collections",
   };
   ASSERT(static_cast<size_t>(feature) < ARRAY_SIZE(kFeatureNames));
   return kFeatureNames[static_cast<int>(feature)];
diff --git a/runtime/vm/experimental_features.h b/runtime/vm/experimental_features.h
index 8efd29e..d6816b3 100644
--- a/runtime/vm/experimental_features.h
+++ b/runtime/vm/experimental_features.h
@@ -14,6 +14,7 @@
 namespace dart {
 
 enum class ExperimentalFeature {
+  nonfunction_type_aliases,
   non_nullable,
   extension_methods,
   constant_update_2018,
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index f730542..52d1f65 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -990,64 +990,70 @@
 #ifndef PRODUCT
   // For now we'll emit the same GC events on all isolates.
   if (Service::gc_stream.enabled()) {
-    isolate_group_->ForEachIsolate([&](Isolate* isolate) {
-      if (!Isolate::IsSystemIsolate(isolate)) {
-        ServiceEvent event(isolate, ServiceEvent::kGC);
-        event.set_gc_stats(&stats_);
-        Service::HandleEvent(&event);
-      }
-    });
+    isolate_group_->ForEachIsolate(
+        [&](Isolate* isolate) {
+          if (!Isolate::IsSystemIsolate(isolate)) {
+            ServiceEvent event(isolate, ServiceEvent::kGC);
+            event.set_gc_stats(&stats_);
+            Service::HandleEvent(&event);
+          }
+        },
+        /*at_safepoint=*/true);
   }
 #endif  // !PRODUCT
   if (Dart::gc_event_callback() != nullptr) {
-    isolate_group_->ForEachIsolate([&](Isolate* isolate) {
-      if (!Isolate::IsSystemIsolate(isolate)) {
-        Dart_GCEvent event;
-        auto isolate_id = Utils::CStringUniquePtr(
-            OS::SCreate(nullptr, ISOLATE_SERVICE_ID_FORMAT_STRING,
-                        isolate->main_port()),
-            std::free);
-        int64_t isolate_uptime_micros = isolate->UptimeMicros();
+    isolate_group_->ForEachIsolate(
+        [&](Isolate* isolate) {
+          if (!Isolate::IsSystemIsolate(isolate)) {
+            Dart_GCEvent event;
+            auto isolate_id = Utils::CStringUniquePtr(
+                OS::SCreate(nullptr, ISOLATE_SERVICE_ID_FORMAT_STRING,
+                            isolate->main_port()),
+                std::free);
+            int64_t isolate_uptime_micros = isolate->UptimeMicros();
 
-        event.isolate_id = isolate_id.get();
-        event.type = GCTypeToString(stats_.type_);
-        event.reason = GCReasonToString(stats_.reason_);
+            event.isolate_id = isolate_id.get();
+            event.type = GCTypeToString(stats_.type_);
+            event.reason = GCReasonToString(stats_.reason_);
 
-        // New space - Scavenger.
-        {
-          intptr_t new_space_collections = new_space_.collections();
+            // New space - Scavenger.
+            {
+              intptr_t new_space_collections = new_space_.collections();
 
-          event.new_space.collections = new_space_collections;
-          event.new_space.used = stats_.after_.new_.used_in_words * kWordSize;
-          event.new_space.capacity =
-              stats_.after_.new_.capacity_in_words * kWordSize;
-          event.new_space.external =
-              stats_.after_.new_.external_in_words * kWordSize;
-          event.new_space.time =
-              MicrosecondsToSeconds(new_space_.gc_time_micros());
-          event.new_space.avg_collection_period =
-              AvgCollectionPeriod(isolate_uptime_micros, new_space_collections);
-        }
+              event.new_space.collections = new_space_collections;
+              event.new_space.used =
+                  stats_.after_.new_.used_in_words * kWordSize;
+              event.new_space.capacity =
+                  stats_.after_.new_.capacity_in_words * kWordSize;
+              event.new_space.external =
+                  stats_.after_.new_.external_in_words * kWordSize;
+              event.new_space.time =
+                  MicrosecondsToSeconds(new_space_.gc_time_micros());
+              event.new_space.avg_collection_period = AvgCollectionPeriod(
+                  isolate_uptime_micros, new_space_collections);
+            }
 
-        // Old space - Page.
-        {
-          intptr_t old_space_collections = old_space_.collections();
+            // Old space - Page.
+            {
+              intptr_t old_space_collections = old_space_.collections();
 
-          event.old_space.collections = old_space_collections;
-          event.old_space.used = stats_.after_.old_.used_in_words * kWordSize;
-          event.old_space.capacity =
-              stats_.after_.old_.capacity_in_words * kWordSize;
-          event.old_space.external =
-              stats_.after_.old_.external_in_words * kWordSize;
-          event.old_space.time =
-              MicrosecondsToSeconds(old_space_.gc_time_micros());
-          event.old_space.avg_collection_period =
-              AvgCollectionPeriod(isolate_uptime_micros, old_space_collections);
-        }
+              event.old_space.collections = old_space_collections;
+              event.old_space.used =
+                  stats_.after_.old_.used_in_words * kWordSize;
+              event.old_space.capacity =
+                  stats_.after_.old_.capacity_in_words * kWordSize;
+              event.old_space.external =
+                  stats_.after_.old_.external_in_words * kWordSize;
+              event.old_space.time =
+                  MicrosecondsToSeconds(old_space_.gc_time_micros());
+              event.old_space.avg_collection_period = AvgCollectionPeriod(
+                  isolate_uptime_micros, old_space_collections);
+            }
 
-        (*Dart::gc_event_callback())(&event);
-      }
-    });
+            (*Dart::gc_event_callback())(&event);
+          }
+        },
+        /*at_safepoint=*/true);
   }
 }
 
diff --git a/runtime/vm/heap/weak_code.cc b/runtime/vm/heap/weak_code.cc
index c482fe7..44730a3 100644
--- a/runtime/vm/heap/weak_code.cc
+++ b/runtime/vm/heap/weak_code.cc
@@ -66,7 +66,8 @@
   return;
 #else
   // Ensure mutators see empty code_objects only after code was deoptimized.
-  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+  DEBUG_ASSERT(
+      IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
 
   if (code_objects.IsNull()) {
     return;
@@ -76,20 +77,22 @@
   // Deoptimize stacks and disable code with mutators stopped.
   isolate_group->RunWithStoppedMutators([&]() {
     Code& code = Code::Handle();
-    isolate_group->ForEachIsolate([&](Isolate* isolate) {
-      auto mutator_thread = isolate->mutator_thread();
-      DartFrameIterator iterator(
-          mutator_thread, StackFrameIterator::kAllowCrossThreadIteration);
-      StackFrame* frame = iterator.NextFrame();
-      while (frame != nullptr) {
-        code = frame->LookupDartCode();
-        if (IsOptimizedCode(code_objects, code)) {
-          ReportDeoptimization(code);
-          DeoptimizeAt(mutator_thread, code, frame);
-        }
-        frame = iterator.NextFrame();
-      }
-    });
+    isolate_group->ForEachIsolate(
+        [&](Isolate* isolate) {
+          auto mutator_thread = isolate->mutator_thread();
+          DartFrameIterator iterator(
+              mutator_thread, StackFrameIterator::kAllowCrossThreadIteration);
+          StackFrame* frame = iterator.NextFrame();
+          while (frame != nullptr) {
+            code = frame->LookupDartCode();
+            if (IsOptimizedCode(code_objects, code)) {
+              ReportDeoptimization(code);
+              DeoptimizeAt(mutator_thread, code, frame);
+            }
+            frame = iterator.NextFrame();
+          }
+        },
+        /*at_safepoint=*/true);
 
     // Switch functions that use dependent code to unoptimized code.
     WeakProperty& weak_property = WeakProperty::Handle();
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 495d026..69ae961 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -1738,6 +1738,7 @@
 #undef ISOLATE_METRIC_CONSTRUCTORS
 #endif  // !defined(PRODUCT)
           start_time_micros_(OS::GetCurrentMonotonicMicros()),
+      message_notify_callback_(nullptr),
       on_shutdown_callback_(Isolate::ShutdownCallback()),
       on_cleanup_callback_(Isolate::CleanupCallback()),
       random_(),
@@ -2731,20 +2732,27 @@
 void IsolateGroup::ForEachIsolate(
     std::function<void(Isolate* isolate)> function,
     bool at_safepoint) {
+  auto thread = Thread::Current();
   if (at_safepoint) {
-    ASSERT(Thread::Current()->IsAtSafepoint() ||
-           (Thread::Current()->task_kind() == Thread::kMutatorTask) ||
-           (Thread::Current()->task_kind() == Thread::kMarkerTask) ||
-           (Thread::Current()->task_kind() == Thread::kCompactorTask) ||
-           (Thread::Current()->task_kind() == Thread::kScavengerTask));
+    ASSERT(thread->IsAtSafepoint() ||
+           (thread->task_kind() == Thread::kMutatorTask) ||
+           (thread->task_kind() == Thread::kMarkerTask) ||
+           (thread->task_kind() == Thread::kCompactorTask) ||
+           (thread->task_kind() == Thread::kScavengerTask));
     for (Isolate* isolate : isolates_) {
       function(isolate);
     }
-  } else {
-    SafepointReadRwLocker ml(Thread::Current(), isolates_lock_.get());
+    return;
+  }
+  if (thread != nullptr && thread->IsAtSafepoint()) {
     for (Isolate* isolate : isolates_) {
       function(isolate);
     }
+    return;
+  }
+  SafepointReadRwLocker ml(thread, isolates_lock_.get());
+  for (Isolate* isolate : isolates_) {
+    function(isolate);
   }
 }
 
@@ -2762,6 +2770,7 @@
     Callable* otherwise,
     bool use_force_growth_in_otherwise) {
   auto thread = Thread::Current();
+  StoppedMutatorsScope stopped_mutators_scope(thread);
 
   if (thread->IsMutatorThread() && !IsolateGroup::AreIsolateGroupsEnabled()) {
     single_current_mutator->Call();
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 90f557a..fd19306 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -1024,11 +1024,11 @@
   }
 
   Dart_MessageNotifyCallback message_notify_callback() const {
-    return message_notify_callback_;
+    return message_notify_callback_.load(std::memory_order_relaxed);
   }
 
   void set_message_notify_callback(Dart_MessageNotifyCallback value) {
-    message_notify_callback_ = value;
+    message_notify_callback_.store(value, std::memory_order_release);
   }
 
   void set_on_shutdown_callback(Dart_IsolateShutdownCallback value) {
@@ -1594,7 +1594,7 @@
 
   // All other fields go here.
   int64_t start_time_micros_;
-  Dart_MessageNotifyCallback message_notify_callback_ = nullptr;
+  std::atomic<Dart_MessageNotifyCallback> message_notify_callback_;
   Dart_IsolateShutdownCallback on_shutdown_callback_ = nullptr;
   Dart_IsolateCleanupCallback on_cleanup_callback_ = nullptr;
   char* name_ = nullptr;
diff --git a/runtime/vm/lockers.cc b/runtime/vm/lockers.cc
index a39f0c6..c3b35f3 100644
--- a/runtime/vm/lockers.cc
+++ b/runtime/vm/lockers.cc
@@ -108,6 +108,12 @@
 bool SafepointRwLock::EnterRead() {
   // No need to safepoint if the current thread is not attached.
   auto thread = Thread::Current();
+  // Attempt to acquire a lock while owning a safepoint could lead to a deadlock
+  // (some other thread might be forced to a safepoint while holding this lock).
+  ASSERT(thread == nullptr ||
+         !thread->isolate_group()->safepoint_handler()->IsOwnedByTheThread(
+             thread));
+
   const bool can_block_without_safepoint = thread == nullptr;
 
   bool acquired_read_lock = false;
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index c76464f..87b76c0 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -570,6 +570,10 @@
 
   bool IsInNoReloadScope() const { return no_reload_scope_depth_ > 0; }
 
+  bool IsInStoppedMutatorsScope() const {
+    return stopped_mutators_scope_depth_ > 0;
+  }
+
 #define DEFINE_OFFSET_METHOD(type_name, member_name, expr, default_init_value) \
   static intptr_t member_name##offset() {                                      \
     return OFFSET_OF(Thread, member_name);                                     \
@@ -1008,6 +1012,7 @@
   ApiLocalScope* api_reusable_scope_;
   int32_t no_callback_scope_depth_;
   intptr_t no_reload_scope_depth_ = 0;
+  intptr_t stopped_mutators_scope_depth_ = 0;
 #if defined(DEBUG)
   int32_t no_safepoint_scope_depth_;
 #endif
@@ -1105,6 +1110,7 @@
   friend class NoReloadScope;
   friend class Simulator;
   friend class StackZone;
+  friend class StoppedMutatorsScope;
   friend class ThreadRegistry;
   friend class CompilerState;
   friend class compiler::target::Thread;
@@ -1173,6 +1179,28 @@
   DISALLOW_COPY_AND_ASSIGN(NoReloadScope);
 };
 
+class StoppedMutatorsScope : public ThreadStackResource {
+ public:
+  explicit StoppedMutatorsScope(Thread* thread)
+      : ThreadStackResource(thread), thread_(thread) {
+#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+    thread->stopped_mutators_scope_depth_++;
+    ASSERT(thread->stopped_mutators_scope_depth_ >= 0);
+#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+  }
+
+  ~StoppedMutatorsScope() {
+#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+    thread_->stopped_mutators_scope_depth_ -= 1;
+    ASSERT(thread_->stopped_mutators_scope_depth_ >= 0);
+#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+  }
+
+ private:
+  Thread* thread_;
+  DISALLOW_COPY_AND_ASSIGN(StoppedMutatorsScope);
+};
+
 // Within a EnterCompilerScope, the thread must operate on cloned fields.
 #if defined(DEBUG)
 class EnterCompilerScope : public ThreadStackResource {
diff --git a/tests/language/generic/function_typedef2_test.dart b/tests/language/generic/function_typedef2_test.dart
index 6d9c0ff..22fd248 100644
--- a/tests/language/generic/function_typedef2_test.dart
+++ b/tests/language/generic/function_typedef2_test.dart
@@ -3,6 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 // Dart test for a function type test that cannot be eliminated at compile time.
 
+// This test validates the static errors for typedefs in language versions
+// prior to the release of nonfunction type aliases (Dart 2.13).
+// @dart=2.12
+
 import "package:expect/expect.dart";
 
 class A {}
diff --git a/tests/language/generic/function_typedef3_test.dart b/tests/language/generic/function_typedef3_test.dart
new file mode 100644
index 0000000..47c3838
--- /dev/null
+++ b/tests/language/generic/function_typedef3_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test for a function type test that cannot be eliminated at compile time.
+
+// This test validates the static errors for typedefs as per the code in
+// function_typedef2_test.dart in language versions after the release of
+// nonfunction type aliases (Dart 2.13).
+
+import "package:expect/expect.dart";
+
+class A {}
+
+typedef int F();
+
+typedef G = F;
+
+typedef H = int;
+
+typedef I = A;
+
+typedef J = List<int>;
+
+typedef K = Function(Function<A>(A<int>));
+//                               ^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_TYPE_ARGUMENTS
+// [cfe] Can't use type arguments with type variable 'A'.
+typedef L = Function({x});
+//                    ^
+// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_CLASS
+// [cfe] Type 'x' not found.
+//                     ^
+// [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+// [cfe] Expected an identifier, but got '}'.
+
+typedef M = Function({int});
+        //               ^
+        // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+        // [cfe] Expected an identifier, but got '}'.
+
+foo({bool int = false}) {}
+main() {
+  bool b = true;
+  Expect.isFalse(b is L);
+  Expect.isFalse(b is M);
+  Expect.isTrue(foo is M);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 0ea8837..13bcfa2 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 13
 PATCH 0
-PRERELEASE 194
+PRERELEASE 195
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/experimental_features.yaml b/tools/experimental_features.yaml
index f3375ea..336213d 100644
--- a/tools/experimental_features.yaml
+++ b/tools/experimental_features.yaml
@@ -119,9 +119,6 @@
   variance:
     help: "Sound variance"
 
-  nonfunction-type-aliases:
-    help: "Type aliases define a <type>, not just a <functionType>"
-
   alternative-invalidation-strategy:
     help: "Alternative invalidation strategy for incremental compilation"
     category: "CFE"
@@ -143,6 +140,16 @@
 # on the command line, and will eventually be removed.
 #
 
+  nonfunction-type-aliases:
+    help: "Type aliases define a <type>, not just a <functionType>"
+    enabledIn: '2.13.0'
+    validation: |
+      typedef S = String;
+      void main() {
+        S s = 'feature enabled';
+        print(s);
+      }
+
   non-nullable:
     help: "Non Nullable by default"
     experimentalReleaseVersion: '2.10.0'