OpenJDK 11: Adding Unsafe new intrinsics for AtomicIntegerFieldUpdater
Adding native implementation for:
jdk.internal.misc.Unsafe.compareAndSetInt
Adding intrinsics for:
jdk.internal.misc.Unsafe.compareAndSetInt
jdk.internal.misc.Unsafe.getIntAcquire
jdk.internal.misc.Unsafe.putIntRelease
Test: m
Test: art/test/testrunner/testrunner.py -t 2235-JdkUnsafeTest
Bug: 188889082
Bug: 190791083
Change-Id: Iba4a66d29ad27e269a7be0d5d5c8397755040784
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 131c069..3c4260f 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -789,6 +789,9 @@
void IntrinsicLocationsBuilderARM64::VisitJdkUnsafeGetVolatile(HInvoke* invoke) {
CreateIntIntIntToIntLocations(allocator_, invoke);
}
+void IntrinsicLocationsBuilderARM64::VisitJdkUnsafeGetAcquire(HInvoke* invoke) {
+ CreateIntIntIntToIntLocations(allocator_, invoke);
+}
void IntrinsicLocationsBuilderARM64::VisitJdkUnsafeGetLong(HInvoke* invoke) {
CreateIntIntIntToIntLocations(allocator_, invoke);
}
@@ -827,6 +830,9 @@
void IntrinsicCodeGeneratorARM64::VisitJdkUnsafeGetVolatile(HInvoke* invoke) {
GenUnsafeGet(invoke, DataType::Type::kInt32, /*is_volatile=*/ true, codegen_);
}
+void IntrinsicCodeGeneratorARM64::VisitJdkUnsafeGetAcquire(HInvoke* invoke) {
+ GenUnsafeGet(invoke, DataType::Type::kInt32, /*is_volatile=*/ true, codegen_);
+}
void IntrinsicCodeGeneratorARM64::VisitJdkUnsafeGetLong(HInvoke* invoke) {
GenUnsafeGet(invoke, DataType::Type::kInt64, /*is_volatile=*/ false, codegen_);
}
@@ -886,6 +892,9 @@
void IntrinsicLocationsBuilderARM64::VisitJdkUnsafePutVolatile(HInvoke* invoke) {
CreateIntIntIntIntToVoid(allocator_, invoke);
}
+void IntrinsicLocationsBuilderARM64::VisitJdkUnsafePutRelease(HInvoke* invoke) {
+ CreateIntIntIntIntToVoid(allocator_, invoke);
+}
void IntrinsicLocationsBuilderARM64::VisitJdkUnsafePutObject(HInvoke* invoke) {
CreateIntIntIntIntToVoid(allocator_, invoke);
}
@@ -994,6 +1003,13 @@
/*is_ordered=*/ false,
codegen_);
}
+void IntrinsicCodeGeneratorARM64::VisitJdkUnsafePutRelease(HInvoke* invoke) {
+ GenUnsafePut(invoke,
+ DataType::Type::kInt32,
+ /*is_volatile=*/ true,
+ /*is_ordered=*/ false,
+ codegen_);
+}
void IntrinsicCodeGeneratorARM64::VisitJdkUnsafePutObject(HInvoke* invoke) {
GenUnsafePut(invoke,
DataType::Type::kReference,
@@ -1478,6 +1494,9 @@
}
}
}
+void IntrinsicLocationsBuilderARM64::VisitJdkUnsafeCompareAndSetInt(HInvoke* invoke) {
+ CreateUnsafeCASLocations(allocator_, invoke);
+}
void IntrinsicCodeGeneratorARM64::VisitUnsafeCASInt(HInvoke* invoke) {
VisitJdkUnsafeCASInt(invoke);
@@ -1498,6 +1517,9 @@
void IntrinsicCodeGeneratorARM64::VisitJdkUnsafeCASObject(HInvoke* invoke) {
GenUnsafeCas(invoke, DataType::Type::kReference, codegen_);
}
+void IntrinsicCodeGeneratorARM64::VisitJdkUnsafeCompareAndSetInt(HInvoke* invoke) {
+ GenUnsafeCas(invoke, DataType::Type::kInt32, codegen_);
+}
enum class GetAndUpdateOp {
kSet,
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index aaa03bd..d007c99 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -2910,6 +2910,15 @@
invoke, codegen_, DataType::Type::kInt32, std::memory_order_seq_cst, /*atomic=*/ true);
}
+void IntrinsicLocationsBuilderARMVIXL::VisitJdkUnsafeGetAcquire(HInvoke* invoke) {
+ CreateUnsafeGetLocations(invoke, codegen_, DataType::Type::kInt32, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitJdkUnsafeGetAcquire(HInvoke* invoke) {
+ GenUnsafeGet(
+ invoke, codegen_, DataType::Type::kInt32, std::memory_order_acquire, /*atomic=*/ true);
+}
+
void IntrinsicLocationsBuilderARMVIXL::VisitJdkUnsafeGetLong(HInvoke* invoke) {
CreateUnsafeGetLocations(invoke, codegen_, DataType::Type::kInt64, /*atomic=*/ false);
}
@@ -3201,6 +3210,19 @@
/*atomic=*/ true,
codegen_);
}
+
+void IntrinsicLocationsBuilderARMVIXL::VisitJdkUnsafePutRelease(HInvoke* invoke) {
+ CreateUnsafePutLocations(invoke, codegen_, DataType::Type::kInt32, /*atomic=*/ true);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitJdkUnsafePutRelease(HInvoke* invoke) {
+ GenUnsafePut(invoke,
+ DataType::Type::kInt32,
+ std::memory_order_release,
+ /*atomic=*/ true,
+ codegen_);
+}
+
void IntrinsicLocationsBuilderARMVIXL::VisitJdkUnsafePutObject(HInvoke* invoke) {
CreateUnsafePutLocations(invoke, codegen_, DataType::Type::kReference, /*atomic=*/ false);
}
@@ -3697,12 +3719,18 @@
CreateUnsafeCASLocations(allocator_, invoke);
}
+void IntrinsicLocationsBuilderARMVIXL::VisitJdkUnsafeCompareAndSetInt(HInvoke* invoke) {
+ CreateUnsafeCASLocations(allocator_, invoke);
+}
void IntrinsicCodeGeneratorARMVIXL::VisitJdkUnsafeCASInt(HInvoke* invoke) {
GenUnsafeCas(invoke, DataType::Type::kInt32, codegen_);
}
void IntrinsicCodeGeneratorARMVIXL::VisitJdkUnsafeCASObject(HInvoke* invoke) {
GenUnsafeCas(invoke, DataType::Type::kReference, codegen_);
}
+void IntrinsicCodeGeneratorARMVIXL::VisitJdkUnsafeCompareAndSetInt(HInvoke* invoke) {
+ GenUnsafeCas(invoke, DataType::Type::kInt32, codegen_);
+}
enum class GetAndUpdateOp {
kSet,
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 453e402..16457f5 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -1774,6 +1774,9 @@
void IntrinsicLocationsBuilderX86::VisitJdkUnsafeGetVolatile(HInvoke* invoke) {
CreateIntIntIntToIntLocations(allocator_, invoke, DataType::Type::kInt32, /*is_volatile=*/ true);
}
+void IntrinsicLocationsBuilderX86::VisitJdkUnsafeGetAcquire(HInvoke* invoke) {
+ CreateIntIntIntToIntLocations(allocator_, invoke, DataType::Type::kInt32, /*is_volatile=*/ true);
+}
void IntrinsicLocationsBuilderX86::VisitJdkUnsafeGetLong(HInvoke* invoke) {
CreateIntIntIntToIntLocations(
allocator_, invoke, DataType::Type::kInt64, /*is_volatile=*/ false);
@@ -1796,6 +1799,9 @@
void IntrinsicCodeGeneratorX86::VisitJdkUnsafeGetVolatile(HInvoke* invoke) {
GenUnsafeGet(invoke, DataType::Type::kInt32, /*is_volatile=*/ true, codegen_);
}
+void IntrinsicCodeGeneratorX86::VisitJdkUnsafeGetAcquire(HInvoke* invoke) {
+ GenUnsafeGet(invoke, DataType::Type::kInt32, /*is_volatile=*/ true, codegen_);
+}
void IntrinsicCodeGeneratorX86::VisitJdkUnsafeGetLong(HInvoke* invoke) {
GenUnsafeGet(invoke, DataType::Type::kInt64, /*is_volatile=*/ false, codegen_);
}
@@ -1870,6 +1876,10 @@
CreateIntIntIntIntToVoidPlusTempsLocations(
allocator_, DataType::Type::kInt32, invoke, /*is_volatile=*/ true);
}
+void IntrinsicLocationsBuilderX86::VisitJdkUnsafePutRelease(HInvoke* invoke) {
+ CreateIntIntIntIntToVoidPlusTempsLocations(
+ allocator_, DataType::Type::kInt32, invoke, /*is_volatile=*/ true);
+}
void IntrinsicLocationsBuilderX86::VisitJdkUnsafePutObject(HInvoke* invoke) {
CreateIntIntIntIntToVoidPlusTempsLocations(
allocator_, DataType::Type::kReference, invoke, /*is_volatile=*/ false);
@@ -1980,6 +1990,9 @@
void IntrinsicCodeGeneratorX86::VisitJdkUnsafePutVolatile(HInvoke* invoke) {
GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt32, /*is_volatile=*/ true, codegen_);
}
+void IntrinsicCodeGeneratorX86::VisitJdkUnsafePutRelease(HInvoke* invoke) {
+ GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt32, /*is_volatile=*/ true, codegen_);
+}
void IntrinsicCodeGeneratorX86::VisitJdkUnsafePutObject(HInvoke* invoke) {
GenUnsafePut(
invoke->GetLocations(), DataType::Type::kReference, /*is_volatile=*/ false, codegen_);
@@ -2071,6 +2084,10 @@
CreateIntIntIntIntIntToInt(allocator_, DataType::Type::kReference, invoke);
}
+void IntrinsicLocationsBuilderX86::VisitJdkUnsafeCompareAndSetInt(HInvoke* invoke) {
+ CreateIntIntIntIntIntToInt(allocator_, DataType::Type::kInt32, invoke);
+}
+
static void GenPrimitiveLockedCmpxchg(DataType::Type type,
CodeGeneratorX86* codegen,
Location expected_value,
@@ -2323,6 +2340,10 @@
GenCAS(DataType::Type::kReference, invoke, codegen_);
}
+void IntrinsicCodeGeneratorX86::VisitJdkUnsafeCompareAndSetInt(HInvoke* invoke) {
+ GenCAS(DataType::Type::kInt32, invoke, codegen_);
+}
+
void IntrinsicLocationsBuilderX86::VisitIntegerReverse(HInvoke* invoke) {
LocationSummary* locations =
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 58dd117..1b4b298 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -1878,6 +1878,9 @@
void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafeGetVolatile(HInvoke* invoke) {
CreateIntIntIntToIntLocations(allocator_, invoke);
}
+void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafeGetAcquire(HInvoke* invoke) {
+ CreateIntIntIntToIntLocations(allocator_, invoke);
+}
void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafeGetLong(HInvoke* invoke) {
CreateIntIntIntToIntLocations(allocator_, invoke);
}
@@ -1917,6 +1920,9 @@
void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafeGetVolatile(HInvoke* invoke) {
GenUnsafeGet(invoke, DataType::Type::kInt32, /*is_volatile=*/ true, codegen_);
}
+void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafeGetAcquire(HInvoke* invoke) {
+ GenUnsafeGet(invoke, DataType::Type::kInt32, /*is_volatile=*/ true, codegen_);
+}
void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafeGetLong(HInvoke* invoke) {
GenUnsafeGet(invoke, DataType::Type::kInt64, /*is_volatile=*/ false, codegen_);
}
@@ -1984,6 +1990,9 @@
void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafePutVolatile(HInvoke* invoke) {
CreateIntIntIntIntToVoidPlusTempsLocations(allocator_, DataType::Type::kInt32, invoke);
}
+void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafePutRelease(HInvoke* invoke) {
+ CreateIntIntIntIntToVoidPlusTempsLocations(allocator_, DataType::Type::kInt32, invoke);
+}
void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafePutObject(HInvoke* invoke) {
CreateIntIntIntIntToVoidPlusTempsLocations(allocator_, DataType::Type::kReference, invoke);
}
@@ -2074,6 +2083,9 @@
void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafePutVolatile(HInvoke* invoke) {
GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt32, /*is_volatile=*/ true, codegen_);
}
+void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafePutRelease(HInvoke* invoke) {
+ GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt32, /* is_volatile= */ true, codegen_);
+}
void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafePutObject(HInvoke* invoke) {
GenUnsafePut(
invoke->GetLocations(), DataType::Type::kReference, /*is_volatile=*/ false, codegen_);
@@ -2161,6 +2173,10 @@
CreateUnsafeCASLocations(allocator_, DataType::Type::kReference, invoke);
}
+void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafeCompareAndSetInt(HInvoke* invoke) {
+ CreateUnsafeCASLocations(allocator_, DataType::Type::kInt32, invoke);
+}
+
// Convert ZF into the Boolean result.
static inline void GenZFlagToResult(X86_64Assembler* assembler, CpuRegister out) {
__ setcc(kZero, out);
@@ -2437,6 +2453,10 @@
GenCAS(DataType::Type::kReference, invoke, codegen_);
}
+void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafeCompareAndSetInt(HInvoke* invoke) {
+ GenCAS(DataType::Type::kInt32, invoke, codegen_);
+}
+
void IntrinsicLocationsBuilderX86_64::VisitIntegerReverse(HInvoke* invoke) {
LocationSummary* locations =
new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h
index 09bdbf6..cec2f4f 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -322,6 +322,7 @@
case Intrinsics::kJdkUnsafeCASInt:
case Intrinsics::kJdkUnsafeCASLong:
case Intrinsics::kJdkUnsafeCASObject:
+ case Intrinsics::kJdkUnsafeCompareAndSetInt:
case Intrinsics::kJdkUnsafeGetAndAddInt:
case Intrinsics::kJdkUnsafeGetAndAddLong:
case Intrinsics::kJdkUnsafeGetAndSetInt:
@@ -330,12 +331,14 @@
case Intrinsics::kJdkUnsafeGetLongVolatile:
case Intrinsics::kJdkUnsafeGetObjectVolatile:
case Intrinsics::kJdkUnsafeGetVolatile:
+ case Intrinsics::kJdkUnsafeGetAcquire:
case Intrinsics::kJdkUnsafePutLongOrdered:
case Intrinsics::kJdkUnsafePutLongVolatile:
case Intrinsics::kJdkUnsafePutObjectOrdered:
case Intrinsics::kJdkUnsafePutObjectVolatile:
case Intrinsics::kJdkUnsafePutOrdered:
case Intrinsics::kJdkUnsafePutVolatile:
+ case Intrinsics::kJdkUnsafePutRelease:
case Intrinsics::kJdkUnsafeLoadFence:
case Intrinsics::kJdkUnsafeStoreFence:
case Intrinsics::kJdkUnsafeFullFence:
diff --git a/runtime/image.cc b/runtime/image.cc
index 358e4ee..99312c8 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -29,8 +29,8 @@
namespace art {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-// Last change: kJdkUnsafe intrinsics
-const uint8_t ImageHeader::kImageVersion[] = { '1', '0', '2', '\0' };
+// Last change: kJdkUnsafe intrinsics for getAcquire/putRelease and compareAndSetInt
+const uint8_t ImageHeader::kImageVersion[] = { '1', '0', '3', '\0' };
ImageHeader::ImageHeader(uint32_t image_reservation_size,
uint32_t component_count,
diff --git a/runtime/interpreter/interpreter_intrinsics.cc b/runtime/interpreter/interpreter_intrinsics.cc
index 706e252..f0b85c2 100644
--- a/runtime/interpreter/interpreter_intrinsics.cc
+++ b/runtime/interpreter/interpreter_intrinsics.cc
@@ -573,8 +573,10 @@
UNIMPLEMENTED_CASE(JdkUnsafeCASInt /* (Ljava/lang/Object;JII)Z */)
UNIMPLEMENTED_CASE(JdkUnsafeCASLong /* (Ljava/lang/Object;JJJ)Z */)
UNIMPLEMENTED_CASE(JdkUnsafeCASObject /* (Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z */)
+ UNIMPLEMENTED_CASE(JdkUnsafeCompareAndSetInt /* (Ljava/lang/Object;JII)Z */)
UNIMPLEMENTED_CASE(JdkUnsafeGet /* (Ljava/lang/Object;J)I */)
UNIMPLEMENTED_CASE(JdkUnsafeGetVolatile /* (Ljava/lang/Object;J)I */)
+ UNIMPLEMENTED_CASE(JdkUnsafeGetAcquire /* (Ljava/lang/Object;J)I */)
UNIMPLEMENTED_CASE(JdkUnsafeGetObject /* (Ljava/lang/Object;J)Ljava/lang/Object; */)
UNIMPLEMENTED_CASE(JdkUnsafeGetObjectVolatile /* (Ljava/lang/Object;J)Ljava/lang/Object; */)
UNIMPLEMENTED_CASE(JdkUnsafeGetLong /* (Ljava/lang/Object;J)J */)
@@ -582,6 +584,7 @@
UNIMPLEMENTED_CASE(JdkUnsafePut /* (Ljava/lang/Object;JI)V */)
UNIMPLEMENTED_CASE(JdkUnsafePutOrdered /* (Ljava/lang/Object;JI)V */)
UNIMPLEMENTED_CASE(JdkUnsafePutVolatile /* (Ljava/lang/Object;JI)V */)
+ UNIMPLEMENTED_CASE(JdkUnsafePutRelease /* (Ljava/lang/Object;JI)V */)
UNIMPLEMENTED_CASE(JdkUnsafePutObject /* (Ljava/lang/Object;JLjava/lang/Object;)V */)
UNIMPLEMENTED_CASE(JdkUnsafePutObjectOrdered /* (Ljava/lang/Object;JLjava/lang/Object;)V */)
UNIMPLEMENTED_CASE(JdkUnsafePutObjectVolatile /* (Ljava/lang/Object;JLjava/lang/Object;)V */)
diff --git a/runtime/intrinsics_list.h b/runtime/intrinsics_list.h
index b463197..6cd6331 100644
--- a/runtime/intrinsics_list.h
+++ b/runtime/intrinsics_list.h
@@ -237,14 +237,17 @@
V(JdkUnsafeCASInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "compareAndSwapInt", "(Ljava/lang/Object;JII)Z") \
V(JdkUnsafeCASLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z") \
V(JdkUnsafeCASObject, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "compareAndSwapObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
+ V(JdkUnsafeCompareAndSetInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "compareAndSetInt", "(Ljava/lang/Object;JII)Z") \
V(JdkUnsafeGet, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getInt", "(Ljava/lang/Object;J)I") \
V(JdkUnsafeGetVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getIntVolatile", "(Ljava/lang/Object;J)I") \
+ V(JdkUnsafeGetAcquire, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getIntAcquire", "(Ljava/lang/Object;J)I") \
V(JdkUnsafeGetObject, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;") \
V(JdkUnsafeGetObjectVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;") \
V(JdkUnsafeGetLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getLong", "(Ljava/lang/Object;J)J") \
V(JdkUnsafeGetLongVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getLongVolatile", "(Ljava/lang/Object;J)J") \
V(JdkUnsafePut, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "putInt", "(Ljava/lang/Object;JI)V") \
V(JdkUnsafePutOrdered, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "putOrderedInt", "(Ljava/lang/Object;JI)V") \
+ V(JdkUnsafePutRelease, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "putIntRelease", "(Ljava/lang/Object;JI)V") \
V(JdkUnsafePutVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "putIntVolatile", "(Ljava/lang/Object;JI)V") \
V(JdkUnsafePutObject, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
V(JdkUnsafePutObjectOrdered, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "putOrderedObject", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
diff --git a/runtime/native/jdk_internal_misc_Unsafe.cc b/runtime/native/jdk_internal_misc_Unsafe.cc
index 407867c..d8e40a9 100644
--- a/runtime/native/jdk_internal_misc_Unsafe.cc
+++ b/runtime/native/jdk_internal_misc_Unsafe.cc
@@ -51,6 +51,19 @@
return success ? JNI_TRUE : JNI_FALSE;
}
+static jboolean Unsafe_compareAndSetInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
+ jint expectedValue, jint newValue) {
+ ScopedFastNativeObjectAccess soa(env);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ // JNI must use non transactional mode.
+ bool success = obj->CasField32<false>(MemberOffset(offset),
+ expectedValue,
+ newValue,
+ CASMode::kStrong,
+ std::memory_order_seq_cst);
+ return success ? JNI_TRUE : JNI_FALSE;
+}
+
static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
jlong expectedValue, jlong newValue) {
ScopedFastNativeObjectAccess soa(env);
@@ -545,6 +558,7 @@
FAST_NATIVE_METHOD(Unsafe, compareAndSwapInt, "(Ljava/lang/Object;JII)Z"),
FAST_NATIVE_METHOD(Unsafe, compareAndSwapLong, "(Ljava/lang/Object;JJJ)Z"),
FAST_NATIVE_METHOD(Unsafe, compareAndSwapObject, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"),
+ FAST_NATIVE_METHOD(Unsafe, compareAndSetInt, "(Ljava/lang/Object;JII)Z"),
FAST_NATIVE_METHOD(Unsafe, getIntVolatile, "(Ljava/lang/Object;J)I"),
FAST_NATIVE_METHOD(Unsafe, putIntVolatile, "(Ljava/lang/Object;JI)V"),
FAST_NATIVE_METHOD(Unsafe, getLongVolatile, "(Ljava/lang/Object;J)J"),
diff --git a/test/2235-JdkUnsafeTest/src/Main.java b/test/2235-JdkUnsafeTest/src/Main.java
index cf295da..72c5a68 100644
--- a/test/2235-JdkUnsafeTest/src/Main.java
+++ b/test/2235-JdkUnsafeTest/src/Main.java
@@ -67,7 +67,9 @@
testArrayBaseOffset(unsafe);
testArrayIndexScale(unsafe);
testGetAndPutAndCAS(unsafe);
+ testCompareAndSet(unsafe);
testGetAndPutVolatile(unsafe);
+ testGetAcquireAndPutRelease(unsafe);
testCopyMemoryPrimitiveArrays(unsafe);
}
@@ -212,6 +214,38 @@
}
}
+ private static void testCompareAndSet(Unsafe unsafe) throws NoSuchFieldException {
+ TestClass t = new TestClass();
+
+ int intValue = 12345678;
+ Field intField = TestClass.class.getDeclaredField("intVar");
+ long intOffset = unsafe.objectFieldOffset(intField);
+ unsafe.putInt(t, intOffset, intValue);
+
+ if (unsafe.compareAndSetInt(t, intOffset, 0, 1)) {
+ System.out.println("Unexpectedly succeeding compareAndSetInt(t, intOffset, 0, 1)");
+ }
+ check(t.intVar, intValue, "Unsafe.compareAndSetInt(Object, long, int, int) - not set");
+
+ if (!unsafe.compareAndSetInt(t, intOffset, intValue, 0)) {
+ System.out.println(
+ "Unexpectedly not succeeding compareAndSetInt(t, intOffset, intValue, 0)");
+ }
+ check(t.intVar, 0, "Unsafe.compareAndSetInt(Object, long, int, int) - gets set");
+
+ if (!unsafe.compareAndSetInt(t, intOffset, 0, 1)) {
+ System.out.println("Unexpectedly not succeeding compareAndSetInt(t, intOffset, 0, 1)");
+ }
+ check(t.intVar, 1, "Unsafe.compareAndSetInt(Object, long, int, int) - gets re-set");
+
+ // Exercise jdk.internal.misc.Unsafe.compareAndSetInt using the same
+ // integer (1) for the `expectedValue` and `newValue` arguments.
+ if (!unsafe.compareAndSetInt(t, intOffset, 1, 1)) {
+ System.out.println("Unexpectedly not succeeding compareAndSetInt(t, intOffset, 1, 1)");
+ }
+ check(t.intVar, 1, "Unsafe.compareAndSetInt(Object, long, int, int) - gets set to same");
+ }
+
private static void testGetAndPutVolatile(Unsafe unsafe) throws NoSuchFieldException {
TestVolatileClass tv = new TestVolatileClass();
@@ -252,6 +286,22 @@
"Unsafe.getObjectVolatile(Object, long)");
}
+ private static void testGetAcquireAndPutRelease(Unsafe unsafe) throws NoSuchFieldException {
+ TestVolatileClass tv = new TestVolatileClass();
+
+ int intValue = 12345678;
+ Field volatileIntField = TestVolatileClass.class.getDeclaredField("volatileIntVar");
+ long volatileIntOffset = unsafe.objectFieldOffset(volatileIntField);
+ check(unsafe.getIntAcquire(tv, volatileIntOffset),
+ 0,
+ "Unsafe.getIntAcquire(Object, long) - initial");
+ unsafe.putIntRelease(tv, volatileIntOffset, intValue);
+ check(tv.volatileIntVar, intValue, "Unsafe.putIntRelease(Object, long, int)");
+ check(unsafe.getIntAcquire(tv, volatileIntOffset),
+ intValue,
+ "Unsafe.getIntAcquire(Object, long)");
+ }
+
// Regression test for "copyMemory" operations hitting a DCHECK() for float/double arrays.
private static void testCopyMemoryPrimitiveArrays(Unsafe unsafe) {
int size = 4 * 1024;