[VM/AOT] Execute catch-entry moves in parallel (our AOT doesn't generate non-cyclic moves)

Change-Id: Idfea23f9003bc3bf4b902da315835b9ac9239f36
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/96580
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index d310c00..058d9c7 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -239,12 +239,15 @@
   }
 
   void ExecuteCatchEntryMoves(const CatchEntryMoves& moves) {
+    Zone* zone = Thread::Current()->zone();
+    auto& value = Object::Handle(zone);
+    auto& dst_values = Array::Handle(zone, Array::New(moves.count()));
+
     uword fp = handler_fp;
     ObjectPool* pool = nullptr;
     for (int j = 0; j < moves.count(); j++) {
       const CatchEntryMove& move = moves.At(j);
 
-      RawObject* value;
       switch (move.source_kind()) {
         case CatchEntryMove::SourceKind::kConstant:
           if (pool == nullptr) {
@@ -295,7 +298,17 @@
           UNREACHABLE();
       }
 
-      *TaggedSlotAt(fp, move.dest_slot()) = value;
+      dst_values.SetAt(j, value);
+    }
+
+    {
+      NoSafepointScope no_safepoint_scope;
+
+      for (int j = 0; j < moves.count(); j++) {
+        const CatchEntryMove& move = moves.At(j);
+        value = dst_values.At(j);
+        *TaggedSlotAt(fp, move.dest_slot()) = value.raw();
+      }
     }
   }