--- a/hotspot/src/cpu/x86/vm/x86_32.ad Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad Wed Feb 24 12:38:50 2016 +0000
@@ -7236,6 +7236,7 @@
instruct compareAndSwapL( rRegI res, eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{
predicate(VM_Version::supports_cx8());
match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapL mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EDX:EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
"MOV $res,0\n\t"
@@ -7249,6 +7250,7 @@
instruct compareAndSwapP( rRegI res, pRegP mem_ptr, eAXRegP oldval, eCXRegP newval, eFlagsReg cr) %{
match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
"MOV $res,0\n\t"
@@ -7261,6 +7263,7 @@
instruct compareAndSwapI( rRegI res, pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{
match(Set res (CompareAndSwapI mem_ptr (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapI mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
"MOV $res,0\n\t"
@@ -7271,6 +7274,31 @@
ins_pipe( pipe_cmpxchg );
%}
+instruct compareAndExchangeL( eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{
+ predicate(VM_Version::supports_cx8());
+ match(Set oldval (CompareAndExchangeL mem_ptr (Binary oldval newval)));
+ effect(KILL cr);
+ format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EDX:EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %}
+ ins_encode( enc_cmpxchg8(mem_ptr) );
+ ins_pipe( pipe_cmpxchg );
+%}
+
+instruct compareAndExchangeP( pRegP mem_ptr, eAXRegP oldval, eCXRegP newval, eFlagsReg cr) %{
+ match(Set oldval (CompareAndExchangeP mem_ptr (Binary oldval newval)));
+ effect(KILL cr);
+ format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %}
+ ins_encode( enc_cmpxchg(mem_ptr) );
+ ins_pipe( pipe_cmpxchg );
+%}
+
+instruct compareAndExchangeI( pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{
+ match(Set oldval (CompareAndExchangeI mem_ptr (Binary oldval newval)));
+ effect(KILL cr);
+ format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %}
+ ins_encode( enc_cmpxchg(mem_ptr) );
+ ins_pipe( pipe_cmpxchg );
+%}
+
instruct xaddI_no_res( memory mem, Universe dummy, immI add, eFlagsReg cr) %{
predicate(n->as_LoadStore()->result_not_used());
match(Set dummy (GetAndAddI mem add));
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad Wed Feb 24 12:38:50 2016 +0000
@@ -7281,6 +7281,7 @@
%{
predicate(VM_Version::supports_cx8());
match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
format %{ "cmpxchgq $mem_ptr,$newval\t# "
@@ -7305,6 +7306,7 @@
%{
predicate(VM_Version::supports_cx8());
match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapL mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
format %{ "cmpxchgq $mem_ptr,$newval\t# "
@@ -7328,6 +7330,7 @@
rFlagsReg cr)
%{
match(Set res (CompareAndSwapI mem_ptr (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapI mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
format %{ "cmpxchgl $mem_ptr,$newval\t# "
@@ -7351,6 +7354,7 @@
rax_RegN oldval, rRegN newval,
rFlagsReg cr) %{
match(Set res (CompareAndSwapN mem_ptr (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapN mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
format %{ "cmpxchgl $mem_ptr,$newval\t# "
@@ -7368,6 +7372,83 @@
ins_pipe( pipe_cmpxchg );
%}
+instruct compareAndExchangeI(
+ memory mem_ptr,
+ rax_RegI oldval, rRegI newval,
+ rFlagsReg cr)
+%{
+ match(Set oldval (CompareAndExchangeI mem_ptr (Binary oldval newval)));
+ effect(KILL cr);
+
+ format %{ "cmpxchgl $mem_ptr,$newval\t# "
+ "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
+ opcode(0x0F, 0xB1);
+ ins_encode(lock_prefix,
+ REX_reg_mem(newval, mem_ptr),
+ OpcP, OpcS,
+ reg_mem(newval, mem_ptr) // lock cmpxchg
+ );
+ ins_pipe( pipe_cmpxchg );
+%}
+
+instruct compareAndExchangeL(
+ memory mem_ptr,
+ rax_RegL oldval, rRegL newval,
+ rFlagsReg cr)
+%{
+ predicate(VM_Version::supports_cx8());
+ match(Set oldval (CompareAndExchangeL mem_ptr (Binary oldval newval)));
+ effect(KILL cr);
+
+ format %{ "cmpxchgq $mem_ptr,$newval\t# "
+ "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
+ opcode(0x0F, 0xB1);
+ ins_encode(lock_prefix,
+ REX_reg_mem_wide(newval, mem_ptr),
+ OpcP, OpcS,
+ reg_mem(newval, mem_ptr) // lock cmpxchg
+ );
+ ins_pipe( pipe_cmpxchg );
+%}
+
+instruct compareAndExchangeN(
+ memory mem_ptr,
+ rax_RegN oldval, rRegN newval,
+ rFlagsReg cr) %{
+ match(Set oldval (CompareAndExchangeN mem_ptr (Binary oldval newval)));
+ effect(KILL cr);
+
+ format %{ "cmpxchgl $mem_ptr,$newval\t# "
+ "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
+ opcode(0x0F, 0xB1);
+ ins_encode(lock_prefix,
+ REX_reg_mem(newval, mem_ptr),
+ OpcP, OpcS,
+ reg_mem(newval, mem_ptr) // lock cmpxchg
+ );
+ ins_pipe( pipe_cmpxchg );
+%}
+
+instruct compareAndExchangeP(
+ memory mem_ptr,
+ rax_RegP oldval, rRegP newval,
+ rFlagsReg cr)
+%{
+ predicate(VM_Version::supports_cx8());
+ match(Set oldval (CompareAndExchangeP mem_ptr (Binary oldval newval)));
+ effect(KILL cr);
+
+ format %{ "cmpxchgq $mem_ptr,$newval\t# "
+ "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
+ opcode(0x0F, 0xB1);
+ ins_encode(lock_prefix,
+ REX_reg_mem_wide(newval, mem_ptr),
+ OpcP, OpcS,
+ reg_mem(newval, mem_ptr) // lock cmpxchg
+ );
+ ins_pipe( pipe_cmpxchg );
+%}
+
instruct xaddI_no_res( memory mem, Universe dummy, immI add, rFlagsReg cr) %{
predicate(n->as_LoadStore()->result_not_used());
match(Set dummy (GetAndAddI mem add));
--- a/hotspot/src/share/vm/adlc/formssel.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/adlc/formssel.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -3491,6 +3491,8 @@
"LoadPLocked",
"StorePConditional", "StoreIConditional", "StoreLConditional",
"CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN",
+ "WeakCompareAndSwapI", "WeakCompareAndSwapL", "WeakCompareAndSwapP", "WeakCompareAndSwapN",
+ "CompareAndExchangeI", "CompareAndExchangeL", "CompareAndExchangeP", "CompareAndExchangeN",
"StoreCM",
"ClearArray",
"GetAndAddI", "GetAndSetI", "GetAndSetP",
--- a/hotspot/src/share/vm/ci/ciConstantPoolCache.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/ci/ciConstantPoolCache.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -41,15 +41,21 @@
_keys = new (arena) GrowableArray<int>(arena, expected_size, 0, 0);
}
+int ciConstantPoolCache::key_compare(const int& key, const int& elt) {
+ if (key < elt) return -1;
+ else if (key > elt) return 1;
+ else return 0;
+}
+
// ------------------------------------------------------------------
// ciConstantPoolCache::get
//
// Get the entry at some index
void* ciConstantPoolCache::get(int index) {
ASSERT_IN_VM;
- int pos = find(index);
- if (pos >= _keys->length() ||
- _keys->at(pos) != index) {
+ bool found = false;
+ int pos = _keys->find_sorted<int, ciConstantPoolCache::key_compare>(index, found);
+ if (!found) {
// This element is not present in the cache.
return NULL;
}
@@ -57,42 +63,15 @@
}
// ------------------------------------------------------------------
-// ciConstantPoolCache::find
-//
-// Use binary search to find the position of this index in the cache.
-// If there is no entry in the cache corresponding to this oop, return
-// the position at which the index would be inserted.
-int ciConstantPoolCache::find(int key) {
- int min = 0;
- int max = _keys->length()-1;
-
- while (max >= min) {
- int mid = (max + min) / 2;
- int value = _keys->at(mid);
- if (value < key) {
- min = mid + 1;
- } else if (value > key) {
- max = mid - 1;
- } else {
- return mid;
- }
- }
- return min;
-}
-
-// ------------------------------------------------------------------
// ciConstantPoolCache::insert
//
// Insert a ciObject into the table at some index.
void ciConstantPoolCache::insert(int index, void* elem) {
- int i;
- int pos = find(index);
- for (i = _keys->length()-1; i >= pos; i--) {
- _keys->at_put_grow(i+1, _keys->at(i));
- _elements->at_put_grow(i+1, _elements->at(i));
- }
- _keys->at_put_grow(pos, index);
- _elements->at_put_grow(pos, elem);
+ bool found = false;
+ int pos = _keys->find_sorted<int, ciConstantPoolCache::key_compare>(index, found);
+ assert(!found, "duplicate");
+ _keys->insert_before(pos, index);
+ _elements->insert_before(pos, elem);
}
// ------------------------------------------------------------------
--- a/hotspot/src/share/vm/ci/ciConstantPoolCache.hpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/ci/ciConstantPoolCache.hpp Wed Feb 24 12:38:50 2016 +0000
@@ -38,7 +38,7 @@
GrowableArray<int>* _keys;
GrowableArray<void*>* _elements;
- int find(int index);
+ static int key_compare(const int& key, const int& elt);
public:
ciConstantPoolCache(Arena* arena, int expected_size);
--- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -260,6 +260,13 @@
return new_object;
}
+int ciObjectFactory::metadata_compare(Metadata* const& key, ciMetadata* const& elt) {
+ Metadata* value = elt->constant_encoding();
+ if (key < value) return -1;
+ else if (key > value) return 1;
+ else return 0;
+}
+
// ------------------------------------------------------------------
// ciObjectFactory::get_metadata
//
@@ -280,7 +287,8 @@
}
#endif // ASSERT
int len = _ci_metadata->length();
- int index = find(key, _ci_metadata);
+ bool found = false;
+ int index = _ci_metadata->find_sorted<Metadata*, ciObjectFactory::metadata_compare>(key, found);
#ifdef ASSERT
if (CIObjectFactoryVerify) {
for (int i=0; i<_ci_metadata->length(); i++) {
@@ -290,7 +298,8 @@
}
}
#endif
- if (!is_found_at(index, key, _ci_metadata)) {
+
+ if (!found) {
// The ciMetadata does not yet exist. Create it and insert it
// into the cache.
ciMetadata* new_object = create_new_metadata(key);
@@ -300,10 +309,10 @@
if (len != _ci_metadata->length()) {
// creating the new object has recursively entered new objects
// into the table. We need to recompute our index.
- index = find(key, _ci_metadata);
+ index = _ci_metadata->find_sorted<Metadata*, ciObjectFactory::metadata_compare>(key, found);
}
- assert(!is_found_at(index, key, _ci_metadata), "no double insert");
- insert(index, new_object, _ci_metadata);
+ assert(!found, "no double insert");
+ _ci_metadata->insert_before(index, new_object);
return new_object;
}
return _ci_metadata->at(index)->as_metadata();
@@ -655,60 +664,6 @@
obj->set_ident(_next_ident++);
}
-// ------------------------------------------------------------------
-// ciObjectFactory::find
-//
-// Use binary search to find the position of this oop in the cache.
-// If there is no entry in the cache corresponding to this oop, return
-// the position at which the oop should be inserted.
-int ciObjectFactory::find(Metadata* key, GrowableArray<ciMetadata*>* objects) {
- int min = 0;
- int max = objects->length()-1;
-
- // print_contents();
-
- while (max >= min) {
- int mid = (max + min) / 2;
- Metadata* value = objects->at(mid)->constant_encoding();
- if (value < key) {
- min = mid + 1;
- } else if (value > key) {
- max = mid - 1;
- } else {
- return mid;
- }
- }
- return min;
-}
-
-// ------------------------------------------------------------------
-// ciObjectFactory::is_found_at
-//
-// Verify that the binary seach found the given key.
-bool ciObjectFactory::is_found_at(int index, Metadata* key, GrowableArray<ciMetadata*>* objects) {
- return (index < objects->length() &&
- objects->at(index)->constant_encoding() == key);
-}
-
-
-// ------------------------------------------------------------------
-// ciObjectFactory::insert
-//
-// Insert a ciObject into the table at some index.
-void ciObjectFactory::insert(int index, ciMetadata* obj, GrowableArray<ciMetadata*>* objects) {
- int len = objects->length();
- if (len == index) {
- objects->append(obj);
- } else {
- objects->append(objects->at(len-1));
- int pos;
- for (pos = len-2; pos >= index; pos--) {
- objects->at_put(pos+1,objects->at(pos));
- }
- objects->at_put(index, obj);
- }
-}
-
static ciObjectFactory::NonPermObject* emptyBucket = NULL;
// ------------------------------------------------------------------
--- a/hotspot/src/share/vm/ci/ciObjectFactory.hpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.hpp Wed Feb 24 12:38:50 2016 +0000
@@ -68,9 +68,7 @@
NonPermObject* _non_perm_bucket[NON_PERM_BUCKETS];
int _non_perm_count;
- int find(Metadata* key, GrowableArray<ciMetadata*>* objects);
- bool is_found_at(int index, Metadata* key, GrowableArray<ciMetadata*>* objects);
- void insert(int index, ciMetadata* obj, GrowableArray<ciMetadata*>* objects);
+ static int metadata_compare(Metadata* const& key, ciMetadata* const& elt);
ciObject* create_new_object(oop o);
ciMetadata* create_new_metadata(Metadata* o);
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -544,6 +544,42 @@
case vmIntrinsics::_putLongVolatile:
case vmIntrinsics::_putFloatVolatile:
case vmIntrinsics::_putDoubleVolatile:
+ case vmIntrinsics::_getObjectAcquire:
+ case vmIntrinsics::_getBooleanAcquire:
+ case vmIntrinsics::_getByteAcquire:
+ case vmIntrinsics::_getShortAcquire:
+ case vmIntrinsics::_getCharAcquire:
+ case vmIntrinsics::_getIntAcquire:
+ case vmIntrinsics::_getLongAcquire:
+ case vmIntrinsics::_getFloatAcquire:
+ case vmIntrinsics::_getDoubleAcquire:
+ case vmIntrinsics::_putObjectRelease:
+ case vmIntrinsics::_putBooleanRelease:
+ case vmIntrinsics::_putByteRelease:
+ case vmIntrinsics::_putShortRelease:
+ case vmIntrinsics::_putCharRelease:
+ case vmIntrinsics::_putIntRelease:
+ case vmIntrinsics::_putLongRelease:
+ case vmIntrinsics::_putFloatRelease:
+ case vmIntrinsics::_putDoubleRelease:
+ case vmIntrinsics::_getObjectOpaque:
+ case vmIntrinsics::_getBooleanOpaque:
+ case vmIntrinsics::_getByteOpaque:
+ case vmIntrinsics::_getShortOpaque:
+ case vmIntrinsics::_getCharOpaque:
+ case vmIntrinsics::_getIntOpaque:
+ case vmIntrinsics::_getLongOpaque:
+ case vmIntrinsics::_getFloatOpaque:
+ case vmIntrinsics::_getDoubleOpaque:
+ case vmIntrinsics::_putObjectOpaque:
+ case vmIntrinsics::_putBooleanOpaque:
+ case vmIntrinsics::_putByteOpaque:
+ case vmIntrinsics::_putShortOpaque:
+ case vmIntrinsics::_putCharOpaque:
+ case vmIntrinsics::_putIntOpaque:
+ case vmIntrinsics::_putLongOpaque:
+ case vmIntrinsics::_putFloatOpaque:
+ case vmIntrinsics::_putDoubleOpaque:
case vmIntrinsics::_getByte_raw:
case vmIntrinsics::_getShort_raw:
case vmIntrinsics::_getChar_raw:
@@ -569,9 +605,27 @@
case vmIntrinsics::_loadFence:
case vmIntrinsics::_storeFence:
case vmIntrinsics::_fullFence:
+ case vmIntrinsics::_compareAndSwapLong:
+ case vmIntrinsics::_weakCompareAndSwapLong:
+ case vmIntrinsics::_weakCompareAndSwapLongAcquire:
+ case vmIntrinsics::_weakCompareAndSwapLongRelease:
+ case vmIntrinsics::_compareAndSwapInt:
+ case vmIntrinsics::_weakCompareAndSwapInt:
+ case vmIntrinsics::_weakCompareAndSwapIntAcquire:
+ case vmIntrinsics::_weakCompareAndSwapIntRelease:
case vmIntrinsics::_compareAndSwapObject:
- case vmIntrinsics::_compareAndSwapLong:
- case vmIntrinsics::_compareAndSwapInt:
+ case vmIntrinsics::_weakCompareAndSwapObject:
+ case vmIntrinsics::_weakCompareAndSwapObjectAcquire:
+ case vmIntrinsics::_weakCompareAndSwapObjectRelease:
+ case vmIntrinsics::_compareAndExchangeIntVolatile:
+ case vmIntrinsics::_compareAndExchangeIntAcquire:
+ case vmIntrinsics::_compareAndExchangeIntRelease:
+ case vmIntrinsics::_compareAndExchangeLongVolatile:
+ case vmIntrinsics::_compareAndExchangeLongAcquire:
+ case vmIntrinsics::_compareAndExchangeLongRelease:
+ case vmIntrinsics::_compareAndExchangeObjectVolatile:
+ case vmIntrinsics::_compareAndExchangeObjectAcquire:
+ case vmIntrinsics::_compareAndExchangeObjectRelease:
if (!InlineUnsafeOps) return true;
break;
case vmIntrinsics::_getShortUnaligned:
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Feb 24 12:38:50 2016 +0000
@@ -1146,6 +1146,64 @@
do_intrinsic(_putFloatVolatile, jdk_internal_misc_Unsafe, putFloatVolatile_name, putFloat_signature, F_RN) \
do_intrinsic(_putDoubleVolatile, jdk_internal_misc_Unsafe, putDoubleVolatile_name, putDouble_signature, F_RN) \
\
+ do_name(getObjectOpaque_name,"getObjectOpaque") do_name(putObjectOpaque_name,"putObjectOpaque") \
+ do_name(getBooleanOpaque_name,"getBooleanOpaque") do_name(putBooleanOpaque_name,"putBooleanOpaque") \
+ do_name(getByteOpaque_name,"getByteOpaque") do_name(putByteOpaque_name,"putByteOpaque") \
+ do_name(getShortOpaque_name,"getShortOpaque") do_name(putShortOpaque_name,"putShortOpaque") \
+ do_name(getCharOpaque_name,"getCharOpaque") do_name(putCharOpaque_name,"putCharOpaque") \
+ do_name(getIntOpaque_name,"getIntOpaque") do_name(putIntOpaque_name,"putIntOpaque") \
+ do_name(getLongOpaque_name,"getLongOpaque") do_name(putLongOpaque_name,"putLongOpaque") \
+ do_name(getFloatOpaque_name,"getFloatOpaque") do_name(putFloatOpaque_name,"putFloatOpaque") \
+ do_name(getDoubleOpaque_name,"getDoubleOpaque") do_name(putDoubleOpaque_name,"putDoubleOpaque") \
+ \
+ do_intrinsic(_getObjectOpaque, jdk_internal_misc_Unsafe, getObjectOpaque_name, getObject_signature, F_R) \
+ do_intrinsic(_getBooleanOpaque, jdk_internal_misc_Unsafe, getBooleanOpaque_name, getBoolean_signature, F_R) \
+ do_intrinsic(_getByteOpaque, jdk_internal_misc_Unsafe, getByteOpaque_name, getByte_signature, F_R) \
+ do_intrinsic(_getShortOpaque, jdk_internal_misc_Unsafe, getShortOpaque_name, getShort_signature, F_R) \
+ do_intrinsic(_getCharOpaque, jdk_internal_misc_Unsafe, getCharOpaque_name, getChar_signature, F_R) \
+ do_intrinsic(_getIntOpaque, jdk_internal_misc_Unsafe, getIntOpaque_name, getInt_signature, F_R) \
+ do_intrinsic(_getLongOpaque, jdk_internal_misc_Unsafe, getLongOpaque_name, getLong_signature, F_R) \
+ do_intrinsic(_getFloatOpaque, jdk_internal_misc_Unsafe, getFloatOpaque_name, getFloat_signature, F_R) \
+ do_intrinsic(_getDoubleOpaque, jdk_internal_misc_Unsafe, getDoubleOpaque_name, getDouble_signature, F_R) \
+ do_intrinsic(_putObjectOpaque, jdk_internal_misc_Unsafe, putObjectOpaque_name, putObject_signature, F_R) \
+ do_intrinsic(_putBooleanOpaque, jdk_internal_misc_Unsafe, putBooleanOpaque_name, putBoolean_signature, F_R) \
+ do_intrinsic(_putByteOpaque, jdk_internal_misc_Unsafe, putByteOpaque_name, putByte_signature, F_R) \
+ do_intrinsic(_putShortOpaque, jdk_internal_misc_Unsafe, putShortOpaque_name, putShort_signature, F_R) \
+ do_intrinsic(_putCharOpaque, jdk_internal_misc_Unsafe, putCharOpaque_name, putChar_signature, F_R) \
+ do_intrinsic(_putIntOpaque, jdk_internal_misc_Unsafe, putIntOpaque_name, putInt_signature, F_R) \
+ do_intrinsic(_putLongOpaque, jdk_internal_misc_Unsafe, putLongOpaque_name, putLong_signature, F_R) \
+ do_intrinsic(_putFloatOpaque, jdk_internal_misc_Unsafe, putFloatOpaque_name, putFloat_signature, F_R) \
+ do_intrinsic(_putDoubleOpaque, jdk_internal_misc_Unsafe, putDoubleOpaque_name, putDouble_signature, F_R) \
+ \
+ do_name(getObjectAcquire_name, "getObjectAcquire") do_name(putObjectRelease_name, "putObjectRelease") \
+ do_name(getBooleanAcquire_name, "getBooleanAcquire") do_name(putBooleanRelease_name, "putBooleanRelease") \
+ do_name(getByteAcquire_name, "getByteAcquire") do_name(putByteRelease_name, "putByteRelease") \
+ do_name(getShortAcquire_name, "getShortAcquire") do_name(putShortRelease_name, "putShortRelease") \
+ do_name(getCharAcquire_name, "getCharAcquire") do_name(putCharRelease_name, "putCharRelease") \
+ do_name(getIntAcquire_name, "getIntAcquire") do_name(putIntRelease_name, "putIntRelease") \
+ do_name(getLongAcquire_name, "getLongAcquire") do_name(putLongRelease_name, "putLongRelease") \
+ do_name(getFloatAcquire_name, "getFloatAcquire") do_name(putFloatRelease_name, "putFloatRelease") \
+ do_name(getDoubleAcquire_name, "getDoubleAcquire") do_name(putDoubleRelease_name, "putDoubleRelease") \
+ \
+ do_intrinsic(_getObjectAcquire, jdk_internal_misc_Unsafe, getObjectAcquire_name, getObject_signature, F_R) \
+ do_intrinsic(_getBooleanAcquire, jdk_internal_misc_Unsafe, getBooleanAcquire_name, getBoolean_signature, F_R) \
+ do_intrinsic(_getByteAcquire, jdk_internal_misc_Unsafe, getByteAcquire_name, getByte_signature, F_R) \
+ do_intrinsic(_getShortAcquire, jdk_internal_misc_Unsafe, getShortAcquire_name, getShort_signature, F_R) \
+ do_intrinsic(_getCharAcquire, jdk_internal_misc_Unsafe, getCharAcquire_name, getChar_signature, F_R) \
+ do_intrinsic(_getIntAcquire, jdk_internal_misc_Unsafe, getIntAcquire_name, getInt_signature, F_R) \
+ do_intrinsic(_getLongAcquire, jdk_internal_misc_Unsafe, getLongAcquire_name, getLong_signature, F_R) \
+ do_intrinsic(_getFloatAcquire, jdk_internal_misc_Unsafe, getFloatAcquire_name, getFloat_signature, F_R) \
+ do_intrinsic(_getDoubleAcquire, jdk_internal_misc_Unsafe, getDoubleAcquire_name, getDouble_signature, F_R) \
+ do_intrinsic(_putObjectRelease, jdk_internal_misc_Unsafe, putObjectRelease_name, putObject_signature, F_R) \
+ do_intrinsic(_putBooleanRelease, jdk_internal_misc_Unsafe, putBooleanRelease_name, putBoolean_signature, F_R) \
+ do_intrinsic(_putByteRelease, jdk_internal_misc_Unsafe, putByteRelease_name, putByte_signature, F_R) \
+ do_intrinsic(_putShortRelease, jdk_internal_misc_Unsafe, putShortRelease_name, putShort_signature, F_R) \
+ do_intrinsic(_putCharRelease, jdk_internal_misc_Unsafe, putCharRelease_name, putChar_signature, F_R) \
+ do_intrinsic(_putIntRelease, jdk_internal_misc_Unsafe, putIntRelease_name, putInt_signature, F_R) \
+ do_intrinsic(_putLongRelease, jdk_internal_misc_Unsafe, putLongRelease_name, putLong_signature, F_R) \
+ do_intrinsic(_putFloatRelease, jdk_internal_misc_Unsafe, putFloatRelease_name, putFloat_signature, F_R) \
+ do_intrinsic(_putDoubleRelease, jdk_internal_misc_Unsafe, putDoubleRelease_name, putDouble_signature, F_R) \
+ \
do_name(getShortUnaligned_name,"getShortUnaligned") do_name(putShortUnaligned_name,"putShortUnaligned") \
do_name(getCharUnaligned_name,"getCharUnaligned") do_name(putCharUnaligned_name,"putCharUnaligned") \
do_name(getIntUnaligned_name,"getIntUnaligned") do_name(putIntUnaligned_name,"putIntUnaligned") \
@@ -1197,24 +1255,68 @@
do_intrinsic(_putDouble_raw, jdk_internal_misc_Unsafe, putDouble_name, putDouble_raw_signature, F_R) \
do_intrinsic(_putAddress_raw, jdk_internal_misc_Unsafe, putAddress_name, putAddress_raw_signature, F_R) \
\
- do_intrinsic(_compareAndSwapObject, jdk_internal_misc_Unsafe, compareAndSwapObject_name, compareAndSwapObject_signature, F_R) \
- do_name( compareAndSwapObject_name, "compareAndSwapObject") \
- do_signature(compareAndSwapObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
- do_intrinsic(_compareAndSwapLong, jdk_internal_misc_Unsafe, compareAndSwapLong_name, compareAndSwapLong_signature, F_R) \
- do_name( compareAndSwapLong_name, "compareAndSwapLong") \
- do_signature(compareAndSwapLong_signature, "(Ljava/lang/Object;JJJ)Z") \
- do_intrinsic(_compareAndSwapInt, jdk_internal_misc_Unsafe, compareAndSwapInt_name, compareAndSwapInt_signature, F_R) \
- do_name( compareAndSwapInt_name, "compareAndSwapInt") \
- do_signature(compareAndSwapInt_signature, "(Ljava/lang/Object;JII)Z") \
- do_intrinsic(_putOrderedObject, jdk_internal_misc_Unsafe, putOrderedObject_name, putOrderedObject_signature, F_R) \
- do_name( putOrderedObject_name, "putOrderedObject") \
- do_alias( putOrderedObject_signature, /*(LObject;JLObject;)V*/ putObject_signature) \
- do_intrinsic(_putOrderedLong, jdk_internal_misc_Unsafe, putOrderedLong_name, putOrderedLong_signature, F_R) \
- do_name( putOrderedLong_name, "putOrderedLong") \
- do_alias( putOrderedLong_signature, /*(Ljava/lang/Object;JJ)V*/ putLong_signature) \
- do_intrinsic(_putOrderedInt, jdk_internal_misc_Unsafe, putOrderedInt_name, putOrderedInt_signature, F_R) \
- do_name( putOrderedInt_name, "putOrderedInt") \
- do_alias( putOrderedInt_signature, /*(Ljava/lang/Object;JI)V*/ putInt_signature) \
+ do_signature(compareAndSwapObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
+ do_signature(compareAndExchangeObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") \
+ do_signature(compareAndSwapLong_signature, "(Ljava/lang/Object;JJJ)Z") \
+ do_signature(compareAndExchangeLong_signature, "(Ljava/lang/Object;JJJ)J") \
+ do_signature(compareAndSwapInt_signature, "(Ljava/lang/Object;JII)Z") \
+ do_signature(compareAndExchangeInt_signature, "(Ljava/lang/Object;JII)I") \
+ \
+ do_name(compareAndSwapObject_name, "compareAndSwapObject") \
+ do_name(compareAndExchangeObjectVolatile_name, "compareAndExchangeObjectVolatile") \
+ do_name(compareAndExchangeObjectAcquire_name, "compareAndExchangeObjectAcquire") \
+ do_name(compareAndExchangeObjectRelease_name, "compareAndExchangeObjectRelease") \
+ do_name(compareAndSwapLong_name, "compareAndSwapLong") \
+ do_name(compareAndExchangeLongVolatile_name, "compareAndExchangeLongVolatile") \
+ do_name(compareAndExchangeLongAcquire_name, "compareAndExchangeLongAcquire") \
+ do_name(compareAndExchangeLongRelease_name, "compareAndExchangeLongRelease") \
+ do_name(compareAndSwapInt_name, "compareAndSwapInt") \
+ do_name(compareAndExchangeIntVolatile_name, "compareAndExchangeIntVolatile") \
+ do_name(compareAndExchangeIntAcquire_name, "compareAndExchangeIntAcquire") \
+ do_name(compareAndExchangeIntRelease_name, "compareAndExchangeIntRelease") \
+ \
+ do_name(weakCompareAndSwapObject_name, "weakCompareAndSwapObject") \
+ do_name(weakCompareAndSwapObjectAcquire_name, "weakCompareAndSwapObjectAcquire") \
+ do_name(weakCompareAndSwapObjectRelease_name, "weakCompareAndSwapObjectRelease") \
+ do_name(weakCompareAndSwapLong_name, "weakCompareAndSwapLong") \
+ do_name(weakCompareAndSwapLongAcquire_name, "weakCompareAndSwapLongAcquire") \
+ do_name(weakCompareAndSwapLongRelease_name, "weakCompareAndSwapLongRelease") \
+ do_name(weakCompareAndSwapInt_name, "weakCompareAndSwapInt") \
+ do_name(weakCompareAndSwapIntAcquire_name, "weakCompareAndSwapIntAcquire") \
+ do_name(weakCompareAndSwapIntRelease_name, "weakCompareAndSwapIntRelease") \
+ \
+ do_intrinsic(_compareAndSwapObject, jdk_internal_misc_Unsafe, compareAndSwapObject_name, compareAndSwapObject_signature, F_RN) \
+ do_intrinsic(_compareAndExchangeObjectVolatile, jdk_internal_misc_Unsafe, compareAndExchangeObjectVolatile_name, compareAndExchangeObject_signature, F_RN) \
+ do_intrinsic(_compareAndExchangeObjectAcquire, jdk_internal_misc_Unsafe, compareAndExchangeObjectAcquire_name, compareAndExchangeObject_signature, F_R) \
+ do_intrinsic(_compareAndExchangeObjectRelease, jdk_internal_misc_Unsafe, compareAndExchangeObjectRelease_name, compareAndExchangeObject_signature, F_R) \
+ do_intrinsic(_compareAndSwapLong, jdk_internal_misc_Unsafe, compareAndSwapLong_name, compareAndSwapLong_signature, F_RN) \
+ do_intrinsic(_compareAndExchangeLongVolatile, jdk_internal_misc_Unsafe, compareAndExchangeLongVolatile_name, compareAndExchangeLong_signature, F_RN) \
+ do_intrinsic(_compareAndExchangeLongAcquire, jdk_internal_misc_Unsafe, compareAndExchangeLongAcquire_name, compareAndExchangeLong_signature, F_R) \
+ do_intrinsic(_compareAndExchangeLongRelease, jdk_internal_misc_Unsafe, compareAndExchangeLongRelease_name, compareAndExchangeLong_signature, F_R) \
+ do_intrinsic(_compareAndSwapInt, jdk_internal_misc_Unsafe, compareAndSwapInt_name, compareAndSwapInt_signature, F_RN) \
+ do_intrinsic(_compareAndExchangeIntVolatile, jdk_internal_misc_Unsafe, compareAndExchangeIntVolatile_name, compareAndExchangeInt_signature, F_RN) \
+ do_intrinsic(_compareAndExchangeIntAcquire, jdk_internal_misc_Unsafe, compareAndExchangeIntAcquire_name, compareAndExchangeInt_signature, F_R) \
+ do_intrinsic(_compareAndExchangeIntRelease, jdk_internal_misc_Unsafe, compareAndExchangeIntRelease_name, compareAndExchangeInt_signature, F_R) \
+ \
+ do_intrinsic(_weakCompareAndSwapObject, jdk_internal_misc_Unsafe, weakCompareAndSwapObject_name, compareAndSwapObject_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapObjectAcquire, jdk_internal_misc_Unsafe, weakCompareAndSwapObjectAcquire_name, compareAndSwapObject_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapObjectRelease, jdk_internal_misc_Unsafe, weakCompareAndSwapObjectRelease_name, compareAndSwapObject_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapLong, jdk_internal_misc_Unsafe, weakCompareAndSwapLong_name, compareAndSwapLong_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapLongAcquire, jdk_internal_misc_Unsafe, weakCompareAndSwapLongAcquire_name, compareAndSwapLong_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapLongRelease, jdk_internal_misc_Unsafe, weakCompareAndSwapLongRelease_name, compareAndSwapLong_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapInt, jdk_internal_misc_Unsafe, weakCompareAndSwapInt_name, compareAndSwapInt_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapIntAcquire, jdk_internal_misc_Unsafe, weakCompareAndSwapIntAcquire_name, compareAndSwapInt_signature, F_R) \
+ do_intrinsic(_weakCompareAndSwapIntRelease, jdk_internal_misc_Unsafe, weakCompareAndSwapIntRelease_name, compareAndSwapInt_signature, F_R) \
+ \
+ do_intrinsic(_putOrderedObject, jdk_internal_misc_Unsafe, putOrderedObject_name, putOrderedObject_signature, F_RN) \
+ do_name( putOrderedObject_name, "putOrderedObject") \
+ do_alias( putOrderedObject_signature, /*(LObject;JLObject;)V*/ putObject_signature) \
+ do_intrinsic(_putOrderedLong, jdk_internal_misc_Unsafe, putOrderedLong_name, putOrderedLong_signature, F_RN) \
+ do_name( putOrderedLong_name, "putOrderedLong") \
+ do_alias( putOrderedLong_signature, /*(Ljava/lang/Object;JJ)V*/ putLong_signature) \
+ do_intrinsic(_putOrderedInt, jdk_internal_misc_Unsafe, putOrderedInt_name, putOrderedInt_signature, F_RN) \
+ do_name( putOrderedInt_name, "putOrderedInt") \
+ do_alias( putOrderedInt_signature, /*(Ljava/lang/Object;JI)V*/ putInt_signature) \
\
do_intrinsic(_getAndAddInt, jdk_internal_misc_Unsafe, getAndAddInt_name, getAndAddInt_signature, F_R) \
do_name( getAndAddInt_name, "getAndAddInt") \
--- a/hotspot/src/share/vm/jvmci/commandLineFlagConstraintsJVMCI.cpp Wed Feb 17 14:06:45 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "jvmci/commandLineFlagConstraintsJVMCI.hpp"
-#include "runtime/arguments.hpp"
-#include "runtime/globals.hpp"
-#include "utilities/defaultStream.hpp"
-
-Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(bool value, bool verbose) {
- if (!EnableJVMCI) {
- if (verbose == true) {
- jio_fprintf(defaultStream::error_stream(), "EnableJVMCI must be enabled\n");
- }
- return Flag::VIOLATES_CONSTRAINT;
- } else {
- return Flag::SUCCESS;
- }
-}
-
-Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(intx value, bool verbose) {
- if (!EnableJVMCI) {
- if (verbose == true) {
- jio_fprintf(defaultStream::error_stream(), "EnableJVMCI must be enabled\n");
- }
- return Flag::VIOLATES_CONSTRAINT;
- } else {
- return Flag::SUCCESS;
- }
-}
--- a/hotspot/src/share/vm/jvmci/commandLineFlagConstraintsJVMCI.hpp Wed Feb 17 14:06:45 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_JVMCI_COMMANDLINEFLAGCONSTRAINTSJVMCI_HPP
-#define SHARE_VM_JVMCI_COMMANDLINEFLAGCONSTRAINTSJVMCI_HPP
-
-#include "runtime/globals.hpp"
-#include "utilities/globalDefinitions.hpp"
-
-/*
- * Here we have JVMCI arguments constraints functions, which are called automatically
- * whenever flag's value changes. If the constraint fails the function should return
- * an appropriate error value.
- */
-
-Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(bool value, bool verbose);
-Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(intx value, bool verbose);
-
-#endif /* SHARE_VM_JVMCI_COMMANDLINEFLAGCONSTRAINTSJVMCI_HPP */
--- a/hotspot/src/share/vm/jvmci/jvmci_globals.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmci_globals.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -24,6 +24,8 @@
#include "precompiled.hpp"
#include "jvmci/jvmci_globals.hpp"
+#include "utilities/defaultStream.hpp"
+#include "runtime/globals_extension.hpp"
JVMCI_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
MATERIALIZE_PD_DEVELOPER_FLAG, \
@@ -34,3 +36,185 @@
MATERIALIZE_NOTPRODUCT_FLAG,
IGNORE_RANGE, \
IGNORE_CONSTRAINT)
+
+#define JVMCI_IGNORE_FLAG_FOUR_PARAM(type, name, value, doc)
+#define JVMCI_IGNORE_FLAG_THREE_PARAM(type, name, doc)
+
+// Return true if jvmci flags are consistent.
+bool JVMCIGlobals::check_jvmci_flags_are_consistent() {
+ if (EnableJVMCI) {
+ return true;
+ }
+
+ // "FLAG_IS_DEFAULT" fail count.
+ int fail_count = 0;
+ // Number of "FLAG_IS_DEFAULT" fails that should be skipped before code
+ // detect real consistency failure.
+ int skip_fail_count;
+
+ // EnableJVMCI flag is false here.
+ // If any other flag is changed, consistency check should fail.
+ // JVMCI_FLAGS macros added below can handle all JVMCI flags automatically.
+ // But it contains check for EnableJVMCI flag too, which is required to be
+ // skipped. This can't be handled easily!
+ // So the code looks for at-least two flag changes to detect consistency
+ // failure when EnableJVMCI flag is changed.
+ // Otherwise one flag change is sufficient to detect consistency failure.
+ // Set skip_fail_count to 0 if EnableJVMCI flag is default.
+ // Set skip_fail_count to 1 if EnableJVMCI flag is changed.
+ // This value will be used to skip fails in macro expanded code later.
+ if (!FLAG_IS_DEFAULT(EnableJVMCI)) {
+ skip_fail_count = 1;
+ } else {
+ skip_fail_count = 0;
+ }
+
+#define EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(FLAG) \
+ if (!FLAG_IS_DEFAULT(FLAG)) { \
+ fail_count++; \
+ if (fail_count > skip_fail_count) { \
+ return false; \
+ } \
+ }
+
+#define JVMCI_DIAGNOSTIC_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name)
+#define JVMCI_EXPERIMENTAL_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name)
+
+ // Check consistency of diagnostic flags if UnlockDiagnosticVMOptions is true
+ // or not default. UnlockDiagnosticVMOptions is default true in debug builds.
+ if (UnlockDiagnosticVMOptions || !FLAG_IS_DEFAULT(UnlockDiagnosticVMOptions)) {
+ JVMCI_FLAGS(JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_DIAGNOSTIC_FLAG_VALUE_CHANGED_CHECK_CODE, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+ }
+
+ // Check consistency of experimental flags if UnlockExperimentalVMOptions is
+ // true or not default.
+ if (UnlockExperimentalVMOptions || !FLAG_IS_DEFAULT(UnlockExperimentalVMOptions)) {
+ JVMCI_FLAGS(JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_EXPERIMENTAL_FLAG_VALUE_CHANGED_CHECK_CODE, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+ }
+
+#ifndef PRODUCT
+#define JVMCI_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name)
+#define JVMCI_PD_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name)
+#define JVMCI_NOTPRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name)
+#else
+#define JVMCI_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc)
+#define JVMCI_PD_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, doc)
+#define JVMCI_NOTPRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc)
+#endif
+
+#define JVMCI_PD_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name)
+#define JVMCI_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name)
+
+ JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE, \
+ JVMCI_PD_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE, \
+ JVMCI_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE, \
+ JVMCI_PD_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_NOTPRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+
+#undef EMIT_FLAG_VALUE_CHANGED_CHECK_CODE
+#undef JVMCI_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE
+#undef JVMCI_PD_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE
+#undef JVMCI_NOTPRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE
+#undef JVMCI_DIAGNOSTIC_FLAG_VALUE_CHANGED_CHECK_CODE
+#undef JVMCI_PD_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE
+#undef JVMCI_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE
+#undef JVMCI_EXPERIMENTAL_FLAG_VALUE_CHANGED_CHECK_CODE
+
+ return true;
+}
+
+// Print jvmci arguments inconsistency error message.
+void JVMCIGlobals::print_jvmci_args_inconsistency_error_message() {
+ const char* error_msg = "Improperly specified VM option '%s'\n";
+ jio_fprintf(defaultStream::error_stream(), "EnableJVMCI must be enabled\n");
+
+#define EMIT_CHECK_PRINT_ERR_MSG_CODE(FLAG) \
+ if (!FLAG_IS_DEFAULT(FLAG)) { \
+ if (strcmp(#FLAG, "EnableJVMCI")) { \
+ jio_fprintf(defaultStream::error_stream(), error_msg, #FLAG); \
+ } \
+ }
+
+#define JVMCI_DIAGNOSTIC_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name)
+#define JVMCI_EXPERIMENTAL_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name)
+
+ if (UnlockDiagnosticVMOptions || !FLAG_IS_DEFAULT(UnlockDiagnosticVMOptions)) {
+ JVMCI_FLAGS(JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_DIAGNOSTIC_FLAG_CHECK_PRINT_ERR_MSG_CODE, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+ }
+
+ if (UnlockExperimentalVMOptions || !FLAG_IS_DEFAULT(UnlockExperimentalVMOptions)) {
+ JVMCI_FLAGS(JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_THREE_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_EXPERIMENTAL_FLAG_CHECK_PRINT_ERR_MSG_CODE, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+ }
+
+#ifndef PRODUCT
+#define JVMCI_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name)
+#define JVMCI_PD_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name)
+#define JVMCI_NOTPRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name)
+#else
+#define JVMCI_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc)
+#define JVMCI_PD_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, doc)
+#define JVMCI_NOTPRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc)
+#endif
+
+#define JVMCI_PD_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name)
+#define JVMCI_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name)
+
+ JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE, \
+ JVMCI_PD_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE, \
+ JVMCI_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE, \
+ JVMCI_PD_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_IGNORE_FLAG_FOUR_PARAM, \
+ JVMCI_NOTPRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE, \
+ IGNORE_RANGE, \
+ IGNORE_CONSTRAINT)
+
+#undef EMIT_CHECK_PRINT_ERR_MSG_CODE
+#undef JVMCI_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE
+#undef JVMCI_PD_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE
+#undef JVMCI_NOTPRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE
+#undef JVMCI_PD_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE
+#undef JVMCI_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE
+#undef JVMCI_DIAGNOSTIC_FLAG_CHECK_PRINT_ERR_MSG_CODE
+#undef JVMCI_EXPERIMENTAL_FLAG_CHECK_PRINT_ERR_MSG_CODE
+
+}
+
+#undef JVMCI_IGNORE_FLAG_FOUR_PARAM
+#undef JVMCI_IGNORE_FLAG_THREE_PARAM
--- a/hotspot/src/share/vm/jvmci/jvmci_globals.hpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmci_globals.hpp Wed Feb 24 12:38:50 2016 +0000
@@ -39,29 +39,23 @@
\
experimental(bool, UseJVMCICompiler, false, \
"Use JVMCI as the default compiler") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(bool, BootstrapJVMCI, false, \
"Bootstrap JVMCI before running Java main method") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(bool, PrintBootstrap, true, \
"Print JVMCI bootstrap progress and summary") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(intx, JVMCIThreads, 1, \
"Force number of JVMCI compiler threads to use") \
range(1, max_jint) \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(intx, JVMCIHostThreads, 1, \
"Force number of compiler threads for JVMCI host compiler") \
range(1, max_jint) \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(bool, CodeInstallSafepointChecks, true, \
"Perform explicit safepoint checks while installing code") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
NOT_COMPILER2(product(intx, MaxVectorSize, 64, \
"Max vector size in bytes, " \
@@ -74,28 +68,22 @@
"Trace level for JVMCI: " \
"1 means emit a message for each CompilerToVM call," \
"levels greater than 1 provide progressively greater detail") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(intx, JVMCICounterSize, 0, \
"Reserved size for benchmark counters") \
range(0, max_jint) \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(bool, JVMCICountersExcludeCompiler, true, \
"Exclude JVMCI compiler threads from benchmark counters") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
develop(bool, JVMCIUseFastLocking, true, \
"Use fast inlined locking code") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
experimental(intx, JVMCINMethodSizeLimit, (80*K)*wordSize, \
"Maximum size of a compiled method.") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
\
develop(bool, TraceUncollectedSpeculations, false, \
- "Print message when a failed speculation was not collected") \
- constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \
+ "Print message when a failed speculation was not collected")
// Read default values for JVMCI globals
@@ -110,4 +98,11 @@
IGNORE_RANGE, \
IGNORE_CONSTRAINT)
+class JVMCIGlobals {
+ public:
+ // Return true if jvmci flags are consistent.
+ static bool check_jvmci_flags_are_consistent();
+ // Print jvmci arguments inconsistency error message.
+ static void print_jvmci_args_inconsistency_error_message();
+};
#endif // SHARE_VM_JVMCI_JVMCIGLOBALS_HPP
--- a/hotspot/src/share/vm/opto/c2compiler.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -243,14 +243,72 @@
case vmIntrinsics::_reverseBytes_l:
if (!Matcher::match_rule_supported(Op_ReverseBytesL)) return false;
break;
+
+ /* CompareAndSwap, Object: */
case vmIntrinsics::_compareAndSwapObject:
#ifdef _LP64
+ if ( UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapN)) return false;
if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapP)) return false;
+#else
+ if (!Matcher::match_rule_supported(Op_CompareAndSwapP)) return false;
#endif
break;
+ case vmIntrinsics::_weakCompareAndSwapObject:
+ case vmIntrinsics::_weakCompareAndSwapObjectAcquire:
+ case vmIntrinsics::_weakCompareAndSwapObjectRelease:
+#ifdef _LP64
+ if ( UseCompressedOops && !Matcher::match_rule_supported(Op_WeakCompareAndSwapN)) return false;
+ if (!UseCompressedOops && !Matcher::match_rule_supported(Op_WeakCompareAndSwapP)) return false;
+#else
+ if (!Matcher::match_rule_supported(Op_WeakCompareAndSwapP)) return false;
+#endif
+ break;
+ /* CompareAndSwap, Long: */
case vmIntrinsics::_compareAndSwapLong:
if (!Matcher::match_rule_supported(Op_CompareAndSwapL)) return false;
break;
+ case vmIntrinsics::_weakCompareAndSwapLong:
+ case vmIntrinsics::_weakCompareAndSwapLongAcquire:
+ case vmIntrinsics::_weakCompareAndSwapLongRelease:
+ if (!Matcher::match_rule_supported(Op_WeakCompareAndSwapL)) return false;
+ break;
+
+ /* CompareAndSwap, Int: */
+ case vmIntrinsics::_compareAndSwapInt:
+ if (!Matcher::match_rule_supported(Op_CompareAndSwapI)) return false;
+ break;
+ case vmIntrinsics::_weakCompareAndSwapInt:
+ case vmIntrinsics::_weakCompareAndSwapIntAcquire:
+ case vmIntrinsics::_weakCompareAndSwapIntRelease:
+ if (!Matcher::match_rule_supported(Op_WeakCompareAndSwapL)) return false;
+ break;
+
+ /* CompareAndExchange, Object: */
+ case vmIntrinsics::_compareAndExchangeObjectVolatile:
+ case vmIntrinsics::_compareAndExchangeObjectAcquire:
+ case vmIntrinsics::_compareAndExchangeObjectRelease:
+#ifdef _LP64
+ if ( UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndExchangeN)) return false;
+ if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndExchangeP)) return false;
+#else
+ if (!Matcher::match_rule_supported(Op_CompareAndExchangeP)) return false;
+#endif
+ break;
+
+ /* CompareAndExchange, Long: */
+ case vmIntrinsics::_compareAndExchangeLongVolatile:
+ case vmIntrinsics::_compareAndExchangeLongAcquire:
+ case vmIntrinsics::_compareAndExchangeLongRelease:
+ if (!Matcher::match_rule_supported(Op_CompareAndExchangeL)) return false;
+ break;
+
+ /* CompareAndExchange, Int: */
+ case vmIntrinsics::_compareAndExchangeIntVolatile:
+ case vmIntrinsics::_compareAndExchangeIntAcquire:
+ case vmIntrinsics::_compareAndExchangeIntRelease:
+ if (!Matcher::match_rule_supported(Op_CompareAndExchangeI)) return false;
+ break;
+
case vmIntrinsics::_getAndAddInt:
if (!Matcher::match_rule_supported(Op_GetAndAddI)) return false;
break;
@@ -382,6 +440,42 @@
case vmIntrinsics::_putLongVolatile:
case vmIntrinsics::_putFloatVolatile:
case vmIntrinsics::_putDoubleVolatile:
+ case vmIntrinsics::_getObjectAcquire:
+ case vmIntrinsics::_getBooleanAcquire:
+ case vmIntrinsics::_getByteAcquire:
+ case vmIntrinsics::_getShortAcquire:
+ case vmIntrinsics::_getCharAcquire:
+ case vmIntrinsics::_getIntAcquire:
+ case vmIntrinsics::_getLongAcquire:
+ case vmIntrinsics::_getFloatAcquire:
+ case vmIntrinsics::_getDoubleAcquire:
+ case vmIntrinsics::_putObjectRelease:
+ case vmIntrinsics::_putBooleanRelease:
+ case vmIntrinsics::_putByteRelease:
+ case vmIntrinsics::_putShortRelease:
+ case vmIntrinsics::_putCharRelease:
+ case vmIntrinsics::_putIntRelease:
+ case vmIntrinsics::_putLongRelease:
+ case vmIntrinsics::_putFloatRelease:
+ case vmIntrinsics::_putDoubleRelease:
+ case vmIntrinsics::_getObjectOpaque:
+ case vmIntrinsics::_getBooleanOpaque:
+ case vmIntrinsics::_getByteOpaque:
+ case vmIntrinsics::_getShortOpaque:
+ case vmIntrinsics::_getCharOpaque:
+ case vmIntrinsics::_getIntOpaque:
+ case vmIntrinsics::_getLongOpaque:
+ case vmIntrinsics::_getFloatOpaque:
+ case vmIntrinsics::_getDoubleOpaque:
+ case vmIntrinsics::_putObjectOpaque:
+ case vmIntrinsics::_putBooleanOpaque:
+ case vmIntrinsics::_putByteOpaque:
+ case vmIntrinsics::_putShortOpaque:
+ case vmIntrinsics::_putCharOpaque:
+ case vmIntrinsics::_putIntOpaque:
+ case vmIntrinsics::_putLongOpaque:
+ case vmIntrinsics::_putFloatOpaque:
+ case vmIntrinsics::_putDoubleOpaque:
case vmIntrinsics::_getShortUnaligned:
case vmIntrinsics::_getCharUnaligned:
case vmIntrinsics::_getIntUnaligned:
@@ -390,7 +484,6 @@
case vmIntrinsics::_putCharUnaligned:
case vmIntrinsics::_putIntUnaligned:
case vmIntrinsics::_putLongUnaligned:
- case vmIntrinsics::_compareAndSwapInt:
case vmIntrinsics::_putOrderedObject:
case vmIntrinsics::_putOrderedInt:
case vmIntrinsics::_putOrderedLong:
--- a/hotspot/src/share/vm/opto/classes.hpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/opto/classes.hpp Wed Feb 24 12:38:50 2016 +0000
@@ -85,6 +85,14 @@
macro(CompareAndSwapL)
macro(CompareAndSwapP)
macro(CompareAndSwapN)
+macro(WeakCompareAndSwapI)
+macro(WeakCompareAndSwapL)
+macro(WeakCompareAndSwapP)
+macro(WeakCompareAndSwapN)
+macro(CompareAndExchangeI)
+macro(CompareAndExchangeL)
+macro(CompareAndExchangeP)
+macro(CompareAndExchangeN)
macro(GetAndAddI)
macro(GetAndAddL)
macro(GetAndSetI)
--- a/hotspot/src/share/vm/opto/compile.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/opto/compile.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -88,7 +88,27 @@
// Return the index at which m must be inserted (or already exists).
// The sort order is by the address of the ciMethod, with is_virtual as minor key.
-int Compile::intrinsic_insertion_index(ciMethod* m, bool is_virtual) {
+class IntrinsicDescPair {
+ private:
+ ciMethod* _m;
+ bool _is_virtual;
+ public:
+ IntrinsicDescPair(ciMethod* m, bool is_virtual) : _m(m), _is_virtual(is_virtual) {}
+ static int compare(IntrinsicDescPair* const& key, CallGenerator* const& elt) {
+ ciMethod* m= elt->method();
+ ciMethod* key_m = key->_m;
+ if (key_m < m) return -1;
+ else if (key_m > m) return 1;
+ else {
+ bool is_virtual = elt->is_virtual();
+ bool key_virtual = key->_is_virtual;
+ if (key_virtual < is_virtual) return -1;
+ else if (key_virtual > is_virtual) return 1;
+ else return 0;
+ }
+ }
+};
+int Compile::intrinsic_insertion_index(ciMethod* m, bool is_virtual, bool& found) {
#ifdef ASSERT
for (int i = 1; i < _intrinsics->length(); i++) {
CallGenerator* cg1 = _intrinsics->at(i-1);
@@ -99,63 +119,28 @@
"compiler intrinsics list must stay sorted");
}
#endif
- // Binary search sorted list, in decreasing intervals [lo, hi].
- int lo = 0, hi = _intrinsics->length()-1;
- while (lo <= hi) {
- int mid = (uint)(hi + lo) / 2;
- ciMethod* mid_m = _intrinsics->at(mid)->method();
- if (m < mid_m) {
- hi = mid-1;
- } else if (m > mid_m) {
- lo = mid+1;
- } else {
- // look at minor sort key
- bool mid_virt = _intrinsics->at(mid)->is_virtual();
- if (is_virtual < mid_virt) {
- hi = mid-1;
- } else if (is_virtual > mid_virt) {
- lo = mid+1;
- } else {
- return mid; // exact match
- }
- }
- }
- return lo; // inexact match
+ IntrinsicDescPair pair(m, is_virtual);
+ return _intrinsics->find_sorted<IntrinsicDescPair*, IntrinsicDescPair::compare>(&pair, found);
}
void Compile::register_intrinsic(CallGenerator* cg) {
if (_intrinsics == NULL) {
_intrinsics = new (comp_arena())GrowableArray<CallGenerator*>(comp_arena(), 60, 0, NULL);
}
- // This code is stolen from ciObjectFactory::insert.
- // Really, GrowableArray should have methods for
- // insert_at, remove_at, and binary_search.
int len = _intrinsics->length();
- int index = intrinsic_insertion_index(cg->method(), cg->is_virtual());
- if (index == len) {
- _intrinsics->append(cg);
- } else {
-#ifdef ASSERT
- CallGenerator* oldcg = _intrinsics->at(index);
- assert(oldcg->method() != cg->method() || oldcg->is_virtual() != cg->is_virtual(), "don't register twice");
-#endif
- _intrinsics->append(_intrinsics->at(len-1));
- int pos;
- for (pos = len-2; pos >= index; pos--) {
- _intrinsics->at_put(pos+1,_intrinsics->at(pos));
- }
- _intrinsics->at_put(index, cg);
- }
+ bool found = false;
+ int index = intrinsic_insertion_index(cg->method(), cg->is_virtual(), found);
+ assert(!found, "registering twice");
+ _intrinsics->insert_before(index, cg);
assert(find_intrinsic(cg->method(), cg->is_virtual()) == cg, "registration worked");
}
CallGenerator* Compile::find_intrinsic(ciMethod* m, bool is_virtual) {
assert(m->is_loaded(), "don't try this on unloaded methods");
if (_intrinsics != NULL) {
- int index = intrinsic_insertion_index(m, is_virtual);
- if (index < _intrinsics->length()
- && _intrinsics->at(index)->method() == m
- && _intrinsics->at(index)->is_virtual() == is_virtual) {
+ bool found = false;
+ int index = intrinsic_insertion_index(m, is_virtual, found);
+ if (found) {
return _intrinsics->at(index);
}
}
@@ -2801,6 +2786,14 @@
case Op_CompareAndSwapL:
case Op_CompareAndSwapP:
case Op_CompareAndSwapN:
+ case Op_WeakCompareAndSwapI:
+ case Op_WeakCompareAndSwapL:
+ case Op_WeakCompareAndSwapP:
+ case Op_WeakCompareAndSwapN:
+ case Op_CompareAndExchangeI:
+ case Op_CompareAndExchangeL:
+ case Op_CompareAndExchangeP:
+ case Op_CompareAndExchangeN:
case Op_GetAndAddI:
case Op_GetAndAddL:
case Op_GetAndSetI:
--- a/hotspot/src/share/vm/opto/compile.hpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/opto/compile.hpp Wed Feb 24 12:38:50 2016 +0000
@@ -1250,7 +1250,7 @@
// Intrinsic setup.
void register_library_intrinsics(); // initializer
CallGenerator* make_vm_intrinsic(ciMethod* m, bool is_virtual); // constructor
- int intrinsic_insertion_index(ciMethod* m, bool is_virtual); // helper
+ int intrinsic_insertion_index(ciMethod* m, bool is_virtual, bool& found); // helper
CallGenerator* find_intrinsic(ciMethod* m, bool is_virtual); // query fn
void register_intrinsic(CallGenerator* cg); // update fn
--- a/hotspot/src/share/vm/opto/escape.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/opto/escape.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -490,6 +490,8 @@
}
break;
}
+ case Op_CompareAndExchangeP:
+ case Op_CompareAndExchangeN:
case Op_GetAndSetP:
case Op_GetAndSetN: {
add_objload_to_connection_graph(n, delayed_worklist);
@@ -499,6 +501,8 @@
case Op_StoreN:
case Op_StoreNKlass:
case Op_StorePConditional:
+ case Op_WeakCompareAndSwapP:
+ case Op_WeakCompareAndSwapN:
case Op_CompareAndSwapP:
case Op_CompareAndSwapN: {
Node* adr = n->in(MemNode::Address);
@@ -698,8 +702,12 @@
case Op_StoreN:
case Op_StoreNKlass:
case Op_StorePConditional:
+ case Op_CompareAndExchangeP:
+ case Op_CompareAndExchangeN:
case Op_CompareAndSwapP:
case Op_CompareAndSwapN:
+ case Op_WeakCompareAndSwapP:
+ case Op_WeakCompareAndSwapN:
case Op_GetAndSetP:
case Op_GetAndSetN: {
Node* adr = n->in(MemNode::Address);
--- a/hotspot/src/share/vm/opto/library_call.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -241,7 +241,9 @@
// Generates the guards that check whether the result of
// Unsafe.getObject should be recorded in an SATB log buffer.
void insert_pre_barrier(Node* base_oop, Node* offset, Node* pre_val, bool need_mem_bar);
- bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile, bool is_unaligned);
+
+ typedef enum { Relaxed, Opaque, Volatile, Acquire, Release } AccessKind;
+ bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, AccessKind kind, bool is_unaligned);
static bool klass_needs_init_guard(Node* kls);
bool inline_unsafe_allocate();
bool inline_unsafe_copyMemory();
@@ -274,9 +276,10 @@
JVMState* arraycopy_restore_alloc_state(AllocateArrayNode* alloc, int& saved_reexecute_sp);
void arraycopy_move_allocation_here(AllocateArrayNode* alloc, Node* dest, JVMState* saved_jvms, int saved_reexecute_sp);
- typedef enum { LS_xadd, LS_xchg, LS_cmpxchg } LoadStoreKind;
- bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind);
- bool inline_unsafe_ordered_store(BasicType type);
+ typedef enum { LS_get_add, LS_get_set, LS_cmp_swap, LS_cmp_swap_weak, LS_cmp_exchange } LoadStoreKind;
+ MemNode::MemOrd access_kind_to_memord_LS(AccessKind access_kind, bool is_store);
+ MemNode::MemOrd access_kind_to_memord(AccessKind access_kind);
+ bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind, AccessKind access_kind);
bool inline_unsafe_fence(vmIntrinsics::ID id);
bool inline_fp_conversions(vmIntrinsics::ID id);
bool inline_number_methods(vmIntrinsics::ID id);
@@ -553,86 +556,147 @@
case vmIntrinsics::_inflateStringC:
case vmIntrinsics::_inflateStringB: return inline_string_copy(!is_compress);
- case vmIntrinsics::_getObject: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, !is_volatile, false);
- case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, !is_volatile, false);
- case vmIntrinsics::_getByte: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, !is_volatile, false);
- case vmIntrinsics::_getShort: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, !is_volatile, false);
- case vmIntrinsics::_getChar: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, !is_volatile, false);
- case vmIntrinsics::_getInt: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, !is_volatile, false);
- case vmIntrinsics::_getLong: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, !is_volatile, false);
- case vmIntrinsics::_getFloat: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, !is_volatile, false);
- case vmIntrinsics::_getDouble: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, !is_volatile, false);
- case vmIntrinsics::_putObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, !is_volatile, false);
- case vmIntrinsics::_putBoolean: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, !is_volatile, false);
- case vmIntrinsics::_putByte: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, !is_volatile, false);
- case vmIntrinsics::_putShort: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, !is_volatile, false);
- case vmIntrinsics::_putChar: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, !is_volatile, false);
- case vmIntrinsics::_putInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, !is_volatile, false);
- case vmIntrinsics::_putLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, !is_volatile, false);
- case vmIntrinsics::_putFloat: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, !is_volatile, false);
- case vmIntrinsics::_putDouble: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, !is_volatile, false);
-
- case vmIntrinsics::_getByte_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_BYTE, !is_volatile, false);
- case vmIntrinsics::_getShort_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_SHORT, !is_volatile, false);
- case vmIntrinsics::_getChar_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_CHAR, !is_volatile, false);
- case vmIntrinsics::_getInt_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_INT, !is_volatile, false);
- case vmIntrinsics::_getLong_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_LONG, !is_volatile, false);
- case vmIntrinsics::_getFloat_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_FLOAT, !is_volatile, false);
- case vmIntrinsics::_getDouble_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_DOUBLE, !is_volatile, false);
- case vmIntrinsics::_getAddress_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_ADDRESS, !is_volatile, false);
-
- case vmIntrinsics::_putByte_raw: return inline_unsafe_access( is_native_ptr, is_store, T_BYTE, !is_volatile, false);
- case vmIntrinsics::_putShort_raw: return inline_unsafe_access( is_native_ptr, is_store, T_SHORT, !is_volatile, false);
- case vmIntrinsics::_putChar_raw: return inline_unsafe_access( is_native_ptr, is_store, T_CHAR, !is_volatile, false);
- case vmIntrinsics::_putInt_raw: return inline_unsafe_access( is_native_ptr, is_store, T_INT, !is_volatile, false);
- case vmIntrinsics::_putLong_raw: return inline_unsafe_access( is_native_ptr, is_store, T_LONG, !is_volatile, false);
- case vmIntrinsics::_putFloat_raw: return inline_unsafe_access( is_native_ptr, is_store, T_FLOAT, !is_volatile, false);
- case vmIntrinsics::_putDouble_raw: return inline_unsafe_access( is_native_ptr, is_store, T_DOUBLE, !is_volatile, false);
- case vmIntrinsics::_putAddress_raw: return inline_unsafe_access( is_native_ptr, is_store, T_ADDRESS, !is_volatile, false);
-
- case vmIntrinsics::_getObjectVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, is_volatile, false);
- case vmIntrinsics::_getBooleanVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, is_volatile, false);
- case vmIntrinsics::_getByteVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, is_volatile, false);
- case vmIntrinsics::_getShortVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, is_volatile, false);
- case vmIntrinsics::_getCharVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, is_volatile, false);
- case vmIntrinsics::_getIntVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, is_volatile, false);
- case vmIntrinsics::_getLongVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, is_volatile, false);
- case vmIntrinsics::_getFloatVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, is_volatile, false);
- case vmIntrinsics::_getDoubleVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, is_volatile, false);
-
- case vmIntrinsics::_putObjectVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, is_volatile, false);
- case vmIntrinsics::_putBooleanVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, is_volatile, false);
- case vmIntrinsics::_putByteVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, is_volatile, false);
- case vmIntrinsics::_putShortVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, is_volatile, false);
- case vmIntrinsics::_putCharVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, is_volatile, false);
- case vmIntrinsics::_putIntVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, is_volatile, false);
- case vmIntrinsics::_putLongVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, is_volatile, false);
- case vmIntrinsics::_putFloatVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, is_volatile, false);
- case vmIntrinsics::_putDoubleVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, is_volatile, false);
-
- case vmIntrinsics::_getShortUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, !is_volatile, true);
- case vmIntrinsics::_getCharUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, !is_volatile, true);
- case vmIntrinsics::_getIntUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, !is_volatile, true);
- case vmIntrinsics::_getLongUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, !is_volatile, true);
-
- case vmIntrinsics::_putShortUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, !is_volatile, true);
- case vmIntrinsics::_putCharUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, !is_volatile, true);
- case vmIntrinsics::_putIntUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, !is_volatile, true);
- case vmIntrinsics::_putLongUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, !is_volatile, true);
-
- case vmIntrinsics::_compareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmpxchg);
- case vmIntrinsics::_compareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmpxchg);
- case vmIntrinsics::_compareAndSwapLong: return inline_unsafe_load_store(T_LONG, LS_cmpxchg);
-
- case vmIntrinsics::_putOrderedObject: return inline_unsafe_ordered_store(T_OBJECT);
- case vmIntrinsics::_putOrderedInt: return inline_unsafe_ordered_store(T_INT);
- case vmIntrinsics::_putOrderedLong: return inline_unsafe_ordered_store(T_LONG);
-
- case vmIntrinsics::_getAndAddInt: return inline_unsafe_load_store(T_INT, LS_xadd);
- case vmIntrinsics::_getAndAddLong: return inline_unsafe_load_store(T_LONG, LS_xadd);
- case vmIntrinsics::_getAndSetInt: return inline_unsafe_load_store(T_INT, LS_xchg);
- case vmIntrinsics::_getAndSetLong: return inline_unsafe_load_store(T_LONG, LS_xchg);
- case vmIntrinsics::_getAndSetObject: return inline_unsafe_load_store(T_OBJECT, LS_xchg);
+ case vmIntrinsics::_getObject: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Relaxed, false);
+ case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Relaxed, false);
+ case vmIntrinsics::_getByte: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Relaxed, false);
+ case vmIntrinsics::_getShort: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Relaxed, false);
+ case vmIntrinsics::_getChar: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Relaxed, false);
+ case vmIntrinsics::_getInt: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Relaxed, false);
+ case vmIntrinsics::_getLong: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Relaxed, false);
+ case vmIntrinsics::_getFloat: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Relaxed, false);
+ case vmIntrinsics::_getDouble: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Relaxed, false);
+
+ case vmIntrinsics::_putObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Relaxed, false);
+ case vmIntrinsics::_putBoolean: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Relaxed, false);
+ case vmIntrinsics::_putByte: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Relaxed, false);
+ case vmIntrinsics::_putShort: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Relaxed, false);
+ case vmIntrinsics::_putChar: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Relaxed, false);
+ case vmIntrinsics::_putInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Relaxed, false);
+ case vmIntrinsics::_putLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Relaxed, false);
+ case vmIntrinsics::_putFloat: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Relaxed, false);
+ case vmIntrinsics::_putDouble: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Relaxed, false);
+
+ case vmIntrinsics::_getByte_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_BYTE, Relaxed, false);
+ case vmIntrinsics::_getShort_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_SHORT, Relaxed, false);
+ case vmIntrinsics::_getChar_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_CHAR, Relaxed, false);
+ case vmIntrinsics::_getInt_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_INT, Relaxed, false);
+ case vmIntrinsics::_getLong_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_LONG, Relaxed, false);
+ case vmIntrinsics::_getFloat_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_FLOAT, Relaxed, false);
+ case vmIntrinsics::_getDouble_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_DOUBLE, Relaxed, false);
+ case vmIntrinsics::_getAddress_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_ADDRESS, Relaxed, false);
+
+ case vmIntrinsics::_putByte_raw: return inline_unsafe_access( is_native_ptr, is_store, T_BYTE, Relaxed, false);
+ case vmIntrinsics::_putShort_raw: return inline_unsafe_access( is_native_ptr, is_store, T_SHORT, Relaxed, false);
+ case vmIntrinsics::_putChar_raw: return inline_unsafe_access( is_native_ptr, is_store, T_CHAR, Relaxed, false);
+ case vmIntrinsics::_putInt_raw: return inline_unsafe_access( is_native_ptr, is_store, T_INT, Relaxed, false);
+ case vmIntrinsics::_putLong_raw: return inline_unsafe_access( is_native_ptr, is_store, T_LONG, Relaxed, false);
+ case vmIntrinsics::_putFloat_raw: return inline_unsafe_access( is_native_ptr, is_store, T_FLOAT, Relaxed, false);
+ case vmIntrinsics::_putDouble_raw: return inline_unsafe_access( is_native_ptr, is_store, T_DOUBLE, Relaxed, false);
+ case vmIntrinsics::_putAddress_raw: return inline_unsafe_access( is_native_ptr, is_store, T_ADDRESS, Relaxed, false);
+
+ case vmIntrinsics::_getObjectVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Volatile, false);
+ case vmIntrinsics::_getBooleanVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Volatile, false);
+ case vmIntrinsics::_getByteVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Volatile, false);
+ case vmIntrinsics::_getShortVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Volatile, false);
+ case vmIntrinsics::_getCharVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Volatile, false);
+ case vmIntrinsics::_getIntVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Volatile, false);
+ case vmIntrinsics::_getLongVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Volatile, false);
+ case vmIntrinsics::_getFloatVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Volatile, false);
+ case vmIntrinsics::_getDoubleVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Volatile, false);
+
+ case vmIntrinsics::_putObjectVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Volatile, false);
+ case vmIntrinsics::_putBooleanVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Volatile, false);
+ case vmIntrinsics::_putByteVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Volatile, false);
+ case vmIntrinsics::_putShortVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Volatile, false);
+ case vmIntrinsics::_putCharVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Volatile, false);
+ case vmIntrinsics::_putIntVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Volatile, false);
+ case vmIntrinsics::_putLongVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Volatile, false);
+ case vmIntrinsics::_putFloatVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Volatile, false);
+ case vmIntrinsics::_putDoubleVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Volatile, false);
+
+ case vmIntrinsics::_getShortUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Relaxed, true);
+ case vmIntrinsics::_getCharUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Relaxed, true);
+ case vmIntrinsics::_getIntUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Relaxed, true);
+ case vmIntrinsics::_getLongUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Relaxed, true);
+
+ case vmIntrinsics::_putShortUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Relaxed, true);
+ case vmIntrinsics::_putCharUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Relaxed, true);
+ case vmIntrinsics::_putIntUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Relaxed, true);
+ case vmIntrinsics::_putLongUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Relaxed, true);
+
+ case vmIntrinsics::_putOrderedObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Release, false);
+ case vmIntrinsics::_putOrderedInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Release, false);
+ case vmIntrinsics::_putOrderedLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Release, false);
+
+ case vmIntrinsics::_getObjectAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Acquire, false);
+ case vmIntrinsics::_getBooleanAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Acquire, false);
+ case vmIntrinsics::_getByteAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Acquire, false);
+ case vmIntrinsics::_getShortAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Acquire, false);
+ case vmIntrinsics::_getCharAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Acquire, false);
+ case vmIntrinsics::_getIntAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Acquire, false);
+ case vmIntrinsics::_getLongAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Acquire, false);
+ case vmIntrinsics::_getFloatAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Acquire, false);
+ case vmIntrinsics::_getDoubleAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Acquire, false);
+
+ case vmIntrinsics::_putObjectRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Release, false);
+ case vmIntrinsics::_putBooleanRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Release, false);
+ case vmIntrinsics::_putByteRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Release, false);
+ case vmIntrinsics::_putShortRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Release, false);
+ case vmIntrinsics::_putCharRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Release, false);
+ case vmIntrinsics::_putIntRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Release, false);
+ case vmIntrinsics::_putLongRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Release, false);
+ case vmIntrinsics::_putFloatRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Release, false);
+ case vmIntrinsics::_putDoubleRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Release, false);
+
+ case vmIntrinsics::_getObjectOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Opaque, false);
+ case vmIntrinsics::_getBooleanOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Opaque, false);
+ case vmIntrinsics::_getByteOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Opaque, false);
+ case vmIntrinsics::_getShortOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Opaque, false);
+ case vmIntrinsics::_getCharOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Opaque, false);
+ case vmIntrinsics::_getIntOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Opaque, false);
+ case vmIntrinsics::_getLongOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Opaque, false);
+ case vmIntrinsics::_getFloatOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Opaque, false);
+ case vmIntrinsics::_getDoubleOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Opaque, false);
+
+ case vmIntrinsics::_putObjectOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Opaque, false);
+ case vmIntrinsics::_putBooleanOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Opaque, false);
+ case vmIntrinsics::_putByteOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Opaque, false);
+ case vmIntrinsics::_putShortOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Opaque, false);
+ case vmIntrinsics::_putCharOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Opaque, false);
+ case vmIntrinsics::_putIntOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Opaque, false);
+ case vmIntrinsics::_putLongOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Opaque, false);
+ case vmIntrinsics::_putFloatOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Opaque, false);
+ case vmIntrinsics::_putDoubleOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Opaque, false);
+
+ case vmIntrinsics::_compareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap, Volatile);
+ case vmIntrinsics::_compareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmp_swap, Volatile);
+ case vmIntrinsics::_compareAndSwapLong: return inline_unsafe_load_store(T_LONG, LS_cmp_swap, Volatile);
+
+ case vmIntrinsics::_weakCompareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap_weak, Relaxed);
+ case vmIntrinsics::_weakCompareAndSwapObjectAcquire: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap_weak, Acquire);
+ case vmIntrinsics::_weakCompareAndSwapObjectRelease: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap_weak, Release);
+ case vmIntrinsics::_weakCompareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmp_swap_weak, Relaxed);
+ case vmIntrinsics::_weakCompareAndSwapIntAcquire: return inline_unsafe_load_store(T_INT, LS_cmp_swap_weak, Acquire);
+ case vmIntrinsics::_weakCompareAndSwapIntRelease: return inline_unsafe_load_store(T_INT, LS_cmp_swap_weak, Release);
+ case vmIntrinsics::_weakCompareAndSwapLong: return inline_unsafe_load_store(T_LONG, LS_cmp_swap_weak, Relaxed);
+ case vmIntrinsics::_weakCompareAndSwapLongAcquire: return inline_unsafe_load_store(T_LONG, LS_cmp_swap_weak, Acquire);
+ case vmIntrinsics::_weakCompareAndSwapLongRelease: return inline_unsafe_load_store(T_LONG, LS_cmp_swap_weak, Release);
+
+ case vmIntrinsics::_compareAndExchangeObjectVolatile: return inline_unsafe_load_store(T_OBJECT, LS_cmp_exchange, Volatile);
+ case vmIntrinsics::_compareAndExchangeObjectAcquire: return inline_unsafe_load_store(T_OBJECT, LS_cmp_exchange, Acquire);
+ case vmIntrinsics::_compareAndExchangeObjectRelease: return inline_unsafe_load_store(T_OBJECT, LS_cmp_exchange, Release);
+ case vmIntrinsics::_compareAndExchangeIntVolatile: return inline_unsafe_load_store(T_INT, LS_cmp_exchange, Volatile);
+ case vmIntrinsics::_compareAndExchangeIntAcquire: return inline_unsafe_load_store(T_INT, LS_cmp_exchange, Acquire);
+ case vmIntrinsics::_compareAndExchangeIntRelease: return inline_unsafe_load_store(T_INT, LS_cmp_exchange, Release);
+ case vmIntrinsics::_compareAndExchangeLongVolatile: return inline_unsafe_load_store(T_LONG, LS_cmp_exchange, Volatile);
+ case vmIntrinsics::_compareAndExchangeLongAcquire: return inline_unsafe_load_store(T_LONG, LS_cmp_exchange, Acquire);
+ case vmIntrinsics::_compareAndExchangeLongRelease: return inline_unsafe_load_store(T_LONG, LS_cmp_exchange, Release);
+
+ case vmIntrinsics::_getAndAddInt: return inline_unsafe_load_store(T_INT, LS_get_add, Volatile);
+ case vmIntrinsics::_getAndAddLong: return inline_unsafe_load_store(T_LONG, LS_get_add, Volatile);
+ case vmIntrinsics::_getAndSetInt: return inline_unsafe_load_store(T_INT, LS_get_set, Volatile);
+ case vmIntrinsics::_getAndSetLong: return inline_unsafe_load_store(T_LONG, LS_get_set, Volatile);
+ case vmIntrinsics::_getAndSetObject: return inline_unsafe_load_store(T_OBJECT, LS_get_set, Volatile);
case vmIntrinsics::_loadFence:
case vmIntrinsics::_storeFence:
@@ -1584,6 +1648,13 @@
assert (type2aelembytes(T_CHAR) == type2aelembytes(T_BYTE)*2,
"sanity: byte[] and char[] scales agree");
+ // Bail when getChar over constants is requested: constant folding would
+ // reject folding mismatched char access over byte[]. A normal inlining for getChar
+ // Java method would constant fold nicely instead.
+ if (!is_store && value->is_Con() && index->is_Con()) {
+ return false;
+ }
+
Node* adr = array_element_address(value, index, T_CHAR);
if (is_store) {
(void) store_to_memory(control(), adr, ch, T_CHAR, TypeAryPtr::BYTES, MemNode::unordered,
@@ -2277,8 +2348,10 @@
return NULL;
}
-bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile, bool unaligned) {
+bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_store, const BasicType type, const AccessKind kind, const bool unaligned) {
if (callee()->is_static()) return false; // caller must have the capability!
+ guarantee(!is_store || kind != Acquire, "Acquire accesses can be produced only for loads");
+ guarantee( is_store || kind != Release, "Release accesses can be produced only for stores");
#ifndef PRODUCT
{
@@ -2367,7 +2440,42 @@
// the barriers get omitted and the unsafe reference begins to "pollute"
// the alias analysis of the rest of the graph, either Compile::can_alias
// or Compile::must_alias will throw a diagnostic assert.)
- bool need_mem_bar = (alias_type->adr_type() == TypeOopPtr::BOTTOM);
+ bool need_mem_bar;
+ switch (kind) {
+ case Relaxed:
+ need_mem_bar = (alias_type->adr_type() == TypeOopPtr::BOTTOM);
+ break;
+ case Opaque:
+ // Opaque uses CPUOrder membars for protection against code movement.
+ case Acquire:
+ case Release:
+ case Volatile:
+ need_mem_bar = true;
+ break;
+ default:
+ ShouldNotReachHere();
+ }
+
+ // Some accesses require access atomicity for all types, notably longs and doubles.
+ // When AlwaysAtomicAccesses is enabled, all accesses are atomic.
+ bool requires_atomic_access = false;
+ switch (kind) {
+ case Relaxed:
+ case Opaque:
+ requires_atomic_access = AlwaysAtomicAccesses;
+ break;
+ case Acquire:
+ case Release:
+ case Volatile:
+ requires_atomic_access = true;
+ break;
+ default:
+ ShouldNotReachHere();
+ }
+
+ // Figure out the memory ordering.
+ // Acquire/Release/Volatile accesses require marking the loads/stores with MemOrd
+ MemNode::MemOrd mo = access_kind_to_memord_LS(kind, is_store);
// If we are reading the value of the referent field of a Reference
// object (either by using Unsafe directly or through reflection)
@@ -2394,22 +2502,30 @@
// and it is not possible to fully distinguish unintended nulls
// from intended ones in this API.
- if (is_volatile) {
- // We need to emit leading and trailing CPU membars (see below) in
- // addition to memory membars when is_volatile. This is a little
- // too strong, but avoids the need to insert per-alias-type
- // volatile membars (for stores; compare Parse::do_put_xxx), which
- // we cannot do effectively here because we probably only have a
- // rough approximation of type.
- need_mem_bar = true;
- // For Stores, place a memory ordering barrier now.
- if (is_store) {
- insert_mem_bar(Op_MemBarRelease);
- } else {
- if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
- insert_mem_bar(Op_MemBarVolatile);
+ // We need to emit leading and trailing CPU membars (see below) in
+ // addition to memory membars for special access modes. This is a little
+ // too strong, but avoids the need to insert per-alias-type
+ // volatile membars (for stores; compare Parse::do_put_xxx), which
+ // we cannot do effectively here because we probably only have a
+ // rough approximation of type.
+
+ switch(kind) {
+ case Relaxed:
+ case Opaque:
+ case Acquire:
+ break;
+ case Release:
+ case Volatile:
+ if (is_store) {
+ insert_mem_bar(Op_MemBarRelease);
+ } else {
+ if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+ insert_mem_bar(Op_MemBarVolatile);
+ }
}
- }
+ break;
+ default:
+ ShouldNotReachHere();
}
// Memory barrier to prevent normal and 'unsafe' accesses from
@@ -2453,10 +2569,9 @@
}
}
if (p == NULL) {
- MemNode::MemOrd mo = is_volatile ? MemNode::acquire : MemNode::unordered;
// To be valid, unsafe loads may depend on other conditions than
// the one that guards them: pin the Load node
- p = make_load(control(), adr, value_type, type, adr_type, mo, LoadNode::Pinned, is_volatile, unaligned, mismatched);
+ p = make_load(control(), adr, value_type, type, adr_type, mo, LoadNode::Pinned, requires_atomic_access, unaligned, mismatched);
// load value
switch (type) {
case T_BOOLEAN:
@@ -2470,7 +2585,9 @@
break;
case T_OBJECT:
if (need_read_barrier) {
- insert_pre_barrier(heap_base_oop, offset, p, !(is_volatile || need_mem_bar));
+ // We do not require a mem bar inside pre_barrier if need_mem_bar
+ // is set: the barriers would be emitted by us.
+ insert_pre_barrier(heap_base_oop, offset, p, !need_mem_bar);
}
break;
case T_ADDRESS:
@@ -2501,9 +2618,8 @@
break;
}
- MemNode::MemOrd mo = is_volatile ? MemNode::release : MemNode::unordered;
- if (type != T_OBJECT ) {
- (void) store_to_memory(control(), adr, val, type, adr_type, mo, is_volatile, unaligned, mismatched);
+ if (type != T_OBJECT) {
+ (void) store_to_memory(control(), adr, val, type, adr_type, mo, requires_atomic_access, unaligned, mismatched);
} else {
// Possibly an oop being stored to Java heap or native memory
if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) {
@@ -2524,7 +2640,7 @@
// Update IdealKit memory.
__ sync_kit(this);
} __ else_(); {
- __ store(__ ctrl(), adr, val, type, alias_type->index(), mo, is_volatile, mismatched);
+ __ store(__ ctrl(), adr, val, type, alias_type->index(), mo, requires_atomic_access, mismatched);
} __ end_if();
// Final sync IdealKit and GraphKit.
final_sync(ideal);
@@ -2533,14 +2649,23 @@
}
}
- if (is_volatile) {
- if (!is_store) {
- insert_mem_bar(Op_MemBarAcquire);
- } else {
- if (!support_IRIW_for_not_multiple_copy_atomic_cpu) {
- insert_mem_bar(Op_MemBarVolatile);
+ switch(kind) {
+ case Relaxed:
+ case Opaque:
+ case Release:
+ break;
+ case Acquire:
+ case Volatile:
+ if (!is_store) {
+ insert_mem_bar(Op_MemBarAcquire);
+ } else {
+ if (!support_IRIW_for_not_multiple_copy_atomic_cpu) {
+ insert_mem_bar(Op_MemBarVolatile);
+ }
}
- }
+ break;
+ default:
+ ShouldNotReachHere();
}
if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder);
@@ -2551,21 +2676,52 @@
//----------------------------inline_unsafe_load_store----------------------------
// This method serves a couple of different customers (depending on LoadStoreKind):
//
-// LS_cmpxchg:
-// public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object x);
-// public final native boolean compareAndSwapInt( Object o, long offset, int expected, int x);
-// public final native boolean compareAndSwapLong( Object o, long offset, long expected, long x);
+// LS_cmp_swap:
+//
+// boolean compareAndSwapObject(Object o, long offset, Object expected, Object x);
+// boolean compareAndSwapInt( Object o, long offset, int expected, int x);
+// boolean compareAndSwapLong( Object o, long offset, long expected, long x);
+//
+// LS_cmp_swap_weak:
+//
+// boolean weakCompareAndSwapObject( Object o, long offset, Object expected, Object x);
+// boolean weakCompareAndSwapObjectAcquire(Object o, long offset, Object expected, Object x);
+// boolean weakCompareAndSwapObjectRelease(Object o, long offset, Object expected, Object x);
+//
+// boolean weakCompareAndSwapInt( Object o, long offset, int expected, int x);
+// boolean weakCompareAndSwapIntAcquire( Object o, long offset, int expected, int x);
+// boolean weakCompareAndSwapIntRelease( Object o, long offset, int expected, int x);
+//
+// boolean weakCompareAndSwapLong( Object o, long offset, long expected, long x);
+// boolean weakCompareAndSwapLongAcquire( Object o, long offset, long expected, long x);
+// boolean weakCompareAndSwapLongRelease( Object o, long offset, long expected, long x);
//
-// LS_xadd:
-// public int getAndAddInt( Object o, long offset, int delta)
-// public long getAndAddLong(Object o, long offset, long delta)
+// LS_cmp_exchange:
+//
+// Object compareAndExchangeObjectVolatile(Object o, long offset, Object expected, Object x);
+// Object compareAndExchangeObjectAcquire( Object o, long offset, Object expected, Object x);
+// Object compareAndExchangeObjectRelease( Object o, long offset, Object expected, Object x);
+//
+// Object compareAndExchangeIntVolatile( Object o, long offset, Object expected, Object x);
+// Object compareAndExchangeIntAcquire( Object o, long offset, Object expected, Object x);
+// Object compareAndExchangeIntRelease( Object o, long offset, Object expected, Object x);
//
-// LS_xchg:
+// Object compareAndExchangeLongVolatile( Object o, long offset, Object expected, Object x);
+// Object compareAndExchangeLongAcquire( Object o, long offset, Object expected, Object x);
+// Object compareAndExchangeLongRelease( Object o, long offset, Object expected, Object x);
+//
+// LS_get_add:
+//
+// int getAndAddInt( Object o, long offset, int delta)
+// long getAndAddLong(Object o, long offset, long delta)
+//
+// LS_get_set:
+//
// int getAndSet(Object o, long offset, int newValue)
// long getAndSet(Object o, long offset, long newValue)
// Object getAndSet(Object o, long offset, Object newValue)
//
-bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind) {
+bool LibraryCallKit::inline_unsafe_load_store(const BasicType type, const LoadStoreKind kind, const AccessKind access_kind) {
// This basic scheme here is the same as inline_unsafe_access, but
// differs in enough details that combining them would make the code
// overly confusing. (This is a true fact! I originally combined
@@ -2582,7 +2738,9 @@
// Check the signatures.
ciSignature* sig = callee()->signature();
rtype = sig->return_type()->basic_type();
- if (kind == LS_xadd || kind == LS_xchg) {
+ switch(kind) {
+ case LS_get_add:
+ case LS_get_set: {
// Check the signatures.
#ifdef ASSERT
assert(rtype == type, "get and set must return the expected type");
@@ -2591,7 +2749,10 @@
assert(sig->type_at(1)->basic_type() == T_LONG, "get and set offset is long");
assert(sig->type_at(2)->basic_type() == type, "get and set must take expected type as new value/delta");
#endif // ASSERT
- } else if (kind == LS_cmpxchg) {
+ break;
+ }
+ case LS_cmp_swap:
+ case LS_cmp_swap_weak: {
// Check the signatures.
#ifdef ASSERT
assert(rtype == T_BOOLEAN, "CAS must return boolean");
@@ -2599,8 +2760,20 @@
assert(sig->type_at(0)->basic_type() == T_OBJECT, "CAS base is object");
assert(sig->type_at(1)->basic_type() == T_LONG, "CAS offset is long");
#endif // ASSERT
- } else {
- ShouldNotReachHere();
+ break;
+ }
+ case LS_cmp_exchange: {
+ // Check the signatures.
+#ifdef ASSERT
+ assert(rtype == type, "CAS must return the expected type");
+ assert(sig->count() == 4, "CAS has 4 arguments");
+ assert(sig->type_at(0)->basic_type() == T_OBJECT, "CAS base is object");
+ assert(sig->type_at(1)->basic_type() == T_LONG, "CAS offset is long");
+#endif // ASSERT
+ break;
+ }
+ default:
+ ShouldNotReachHere();
}
}
#endif //PRODUCT
@@ -2613,19 +2786,29 @@
Node* offset = NULL;
Node* oldval = NULL;
Node* newval = NULL;
- if (kind == LS_cmpxchg) {
- const bool two_slot_type = type2size[type] == 2;
- receiver = argument(0); // type: oop
- base = argument(1); // type: oop
- offset = argument(2); // type: long
- oldval = argument(4); // type: oop, int, or long
- newval = argument(two_slot_type ? 6 : 5); // type: oop, int, or long
- } else if (kind == LS_xadd || kind == LS_xchg){
- receiver = argument(0); // type: oop
- base = argument(1); // type: oop
- offset = argument(2); // type: long
- oldval = NULL;
- newval = argument(4); // type: oop, int, or long
+ switch(kind) {
+ case LS_cmp_swap:
+ case LS_cmp_swap_weak:
+ case LS_cmp_exchange: {
+ const bool two_slot_type = type2size[type] == 2;
+ receiver = argument(0); // type: oop
+ base = argument(1); // type: oop
+ offset = argument(2); // type: long
+ oldval = argument(4); // type: oop, int, or long
+ newval = argument(two_slot_type ? 6 : 5); // type: oop, int, or long
+ break;
+ }
+ case LS_get_add:
+ case LS_get_set: {
+ receiver = argument(0); // type: oop
+ base = argument(1); // type: oop
+ offset = argument(2); // type: long
+ oldval = NULL;
+ newval = argument(4); // type: oop, int, or long
+ break;
+ }
+ default:
+ ShouldNotReachHere();
}
// Null check receiver.
@@ -2650,11 +2833,23 @@
Compile::AliasType* alias_type = C->alias_type(adr_type);
assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here");
- if (kind == LS_xchg && type == T_OBJECT) {
- const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type);
- if (tjp != NULL) {
- value_type = tjp;
+ switch (kind) {
+ case LS_get_set:
+ case LS_cmp_exchange: {
+ if (type == T_OBJECT) {
+ const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type);
+ if (tjp != NULL) {
+ value_type = tjp;
+ }
+ }
+ break;
}
+ case LS_cmp_swap:
+ case LS_cmp_swap_weak:
+ case LS_get_add:
+ break;
+ default:
+ ShouldNotReachHere();
}
int alias_idx = C->get_alias_index(adr_type);
@@ -2664,9 +2859,22 @@
// into actual barriers on most machines, but we still need rest of
// compiler to respect ordering.
- insert_mem_bar(Op_MemBarRelease);
+ switch (access_kind) {
+ case Relaxed:
+ case Acquire:
+ break;
+ case Release:
+ case Volatile:
+ insert_mem_bar(Op_MemBarRelease);
+ break;
+ default:
+ ShouldNotReachHere();
+ }
insert_mem_bar(Op_MemBarCPUOrder);
+ // Figure out the memory ordering.
+ MemNode::MemOrd mo = access_kind_to_memord(access_kind);
+
// 4984716: MemBars must be inserted before this
// memory node in order to avoid a false
// dependency which will confuse the scheduler.
@@ -2677,25 +2885,45 @@
Node* load_store = NULL;
switch(type) {
case T_INT:
- if (kind == LS_xadd) {
- load_store = _gvn.transform(new GetAndAddINode(control(), mem, adr, newval, adr_type));
- } else if (kind == LS_xchg) {
- load_store = _gvn.transform(new GetAndSetINode(control(), mem, adr, newval, adr_type));
- } else if (kind == LS_cmpxchg) {
- load_store = _gvn.transform(new CompareAndSwapINode(control(), mem, adr, newval, oldval));
- } else {
- ShouldNotReachHere();
+ switch(kind) {
+ case LS_get_add:
+ load_store = _gvn.transform(new GetAndAddINode(control(), mem, adr, newval, adr_type));
+ break;
+ case LS_get_set:
+ load_store = _gvn.transform(new GetAndSetINode(control(), mem, adr, newval, adr_type));
+ break;
+ case LS_cmp_swap_weak:
+ load_store = _gvn.transform(new WeakCompareAndSwapINode(control(), mem, adr, newval, oldval, mo));
+ break;
+ case LS_cmp_swap:
+ load_store = _gvn.transform(new CompareAndSwapINode(control(), mem, adr, newval, oldval, mo));
+ break;
+ case LS_cmp_exchange:
+ load_store = _gvn.transform(new CompareAndExchangeINode(control(), mem, adr, newval, oldval, adr_type, mo));
+ break;
+ default:
+ ShouldNotReachHere();
}
break;
case T_LONG:
- if (kind == LS_xadd) {
- load_store = _gvn.transform(new GetAndAddLNode(control(), mem, adr, newval, adr_type));
- } else if (kind == LS_xchg) {
- load_store = _gvn.transform(new GetAndSetLNode(control(), mem, adr, newval, adr_type));
- } else if (kind == LS_cmpxchg) {
- load_store = _gvn.transform(new CompareAndSwapLNode(control(), mem, adr, newval, oldval));
- } else {
- ShouldNotReachHere();
+ switch(kind) {
+ case LS_get_add:
+ load_store = _gvn.transform(new GetAndAddLNode(control(), mem, adr, newval, adr_type));
+ break;
+ case LS_get_set:
+ load_store = _gvn.transform(new GetAndSetLNode(control(), mem, adr, newval, adr_type));
+ break;
+ case LS_cmp_swap_weak:
+ load_store = _gvn.transform(new WeakCompareAndSwapLNode(control(), mem, adr, newval, oldval, mo));
+ break;
+ case LS_cmp_swap:
+ load_store = _gvn.transform(new CompareAndSwapLNode(control(), mem, adr, newval, oldval, mo));
+ break;
+ case LS_cmp_exchange:
+ load_store = _gvn.transform(new CompareAndExchangeLNode(control(), mem, adr, newval, oldval, adr_type, mo));
+ break;
+ default:
+ ShouldNotReachHere();
}
break;
case T_OBJECT:
@@ -2706,65 +2934,109 @@
newval = _gvn.makecon(TypePtr::NULL_PTR);
// Reference stores need a store barrier.
- if (kind == LS_xchg) {
- // If pre-barrier must execute before the oop store, old value will require do_load here.
- if (!can_move_pre_barrier()) {
- pre_barrier(true /* do_load*/,
- control(), base, adr, alias_idx, newval, value_type->make_oopptr(),
- NULL /* pre_val*/,
+ switch(kind) {
+ case LS_get_set: {
+ // If pre-barrier must execute before the oop store, old value will require do_load here.
+ if (!can_move_pre_barrier()) {
+ pre_barrier(true /* do_load*/,
+ control(), base, adr, alias_idx, newval, value_type->make_oopptr(),
+ NULL /* pre_val*/,
+ T_OBJECT);
+ } // Else move pre_barrier to use load_store value, see below.
+ break;
+ }
+ case LS_cmp_swap_weak:
+ case LS_cmp_swap:
+ case LS_cmp_exchange: {
+ // Same as for newval above:
+ if (_gvn.type(oldval) == TypePtr::NULL_PTR) {
+ oldval = _gvn.makecon(TypePtr::NULL_PTR);
+ }
+ // The only known value which might get overwritten is oldval.
+ pre_barrier(false /* do_load */,
+ control(), NULL, NULL, max_juint, NULL, NULL,
+ oldval /* pre_val */,
T_OBJECT);
- } // Else move pre_barrier to use load_store value, see below.
- } else if (kind == LS_cmpxchg) {
- // Same as for newval above:
- if (_gvn.type(oldval) == TypePtr::NULL_PTR) {
- oldval = _gvn.makecon(TypePtr::NULL_PTR);
+ break;
}
- // The only known value which might get overwritten is oldval.
- pre_barrier(false /* do_load */,
- control(), NULL, NULL, max_juint, NULL, NULL,
- oldval /* pre_val */,
- T_OBJECT);
- } else {
- ShouldNotReachHere();
+ default:
+ ShouldNotReachHere();
}
#ifdef _LP64
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
Node *newval_enc = _gvn.transform(new EncodePNode(newval, newval->bottom_type()->make_narrowoop()));
- if (kind == LS_xchg) {
- load_store = _gvn.transform(new GetAndSetNNode(control(), mem, adr,
- newval_enc, adr_type, value_type->make_narrowoop()));
- } else {
- assert(kind == LS_cmpxchg, "wrong LoadStore operation");
- Node *oldval_enc = _gvn.transform(new EncodePNode(oldval, oldval->bottom_type()->make_narrowoop()));
- load_store = _gvn.transform(new CompareAndSwapNNode(control(), mem, adr,
- newval_enc, oldval_enc));
+
+ switch(kind) {
+ case LS_get_set:
+ load_store = _gvn.transform(new GetAndSetNNode(control(), mem, adr, newval_enc, adr_type, value_type->make_narrowoop()));
+ break;
+ case LS_cmp_swap_weak: {
+ Node *oldval_enc = _gvn.transform(new EncodePNode(oldval, oldval->bottom_type()->make_narrowoop()));
+ load_store = _gvn.transform(new WeakCompareAndSwapNNode(control(), mem, adr, newval_enc, oldval_enc, mo));
+ break;
+ }
+ case LS_cmp_swap: {
+ Node *oldval_enc = _gvn.transform(new EncodePNode(oldval, oldval->bottom_type()->make_narrowoop()));
+ load_store = _gvn.transform(new CompareAndSwapNNode(control(), mem, adr, newval_enc, oldval_enc, mo));
+ break;
+ }
+ case LS_cmp_exchange: {
+ Node *oldval_enc = _gvn.transform(new EncodePNode(oldval, oldval->bottom_type()->make_narrowoop()));
+ load_store = _gvn.transform(new CompareAndExchangeNNode(control(), mem, adr, newval_enc, oldval_enc, adr_type, value_type->make_narrowoop(), mo));
+ break;
+ }
+ default:
+ ShouldNotReachHere();
}
} else
#endif
- {
- if (kind == LS_xchg) {
+ switch (kind) {
+ case LS_get_set:
load_store = _gvn.transform(new GetAndSetPNode(control(), mem, adr, newval, adr_type, value_type->is_oopptr()));
- } else {
- assert(kind == LS_cmpxchg, "wrong LoadStore operation");
- load_store = _gvn.transform(new CompareAndSwapPNode(control(), mem, adr, newval, oldval));
- }
+ break;
+ case LS_cmp_swap_weak:
+ load_store = _gvn.transform(new WeakCompareAndSwapPNode(control(), mem, adr, newval, oldval, mo));
+ break;
+ case LS_cmp_swap:
+ load_store = _gvn.transform(new CompareAndSwapPNode(control(), mem, adr, newval, oldval, mo));
+ break;
+ case LS_cmp_exchange:
+ load_store = _gvn.transform(new CompareAndExchangePNode(control(), mem, adr, newval, oldval, adr_type, value_type->is_oopptr(), mo));
+ break;
+ default:
+ ShouldNotReachHere();
}
- if (kind == LS_cmpxchg) {
- // Emit the post barrier only when the actual store happened.
- // This makes sense to check only for compareAndSet that can fail to set the value.
- // CAS success path is marked more likely since we anticipate this is a performance
- // critical path, while CAS failure path can use the penalty for going through unlikely
- // path as backoff. Which is still better than doing a store barrier there.
- IdealKit ideal(this);
- ideal.if_then(load_store, BoolTest::ne, ideal.ConI(0), PROB_STATIC_FREQUENT); {
- sync_kit(ideal);
- post_barrier(ideal.ctrl(), load_store, base, adr, alias_idx, newval, T_OBJECT, true);
- ideal.sync_kit(this);
- } ideal.end_if();
- final_sync(ideal);
- } else {
- post_barrier(control(), load_store, base, adr, alias_idx, newval, T_OBJECT, true);
+
+ // Emit the post barrier only when the actual store happened. This makes sense
+ // to check only for LS_cmp_* that can fail to set the value.
+ // LS_cmp_exchange does not produce any branches by default, so there is no
+ // boolean result to piggyback on. TODO: When we merge CompareAndSwap with
+ // CompareAndExchange and move branches here, it would make sense to conditionalize
+ // post_barriers for LS_cmp_exchange as well.
+ //
+ // CAS success path is marked more likely since we anticipate this is a performance
+ // critical path, while CAS failure path can use the penalty for going through unlikely
+ // path as backoff. Which is still better than doing a store barrier there.
+ switch (kind) {
+ case LS_get_set:
+ case LS_cmp_exchange: {
+ post_barrier(control(), load_store, base, adr, alias_idx, newval, T_OBJECT, true);
+ break;
+ }
+ case LS_cmp_swap_weak:
+ case LS_cmp_swap: {
+ IdealKit ideal(this);
+ ideal.if_then(load_store, BoolTest::ne, ideal.ConI(0), PROB_STATIC_FREQUENT); {
+ sync_kit(ideal);
+ post_barrier(ideal.ctrl(), load_store, base, adr, alias_idx, newval, T_OBJECT, true);
+ ideal.sync_kit(this);
+ } ideal.end_if();
+ final_sync(ideal);
+ break;
+ }
+ default:
+ ShouldNotReachHere();
}
break;
default:
@@ -2778,7 +3050,7 @@
Node* proj = _gvn.transform(new SCMemProjNode(load_store));
set_memory(proj, alias_idx);
- if (type == T_OBJECT && kind == LS_xchg) {
+ if (type == T_OBJECT && (kind == LS_get_set || kind == LS_cmp_exchange)) {
#ifdef _LP64
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
load_store = _gvn.transform(new DecodeNNode(load_store, load_store->get_ptr_type()));
@@ -2797,74 +3069,52 @@
// Add the trailing membar surrounding the access
insert_mem_bar(Op_MemBarCPUOrder);
- insert_mem_bar(Op_MemBarAcquire);
+
+ switch (access_kind) {
+ case Relaxed:
+ case Release:
+ break; // do nothing
+ case Acquire:
+ case Volatile:
+ insert_mem_bar(Op_MemBarAcquire);
+ break;
+ default:
+ ShouldNotReachHere();
+ }
assert(type2size[load_store->bottom_type()->basic_type()] == type2size[rtype], "result type should match");
set_result(load_store);
return true;
}
-//----------------------------inline_unsafe_ordered_store----------------------
-// public native void Unsafe.putOrderedObject(Object o, long offset, Object x);
-// public native void Unsafe.putOrderedInt(Object o, long offset, int x);
-// public native void Unsafe.putOrderedLong(Object o, long offset, long x);
-bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) {
- // This is another variant of inline_unsafe_access, differing in
- // that it always issues store-store ("release") barrier and ensures
- // store-atomicity (which only matters for "long").
-
- if (callee()->is_static()) return false; // caller must have the capability!
-
-#ifndef PRODUCT
- {
- ResourceMark rm;
- // Check the signatures.
- ciSignature* sig = callee()->signature();
-#ifdef ASSERT
- BasicType rtype = sig->return_type()->basic_type();
- assert(rtype == T_VOID, "must return void");
- assert(sig->count() == 3, "has 3 arguments");
- assert(sig->type_at(0)->basic_type() == T_OBJECT, "base is object");
- assert(sig->type_at(1)->basic_type() == T_LONG, "offset is long");
-#endif // ASSERT
- }
-#endif //PRODUCT
-
- C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe".
-
- // Get arguments:
- Node* receiver = argument(0); // type: oop
- Node* base = argument(1); // type: oop
- Node* offset = argument(2); // type: long
- Node* val = argument(4); // type: oop, int, or long
-
- // Null check receiver.
- receiver = null_check(receiver);
- if (stopped()) {
- return true;
- }
-
- // Build field offset expression.
- assert(Unsafe_field_offset_to_byte_offset(11) == 11, "fieldOffset must be byte-scaled");
- // 32-bit machines ignore the high half of long offsets
- offset = ConvL2X(offset);
- Node* adr = make_unsafe_address(base, offset);
- const TypePtr *adr_type = _gvn.type(adr)->isa_ptr();
- const Type *value_type = Type::get_const_basic_type(type);
- Compile::AliasType* alias_type = C->alias_type(adr_type);
-
- insert_mem_bar(Op_MemBarRelease);
- insert_mem_bar(Op_MemBarCPUOrder);
- // Ensure that the store is atomic for longs:
- const bool require_atomic_access = true;
- Node* store;
- if (type == T_OBJECT) // reference stores need a store barrier.
- store = store_oop_to_unknown(control(), base, adr, adr_type, val, type, MemNode::release);
- else {
- store = store_to_memory(control(), adr, val, type, adr_type, MemNode::release, require_atomic_access);
- }
- insert_mem_bar(Op_MemBarCPUOrder);
- return true;
+MemNode::MemOrd LibraryCallKit::access_kind_to_memord_LS(AccessKind kind, bool is_store) {
+ MemNode::MemOrd mo = MemNode::unset;
+ switch(kind) {
+ case Opaque:
+ case Relaxed: mo = MemNode::unordered; break;
+ case Acquire: mo = MemNode::acquire; break;
+ case Release: mo = MemNode::release; break;
+ case Volatile: mo = is_store ? MemNode::release : MemNode::acquire; break;
+ default:
+ ShouldNotReachHere();
+ }
+ guarantee(mo != MemNode::unset, "Should select memory ordering");
+ return mo;
+}
+
+MemNode::MemOrd LibraryCallKit::access_kind_to_memord(AccessKind kind) {
+ MemNode::MemOrd mo = MemNode::unset;
+ switch(kind) {
+ case Opaque:
+ case Relaxed: mo = MemNode::unordered; break;
+ case Acquire: mo = MemNode::acquire; break;
+ case Release: mo = MemNode::release; break;
+ case Volatile: mo = MemNode::seqcst; break;
+ default:
+ ShouldNotReachHere();
+ }
+ guarantee(mo != MemNode::unset, "Should select memory ordering");
+ return mo;
}
bool LibraryCallKit::inline_unsafe_fence(vmIntrinsics::ID id) {
--- a/hotspot/src/share/vm/opto/loopTransform.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -2417,6 +2417,14 @@
((bol->in(1)->Opcode() == Op_StorePConditional ) ||
(bol->in(1)->Opcode() == Op_StoreIConditional ) ||
(bol->in(1)->Opcode() == Op_StoreLConditional ) ||
+ (bol->in(1)->Opcode() == Op_CompareAndExchangeI ) ||
+ (bol->in(1)->Opcode() == Op_CompareAndExchangeL ) ||
+ (bol->in(1)->Opcode() == Op_CompareAndExchangeP ) ||
+ (bol->in(1)->Opcode() == Op_CompareAndExchangeN ) ||
+ (bol->in(1)->Opcode() == Op_WeakCompareAndSwapI ) ||
+ (bol->in(1)->Opcode() == Op_WeakCompareAndSwapL ) ||
+ (bol->in(1)->Opcode() == Op_WeakCompareAndSwapP ) ||
+ (bol->in(1)->Opcode() == Op_WeakCompareAndSwapN ) ||
(bol->in(1)->Opcode() == Op_CompareAndSwapI ) ||
(bol->in(1)->Opcode() == Op_CompareAndSwapL ) ||
(bol->in(1)->Opcode() == Op_CompareAndSwapP ) ||
--- a/hotspot/src/share/vm/opto/matcher.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/opto/matcher.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -2307,6 +2307,14 @@
case Op_StorePConditional:
case Op_StoreIConditional:
case Op_StoreLConditional:
+ case Op_CompareAndExchangeI:
+ case Op_CompareAndExchangeL:
+ case Op_CompareAndExchangeP:
+ case Op_CompareAndExchangeN:
+ case Op_WeakCompareAndSwapI:
+ case Op_WeakCompareAndSwapL:
+ case Op_WeakCompareAndSwapP:
+ case Op_WeakCompareAndSwapN:
case Op_CompareAndSwapI:
case Op_CompareAndSwapL:
case Op_CompareAndSwapP:
@@ -2522,6 +2530,14 @@
// that a monitor exit operation contains a serializing instruction.
if (xop == Op_MemBarVolatile ||
+ xop == Op_CompareAndExchangeI ||
+ xop == Op_CompareAndExchangeL ||
+ xop == Op_CompareAndExchangeP ||
+ xop == Op_CompareAndExchangeN ||
+ xop == Op_WeakCompareAndSwapL ||
+ xop == Op_WeakCompareAndSwapP ||
+ xop == Op_WeakCompareAndSwapN ||
+ xop == Op_WeakCompareAndSwapI ||
xop == Op_CompareAndSwapL ||
xop == Op_CompareAndSwapP ||
xop == Op_CompareAndSwapN ||
--- a/hotspot/src/share/vm/opto/memnode.hpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/opto/memnode.hpp Wed Feb 24 12:38:50 2016 +0000
@@ -56,7 +56,9 @@
};
typedef enum { unordered = 0,
acquire, // Load has to acquire or be succeeded by MemBarAcquire.
- release // Store has to release or be preceded by MemBarRelease.
+ release, // Store has to release or be preceded by MemBarRelease.
+ seqcst, // LoadStore has to have both acquire and release semantics.
+ unset // The memory ordering is not set (used for testing)
} MemOrd;
protected:
MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at )
@@ -848,34 +850,121 @@
virtual uint ideal_reg() const { return Op_RegFlags; }
};
+class CompareAndSwapNode : public LoadStoreConditionalNode {
+private:
+ const MemNode::MemOrd _mem_ord;
+public:
+ CompareAndSwapNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : LoadStoreConditionalNode(c, mem, adr, val, ex), _mem_ord(mem_ord) {}
+ MemNode::MemOrd order() const {
+ return _mem_ord;
+ }
+};
+
+class CompareAndExchangeNode : public LoadStoreNode {
+private:
+ const MemNode::MemOrd _mem_ord;
+public:
+ enum {
+ ExpectedIn = MemNode::ValueIn+1 // One more input than MemNode
+ };
+ CompareAndExchangeNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord, const TypePtr* at, const Type* t) :
+ LoadStoreNode(c, mem, adr, val, at, t, 5), _mem_ord(mem_ord) {
+ init_req(ExpectedIn, ex );
+ }
+
+ MemNode::MemOrd order() const {
+ return _mem_ord;
+ }
+};
//------------------------------CompareAndSwapLNode---------------------------
-class CompareAndSwapLNode : public LoadStoreConditionalNode {
+class CompareAndSwapLNode : public CompareAndSwapNode {
public:
- CompareAndSwapLNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex) : LoadStoreConditionalNode(c, mem, adr, val, ex) { }
+ CompareAndSwapLNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
virtual int Opcode() const;
};
//------------------------------CompareAndSwapINode---------------------------
-class CompareAndSwapINode : public LoadStoreConditionalNode {
+class CompareAndSwapINode : public CompareAndSwapNode {
public:
- CompareAndSwapINode( Node *c, Node *mem, Node *adr, Node *val, Node *ex) : LoadStoreConditionalNode(c, mem, adr, val, ex) { }
+ CompareAndSwapINode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
virtual int Opcode() const;
};
//------------------------------CompareAndSwapPNode---------------------------
-class CompareAndSwapPNode : public LoadStoreConditionalNode {
+class CompareAndSwapPNode : public CompareAndSwapNode {
public:
- CompareAndSwapPNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex) : LoadStoreConditionalNode(c, mem, adr, val, ex) { }
+ CompareAndSwapPNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
virtual int Opcode() const;
};
//------------------------------CompareAndSwapNNode---------------------------
-class CompareAndSwapNNode : public LoadStoreConditionalNode {
+class CompareAndSwapNNode : public CompareAndSwapNode {
+public:
+ CompareAndSwapNNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
+ virtual int Opcode() const;
+};
+
+
+//------------------------------WeakCompareAndSwapLNode---------------------------
+class WeakCompareAndSwapLNode : public CompareAndSwapNode {
+public:
+ WeakCompareAndSwapLNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
+ virtual int Opcode() const;
+};
+
+
+//------------------------------WeakCompareAndSwapINode---------------------------
+class WeakCompareAndSwapINode : public CompareAndSwapNode {
+public:
+ WeakCompareAndSwapINode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
+ virtual int Opcode() const;
+};
+
+
+//------------------------------WeakCompareAndSwapPNode---------------------------
+class WeakCompareAndSwapPNode : public CompareAndSwapNode {
public:
- CompareAndSwapNNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex) : LoadStoreConditionalNode(c, mem, adr, val, ex) { }
+ WeakCompareAndSwapPNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
+ virtual int Opcode() const;
+};
+
+//------------------------------WeakCompareAndSwapNNode---------------------------
+class WeakCompareAndSwapNNode : public CompareAndSwapNode {
+public:
+ WeakCompareAndSwapNNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { }
+ virtual int Opcode() const;
+};
+
+//------------------------------CompareAndExchangeLNode---------------------------
+class CompareAndExchangeLNode : public CompareAndExchangeNode {
+public:
+ CompareAndExchangeLNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, MemNode::MemOrd mem_ord) : CompareAndExchangeNode(c, mem, adr, val, ex, mem_ord, at, TypeLong::LONG) { }
+ virtual int Opcode() const;
+};
+
+
+//------------------------------CompareAndExchangeINode---------------------------
+class CompareAndExchangeINode : public CompareAndExchangeNode {
+public:
+ CompareAndExchangeINode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, MemNode::MemOrd mem_ord) : CompareAndExchangeNode(c, mem, adr, val, ex, mem_ord, at, TypeInt::INT) { }
+ virtual int Opcode() const;
+};
+
+
+//------------------------------CompareAndExchangePNode---------------------------
+class CompareAndExchangePNode : public CompareAndExchangeNode {
+public:
+ CompareAndExchangePNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, const Type* t, MemNode::MemOrd mem_ord) : CompareAndExchangeNode(c, mem, adr, val, ex, mem_ord, at, t) { }
+ virtual int Opcode() const;
+};
+
+//------------------------------CompareAndExchangeNNode---------------------------
+class CompareAndExchangeNNode : public CompareAndExchangeNode {
+public:
+ CompareAndExchangeNNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, const Type* t, MemNode::MemOrd mem_ord) : CompareAndExchangeNode(c, mem, adr, val, ex, mem_ord, at, t) { }
virtual int Opcode() const;
};
--- a/hotspot/src/share/vm/opto/node.hpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/opto/node.hpp Wed Feb 24 12:38:50 2016 +0000
@@ -60,6 +60,8 @@
class CodeBuffer;
class ConstraintCastNode;
class ConNode;
+class CompareAndSwapNode;
+class CompareAndExchangeNode;
class CountedLoopNode;
class CountedLoopEndNode;
class DecodeNarrowPtrNode;
@@ -679,6 +681,9 @@
DEFINE_CLASS_ID(Store, Mem, 1)
DEFINE_CLASS_ID(StoreVector, Store, 0)
DEFINE_CLASS_ID(LoadStore, Mem, 2)
+ DEFINE_CLASS_ID(LoadStoreConditional, LoadStore, 0)
+ DEFINE_CLASS_ID(CompareAndSwap, LoadStoreConditional, 0)
+ DEFINE_CLASS_ID(CompareAndExchangeNode, LoadStore, 1)
DEFINE_CLASS_ID(Region, Node, 5)
DEFINE_CLASS_ID(Loop, Region, 0)
--- a/hotspot/src/share/vm/prims/unsafe.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/prims/unsafe.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -1117,6 +1117,44 @@
// JSR166 ------------------------------------------------------------------
+UNSAFE_ENTRY(jobject, Unsafe_CompareAndExchangeObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
+ UnsafeWrapper("Unsafe_CompareAndExchangeObject");
+ oop x = JNIHandles::resolve(x_h);
+ oop e = JNIHandles::resolve(e_h);
+ oop p = JNIHandles::resolve(obj);
+ HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);
+ oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);
+ if (res == e)
+ update_barrier_set((void*)addr, x);
+ return JNIHandles::make_local(env, res);
+UNSAFE_END
+
+UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
+ UnsafeWrapper("Unsafe_CompareAndExchangeInt");
+ oop p = JNIHandles::resolve(obj);
+ jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
+ return (jint)(Atomic::cmpxchg(x, addr, e));
+UNSAFE_END
+
+UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x))
+ UnsafeWrapper("Unsafe_CompareAndExchangeLong");
+ Handle p (THREAD, JNIHandles::resolve(obj));
+ jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
+#ifdef SUPPORTS_NATIVE_CX8
+ return (jlong)(Atomic::cmpxchg(x, addr, e));
+#else
+ if (VM_Version::supports_cx8())
+ return (jlong)(Atomic::cmpxchg(x, addr, e));
+ else {
+ MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
+ jlong val = Atomic::load(addr);
+ if (val == e)
+ Atomic::store(x, addr);
+ return val;
+ }
+#endif
+UNSAFE_END
+
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
UnsafeWrapper("Unsafe_CompareAndSwapObject");
oop x = JNIHandles::resolve(x_h);
@@ -1384,6 +1422,10 @@
{CC "compareAndSwapObject", CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSwapObject)},
{CC "compareAndSwapInt", CC "(" OBJ "J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)},
{CC "compareAndSwapLong", CC "(" OBJ "J""J""J"")Z", FN_PTR(Unsafe_CompareAndSwapLong)},
+ {CC "compareAndExchangeObjectVolatile", CC "(" OBJ "J" OBJ "" OBJ ")" OBJ, FN_PTR(Unsafe_CompareAndExchangeObject)},
+ {CC "compareAndExchangeIntVolatile", CC "(" OBJ "J""I""I"")I", FN_PTR(Unsafe_CompareAndExchangeInt)},
+ {CC "compareAndExchangeLongVolatile", CC "(" OBJ "J""J""J"")J", FN_PTR(Unsafe_CompareAndExchangeLong)},
+
{CC "putOrderedObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetOrderedObject)},
{CC "putOrderedInt", CC "(" OBJ "JI)V", FN_PTR(Unsafe_SetOrderedInt)},
{CC "putOrderedLong", CC "(" OBJ "JJ)V", FN_PTR(Unsafe_SetOrderedLong)},
--- a/hotspot/src/share/vm/runtime/arguments.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -2314,6 +2314,17 @@
//===========================================================================================================
// Parsing of main arguments
+#if INCLUDE_JVMCI
+// Check consistency of jvmci vm argument settings.
+bool Arguments::check_jvmci_args_consistency() {
+ if (!EnableJVMCI && !JVMCIGlobals::check_jvmci_flags_are_consistent()) {
+ JVMCIGlobals::print_jvmci_args_inconsistency_error_message();
+ return false;
+ }
+ return true;
+}
+#endif //INCLUDE_JVMCI
+
// Check consistency of GC selection
bool Arguments::check_gc_consistency() {
// Ensure that the user has not selected conflicting sets
@@ -2410,6 +2421,9 @@
#endif
}
#if INCLUDE_JVMCI
+
+ status = status && check_jvmci_args_consistency();
+
if (EnableJVMCI) {
if (!ScavengeRootsInCode) {
warning("forcing ScavengeRootsInCode non-zero because JVMCI is enabled");
--- a/hotspot/src/share/vm/runtime/arguments.hpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Wed Feb 24 12:38:50 2016 +0000
@@ -505,7 +505,10 @@
static void set_gc_specific_flags();
static inline bool gc_selected(); // whether a gc has been selected
static void select_gc_ergonomically();
-
+#if INCLUDE_JVMCI
+ // Check consistency of jvmci vm argument settings.
+ static bool check_jvmci_args_consistency();
+#endif
// Check for consistency in the selection of the garbage collector.
static bool check_gc_consistency(); // Check user-selected gc
// Check consistency or otherwise of VM argument settings
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -33,9 +33,6 @@
#include "runtime/commandLineFlagConstraintsRuntime.hpp"
#include "runtime/os.hpp"
#include "utilities/macros.hpp"
-#if INCLUDE_JVMCI
-#include "jvmci/commandLineFlagConstraintsJVMCI.hpp"
-#endif
class CommandLineFlagConstraint_bool : public CommandLineFlagConstraint {
CommandLineFlagConstraintFunc_bool _constraint;
@@ -254,17 +251,6 @@
IGNORE_RANGE,
EMIT_CONSTRAINT_CHECK));
-#if INCLUDE_JVMCI
- emit_constraint_no(NULL JVMCI_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
- EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
- EMIT_CONSTRAINT_PRODUCT_FLAG,
- EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
- EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
- EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
- EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
- IGNORE_RANGE,
- EMIT_CONSTRAINT_CHECK));
-#endif // INCLUDE_JVMCI
#ifdef COMPILER1
emit_constraint_no(NULL C1_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Feb 24 12:38:50 2016 +0000
@@ -2005,10 +2005,20 @@
declare_c2_type(LoadStoreNode, Node) \
declare_c2_type(StorePConditionalNode, LoadStoreNode) \
declare_c2_type(StoreLConditionalNode, LoadStoreNode) \
- declare_c2_type(CompareAndSwapLNode, LoadStoreNode) \
- declare_c2_type(CompareAndSwapINode, LoadStoreNode) \
- declare_c2_type(CompareAndSwapPNode, LoadStoreNode) \
- declare_c2_type(CompareAndSwapNNode, LoadStoreNode) \
+ declare_c2_type(CompareAndSwapNode, LoadStoreConditionalNode) \
+ declare_c2_type(CompareAndSwapLNode, CompareAndSwapNode) \
+ declare_c2_type(CompareAndSwapINode, CompareAndSwapNode) \
+ declare_c2_type(CompareAndSwapPNode, CompareAndSwapNode) \
+ declare_c2_type(CompareAndSwapNNode, CompareAndSwapNode) \
+ declare_c2_type(WeakCompareAndSwapLNode, CompareAndSwapNode) \
+ declare_c2_type(WeakCompareAndSwapINode, CompareAndSwapNode) \
+ declare_c2_type(WeakCompareAndSwapPNode, CompareAndSwapNode) \
+ declare_c2_type(WeakCompareAndSwapNNode, CompareAndSwapNode) \
+ declare_c2_type(CompareAndExchangeNode, LoadStoreNode) \
+ declare_c2_type(CompareAndExchangeLNode, CompareAndExchangeNode) \
+ declare_c2_type(CompareAndExchangeINode, CompareAndExchangeNode) \
+ declare_c2_type(CompareAndExchangePNode, CompareAndExchangeNode) \
+ declare_c2_type(CompareAndExchangeNNode, CompareAndExchangeNode) \
declare_c2_type(MulNode, Node) \
declare_c2_type(MulINode, MulNode) \
declare_c2_type(MulLNode, MulNode) \
--- a/hotspot/src/share/vm/utilities/growableArray.hpp Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/src/share/vm/utilities/growableArray.hpp Wed Feb 24 12:38:50 2016 +0000
@@ -396,7 +396,7 @@
int max = length() - 1;
while (max >= min) {
- int mid = (max + min) / 2;
+ int mid = (int)(((uint)max + min) / 2);
E value = at(mid);
int diff = compare(key, value);
if (diff > 0) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/c2/TestDominatingDeadCheckCast.java Wed Feb 24 12:38:50 2016 +0000
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8149797
+ * @summary node replaced by dominating dead cast during parsing
+ * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:TypeProfileLevel=200 -XX:CompileCommand=dontinline,TestDominatingDeadCheckCast::not_inlined TestDominatingDeadCheckCast
+ *
+ */
+
+public class TestDominatingDeadCheckCast {
+
+ static class A {
+ int f;
+ }
+
+ static class B extends A {
+ }
+
+ static A not_inlined() {
+ return new A();
+ }
+
+ static void inlined(A param) {
+ param.f = 42;
+ }
+
+ static A field;
+
+ static void test(boolean flag1, boolean flag2, boolean flag3, boolean flag4, boolean flag5) {
+ // Go through memory rather than through a local to defeat C2's replace_in_map
+ field = not_inlined();
+ // Speculation adds a CheckCast on entry of this inlined
+ // method for the parameter
+ inlined(field);
+ // Walk up the dominators is depth limited, make the CheckCast
+ // above unreachable from the last inlined call
+ if (flag1) {
+ if (flag2) {
+ if (flag3) {
+ // Speculation adds a CheckCast on entry of this
+ // inlined method for the parameter. This
+ // CheckCast is replaced by the CheckCast of the
+ // first inlined method call but the replaced
+ // CheckCast is still around during parsing.
+ inlined(field);
+ // Same as above, some useless control
+ if (flag4) {
+ if (flag5) {
+ // Speculation adds a CheckCast on entry
+ // of this inlined method for the
+ // parameter. This CheckCast is replaced
+ // by the dead CheckCast of the previous
+ // inlined() call.
+ inlined(field);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ static public void main(String[] args) {
+ field = new A();
+ for (int i = 0; i < 20000; i++) {
+ test(true, true, true, true, true);
+ }
+ }
+}
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.java Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.java Wed Feb 24 12:38:50 2016 +0000
@@ -128,6 +128,20 @@
}
+ // Lazy
+ {
+ UNSAFE.putBooleanRelease(base, offset, true);
+ boolean x = UNSAFE.getBooleanAcquire(base, offset);
+ assertEquals(x, true, "putRelease boolean value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putBooleanOpaque(base, offset, false);
+ boolean x = UNSAFE.getBooleanOpaque(base, offset);
+ assertEquals(x, false, "putOpaque boolean value");
+ }
+
}
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.java Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.java Wed Feb 24 12:38:50 2016 +0000
@@ -157,6 +157,20 @@
}
+ // Lazy
+ {
+ UNSAFE.putByteRelease(base, offset, (byte)1);
+ byte x = UNSAFE.getByteAcquire(base, offset);
+ assertEquals(x, (byte)1, "putRelease byte value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putByteOpaque(base, offset, (byte)2);
+ byte x = UNSAFE.getByteOpaque(base, offset);
+ assertEquals(x, (byte)2, "putOpaque byte value");
+ }
+
}
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.java Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.java Wed Feb 24 12:38:50 2016 +0000
@@ -157,6 +157,20 @@
}
+ // Lazy
+ {
+ UNSAFE.putCharRelease(base, offset, 'a');
+ char x = UNSAFE.getCharAcquire(base, offset);
+ assertEquals(x, 'a', "putRelease char value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putCharOpaque(base, offset, 'b');
+ char x = UNSAFE.getCharOpaque(base, offset);
+ assertEquals(x, 'b', "putOpaque char value");
+ }
+
// Unaligned
{
UNSAFE.putCharUnaligned(base, offset, 'b');
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.java Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.java Wed Feb 24 12:38:50 2016 +0000
@@ -157,6 +157,20 @@
}
+ // Lazy
+ {
+ UNSAFE.putDoubleRelease(base, offset, 1.0d);
+ double x = UNSAFE.getDoubleAcquire(base, offset);
+ assertEquals(x, 1.0d, "putRelease double value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putDoubleOpaque(base, offset, 2.0d);
+ double x = UNSAFE.getDoubleOpaque(base, offset);
+ assertEquals(x, 2.0d, "putOpaque double value");
+ }
+
}
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.java Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.java Wed Feb 24 12:38:50 2016 +0000
@@ -157,6 +157,20 @@
}
+ // Lazy
+ {
+ UNSAFE.putFloatRelease(base, offset, 1.0f);
+ float x = UNSAFE.getFloatAcquire(base, offset);
+ assertEquals(x, 1.0f, "putRelease float value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putFloatOpaque(base, offset, 2.0f);
+ float x = UNSAFE.getFloatOpaque(base, offset);
+ assertEquals(x, 2.0f, "putOpaque float value");
+ }
+
}
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.java Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.java Wed Feb 24 12:38:50 2016 +0000
@@ -163,6 +163,20 @@
assertEquals(x, 1, "putRelease int value");
}
+ // Lazy
+ {
+ UNSAFE.putIntRelease(base, offset, 1);
+ int x = UNSAFE.getIntAcquire(base, offset);
+ assertEquals(x, 1, "putRelease int value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putIntOpaque(base, offset, 2);
+ int x = UNSAFE.getIntOpaque(base, offset);
+ assertEquals(x, 2, "putOpaque int value");
+ }
+
// Unaligned
{
UNSAFE.putIntUnaligned(base, offset, 2);
@@ -199,6 +213,70 @@
assertEquals(x, 2, "failing compareAndSwap int value");
}
+ // Advanced compare
+ {
+ int r = UNSAFE.compareAndExchangeIntVolatile(base, offset, 2, 1);
+ assertEquals(r, 2, "success compareAndExchangeVolatile int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 1, "success compareAndExchangeVolatile int value");
+ }
+
+ {
+ int r = UNSAFE.compareAndExchangeIntVolatile(base, offset, 2, 3);
+ assertEquals(r, 1, "failing compareAndExchangeVolatile int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 1, "failing compareAndExchangeVolatile int value");
+ }
+
+ {
+ int r = UNSAFE.compareAndExchangeIntAcquire(base, offset, 1, 2);
+ assertEquals(r, 1, "success compareAndExchangeAcquire int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 2, "success compareAndExchangeAcquire int value");
+ }
+
+ {
+ int r = UNSAFE.compareAndExchangeIntAcquire(base, offset, 1, 3);
+ assertEquals(r, 2, "failing compareAndExchangeAcquire int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 2, "failing compareAndExchangeAcquire int value");
+ }
+
+ {
+ int r = UNSAFE.compareAndExchangeIntRelease(base, offset, 2, 1);
+ assertEquals(r, 2, "success compareAndExchangeRelease int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 1, "success compareAndExchangeRelease int value");
+ }
+
+ {
+ int r = UNSAFE.compareAndExchangeIntRelease(base, offset, 2, 3);
+ assertEquals(r, 1, "failing compareAndExchangeRelease int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 1, "failing compareAndExchangeRelease int value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapInt(base, offset, 1, 2);
+ assertEquals(r, true, "weakCompareAndSwap int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 2, "weakCompareAndSwap int value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapIntAcquire(base, offset, 2, 1);
+ assertEquals(r, true, "weakCompareAndSwapAcquire int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 1, "weakCompareAndSwapAcquire int");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapIntRelease(base, offset, 1, 2);
+ assertEquals(r, true, "weakCompareAndSwapRelease int");
+ int x = UNSAFE.getInt(base, offset);
+ assertEquals(x, 2, "weakCompareAndSwapRelease int");
+ }
+
// Compare set and get
{
int o = UNSAFE.getAndSetInt(base, offset, 1);
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.java Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.java Wed Feb 24 12:38:50 2016 +0000
@@ -163,6 +163,20 @@
assertEquals(x, 1L, "putRelease long value");
}
+ // Lazy
+ {
+ UNSAFE.putLongRelease(base, offset, 1L);
+ long x = UNSAFE.getLongAcquire(base, offset);
+ assertEquals(x, 1L, "putRelease long value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putLongOpaque(base, offset, 2L);
+ long x = UNSAFE.getLongOpaque(base, offset);
+ assertEquals(x, 2L, "putOpaque long value");
+ }
+
// Unaligned
{
UNSAFE.putLongUnaligned(base, offset, 2L);
@@ -199,6 +213,70 @@
assertEquals(x, 2L, "failing compareAndSwap long value");
}
+ // Advanced compare
+ {
+ long r = UNSAFE.compareAndExchangeLongVolatile(base, offset, 2L, 1L);
+ assertEquals(r, 2L, "success compareAndExchangeVolatile long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 1L, "success compareAndExchangeVolatile long value");
+ }
+
+ {
+ long r = UNSAFE.compareAndExchangeLongVolatile(base, offset, 2L, 3L);
+ assertEquals(r, 1L, "failing compareAndExchangeVolatile long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 1L, "failing compareAndExchangeVolatile long value");
+ }
+
+ {
+ long r = UNSAFE.compareAndExchangeLongAcquire(base, offset, 1L, 2L);
+ assertEquals(r, 1L, "success compareAndExchangeAcquire long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 2L, "success compareAndExchangeAcquire long value");
+ }
+
+ {
+ long r = UNSAFE.compareAndExchangeLongAcquire(base, offset, 1L, 3L);
+ assertEquals(r, 2L, "failing compareAndExchangeAcquire long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 2L, "failing compareAndExchangeAcquire long value");
+ }
+
+ {
+ long r = UNSAFE.compareAndExchangeLongRelease(base, offset, 2L, 1L);
+ assertEquals(r, 2L, "success compareAndExchangeRelease long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 1L, "success compareAndExchangeRelease long value");
+ }
+
+ {
+ long r = UNSAFE.compareAndExchangeLongRelease(base, offset, 2L, 3L);
+ assertEquals(r, 1L, "failing compareAndExchangeRelease long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 1L, "failing compareAndExchangeRelease long value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapLong(base, offset, 1L, 2L);
+ assertEquals(r, true, "weakCompareAndSwap long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 2L, "weakCompareAndSwap long value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapLongAcquire(base, offset, 2L, 1L);
+ assertEquals(r, true, "weakCompareAndSwapAcquire long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 1L, "weakCompareAndSwapAcquire long");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapLongRelease(base, offset, 1L, 2L);
+ assertEquals(r, true, "weakCompareAndSwapRelease long");
+ long x = UNSAFE.getLong(base, offset);
+ assertEquals(x, 2L, "weakCompareAndSwapRelease long");
+ }
+
// Compare set and get
{
long o = UNSAFE.getAndSetLong(base, offset, 1L);
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.java Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.java Wed Feb 24 12:38:50 2016 +0000
@@ -134,6 +134,20 @@
assertEquals(x, "foo", "putRelease Object value");
}
+ // Lazy
+ {
+ UNSAFE.putObjectRelease(base, offset, "foo");
+ Object x = UNSAFE.getObjectAcquire(base, offset);
+ assertEquals(x, "foo", "putRelease Object value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putObjectOpaque(base, offset, "bar");
+ Object x = UNSAFE.getObjectOpaque(base, offset);
+ assertEquals(x, "bar", "putOpaque Object value");
+ }
+
UNSAFE.putObject(base, offset, "foo");
@@ -152,6 +166,70 @@
assertEquals(x, "bar", "failing compareAndSwap Object value");
}
+ // Advanced compare
+ {
+ Object r = UNSAFE.compareAndExchangeObjectVolatile(base, offset, "bar", "foo");
+ assertEquals(r, "bar", "success compareAndExchangeVolatile Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "foo", "success compareAndExchangeVolatile Object value");
+ }
+
+ {
+ Object r = UNSAFE.compareAndExchangeObjectVolatile(base, offset, "bar", "baz");
+ assertEquals(r, "foo", "failing compareAndExchangeVolatile Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "foo", "failing compareAndExchangeVolatile Object value");
+ }
+
+ {
+ Object r = UNSAFE.compareAndExchangeObjectAcquire(base, offset, "foo", "bar");
+ assertEquals(r, "foo", "success compareAndExchangeAcquire Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "bar", "success compareAndExchangeAcquire Object value");
+ }
+
+ {
+ Object r = UNSAFE.compareAndExchangeObjectAcquire(base, offset, "foo", "baz");
+ assertEquals(r, "bar", "failing compareAndExchangeAcquire Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "bar", "failing compareAndExchangeAcquire Object value");
+ }
+
+ {
+ Object r = UNSAFE.compareAndExchangeObjectRelease(base, offset, "bar", "foo");
+ assertEquals(r, "bar", "success compareAndExchangeRelease Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "foo", "success compareAndExchangeRelease Object value");
+ }
+
+ {
+ Object r = UNSAFE.compareAndExchangeObjectRelease(base, offset, "bar", "baz");
+ assertEquals(r, "foo", "failing compareAndExchangeRelease Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "foo", "failing compareAndExchangeRelease Object value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapObject(base, offset, "foo", "bar");
+ assertEquals(r, true, "weakCompareAndSwap Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "bar", "weakCompareAndSwap Object value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapObjectAcquire(base, offset, "bar", "foo");
+ assertEquals(r, true, "weakCompareAndSwapAcquire Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "foo", "weakCompareAndSwapAcquire Object");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwapObjectRelease(base, offset, "foo", "bar");
+ assertEquals(r, true, "weakCompareAndSwapRelease Object");
+ Object x = UNSAFE.getObject(base, offset);
+ assertEquals(x, "bar", "weakCompareAndSwapRelease Object");
+ }
+
// Compare set and get
{
Object o = UNSAFE.getAndSetObject(base, offset, "foo");
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.java Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.java Wed Feb 24 12:38:50 2016 +0000
@@ -157,6 +157,20 @@
}
+ // Lazy
+ {
+ UNSAFE.putShortRelease(base, offset, (short)1);
+ short x = UNSAFE.getShortAcquire(base, offset);
+ assertEquals(x, (short)1, "putRelease short value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.putShortOpaque(base, offset, (short)2);
+ short x = UNSAFE.getShortOpaque(base, offset);
+ assertEquals(x, (short)2, "putOpaque short value");
+ }
+
// Unaligned
{
UNSAFE.putShortUnaligned(base, offset, (short)2);
--- a/hotspot/test/compiler/unsafe/X-UnsafeAccessTest.java.template Wed Feb 17 14:06:45 2016 +0000
+++ b/hotspot/test/compiler/unsafe/X-UnsafeAccessTest.java.template Wed Feb 24 12:38:50 2016 +0000
@@ -170,6 +170,22 @@
#end[Ordered]
#if[JdkInternalMisc]
+ // Lazy
+ {
+ UNSAFE.put$Type$Release(base, offset, $value1$);
+ $type$ x = UNSAFE.get$Type$Acquire(base, offset);
+ assertEquals(x, $value1$, "putRelease $type$ value");
+ }
+
+ // Opaque
+ {
+ UNSAFE.put$Type$Opaque(base, offset, $value2$);
+ $type$ x = UNSAFE.get$Type$Opaque(base, offset);
+ assertEquals(x, $value2$, "putOpaque $type$ value");
+ }
+#end[JdkInternalMisc]
+
+#if[JdkInternalMisc]
#if[Unaligned]
// Unaligned
{
@@ -210,6 +226,72 @@
assertEquals(x, $value2$, "failing compareAndSwap $type$ value");
}
+#if[JdkInternalMisc]
+ // Advanced compare
+ {
+ $type$ r = UNSAFE.compareAndExchange$Type$Volatile(base, offset, $value2$, $value1$);
+ assertEquals(r, $value2$, "success compareAndExchangeVolatile $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value1$, "success compareAndExchangeVolatile $type$ value");
+ }
+
+ {
+ $type$ r = UNSAFE.compareAndExchange$Type$Volatile(base, offset, $value2$, $value3$);
+ assertEquals(r, $value1$, "failing compareAndExchangeVolatile $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value1$, "failing compareAndExchangeVolatile $type$ value");
+ }
+
+ {
+ $type$ r = UNSAFE.compareAndExchange$Type$Acquire(base, offset, $value1$, $value2$);
+ assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
+ }
+
+ {
+ $type$ r = UNSAFE.compareAndExchange$Type$Acquire(base, offset, $value1$, $value3$);
+ assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
+ }
+
+ {
+ $type$ r = UNSAFE.compareAndExchange$Type$Release(base, offset, $value2$, $value1$);
+ assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
+ }
+
+ {
+ $type$ r = UNSAFE.compareAndExchange$Type$Release(base, offset, $value2$, $value3$);
+ assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwap$Type$(base, offset, $value1$, $value2$);
+ assertEquals(r, true, "weakCompareAndSwap $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value2$, "weakCompareAndSwap $type$ value");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwap$Type$Acquire(base, offset, $value2$, $value1$);
+ assertEquals(r, true, "weakCompareAndSwapAcquire $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value1$, "weakCompareAndSwapAcquire $type$");
+ }
+
+ {
+ boolean r = UNSAFE.weakCompareAndSwap$Type$Release(base, offset, $value1$, $value2$);
+ assertEquals(r, true, "weakCompareAndSwapRelease $type$");
+ $type$ x = UNSAFE.get$Type$(base, offset);
+ assertEquals(x, $value2$, "weakCompareAndSwapRelease $type$");
+ }
+#end[JdkInternalMisc]
+
// Compare set and get
{
$type$ o = UNSAFE.getAndSet$Type$(base, offset, $value1$);
@@ -244,4 +326,5 @@
}
#end[!boolean]
#end[!Object]
-}
\ No newline at end of file
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/unsafe/generate-unsafe-tests.sh Wed Feb 24 12:38:50 2016 +0000
@@ -0,0 +1,97 @@
+#!/bin/bash
+
+javac -d . ../../../../jdk/make/src/classes/build/tools/spp/Spp.java
+
+SPP=build.tools.spp.Spp
+
+# Generates unsafe access tests for objects and all primitive types
+# $1 = package name to Unsafe, sun.misc | jdk.internal.misc
+# $2 = test class qualifier name, SunMisc | JdkInternalMisc
+function generate {
+ package=$1
+ Qualifier=$2
+
+ for type in boolean byte short char int long float double Object
+ do
+ Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}"
+ args="-K$type -Dtype=$type -DType=$Type"
+
+ case $type in
+ Object|int|long)
+ args="$args -KCAS -KOrdered"
+ ;;
+ esac
+
+ case $type in
+ int|long)
+ args="$args -KAtomicAdd"
+ ;;
+ esac
+
+ case $type in
+ short|char|int|long)
+ args="$args -KUnaligned"
+ ;;
+ esac
+
+ case $type in
+ boolean)
+ value1=true
+ value2=false
+ value3=false
+ ;;
+ byte)
+ value1=(byte)1
+ value2=(byte)2
+ value3=(byte)3
+ ;;
+ short)
+ value1=(short)1
+ value2=(short)2
+ value3=(short)3
+ ;;
+ char)
+ value1=\'a\'
+ value2=\'b\'
+ value3=\'c\'
+ ;;
+ int)
+ value1=1
+ value2=2
+ value3=3
+ ;;
+ long)
+ value1=1L
+ value2=2L
+ value3=3L
+ ;;
+ float)
+ value1=1.0f
+ value2=2.0f
+ value3=3.0f
+ ;;
+ double)
+ value1=1.0d
+ value2=2.0d
+ value3=3.0d
+ ;;
+ Object)
+ value1=\"foo\"
+ value2=\"bar\"
+ value3=\"baz\"
+ ;;
+ esac
+
+ args="$args -Dvalue1=$value1 -Dvalue2=$value2 -Dvalue3=$value3"
+
+ echo $args
+
+ java $SPP -nel -K$Qualifier -Dpackage=$package -DQualifier=$Qualifier \
+ $args < X-UnsafeAccessTest.java.template > ${Qualifier}UnsafeAccessTest${Type}.java
+ done
+}
+
+generate sun.misc SunMisc
+generate jdk.internal.misc JdkInternalMisc
+
+rm -fr build
\ No newline at end of file