X86: Clean up interface type check for heap poisoning.

Test: ART_HEAP_POISONING=true m test-art-host-gtest
Test: ART_HEAP_POISONING=true testrunner.py --host --optimizing
Bug: 32577579
Change-Id: Icb2a838fc3a2ddcc2a50b72236afe2cd65f02e01
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index e25688c..106531c 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -337,6 +337,13 @@
     CodeGeneratorX86_64* x86_64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
     __ Bind(GetEntryLabel());
 
+    if (kPoisonHeapReferences &&
+        instruction_->IsCheckCast() &&
+        instruction_->AsCheckCast()->GetTypeCheckKind() == TypeCheckKind::kInterfaceCheck) {
+      // First, unpoison the `cls` reference that was poisoned for direct memory comparison.
+      __ UnpoisonHeapReference(locations->InAt(1).AsRegister<CpuRegister>());
+    }
+
     if (!is_fatal_) {
       SaveLiveRegisters(codegen, locations);
     }
@@ -5729,7 +5736,7 @@
 }
 
 static bool CheckCastTypeCheckNeedsATemporary(TypeCheckKind type_check_kind) {
-  if (type_check_kind == TypeCheckKind::kInterfaceCheck && !kPoisonHeapReferences) {
+  if (type_check_kind == TypeCheckKind::kInterfaceCheck) {
     // We need a temporary for holding the iftable length.
     return true;
   }
@@ -6019,7 +6026,7 @@
     case TypeCheckKind::kArrayObjectCheck:
       return !throws_into_catch && !kEmitCompilerReadBarrier;
     case TypeCheckKind::kInterfaceCheck:
-      return !throws_into_catch && !kEmitCompilerReadBarrier && !kPoisonHeapReferences;
+      return !throws_into_catch && !kEmitCompilerReadBarrier;
     case TypeCheckKind::kArrayCheck:
     case TypeCheckKind::kUnresolvedCheck:
       return false;
@@ -6233,42 +6240,40 @@
     }
 
     case TypeCheckKind::kInterfaceCheck:
-      // Fast path for the interface check. We always go slow path for heap poisoning since
-      // unpoisoning cls would require an extra temp.
-      if (!kPoisonHeapReferences) {
-        // Try to avoid read barriers to improve the fast path. We can not get false positives by
-        // doing this.
-        // /* HeapReference<Class> */ temp = obj->klass_
-        GenerateReferenceLoadTwoRegisters(instruction,
-                                          temp_loc,
-                                          obj_loc,
-                                          class_offset,
-                                          kWithoutReadBarrier);
+      // Fast path for the interface check. Try to avoid read barriers to improve the fast path.
+      // We can not get false positives by doing this.
+      // /* HeapReference<Class> */ temp = obj->klass_
+      GenerateReferenceLoadTwoRegisters(instruction,
+                                        temp_loc,
+                                        obj_loc,
+                                        class_offset,
+                                        kWithoutReadBarrier);
 
-        // /* HeapReference<Class> */ temp = temp->iftable_
-        GenerateReferenceLoadTwoRegisters(instruction,
-                                          temp_loc,
-                                          temp_loc,
-                                          iftable_offset,
-                                          kWithoutReadBarrier);
-        // Iftable is never null.
-        __ movl(maybe_temp2_loc.AsRegister<CpuRegister>(), Address(temp, array_length_offset));
-        // Loop through the iftable and check if any class matches.
-        NearLabel start_loop;
-        __ Bind(&start_loop);
-        // Need to subtract first to handle the empty array case.
-        __ subl(maybe_temp2_loc.AsRegister<CpuRegister>(), Immediate(2));
-        __ j(kNegative, type_check_slow_path->GetEntryLabel());
-        // Go to next interface if the classes do not match.
-        __ cmpl(cls.AsRegister<CpuRegister>(),
-                CodeGeneratorX86_64::ArrayAddress(temp,
-                                                  maybe_temp2_loc,
-                                                  TIMES_4,
-                                                  object_array_data_offset));
-        __ j(kNotEqual, &start_loop);  // Return if same class.
-      } else {
-        __ jmp(type_check_slow_path->GetEntryLabel());
-      }
+      // /* HeapReference<Class> */ temp = temp->iftable_
+      GenerateReferenceLoadTwoRegisters(instruction,
+                                        temp_loc,
+                                        temp_loc,
+                                        iftable_offset,
+                                        kWithoutReadBarrier);
+      // Iftable is never null.
+      __ movl(maybe_temp2_loc.AsRegister<CpuRegister>(), Address(temp, array_length_offset));
+      // Maybe poison the `cls` for direct comparison with memory.
+      __ MaybePoisonHeapReference(cls.AsRegister<CpuRegister>());
+      // Loop through the iftable and check if any class matches.
+      NearLabel start_loop;
+      __ Bind(&start_loop);
+      // Need to subtract first to handle the empty array case.
+      __ subl(maybe_temp2_loc.AsRegister<CpuRegister>(), Immediate(2));
+      __ j(kNegative, type_check_slow_path->GetEntryLabel());
+      // Go to next interface if the classes do not match.
+      __ cmpl(cls.AsRegister<CpuRegister>(),
+              CodeGeneratorX86_64::ArrayAddress(temp,
+                                                maybe_temp2_loc,
+                                                TIMES_4,
+                                                object_array_data_offset));
+      __ j(kNotEqual, &start_loop);  // Return if same class.
+      // If `cls` was poisoned above, unpoison it.
+      __ MaybeUnpoisonHeapReference(cls.AsRegister<CpuRegister>());
       break;
   }