Give Field::is_nullable the same consistency check as guarded_cid

Fixes: https://github.com/dart-lang/sdk/issues/36717
Bug: https://github.com/dart-lang/sdk/issues/36717
Change-Id: Ic58b9a004a0bbab91d330c24212ff2d8634c084f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/100273
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Liam Appelbe <liama@google.com>
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index e477dfc..b0f294f 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -168,7 +168,7 @@
     if (H.thread()->IsMutatorThread()) {
       field.RecordStore(Object::null_object());
     } else {
-      ASSERT(field.is_nullable());
+      ASSERT(field.is_nullable(/* silence_assert = */ true));
     }
     return Fragment();
   }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index b2f00e5..540a7ac 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -3452,7 +3452,18 @@
   // Internally we is_nullable_ field contains either kNullCid (nullable) or
   // kInvalidCid (non-nullable) instead of boolean. This is done to simplify
   // guarding sequence in the generated code.
-  bool is_nullable() const { return raw_ptr()->is_nullable_ == kNullCid; }
+  bool is_nullable(bool silence_assert = false) const {
+#if defined(DEBUG)
+    if (!silence_assert) {
+      // Same assert as guarded_cid(), because is_nullable() also needs to be
+      // consistent for the background compiler.
+      Thread* thread = Thread::Current();
+      ASSERT(!IsOriginal() || is_static() || thread->IsMutatorThread() ||
+             thread->IsAtSafepoint());
+    }
+#endif
+    return raw_ptr()->is_nullable_ == kNullCid;
+  }
   void set_is_nullable(bool val) const {
     ASSERT(Thread::Current()->IsMutatorThread());
     StoreNonPointer(&raw_ptr()->is_nullable_, val ? kNullCid : kIllegalCid);