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;
}