[vm] Fix Instructions::Equals for the JIT.

As discovered by @blaugold on GitHub, Instructions::Equals can give a
false negative on the JIT if the GC flags in the object header are set
differently.

This CL changes Instructions::Equals to only compare the
Instructions-specific portion of the object, namely the size_and_flags_
field and the content bytes. If those match, then the important parts of
the object header match: the cid is always kInstructionsCid, as the
Equals method assumes non-null instances, and the size in the object
header is calculated using the content size from size_and_flags_.

TEST=Manually ran failing tests after cherry picking CL 221360 on top.

Bug: https://github.com/dart-lang/sdk/issues/39843
Change-Id: I25c25bbe6b1bf615d4cd923bfe871da7e929822a
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-dwarf-linux-product-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-linux-product-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/221467
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 181a9e9..6fb03db 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -5487,9 +5487,19 @@
   }
 
   static bool Equals(InstructionsPtr a, InstructionsPtr b) {
-    if (Size(a) != Size(b)) return false;
+    // This method should only be called on non-null Instructions objects.
+    ASSERT_EQUAL(a->GetClassId(), kInstructionsCid);
+    ASSERT_EQUAL(b->GetClassId(), kInstructionsCid);
+    // Don't include the object header tags wholesale in the comparison,
+    // because the GC tags may differ in JIT mode. In fact, we can skip checking
+    // the object header entirely, as we're guaranteed that the cids match,
+    // because there are no subclasses for the Instructions class, and the sizes
+    // should match if the content size encoded in size_and_flags_ matches.
+    if (a->untag()->size_and_flags_ != b->untag()->size_and_flags_) {
+      return false;
+    }
     NoSafepointScope no_safepoint;
-    return memcmp(a->untag(), b->untag(), InstanceSize(Size(a))) == 0;
+    return memcmp(a->untag()->data(), b->untag()->data(), Size(a)) == 0;
   }
 
   uint32_t Hash() const {