x86_64: Implement Unsafe.compareAndSetObject intrinsic.
The implementation is the same as Unsafe.compareAndSwapObject, as the
latter operation has compare-and-set semantics.
Benchmarks improvements (using benchmarks provided by
https://android-review.googlesource.com/1420959):
benchmark before after
-----------------------------------------------------
UnsafeCompareAndSetStaticFieldString 1.333 0.009
UnsafeCompareAndSetFieldString 1.336 0.009
Bug: 71781600
Test: ART_HEAP_POISONING=true m build-art-host-tests \
&& art/test.py --host -r -t 712-varhandle-invocations --64
Change-Id: I19a5dc15304693016c7b93294dafae4a90606cff
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 0747a3a..0febe11 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -596,7 +596,6 @@
Register ref_reg = ref_cpu_reg.AsRegister();
DCHECK(locations->CanCall());
DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(ref_reg)) << ref_reg;
- // This slow path is only used by the UnsafeCASObject intrinsic.
DCHECK((instruction_->IsInvoke() && instruction_->GetLocations()->Intrinsified()))
<< "Unexpected instruction in read barrier marking and field updating slow path: "
<< instruction_->DebugName();
@@ -608,6 +607,7 @@
static constexpr auto kVarHandleGAU = mirror::VarHandle::AccessModeTemplate::kGetAndUpdate;
DCHECK(intrinsic == Intrinsics::kUnsafeCASObject ||
intrinsic == Intrinsics::kJdkUnsafeCASObject ||
+ intrinsic == Intrinsics::kJdkUnsafeCompareAndSetObject ||
mirror::VarHandle::GetAccessModeTemplateByIntrinsic(intrinsic) == kVarHandleCAS ||
mirror::VarHandle::GetAccessModeTemplateByIntrinsic(intrinsic) == kVarHandleCAX ||
mirror::VarHandle::GetAccessModeTemplateByIntrinsic(intrinsic) == kVarHandleGAU);
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 66d0743..75d3e3b 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -2137,7 +2137,8 @@
bool can_call = kEmitCompilerReadBarrier &&
kUseBakerReadBarrier &&
(invoke->GetIntrinsic() == Intrinsics::kUnsafeCASObject ||
- invoke->GetIntrinsic() == Intrinsics::kJdkUnsafeCASObject);
+ invoke->GetIntrinsic() == Intrinsics::kJdkUnsafeCASObject ||
+ invoke->GetIntrinsic() == Intrinsics::kJdkUnsafeCompareAndSetObject);
LocationSummary* locations =
new (allocator) LocationSummary(invoke,
can_call
@@ -2179,21 +2180,18 @@
}
void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafeCASInt(HInvoke* invoke) {
- CreateUnsafeCASLocations(allocator_, DataType::Type::kInt32, invoke);
+ // `jdk.internal.misc.Unsafe.compareAndSwapObject` has compare-and-set semantics (see javadoc).
+ VisitJdkUnsafeCompareAndSetInt(invoke);
}
void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafeCASLong(HInvoke* invoke) {
- CreateUnsafeCASLocations(allocator_, DataType::Type::kInt64, invoke);
+ // `jdk.internal.misc.Unsafe.compareAndSwapLong` has compare-and-set semantics (see javadoc).
+ VisitJdkUnsafeCompareAndSetLong(invoke);
}
void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafeCASObject(HInvoke* invoke) {
- // The only read barrier implementation supporting the
- // UnsafeCASObject intrinsic is the Baker-style read barriers.
- if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier) {
- return;
- }
-
- CreateUnsafeCASLocations(allocator_, DataType::Type::kReference, invoke);
+ // `jdk.internal.misc.Unsafe.compareAndSwapObject` has compare-and-set semantics (see javadoc).
+ VisitJdkUnsafeCompareAndSetObject(invoke);
}
void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafeCompareAndSetInt(HInvoke* invoke) {
@@ -2204,6 +2202,15 @@
CreateUnsafeCASLocations(allocator_, DataType::Type::kInt64, invoke);
}
+void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafeCompareAndSetObject(HInvoke* invoke) {
+ // The only supported read barrier implementation is the Baker-style read barriers.
+ if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier) {
+ return;
+ }
+
+ CreateUnsafeCASLocations(allocator_, DataType::Type::kReference, invoke);
+}
+
// Convert ZF into the Boolean result.
static inline void GenZFlagToResult(X86_64Assembler* assembler, CpuRegister out) {
__ setcc(kZero, out);
@@ -2499,19 +2506,18 @@
}
void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafeCASInt(HInvoke* invoke) {
- GenCAS(DataType::Type::kInt32, invoke, codegen_);
+ // `jdk.internal.misc.Unsafe.compareAndSwapObject` has compare-and-set semantics (see javadoc).
+ VisitJdkUnsafeCompareAndSetInt(invoke);
}
void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafeCASLong(HInvoke* invoke) {
- GenCAS(DataType::Type::kInt64, invoke, codegen_);
+ // `jdk.internal.misc.Unsafe.compareAndSwapLong` has compare-and-set semantics (see javadoc).
+ VisitJdkUnsafeCompareAndSetLong(invoke);
}
void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafeCASObject(HInvoke* invoke) {
- // The only read barrier implementation supporting the
- // UnsafeCASObject intrinsic is the Baker-style read barriers.
- DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier);
-
- GenCAS(DataType::Type::kReference, invoke, codegen_);
+ // `jdk.internal.misc.Unsafe.compareAndSwapObject` has compare-and-set semantics (see javadoc).
+ VisitJdkUnsafeCompareAndSetObject(invoke);
}
void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafeCompareAndSetInt(HInvoke* invoke) {
@@ -2522,6 +2528,13 @@
GenCAS(DataType::Type::kInt64, invoke, codegen_);
}
+void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafeCompareAndSetObject(HInvoke* invoke) {
+ // The only supported read barrier implementation is the Baker-style read barriers.
+ DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier);
+
+ GenCAS(DataType::Type::kReference, invoke, codegen_);
+}
+
void IntrinsicLocationsBuilderX86_64::VisitIntegerReverse(HInvoke* invoke) {
LocationSummary* locations =
new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
@@ -4891,7 +4904,6 @@
UNIMPLEMENTED_INTRINSIC(X86_64, JdkUnsafeGetAndSetInt)
UNIMPLEMENTED_INTRINSIC(X86_64, JdkUnsafeGetAndSetLong)
UNIMPLEMENTED_INTRINSIC(X86_64, JdkUnsafeGetAndSetObject)
-UNIMPLEMENTED_INTRINSIC(X86_64, JdkUnsafeCompareAndSetObject)
UNREACHABLE_INTRINSICS(X86_64)