Version 2.18.0-19.0.dev

Merge commit 'af39b6b9ca969d1a1fd961451c529c297df7a84b' into 'dev'
diff --git a/DEPS b/DEPS
index db8fe96..b87899a 100644
--- a/DEPS
+++ b/DEPS
@@ -165,7 +165,7 @@
   "test_reflective_loader_rev": "fcfce37666672edac849d2af6dffc0f8df236a94",
   "test_rev": "b6aba5544628730b7d6a38eae1aef9117a1bb235",
   "typed_data_rev": "29ce5a92b03326d0b8035916ac04f528874994bd",
-  "usage_rev": "f0cb8f7cce8b675255c81488dbab8cf9f2f56404",
+  "usage_rev": "e85d575d6decb921c57a43b9844bba3607479f56",
   "vector_math_rev": "0cbed0914d49a6a44555e6d5444c438a4a4c3fc1",
   "watcher_rev": "f76997ab0c857dc5537ac0975a9ada92b54ef949",
   "webdriver_rev": "ff5ccb1522edf4bed578ead4d65e0cbc1f2c4f02",
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart
index 7205ecd..01d4004 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart
@@ -55,7 +55,7 @@
       SerializationMode serializationMode,
       String programPath,
       List<String> arguments) async {
-    late ServerSocket serverSocket;
+    ServerSocket serverSocket;
     // Try an ipv6 address loopback first, and fall back on ipv4.
     try {
       serverSocket = await ServerSocket.bind(InternetAddress.loopbackIPv6, 0);
diff --git a/pkg/analyzer/lib/src/dart/analysis/results.dart b/pkg/analyzer/lib/src/dart/analysis/results.dart
index d43672d..0c957ae 100644
--- a/pkg/analyzer/lib/src/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/results.dart
@@ -274,16 +274,26 @@
       : super(session, path, uri, lineInfo, isPart);
 }
 
-class _DeclarationByElementLocator extends GeneralizingAstVisitor<void> {
+/// A visitor which locates the [AstNode] which declares [element].
+class _DeclarationByElementLocator extends UnifyingAstVisitor<void> {
+  // TODO: This visitor could be further optimized by special casing each static
+  // type of [element]. For example, for library-level elements (classes etc),
+  // we can iterate over the compilation unit's declarations.
+
   final Element element;
+  final int _nameOffset;
   AstNode? result;
 
-  _DeclarationByElementLocator(this.element);
+  _DeclarationByElementLocator(this.element) : _nameOffset = element.nameOffset;
 
   @override
   void visitNode(AstNode node) {
     if (result != null) return;
 
+    if (node.endToken.end < _nameOffset || node.offset > _nameOffset) {
+      return;
+    }
+
     if (element is ClassElement) {
       if (node is ClassOrMixinDeclaration) {
         if (_hasOffset(node.name)) {
@@ -358,10 +368,12 @@
       }
     }
 
-    super.visitNode(node);
+    if (result == null) {
+      node.visitChildren(this);
+    }
   }
 
   bool _hasOffset(AstNode? node) {
-    return node?.offset == element.nameOffset;
+    return node?.offset == _nameOffset;
   }
 }
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 6f7a96a..8e83316 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -184,6 +184,8 @@
   // Experimental flags.
   static const String resolveOnly = '--resolve-only';
 
+  static const String cfeConstants = '--cfe-constants';
+
   // `--no-shipping` and `--canary` control sets of flags. For simplicity, these
   // flags live in options.dart.
   // Shipping features default to on, but can be disabled individually. All
diff --git a/pkg/compiler/tool/modular_test_suite.dart b/pkg/compiler/tool/modular_test_suite.dart
index 491d6ad..430c81a 100644
--- a/pkg/compiler/tool/modular_test_suite.dart
+++ b/pkg/compiler/tool/modular_test_suite.dart
@@ -26,7 +26,9 @@
           FullDillCompilationStep(onlyOnSdk: true),
           ModularAnalysisStep(onlyOnSdk: true),
           ModularAnalysisStep(),
-          ConcatenateDillsStep(useModularAnalysis: true),
+          // TODO(joshualitt): Re-enable ConcatenateDillStep after it works
+          // correctly alongside modular analysis.
+          // ConcatenateDillsStep(useModularAnalysis: true),
           ComputeClosedWorldStep(useModularAnalysis: true),
           GlobalAnalysisStep(),
           Dart2jsCodegenStep(codeId0),
diff --git a/pkg/compiler/tool/modular_test_suite_helper.dart b/pkg/compiler/tool/modular_test_suite_helper.dart
index 98985b9..91525b6 100644
--- a/pkg/compiler/tool/modular_test_suite_helper.dart
+++ b/pkg/compiler/tool/modular_test_suite_helper.dart
@@ -277,6 +277,7 @@
         '${Flags.sources}=${sources.join(',')}'
       else
         '${Flags.inputDill}=${toUri(module, dillId)}',
+      '${Flags.cfeConstants}',
       if (dillDependencies.isNotEmpty)
         '--dill-dependencies=${dillDependencies.join(',')}',
       '--out=${toUri(module, modularUpdatedDillId)}',
@@ -363,10 +364,13 @@
 class ComputeClosedWorldStep extends IOModularStep {
   final bool useModularAnalysis;
 
+  DataId get idForDill =>
+      useModularAnalysis ? modularUpdatedDillId : fullDillId;
+
   ComputeClosedWorldStep({this.useModularAnalysis});
 
   List<DataId> get dependencies => [
-        fullDillId,
+        idForDill,
         if (useModularAnalysis) modularDataId,
       ];
 
@@ -391,6 +395,8 @@
     if (_options.verbose)
       print("\nstep: dart2js compute closed world on $module");
     Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+    Iterable<String> dillDependencies =
+        transitiveDependencies.map((m) => '${toUri(m, idForDill)}');
     List<String> dataDependencies = transitiveDependencies
         .map((m) => '${toUri(m, modularDataId)}')
         .toList();
@@ -401,8 +407,12 @@
       // TODO(sigmund): remove this dependency on libraries.json
       if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
       '${Flags.entryUri}=$fakeRoot${module.mainSource}',
-      '${Flags.inputDill}=${toUri(module, fullDillId)}',
+      '${Flags.inputDill}=${toUri(module, idForDill)}',
       for (String flag in flags) '--enable-experiment=$flag',
+      if (useModularAnalysis) ...[
+        '${Flags.dillDependencies}=${dillDependencies.join(',')}',
+        '${Flags.readModularAnalysis}=${dataDependencies.join(',')}',
+      ],
       '${Flags.writeClosedWorld}=${toUri(module, closedWorldId)}',
       Flags.noClosedWorldInData,
       '--out=${toUri(module, globalUpdatedDillId)}',
diff --git a/runtime/bin/ffi_test/clobber_arm64.S b/runtime/bin/ffi_test/clobber_arm64.S
index 38105d5..f86f277 100644
--- a/runtime/bin/ffi_test/clobber_arm64.S
+++ b/runtime/bin/ffi_test/clobber_arm64.S
@@ -3,9 +3,11 @@
 #if defined(__linux__) || defined(__FreeBSD__) /* HOST_OS_LINUX */
 .globl ClobberAndCall
 .type ClobberAndCall, @function
+.align 4
 ClobberAndCall:
 #else /* HOST_OS_MACOS */
 .globl _ClobberAndCall
+.align 4
 _ClobberAndCall:
 #endif
 
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 68b49e4..462413c 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -234,8 +234,8 @@
   P(use_field_guards, bool, true, "Use field guards and track field types")    \
   C(use_osr, false, true, bool, true, "Use OSR")                               \
   P(use_slow_path, bool, false, "Whether to avoid inlined fast paths.")        \
-  R(verbose_gc, false, bool, false, "Enables verbose GC.")                     \
-  R(verbose_gc_hdr, 40, int, 40, "Print verbose GC header interval.")          \
+  P(verbose_gc, bool, false, "Enables verbose GC.")                            \
+  P(verbose_gc_hdr, int, 40, "Print verbose GC header interval.")              \
   R(verify_after_gc, false, bool, false,                                       \
     "Enables heap verification after GC.")                                     \
   R(verify_before_gc, false, bool, false,                                      \
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index 481bafe..a57bcfc 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -522,7 +522,8 @@
                                     ? VMTag::kGCIdleTagId
                                     : VMTag::kGCOldSpaceTagId);
     TIMELINE_FUNCTION_GC_DURATION(thread, "CollectOldGeneration");
-    old_space_.CollectGarbage(type == GCType::kMarkCompact, true /* finish */);
+    old_space_.CollectGarbage(thread, /*compact=*/type == GCType::kMarkCompact,
+                              /*finalize=*/true);
     RecordAfterGC(type);
     PrintStats();
 #if defined(SUPPORT_TIMELINE)
@@ -623,7 +624,7 @@
                                   ? VMTag::kGCIdleTagId
                                   : VMTag::kGCOldSpaceTagId);
   TIMELINE_FUNCTION_GC_DURATION(thread, "StartConcurrentMarking");
-  old_space_.CollectGarbage(/*compact=*/false, /*finalize=*/false);
+  old_space_.CollectGarbage(thread, /*compact=*/false, /*finalize=*/false);
   RecordAfterGC(GCType::kStartConcurrentMark);
   PrintStats();
 #if defined(SUPPORT_TIMELINE)
@@ -1019,8 +1020,7 @@
   stats_.before_.micros_ = OS::GetCurrentMonotonicMicros();
   stats_.before_.new_ = new_space_.GetCurrentUsage();
   stats_.before_.old_ = old_space_.GetCurrentUsage();
-  for (int i = 0; i < GCStats::kTimeEntries; i++)
-    stats_.times_[i] = 0;
+  stats_.before_.store_buffer_ = isolate_group_->store_buffer()->Size();
 }
 
 static double AvgCollectionPeriod(int64_t run_time, intptr_t collections) {
@@ -1043,6 +1043,7 @@
   }
   stats_.after_.new_ = new_space_.GetCurrentUsage();
   stats_.after_.old_ = old_space_.GetCurrentUsage();
+  stats_.after_.store_buffer_ = isolate_group_->store_buffer()->Size();
 #ifndef PRODUCT
   // For now we'll emit the same GC events on all isolates.
   if (Service::gc_stream.enabled()) {
@@ -1114,24 +1115,20 @@
 }
 
 void Heap::PrintStats() {
-#if !defined(PRODUCT)
   if (!FLAG_verbose_gc) return;
 
   if ((FLAG_verbose_gc_hdr != 0) &&
       (((stats_.num_ - 1) % FLAG_verbose_gc_hdr) == 0)) {
     OS::PrintErr(
-        "[              |                          |     |       |      "
-        "| new gen     | new gen     | new gen "
-        "| old gen       | old gen       | old gen     "
-        "| sweep | safe- | roots/| stbuf/| tospc/| weaks/  ]\n"
-        "[ GC isolate   | space (reason)           | GC# | start | time "
-        "| used (MB)   | capacity MB | external"
-        "| used (MB)     | capacity (MB) | external MB "
-        "| thread| point |marking| reset | sweep |swplrge  ]\n"
+        "[              |                          |     |       |      | new "
+        "gen     | new gen     | new gen | old gen       | old gen       | old "
+        "gen     |  store  | delta used   ]\n"
+        "[ GC isolate   | space (reason)           | GC# | start | time | used "
+        "(MB)   | capacity MB | external| used (MB)     | capacity (MB) | "
+        "external MB |  buffer | new  | old   ]\n"
         "[              |                          |     |  (s)  | (ms) "
-        "|before| after|before| after| b4 |aftr"
-        "| before| after | before| after |before| after"
-        "| (ms)  | (ms)  | (ms)  | (ms)  | (ms)  | (ms)    ]\n");
+        "|before| after|before| after| b4 |aftr| before| after | before| after "
+        "|before| after| b4 |aftr| (MB) | (MB)  ]\n");
   }
 
   // clang-format off
@@ -1146,7 +1143,8 @@
     "%6.1f, %6.1f, "   // old gen: in use before/after
     "%6.1f, %6.1f, "   // old gen: capacity before/after
     "%5.1f, %5.1f, "   // old gen: external before/after
-    "%6.2f, %6.2f, %6.2f, %6.2f, %6.2f, %6.2f, "  // times
+    "%3" Pd ", %3" Pd ", "   // store buffer: before/after
+    "%5.1f, %6.1f, "   // delta used: new gen/old gen
     "]\n",  // End with a comma to make it easier to import in spreadsheets.
     isolate_group()->source()->name,
     GCTypeToString(stats_.type_),
@@ -1167,14 +1165,13 @@
     WordsToMB(stats_.after_.old_.capacity_in_words),
     WordsToMB(stats_.before_.old_.external_in_words),
     WordsToMB(stats_.after_.old_.external_in_words),
-    MicrosecondsToMilliseconds(stats_.times_[0]),
-    MicrosecondsToMilliseconds(stats_.times_[1]),
-    MicrosecondsToMilliseconds(stats_.times_[2]),
-    MicrosecondsToMilliseconds(stats_.times_[3]),
-    MicrosecondsToMilliseconds(stats_.times_[4]),
-    MicrosecondsToMilliseconds(stats_.times_[5]));
+    stats_.before_.store_buffer_,
+    stats_.after_.store_buffer_,
+    WordsToMB(stats_.after_.new_.used_in_words -
+              stats_.before_.new_.used_in_words),
+    WordsToMB(stats_.after_.old_.used_in_words -
+              stats_.before_.old_.used_in_words));
   // clang-format on
-#endif  // !defined(PRODUCT)
 }
 
 void Heap::PrintStatsToTimeline(TimelineEventScope* event, GCReason reason) {
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index 179122d..112c59f 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -256,12 +256,6 @@
   void ForwardWeakEntries(ObjectPtr before_object, ObjectPtr after_object);
   void ForwardWeakTables(ObjectPointerVisitor* visitor);
 
-  // Stats collection.
-  void RecordTime(int id, int64_t micros) {
-    ASSERT((id >= 0) && (id < GCStats::kTimeEntries));
-    stats_.times_[id] = micros;
-  }
-
   void UpdateGlobalMaxUsed();
 
   static bool IsAllocatableInNewSpace(intptr_t size) {
@@ -314,16 +308,14 @@
       int64_t micros_;
       SpaceUsage new_;
       SpaceUsage old_;
+      intptr_t store_buffer_;
 
      private:
       DISALLOW_COPY_AND_ASSIGN(Data);
     };
 
-    enum { kTimeEntries = 6 };
-
     Data before_;
     Data after_;
-    int64_t times_[kTimeEntries];
 
    private:
     DISALLOW_COPY_AND_ASSIGN(GCStats);
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index 6c7c909..f1c3ed4 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -1100,7 +1100,7 @@
   }
 }
 
-void PageSpace::CollectGarbage(bool compact, bool finalize) {
+void PageSpace::CollectGarbage(Thread* thread, bool compact, bool finalize) {
   ASSERT(GrowthControlState());
 
   if (!finalize) {
@@ -1112,16 +1112,11 @@
 #endif
   }
 
-  Thread* thread = Thread::Current();
-  const int64_t pre_safe_point = OS::GetCurrentMonotonicMicros();
   GcSafepointOperationScope safepoint_scope(thread);
 
-  const int64_t pre_wait_for_sweepers = OS::GetCurrentMonotonicMicros();
   // Wait for pending tasks to complete and then account for the driver task.
-  Phase waited_for;
   {
     MonitorLocker locker(tasks_lock());
-    waited_for = phase();
     if (!finalize &&
         (phase() == kMarking || phase() == kAwaitingFinalization)) {
       // Concurrent mark is already running.
@@ -1136,26 +1131,11 @@
     set_tasks(1);
   }
 
-  if (FLAG_verbose_gc) {
-    const int64_t wait =
-        OS::GetCurrentMonotonicMicros() - pre_wait_for_sweepers;
-    if (waited_for == kMarking) {
-      THR_Print("Waited %" Pd64 " us for concurrent marking to finish.\n",
-                wait);
-    } else if (waited_for == kSweepingRegular || waited_for == kSweepingLarge) {
-      THR_Print("Waited %" Pd64 " us for concurrent sweeping to finish.\n",
-                wait);
-    }
-  }
-
   // Ensure that all threads for this isolate are at a safepoint (either
   // stopped or in native code). We have guards around Newgen GC and oldgen GC
   // to ensure that if two threads are racing to collect at the same time the
   // loser skips collection and goes straight to allocation.
-  {
-    CollectGarbageHelper(compact, finalize, pre_wait_for_sweepers,
-                         pre_safe_point);
-  }
+  CollectGarbageHelper(thread, compact, finalize);
 
   // Done, reset the task count.
   {
@@ -1165,11 +1145,9 @@
   }
 }
 
-void PageSpace::CollectGarbageHelper(bool compact,
-                                     bool finalize,
-                                     int64_t pre_wait_for_sweepers,
-                                     int64_t pre_safe_point) {
-  Thread* thread = Thread::Current();
+void PageSpace::CollectGarbageHelper(Thread* thread,
+                                     bool compact,
+                                     bool finalize) {
   ASSERT(thread->IsAtSafepoint());
   auto isolate_group = heap_->isolate_group();
   ASSERT(isolate_group == IsolateGroup::Current());
@@ -1182,7 +1160,7 @@
       [&](Isolate* isolate) { isolate->field_table()->FreeOldTables(); },
       /*at_safepoint=*/true);
 
-  NoSafepointScope no_safepoints;
+  NoSafepointScope no_safepoints(thread);
 
   if (FLAG_print_free_list_before_gc) {
     for (intptr_t i = 0; i < num_freelists_; i++) {
@@ -1224,8 +1202,6 @@
   delete marker_;
   marker_ = NULL;
 
-  int64_t mid1 = OS::GetCurrentMonotonicMicros();
-
   // Abandon the remainder of the bump allocation block.
   AbandonBumpAllocation();
   // Reset the freelists and setup sweeping.
@@ -1233,19 +1209,15 @@
     freelists_[i].Reset();
   }
 
-  int64_t mid2 = OS::GetCurrentMonotonicMicros();
-  int64_t mid3 = 0;
+  if (FLAG_verify_before_gc) {
+    OS::PrintErr("Verifying before sweeping...");
+    heap_->VerifyGC(kAllowMarked);
+    OS::PrintErr(" done.\n");
+  }
 
   {
-    if (FLAG_verify_before_gc) {
-      OS::PrintErr("Verifying before sweeping...");
-      heap_->VerifyGC(kAllowMarked);
-      OS::PrintErr(" done.\n");
-    }
-
     // Executable pages are always swept immediately to simplify
     // code protection.
-
     TIMELINE_FUNCTION_GC_DURATION(thread, "SweepExecutable");
     GCSweeper sweeper;
     OldPage* prev_page = NULL;
@@ -1263,8 +1235,6 @@
       // Advance to the next page.
       page = next_page;
     }
-
-    mid3 = OS::GetCurrentMonotonicMicros();
   }
 
   bool has_reservation = MarkReservation();
@@ -1315,13 +1285,6 @@
   page_space_controller_.EvaluateGarbageCollection(
       usage_before, GetCurrentUsage(), start, end);
 
-  heap_->RecordTime(kConcurrentSweep, pre_safe_point - pre_wait_for_sweepers);
-  heap_->RecordTime(kSafePoint, start - pre_safe_point);
-  heap_->RecordTime(kMarkObjects, mid1 - start);
-  heap_->RecordTime(kResetFreeLists, mid2 - mid1);
-  heap_->RecordTime(kSweepPages, mid3 - mid2);
-  heap_->RecordTime(kSweepLargePages, end - mid3);
-
   if (FLAG_print_free_list_after_gc) {
     for (intptr_t i = 0; i < num_freelists_; i++) {
       OS::PrintErr("After GC: Freelist %" Pd "\n", i);
@@ -1748,8 +1711,8 @@
   if (FLAG_log_growth || FLAG_verbose_gc) {
     THR_Print("%s: threshold=%" Pd "kB, idle_threshold=%" Pd "kB, reason=%s\n",
               heap_->isolate_group()->source()->name,
-              hard_gc_threshold_in_words_ / KBInWords,
-              idle_gc_threshold_in_words_ / KBInWords, reason);
+              RoundWordsToKB(hard_gc_threshold_in_words_),
+              RoundWordsToKB(idle_gc_threshold_in_words_), reason);
   }
 }
 
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index 5a3c5c0..fca17a2 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -408,7 +408,7 @@
                        OldPage::PageType type) const;
 
   // Collect the garbage in the page space using mark-sweep or mark-compact.
-  void CollectGarbage(bool compact, bool finalize);
+  void CollectGarbage(Thread* thread, bool compact, bool finalize);
 
   void AddRegionsToObjectSet(ObjectSet* set) const;
 
@@ -573,10 +573,7 @@
   void FreeLargePage(OldPage* page, OldPage* previous_page);
   void FreePages(OldPage* pages);
 
-  void CollectGarbageHelper(bool compact,
-                            bool finalize,
-                            int64_t pre_wait_for_sweepers,
-                            int64_t pre_safe_point);
+  void CollectGarbageHelper(Thread* thread, bool compact, bool finalize);
   void SweepLarge();
   void Sweep(bool exclusive);
   void ConcurrentSweep(IsolateGroup* isolate_group);
diff --git a/runtime/vm/heap/pointer_block.cc b/runtime/vm/heap/pointer_block.cc
index daedab8..672bdc0 100644
--- a/runtime/vm/heap/pointer_block.cc
+++ b/runtime/vm/heap/pointer_block.cc
@@ -228,6 +228,11 @@
   return (full_.length() + partial_.length()) > kMaxNonEmpty;
 }
 
+intptr_t StoreBuffer::Size() {
+  MonitorLocker ml(&monitor_);
+  return full_.length() + partial_.length();
+}
+
 void StoreBuffer::VisitObjectPointers(ObjectPointerVisitor* visitor) {
   for (Block* block = full_.Peek(); block != NULL; block = block->next()) {
     block->VisitObjectPointers(visitor);
diff --git a/runtime/vm/heap/pointer_block.h b/runtime/vm/heap/pointer_block.h
index fb10fa6..1b6fd5a 100644
--- a/runtime/vm/heap/pointer_block.h
+++ b/runtime/vm/heap/pointer_block.h
@@ -268,6 +268,7 @@
   // Check whether non-empty blocks have exceeded kMaxNonEmpty (but takes no
   // action).
   bool Overflowed();
+  intptr_t Size();
 
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
 };
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index d2f7de4..c94c042 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -1742,9 +1742,6 @@
   Thread* thread = Thread::Current();
   GcSafepointOperationScope safepoint_scope(thread);
 
-  int64_t safe_point = OS::GetCurrentMonotonicMicros();
-  heap_->RecordTime(kSafePoint, safe_point - start);
-
   // Scavenging is not reentrant. Make sure that is the case.
   ASSERT(!scavenging_);
   scavenging_ = true;
diff --git a/runtime/vm/heap/scavenger.h b/runtime/vm/heap/scavenger.h
index 5a93aec..bfd8fc5 100644
--- a/runtime/vm/heap/scavenger.h
+++ b/runtime/vm/heap/scavenger.h
@@ -180,6 +180,13 @@
   bool Contains(uword addr) const;
   void WriteProtect(bool read_only);
 
+  intptr_t used_in_words() const {
+    intptr_t size = 0;
+    for (const NewPage* p = head_; p != nullptr; p = p->next()) {
+      size += (p->object_end() - p->object_start());
+    }
+    return size >> kWordSizeLog2;
+  }
   intptr_t capacity_in_words() const { return capacity_in_words_; }
   intptr_t max_capacity_in_words() const { return max_capacity_in_words_; }
 
@@ -284,7 +291,7 @@
 
   int64_t UsedInWords() const {
     MutexLocker ml(&space_lock_);
-    return to_->capacity_in_words();
+    return to_->used_in_words();
   }
   int64_t CapacityInWords() const { return to_->max_capacity_in_words(); }
   int64_t ExternalInWords() const { return external_size_ >> kWordSizeLog2; }
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index d009f9a..bdb1a01 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -96,12 +96,19 @@
 
   /// Throws [error] with associated stack trace [stackTrace].
   ///
-  /// If [error] extends [Error] and has not yet been thrown,
-  /// its [stackTrace] is set as well, just as if it was thrown by a `throw`.
-  /// The actual stack trace captured along with the [error],
-  /// or set on [error] if it is an [Error],
-  /// may not be the [stackTrace] object itself,
-  /// but will be a stack trace with the same content.
+  /// Behaves like `throw error` would
+  /// if the [current stack trace][StackTrace.current] was [stackTrace]
+  /// at the time of the `throw`.
+  ///
+  /// Like for a `throw`, if [error] extends [Error], and it has not been
+  /// thrown before, its [Error.stackTrace] property will be set to
+  /// the [stackTrace].
+  ///
+  /// This function does not guarantee to preserve the identity of [stackTrace].
+  /// The [StackTrace] object that is caught by a `try`/`catch` of
+  /// this error, or which is set as the [Error.stackTrace] of an [error],
+  /// may not be the same [stackTrace] object provided as argument,
+  /// but it will have the same contents according to [StackTrace.toString].
   @Since("2.16")
   static Never throwWithStackTrace(Object error, StackTrace stackTrace) {
     checkNotNullable(error, "error");
diff --git a/sdk/lib/core/int.dart b/sdk/lib/core/int.dart
index 32c6682..e2465cc 100644
--- a/sdk/lib/core/int.dart
+++ b/sdk/lib/core/int.dart
@@ -116,7 +116,7 @@
   /// Shift the bits of this integer to the left by [shiftAmount].
   ///
   /// Shifting to the left makes the number larger, effectively multiplying
-  /// the number by `pow(2, shiftIndex)`.
+  /// the number by `pow(2, shiftAmount)`.
   ///
   /// There is no limit on the size of the result. It may be relevant to
   /// limit intermediate values by using the "and" operator with a suitable
@@ -136,7 +136,7 @@
   ///
   /// Shifting to the right makes the number smaller and drops the least
   /// significant bits, effectively doing an integer division by
-  /// `pow(2, shiftIndex)`.
+  /// `pow(2, shiftAmount)`.
   ///
   /// It is an error if [shiftAmount] is negative.
   ///
diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart
index 2a67153..ea6a330 100644
--- a/sdk/lib/typed_data/typed_data.dart
+++ b/sdk/lib/typed_data/typed_data.dart
@@ -15,6 +15,7 @@
 
 import "dart:_internal" show Since, UnmodifiableListBase;
 
+@Since("2.10")
 export "dart:_internal" show BytesBuilder;
 
 part "unmodifiable_typed_data.dart";
diff --git a/tools/OWNERS b/tools/OWNERS
index fefa34e..d3ed883 100644
--- a/tools/OWNERS
+++ b/tools/OWNERS
@@ -3,6 +3,7 @@
 # Groups administrate themselves.
 per-file OWNERS_ANALYZER=file:OWNERS_ANALYZER
 per-file OWNERS_CFE=file:OWNERS_CFE
+per-file OWNERS_ECOSYSTEM=file:OWNERS_ECOSYSTEM
 per-file OWNERS_FOUNDATION=file:OWNERS_FOUNDATION
 per-file OWNERS_INFRA=file:OWNERS_INFRA
 per-file OWNERS_PRODUCT=file:OWNERS_PRODUCT
diff --git a/tools/OWNERS_ECOSYSTEM b/tools/OWNERS_ECOSYSTEM
new file mode 100644
index 0000000..1b71776
--- /dev/null
+++ b/tools/OWNERS_ECOSYSTEM
@@ -0,0 +1,5 @@
+devoncarew@google.com
+kevmoo@google.com
+mit@google.com
+nbosch@google.com
+omersa@google.com
diff --git a/tools/OWNERS_ENG b/tools/OWNERS_ENG
index ef746ec..0fc41bb 100644
--- a/tools/OWNERS_ENG
+++ b/tools/OWNERS_ENG
@@ -1,6 +1,7 @@
 # All engineering teams
 file:OWNERS_ANALYZER
 file:OWNERS_CFE
+file:OWNERS_ECOSYSTEM
 file:OWNERS_FOUNDATION
 file:OWNERS_INFRA
 file:OWNERS_PUB
diff --git a/tools/VERSION b/tools/VERSION
index fd91a2d..d5f67ab 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 18
+PRERELEASE 19
 PRERELEASE_PATCH 0
\ No newline at end of file