Version 2.18.0-78.0.dev

Merge commit '8566dbeb5790663792f331269996c39f087d713b' into 'dev'
diff --git a/DEPS b/DEPS
index 51d7633..fe525a4 100644
--- a/DEPS
+++ b/DEPS
@@ -49,7 +49,7 @@
   "co19_2_rev": "b2034a17609472e374623f3dbe0efd9f5cb258af",
 
   # The internal benchmarks to use. See go/dart-benchmarks-internal
-  "benchmarks_internal_rev": "076df10d9b77af337f2d8029725787155eb1cd52",
+  "benchmarks_internal_rev": "599aa474a03c37be146f82dfbad85f34f25ffa47",
   "checkout_benchmarks_internal": False,
 
   # Checkout Android dependencies only on Mac and Linux.
diff --git a/benchmarks/Isolate/dart2/Isolate.dart b/benchmarks/Isolate/dart2/Isolate.dart
index 7014df6..c8bfaab 100644
--- a/benchmarks/Isolate/dart2/Isolate.dart
+++ b/benchmarks/Isolate/dart2/Isolate.dart
@@ -8,8 +8,7 @@
 import 'dart:isolate';
 import 'dart:typed_data';
 
-import 'package:benchmark_harness/benchmark_harness.dart'
-    show PrintEmitter, ScoreEmitter;
+import 'package:benchmark_harness/benchmark_harness.dart';
 import 'package:meta/meta.dart';
 
 class SendReceiveBytes extends AsyncBenchmarkBase {
diff --git a/build/toolchain/win/setup_toolchain.py b/build/toolchain/win/setup_toolchain.py
index d1d4fb5..10b878a 100644
--- a/build/toolchain/win/setup_toolchain.py
+++ b/build/toolchain/win/setup_toolchain.py
@@ -118,8 +118,15 @@
     args.extend(('&&', 'set'))
     popen = subprocess.Popen(
         args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-    variables, _ = popen.communicate()
-    env = _ExtractImportantEnvironment(variables)
+    stdout_data, stderr_data = popen.communicate()
+    if popen.returncode != 0:
+      print('Error, got returncode:', popen.returncode)
+      print('## stdout:')
+      print(stdout_data)
+      print('## stderr:')
+      print(stderr_data)
+      sys.exit(2)
+    env = _ExtractImportantEnvironment(stdout_data)
     env['PATH'] = runtime_dirs + ';' + env['PATH']
 
     if cpu == target_cpu:
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index 9a145c4..1049101 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -1394,6 +1394,20 @@
   __ Bind(&init_done);
   __ Comment("Copy frame to SuspendState");
 
+#ifdef DEBUG
+  {
+    // Verify that SuspendState.frame_size == kFrameSize.
+    Label okay;
+    __ LoadFromOffset(
+        kTemp,
+        FieldAddress(kSuspendState, target::SuspendState::frame_size_offset()));
+    __ CompareRegisters(kTemp, kFrameSize);
+    __ BranchIf(EQUAL, &okay);
+    __ Breakpoint();
+    __ Bind(&okay);
+  }
+#endif
+
   __ LoadFromOffset(
       kTemp, Address(FPREG, kSavedCallerPcSlotFromFp * target::kWordSize));
   __ StoreToOffset(
@@ -1412,6 +1426,8 @@
 
 #ifdef DEBUG
   {
+    // Verify that kSuspendState matches :suspend_state in the copied stack
+    // frame.
     Label okay;
     __ LoadFromOffset(
         kTemp,
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index ed63079..da1ffb1 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -222,8 +222,8 @@
   Timeline::stream_##name##_.set_enabled(false);
   TIMELINE_STREAM_LIST(TIMELINE_STREAM_DISABLE)
 #undef TIMELINE_STREAM_DISABLE
-  Timeline::Clear();
   RecorderLock::WaitForShutdown();
+  Timeline::Clear();
   delete recorder_;
   recorder_ = NULL;
   if (enabled_streams_ != NULL) {
diff --git a/sdk/lib/core/weak.dart b/sdk/lib/core/weak.dart
index 0da4c16..e7832d8 100644
--- a/sdk/lib/core/weak.dart
+++ b/sdk/lib/core/weak.dart
@@ -93,8 +93,8 @@
 /// /// ```
 /// /// final cached = CachedComputation(
 /// ///     () => jsonDecode(someJsonSource) as Object);
-/// /// print(cached.result);
-/// /// print(cached.result);
+/// /// print(cached.result); // Executes computation.
+/// /// print(cached.result); // Most likely uses cache.
 /// /// ```
 /// class CachedComputation<R extends Object> {
 ///   final R Function() computation;
@@ -164,8 +164,8 @@
 ///   factory Database.connect() {
 ///     // Wraps the connection in a nice user API,
 ///     // *and* closes connection if the user forgets to.
-///     var connection = DBConnection.connect();
-///     var wrapper = Database._fromConnection(connection);
+///     final connection = DBConnection.connect();
+///     final wrapper = Database._fromConnection(connection);
 ///     // Get finalizer callback when `wrapper` is no longer reachable.
 ///     _finalizer.attach(wrapper, connection, detach: wrapper);
 ///     return wrapper;
@@ -253,8 +253,8 @@
   ///   factory Database.connect() {
   ///     // Wraps the connection in a nice user API,
   ///     // *and* closes connection if the user forgets to.
-  ///     var connection = DBConnection.connect();
-  ///     var wrapper = Database._fromConnection();
+  ///     final connection = DBConnection.connect();
+  ///     final wrapper = Database._fromConnection();
   ///     // Get finalizer callback when `wrapper` is no longer reachable.
   ///     _finalizer.attach(wrapper, connection, detach: wrapper);
   ///     return wrapper;
diff --git a/sdk/lib/ffi/allocation.dart b/sdk/lib/ffi/allocation.dart
index 45673cc..0ffdbbe 100644
--- a/sdk/lib/ffi/allocation.dart
+++ b/sdk/lib/ffi/allocation.dart
@@ -4,7 +4,53 @@
 
 part of dart.ffi;
 
+// Examples can assume:
+// late Allocator allocator;
+// late Allocator calloc;
+
 /// Manages memory on the native heap.
+///
+/// When allocating memory, prefer calling this allocator directly as a
+/// function (see [AllocatorAlloc.call] for details).
+///
+/// This interface provides only the [allocate] method to allocate a block of
+/// bytes, and the [free] method to release such a block again.
+/// Implementations only need to provide those two methods.
+/// The [AllocatorAlloc.call] extension method is defined in terms of those
+/// lower-level operations.
+///
+/// An example of an allocator wrapping another to count the number of
+/// allocations:
+///
+/// ```dart
+/// class CountingAllocator implements Allocator {
+///   final Allocator _wrappedAllocator;
+///   int _totalAllocations = 0;
+///   int _nonFreedAllocations = 0;
+///
+///   CountingAllocator([Allocator? allocator])
+///       : _wrappedAllocator = allocator ?? calloc;
+///
+///   int get totalAllocations => _totalAllocations;
+///
+///   int get nonFreedAllocations => _nonFreedAllocations;
+///
+///   @override
+///   Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
+///     final result =
+///         _wrappedAllocator.allocate<T>(byteCount, alignment: alignment);
+///     _totalAllocations++;
+///     _nonFreedAllocations++;
+///     return result;
+///   }
+///
+///   @override
+///   void free(Pointer<NativeType> pointer) {
+///     _wrappedAllocator.free(pointer);
+///     _nonFreedAllocations--;
+///   }
+/// }
+/// ```
 @Since('2.12')
 abstract class Allocator {
   /// This interface is meant to be implemented, not extended or mixed in.
@@ -17,6 +63,24 @@
   /// If [alignment] is provided, the allocated memory will be at least aligned
   /// to [alignment] bytes.
   ///
+  /// To allocate a multiple of `sizeOf<T>()` bytes, call the allocator
+  /// directly as a function: `allocator<T>(count)` (see [AllocatorAlloc.call]
+  /// for details).
+  ///
+  /// ```dart
+  /// // This allocates two bytes. If you intended two Int32's, this is an
+  /// // error.
+  /// allocator.allocate<Int32>(2);
+  ///
+  /// // This allocates eight bytes, which is enough space for two Int32's.
+  /// // However, this is not the idiomatic way.
+  /// allocator.allocate<Int32>(sizeOf<Int32>() * 2);
+  ///
+  /// // The idiomatic way to allocate space for two Int32 is to call the
+  /// // allocator directly as a function.
+  /// allocator<Int32>(2);
+  /// ```
+  ///
   /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
   /// satisfied.
   Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment});
@@ -31,9 +95,19 @@
 /// Extension on [Allocator] to provide allocation with [NativeType].
 @Since('2.12')
 extension AllocatorAlloc on Allocator {
-  /// Allocates `sizeOf<T>() * count` bytes of memory using
-  /// `allocator.allocate`.
+  /// Allocates `sizeOf<T>() * count` bytes of memory using [allocate].
+  ///
+  /// ```dart
+  /// // This allocates eight bytes, which is enough space for two Int32's.
+  /// allocator<Int32>(2);
+  /// ```
   ///
   /// This extension method must be invoked with a compile-time constant [T].
+  ///
+  /// To allocate a specific number of bytes, not just a multiple of
+  /// `sizeOf<T>()`, use [allocate].
+  /// To allocate with a non constant [T], use [allocate].
+  /// Prefer [call] for normal use, and use [allocate] for implementing an
+  /// [Allocator] in terms of other allocators.
   external Pointer<T> call<T extends NativeType>([int count = 1]);
 }
diff --git a/tests/language/inference_update_1/horizontal_inference_enabled_test.dart b/tests/language/inference_update_1/horizontal_inference_enabled_test.dart
index 1cbeeda..d7fc7e1 100644
--- a/tests/language/inference_update_1/horizontal_inference_enabled_test.dart
+++ b/tests/language/inference_update_1/horizontal_inference_enabled_test.dart
@@ -71,7 +71,7 @@
       .expectStaticType<Exactly<List<int>>>();
 }
 
-testLongDepedencyChain(
+testLongDependencyChain(
     V Function<T, U, V>(T Function(), U Function(T), V Function(U)) f) {
   f(() => [0], (x) => x.single..expectStaticType<Exactly<int>>(),
           (y) => {y}..expectStaticType<Exactly<Set<int>>>())
diff --git a/tools/VERSION b/tools/VERSION
index b748ba7..1604640 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 77
+PRERELEASE 78
 PRERELEASE_PATCH 0
\ No newline at end of file