< prev index next >

src/share/vm/prims/unsafe.cpp

Print this page
rev 12711 : 8181292: Backport Rename internal Unsafe.compare methods from 10 to 9
Reviewed-by: psandoz, dholmes, thartmann
Contributed-by: ron.pressler@oracle.com, claes.redestad@oracle.com
   1 /*
   2  * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *


 361   } else {
 362     oop_store((oop*)addr, x);
 363   }
 364 
 365   OrderAccess::fence();
 366 } UNSAFE_END
 367 
 368 UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) {
 369   oop v = *(oop*) (address) addr;
 370 
 371   return JNIHandles::make_local(env, v);
 372 } UNSAFE_END
 373 
 374 #ifndef SUPPORTS_NATIVE_CX8
 375 
 376 // VM_Version::supports_cx8() is a surrogate for 'supports atomic long memory ops'.
 377 //
 378 // On platforms which do not support atomic compare-and-swap of jlong (8 byte)
 379 // values we have to use a lock-based scheme to enforce atomicity. This has to be
 380 // applied to all Unsafe operations that set the value of a jlong field. Even so
 381 // the compareAndSwapLong operation will not be atomic with respect to direct stores
 382 // to the field from Java code. It is important therefore that any Java code that
 383 // utilizes these Unsafe jlong operations does not perform direct stores. To permit
 384 // direct loads of the field from Java code we must also use Atomic::store within the
 385 // locked regions. And for good measure, in case there are direct stores, we also
 386 // employ Atomic::load within those regions. Note that the field in question must be
 387 // volatile and so must have atomic load/store accesses applied at the Java level.
 388 //
 389 // The locking scheme could utilize a range of strategies for controlling the locking
 390 // granularity: from a lock per-field through to a single global lock. The latter is
 391 // the simplest and is used for the current implementation. Note that the Java object
 392 // that contains the field, can not, in general, be used for locking. To do so can lead
 393 // to deadlocks as we may introduce locking into what appears to the Java code to be a
 394 // lock-free path.
 395 //
 396 // As all the locked-regions are very short and themselves non-blocking we can treat
 397 // them as leaf routines and elide safepoint checks (ie we don't perform any thread
 398 // state transitions even when blocking for the lock). Note that if we do choose to
 399 // add safepoint checks and thread state transitions, we must ensure that we calculate
 400 // the address of the field _after_ we have acquired the lock, else the object may have
 401 // been moved by the GC


 996   Handle p(THREAD, JNIHandles::resolve(obj));
 997   jlong* addr = (jlong*)index_oop_from_field_offset_long(p(), offset);
 998 
 999 #ifdef SUPPORTS_NATIVE_CX8
1000   return (jlong)(Atomic::cmpxchg(x, addr, e));
1001 #else
1002   if (VM_Version::supports_cx8()) {
1003     return (jlong)(Atomic::cmpxchg(x, addr, e));
1004   } else {
1005     MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
1006 
1007     jlong val = Atomic::load(addr);
1008     if (val == e) {
1009       Atomic::store(x, addr);
1010     }
1011     return val;
1012   }
1013 #endif
1014 } UNSAFE_END
1015 
1016 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) {
1017   oop x = JNIHandles::resolve(x_h);
1018   oop e = JNIHandles::resolve(e_h);
1019   oop p = JNIHandles::resolve(obj);
1020   HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);
1021   oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);
1022   if (res != e) {
1023     return false;
1024   }
1025 
1026   update_barrier_set((void*)addr, x);
1027 
1028   return true;
1029 } UNSAFE_END
1030 
1031 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
1032   oop p = JNIHandles::resolve(obj);
1033   jint* addr = (jint *)index_oop_from_field_offset_long(p, offset);
1034 
1035   return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
1036 } UNSAFE_END
1037 
1038 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) {
1039   Handle p(THREAD, JNIHandles::resolve(obj));
1040   jlong* addr = (jlong*)index_oop_from_field_offset_long(p(), offset);
1041 
1042 #ifdef SUPPORTS_NATIVE_CX8
1043   return (jlong)(Atomic::cmpxchg(x, addr, e)) == e;
1044 #else
1045   if (VM_Version::supports_cx8()) {
1046     return (jlong)(Atomic::cmpxchg(x, addr, e)) == e;
1047   } else {
1048     MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
1049 
1050     jlong val = Atomic::load(addr);
1051     if (val != e) {
1052       return false;
1053     }
1054 
1055     Atomic::store(x, addr);
1056     return true;
1057   }
1058 #endif


1177     DECLARE_GETPUTOOP(Long, J),
1178     DECLARE_GETPUTOOP(Float, F),
1179     DECLARE_GETPUTOOP(Double, D),
1180 
1181     {CC "allocateMemory0",    CC "(J)" ADR,              FN_PTR(Unsafe_AllocateMemory0)},
1182     {CC "reallocateMemory0",  CC "(" ADR "J)" ADR,       FN_PTR(Unsafe_ReallocateMemory0)},
1183     {CC "freeMemory0",        CC "(" ADR ")V",           FN_PTR(Unsafe_FreeMemory0)},
1184 
1185     {CC "objectFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_ObjectFieldOffset0)},
1186     {CC "staticFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_StaticFieldOffset0)},
1187     {CC "staticFieldBase0",   CC "(" FLD ")" OBJ,        FN_PTR(Unsafe_StaticFieldBase0)},
1188     {CC "ensureClassInitialized0", CC "(" CLS ")V",      FN_PTR(Unsafe_EnsureClassInitialized0)},
1189     {CC "arrayBaseOffset0",   CC "(" CLS ")I",           FN_PTR(Unsafe_ArrayBaseOffset0)},
1190     {CC "arrayIndexScale0",   CC "(" CLS ")I",           FN_PTR(Unsafe_ArrayIndexScale0)},
1191     {CC "addressSize0",       CC "()I",                  FN_PTR(Unsafe_AddressSize0)},
1192     {CC "pageSize",           CC "()I",                  FN_PTR(Unsafe_PageSize)},
1193 
1194     {CC "defineClass0",       CC "(" DC_Args ")" CLS,    FN_PTR(Unsafe_DefineClass0)},
1195     {CC "allocateInstance",   CC "(" CLS ")" OBJ,        FN_PTR(Unsafe_AllocateInstance)},
1196     {CC "throwException",     CC "(" THR ")V",           FN_PTR(Unsafe_ThrowException)},
1197     {CC "compareAndSwapObject", CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSwapObject)},
1198     {CC "compareAndSwapInt",  CC "(" OBJ "J""I""I"")Z",  FN_PTR(Unsafe_CompareAndSwapInt)},
1199     {CC "compareAndSwapLong", CC "(" OBJ "J""J""J"")Z",  FN_PTR(Unsafe_CompareAndSwapLong)},
1200     {CC "compareAndExchangeObjectVolatile", CC "(" OBJ "J" OBJ "" OBJ ")" OBJ, FN_PTR(Unsafe_CompareAndExchangeObject)},
1201     {CC "compareAndExchangeIntVolatile",  CC "(" OBJ "J""I""I"")I", FN_PTR(Unsafe_CompareAndExchangeInt)},
1202     {CC "compareAndExchangeLongVolatile", CC "(" OBJ "J""J""J"")J", FN_PTR(Unsafe_CompareAndExchangeLong)},
1203 
1204     {CC "park",               CC "(ZJ)V",                FN_PTR(Unsafe_Park)},
1205     {CC "unpark",             CC "(" OBJ ")V",           FN_PTR(Unsafe_Unpark)},
1206 
1207     {CC "getLoadAverage0",    CC "([DI)I",               FN_PTR(Unsafe_GetLoadAverage0)},
1208 
1209     {CC "copyMemory0",        CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory0)},
1210     {CC "copySwapMemory0",    CC "(" OBJ "J" OBJ "JJJ)V", FN_PTR(Unsafe_CopySwapMemory0)},
1211     {CC "setMemory0",         CC "(" OBJ "JJB)V",        FN_PTR(Unsafe_SetMemory0)},
1212 
1213     {CC "defineAnonymousClass0", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass0)},
1214 
1215     {CC "shouldBeInitialized0", CC "(" CLS ")Z",         FN_PTR(Unsafe_ShouldBeInitialized0)},
1216 
1217     {CC "loadFence",          CC "()V",                  FN_PTR(Unsafe_LoadFence)},
1218     {CC "storeFence",         CC "()V",                  FN_PTR(Unsafe_StoreFence)},
1219     {CC "fullFence",          CC "()V",                  FN_PTR(Unsafe_FullFence)},
1220 
1221     {CC "isBigEndian0",       CC "()Z",                  FN_PTR(Unsafe_isBigEndian0)},
1222     {CC "unalignedAccess0",   CC "()Z",                  FN_PTR(Unsafe_unalignedAccess0)}


   1 /*
   2  * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *


 361   } else {
 362     oop_store((oop*)addr, x);
 363   }
 364 
 365   OrderAccess::fence();
 366 } UNSAFE_END
 367 
 368 UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) {
 369   oop v = *(oop*) (address) addr;
 370 
 371   return JNIHandles::make_local(env, v);
 372 } UNSAFE_END
 373 
 374 #ifndef SUPPORTS_NATIVE_CX8
 375 
 376 // VM_Version::supports_cx8() is a surrogate for 'supports atomic long memory ops'.
 377 //
 378 // On platforms which do not support atomic compare-and-swap of jlong (8 byte)
 379 // values we have to use a lock-based scheme to enforce atomicity. This has to be
 380 // applied to all Unsafe operations that set the value of a jlong field. Even so
 381 // the compareAndSetLong operation will not be atomic with respect to direct stores
 382 // to the field from Java code. It is important therefore that any Java code that
 383 // utilizes these Unsafe jlong operations does not perform direct stores. To permit
 384 // direct loads of the field from Java code we must also use Atomic::store within the
 385 // locked regions. And for good measure, in case there are direct stores, we also
 386 // employ Atomic::load within those regions. Note that the field in question must be
 387 // volatile and so must have atomic load/store accesses applied at the Java level.
 388 //
 389 // The locking scheme could utilize a range of strategies for controlling the locking
 390 // granularity: from a lock per-field through to a single global lock. The latter is
 391 // the simplest and is used for the current implementation. Note that the Java object
 392 // that contains the field, can not, in general, be used for locking. To do so can lead
 393 // to deadlocks as we may introduce locking into what appears to the Java code to be a
 394 // lock-free path.
 395 //
 396 // As all the locked-regions are very short and themselves non-blocking we can treat
 397 // them as leaf routines and elide safepoint checks (ie we don't perform any thread
 398 // state transitions even when blocking for the lock). Note that if we do choose to
 399 // add safepoint checks and thread state transitions, we must ensure that we calculate
 400 // the address of the field _after_ we have acquired the lock, else the object may have
 401 // been moved by the GC


 996   Handle p(THREAD, JNIHandles::resolve(obj));
 997   jlong* addr = (jlong*)index_oop_from_field_offset_long(p(), offset);
 998 
 999 #ifdef SUPPORTS_NATIVE_CX8
1000   return (jlong)(Atomic::cmpxchg(x, addr, e));
1001 #else
1002   if (VM_Version::supports_cx8()) {
1003     return (jlong)(Atomic::cmpxchg(x, addr, e));
1004   } else {
1005     MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
1006 
1007     jlong val = Atomic::load(addr);
1008     if (val == e) {
1009       Atomic::store(x, addr);
1010     }
1011     return val;
1012   }
1013 #endif
1014 } UNSAFE_END
1015 
1016 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) {
1017   oop x = JNIHandles::resolve(x_h);
1018   oop e = JNIHandles::resolve(e_h);
1019   oop p = JNIHandles::resolve(obj);
1020   HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);
1021   oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);
1022   if (res != e) {
1023     return false;
1024   }
1025 
1026   update_barrier_set((void*)addr, x);
1027 
1028   return true;
1029 } UNSAFE_END
1030 
1031 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
1032   oop p = JNIHandles::resolve(obj);
1033   jint* addr = (jint *)index_oop_from_field_offset_long(p, offset);
1034 
1035   return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
1036 } UNSAFE_END
1037 
1038 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) {
1039   Handle p(THREAD, JNIHandles::resolve(obj));
1040   jlong* addr = (jlong*)index_oop_from_field_offset_long(p(), offset);
1041 
1042 #ifdef SUPPORTS_NATIVE_CX8
1043   return (jlong)(Atomic::cmpxchg(x, addr, e)) == e;
1044 #else
1045   if (VM_Version::supports_cx8()) {
1046     return (jlong)(Atomic::cmpxchg(x, addr, e)) == e;
1047   } else {
1048     MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
1049 
1050     jlong val = Atomic::load(addr);
1051     if (val != e) {
1052       return false;
1053     }
1054 
1055     Atomic::store(x, addr);
1056     return true;
1057   }
1058 #endif


1177     DECLARE_GETPUTOOP(Long, J),
1178     DECLARE_GETPUTOOP(Float, F),
1179     DECLARE_GETPUTOOP(Double, D),
1180 
1181     {CC "allocateMemory0",    CC "(J)" ADR,              FN_PTR(Unsafe_AllocateMemory0)},
1182     {CC "reallocateMemory0",  CC "(" ADR "J)" ADR,       FN_PTR(Unsafe_ReallocateMemory0)},
1183     {CC "freeMemory0",        CC "(" ADR ")V",           FN_PTR(Unsafe_FreeMemory0)},
1184 
1185     {CC "objectFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_ObjectFieldOffset0)},
1186     {CC "staticFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_StaticFieldOffset0)},
1187     {CC "staticFieldBase0",   CC "(" FLD ")" OBJ,        FN_PTR(Unsafe_StaticFieldBase0)},
1188     {CC "ensureClassInitialized0", CC "(" CLS ")V",      FN_PTR(Unsafe_EnsureClassInitialized0)},
1189     {CC "arrayBaseOffset0",   CC "(" CLS ")I",           FN_PTR(Unsafe_ArrayBaseOffset0)},
1190     {CC "arrayIndexScale0",   CC "(" CLS ")I",           FN_PTR(Unsafe_ArrayIndexScale0)},
1191     {CC "addressSize0",       CC "()I",                  FN_PTR(Unsafe_AddressSize0)},
1192     {CC "pageSize",           CC "()I",                  FN_PTR(Unsafe_PageSize)},
1193 
1194     {CC "defineClass0",       CC "(" DC_Args ")" CLS,    FN_PTR(Unsafe_DefineClass0)},
1195     {CC "allocateInstance",   CC "(" CLS ")" OBJ,        FN_PTR(Unsafe_AllocateInstance)},
1196     {CC "throwException",     CC "(" THR ")V",           FN_PTR(Unsafe_ThrowException)},
1197     {CC "compareAndSetObject",CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSetObject)},
1198     {CC "compareAndSetInt",   CC "(" OBJ "J""I""I"")Z",  FN_PTR(Unsafe_CompareAndSetInt)},
1199     {CC "compareAndSetLong",  CC "(" OBJ "J""J""J"")Z",  FN_PTR(Unsafe_CompareAndSetLong)},
1200     {CC "compareAndExchangeObject", CC "(" OBJ "J" OBJ "" OBJ ")" OBJ, FN_PTR(Unsafe_CompareAndExchangeObject)},
1201     {CC "compareAndExchangeInt",  CC "(" OBJ "J""I""I"")I", FN_PTR(Unsafe_CompareAndExchangeInt)},
1202     {CC "compareAndExchangeLong", CC "(" OBJ "J""J""J"")J", FN_PTR(Unsafe_CompareAndExchangeLong)},
1203 
1204     {CC "park",               CC "(ZJ)V",                FN_PTR(Unsafe_Park)},
1205     {CC "unpark",             CC "(" OBJ ")V",           FN_PTR(Unsafe_Unpark)},
1206 
1207     {CC "getLoadAverage0",    CC "([DI)I",               FN_PTR(Unsafe_GetLoadAverage0)},
1208 
1209     {CC "copyMemory0",        CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory0)},
1210     {CC "copySwapMemory0",    CC "(" OBJ "J" OBJ "JJJ)V", FN_PTR(Unsafe_CopySwapMemory0)},
1211     {CC "setMemory0",         CC "(" OBJ "JJB)V",        FN_PTR(Unsafe_SetMemory0)},
1212 
1213     {CC "defineAnonymousClass0", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass0)},
1214 
1215     {CC "shouldBeInitialized0", CC "(" CLS ")Z",         FN_PTR(Unsafe_ShouldBeInitialized0)},
1216 
1217     {CC "loadFence",          CC "()V",                  FN_PTR(Unsafe_LoadFence)},
1218     {CC "storeFence",         CC "()V",                  FN_PTR(Unsafe_StoreFence)},
1219     {CC "fullFence",          CC "()V",                  FN_PTR(Unsafe_FullFence)},
1220 
1221     {CC "isBigEndian0",       CC "()Z",                  FN_PTR(Unsafe_isBigEndian0)},
1222     {CC "unalignedAccess0",   CC "()Z",                  FN_PTR(Unsafe_unalignedAccess0)}


< prev index next >