[vm, compiler] Fix incorrect derivation of a concrete cid from FutureOr.

Bug: https://github.com/dart-lang/sdk/issues/34128
Change-Id: I694b3b7556ee999de3c67c1cd4a8a98654365c24
Reviewed-on: https://dart-review.googlesource.com/69480
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Aart Bik <ajcbik@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index 5d079b7..3e7de20 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -1548,6 +1548,12 @@
     // And the result with the negated space bit of the object.
     bic(IP, IP, Operand(object));
   } else {
+#if defined(DEBUG)
+    Label okay;
+    BranchIfNotSmi(value, &okay);
+    Stop("Unexpected Smi!");
+    Bind(&okay);
+#endif
     bic(IP, value, Operand(object));
   }
   tst(IP, Operand(kNewObjectAlignmentOffset));
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 2199fd6..3a4b8de 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -915,6 +915,12 @@
   // Write-barrier triggers if the value is in the new space (has bit set) and
   // the object is in the old space (has bit cleared).
   if (value_can_be_smi == kValueIsNotSmi) {
+#if defined(DEBUG)
+    Label okay;
+    BranchIfNotSmi(value, &okay);
+    Stop("Unexpected Smi!");
+    Bind(&okay);
+#endif
     // To check that, we compute value & ~object and skip the write barrier
     // if the bit is not set. We can't destroy the object.
     bic(TMP, value, Operand(object));
@@ -954,7 +960,7 @@
   ASSERT(object != value);
   str(value, dest);
   Label done;
-  StoreIntoObjectFilter(object, value, &done, kValueCanBeSmi, kJumpToNoUpdate);
+  StoreIntoObjectFilter(object, value, &done, can_be_smi, kJumpToNoUpdate);
   if (!lr_reserved) Push(LR);
   ldr(LR, Address(THR, Thread::update_store_buffer_wrappers_offset(object)));
   blr(LR);
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index b566572..88d0063 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -1840,6 +1840,12 @@
                                       CanBeSmi can_be_smi,
                                       BarrierFilterMode how_to_jump) {
   if (can_be_smi == kValueIsNotSmi) {
+#if defined(DEBUG)
+    Label okay;
+    BranchIfNotSmi(value, &okay);
+    Stop("Unexpected Smi!");
+    Bind(&okay);
+#endif
     COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) &&
                    (kOldObjectAlignmentOffset == 0));
     // Write-barrier triggers if the value is in the new space (has bit set) and
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 353b8ed..5b61175 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1224,6 +1224,12 @@
                  (kOldObjectAlignmentOffset == 0));
 
   if (can_be_smi == kValueIsNotSmi) {
+#if defined(DEBUG)
+    Label okay;
+    BranchIfNotSmi(value, &okay);
+    Stop("Unexpected Smi!");
+    Bind(&okay);
+#endif
     // Write-barrier triggers if the value is in the new space (has bit set) and
     // the object is in the old space (has bit cleared).
     // To check that we could compute value & ~object and skip the write barrier
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 7b6458c..d0d8793 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -662,6 +662,10 @@
       cid_ = kClosureCid;
     } else if (type_->HasResolvedTypeClass()) {
       const Class& type_class = Class::Handle(type_->type_class());
+      if (type_class.IsFutureOrClass()) {
+        // FutureOr<T> may be Future<T> or T.
+        return cid_ = kDynamicCid;
+      }
       Thread* thread = Thread::Current();
       CHA* cha = thread->cha();
       // Don't infer a cid from an abstract type since there can be multiple