Version 2.14.0-106.0.dev

Merge commit '02a8dd90e11286eb8427a12011c0fbeebe50f50f' into 'dev'
diff --git a/pkg/native_stack_traces/CHANGELOG.md b/pkg/native_stack_traces/CHANGELOG.md
index ae7d875..7c60f28 100644
--- a/pkg/native_stack_traces/CHANGELOG.md
+++ b/pkg/native_stack_traces/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog
 
+## 0.4.3
+
+- Exported some more of the ELF utilities for use in Dart tests.
+
 ## 0.4.2
 
 - When decoding a stack trace, frames corresponding to the functions
diff --git a/pkg/native_stack_traces/lib/elf.dart b/pkg/native_stack_traces/lib/elf.dart
index de32cd3..3b1624b 100644
--- a/pkg/native_stack_traces/lib/elf.dart
+++ b/pkg/native_stack_traces/lib/elf.dart
@@ -2,7 +2,7 @@
 // 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.
 
-export 'src/elf.dart' show Elf, Symbol;
+export 'src/elf.dart' show Elf, Section, Symbol;
 export 'src/constants.dart'
     show
         isolateDataSymbolName,
diff --git a/pkg/native_stack_traces/pubspec.yaml b/pkg/native_stack_traces/pubspec.yaml
index d398708..bdf1f94 100644
--- a/pkg/native_stack_traces/pubspec.yaml
+++ b/pkg/native_stack_traces/pubspec.yaml
@@ -1,6 +1,6 @@
 name: native_stack_traces
 description: Utilities for working with non-symbolic stack traces.
-version: 0.4.2
+version: 0.4.3
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/native_stack_traces
 
diff --git a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
index 8719b76..212571a 100644
--- a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
+++ b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
@@ -189,12 +189,17 @@
     final expectedSize =
         profile.nodes.fold<int>(0, (size, n) => size + n.selfSize);
 
+    // May not be ELF, but another format.
+    final elf = Elf.fromFile(snapshotPath);
+
     var checkedSize = false;
     if (!useAsm) {
-      // Verify that the total size of the snapshot text and data sections is
-      // the same as the sum of the shallow sizes of all objects in the profile.
-      // This ensures that all bytes are accounted for in some way.
-      final elf = Elf.fromFile(snapshotPath);
+      // Verify that the total size of the snapshot text and data section
+      // symbols is the same as the sum of the shallow sizes of all objects in
+      // the profile. This ensures that all bytes are accounted for in some way.
+      //
+      // We only check this when generating ELF directly because that's when
+      // we're guaranteed the symbols will have non-zero size.
       Expect.isNotNull(elf);
       elf!; // To refine type to non-nullable version.
 
@@ -215,10 +220,54 @@
 
       Expect.equals(
           expectedSize, actualSize, "failed on $description snapshot");
+      Expect.equals(expectedSize, actualSize,
+          "symbol size check failed on $description snapshot");
+      checkedSize = true;
+    }
+
+    // See Elf::kPages in runtime/vm/elf.h, which is also used for assembly
+    // padding.
+    final segmentAlignment = 16 * 1024;
+
+    if (elf != null) {
+      // Verify that the total size of the snapshot text and data sections is
+      // approximately the sum of the shallow sizes of all objects in the
+      // profile. As sections might be merged by the assembler when useAsm is
+      // true, we need to account for possible padding.
+      final textSections = elf.namedSections(".text");
+      Expect.isNotEmpty(textSections);
+      Expect.isTrue(
+          textSections.length <= 2, "More text sections than expected");
+      final dataSections = elf.namedSections(".rodata");
+      Expect.isNotEmpty(dataSections);
+      Expect.isTrue(
+          dataSections.length <= 2, "More data sections than expected");
+
+      var actualSize = 0;
+      for (final section in textSections) {
+        actualSize += section.length;
+      }
+      for (final section in dataSections) {
+        actualSize += section.length;
+      }
+
+      final mergedCount = (2 - textSections.length) + (2 - dataSections.length);
+      final possiblePadding = mergedCount * segmentAlignment;
+
+      Expect.approxEquals(
+          expectedSize,
+          actualSize,
+          possiblePadding,
+          "section size failed on $description snapshot" +
+              (!useAsm ? ", but symbol size test passed" : ""));
       checkedSize = true;
     }
 
     if (stripUtil || stripFlag) {
+      // Verify that the actual size of the stripped snapshot is close to the
+      // sum of the shallow sizes of all objects in the profile. They will not
+      // be exactly equal because of global headers, padding, and non-text/data
+      // sections.
       var strippedSnapshotPath = snapshotPath;
       if (stripUtil) {
         strippedSnapshotPath = snapshotPath + '.stripped';
@@ -227,20 +276,18 @@
         print("Stripped snapshot generated at $strippedSnapshotPath.");
       }
 
-      // Verify that the actual size of the stripped snapshot is close to the
-      // sum of the shallow sizes of all objects in the profile. They will not
-      // be exactly equal because of global headers and padding.
       final actualSize = await File(strippedSnapshotPath).length();
 
-      // See Elf::kPages in runtime/vm/elf.h, which is also used for assembly
-      // padding.
-      final segmentAlignment = 16 * 1024;
       // Not every byte is accounted for by the snapshot profile, and data and
       // instruction segments are padded to an alignment boundary.
       final tolerance = 0.03 * actualSize + 2 * segmentAlignment;
 
-      Expect.approxEquals(expectedSize, actualSize, tolerance,
-          "failed on $description snapshot");
+      Expect.approxEquals(
+          expectedSize,
+          actualSize,
+          tolerance,
+          "total size check failed on $description snapshot" +
+              (elf != null ? ", but section size checks passed" : ""));
       checkedSize = true;
     }
 
diff --git a/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart b/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart
index 0628aa0..9b7c95d 100644
--- a/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart
+++ b/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart
@@ -197,12 +197,17 @@
     final expectedSize =
         profile.nodes.fold<int>(0, (size, n) => size + n.selfSize);
 
+    // May not be ELF, but another format.
+    final elf = Elf.fromFile(snapshotPath);
+
     var checkedSize = false;
     if (!useAsm) {
-      // Verify that the total size of the snapshot text and data sections is
-      // the same as the sum of the shallow sizes of all objects in the profile.
-      // This ensures that all bytes are accounted for in some way.
-      final elf = Elf.fromFile(snapshotPath);
+      // Verify that the total size of the snapshot text and data section
+      // symbols is the same as the sum of the shallow sizes of all objects in
+      // the profile. This ensures that all bytes are accounted for in some way.
+      //
+      // We only check this when generating ELF directly because that's when
+      // we're guaranteed the symbols will have non-zero size.
       Expect.isNotNull(elf);
 
       final vmTextSectionSymbol = elf.dynamicSymbolFor(vmSymbolName);
@@ -220,12 +225,54 @@
           isolateTextSectionSymbol.size +
           isolateDataSectionSymbol.size;
 
-      Expect.equals(
-          expectedSize, actualSize, "failed on $description snapshot");
+      Expect.equals(expectedSize, actualSize,
+          "symbol size check failed on $description snapshot");
+      checkedSize = true;
+    }
+
+    // See Elf::kPages in runtime/vm/elf.h, which is also used for assembly
+    // padding.
+    final segmentAlignment = 16 * 1024;
+
+    if (elf != null) {
+      // Verify that the total size of the snapshot text and data sections is
+      // approximately the sum of the shallow sizes of all objects in the
+      // profile. As sections might be merged by the assembler when useAsm is
+      // true, we need to account for possible padding.
+      final textSections = elf.namedSections(".text");
+      Expect.isNotEmpty(textSections);
+      Expect.isTrue(
+          textSections.length <= 2, "More text sections than expected");
+      final dataSections = elf.namedSections(".rodata");
+      Expect.isNotEmpty(dataSections);
+      Expect.isTrue(
+          dataSections.length <= 2, "More data sections than expected");
+
+      var actualSize = 0;
+      for (final section in textSections) {
+        actualSize += section.length;
+      }
+      for (final section in dataSections) {
+        actualSize += section.length;
+      }
+
+      final mergedCount = (2 - textSections.length) + (2 - dataSections.length);
+      final possiblePadding = mergedCount * segmentAlignment;
+
+      Expect.approxEquals(
+          expectedSize,
+          actualSize,
+          possiblePadding,
+          "section size failed on $description snapshot" +
+              (!useAsm ? ", but symbol size test passed" : ""));
       checkedSize = true;
     }
 
     if (stripUtil || stripFlag) {
+      // Verify that the actual size of the stripped snapshot is close to the
+      // sum of the shallow sizes of all objects in the profile. They will not
+      // be exactly equal because of global headers, padding, and non-text/data
+      // sections.
       var strippedSnapshotPath = snapshotPath;
       if (stripUtil) {
         strippedSnapshotPath = snapshotPath + '.stripped';
@@ -234,20 +281,18 @@
         print("Stripped snapshot generated at $strippedSnapshotPath.");
       }
 
-      // Verify that the actual size of the stripped snapshot is close to the
-      // sum of the shallow sizes of all objects in the profile. They will not
-      // be exactly equal because of global headers and padding.
       final actualSize = await File(strippedSnapshotPath).length();
 
-      // See Elf::kPages in runtime/vm/elf.h, which is also used for assembly
-      // padding.
-      final segmentAlignment = 16 * 1024;
       // Not every byte is accounted for by the snapshot profile, and data and
       // instruction segments are padded to an alignment boundary.
       final tolerance = 0.03 * actualSize + 2 * segmentAlignment;
 
-      Expect.approxEquals(expectedSize, actualSize, tolerance,
-          "failed on $description snapshot");
+      Expect.approxEquals(
+          expectedSize,
+          actualSize,
+          tolerance,
+          "total size check failed on $description snapshot" +
+              (elf != null ? ", but section size checks passed" : ""));
       checkedSize = true;
     }
 
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index cf5a69a..ee64cc5 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -48,7 +48,7 @@
   TransitionNativeToVM transition(thread);
   StackZone zone(thread);
   HANDLESCOPE(thread);
-  Timer timer(true, "Compile all of Core lib benchmark");
+  Timer timer;
   timer.Start();
   const Error& error =
       Error::Handle(Library::CompileAll(/*ignore_error=*/true));
@@ -92,7 +92,7 @@
 //
 BENCHMARK(CorelibIsolateStartup) {
   const int kNumIterations = 1000;
-  Timer timer(true, "CorelibIsolateStartup");
+  Timer timer;
   Isolate* isolate = thread->isolate();
   Dart_ExitIsolate();
   for (int i = 0; i < kNumIterations; i++) {
@@ -192,7 +192,7 @@
   result = Dart_Invoke(lib, NewString("benchmark"), 1, args);
   EXPECT_VALID(result);
 
-  Timer timer(true, "UseDartApi benchmark");
+  Timer timer;
   timer.Start();
   result = Dart_Invoke(lib, NewString("benchmark"), 1, args);
   EXPECT_VALID(result);
@@ -208,7 +208,7 @@
 //
 BENCHMARK(DartStringAccess) {
   const int kNumIterations = 10000000;
-  Timer timer(true, "DartStringAccess benchmark");
+  Timer timer;
   timer.Start();
   Dart_EnterScope();
 
@@ -281,7 +281,7 @@
   result = Dart_FinalizeLoading(false);
   EXPECT_VALID(result);
 
-  Timer timer(true, "Compile all of kernel service benchmark");
+  Timer timer;
   timer.Start();
 #if !defined(PRODUCT)
   const bool old_flag = FLAG_background_compilation;
@@ -303,7 +303,7 @@
 // Measure frame lookup during stack traversal.
 //
 static void StackFrame_accessFrame(Dart_NativeArguments args) {
-  Timer timer(true, "LookupDartCode benchmark");
+  Timer timer;
   timer.Start();
   {
     Thread* thread = Thread::Current();
@@ -474,7 +474,7 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
 
-  Timer timer(true, "currentMirrorSystem() benchmark");
+  Timer timer;
   timer.Start();
   Dart_Handle result = Dart_Invoke(lib, NewString("benchmark"), 0, NULL);
   EXPECT_VALID(result);
@@ -496,7 +496,7 @@
     Api::CheckAndFinalizePendingClasses(thread);
   }
   Dart_Isolate isolate = Dart_CurrentIsolate();
-  Timer timer(true, "Enter and Exit isolate");
+  Timer timer;
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     Dart_ExitIsolate();
@@ -513,7 +513,7 @@
   HANDLESCOPE(thread);
   const Object& null_object = Object::Handle();
   const intptr_t kLoopCount = 1000000;
-  Timer timer(true, "Serialize Null");
+  Timer timer;
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
@@ -536,7 +536,7 @@
   HANDLESCOPE(thread);
   const Integer& smi_object = Integer::Handle(Smi::New(42));
   const intptr_t kLoopCount = 1000000;
-  Timer timer(true, "Serialize Smi");
+  Timer timer;
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
@@ -561,7 +561,7 @@
   array_object.SetAt(0, Integer::Handle(Smi::New(42)));
   array_object.SetAt(1, Object::Handle());
   const intptr_t kLoopCount = 1000000;
-  Timer timer(true, "Simple Message");
+  Timer timer;
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
@@ -595,7 +595,7 @@
   Instance& map = Instance::Handle();
   map ^= Api::UnwrapHandle(h_result);
   const intptr_t kLoopCount = 100;
-  Timer timer(true, "Large Map");
+  Timer timer;
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index b99bc8a..6802b92 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -2481,6 +2481,13 @@
 
   intptr_t Count(Serializer* s) { return objects_.length(); }
 
+  void CreateArtificialTargetNodesIfNeeded(Serializer* s) {
+    for (intptr_t i = 0; i < objects_.length(); i++) {
+      WeakSerializationReferencePtr weak = objects_[i];
+      s->CreateArtificialNodeIfNeeded(weak->untag()->target());
+    }
+  }
+
   void WriteAlloc(Serializer* s) {
     UNREACHABLE();  // No WSRs are serialized, and so this cluster is not added.
   }
@@ -6268,34 +6275,29 @@
     ObjectPtr object,
     const V8SnapshotProfileWriter::Reference& reference) {
   if (profile_writer_ == nullptr) return;
-
+  const auto& object_id = GetProfileId(object);
 #if defined(DART_PRECOMPILER)
-  // Make artificial nodes for dropped targets in WSRs.
   if (object->IsHeapObject() && object->IsWeakSerializationReference()) {
-    const auto& wsr = WeakSerializationReference::RawCast(object);
-    const auto& target = wsr->untag()->target();
-    const bool wsr_reachable = !CreateArtificialNodeIfNeeded(wsr);
-    if (wsr_reachable && HasArtificialRef(target)) {
-      // The target has artificial information used for snapshot analysis and
-      // the replacement is part of the snapshot, so write information for both.
-      const auto& replacement = wsr->untag()->replacement();
+    auto const wsr = WeakSerializationReference::RawCast(object);
+    auto const target = wsr->untag()->target();
+    const auto& target_id = GetProfileId(target);
+    if (object_id != target_id) {
+      const auto& replacement_id = GetProfileId(wsr->untag()->replacement());
+      ASSERT(object_id == replacement_id);
+      // The target of the WSR will be replaced in the snapshot, so write
+      // attributions for both the dropped target and for the replacement.
       profile_writer_->AttributeDroppedReferenceTo(
-          object_currently_writing_.id_, reference, GetProfileId(target),
-          GetProfileId(replacement));
+          object_currently_writing_.id_, reference, target_id, replacement_id);
       return;
     }
-    // The replacement isn't used, as either the target is strongly referenced
-    // or the WSR itself is unreachable, so fall through to attributing a
-    // reference to the WSR (which shares a profile ID with the target).
-    ASSERT(GetProfileId(wsr) == GetProfileId(target));
-  } else if (object_currently_writing_.id_.IsArtificial()) {
-    // We may need to recur when writing members of artificial nodes in
-    // CreateArtificialNodeIfNeeded.
-    CreateArtificialNodeIfNeeded(object);
+    // The replacement isn't used for this WSR in the snapshot, as either the
+    // target is strongly referenced or the WSR itself is unreachable, so fall
+    // through to attributing a reference to the WSR (which shares the profile
+    // ID of the target).
   }
 #endif
   profile_writer_->AttributeReferenceTo(object_currently_writing_.id_,
-                                        reference, GetProfileId(object));
+                                        reference, object_id);
 }
 
 Serializer::WritingObjectScope::WritingObjectScope(
@@ -6364,33 +6366,19 @@
   // UnsafeRefId will do lazy reference allocation for WSRs.
   intptr_t id = UnsafeRefId(obj);
   ASSERT(id != kUnallocatedReference);
-  if (IsArtificialReference(id)) {
-    return true;
+  if (id != kUnreachableReference) {
+    return IsArtificialReference(id);
   }
   if (obj->IsHeapObject() && obj->IsWeakSerializationReference()) {
-    // The object ID for the WSR may need lazy resolution.
-    if (id == kUnallocatedReference) {
-      id = UnsafeRefId(obj);
-    }
-    ASSERT(id != kUnallocatedReference);
-    // Create an artificial node for an unreachable target at this point,
-    // whether or not the WSR itself is reachable.
-    const auto& target =
+    auto const target =
         WeakSerializationReference::RawCast(obj)->untag()->target();
     CreateArtificialNodeIfNeeded(target);
-    if (id == kUnreachableReference) {
-      ASSERT(HasArtificialRef(target));
-      // We can safely set the WSR's object ID to the target's artificial one,
-      // as that won't make it look reachable.
-      heap_->SetObjectId(obj, heap_->GetObjectId(target));
-      return true;
-    }
-    // The WSR is reachable, so continue to the IsAllocatedReference behavior.
+    // Since the WSR is unreachable, we can replace its id with whatever the
+    // ID of the target is, whether real or artificial.
+    id = heap_->GetObjectId(target);
+    heap_->SetObjectId(obj, id);
+    return IsArtificialReference(id);
   }
-  if (IsAllocatedReference(id)) {
-    return false;
-  }
-  ASSERT_EQUAL(id, kUnreachableReference);
 
   const char* type = nullptr;
   const char* name = nullptr;
@@ -6490,6 +6478,7 @@
   id = AssignArtificialRef(obj);
   Serializer::WritingObjectScope scope(this, type, obj, name);
   for (const auto& link : links) {
+    CreateArtificialNodeIfNeeded(link.first);
     AttributeReference(link.first, link.second);
   }
   return true;
@@ -7045,10 +7034,11 @@
   }
 
 #if defined(DART_PRECOMPILER)
-  if (auto const cluster = CID_CLUSTER(WeakSerializationReference)) {
+  auto const wsr_cluster = CID_CLUSTER(WeakSerializationReference);
+  if (wsr_cluster != nullptr) {
     // Now that we have computed the reachability fixpoint, we remove the
     // count of now-reachable WSRs as they are not actually serialized.
-    num_written_objects_ -= cluster->Count(this);
+    num_written_objects_ -= wsr_cluster->Count(this);
     // We don't need to write this cluster, so remove it from consideration.
     clusters_by_cid_[kWeakSerializationReferenceCid] = nullptr;
   }
@@ -7137,6 +7127,19 @@
   // And recorded them all in [objects_].
   ASSERT(objects_->length() == num_objects);
 
+#if defined(DART_PRECOMPILER)
+  if (profile_writer_ != nullptr && wsr_cluster != nullptr) {
+    // Post-WriteAlloc, we eagerly create artificial nodes for any unreachable
+    // targets in reachable WSRs if writing a v8 snapshot profile, since they
+    // will be used in AttributeReference().
+    //
+    // Unreachable WSRs may also need artifical nodes, as they may be members
+    // of other unreachable objects that have artificial nodes in the profile,
+    // but they are instead lazily handled in CreateArtificialNodeIfNeeded().
+    wsr_cluster->CreateArtificialTargetNodesIfNeeded(this);
+  }
+#endif
+
   for (SerializationCluster* cluster : clusters) {
     cluster->WriteAndMeasureFill(this);
 #if defined(DEBUG)
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 56c13e8..016356d 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -27,6 +27,7 @@
 #include "vm/compiler/cha.h"
 #include "vm/compiler/compiler_pass.h"
 #include "vm/compiler/compiler_state.h"
+#include "vm/compiler/compiler_timings.h"
 #include "vm/compiler/frontend/flow_graph_builder.h"
 #include "vm/compiler/frontend/kernel_to_il.h"
 #include "vm/compiler/jit/compiler.h"
@@ -60,6 +61,10 @@
 #define IG (isolate_group())
 #define Z (zone())
 
+DEFINE_FLAG(bool,
+            print_precompiler_timings,
+            false,
+            "Print per-phase breakdown of time spent precompiling");
 DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynamic targets");
 DEFINE_FLAG(bool, print_gop, false, "Print global object pool");
 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler.");
@@ -331,12 +336,21 @@
   if (setjmp(*jump.Set()) == 0) {
     Precompiler precompiler(Thread::Current());
     precompiler.DoCompileAll();
+    precompiler.ReportStats();
     return Error::null();
   } else {
     return Thread::Current()->StealStickyError();
   }
 }
 
+void Precompiler::ReportStats() {
+  if (!FLAG_print_precompiler_timings) {
+    return;
+  }
+
+  thread()->compiler_timings()->Print();
+}
+
 Precompiler::Precompiler(Thread* thread)
     : thread_(thread),
       zone_(NULL),
@@ -378,6 +392,10 @@
       get_runtime_type_is_unique_(false) {
   ASSERT(Precompiler::singleton_ == NULL);
   Precompiler::singleton_ = this;
+
+  if (FLAG_print_precompiler_timings) {
+    thread->set_compiler_timings(new CompilerTimings());
+  }
 }
 
 Precompiler::~Precompiler() {
@@ -389,9 +407,13 @@
 
   ASSERT(Precompiler::singleton_ == this);
   Precompiler::singleton_ = NULL;
+
+  delete thread()->compiler_timings();
+  thread()->set_compiler_timings(nullptr);
 }
 
 void Precompiler::DoCompileAll() {
+  PRECOMPILER_TIMER_SCOPE(this, CompileAll);
   {
     StackZone stack_zone(T);
     zone_ = stack_zone.GetZone();
@@ -530,44 +552,60 @@
         tracer_ = nullptr;
       }
 
-      TraceForRetainedFunctions();
+      {
+        PRECOMPILER_TIMER_SCOPE(this, TraceForRetainedFunctions);
+        TraceForRetainedFunctions();
+      }
+
       FinalizeDispatchTable();
       ReplaceFunctionStaticCallEntries();
 
-      DropFunctions();
-      DropFields();
-      TraceTypesFromRetainedClasses();
-      DropTypes();
-      DropFunctionTypes();
-      DropTypeParameters();
-      DropTypeArguments();
+      {
+        PRECOMPILER_TIMER_SCOPE(this, Drop);
 
-      // Clear these before dropping classes as they may hold onto otherwise
-      // dead instances of classes we will remove or otherwise unused symbols.
-      IG->object_store()->set_unique_dynamic_targets(Array::null_array());
-      Class& null_class = Class::Handle(Z);
-      Function& null_function = Function::Handle(Z);
-      Field& null_field = Field::Handle(Z);
-      IG->object_store()->set_pragma_class(null_class);
-      IG->object_store()->set_pragma_name(null_field);
-      IG->object_store()->set_pragma_options(null_field);
-      IG->object_store()->set_completer_class(null_class);
-      IG->object_store()->set_symbol_class(null_class);
-      IG->object_store()->set_compiletime_error_class(null_class);
-      IG->object_store()->set_growable_list_factory(null_function);
-      IG->object_store()->set_simple_instance_of_function(null_function);
-      IG->object_store()->set_simple_instance_of_true_function(null_function);
-      IG->object_store()->set_simple_instance_of_false_function(null_function);
-      IG->object_store()->set_async_star_move_next_helper(null_function);
-      IG->object_store()->set_complete_on_async_return(null_function);
-      IG->object_store()->set_async_star_stream_controller(null_class);
-      DropMetadata();
-      DropLibraryEntries();
+        DropFunctions();
+        DropFields();
+        TraceTypesFromRetainedClasses();
+        DropTypes();
+        DropFunctionTypes();
+        DropTypeParameters();
+        DropTypeArguments();
+
+        // Clear these before dropping classes as they may hold onto otherwise
+        // dead instances of classes we will remove or otherwise unused symbols.
+        IG->object_store()->set_unique_dynamic_targets(Array::null_array());
+        Class& null_class = Class::Handle(Z);
+        Function& null_function = Function::Handle(Z);
+        Field& null_field = Field::Handle(Z);
+        IG->object_store()->set_pragma_class(null_class);
+        IG->object_store()->set_pragma_name(null_field);
+        IG->object_store()->set_pragma_options(null_field);
+        IG->object_store()->set_completer_class(null_class);
+        IG->object_store()->set_symbol_class(null_class);
+        IG->object_store()->set_compiletime_error_class(null_class);
+        IG->object_store()->set_growable_list_factory(null_function);
+        IG->object_store()->set_simple_instance_of_function(null_function);
+        IG->object_store()->set_simple_instance_of_true_function(null_function);
+        IG->object_store()->set_simple_instance_of_false_function(
+            null_function);
+        IG->object_store()->set_async_star_move_next_helper(null_function);
+        IG->object_store()->set_complete_on_async_return(null_function);
+        IG->object_store()->set_async_star_stream_controller(null_class);
+        DropMetadata();
+        DropLibraryEntries();
+      }
     }
-    DropClasses();
-    DropLibraries();
 
-    Obfuscate();
+    {
+      PRECOMPILER_TIMER_SCOPE(this, Drop);
+      DropClasses();
+      DropLibraries();
+    }
+
+    {
+      PRECOMPILER_TIMER_SCOPE(this, Obfuscate);
+      Obfuscate();
+    }
 
 #if defined(DEBUG)
     const auto& non_visited =
@@ -578,7 +616,11 @@
     }
 #endif
     DiscardCodeObjects();
-    ProgramVisitor::Dedup(T);
+
+    {
+      PRECOMPILER_TIMER_SCOPE(this, Dedup);
+      ProgramVisitor::Dedup(T);
+    }
 
     if (FLAG_write_retained_reasons_to != nullptr) {
       reasons_writer.Write();
@@ -614,6 +656,7 @@
 }
 
 void Precompiler::PrecompileConstructors() {
+  PRECOMPILER_TIMER_SCOPE(this, PrecompileConstructors);
   class ConstructorVisitor : public FunctionVisitor {
    public:
     explicit ConstructorVisitor(Precompiler* precompiler, Zone* zone)
@@ -683,6 +726,8 @@
 }
 
 void Precompiler::Iterate() {
+  PRECOMPILER_TIMER_SCOPE(this, Iterate);
+
   Function& function = Function::Handle(Z);
 
   phase_ = Phase::kFixpointCodeGeneration;
@@ -792,6 +837,7 @@
   if (!error_.IsNull()) {
     Jump(error_);
   }
+
   // Used in the JIT to save type-feedback across compilations.
   function.ClearICDataArray();
   AddCalleesOf(function, gop_offset);
@@ -1886,6 +1932,7 @@
 }
 
 void Precompiler::FinalizeDispatchTable() {
+  PRECOMPILER_TIMER_SCOPE(this, FinalizeDispatchTable);
   if (!FLAG_use_bare_instructions || !FLAG_use_table_dispatch) return;
   // Build the entries used to serialize the dispatch table before
   // dropping functions, as we may clear references to Code objects.
@@ -1918,6 +1965,7 @@
 }
 
 void Precompiler::ReplaceFunctionStaticCallEntries() {
+  PRECOMPILER_TIMER_SCOPE(this, ReplaceFunctionStaticCallEntries);
   class StaticCallTableEntryFixer : public CodeVisitor {
    public:
     explicit StaticCallTableEntryFixer(Zone* zone)
@@ -2162,6 +2210,7 @@
 }
 
 void Precompiler::AttachOptimizedTypeTestingStub() {
+  PRECOMPILER_TIMER_SCOPE(this, AttachOptimizedTypeTestingStub);
   IsolateGroup::Current()->heap()->CollectAllGarbage();
   GrowableHandlePtrArray<const AbstractType> types(Z, 200);
   {
@@ -3083,6 +3132,7 @@
         ic_data_array = new (zone) ZoneGrowableArray<const ICData*>();
 
         TIMELINE_DURATION(thread(), CompilerVerbose, "BuildFlowGraph");
+        COMPILER_TIMINGS_TIMER_SCOPE(thread(), BuildGraph);
         flow_graph =
             pipeline->BuildFlowGraph(zone, parsed_function(), ic_data_array,
                                      Compiler::kNoOSRDeoptId, optimized());
@@ -3169,10 +3219,12 @@
           pass_state.inline_id_to_token_pos, pass_state.caller_inline_id,
           ic_data_array, function_stats);
       {
+        COMPILER_TIMINGS_TIMER_SCOPE(thread(), EmitCode);
         TIMELINE_DURATION(thread(), CompilerVerbose, "CompileGraph");
         graph_compiler.CompileGraph();
       }
       {
+        COMPILER_TIMINGS_TIMER_SCOPE(thread(), FinalizeCode);
         TIMELINE_DURATION(thread(), CompilerVerbose, "FinalizeCompilation");
         ASSERT(thread()->IsMutatorThread());
         FinalizeCompilation(&assembler, &graph_compiler, flow_graph,
@@ -3282,7 +3334,7 @@
     Zone* const zone = stack_zone.GetZone();
     const bool trace_compiler =
         FLAG_trace_compiler || (FLAG_trace_optimizing_compiler && optimized);
-    Timer per_compile_timer(trace_compiler, "Compilation time");
+    Timer per_compile_timer;
     per_compile_timer.Start();
 
     ParsedFunction* parsed_function = new (zone)
@@ -3346,6 +3398,7 @@
                                       Thread* thread,
                                       Zone* zone,
                                       const Function& function) {
+  PRECOMPILER_TIMER_SCOPE(precompiler, CompileFunction);
   NoActiveIsolateScope no_isolate_scope;
 
   VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId);
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index fba9413..c5d14fc 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -16,6 +16,7 @@
 #include "vm/hash_table.h"
 #include "vm/object.h"
 #include "vm/symbols.h"
+#include "vm/timer.h"
 
 namespace dart {
 
@@ -267,6 +268,10 @@
 
   bool is_tracing() const { return is_tracing_; }
 
+  Thread* thread() const { return thread_; }
+  Zone* zone() const { return zone_; }
+  Isolate* isolate() const { return isolate_; }
+
  private:
   static Precompiler* singleton_;
 
@@ -289,6 +294,8 @@
   explicit Precompiler(Thread* thread);
   ~Precompiler();
 
+  void ReportStats();
+
   void DoCompileAll();
   void AddRoots();
   void AddAnnotatedRoots();
@@ -348,9 +355,6 @@
 
   void FinalizeAllClasses();
 
-  Thread* thread() const { return thread_; }
-  Zone* zone() const { return zone_; }
-  Isolate* isolate() const { return isolate_; }
   IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
 
   Thread* thread_;
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index fcc76b4..bf1dc6a 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -3421,28 +3421,31 @@
 }
 #endif  // !PRODUCT
 
-void Assembler::TryAllocate(const Class& cls,
-                            Label* failure,
-                            JumpDistance distance,
-                            Register instance_reg,
-                            Register temp_reg) {
+void Assembler::TryAllocateObject(intptr_t cid,
+                                  intptr_t instance_size,
+                                  Label* failure,
+                                  JumpDistance distance,
+                                  Register instance_reg,
+                                  Register temp_reg) {
   ASSERT(failure != NULL);
-  const intptr_t instance_size = target::Class::GetInstanceSize(cls);
+  ASSERT(instance_reg != kNoRegister);
+  ASSERT(instance_reg != temp_reg);
+  ASSERT(instance_reg != IP);
+  ASSERT(temp_reg != kNoRegister);
+  ASSERT(temp_reg != IP);
+  ASSERT(instance_size != 0);
+  ASSERT(Utils::IsAligned(instance_size,
+                          target::ObjectAlignment::kObjectAlignment));
   if (FLAG_inline_alloc &&
       target::Heap::IsAllocatableInNewSpace(instance_size)) {
-    const classid_t cid = target::Class::GetId(cls);
-    ASSERT(instance_reg != temp_reg);
-    ASSERT(temp_reg != IP);
-    ASSERT(instance_size != 0);
     NOT_IN_PRODUCT(LoadAllocationStatsAddress(temp_reg, cid));
     ldr(instance_reg, Address(THR, target::Thread::top_offset()));
     // TODO(koda): Protect against unsigned overflow here.
-    AddImmediateSetFlags(instance_reg, instance_reg, instance_size);
-
-    // instance_reg: potential next object start.
+    AddImmediate(instance_reg, instance_size);
+    // instance_reg: potential top (next object start).
     ldr(IP, Address(THR, target::Thread::end_offset()));
     cmp(IP, Operand(instance_reg));
-    // fail if heap end unsigned less than or equal to instance_reg.
+    // fail if heap end unsigned less than or equal to new heap top.
     b(failure, LS);
 
     // If this allocation is traced, program will jump to failure path
@@ -3453,13 +3456,12 @@
     // Successfully allocated the object, now update top to point to
     // next object start and store the class in the class field of object.
     str(instance_reg, Address(THR, target::Thread::top_offset()));
-
-    ASSERT(instance_size >= kHeapObjectTag);
+    // Move instance_reg back to the start of the object and tag it.
     AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
 
     const uword tags = target::MakeTagWordForNewSpaceObject(cid, instance_size);
-    LoadImmediate(IP, tags);
-    str(IP, FieldAddress(instance_reg, target::Object::tags_offset()));
+    LoadImmediate(temp_reg, tags);
+    str(temp_reg, FieldAddress(instance_reg, target::Object::tags_offset()));
   } else {
     b(failure);
   }
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 263f5fb..e03aa97 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -388,9 +388,8 @@
   // Unconditional jump to a given address in memory.
   void Jump(const Address& address) { Branch(address); }
 
-  void LoadField(Register dst, FieldAddress address) { ldr(dst, address); }
-  void LoadCompressedField(Register dst, FieldAddress address) {
-    LoadField(dst, address);
+  void LoadField(Register dst, const FieldAddress& address) override {
+    ldr(dst, address);
   }
   void LoadMemoryValue(Register dst, Register base, int32_t offset) {
     LoadFromOffset(dst, base, offset);
@@ -854,11 +853,6 @@
   }
   void CompareObject(Register rn, const Object& object);
 
-  enum CanBeSmi {
-    kValueIsNotSmi,
-    kValueCanBeSmi,
-  };
-
   // Store into a heap object and apply the generational and incremental write
   // barriers. All stores into heap objects must pass through this function or,
   // if the value can be proven either Smi or old-and-premarked, its NoBarrier
@@ -867,7 +861,7 @@
   void StoreIntoObject(Register object,      // Object we are storing into.
                        const Address& dest,  // Where we are storing into.
                        Register value,       // Value we are storing.
-                       CanBeSmi can_value_be_smi = kValueCanBeSmi);
+                       CanBeSmi can_value_be_smi = kValueCanBeSmi) override;
   void StoreIntoArray(Register object,
                       Register slot,
                       Register value,
@@ -879,7 +873,7 @@
 
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
-                                Register value);
+                                Register value) override;
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
                                 const Object& value);
@@ -1274,15 +1268,12 @@
   // which will allocate in the runtime where tracing occurs.
   void MaybeTraceAllocation(Register stats_addr_reg, Label* trace);
 
-  // Inlined allocation of an instance of class 'cls', code has no runtime
-  // calls. Jump to 'failure' if the instance cannot be allocated here.
-  // Allocated instance is returned in 'instance_reg'.
-  // Only the tags field of the object is initialized.
-  void TryAllocate(const Class& cls,
-                   Label* failure,
-                   JumpDistance distance,
-                   Register instance_reg,
-                   Register temp_reg);
+  void TryAllocateObject(intptr_t cid,
+                         intptr_t instance_size,
+                         Label* failure,
+                         JumpDistance distance,
+                         Register instance_reg,
+                         Register temp_reg) override;
 
   void TryAllocateArray(intptr_t cid,
                         intptr_t instance_size,
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 11cc859..a1f7c7f 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -1841,46 +1841,48 @@
 }
 #endif  // !PRODUCT
 
-void Assembler::TryAllocate(const Class& cls,
-                            Label* failure,
-                            JumpDistance distance,
-                            Register instance_reg,
-                            Register top_reg,
-                            bool tag_result) {
+void Assembler::TryAllocateObject(intptr_t cid,
+                                  intptr_t instance_size,
+                                  Label* failure,
+                                  JumpDistance distance,
+                                  Register instance_reg,
+                                  Register temp_reg) {
   ASSERT(failure != NULL);
-  const intptr_t instance_size = target::Class::GetInstanceSize(cls);
+  ASSERT(instance_size != 0);
+  ASSERT(instance_reg != temp_reg);
+  ASSERT(temp_reg != kNoRegister);
+  ASSERT(Utils::IsAligned(instance_size,
+                          target::ObjectAlignment::kObjectAlignment));
   if (FLAG_inline_alloc &&
       target::Heap::IsAllocatableInNewSpace(instance_size)) {
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    const classid_t cid = target::Class::GetId(cls);
-    NOT_IN_PRODUCT(MaybeTraceAllocation(cid, /*temp_reg=*/top_reg, failure));
-
-    const Register kEndReg = TMP;
-
-    // instance_reg: potential next object start.
+    NOT_IN_PRODUCT(MaybeTraceAllocation(cid, temp_reg, failure));
     RELEASE_ASSERT((target::Thread::top_offset() + target::kWordSize) ==
                    target::Thread::end_offset());
-    ldp(instance_reg, kEndReg,
+    ldp(instance_reg, temp_reg,
         Address(THR, target::Thread::top_offset(), Address::PairOffset));
+    // instance_reg: current top (next object start).
+    // temp_reg: heap end
 
     // TODO(koda): Protect against unsigned overflow here.
-    AddImmediate(top_reg, instance_reg, instance_size);
-    cmp(kEndReg, Operand(top_reg));
-    b(failure, LS);  // Unsigned lower or equal.
+    AddImmediate(instance_reg, instance_size);
+    // instance_reg: potential top (next object start).
+    // fail if heap end unsigned less than or equal to new heap top.
+    cmp(temp_reg, Operand(instance_reg));
+    b(failure, LS);
 
-    // Successfully allocated the object, now update top to point to
+    // Successfully allocated the object, now update temp to point to
     // next object start and store the class in the class field of object.
-    str(top_reg, Address(THR, target::Thread::top_offset()));
+    str(instance_reg, Address(THR, target::Thread::top_offset()));
+    // Move instance_reg back to the start of the object and tag it.
+    AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
 
     const uword tags = target::MakeTagWordForNewSpaceObject(cid, instance_size);
-    LoadImmediate(TMP, tags);
-    StoreToOffset(TMP, instance_reg, target::Object::tags_offset());
-
-    if (tag_result) {
-      AddImmediate(instance_reg, kHeapObjectTag);
-    }
+    LoadImmediate(temp_reg, tags);
+    StoreToOffset(temp_reg,
+                  FieldAddress(instance_reg, target::Object::tags_offset()));
   } else {
     b(failure);
   }
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 7d0921b..4dcf55a 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -547,8 +547,10 @@
     br(TMP);
   }
 
-  void LoadField(Register dst, FieldAddress address) { ldr(dst, address); }
-  void LoadCompressedField(Register dst, FieldAddress address) {
+  void LoadField(Register dst, const FieldAddress& address) override {
+    ldr(dst, address);
+  }
+  void LoadCompressedField(Register dst, const FieldAddress& address) override {
     LoadCompressed(dst, address);
   }
   void LoadMemoryValue(Register dst, Register base, int32_t offset) {
@@ -1762,11 +1764,6 @@
     StoreQToOffset(src, base, offset - kHeapObjectTag);
   }
 
-  enum CanBeSmi {
-    kValueIsNotSmi,
-    kValueCanBeSmi,
-  };
-
   void LoadCompressed(Register dest, const Address& slot);
   void LoadCompressedSmi(Register dest, const Address& slot);
 
@@ -1778,11 +1775,12 @@
   void StoreIntoObject(Register object,
                        const Address& dest,
                        Register value,
-                       CanBeSmi can_value_be_smi = kValueCanBeSmi);
-  void StoreCompressedIntoObject(Register object,
-                                 const Address& dest,
-                                 Register value,
-                                 CanBeSmi can_value_be_smi = kValueCanBeSmi);
+                       CanBeSmi can_value_be_smi = kValueCanBeSmi) override;
+  void StoreCompressedIntoObject(
+      Register object,
+      const Address& dest,
+      Register value,
+      CanBeSmi can_value_be_smi = kValueCanBeSmi) override;
   void StoreBarrier(Register object, Register value, CanBeSmi can_value_be_smi);
   void StoreIntoArray(Register object,
                       Register slot,
@@ -1800,10 +1798,10 @@
       CanBeSmi can_value_be_smi = kValueCanBeSmi);
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
-                                Register value);
+                                Register value) override;
   void StoreCompressedIntoObjectNoBarrier(Register object,
                                           const Address& dest,
-                                          Register value);
+                                          Register value) override;
   void StoreIntoObjectOffsetNoBarrier(Register object,
                                       int32_t offset,
                                       Register value);
@@ -1990,19 +1988,12 @@
   // which will allocate in the runtime where tracing occurs.
   void MaybeTraceAllocation(intptr_t cid, Register temp_reg, Label* trace);
 
-  // Inlined allocation of an instance of class 'cls', code has no runtime
-  // calls. Jump to 'failure' if the instance cannot be allocated here.
-  // Allocated instance is returned in 'instance_reg'.
-  // Only the tags field of the object is initialized.
-  // Result:
-  //   * [instance_reg] will contain allocated new-space object
-  //   * [top_reg] will contain Thread::top_offset()
-  void TryAllocate(const Class& cls,
-                   Label* failure,
-                   JumpDistance distance,
-                   Register instance_reg,
-                   Register top_reg,
-                   bool tag_result = true);
+  void TryAllocateObject(intptr_t cid,
+                         intptr_t instance_size,
+                         Label* failure,
+                         JumpDistance distance,
+                         Register instance_reg,
+                         Register top_reg) override;
 
   void TryAllocateArray(intptr_t cid,
                         intptr_t instance_size,
diff --git a/runtime/vm/compiler/assembler/assembler_base.cc b/runtime/vm/compiler/assembler/assembler_base.cc
index 9d50186..45e6a6f 100644
--- a/runtime/vm/compiler/assembler/assembler_base.cc
+++ b/runtime/vm/compiler/assembler/assembler_base.cc
@@ -5,6 +5,7 @@
 #include "vm/compiler/assembler/assembler_base.h"
 
 #include "platform/utils.h"
+#include "vm/compiler/backend/slot.h"
 #include "vm/cpu.h"
 #include "vm/heap/heap.h"
 #include "vm/memory_region.h"
@@ -26,6 +27,53 @@
 
 AssemblerBase::~AssemblerBase() {}
 
+void AssemblerBase::LoadFromSlot(Register dst,
+                                 Register base,
+                                 const Slot& slot) {
+  auto const rep = slot.representation();
+  const FieldAddress address(base, slot.offset_in_bytes());
+  if (rep != kTagged) {
+    auto const sz = RepresentationUtils::OperandSize(rep);
+    return LoadFromOffset(dst, address, sz);
+  }
+  if (slot.is_compressed()) {
+    return LoadCompressedField(dst, address);
+  }
+  return LoadField(dst, address);
+}
+
+void AssemblerBase::StoreToSlot(Register src, Register base, const Slot& slot) {
+  auto const rep = slot.representation();
+  const FieldAddress address(base, slot.offset_in_bytes());
+  if (rep != kTagged) {
+    auto const sz = RepresentationUtils::OperandSize(rep);
+    return StoreToOffset(src, address, sz);
+  }
+  if (slot.is_compressed()) {
+    return StoreCompressedIntoObject(
+        base, address, src,
+        slot.ComputeCompileType().CanBeSmi() ? kValueCanBeSmi : kValueIsNotSmi);
+  }
+  return StoreIntoObject(
+      base, address, src,
+      slot.ComputeCompileType().CanBeSmi() ? kValueCanBeSmi : kValueIsNotSmi);
+}
+
+void AssemblerBase::StoreToSlotNoBarrier(Register src,
+                                         Register base,
+                                         const Slot& slot) {
+  auto const rep = slot.representation();
+  const FieldAddress address(base, slot.offset_in_bytes());
+  if (rep != kTagged) {
+    auto const sz = RepresentationUtils::OperandSize(rep);
+    return StoreToOffset(src, address, sz);
+  }
+  if (slot.is_compressed()) {
+    return StoreCompressedIntoObjectNoBarrier(base, address, src);
+  }
+  return StoreIntoObjectNoBarrier(base, address, src);
+}
+
 intptr_t AssemblerBase::InsertAlignedRelocation(BSS::Relocation reloc) {
   // We cannot put a relocation at the very start (it's not a valid
   // instruction)!
diff --git a/runtime/vm/compiler/assembler/assembler_base.h b/runtime/vm/compiler/assembler/assembler_base.h
index 4b81856..383a067 100644
--- a/runtime/vm/compiler/assembler/assembler_base.h
+++ b/runtime/vm/compiler/assembler/assembler_base.h
@@ -25,6 +25,7 @@
 #endif
 
 class MemoryRegion;
+class Slot;
 
 namespace compiler {
 
@@ -211,6 +212,7 @@
 class AssemblerFixup;
 class AssemblerBuffer;
 class Address;
+class FieldAddress;
 
 class Label : public ZoneAllocated {
  public:
@@ -561,12 +563,97 @@
 
   virtual void Breakpoint() = 0;
 
+  // Inlined allocation in new space of an instance of an object whose instance
+  // size is known at compile time with class ID 'cid'. The generated code has
+  // no runtime calls. Jump to 'failure' if the instance cannot be allocated
+  // here and should be done via runtime call instead.
+  //
+  // ObjectPtr to allocated instance is returned in 'instance_reg'.
+  //
+  // WARNING: The caller is responsible for initializing all GC-visible fields
+  // of the object other than the tags field, which is initialized here.
+  virtual void TryAllocateObject(intptr_t cid,
+                                 intptr_t instance_size,
+                                 Label* failure,
+                                 JumpDistance distance,
+                                 Register instance_reg,
+                                 Register temp) = 0;
+
+  // An alternative version of TryAllocateObject that takes a Class object
+  // and passes the class id and instance size to TryAllocateObject along with
+  // the other arguments.
+  void TryAllocate(const Class& cls,
+                   Label* failure,
+                   JumpDistance distance,
+                   Register instance_reg,
+                   Register temp) {
+    TryAllocateObject(target::Class::GetId(cls),
+                      target::Class::GetInstanceSize(cls), failure, distance,
+                      instance_reg, temp);
+  }
+
   virtual void LoadFromOffset(Register dst,
                               const Address& address,
                               OperandSize sz = kWordBytes) = 0;
+  // Does not use write barriers, use StoreIntoObject instead for boxed fields.
   virtual void StoreToOffset(Register src,
                              const Address& address,
                              OperandSize sz = kWordBytes) = 0;
+  enum CanBeSmi {
+    kValueCanBeSmi,
+    kValueIsNotSmi,
+  };
+
+  virtual void LoadField(Register dst, const FieldAddress& address) = 0;
+  void LoadFromSlot(Register dst, Register base, const Slot& slot);
+
+  virtual void StoreIntoObject(
+      Register object,      // Object we are storing into.
+      const Address& dest,  // Where we are storing into.
+      Register value,       // Value we are storing.
+      CanBeSmi can_be_smi = kValueCanBeSmi) = 0;
+  virtual void StoreIntoObjectNoBarrier(
+      Register object,      // Object we are storing into.
+      const Address& dest,  // Where we are storing into.
+      Register value) = 0;  // Value we are storing.
+  // For native unboxed slots, both methods are the same, as no write barrier
+  // is needed.
+  void StoreToSlot(Register src, Register base, const Slot& slot);
+  void StoreToSlotNoBarrier(Register src, Register base, const Slot& slot);
+
+  // Install pure virtual methods if using compressed pointers, to ensure that
+  // these methods are overridden. If there are no compressed pointers, forward
+  // to the uncompressed version.
+#if defined(DART_COMPRESSED_POINTERS)
+  virtual void LoadCompressedField(Register dst,
+                                   const FieldAddress& address) = 0;
+  virtual void StoreCompressedIntoObject(
+      Register object,      // Object we are storing into.
+      const Address& dest,  // Where we are storing into.
+      Register value,       // Value we are storing.
+      CanBeSmi can_be_smi = kValueCanBeSmi) = 0;
+  virtual void StoreCompressedIntoObjectNoBarrier(
+      Register object,      // Object we are storing into.
+      const Address& dest,  // Where we are storing into.
+      Register value) = 0;  // Value we are storing.
+#else
+  virtual void LoadCompressedField(Register dst, const FieldAddress& address) {
+    LoadField(dst, address);
+  }
+  virtual void StoreCompressedIntoObject(
+      Register object,      // Object we are storing into.
+      const Address& dest,  // Where we are storing into.
+      Register value,       // Value we are storing.
+      CanBeSmi can_be_smi = kValueCanBeSmi) {
+    StoreIntoObject(object, dest, value, can_be_smi);
+  }
+  virtual void StoreCompressedIntoObjectNoBarrier(
+      Register object,      // Object we are storing into.
+      const Address& dest,  // Where we are storing into.
+      Register value) {     // Value we are storing.
+    StoreIntoObjectNoBarrier(object, dest, value);
+  }
+#endif  // defined(DART_COMPRESSED_POINTERS)
 
   intptr_t InsertAlignedRelocation(BSS::Relocation reloc);
 
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index a3b7a9a..4850162 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2520,20 +2520,21 @@
 }
 #endif  // !PRODUCT
 
-void Assembler::TryAllocate(const Class& cls,
-                            Label* failure,
-                            JumpDistance distance,
-                            Register instance_reg,
-                            Register temp_reg) {
+void Assembler::TryAllocateObject(intptr_t cid,
+                                  intptr_t instance_size,
+                                  Label* failure,
+                                  JumpDistance distance,
+                                  Register instance_reg,
+                                  Register temp_reg) {
   ASSERT(failure != NULL);
-  ASSERT(temp_reg != kNoRegister);
-  const intptr_t instance_size = target::Class::GetInstanceSize(cls);
+  ASSERT(instance_size != 0);
+  ASSERT(Utils::IsAligned(instance_size,
+                          target::ObjectAlignment::kObjectAlignment));
   if (FLAG_inline_alloc &&
       target::Heap::IsAllocatableInNewSpace(instance_size)) {
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
-    const classid_t cid = target::Class::GetId(cls);
     NOT_IN_PRODUCT(MaybeTraceAllocation(cid, temp_reg, failure, distance));
     movl(instance_reg, Address(THR, target::Thread::top_offset()));
     addl(instance_reg, Immediate(instance_size));
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index ceda7d9..5447918 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -598,13 +598,11 @@
                       OperandSize sz = kFourBytes) {
     LoadFromOffset(dst, Address(base, offset), sz);
   }
-  void LoadField(Register dst,
-                 const FieldAddress& address,
-                 OperandSize sz = kFourBytes) {
-    LoadFromOffset(dst, address, sz);
+  void LoadField(Register dst, const FieldAddress& address) override {
+    LoadField(dst, address, kFourBytes);
   }
-  void LoadCompressedField(Register dst, const FieldAddress& address) {
-    LoadField(dst, address);
+  void LoadField(Register dst, const FieldAddress& address, OperandSize sz) {
+    LoadFromOffset(dst, address, sz);
   }
   void LoadFieldFromOffset(Register reg,
                            Register base,
@@ -720,11 +718,6 @@
   void CompareObject(Register reg, const Object& object);
   void LoadDoubleConstant(XmmRegister dst, double value);
 
-  enum CanBeSmi {
-    kValueIsNotSmi,
-    kValueCanBeSmi,
-  };
-
   // Store into a heap object and apply the generational write barrier. (Unlike
   // the other architectures, this does not apply the incremental write barrier,
   // and so concurrent marking is not enabled for now on IA32.) All stores into
@@ -734,15 +727,14 @@
   void StoreIntoObject(Register object,      // Object we are storing into.
                        const Address& dest,  // Where we are storing into.
                        Register value,       // Value we are storing.
-                       CanBeSmi can_value_be_smi = kValueCanBeSmi);
+                       CanBeSmi can_value_be_smi = kValueCanBeSmi) override;
   void StoreIntoArray(Register object,  // Object we are storing into.
                       Register slot,    // Where we are storing into.
                       Register value,   // Value we are storing.
                       CanBeSmi can_value_be_smi = kValueCanBeSmi);
-
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
-                                Register value);
+                                Register value) override;
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
                                 const Object& value);
@@ -967,15 +959,12 @@
                             Label* trace,
                             JumpDistance distance);
 
-  // Inlined allocation of an instance of class 'cls', code has no runtime
-  // calls. Jump to 'failure' if the instance cannot be allocated here.
-  // Allocated instance is returned in 'instance_reg'.
-  // Only the tags field of the object is initialized.
-  void TryAllocate(const Class& cls,
-                   Label* failure,
-                   JumpDistance distance,
-                   Register instance_reg,
-                   Register temp_reg);
+  void TryAllocateObject(intptr_t cid,
+                         intptr_t instance_size,
+                         Label* failure,
+                         JumpDistance distance,
+                         Register instance_reg,
+                         Register temp_reg) override;
 
   void TryAllocateArray(intptr_t cid,
                         intptr_t instance_size,
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index ae7798a..7ab5c8e 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -2061,16 +2061,18 @@
 }
 #endif  // !PRODUCT
 
-void Assembler::TryAllocate(const Class& cls,
-                            Label* failure,
-                            JumpDistance distance,
-                            Register instance_reg,
-                            Register temp) {
+void Assembler::TryAllocateObject(intptr_t cid,
+                                  intptr_t instance_size,
+                                  Label* failure,
+                                  JumpDistance distance,
+                                  Register instance_reg,
+                                  Register temp_reg) {
   ASSERT(failure != NULL);
-  const intptr_t instance_size = target::Class::GetInstanceSize(cls);
+  ASSERT(instance_size != 0);
+  ASSERT(Utils::IsAligned(instance_size,
+                          target::ObjectAlignment::kObjectAlignment));
   if (FLAG_inline_alloc &&
       target::Heap::IsAllocatableInNewSpace(instance_size)) {
-    const classid_t cid = target::Class::GetId(cls);
     // If this allocation is traced, program will jump to failure path
     // (i.e. the allocation stub) which will allocate the object and trace the
     // allocation call site.
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 182c1ec..5acae47 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -777,11 +777,6 @@
   void PushObject(const Object& object);
   void CompareObject(Register reg, const Object& object);
 
-  enum CanBeSmi {
-    kValueIsNotSmi,
-    kValueCanBeSmi,
-  };
-
   void LoadCompressed(Register dest, const Address& slot);
   void LoadCompressedSmi(Register dest, const Address& slot);
 
@@ -793,12 +788,12 @@
   void StoreIntoObject(Register object,      // Object we are storing into.
                        const Address& dest,  // Where we are storing into.
                        Register value,       // Value we are storing.
-                       CanBeSmi can_be_smi = kValueCanBeSmi);
+                       CanBeSmi can_be_smi = kValueCanBeSmi) override;
   void StoreCompressedIntoObject(
       Register object,      // Object we are storing into.
       const Address& dest,  // Where we are storing into.
       Register value,       // Value we are storing.
-      CanBeSmi can_be_smi = kValueCanBeSmi);
+      CanBeSmi can_be_smi = kValueCanBeSmi) override;
   void StoreBarrier(Register object,  // Object we are storing into.
                     Register value,   // Value we are storing.
                     CanBeSmi can_be_smi);
@@ -809,10 +804,10 @@
 
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
-                                Register value);
+                                Register value) override;
   void StoreCompressedIntoObjectNoBarrier(Register object,
                                           const Address& dest,
-                                          Register value);
+                                          Register value) override;
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
                                 const Object& value);
@@ -942,12 +937,13 @@
                       OperandSize sz = kEightBytes) {
     LoadFromOffset(dst, Address(base, offset), sz);
   }
-  void LoadField(Register dst,
-                 FieldAddress address,
-                 OperandSize sz = kEightBytes) {
+  void LoadField(Register dst, const FieldAddress& address) override {
+    LoadField(dst, address, kEightBytes);
+  }
+  void LoadField(Register dst, const FieldAddress& address, OperandSize sz) {
     LoadFromOffset(dst, address, sz);
   }
-  void LoadCompressedField(Register dst, FieldAddress address) {
+  void LoadCompressedField(Register dst, const FieldAddress& address) override {
     LoadCompressed(dst, address);
   }
   void LoadFieldFromOffset(Register dst,
@@ -1084,15 +1080,12 @@
   // which will allocate in the runtime where tracing occurs.
   void MaybeTraceAllocation(intptr_t cid, Label* trace, JumpDistance distance);
 
-  // Inlined allocation of an instance of class 'cls', code has no runtime
-  // calls. Jump to 'failure' if the instance cannot be allocated here.
-  // Allocated instance is returned in 'instance_reg'.
-  // Only the tags field of the object is initialized.
-  void TryAllocate(const Class& cls,
-                   Label* failure,
-                   JumpDistance distance,
-                   Register instance_reg,
-                   Register temp);
+  void TryAllocateObject(intptr_t cid,
+                         intptr_t instance_size,
+                         Label* failure,
+                         JumpDistance distance,
+                         Register instance_reg,
+                         Register temp) override;
 
   void TryAllocateArray(intptr_t cid,
                         intptr_t instance_size,
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 9f9b3f4..529eda6 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -933,6 +933,10 @@
   SetValue(instr, non_constant_);
 }
 
+void ConstantPropagator::VisitAllocateClosure(AllocateClosureInstr* instr) {
+  SetValue(instr, non_constant_);
+}
+
 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) {
   SetValue(instr, non_constant_);
 }
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 2d890b4..a24af44 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -12,6 +12,7 @@
 #include "vm/compiler/backend/range_analysis.h"
 #include "vm/compiler/cha.h"
 #include "vm/compiler/compiler_state.h"
+#include "vm/compiler/compiler_timings.h"
 #include "vm/compiler/frontend/flow_graph_builder.h"
 #include "vm/growable_array.h"
 #include "vm/object_store.h"
@@ -336,6 +337,8 @@
 };
 
 void FlowGraph::DiscoverBlocks() {
+  COMPILER_TIMINGS_TIMER_SCOPE(thread(), DiscoverBlocks);
+
   StackZone zone(thread());
 
   // Initialize state.
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 9d6c4a5..226e449 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -991,6 +991,24 @@
   ASSERT(!CompilerState::Current().is_aot());
 }
 
+LocationSummary* AllocateClosureInstr::MakeLocationSummary(Zone* zone,
+                                                           bool opt) const {
+  const intptr_t kNumInputs = 0;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  locs->set_out(0, Location::RegisterLocation(AllocateClosureABI::kResultReg));
+  return locs;
+}
+
+void AllocateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Code& stub = Code::ZoneHandle(
+      compiler->zone(),
+      compiler->isolate_group()->object_store()->allocate_closure_stub());
+  compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
+                             locs(), deopt_id(), env());
+}
+
 LocationSummary* AllocateTypedDataInstr::MakeLocationSummary(Zone* zone,
                                                              bool opt) const {
   const intptr_t kNumInputs = 1;
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 50300c3..917d7df 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -429,6 +429,7 @@
   M(InstanceOf, _)                                                             \
   M(CreateArray, _)                                                            \
   M(AllocateObject, _)                                                         \
+  M(AllocateClosure, _)                                                        \
   M(AllocateTypedData, _)                                                      \
   M(LoadField, _)                                                              \
   M(LoadUntagged, kNoGC)                                                       \
@@ -3952,7 +3953,6 @@
         ArgumentsSizeWithoutTypeArgs(), argument_names());
   }
 
-
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) {
     (*inputs_)[i] = value;
@@ -6122,6 +6122,8 @@
     return InputCount();
   }
 
+  PRINT_OPERANDS_TO_SUPPORT
+
   DEFINE_INSTRUCTION_TYPE_CHECK(Allocation);
 
  private:
@@ -6159,8 +6161,7 @@
                       Value* type_arguments = nullptr)
       : AllocationInstr(source, deopt_id),
         cls_(cls),
-        type_arguments_(type_arguments),
-        closure_function_(Function::ZoneHandle()) {
+        type_arguments_(type_arguments) {
     ASSERT((cls.NumTypeArguments() > 0) == (type_arguments != nullptr));
     if (type_arguments != nullptr) {
       SetInputAt(0, type_arguments);
@@ -6173,11 +6174,6 @@
   const Class& cls() const { return cls_; }
   Value* type_arguments() const { return type_arguments_; }
 
-  const Function& closure_function() const { return closure_function_; }
-  void set_closure_function(const Function& function) {
-    closure_function_ = function.ptr();
-  }
-
   virtual intptr_t InputCount() const {
     return (type_arguments_ != nullptr) ? 1 : 0;
   }
@@ -6207,11 +6203,41 @@
 
   const Class& cls_;
   Value* type_arguments_;
-  Function& closure_function_;
 
   DISALLOW_COPY_AND_ASSIGN(AllocateObjectInstr);
 };
 
+// Allocates and null initializes a closure object. The closure function, when
+// non-null, is used to determine the precise type of the resulting closure
+// and to inline the closure function when applicable.
+class AllocateClosureInstr : public TemplateAllocation<0> {
+ public:
+  AllocateClosureInstr(const InstructionSource& source,
+                       const Function& closure_function,
+                       intptr_t deopt_id)
+      : TemplateAllocation(source, deopt_id),
+        closure_function_(closure_function) {}
+
+  DECLARE_INSTRUCTION(AllocateClosure)
+  virtual CompileType ComputeType() const;
+
+  const Function& closure_function() const { return closure_function_; }
+
+  virtual bool HasUnknownSideEffects() const { return false; }
+
+  virtual bool WillAllocateNewOrRemembered() const {
+    return Heap::IsAllocatableInNewSpace(
+        compiler::target::Closure::InstanceSize());
+  }
+
+  PRINT_OPERANDS_TO_SUPPORT
+
+ private:
+  const Function& closure_function_;
+
+  DISALLOW_COPY_AND_ASSIGN(AllocateClosureInstr);
+};
+
 class AllocateUninitializedContextInstr : public TemplateAllocation<0> {
  public:
   AllocateUninitializedContextInstr(const InstructionSource& source,
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index 6c903ec..c816dac 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -654,17 +654,32 @@
   right()->PrintTo(f);
 }
 
-void AllocateObjectInstr::PrintOperandsTo(BaseTextBuffer* f) const {
-  f->Printf("%s", String::Handle(cls().ScrubbedName()).ToCString());
-  for (intptr_t i = 0; i < InputCount(); ++i) {
+void AllocationInstr::PrintOperandsTo(BaseTextBuffer* f) const {
+  Definition::PrintOperandsTo(f);
+  if (InputCount() > 0) {
     f->AddString(", ");
-    InputAt(i)->PrintTo(f);
   }
   if (Identity().IsNotAliased()) {
-    f->AddString(" <not-aliased>");
+    f->AddString("<not-aliased>");
   }
 }
 
+void AllocateObjectInstr::PrintOperandsTo(BaseTextBuffer* f) const {
+  f->Printf("cls=%s", String::Handle(cls().ScrubbedName()).ToCString());
+  if (InputCount() > 0 || Identity().IsNotAliased()) {
+    f->AddString(", ");
+  }
+  AllocationInstr::PrintOperandsTo(f);
+}
+
+void AllocateClosureInstr::PrintOperandsTo(BaseTextBuffer* f) const {
+  f->Printf("function=%s", closure_function().ToCString());
+  if (InputCount() > 0 || Identity().IsNotAliased()) {
+    f->AddString(", ");
+  }
+  TemplateAllocation::PrintOperandsTo(f);
+}
+
 void MaterializeObjectInstr::PrintOperandsTo(BaseTextBuffer* f) const {
   f->Printf("%s", String::Handle(cls_.ScrubbedName()).ToCString());
   for (intptr_t i = 0; i < InputCount(); i++) {
@@ -710,16 +725,20 @@
 }
 
 void AllocateContextInstr::PrintOperandsTo(BaseTextBuffer* f) const {
-  f->Printf("%" Pd "", num_context_variables());
+  f->Printf("num_variables=%" Pd "", num_context_variables());
+  if (InputCount() > 0 || Identity().IsNotAliased()) {
+    f->AddString(", ");
+  }
+  TemplateAllocation::PrintOperandsTo(f);
 }
 
 void AllocateUninitializedContextInstr::PrintOperandsTo(
     BaseTextBuffer* f) const {
-  f->Printf("%" Pd "", num_context_variables());
-
-  if (Identity().IsNotAliased()) {
-    f->AddString(" <not-aliased>");
+  f->Printf("num_variables=%" Pd "", num_context_variables());
+  if (InputCount() > 0 || Identity().IsNotAliased()) {
+    f->AddString(", ");
   }
+  TemplateAllocation::PrintOperandsTo(f);
 }
 
 void MathUnaryInstr::PrintOperandsTo(BaseTextBuffer* f) const {
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 4050f44..c727f66 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -13,6 +13,7 @@
 #include "vm/compiler/backend/il_printer.h"
 #include "vm/compiler/backend/type_propagator.h"
 #include "vm/compiler/compiler_pass.h"
+#include "vm/compiler/compiler_timings.h"
 #include "vm/compiler/frontend/flow_graph_builder.h"
 #include "vm/compiler/frontend/kernel_to_il.h"
 #include "vm/compiler/jit/compiler.h"
@@ -440,6 +441,7 @@
   void FindCallSites(FlowGraph* graph,
                      intptr_t depth,
                      GrowableArray<InlinedInfo>* inlined_info) {
+    COMPILER_TIMINGS_TIMER_SCOPE(graph->thread(), FindCallSites);
     ASSERT(graph != NULL);
     if (depth > inlining_depth_threshold_) {
       if (FLAG_print_inlining_tree) {
@@ -891,6 +893,24 @@
                    const Array& argument_names,
                    InlinedCallData* call_data,
                    bool stricter_heuristic) {
+    Timer timer;
+    if (thread()->compiler_timings() != nullptr) {
+      timer.Start();
+    }
+    const bool success = TryInliningImpl(function, argument_names, call_data,
+                                         stricter_heuristic);
+    if (thread()->compiler_timings() != nullptr) {
+      timer.Stop();
+      thread()->compiler_timings()->RecordInliningStatsByOutcome(success,
+                                                                 timer);
+    }
+    return success;
+  }
+
+  bool TryInliningImpl(const Function& function,
+                       const Array& argument_names,
+                       InlinedCallData* call_data,
+                       bool stricter_heuristic) {
     if (trace_inlining()) {
       String& name = String::Handle(function.QualifiedUserVisibleName());
       THR_Print("  => %s (deopt count %d)\n", name.ToCString(),
@@ -1040,6 +1060,7 @@
             caller_graph_->max_block_id() + 1,
             entry_kind == Code::EntryKind::kUnchecked);
         {
+          COMPILER_TIMINGS_TIMER_SCOPE(thread(), BuildGraph);
           callee_graph = builder.BuildGraph();
 #if defined(DEBUG)
           // The inlining IDs of instructions in the callee graph are unset
@@ -1051,6 +1072,10 @@
 #endif
           CalleeGraphValidator::Validate(callee_graph);
         }
+
+        {
+          COMPILER_TIMINGS_TIMER_SCOPE(thread(), PopulateWithICData);
+
 #if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
         if (CompilerState::Current().is_aot()) {
           callee_graph->PopulateWithICData(parsed_function->function());
@@ -1063,6 +1088,7 @@
         if (!CompilerState::Current().is_aot() && function.is_intrinsic()) {
           callee_graph->PopulateWithICData(parsed_function->function());
         }
+        }
 
         // The parameter stubs are a copy of the actual arguments providing
         // concrete information about the values, for example constant values,
@@ -1127,6 +1153,7 @@
 
         {
           // Compute SSA on the callee graph, catching bailouts.
+          COMPILER_TIMINGS_TIMER_SCOPE(thread(), ComputeSSA);
           callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(),
                                    param_stubs);
 #if defined(DEBUG)
@@ -1196,46 +1223,54 @@
                                            &call_site_count);
 
         // Use heuristics do decide if this call should be inlined.
-        InliningDecision decision =
-            ShouldWeInline(function, instruction_count, call_site_count);
-        if (!decision.value) {
-          // If size is larger than all thresholds, don't consider it again.
-          if ((instruction_count > FLAG_inlining_size_threshold) &&
-              (call_site_count > FLAG_inlining_callee_call_sites_threshold)) {
-            function.set_is_inlinable(false);
-          }
-          TRACE_INLINING(
-              THR_Print("     Bailout: heuristics (%s) with "
-                        "code size:  %" Pd ", "
-                        "call sites: %" Pd ", "
-                        "inlining depth of callee: %d, "
-                        "const args: %" Pd "\n",
-                        decision.reason, instruction_count, call_site_count,
-                        function.inlining_depth(), constants_count));
-          PRINT_INLINING_TREE("Heuristic fail", &call_data->caller, &function,
-                              call_data->call);
-          return false;
-        }
-
-        // If requested, a stricter heuristic is applied to this inlining. This
-        // heuristic always scans the method (rather than possibly reusing
-        // cached results) to make sure all specializations are accounted for.
-        // TODO(ajcbik): with the now better bookkeeping, explore removing this
-        if (stricter_heuristic) {
-          if (!IsSmallLeaf(callee_graph)) {
+        {
+          COMPILER_TIMINGS_TIMER_SCOPE(thread(), MakeInliningDecision);
+          InliningDecision decision =
+              ShouldWeInline(function, instruction_count, call_site_count);
+          if (!decision.value) {
+            // If size is larger than all thresholds, don't consider it again.
+            if ((instruction_count > FLAG_inlining_size_threshold) &&
+                (call_site_count > FLAG_inlining_callee_call_sites_threshold)) {
+              function.set_is_inlinable(false);
+            }
             TRACE_INLINING(
-                THR_Print("     Bailout: heuristics (no small leaf)\n"));
-            PRINT_INLINING_TREE("Heuristic fail (no small leaf)",
-                                &call_data->caller, &function, call_data->call);
+                THR_Print("     Bailout: heuristics (%s) with "
+                          "code size:  %" Pd ", "
+                          "call sites: %" Pd ", "
+                          "inlining depth of callee: %d, "
+                          "const args: %" Pd "\n",
+                          decision.reason, instruction_count, call_site_count,
+                          function.inlining_depth(), constants_count));
+            PRINT_INLINING_TREE("Heuristic fail", &call_data->caller, &function,
+                                call_data->call);
             return false;
           }
+
+          // If requested, a stricter heuristic is applied to this inlining.
+          // This heuristic always scans the method (rather than possibly
+          // reusing cached results) to make sure all specializations are
+          // accounted for.
+          // TODO(ajcbik): with the now better bookkeeping, explore removing
+          // this
+          if (stricter_heuristic) {
+            if (!IsSmallLeaf(callee_graph)) {
+              TRACE_INLINING(
+                  THR_Print("     Bailout: heuristics (no small leaf)\n"));
+              PRINT_INLINING_TREE("Heuristic fail (no small leaf)",
+                                  &call_data->caller, &function,
+                                  call_data->call);
+              return false;
+            }
+          }
         }
 
         // Inline dispatcher methods regardless of the current depth.
-        const intptr_t depth =
-            function.IsDispatcherOrImplicitAccessor() ? 0 : inlining_depth_;
-        collected_call_sites_->FindCallSites(callee_graph, depth,
-                                             &inlined_info_);
+        {
+          const intptr_t depth =
+              function.IsDispatcherOrImplicitAccessor() ? 0 : inlining_depth_;
+          collected_call_sites_->FindCallSites(callee_graph, depth,
+                                               &inlined_info_);
+        }
 
         // Add the function to the cache.
         if (!in_cache) {
@@ -1262,9 +1297,12 @@
               callee_guarded_fields[i]);
         }
 
-        FlowGraphInliner::SetInliningId(
-            callee_graph, inliner_->NextInlineId(callee_graph->function(),
-                                                 call_data->call->source()));
+        {
+          COMPILER_TIMINGS_TIMER_SCOPE(thread(), SetInliningId);
+          FlowGraphInliner::SetInliningId(
+              callee_graph, inliner_->NextInlineId(callee_graph->function(),
+                                                   call_data->call->source()));
+        }
         TRACE_INLINING(THR_Print("     Success\n"));
         TRACE_INLINING(THR_Print(
             "       with reason %s, code size %" Pd ", call sites: %" Pd "\n",
@@ -1365,6 +1403,7 @@
   }
 
   void InlineCall(InlinedCallData* call_data) {
+    COMPILER_TIMINGS_TIMER_SCOPE(thread(), InlineCall);
     FlowGraph* callee_graph = call_data->callee_graph;
     auto callee_function_entry = callee_graph->graph_entry()->normal_entry();
 
@@ -1473,11 +1512,8 @@
       Function& target = Function::ZoneHandle();
       Definition* receiver =
           call->Receiver()->definition()->OriginalDefinition();
-      if (AllocateObjectInstr* alloc = receiver->AsAllocateObject()) {
-        if (!alloc->closure_function().IsNull()) {
-          target = alloc->closure_function().ptr();
-          ASSERT(alloc->cls().IsClosureClass());
-        }
+      if (const auto* alloc = receiver->AsAllocateClosure()) {
+        target = alloc->closure_function().ptr();
       } else if (ConstantInstr* constant = receiver->AsConstant()) {
         if (constant->value().IsClosure()) {
           target = Closure::Cast(constant->value()).function();
@@ -1845,6 +1881,7 @@
 // If not all variants are inlined, we add a PolymorphicInstanceCall
 // instruction to handle the non-inlined variants.
 TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
+  COMPILER_TIMINGS_TIMER_SCOPE(owner_->thread(), BuildDecisionGraph);
   const intptr_t try_idx = call_->GetBlock()->try_index();
 
   // Start with a fresh target entry.
@@ -2204,6 +2241,7 @@
                                         bool force,
                                         intptr_t* instruction_count,
                                         intptr_t* call_site_count) {
+  COMPILER_TIMINGS_TIMER_SCOPE(flow_graph->thread(), CollectGraphInfo);
   const Function& function = flow_graph->function();
   // For OSR, don't even bother.
   if (flow_graph->IsCompiledForOsr()) {
@@ -2259,16 +2297,20 @@
 }
 
 bool FlowGraphInliner::FunctionHasPreferInlinePragma(const Function& function) {
+  Thread* thread = dart::Thread::Current();
+  COMPILER_TIMINGS_TIMER_SCOPE(thread, CheckForPragma);
   Object& options = Object::Handle();
-  return Library::FindPragma(dart::Thread::Current(), /*only_core=*/false,
-                             function, Symbols::vm_prefer_inline(),
+  return Library::FindPragma(thread, /*only_core=*/false, function,
+                             Symbols::vm_prefer_inline(),
                              /*multiple=*/false, &options);
 }
 
 bool FlowGraphInliner::FunctionHasNeverInlinePragma(const Function& function) {
+  Thread* thread = dart::Thread::Current();
+  COMPILER_TIMINGS_TIMER_SCOPE(thread, CheckForPragma);
   Object& options = Object::Handle();
-  return Library::FindPragma(dart::Thread::Current(), /*only_core=*/false,
-                             function, Symbols::vm_never_inline(),
+  return Library::FindPragma(thread, /*only_core=*/false, function,
+                             Symbols::vm_never_inline(),
                              /*multiple=*/false, &options);
 }
 
@@ -2279,6 +2321,7 @@
     return true;
   }
 
+  COMPILER_TIMINGS_TIMER_SCOPE(dart::Thread::Current(), MakeInliningDecision);
   // We don't want to inline DIFs for recognized methods because we would rather
   // replace them with inline FG before inlining introduces any superfluous
   // AssertAssignable instructions.
@@ -3619,6 +3662,8 @@
     Definition** result,
     SpeculativeInliningPolicy* policy,
     FlowGraphInliner::ExactnessInfo* exactness) {
+  COMPILER_TIMINGS_TIMER_SCOPE(flow_graph->thread(), InlineRecognizedMethod);
+
   if (receiver_cid == kNeverCid) {
     // Receiver was defined in dead code and was replaced by the sentinel.
     // Original receiver cid is lost, so don't try to inline recognized
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index 920a8cf..bf2afc0 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -2009,15 +2009,6 @@
           continue;
         }
 
-        // For object allocation forward initial values of the fields to
-        // subsequent loads (and potential dead stores) except for final
-        // fields of escaping objects. Final fields are initialized in
-        // constructor which potentially was not inlined into the function
-        // that we are currently optimizing. However at the same time we
-        // assume that values of the final fields can be forwarded across
-        // side-effects. If we add 'null' as known values for these fields
-        // here we will incorrectly propagate this null across constructor
-        // invocation.
         if (auto alloc = instr->AsAllocateObject()) {
           for (Value* use = alloc->input_use_list(); use != NULL;
                use = use->next_use()) {
@@ -2037,11 +2028,19 @@
             }
 
             if (slot != nullptr) {
-              // Found a load/store. Initialize current value of the field
-              // to null for normal fields, or with type arguments.
-
-              // If the object escapes then don't forward final fields - see
-              // the comment above for explanation.
+              // Found a load/store. For object allocation, forward initial
+              // values of the fields to subsequent loads (and potential dead
+              // stores). For most fields, this is null, except for the type
+              // arguments slot. However, we do not forward an initial null
+              // value for final fields of escaping objects.
+              //
+              // Final fields are initialized in constructors. However, at the
+              // same time we assume that known values of final fields can be
+              // forwarded across side-effects. For an escaping object, one such
+              // side effect can be an uninlined constructor invocation. Thus,
+              // if we add 'null' as known initial values for these fields,
+              // this null will be incorrectly propagated across any uninlined
+              // constructor invocation and used instead of the real value.
               if (aliased_set_->CanBeAliased(alloc) && slot->IsDartField() &&
                   slot->is_immutable()) {
                 continue;
@@ -2061,6 +2060,39 @@
             }
           }
           continue;
+        } else if (auto alloc = instr->AsAllocateClosure()) {
+          for (Value* use = alloc->input_use_list(); use != nullptr;
+               use = use->next_use()) {
+            // Look for all immediate loads/stores from this object.
+            if (use->use_index() != 0) {
+              continue;
+            }
+            const Slot* slot = nullptr;
+            intptr_t place_id = 0;
+            if (auto load = use->instruction()->AsLoadField()) {
+              slot = &load->slot();
+              place_id = GetPlaceId(load);
+            } else if (auto store =
+                           use->instruction()->AsStoreInstanceField()) {
+              slot = &store->slot();
+              place_id = GetPlaceId(store);
+            }
+
+            if (slot != nullptr) {
+              // Found a load/store. Initialize current value of the field
+              // to null.
+              //
+              // Note that unlike objects in general, there is no _Closure
+              // constructor in Dart code, but instead the FlowGraphBuilder
+              // explicitly initializes each non-null closure field in the flow
+              // graph with StoreInstanceField instructions post-allocation.
+              Definition* forward_def = graph_->constant_null();
+              gen->Add(place_id);
+              if (out_values == nullptr) out_values = CreateBlockOutValues();
+              (*out_values)[place_id] = forward_def;
+            }
+          }
+          continue;
         } else if (auto alloc = instr->AsCreateArray()) {
           for (Value* use = alloc->input_use_list(); use != nullptr;
                use = use->next_use()) {
@@ -3049,6 +3081,7 @@
 // can be sunk by the Allocation Sinking pass.
 static bool IsSupportedAllocation(Instruction* instr) {
   return instr->IsAllocateObject() || instr->IsAllocateUninitializedContext() ||
+         instr->IsAllocateClosure() ||
          (instr->IsArrayAllocation() &&
           IsValidLengthForAllocationSinking(instr->AsArrayAllocation()));
 }
@@ -3566,6 +3599,9 @@
   intptr_t num_elements = -1;
   if (auto instr = alloc->AsAllocateObject()) {
     cls = &(instr->cls());
+  } else if (auto instr = alloc->AsAllocateClosure()) {
+    cls = &Class::ZoneHandle(
+        flow_graph_->isolate_group()->object_store()->closure_class());
   } else if (auto instr = alloc->AsAllocateUninitializedContext()) {
     cls = &Class::ZoneHandle(Object::context_class());
     num_elements = instr->num_context_variables();
@@ -3690,6 +3726,10 @@
                                                    alloc_object->cls()));
     }
   }
+  if (auto alloc_closure = alloc->AsAllocateClosure()) {
+    // Any closure slots that are non-null are explicitly initialized
+    // post-allocation using StoreInstanceField instructions.
+  }
   if (alloc->IsCreateArray()) {
     AddSlot(
         slots,
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index 6248192..670e1d6 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -345,12 +345,23 @@
 CompileType Slot::ComputeCompileType() const {
   // If we unboxed the slot, we may know a more precise type.
   switch (representation()) {
+#if defined(TARGET_ARCH_IS_32_BIT)
+    // Int32/Uint32 values are not guaranteed to fit in a Smi.
+    case kUnboxedInt32:
+    case kUnboxedUint32:
+#endif
     case kUnboxedInt64:
       if (nullable_cid() == kDynamicCid) {
         return CompileType::Int();
       }
-      // Might be an CID like nullable_cid == kSmiCid.
       break;
+#if defined(TARGET_ARCH_IS_64_BIT)
+    // Int32/Uint32 values are guaranteed to fit in a Smi.
+    case kUnboxedInt32:
+    case kUnboxedUint32:
+#endif
+    case kUnboxedUint8:
+      return CompileType::Smi();
     case kUnboxedDouble:
       return CompileType::FromCid(kDoubleCid);
     case kUnboxedInt32x4:
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 6175f11..72a427f 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -1486,16 +1486,19 @@
 }
 
 CompileType AllocateObjectInstr::ComputeType() const {
-  if (!closure_function().IsNull()) {
-    ASSERT(cls().id() == kClosureCid);
-    const FunctionType& sig =
-        FunctionType::ZoneHandle(closure_function().signature());
-    return CompileType(CompileType::kNonNullable, kClosureCid, &sig);
-  }
   // TODO(vegorov): Incorporate type arguments into the returned type.
   return CompileType::FromCid(cls().id());
 }
 
+CompileType AllocateClosureInstr::ComputeType() const {
+  const auto& func = closure_function();
+  if (!func.IsNull()) {
+    const auto& sig = FunctionType::ZoneHandle(func.signature());
+    return CompileType(CompileType::kNonNullable, kClosureCid, &sig);
+  }
+  return CompileType::FromCid(kClosureCid);
+}
+
 CompileType LoadUntaggedInstr::ComputeType() const {
   return CompileType::Dynamic();
 }
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index 1dfcdce..d6071ee 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -15,11 +15,13 @@
 #include "vm/compiler/backend/redundancy_elimination.h"
 #include "vm/compiler/backend/type_propagator.h"
 #include "vm/compiler/call_specializer.h"
+#include "vm/compiler/compiler_timings.h"
 #include "vm/compiler/write_barrier_elimination.h"
 #if defined(DART_PRECOMPILER)
 #include "vm/compiler/aot/aot_call_specializer.h"
 #include "vm/compiler/aot/precompiler.h"
 #endif
+#include "vm/thread.h"
 #include "vm/timeline.h"
 
 #define COMPILER_PASS_REPEAT(Name, Body)                                       \
@@ -207,7 +209,10 @@
     PrintGraph(state, kTraceBefore, round);
     {
       TIMELINE_DURATION(thread, CompilerVerbose, name());
-      repeat = DoBody(state);
+      {
+        COMPILER_TIMINGS_PASS_TIMER_SCOPE(thread, id());
+        repeat = DoBody(state);
+      }
       thread->CheckForSafepoint();
     }
     PrintGraph(state, kTraceAfter, round);
diff --git a/runtime/vm/compiler/compiler_pass.h b/runtime/vm/compiler/compiler_pass.h
index 39dc9bd..1438db8 100644
--- a/runtime/vm/compiler/compiler_pass.h
+++ b/runtime/vm/compiler/compiler_pass.h
@@ -12,6 +12,7 @@
 #include <initializer_list>
 
 #include "vm/growable_array.h"
+#include "vm/timer.h"
 #include "vm/token_position.h"
 #include "vm/zone.h"
 
@@ -110,7 +111,7 @@
   static constexpr intptr_t kNumPasses = 0 COMPILER_PASS_LIST(ADD_ONE);
 #undef ADD_ONE
 
-  CompilerPass(Id id, const char* name) : name_(name), flags_(0) {
+  CompilerPass(Id id, const char* name) : id_(id), name_(name), flags_(0) {
     ASSERT(passes_[id] == NULL);
     passes_[id] = this;
 
@@ -133,6 +134,7 @@
 
   intptr_t flags() const { return flags_; }
   const char* name() const { return name_; }
+  Id id() const { return id_; }
 
   bool IsFlagSet(Flag flag) const { return (flags() & flag) != 0; }
 
@@ -187,6 +189,7 @@
 
   static CompilerPass* passes_[];
 
+  Id id_;
   const char* name_;
   intptr_t flags_;
 };
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index 1b237e9..51b81d1 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -87,6 +87,8 @@
   "compiler_pass.h",
   "compiler_state.cc",
   "compiler_state.h",
+  "compiler_timings.cc",
+  "compiler_timings.h",
   "ffi/abi.cc",
   "ffi/abi.h",
   "ffi/call.cc",
diff --git a/runtime/vm/compiler/compiler_state.h b/runtime/vm/compiler/compiler_state.h
index a200ea9..db608f3 100644
--- a/runtime/vm/compiler/compiler_state.h
+++ b/runtime/vm/compiler/compiler_state.h
@@ -13,6 +13,7 @@
 #include "vm/compiler/cha.h"
 #include "vm/heap/safepoint.h"
 #include "vm/thread.h"
+#include "vm/timer.h"
 
 namespace dart {
 
diff --git a/runtime/vm/compiler/compiler_timings.cc b/runtime/vm/compiler/compiler_timings.cc
new file mode 100644
index 0000000..b031442
--- /dev/null
+++ b/runtime/vm/compiler/compiler_timings.cc
@@ -0,0 +1,106 @@
+// 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.
+
+#include "vm/compiler/compiler_timings.h"
+
+namespace dart {
+
+namespace {
+#define DEFINE_NAME(Name) #Name,
+const char* timer_names[] = {COMPILER_TIMERS_LIST(DEFINE_NAME)};
+#undef DEFINE_NAME
+
+}  // namespace
+
+void CompilerTimings::PrintTimers(
+    Zone* zone,
+    const std::unique_ptr<CompilerTimings::Timers>& timers,
+    const Timer& total,
+    intptr_t level) {
+  const int64_t total_elapsed = total.TotalElapsedTime();
+
+  int64_t total_accounted = 0;
+  int64_t total_accounted_cpu = 0;
+  for (intptr_t i = 0; i < kNumTimers; i++) {
+    const auto& entry = timers->timers_[i];
+    total_accounted += entry.TotalElapsedTime();
+    total_accounted_cpu += entry.TotalElapsedTimeCpu();
+  }
+
+  if (level > 0) {
+    // Print (self: ...) timing on the previous line if our amount of time
+    // spent outside of nested timers is between 1% and 99%.
+    const double kMinInterestingSelfPercent = 1.0;
+    const double kMaxInterestingSelfPercent = 99.0;
+
+    const int64_t self = total_elapsed - total_accounted;
+    const auto self_pct =
+        static_cast<double>(Utils::Abs(self)) * 100 / total_elapsed;
+    if (kMinInterestingSelfPercent < self_pct &&
+        self_pct < kMaxInterestingSelfPercent) {
+      const int64_t self_cpu =
+          total.TotalElapsedTimeCpu() - total_accounted_cpu;
+      const auto self_timer = Timer(self, self_cpu);
+      OS::PrintErr(" (self: [%6.2f%%] %s)\n", self_pct,
+                   self_timer.FormatElapsedHumanReadable(zone));
+    } else {
+      OS::PrintErr("\n");
+    }
+  }
+
+  // Sort timers by the amount of time elapsed within each one.
+  Timer* by_elapsed[kNumTimers];
+  for (intptr_t i = 0; i < kNumTimers; i++) {
+    by_elapsed[i] = &timers->timers_[i];
+  }
+  qsort(by_elapsed, kNumTimers, sizeof(Timer*),
+        [](const void* pa, const void* pb) -> int {
+          const auto a_elapsed =
+              (*static_cast<Timer* const*>(pa))->TotalElapsedTime();
+          const auto b_elapsed =
+              (*static_cast<Timer* const*>(pb))->TotalElapsedTime();
+          return b_elapsed < a_elapsed ? -1 : b_elapsed > a_elapsed ? 1 : 0;
+        });
+
+  // Print sorted in descending order.
+  for (intptr_t i = 0; i < kNumTimers; i++) {
+    auto timer = by_elapsed[i];
+    if (timer->TotalElapsedTime() > 0) {
+      const auto timer_id = static_cast<TimerId>(timer - &timers->timers_[0]);
+      const auto pct =
+          static_cast<double>(timer->TotalElapsedTime()) * 100 / total_elapsed;
+      // Must be int for * width specifier.
+      const int indent = static_cast<int>(level * 2);
+
+      // Note: don't emit EOL because PrintTimers can print self timing.
+      OS::PrintErr(
+          "%*s[%6.2f%%] %-*s %-10s", indent, "", pct, 60 - indent,
+          timer_names[timer_id],
+          Timer::FormatElapsedHumanReadable(zone, timer->TotalElapsedTime(),
+                                            timer->TotalElapsedTimeCpu()));
+
+      // Print nested timers if any or just emit EOL.
+      if (timers->nested_[timer_id] != nullptr) {
+        PrintTimers(zone, timers->nested_[timer_id], *timer, level + 1);
+      } else {
+        OS::PrintErr("\n");
+      }
+    }
+  }
+}
+
+void CompilerTimings::Print() {
+  Zone* zone = Thread::Current()->zone();
+
+  OS::PrintErr("Precompilation took: %s\n",
+               total_.FormatElapsedHumanReadable(zone));
+
+  PrintTimers(zone, root_, total_, 0);
+
+  OS::PrintErr("Inlining by outcome\n  Success: %s\n  Failure: %s\n",
+               try_inlining_success_.FormatElapsedHumanReadable(zone),
+               try_inlining_failure_.FormatElapsedHumanReadable(zone));
+}
+
+}  // namespace dart
diff --git a/runtime/vm/compiler/compiler_timings.h b/runtime/vm/compiler/compiler_timings.h
new file mode 100644
index 0000000..6f9b31b
--- /dev/null
+++ b/runtime/vm/compiler/compiler_timings.h
@@ -0,0 +1,160 @@
+// 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.
+
+#ifndef RUNTIME_VM_COMPILER_COMPILER_TIMINGS_H_
+#define RUNTIME_VM_COMPILER_COMPILER_TIMINGS_H_
+
+#include <memory>
+
+#include "platform/allocation.h"
+#include "vm/compiler/compiler_pass.h"
+#include "vm/thread.h"
+#include "vm/timer.h"
+
+#if defined(DART_PRECOMPILED_RUNTIME)
+#error "AOT runtime should not use compiler sources (including header files)"
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+
+#define PRECOMPILER_TIMERS_LIST(V)                                             \
+  V(CompileAll)                                                                \
+  V(Iterate)                                                                   \
+  V(CompileFunction)                                                           \
+  V(PrecompileConstructors)                                                    \
+  V(AttachOptimizedTypeTestingStub)                                            \
+  V(TraceForRetainedFunctions)                                                 \
+  V(FinalizeDispatchTable)                                                     \
+  V(ReplaceFunctionStaticCallEntries)                                          \
+  V(Drop)                                                                      \
+  V(Obfuscate)                                                                 \
+  V(Dedup)                                                                     \
+  V(SymbolsCompact)
+
+#define INLINING_TIMERS_LIST(V)                                                \
+  V(CollectGraphInfo)                                                          \
+  V(PopulateWithICData)                                                        \
+  V(FindCallSites)                                                             \
+  V(SetInliningId)                                                             \
+  V(MakeInliningDecision)                                                      \
+  V(CheckForPragma)                                                            \
+  V(InlineCall)                                                                \
+  V(InlineRecognizedMethod)                                                    \
+  V(DiscoverBlocks)                                                            \
+  V(BuildDecisionGraph)                                                        \
+  V(PrepareGraphs)
+
+// Note: COMPILER_PASS_LIST must be the first element of the list below because
+// we expect that pass ids are the same as ids of corresponding timers.
+#define COMPILER_TIMERS_LIST(V)                                                \
+  COMPILER_PASS_LIST(V)                                                        \
+  PRECOMPILER_TIMERS_LIST(V)                                                   \
+  INLINING_TIMERS_LIST(V)                                                      \
+  V(BuildGraph)                                                                \
+  V(EmitCode)                                                                  \
+  V(FinalizeCode)
+
+namespace dart {
+
+// |CompilerTimings| provides a way to track time taken by various compiler
+// passes via a fixed number of timers (specified in |COMPILER_TIMERS_LIST|).
+//
+// It supports arbitrary nesting of timers e.g. if |DiscoverBlocks| is invoked
+// within two different compiler passes like |IfConvert| and |BranchSimplify|
+// then |CompilerTimings| will separate these two invocations and measure each
+// separately.
+class CompilerTimings : public MallocAllocated {
+ private:
+#define INC(Name) +1
+  static constexpr intptr_t kNumTimers = 0 COMPILER_TIMERS_LIST(INC);
+#undef INC
+
+  struct Timers : public MallocAllocated {
+    Timer timers_[kNumTimers];
+    std::unique_ptr<Timers> nested_[kNumTimers];
+  };
+
+ public:
+  enum TimerId {
+#define DECLARE_TIMER_ID(Name) k##Name,
+    COMPILER_TIMERS_LIST(DECLARE_TIMER_ID)
+#undef DECLARE_TIMER_ID
+  };
+
+  // Timing scope which starts and stop the timer with the given |id|.
+  class Scope : public StackResource {
+   public:
+    Scope(Thread* thread, TimerId id)
+        : StackResource(thread), stats_(thread->compiler_timings()) {
+      if (stats_ != nullptr) {
+        outer_nested_ = stats_->nested_;
+        if (*outer_nested_ == nullptr) {
+          // Created array of nested timers if we don't have one yet.
+          *outer_nested_ = std::make_unique<Timers>();
+        }
+
+        timer_ = &(*outer_nested_)->timers_[id];
+        stats_->nested_ = &(*outer_nested_)->nested_[id];
+
+        timer_->Start();
+      }
+    }
+
+    ~Scope() {
+      if (stats_ != nullptr) {
+        timer_->Stop();
+        stats_->nested_ = outer_nested_;
+      }
+    }
+
+   private:
+    CompilerTimings* const stats_;
+    Timer* timer_;
+    std::unique_ptr<Timers>* outer_nested_;
+  };
+
+  CompilerTimings() { total_.Start(); }
+
+  void RecordInliningStatsByOutcome(bool success, const Timer& timer) {
+    if (success) {
+      try_inlining_success_.AddTotal(timer);
+    } else {
+      try_inlining_failure_.AddTotal(timer);
+    }
+  }
+
+  void Print();
+
+ private:
+  void PrintTimers(Zone* zone,
+                   const std::unique_ptr<CompilerTimings::Timers>& timers,
+                   const Timer& total,
+                   intptr_t level);
+
+  Timer total_;
+  std::unique_ptr<Timers> root_ = std::make_unique<Timers>();
+
+  // Timers nested under the currently running timer(s).
+  std::unique_ptr<Timers>* nested_ = &root_;
+
+  Timer try_inlining_success_;
+  Timer try_inlining_failure_;
+};
+
+#define TIMER_SCOPE_NAME2(counter) timer_scope_##counter
+#define TIMER_SCOPE_NAME(counter) TIMER_SCOPE_NAME2(counter)
+
+#define COMPILER_TIMINGS_TIMER_SCOPE(thread, timer_id)                         \
+  CompilerTimings::Scope TIMER_SCOPE_NAME(__COUNTER__)(                        \
+      thread, CompilerTimings::k##timer_id)
+
+#define COMPILER_TIMINGS_PASS_TIMER_SCOPE(thread, pass_id)                     \
+  CompilerTimings::Scope TIMER_SCOPE_NAME(__COUNTER__)(                        \
+      thread, static_cast<CompilerTimings::TimerId>(pass_id))
+
+#define PRECOMPILER_TIMER_SCOPE(precompiler, timer_id)                         \
+  CompilerTimings::Scope TIMER_SCOPE_NAME(__COUNTER__)(                        \
+      (precompiler)->thread(), CompilerTimings::k##timer_id)
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_COMPILER_COMPILER_TIMINGS_H_
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 4d789d4..8274032 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -889,13 +889,10 @@
   return Fragment(allocate);
 }
 
-Fragment BaseFlowGraphBuilder::AllocateClosure(
-    TokenPosition position,
-    const Function& closure_function) {
-  const Class& cls = Class::ZoneHandle(Z, IG->object_store()->closure_class());
-  AllocateObjectInstr* allocate = new (Z)
-      AllocateObjectInstr(InstructionSource(position), cls, GetNextDeoptId());
-  allocate->set_closure_function(closure_function);
+Fragment BaseFlowGraphBuilder::AllocateClosure(const Function& closure_function,
+                                               TokenPosition position) {
+  auto* allocate = new (Z) AllocateClosureInstr(
+      InstructionSource(position), closure_function, GetNextDeoptId());
   Push(allocate);
   return Fragment(allocate);
 }
@@ -1009,7 +1006,7 @@
   code += LoadLocal(pointer);
   code += StoreNativeField(*context_slots[0]);
 
-  code += AllocateClosure(TokenPosition::kNoSource, target);
+  code += AllocateClosure(target);
   LocalVariable* closure = MakeTemporary();
 
   code += LoadLocal(closure);
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index ae5bcb3..483750a 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -341,8 +341,10 @@
   Fragment AssertBool(TokenPosition position);
   Fragment BooleanNegate();
   Fragment AllocateContext(const ZoneGrowableArray<const Slot*>& scope);
-  Fragment AllocateClosure(TokenPosition position,
-                           const Function& closure_function);
+  // closure_function can be null if not statically known (i.e., copying from
+  // another closure object).
+  Fragment AllocateClosure(const Function& closure_function,
+                           TokenPosition position = TokenPosition::kNoSource);
   Fragment CreateArray();
   Fragment AllocateTypedData(TokenPosition position, classid_t class_id);
   Fragment InstantiateType(const AbstractType& type);
diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.cc b/runtime/vm/compiler/frontend/flow_graph_builder.cc
index c2ed762..8b7a394 100644
--- a/runtime/vm/compiler/frontend/flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/flow_graph_builder.cc
@@ -7,6 +7,7 @@
 #include "vm/compiler/backend/branch_optimizer.h"
 #include "vm/compiler/backend/flow_graph.h"
 #include "vm/compiler/backend/il.h"
+#include "vm/compiler/compiler_timings.h"
 #include "vm/compiler/frontend/kernel_to_il.h"
 #include "vm/object.h"
 #include "vm/zone.h"
@@ -37,6 +38,7 @@
 }
 
 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) {
+  COMPILER_TIMINGS_TIMER_SCOPE(callee_graph->thread(), PrepareGraphs);
   ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1);
   ASSERT(callee_graph->max_block_id() > caller_graph_->max_block_id());
   ASSERT(callee_graph->max_virtual_register_number() >
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index dc366d3..36e5460 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1487,8 +1487,12 @@
   return flow_graph_builder_->LookupVariable(kernel_offset);
 }
 
-LocalVariable* StreamingFlowGraphBuilder::MakeTemporary() {
-  return flow_graph_builder_->MakeTemporary();
+LocalVariable* StreamingFlowGraphBuilder::MakeTemporary(const char* suffix) {
+  return flow_graph_builder_->MakeTemporary(suffix);
+}
+
+Fragment StreamingFlowGraphBuilder::DropTemporary(LocalVariable** variable) {
+  return flow_graph_builder_->DropTemporary(variable);
 }
 
 Function& StreamingFlowGraphBuilder::FindMatchingFunction(
@@ -4370,15 +4374,14 @@
   Fragment instructions = BuildExpression();
   LocalVariable* original_closure = MakeTemporary();
 
-  instructions += AllocateObject(
-      TokenPosition::kNoSource,
-      Class::ZoneHandle(Z, IG->object_store()->closure_class()), 0);
+  // The closure function isn't known at compile time.
+  instructions += flow_graph_builder_->AllocateClosure(Object::null_function());
   LocalVariable* new_closure = MakeTemporary();
 
   intptr_t num_type_args = ReadListLength();
   const TypeArguments& type_args = T.BuildTypeArguments(num_type_args);
   instructions += TranslateInstantiatedTypeArguments(type_args);
-  LocalVariable* type_args_vec = MakeTemporary();
+  LocalVariable* type_args_vec = MakeTemporary("type_args");
 
   // Check the bounds.
   //
@@ -4401,7 +4404,7 @@
   instructions += flow_graph_builder_->StoreNativeField(
       Slot::Closure_delayed_type_arguments(),
       StoreInstanceFieldInstr::Kind::kInitializing);
-  instructions += Drop();  // Drop type args.
+  instructions += DropTemporary(&type_args_vec);
 
   // Copy over the target function.
   instructions += LoadLocal(new_closure);
@@ -5565,8 +5568,7 @@
 
   function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
 
-  Fragment instructions =
-      flow_graph_builder_->AllocateClosure(TokenPosition::kNoSource, function);
+  Fragment instructions = flow_graph_builder_->AllocateClosure(function);
   LocalVariable* closure = MakeTemporary();
 
   // The function signature can have uninstantiated class type parameters.
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index c11dc7d..89105dd 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -137,7 +137,8 @@
   intptr_t PeekArgumentsCount();
 
   // See BaseFlowGraphBuilder::MakeTemporary.
-  LocalVariable* MakeTemporary();
+  LocalVariable* MakeTemporary(const char* suffix = nullptr);
+  Fragment DropTemporary(LocalVariable** variable);
 
   LocalVariable* LookupVariable(intptr_t kernel_offset);
   Function& FindMatchingFunction(const Class& klass,
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 8e3f11e..064f260 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1584,7 +1584,7 @@
 Fragment FlowGraphBuilder::BuildImplicitClosureCreation(
     const Function& target) {
   Fragment fragment;
-  fragment += AllocateClosure(TokenPosition::kNoSource, target);
+  fragment += AllocateClosure(target);
   LocalVariable* closure = MakeTemporary();
 
   // The function signature can have uninstantiated class type parameters.
@@ -1658,8 +1658,8 @@
   if (definition->IsConstant() || definition->IsLoadStaticField()) {
     return true;
   }
-  if (definition->IsAllocateObject()) {
-    return !definition->AsAllocateObject()->closure_function().IsNull();
+  if (auto const alloc = definition->AsAllocateClosure()) {
+    return !alloc->closure_function().IsNull();
   }
   return definition->IsLoadLocal();
 }
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 7539cf8..0104e80 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -704,7 +704,7 @@
     Zone* const zone = stack_zone.GetZone();
     const bool trace_compiler =
         FLAG_trace_compiler || (FLAG_trace_optimizing_compiler && optimized);
-    Timer per_compile_timer(trace_compiler, "Compilation time");
+    Timer per_compile_timer;
     per_compile_timer.Start();
 
     ParsedFunction* parsed_function = new (zone)
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 6b414a1..7f52832 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -29,6 +29,11 @@
   return Utils::IsInt(kSmiBits + 1, v);
 }
 
+bool WillAllocateNewOrRememberedObject(intptr_t instance_size) {
+  ASSERT(Utils::IsAligned(instance_size, ObjectAlignment::kObjectAlignment));
+  return dart::Heap::IsAllocatableInNewSpace(instance_size);
+}
+
 bool WillAllocateNewOrRememberedContext(intptr_t num_context_variables) {
   if (!dart::Context::IsValidLength(num_context_variables)) return false;
   return dart::Heap::IsAllocatableInNewSpace(
@@ -191,6 +196,11 @@
   return Class::Handle(object_store->int32x4_class());
 }
 
+const Class& ClosureClass() {
+  auto object_store = IsolateGroup::Current()->object_store();
+  return Class::Handle(object_store->closure_class());
+}
+
 const Array& OneArgArgumentsDescriptor() {
   return Array::ZoneHandle(
       ArgumentsDescriptor::NewBoxed(/*type_args_len=*/0, /*num_arguments=*/1));
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index a1e4ed8..4dea5ad 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -117,6 +117,7 @@
 const Class& Float32x4Class();
 const Class& Float64x2Class();
 const Class& Int32x4Class();
+const Class& ClosureClass();
 const Array& OneArgArgumentsDescriptor();
 
 template <typename To, typename From>
@@ -410,6 +411,8 @@
 word ToRawPointer(const dart::Object& a);
 #endif  // defined(TARGET_ARCH_IA32)
 
+bool WillAllocateNewOrRememberedObject(intptr_t instance_size);
+
 bool WillAllocateNewOrRememberedContext(intptr_t num_context_variables);
 
 bool WillAllocateNewOrRememberedArray(intptr_t length);
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index 04ee986..ff5bee2 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -245,9 +245,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 368;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    720;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     724;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    728;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 120;
 static constexpr dart::compiler::target::word
@@ -272,7 +272,7 @@
     Thread_allocate_object_slow_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 196;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 760;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 764;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 332;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
@@ -283,7 +283,7 @@
     Thread_call_to_runtime_entry_point_offset = 268;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 136;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 768;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 772;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -301,7 +301,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    740;
+    744;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
@@ -321,13 +321,13 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 364;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    728;
+    732;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    756;
+    760;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 772;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 776;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
 static constexpr dart::compiler::target::word
@@ -369,11 +369,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 732;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 736;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 736;
+    Thread_saved_shadow_call_stack_offset = 740;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    744;
+    748;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
@@ -407,9 +407,9 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     36;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 748;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 752;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 752;
+    Thread_callback_stack_return_offset = 756;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
 static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -467,7 +467,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        688, 692, 696, 700, 704, -1, 708, -1, 712, 716, -1, -1, -1, -1, -1, -1};
+        692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 12;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 8;
 static constexpr dart::compiler::target::word Array_header_size = 12;
@@ -785,9 +785,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1456;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     1464;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1472;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -813,7 +813,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -824,7 +824,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1552;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1560;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -842,7 +842,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1496;
+    1504;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -862,14 +862,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1472;
+    1480;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1528;
+    1536;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1560;
+    1568;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -911,11 +911,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1480;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1488;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1488;
+    Thread_saved_shadow_call_stack_offset = 1496;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1504;
+    1512;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -950,9 +950,9 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1512;
+    1520;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1520;
+    Thread_callback_stack_return_offset = 1528;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -1011,8 +1011,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, -1,   -1,   1400, 1408,
-        1416, 1424, 1432, -1,   1440, 1448, -1,   -1};
+        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
+        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -1328,9 +1328,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 368;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    688;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     692;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    696;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 120;
 static constexpr dart::compiler::target::word
@@ -1355,7 +1355,7 @@
     Thread_allocate_object_slow_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 196;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 728;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 732;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 332;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
@@ -1366,7 +1366,7 @@
     Thread_call_to_runtime_entry_point_offset = 268;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 136;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 736;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 740;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -1384,7 +1384,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    708;
+    712;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
@@ -1404,13 +1404,13 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 364;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    696;
+    700;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    724;
+    728;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 740;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 744;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
 static constexpr dart::compiler::target::word
@@ -1452,11 +1452,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 700;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 704;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 704;
+    Thread_saved_shadow_call_stack_offset = 708;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    712;
+    716;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
@@ -1490,9 +1490,9 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     36;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 716;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 720;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 720;
+    Thread_callback_stack_return_offset = 724;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
 static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -1865,9 +1865,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1520;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     1528;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1536;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -1893,7 +1893,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1600;
+    1608;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -1904,7 +1904,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1616;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -1922,7 +1922,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1560;
+    1568;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -1942,14 +1942,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1592;
+    1600;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1624;
+    1632;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -1991,11 +1991,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1544;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1552;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1552;
+    Thread_saved_shadow_call_stack_offset = 1560;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1568;
+    1576;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -2030,9 +2030,9 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1576;
+    1584;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1584;
+    Thread_callback_stack_return_offset = 1592;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -2091,9 +2091,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448,
-        1456, 1464, 1472, 1480, -1,   -1,   -1,   -1,   1488, 1496, -1,
-        -1,   -1,   1504, 1512, -1,   -1,   -1,   -1,   -1,   -1};
+        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
+        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
+        -1,   -1,   1512, 1520, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -2410,9 +2410,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1456;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     1464;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1472;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -2438,7 +2438,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -2449,7 +2449,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1552;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1560;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -2467,7 +2467,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1496;
+    1504;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -2487,14 +2487,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1472;
+    1480;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1528;
+    1536;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1560;
+    1568;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -2536,11 +2536,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1480;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1488;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1488;
+    Thread_saved_shadow_call_stack_offset = 1496;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1504;
+    1512;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -2575,9 +2575,9 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1512;
+    1520;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1520;
+    Thread_callback_stack_return_offset = 1528;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -2636,8 +2636,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, -1,   -1,   1400, 1408,
-        1416, 1424, 1432, -1,   1440, 1448, -1,   -1};
+        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
+        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -2954,9 +2954,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1520;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     1528;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1536;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -2982,7 +2982,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1600;
+    1608;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -2993,7 +2993,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1616;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -3011,7 +3011,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1560;
+    1568;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -3031,14 +3031,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1592;
+    1600;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1624;
+    1632;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -3080,11 +3080,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1544;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1552;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1552;
+    Thread_saved_shadow_call_stack_offset = 1560;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1568;
+    1576;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -3119,9 +3119,9 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1576;
+    1584;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1584;
+    Thread_callback_stack_return_offset = 1592;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -3180,9 +3180,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448,
-        1456, 1464, 1472, 1480, -1,   -1,   -1,   -1,   1488, 1496, -1,
-        -1,   -1,   1504, 1512, -1,   -1,   -1,   -1,   -1,   -1};
+        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
+        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
+        -1,   -1,   1512, 1520, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -3494,9 +3494,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 368;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    720;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     724;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    728;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 120;
 static constexpr dart::compiler::target::word
@@ -3521,7 +3521,7 @@
     Thread_allocate_object_slow_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 196;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 760;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 764;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 332;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
@@ -3532,7 +3532,7 @@
     Thread_call_to_runtime_entry_point_offset = 268;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 136;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 768;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 772;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -3550,7 +3550,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    740;
+    744;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
@@ -3570,13 +3570,13 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 364;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    728;
+    732;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    756;
+    760;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 772;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 776;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
 static constexpr dart::compiler::target::word
@@ -3618,11 +3618,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 732;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 736;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 736;
+    Thread_saved_shadow_call_stack_offset = 740;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    744;
+    748;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
@@ -3656,9 +3656,9 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     36;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 748;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 752;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 752;
+    Thread_callback_stack_return_offset = 756;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
 static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -3716,7 +3716,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        688, 692, 696, 700, 704, -1, 708, -1, 712, 716, -1, -1, -1, -1, -1, -1};
+        692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 12;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 8;
 static constexpr dart::compiler::target::word Array_header_size = 12;
@@ -4028,9 +4028,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1456;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     1464;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1472;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -4056,7 +4056,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -4067,7 +4067,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1552;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1560;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -4085,7 +4085,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1496;
+    1504;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -4105,14 +4105,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1472;
+    1480;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1528;
+    1536;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1560;
+    1568;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -4154,11 +4154,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1480;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1488;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1488;
+    Thread_saved_shadow_call_stack_offset = 1496;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1504;
+    1512;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -4193,9 +4193,9 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1512;
+    1520;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1520;
+    Thread_callback_stack_return_offset = 1528;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -4254,8 +4254,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, -1,   -1,   1400, 1408,
-        1416, 1424, 1432, -1,   1440, 1448, -1,   -1};
+        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
+        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -4565,9 +4565,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 368;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    688;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     692;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    696;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 120;
 static constexpr dart::compiler::target::word
@@ -4592,7 +4592,7 @@
     Thread_allocate_object_slow_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 196;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 728;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 732;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 332;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
@@ -4603,7 +4603,7 @@
     Thread_call_to_runtime_entry_point_offset = 268;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 136;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 736;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 740;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -4621,7 +4621,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    708;
+    712;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
@@ -4641,13 +4641,13 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 364;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    696;
+    700;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    724;
+    728;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 740;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 744;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
 static constexpr dart::compiler::target::word
@@ -4689,11 +4689,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 700;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 704;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 704;
+    Thread_saved_shadow_call_stack_offset = 708;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    712;
+    716;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
@@ -4727,9 +4727,9 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     36;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 716;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 720;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 720;
+    Thread_callback_stack_return_offset = 724;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
 static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -5096,9 +5096,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1520;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     1528;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1536;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -5124,7 +5124,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1600;
+    1608;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -5135,7 +5135,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1616;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -5153,7 +5153,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1560;
+    1568;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -5173,14 +5173,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1592;
+    1600;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1624;
+    1632;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -5222,11 +5222,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1544;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1552;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1552;
+    Thread_saved_shadow_call_stack_offset = 1560;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1568;
+    1576;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -5261,9 +5261,9 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1576;
+    1584;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1584;
+    Thread_callback_stack_return_offset = 1592;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -5322,9 +5322,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448,
-        1456, 1464, 1472, 1480, -1,   -1,   -1,   -1,   1488, 1496, -1,
-        -1,   -1,   1504, 1512, -1,   -1,   -1,   -1,   -1,   -1};
+        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
+        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
+        -1,   -1,   1512, 1520, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -5635,9 +5635,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1456;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     1464;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1472;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -5663,7 +5663,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -5674,7 +5674,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1552;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1560;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -5692,7 +5692,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1496;
+    1504;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -5712,14 +5712,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1472;
+    1480;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1528;
+    1536;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1560;
+    1568;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -5761,11 +5761,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1480;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1488;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1488;
+    Thread_saved_shadow_call_stack_offset = 1496;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1504;
+    1512;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -5800,9 +5800,9 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1512;
+    1520;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1520;
+    Thread_callback_stack_return_offset = 1528;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -5861,8 +5861,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, -1,   -1,   1400, 1408,
-        1416, 1424, 1432, -1,   1440, 1448, -1,   -1};
+        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
+        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -6173,9 +6173,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1520;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     1528;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1536;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -6201,7 +6201,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1600;
+    1608;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -6212,7 +6212,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1616;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -6230,7 +6230,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1560;
+    1568;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -6250,14 +6250,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1592;
+    1600;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1624;
+    1632;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -6299,11 +6299,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1544;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1552;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1552;
+    Thread_saved_shadow_call_stack_offset = 1560;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1568;
+    1576;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -6338,9 +6338,9 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1576;
+    1584;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1584;
+    Thread_callback_stack_return_offset = 1592;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -6399,9 +6399,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448,
-        1456, 1464, 1472, 1480, -1,   -1,   -1,   -1,   1488, 1496, -1,
-        -1,   -1,   1504, 1512, -1,   -1,   -1,   -1,   -1,   -1};
+        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
+        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
+        -1,   -1,   1512, 1520, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -6747,9 +6747,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 368;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 720;
+    AOT_Thread_active_exception_offset = 724;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 724;
+    AOT_Thread_active_stacktrace_offset = 728;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 120;
 static constexpr dart::compiler::target::word
@@ -6775,7 +6775,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 196;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    760;
+    764;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 332;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -6788,7 +6788,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 136;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    768;
+    772;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -6807,7 +6807,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 740;
+    AOT_Thread_execution_state_offset = 744;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
@@ -6827,14 +6827,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 364;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 728;
+    AOT_Thread_global_object_pool_offset = 732;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 756;
+    AOT_Thread_exit_through_ffi_offset = 760;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 44;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    772;
+    776;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 68;
 static constexpr dart::compiler::target::word
@@ -6878,11 +6878,11 @@
     104;
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 732;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 736;
+    AOT_Thread_saved_shadow_call_stack_offset = 740;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 744;
+    AOT_Thread_safepoint_state_offset = 748;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
@@ -6919,9 +6919,9 @@
     AOT_Thread_write_barrier_mask_offset = 36;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 40;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    748;
+    752;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 752;
+    AOT_Thread_callback_stack_return_offset = 756;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -6992,7 +6992,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        688, 692, 696, 700, 704, -1, 708, -1, 712, 716, -1, -1, -1, -1, -1, -1};
+        692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     12;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 8;
@@ -7349,9 +7349,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1456;
+    AOT_Thread_active_exception_offset = 1464;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1464;
+    AOT_Thread_active_stacktrace_offset = 1472;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -7377,7 +7377,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -7390,7 +7390,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1552;
+    1560;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -7409,7 +7409,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1496;
+    AOT_Thread_execution_state_offset = 1504;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -7429,14 +7429,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1472;
+    AOT_Thread_global_object_pool_offset = 1480;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1528;
+    AOT_Thread_exit_through_ffi_offset = 1536;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1560;
+    1568;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
@@ -7481,11 +7481,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1480;
+    1488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1488;
+    AOT_Thread_saved_shadow_call_stack_offset = 1496;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1504;
+    AOT_Thread_safepoint_state_offset = 1512;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -7522,9 +7522,9 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1512;
+    1520;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1520;
+    AOT_Thread_callback_stack_return_offset = 1528;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -7596,8 +7596,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, -1,   -1,   1400, 1408,
-        1416, 1424, 1432, -1,   1440, 1448, -1,   -1};
+        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
+        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -7957,9 +7957,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1520;
+    AOT_Thread_active_exception_offset = 1528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1528;
+    AOT_Thread_active_stacktrace_offset = 1536;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -7985,7 +7985,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1600;
+    1608;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -7998,7 +7998,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1616;
+    1624;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -8017,7 +8017,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1560;
+    AOT_Thread_execution_state_offset = 1568;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -8037,14 +8037,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1536;
+    AOT_Thread_global_object_pool_offset = 1544;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1592;
+    AOT_Thread_exit_through_ffi_offset = 1600;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1624;
+    1632;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
@@ -8089,11 +8089,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1544;
+    1552;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1552;
+    AOT_Thread_saved_shadow_call_stack_offset = 1560;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1568;
+    AOT_Thread_safepoint_state_offset = 1576;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -8130,9 +8130,9 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1576;
+    1584;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1584;
+    AOT_Thread_callback_stack_return_offset = 1592;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -8204,9 +8204,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448,
-        1456, 1464, 1472, 1480, -1,   -1,   -1,   -1,   1488, 1496, -1,
-        -1,   -1,   1504, 1512, -1,   -1,   -1,   -1,   -1,   -1};
+        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
+        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
+        -1,   -1,   1512, 1520, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -8563,9 +8563,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1456;
+    AOT_Thread_active_exception_offset = 1464;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1464;
+    AOT_Thread_active_stacktrace_offset = 1472;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -8591,7 +8591,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -8604,7 +8604,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1552;
+    1560;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -8623,7 +8623,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1496;
+    AOT_Thread_execution_state_offset = 1504;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -8643,14 +8643,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1472;
+    AOT_Thread_global_object_pool_offset = 1480;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1528;
+    AOT_Thread_exit_through_ffi_offset = 1536;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1560;
+    1568;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
@@ -8695,11 +8695,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1480;
+    1488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1488;
+    AOT_Thread_saved_shadow_call_stack_offset = 1496;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1504;
+    AOT_Thread_safepoint_state_offset = 1512;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -8736,9 +8736,9 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1512;
+    1520;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1520;
+    AOT_Thread_callback_stack_return_offset = 1528;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -8810,8 +8810,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, -1,   -1,   1400, 1408,
-        1416, 1424, 1432, -1,   1440, 1448, -1,   -1};
+        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
+        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -9168,9 +9168,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1520;
+    AOT_Thread_active_exception_offset = 1528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1528;
+    AOT_Thread_active_stacktrace_offset = 1536;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -9196,7 +9196,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1600;
+    1608;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -9209,7 +9209,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1616;
+    1624;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -9228,7 +9228,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1560;
+    AOT_Thread_execution_state_offset = 1568;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -9248,14 +9248,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1536;
+    AOT_Thread_global_object_pool_offset = 1544;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1592;
+    AOT_Thread_exit_through_ffi_offset = 1600;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1624;
+    1632;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
@@ -9300,11 +9300,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1544;
+    1552;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1552;
+    AOT_Thread_saved_shadow_call_stack_offset = 1560;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1568;
+    AOT_Thread_safepoint_state_offset = 1576;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -9341,9 +9341,9 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1576;
+    1584;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1584;
+    AOT_Thread_callback_stack_return_offset = 1592;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -9415,9 +9415,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448,
-        1456, 1464, 1472, 1480, -1,   -1,   -1,   -1,   1488, 1496, -1,
-        -1,   -1,   1504, 1512, -1,   -1,   -1,   -1,   -1,   -1};
+        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
+        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
+        -1,   -1,   1512, 1520, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -9768,9 +9768,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 368;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 720;
+    AOT_Thread_active_exception_offset = 724;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 724;
+    AOT_Thread_active_stacktrace_offset = 728;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 120;
 static constexpr dart::compiler::target::word
@@ -9796,7 +9796,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 196;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    760;
+    764;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 332;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -9809,7 +9809,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 136;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    768;
+    772;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -9828,7 +9828,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 740;
+    AOT_Thread_execution_state_offset = 744;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
@@ -9848,14 +9848,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 364;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 728;
+    AOT_Thread_global_object_pool_offset = 732;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 756;
+    AOT_Thread_exit_through_ffi_offset = 760;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 44;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    772;
+    776;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 68;
 static constexpr dart::compiler::target::word
@@ -9899,11 +9899,11 @@
     104;
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 732;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 736;
+    AOT_Thread_saved_shadow_call_stack_offset = 740;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 744;
+    AOT_Thread_safepoint_state_offset = 748;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
@@ -9940,9 +9940,9 @@
     AOT_Thread_write_barrier_mask_offset = 36;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 40;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    748;
+    752;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 752;
+    AOT_Thread_callback_stack_return_offset = 756;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -10013,7 +10013,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        688, 692, 696, 700, 704, -1, 708, -1, 712, 716, -1, -1, -1, -1, -1, -1};
+        692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     12;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 8;
@@ -10363,9 +10363,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1456;
+    AOT_Thread_active_exception_offset = 1464;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1464;
+    AOT_Thread_active_stacktrace_offset = 1472;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -10391,7 +10391,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -10404,7 +10404,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1552;
+    1560;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -10423,7 +10423,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1496;
+    AOT_Thread_execution_state_offset = 1504;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -10443,14 +10443,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1472;
+    AOT_Thread_global_object_pool_offset = 1480;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1528;
+    AOT_Thread_exit_through_ffi_offset = 1536;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1560;
+    1568;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
@@ -10495,11 +10495,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1480;
+    1488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1488;
+    AOT_Thread_saved_shadow_call_stack_offset = 1496;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1504;
+    AOT_Thread_safepoint_state_offset = 1512;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -10536,9 +10536,9 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1512;
+    1520;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1520;
+    AOT_Thread_callback_stack_return_offset = 1528;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -10610,8 +10610,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, -1,   -1,   1400, 1408,
-        1416, 1424, 1432, -1,   1440, 1448, -1,   -1};
+        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
+        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -10964,9 +10964,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1520;
+    AOT_Thread_active_exception_offset = 1528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1528;
+    AOT_Thread_active_stacktrace_offset = 1536;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -10992,7 +10992,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1600;
+    1608;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -11005,7 +11005,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1616;
+    1624;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -11024,7 +11024,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1560;
+    AOT_Thread_execution_state_offset = 1568;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -11044,14 +11044,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1536;
+    AOT_Thread_global_object_pool_offset = 1544;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1592;
+    AOT_Thread_exit_through_ffi_offset = 1600;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1624;
+    1632;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
@@ -11096,11 +11096,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1544;
+    1552;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1552;
+    AOT_Thread_saved_shadow_call_stack_offset = 1560;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1568;
+    AOT_Thread_safepoint_state_offset = 1576;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -11137,9 +11137,9 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1576;
+    1584;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1584;
+    AOT_Thread_callback_stack_return_offset = 1592;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -11211,9 +11211,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448,
-        1456, 1464, 1472, 1480, -1,   -1,   -1,   -1,   1488, 1496, -1,
-        -1,   -1,   1504, 1512, -1,   -1,   -1,   -1,   -1,   -1};
+        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
+        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
+        -1,   -1,   1512, 1520, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -11563,9 +11563,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1456;
+    AOT_Thread_active_exception_offset = 1464;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1464;
+    AOT_Thread_active_stacktrace_offset = 1472;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -11591,7 +11591,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -11604,7 +11604,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1552;
+    1560;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -11623,7 +11623,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1496;
+    AOT_Thread_execution_state_offset = 1504;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -11643,14 +11643,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1472;
+    AOT_Thread_global_object_pool_offset = 1480;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1528;
+    AOT_Thread_exit_through_ffi_offset = 1536;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1560;
+    1568;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
@@ -11695,11 +11695,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1480;
+    1488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1488;
+    AOT_Thread_saved_shadow_call_stack_offset = 1496;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1504;
+    AOT_Thread_safepoint_state_offset = 1512;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -11736,9 +11736,9 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1512;
+    1520;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1520;
+    AOT_Thread_callback_stack_return_offset = 1528;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -11810,8 +11810,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, -1,   -1,   1400, 1408,
-        1416, 1424, 1432, -1,   1440, 1448, -1,   -1};
+        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
+        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -12161,9 +12161,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1520;
+    AOT_Thread_active_exception_offset = 1528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1528;
+    AOT_Thread_active_stacktrace_offset = 1536;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -12189,7 +12189,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1600;
+    1608;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -12202,7 +12202,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1616;
+    1624;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -12221,7 +12221,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1560;
+    AOT_Thread_execution_state_offset = 1568;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -12241,14 +12241,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1536;
+    AOT_Thread_global_object_pool_offset = 1544;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1592;
+    AOT_Thread_exit_through_ffi_offset = 1600;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1624;
+    1632;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
@@ -12293,11 +12293,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1544;
+    1552;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1552;
+    AOT_Thread_saved_shadow_call_stack_offset = 1560;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1568;
+    AOT_Thread_safepoint_state_offset = 1576;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -12334,9 +12334,9 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1576;
+    1584;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1584;
+    AOT_Thread_callback_stack_return_offset = 1592;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -12408,9 +12408,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448,
-        1456, 1464, 1472, 1480, -1,   -1,   -1,   -1,   1488, 1496, -1,
-        -1,   -1,   1504, 1512, -1,   -1,   -1,   -1,   -1,   -1};
+        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
+        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
+        -1,   -1,   1512, 1520, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index ebd626c..5af39cf 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -18,10 +18,6 @@
 #define __ assembler->
 
 namespace dart {
-
-DECLARE_FLAG(bool, inline_alloc);
-DECLARE_FLAG(bool, use_slow_path);
-
 namespace compiler {
 
 intptr_t StubCodeCompiler::WordOffsetFromFpToCpuRegister(
@@ -759,6 +755,69 @@
 #undef GENERATE_BREAKPOINT_STUB
 #endif  // !defined(TARGET_ARCH_IA32)
 
+// Called for inline allocation of closure.
+// Output:
+//   AllocateClosureABI::kResultReg: new allocated Closure object.
+// Clobbered:
+//   AllocateClosureABI::kScratchReg
+void StubCodeCompiler::GenerateAllocateClosureStub(Assembler* assembler) {
+  const intptr_t instance_size =
+      target::RoundedAllocationSize(target::Closure::InstanceSize());
+  if (!FLAG_use_slow_path && FLAG_inline_alloc) {
+    Label slow_case;
+    __ Comment("Inline allocation of uninitialized closure");
+#if defined(DEBUG)
+    // Need to account for the debug checks added by StoreToSlotNoBarrier.
+    const auto distance = Assembler::kFarJump;
+#else
+    const auto distance = Assembler::kNearJump;
+#endif
+    __ TryAllocateObject(kClosureCid, instance_size, &slow_case, distance,
+                         AllocateClosureABI::kResultReg,
+                         AllocateClosureABI::kScratchReg);
+
+    __ Comment("Inline initialization of allocated closure");
+    // Put null in the scratch register for initializing boxed fields.
+    // We initialize the fields in offset order below.
+    __ LoadObject(AllocateClosureABI::kScratchReg, NullObject());
+    __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg,
+                            AllocateClosureABI::kResultReg,
+                            Slot::Closure_instantiator_type_arguments());
+    __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg,
+                            AllocateClosureABI::kResultReg,
+                            Slot::Closure_function_type_arguments());
+    __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg,
+                            AllocateClosureABI::kResultReg,
+                            Slot::Closure_delayed_type_arguments());
+    __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg,
+                            AllocateClosureABI::kResultReg,
+                            Slot::Closure_function());
+    __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg,
+                            AllocateClosureABI::kResultReg,
+                            Slot::Closure_context());
+    __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg,
+                            AllocateClosureABI::kResultReg,
+                            Slot::Closure_hash());
+
+    // AllocateClosureABI::kResultReg: new object.
+    __ Ret();
+
+    __ Bind(&slow_case);
+  }
+
+  __ Comment("Closure allocation via runtime");
+  __ EnterStubFrame();
+  __ PushObject(NullObject());  // Space on the stack for the return value.
+  __ CallRuntime(kAllocateClosureRuntimeEntry, 0);
+  __ PopRegister(AllocateClosureABI::kResultReg);
+  ASSERT(target::WillAllocateNewOrRememberedObject(instance_size));
+  EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
+  __ LeaveStubFrame();
+
+  // AllocateClosureABI::kResultReg: new object
+  __ Ret();
+}
+
 // The UnhandledException class lives in the VM isolate, so it cannot cache
 // an allocation stub for itself. Instead, we cache it in the stub code list.
 void StubCodeCompiler::GenerateAllocateUnhandledExceptionStub(
diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h
index 357c005..7c5c243 100644
--- a/runtime/vm/compiler/stub_code_compiler.h
+++ b/runtime/vm/compiler/stub_code_compiler.h
@@ -57,6 +57,8 @@
       const Object& context_allocation_stub);
 #endif
 
+  static void EnsureIsNewOrRemembered(Assembler* assembler,
+                                      bool preserve_registers = true);
   static ArrayPtr BuildStaticCallsTable(
       Zone* zone,
       compiler::UnresolvedPcRelativeCalls* unresolved_calls);
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index af6c94f..e757ee3 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -28,9 +28,6 @@
 #define __ assembler->
 
 namespace dart {
-
-DECLARE_FLAG(bool, precompiled_mode);
-
 namespace compiler {
 
 // Ensures that [R0] is a new object, if not it will be added to the remembered
@@ -38,8 +35,8 @@
 //
 // WARNING: This might clobber all registers except for [R0], [THR] and [FP].
 // The caller should simply call LeaveStubFrame() and return.
-static void EnsureIsNewOrRemembered(Assembler* assembler,
-                                    bool preserve_registers = true) {
+void StubCodeCompiler::EnsureIsNewOrRemembered(Assembler* assembler,
+                                               bool preserve_registers) {
   // If the object is not remembered we call a leaf-runtime to add it to the
   // remembered set.
   Label done;
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 3d5f6c4..78627e8 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -27,9 +27,6 @@
 #define __ assembler->
 
 namespace dart {
-
-DECLARE_FLAG(bool, precompiled_mode);
-
 namespace compiler {
 
 // Ensures that [R0] is a new object, if not it will be added to the remembered
@@ -37,8 +34,8 @@
 //
 // WARNING: This might clobber all registers except for [R0], [THR] and [FP].
 // The caller should simply call LeaveStubFrame() and return.
-static void EnsureIsNewOrRemembered(Assembler* assembler,
-                                    bool preserve_registers = true) {
+void StubCodeCompiler::EnsureIsNewOrRemembered(Assembler* assembler,
+                                               bool preserve_registers) {
   // If the object is not remembered we call a leaf-runtime to add it to the
   // remembered set.
   Label done;
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index f52098f..7e7e6da 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -26,7 +26,6 @@
 #define __ assembler->
 
 namespace dart {
-
 namespace compiler {
 
 // Ensures that [EAX] is a new object, if not it will be added to the remembered
@@ -34,8 +33,8 @@
 //
 // WARNING: This might clobber all registers except for [EAX], [THR] and [FP].
 // The caller should simply call LeaveFrame() and return.
-static void EnsureIsNewOrRemembered(Assembler* assembler,
-                                    bool preserve_registers = true) {
+void StubCodeCompiler::EnsureIsNewOrRemembered(Assembler* assembler,
+                                               bool preserve_registers) {
   // If the object is not remembered we call a leaf-runtime to add it to the
   // remembered set.
   Label done;
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index 321838f..2dc6cd6 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -28,9 +28,6 @@
 #define __ assembler->
 
 namespace dart {
-
-DECLARE_FLAG(bool, precompiled_mode);
-
 namespace compiler {
 
 // Ensures that [RAX] is a new object, if not it will be added to the remembered
@@ -38,8 +35,8 @@
 //
 // WARNING: This might clobber all registers except for [RAX], [THR] and [FP].
 // The caller should simply call LeaveStubFrame() and return.
-static void EnsureIsNewOrRemembered(Assembler* assembler,
-                                    bool preserve_registers = true) {
+void StubCodeCompiler::EnsureIsNewOrRemembered(Assembler* assembler,
+                                               bool preserve_registers) {
   // If the object is not remembered we call a leaf-runtime to add it to the
   // remembered set.
   Label done;
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index fbcf4db..b0a6159 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -451,6 +451,12 @@
   static const Register kIndexReg = R1;
 };
 
+// ABI for AllocateClosureStub.
+struct AllocateClosureABI {
+  static const Register kResultReg = R0;
+  static const Register kScratchReg = R4;
+};
+
 // ABI for AllocateMintShared*Stub.
 struct AllocateMintABI {
   static const Register kResultReg = R0;
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index ae8436e..ec77884 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -292,6 +292,12 @@
   static const Register kIndexReg = R1;
 };
 
+// ABI for AllocateClosureStub.
+struct AllocateClosureABI {
+  static const Register kResultReg = R0;
+  static const Register kScratchReg = R4;
+};
+
 // ABI for AllocateMintShared*Stub.
 struct AllocateMintABI {
   static const Register kResultReg = R0;
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index 73912e2..5272b47 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -202,6 +202,12 @@
   static const Register kTempReg = EBX;
 };
 
+// ABI for AllocateClosureStub.
+struct AllocateClosureABI {
+  static const Register kResultReg = EAX;
+  static const Register kScratchReg = EDX;
+};
+
 // ABI for Allocate<TypedData>ArrayStub.
 struct AllocateTypedDataArrayABI {
   static const Register kLengthReg = EAX;
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 73578fa..67ef651 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -263,6 +263,12 @@
   static const Register kIndexReg = RBX;
 };
 
+// ABI for AllocateClosureStub.
+struct AllocateClosureABI {
+  static const Register kResultReg = RAX;
+  static const Register kScratchReg = R13;
+};
+
 // ABI for AllocateMintShared*Stub.
 struct AllocateMintABI {
   static const Register kResultReg = RAX;
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index c1ffddc..eec9974e 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -212,6 +212,7 @@
   RW(Code, allocate_float32x4_array_stub)                                      \
   RW(Code, allocate_int32x4_array_stub)                                        \
   RW(Code, allocate_float64x2_array_stub)                                      \
+  RW(Code, allocate_closure_stub)                                              \
   RW(Code, allocate_context_stub)                                              \
   RW(Code, allocate_object_stub)                                               \
   RW(Code, allocate_object_parametrized_stub)                                  \
@@ -285,6 +286,7 @@
   DO(allocate_float32x4_array_stub, AllocateFloat32x4Array)                    \
   DO(allocate_int32x4_array_stub, AllocateInt32x4Array)                        \
   DO(allocate_float64x2_array_stub, AllocateFloat64x2Array)                    \
+  DO(allocate_closure_stub, AllocateClosure)                                   \
   DO(allocate_context_stub, AllocateContext)                                   \
   DO(allocate_object_stub, AllocateObject)                                     \
   DO(allocate_object_parametrized_stub, AllocateObjectParameterized)           \
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index 40f1a09..5d6bd68 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -1078,12 +1078,8 @@
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile);
 
-    EXPECT_SUBSTRING("DRT_AllocateObject", walker.VMTagName());
-#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
-    EXPECT_STREQ("[Stub] Allocate _Closure", walker.CurrentName());
-#else
-    EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
-#endif
+    EXPECT_SUBSTRING("DRT_AllocateClosure", walker.VMTagName());
+    EXPECT_STREQ("[Stub] AllocateClosure", walker.CurrentName());
     EXPECT(walker.Down());
     EXPECT_SUBSTRING("foo", walker.CurrentName());
     EXPECT(!walker.Down());
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index cdfc80f..1565559 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -595,6 +595,17 @@
   UNREACHABLE();
 }
 
+// Allocate a new closure and initialize its fields to null.
+// Return value: newly allocated closure.
+DEFINE_RUNTIME_ENTRY(AllocateClosure, 0) {
+  const Closure& closure = Closure::Handle(
+      zone, Closure::New(
+                Object::null_type_arguments(), Object::null_type_arguments(),
+                Object::null_type_arguments(), Object::null_function(),
+                Context::Handle(Context::null()), SpaceForRuntimeAllocation()));
+  arguments.SetReturn(closure);
+}
+
 // Allocate a new context large enough to hold the given number of variables.
 // Arg0: number of variables.
 // Return value: newly allocated context.
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index 66915bf..69b2872 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -15,6 +15,7 @@
   V(AllocateFloat64x2)                                                         \
   V(AllocateInt32x4)                                                           \
   V(AllocateTypedData)                                                         \
+  V(AllocateClosure)                                                           \
   V(AllocateContext)                                                           \
   V(AllocateObject)                                                            \
   V(BreakpointRuntimeHandler)                                                  \
diff --git a/runtime/vm/scope_timer.h b/runtime/vm/scope_timer.h
index 0707980..4e67ed2 100644
--- a/runtime/vm/scope_timer.h
+++ b/runtime/vm/scope_timer.h
@@ -35,7 +35,7 @@
     }
     int64_t elapsed = GetElapsed();
     double seconds = MicrosecondsToSeconds(elapsed);
-    OS::PrintErr("%s: %f seconds (%" Pd64 " \u00B5s)\n", name_, seconds,
+    OS::PrintErr("%s: %.2f seconds (%" Pd64 " \u00B5s)\n", name_, seconds,
                  elapsed);
   }
 
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 7ee9e11..944124f 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -726,7 +726,7 @@
   uint8_t* isolate_snapshot_data_buffer;
 
   // Start an Isolate, load a script and create a full snapshot.
-  Timer timer1(true, "Snapshot_test");
+  Timer timer1;
   timer1.Start();
   {
     TestIsolateScope __test_isolate__;
@@ -760,7 +760,7 @@
 
   // Now Create another isolate using the snapshot and execute a method
   // from the script.
-  Timer timer2(true, "Snapshot_test");
+  Timer timer2;
   timer2.Start();
   TestCase::CreateTestIsolateFromSnapshot(isolate_snapshot_data_buffer);
   {
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index acdb074..3adc5d9 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -187,6 +187,8 @@
       return object_store->allocate_float64x2_stub();
     case kInt32x4Cid:
       return object_store->allocate_int32x4_stub();
+    case kClosureCid:
+      return object_store->allocate_closure_stub();
   }
   Code& stub = Code::Handle(zone, cls.allocation_stub());
   if (stub.IsNull()) {
diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h
index cba3285..e63fdd4 100644
--- a/runtime/vm/stub_code_list.h
+++ b/runtime/vm/stub_code_list.h
@@ -50,6 +50,7 @@
   V(AllocateFloat64x2Array)                                                    \
   V(AllocateMintSharedWithFPURegs)                                             \
   V(AllocateMintSharedWithoutFPURegs)                                          \
+  V(AllocateClosure)                                                           \
   V(AllocateContext)                                                           \
   V(AllocateObject)                                                            \
   V(AllocateObjectParameterized)                                               \
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index dcf8d0b..f0cb6c1 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -32,6 +32,7 @@
 class ApiLocalScope;
 class Array;
 class CompilerState;
+class CompilerTimings;
 class Class;
 class Code;
 class Error;
@@ -506,6 +507,12 @@
     type_usage_info_ = value;
   }
 
+  CompilerTimings* compiler_timings() const { return compiler_timings_; }
+
+  void set_compiler_timings(CompilerTimings* stats) {
+    compiler_timings_ = stats;
+  }
+
   int32_t no_callback_scope_depth() const { return no_callback_scope_depth_; }
 
   void IncrementNoCallbackScopeDepth() {
@@ -1117,6 +1124,8 @@
   TypeUsageInfo* type_usage_info_;
   GrowableObjectArrayPtr pending_functions_;
 
+  CompilerTimings* compiler_timings_ = nullptr;
+
   ErrorPtr sticky_error_;
 
   Random thread_random_;
diff --git a/runtime/vm/timer.h b/runtime/vm/timer.h
index 922c43a..8f478d5 100644
--- a/runtime/vm/timer.h
+++ b/runtime/vm/timer.h
@@ -13,17 +13,24 @@
 
 namespace dart {
 
+struct MeasureMonotonic {
+  static inline int64_t Now() { return OS::GetCurrentMonotonicMicros(); }
+};
+
+struct MeasureCpu {
+  static inline int64_t Now() { return OS::GetCurrentThreadCPUMicros(); }
+};
+
 // Timer class allows timing of specific operations in the VM.
-class Timer : public ValueObject {
+template <typename Measure>
+class TimerImpl : public ValueObject {
  public:
-  Timer(bool report, const char* message) : report_(report), message_(message) {
-    Reset();
-  }
-  ~Timer() {}
+  TimerImpl() { Reset(); }
+  ~TimerImpl() {}
 
   // Start timer.
   void Start() {
-    start_ = OS::GetCurrentMonotonicMicros();
+    start_ = Measure::Now();
     running_ = true;
   }
 
@@ -31,7 +38,7 @@
   void Stop() {
     ASSERT(start_ != 0);
     ASSERT(running());
-    stop_ = OS::GetCurrentMonotonicMicros();
+    stop_ = Measure::Now();
     int64_t elapsed = ElapsedMicros();
     max_contiguous_ = Utils::Maximum(max_contiguous_.load(), elapsed);
     // Make increment atomic in case it occurs in parallel with aggregation.
@@ -43,7 +50,7 @@
   int64_t TotalElapsedTime() const {
     int64_t result = total_;
     if (running_) {
-      int64_t now = OS::GetCurrentMonotonicMicros();
+      int64_t now = Measure::Now();
       result += (now - start_);
     }
     return result;
@@ -52,7 +59,7 @@
   int64_t MaxContiguous() const {
     int64_t result = max_contiguous_;
     if (running_) {
-      int64_t now = OS::GetCurrentMonotonicMicros();
+      int64_t now = Measure::Now();
       result = Utils::Maximum(result, now - start_);
     }
     return result;
@@ -71,14 +78,17 @@
            (max_contiguous_ == 0) && !running_;
   }
 
-  void AddTotal(const Timer& other) { total_.fetch_add(other.total_); }
+  void AddTotal(const TimerImpl& other) { total_.fetch_add(other.total_); }
 
   // Accessors.
-  bool report() const { return report_; }
   bool running() const { return running_; }
-  const char* message() const { return message_; }
 
  private:
+  friend class Timer;
+
+  explicit TimerImpl(int64_t elapsed)
+      : total_(elapsed), max_contiguous_(elapsed) {}
+
   int64_t ElapsedMicros() const {
     ASSERT(start_ != 0);
     ASSERT(stop_ != 0);
@@ -89,13 +99,105 @@
   RelaxedAtomic<int64_t> stop_;
   RelaxedAtomic<int64_t> total_;
   RelaxedAtomic<int64_t> max_contiguous_;
-  bool report_;
-  bool running_;
-  const char* message_;
+
+  bool running_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(TimerImpl);
+};
+
+class Timer : public ValueObject {
+ public:
+  Timer(int64_t elapsed, int64_t elapsed_cpu)
+      : monotonic_(elapsed), cpu_(elapsed) {}
+  Timer() { Reset(); }
+  ~Timer() {}
+
+  // Start timer.
+  void Start() {
+    cpu_.Start();
+    monotonic_.Start();
+  }
+
+  // Stop timer.
+  void Stop() {
+    cpu_.Stop();
+    monotonic_.Stop();
+  }
+
+  // Get total cumulative elapsed time in micros.
+  int64_t TotalElapsedTime() const { return monotonic_.TotalElapsedTime(); }
+  int64_t TotalElapsedTimeCpu() const { return cpu_.TotalElapsedTime(); }
+
+  int64_t MaxContiguous() const { return monotonic_.MaxContiguous(); }
+
+  void Reset() {
+    monotonic_.Reset();
+    cpu_.Reset();
+  }
+
+  bool IsReset() const { return monotonic_.IsReset(); }
+
+  void AddTotal(const Timer& other) {
+    monotonic_.AddTotal(other.monotonic_);
+    cpu_.AddTotal(other.cpu_);
+  }
+
+  const char* FormatElapsedHumanReadable(Zone* zone) const {
+    return FormatElapsedHumanReadable(zone, TotalElapsedTime(),
+                                      TotalElapsedTimeCpu());
+  }
+
+  static const char* FormatTime(Zone* zone, int64_t total) {
+    if (total > kMicrosecondsPerSecond) {
+      return OS::SCreate(zone, "%6.2f s", MicrosecondsToSeconds(total));
+    } else if (total > kMicrosecondsPerMillisecond) {
+      return OS::SCreate(zone, "%6.2f ms", MicrosecondsToMilliseconds(total));
+    } else {
+      return OS::SCreate(zone, "%6" Pd64 " \u00B5s", total);
+    }
+  }
+
+  static constexpr double kCpuTimeReportingThreshold = 0.05;
+
+  // Formats the given monotonic and CPU times as a human readable string.
+  //
+  // CPU time is included into the formated string only if
+  // it is |kCpuTimeReportingThreshold| percent different from the monotonic
+  // time.
+  static const char* FormatElapsedHumanReadable(Zone* zone,
+                                                int64_t total_elapsed,
+                                                int64_t total_elapsed_cpu) {
+    if ((total_elapsed == 0) ||
+        static_cast<double>(Utils::Abs(total_elapsed - total_elapsed_cpu) /
+                            total_elapsed) < kCpuTimeReportingThreshold) {
+      return FormatTime(zone, total_elapsed);
+    } else {
+      return OS::SCreate(zone, "%s (cpu %s)", FormatTime(zone, total_elapsed),
+                         FormatTime(zone, total_elapsed_cpu));
+    }
+  }
+
+ private:
+  TimerImpl<MeasureMonotonic> monotonic_;
+  TimerImpl<MeasureCpu> cpu_;
 
   DISALLOW_COPY_AND_ASSIGN(Timer);
 };
 
+class TimerScope : public StackResource {
+ public:
+  TimerScope(ThreadState* thread, Timer* timer)
+      : StackResource(thread), timer_(timer) {
+    if (timer_ != nullptr) timer_->Start();
+  }
+  ~TimerScope() {
+    if (timer_ != nullptr) timer_->Stop();
+  }
+
+ private:
+  Timer* const timer_;
+};
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_TIMER_H_
diff --git a/tools/VERSION b/tools/VERSION
index 111a69f..ec96746 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 105
+PRERELEASE 106
 PRERELEASE_PATCH 0
\ No newline at end of file