8148146: Integrate new internal Unsafe entry points, and basic intrinsic support for VarHandles

Reviewed-by: psandoz, kvn, jrose, adinn, simonis, coleenp
This commit is contained in:
Aleksey Shipilev 2016-02-23 22:09:41 +03:00
parent 449c65bf50
commit 0c43809cfe
27 changed files with 1590 additions and 295 deletions

View file

@ -7236,6 +7236,7 @@ instruct storeLConditional( memory mem, eADXRegL oldval, eBCXRegL newval, eFlags
instruct compareAndSwapL( rRegI res, eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{ instruct compareAndSwapL( rRegI res, eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{
predicate(VM_Version::supports_cx8()); predicate(VM_Version::supports_cx8());
match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval))); match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval)));
match(Set res (WeakCompareAndSwapL mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval); effect(KILL cr, KILL oldval);
format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EDX:EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EDX:EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
"MOV $res,0\n\t" "MOV $res,0\n\t"
@ -7249,6 +7250,7 @@ instruct compareAndSwapL( rRegI res, eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL
instruct compareAndSwapP( rRegI res, pRegP mem_ptr, eAXRegP oldval, eCXRegP newval, eFlagsReg cr) %{ 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 (CompareAndSwapP mem_ptr (Binary oldval newval)));
match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval); effect(KILL cr, KILL oldval);
format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
"MOV $res,0\n\t" "MOV $res,0\n\t"
@ -7261,6 +7263,7 @@ instruct compareAndSwapP( rRegI res, pRegP mem_ptr, eAXRegP oldval, eCXRegP new
instruct compareAndSwapI( rRegI res, pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{ 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 (CompareAndSwapI mem_ptr (Binary oldval newval)));
match(Set res (WeakCompareAndSwapI mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval); effect(KILL cr, KILL oldval);
format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
"MOV $res,0\n\t" "MOV $res,0\n\t"
@ -7271,6 +7274,31 @@ instruct compareAndSwapI( rRegI res, pRegP mem_ptr, eAXRegI oldval, eCXRegI newv
ins_pipe( pipe_cmpxchg ); 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) %{ instruct xaddI_no_res( memory mem, Universe dummy, immI add, eFlagsReg cr) %{
predicate(n->as_LoadStore()->result_not_used()); predicate(n->as_LoadStore()->result_not_used());
match(Set dummy (GetAndAddI mem add)); match(Set dummy (GetAndAddI mem add));

View file

@ -7281,6 +7281,7 @@ instruct compareAndSwapP(rRegI res,
%{ %{
predicate(VM_Version::supports_cx8()); predicate(VM_Version::supports_cx8());
match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval))); match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval)));
match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval); effect(KILL cr, KILL oldval);
format %{ "cmpxchgq $mem_ptr,$newval\t# " format %{ "cmpxchgq $mem_ptr,$newval\t# "
@ -7305,6 +7306,7 @@ instruct compareAndSwapL(rRegI res,
%{ %{
predicate(VM_Version::supports_cx8()); predicate(VM_Version::supports_cx8());
match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval))); match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval)));
match(Set res (WeakCompareAndSwapL mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval); effect(KILL cr, KILL oldval);
format %{ "cmpxchgq $mem_ptr,$newval\t# " format %{ "cmpxchgq $mem_ptr,$newval\t# "
@ -7328,6 +7330,7 @@ instruct compareAndSwapI(rRegI res,
rFlagsReg cr) rFlagsReg cr)
%{ %{
match(Set res (CompareAndSwapI mem_ptr (Binary oldval newval))); match(Set res (CompareAndSwapI mem_ptr (Binary oldval newval)));
match(Set res (WeakCompareAndSwapI mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval); effect(KILL cr, KILL oldval);
format %{ "cmpxchgl $mem_ptr,$newval\t# " format %{ "cmpxchgl $mem_ptr,$newval\t# "
@ -7351,6 +7354,7 @@ instruct compareAndSwapN(rRegI res,
rax_RegN oldval, rRegN newval, rax_RegN oldval, rRegN newval,
rFlagsReg cr) %{ rFlagsReg cr) %{
match(Set res (CompareAndSwapN mem_ptr (Binary oldval newval))); match(Set res (CompareAndSwapN mem_ptr (Binary oldval newval)));
match(Set res (WeakCompareAndSwapN mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval); effect(KILL cr, KILL oldval);
format %{ "cmpxchgl $mem_ptr,$newval\t# " format %{ "cmpxchgl $mem_ptr,$newval\t# "
@ -7368,6 +7372,83 @@ instruct compareAndSwapN(rRegI res,
ins_pipe( pipe_cmpxchg ); 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) %{ instruct xaddI_no_res( memory mem, Universe dummy, immI add, rFlagsReg cr) %{
predicate(n->as_LoadStore()->result_not_used()); predicate(n->as_LoadStore()->result_not_used());
match(Set dummy (GetAndAddI mem add)); match(Set dummy (GetAndAddI mem add));

View file

@ -3491,6 +3491,8 @@ int MatchNode::needs_ideal_memory_edge(FormDict &globals) const {
"LoadPLocked", "LoadPLocked",
"StorePConditional", "StoreIConditional", "StoreLConditional", "StorePConditional", "StoreIConditional", "StoreLConditional",
"CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN", "CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN",
"WeakCompareAndSwapI", "WeakCompareAndSwapL", "WeakCompareAndSwapP", "WeakCompareAndSwapN",
"CompareAndExchangeI", "CompareAndExchangeL", "CompareAndExchangeP", "CompareAndExchangeN",
"StoreCM", "StoreCM",
"ClearArray", "ClearArray",
"GetAndAddI", "GetAndSetI", "GetAndSetP", "GetAndAddI", "GetAndSetI", "GetAndSetP",

View file

@ -544,6 +544,42 @@ bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) {
case vmIntrinsics::_putLongVolatile: case vmIntrinsics::_putLongVolatile:
case vmIntrinsics::_putFloatVolatile: case vmIntrinsics::_putFloatVolatile:
case vmIntrinsics::_putDoubleVolatile: 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::_getByte_raw:
case vmIntrinsics::_getShort_raw: case vmIntrinsics::_getShort_raw:
case vmIntrinsics::_getChar_raw: case vmIntrinsics::_getChar_raw:
@ -569,9 +605,27 @@ bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) {
case vmIntrinsics::_loadFence: case vmIntrinsics::_loadFence:
case vmIntrinsics::_storeFence: case vmIntrinsics::_storeFence:
case vmIntrinsics::_fullFence: case vmIntrinsics::_fullFence:
case vmIntrinsics::_compareAndSwapObject:
case vmIntrinsics::_compareAndSwapLong: case vmIntrinsics::_compareAndSwapLong:
case vmIntrinsics::_weakCompareAndSwapLong:
case vmIntrinsics::_weakCompareAndSwapLongAcquire:
case vmIntrinsics::_weakCompareAndSwapLongRelease:
case vmIntrinsics::_compareAndSwapInt: case vmIntrinsics::_compareAndSwapInt:
case vmIntrinsics::_weakCompareAndSwapInt:
case vmIntrinsics::_weakCompareAndSwapIntAcquire:
case vmIntrinsics::_weakCompareAndSwapIntRelease:
case vmIntrinsics::_compareAndSwapObject:
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; if (!InlineUnsafeOps) return true;
break; break;
case vmIntrinsics::_getShortUnaligned: case vmIntrinsics::_getShortUnaligned:

View file

@ -1146,6 +1146,64 @@
do_intrinsic(_putFloatVolatile, jdk_internal_misc_Unsafe, putFloatVolatile_name, putFloat_signature, F_RN) \ 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_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(getShortUnaligned_name,"getShortUnaligned") do_name(putShortUnaligned_name,"putShortUnaligned") \
do_name(getCharUnaligned_name,"getCharUnaligned") do_name(putCharUnaligned_name,"putCharUnaligned") \ do_name(getCharUnaligned_name,"getCharUnaligned") do_name(putCharUnaligned_name,"putCharUnaligned") \
do_name(getIntUnaligned_name,"getIntUnaligned") do_name(putIntUnaligned_name,"putIntUnaligned") \ 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(_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(_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_signature(compareAndSwapObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
do_name( compareAndSwapObject_name, "compareAndSwapObject") \ do_signature(compareAndExchangeObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") \
do_signature(compareAndSwapObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \ do_signature(compareAndSwapLong_signature, "(Ljava/lang/Object;JJJ)Z") \
do_intrinsic(_compareAndSwapLong, jdk_internal_misc_Unsafe, compareAndSwapLong_name, compareAndSwapLong_signature, F_R) \ do_signature(compareAndExchangeLong_signature, "(Ljava/lang/Object;JJJ)J") \
do_name( compareAndSwapLong_name, "compareAndSwapLong") \ do_signature(compareAndSwapInt_signature, "(Ljava/lang/Object;JII)Z") \
do_signature(compareAndSwapLong_signature, "(Ljava/lang/Object;JJJ)Z") \ do_signature(compareAndExchangeInt_signature, "(Ljava/lang/Object;JII)I") \
do_intrinsic(_compareAndSwapInt, jdk_internal_misc_Unsafe, compareAndSwapInt_name, compareAndSwapInt_signature, F_R) \ \
do_name( compareAndSwapInt_name, "compareAndSwapInt") \ do_name(compareAndSwapObject_name, "compareAndSwapObject") \
do_signature(compareAndSwapInt_signature, "(Ljava/lang/Object;JII)Z") \ do_name(compareAndExchangeObjectVolatile_name, "compareAndExchangeObjectVolatile") \
do_intrinsic(_putOrderedObject, jdk_internal_misc_Unsafe, putOrderedObject_name, putOrderedObject_signature, F_R) \ do_name(compareAndExchangeObjectAcquire_name, "compareAndExchangeObjectAcquire") \
do_name( putOrderedObject_name, "putOrderedObject") \ do_name(compareAndExchangeObjectRelease_name, "compareAndExchangeObjectRelease") \
do_alias( putOrderedObject_signature, /*(LObject;JLObject;)V*/ putObject_signature) \ do_name(compareAndSwapLong_name, "compareAndSwapLong") \
do_intrinsic(_putOrderedLong, jdk_internal_misc_Unsafe, putOrderedLong_name, putOrderedLong_signature, F_R) \ do_name(compareAndExchangeLongVolatile_name, "compareAndExchangeLongVolatile") \
do_name( putOrderedLong_name, "putOrderedLong") \ do_name(compareAndExchangeLongAcquire_name, "compareAndExchangeLongAcquire") \
do_alias( putOrderedLong_signature, /*(Ljava/lang/Object;JJ)V*/ putLong_signature) \ do_name(compareAndExchangeLongRelease_name, "compareAndExchangeLongRelease") \
do_intrinsic(_putOrderedInt, jdk_internal_misc_Unsafe, putOrderedInt_name, putOrderedInt_signature, F_R) \ do_name(compareAndSwapInt_name, "compareAndSwapInt") \
do_name( putOrderedInt_name, "putOrderedInt") \ do_name(compareAndExchangeIntVolatile_name, "compareAndExchangeIntVolatile") \
do_alias( putOrderedInt_signature, /*(Ljava/lang/Object;JI)V*/ putInt_signature) \ 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_intrinsic(_getAndAddInt, jdk_internal_misc_Unsafe, getAndAddInt_name, getAndAddInt_signature, F_R) \
do_name( getAndAddInt_name, "getAndAddInt") \ do_name( getAndAddInt_name, "getAndAddInt") \

View file

@ -243,14 +243,72 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt
case vmIntrinsics::_reverseBytes_l: case vmIntrinsics::_reverseBytes_l:
if (!Matcher::match_rule_supported(Op_ReverseBytesL)) return false; if (!Matcher::match_rule_supported(Op_ReverseBytesL)) return false;
break; break;
/* CompareAndSwap, Object: */
case vmIntrinsics::_compareAndSwapObject: case vmIntrinsics::_compareAndSwapObject:
#ifdef _LP64 #ifdef _LP64
if ( UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapN)) return false;
if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapP)) return false; if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapP)) return false;
#else
if (!Matcher::match_rule_supported(Op_CompareAndSwapP)) return false;
#endif #endif
break; 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: case vmIntrinsics::_compareAndSwapLong:
if (!Matcher::match_rule_supported(Op_CompareAndSwapL)) return false; if (!Matcher::match_rule_supported(Op_CompareAndSwapL)) return false;
break; 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: case vmIntrinsics::_getAndAddInt:
if (!Matcher::match_rule_supported(Op_GetAndAddI)) return false; if (!Matcher::match_rule_supported(Op_GetAndAddI)) return false;
break; break;
@ -382,6 +440,42 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt
case vmIntrinsics::_putLongVolatile: case vmIntrinsics::_putLongVolatile:
case vmIntrinsics::_putFloatVolatile: case vmIntrinsics::_putFloatVolatile:
case vmIntrinsics::_putDoubleVolatile: 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::_getShortUnaligned:
case vmIntrinsics::_getCharUnaligned: case vmIntrinsics::_getCharUnaligned:
case vmIntrinsics::_getIntUnaligned: case vmIntrinsics::_getIntUnaligned:
@ -390,7 +484,6 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt
case vmIntrinsics::_putCharUnaligned: case vmIntrinsics::_putCharUnaligned:
case vmIntrinsics::_putIntUnaligned: case vmIntrinsics::_putIntUnaligned:
case vmIntrinsics::_putLongUnaligned: case vmIntrinsics::_putLongUnaligned:
case vmIntrinsics::_compareAndSwapInt:
case vmIntrinsics::_putOrderedObject: case vmIntrinsics::_putOrderedObject:
case vmIntrinsics::_putOrderedInt: case vmIntrinsics::_putOrderedInt:
case vmIntrinsics::_putOrderedLong: case vmIntrinsics::_putOrderedLong:

View file

@ -85,6 +85,14 @@ macro(CompareAndSwapI)
macro(CompareAndSwapL) macro(CompareAndSwapL)
macro(CompareAndSwapP) macro(CompareAndSwapP)
macro(CompareAndSwapN) macro(CompareAndSwapN)
macro(WeakCompareAndSwapI)
macro(WeakCompareAndSwapL)
macro(WeakCompareAndSwapP)
macro(WeakCompareAndSwapN)
macro(CompareAndExchangeI)
macro(CompareAndExchangeL)
macro(CompareAndExchangeP)
macro(CompareAndExchangeN)
macro(GetAndAddI) macro(GetAndAddI)
macro(GetAndAddL) macro(GetAndAddL)
macro(GetAndSetI) macro(GetAndSetI)

View file

@ -2786,6 +2786,14 @@ void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) {
case Op_CompareAndSwapL: case Op_CompareAndSwapL:
case Op_CompareAndSwapP: case Op_CompareAndSwapP:
case Op_CompareAndSwapN: 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_GetAndAddI:
case Op_GetAndAddL: case Op_GetAndAddL:
case Op_GetAndSetI: case Op_GetAndSetI:

View file

@ -490,6 +490,8 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de
} }
break; break;
} }
case Op_CompareAndExchangeP:
case Op_CompareAndExchangeN:
case Op_GetAndSetP: case Op_GetAndSetP:
case Op_GetAndSetN: { case Op_GetAndSetN: {
add_objload_to_connection_graph(n, delayed_worklist); add_objload_to_connection_graph(n, delayed_worklist);
@ -499,6 +501,8 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de
case Op_StoreN: case Op_StoreN:
case Op_StoreNKlass: case Op_StoreNKlass:
case Op_StorePConditional: case Op_StorePConditional:
case Op_WeakCompareAndSwapP:
case Op_WeakCompareAndSwapN:
case Op_CompareAndSwapP: case Op_CompareAndSwapP:
case Op_CompareAndSwapN: { case Op_CompareAndSwapN: {
Node* adr = n->in(MemNode::Address); Node* adr = n->in(MemNode::Address);
@ -698,8 +702,12 @@ void ConnectionGraph::add_final_edges(Node *n) {
case Op_StoreN: case Op_StoreN:
case Op_StoreNKlass: case Op_StoreNKlass:
case Op_StorePConditional: case Op_StorePConditional:
case Op_CompareAndExchangeP:
case Op_CompareAndExchangeN:
case Op_CompareAndSwapP: case Op_CompareAndSwapP:
case Op_CompareAndSwapN: case Op_CompareAndSwapN:
case Op_WeakCompareAndSwapP:
case Op_WeakCompareAndSwapN:
case Op_GetAndSetP: case Op_GetAndSetP:
case Op_GetAndSetN: { case Op_GetAndSetN: {
Node* adr = n->in(MemNode::Address); Node* adr = n->in(MemNode::Address);

View file

@ -241,7 +241,9 @@ class LibraryCallKit : public GraphKit {
// Generates the guards that check whether the result of // Generates the guards that check whether the result of
// Unsafe.getObject should be recorded in an SATB log buffer. // 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); 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); static bool klass_needs_init_guard(Node* kls);
bool inline_unsafe_allocate(); bool inline_unsafe_allocate();
bool inline_unsafe_copyMemory(); bool inline_unsafe_copyMemory();
@ -274,9 +276,10 @@ class LibraryCallKit : public GraphKit {
JVMState* arraycopy_restore_alloc_state(AllocateArrayNode* alloc, int& saved_reexecute_sp); 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); 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; typedef enum { LS_get_add, LS_get_set, LS_cmp_swap, LS_cmp_swap_weak, LS_cmp_exchange } LoadStoreKind;
bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind); MemNode::MemOrd access_kind_to_memord_LS(AccessKind access_kind, bool is_store);
bool inline_unsafe_ordered_store(BasicType type); 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_unsafe_fence(vmIntrinsics::ID id);
bool inline_fp_conversions(vmIntrinsics::ID id); bool inline_fp_conversions(vmIntrinsics::ID id);
bool inline_number_methods(vmIntrinsics::ID id); bool inline_number_methods(vmIntrinsics::ID id);
@ -553,86 +556,147 @@ bool LibraryCallKit::try_to_inline(int predicate) {
case vmIntrinsics::_inflateStringC: case vmIntrinsics::_inflateStringC:
case vmIntrinsics::_inflateStringB: return inline_string_copy(!is_compress); 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::_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, !is_volatile, 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, !is_volatile, 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, !is_volatile, 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, !is_volatile, 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, !is_volatile, 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, !is_volatile, 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, !is_volatile, 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, !is_volatile, 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, !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::_putObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Relaxed, false);
case vmIntrinsics::_getShort_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_SHORT, !is_volatile, false); case vmIntrinsics::_putBoolean: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Relaxed, false);
case vmIntrinsics::_getChar_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_CHAR, !is_volatile, false); case vmIntrinsics::_putByte: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Relaxed, false);
case vmIntrinsics::_getInt_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_INT, !is_volatile, false); case vmIntrinsics::_putShort: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Relaxed, false);
case vmIntrinsics::_getLong_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_LONG, !is_volatile, false); case vmIntrinsics::_putChar: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Relaxed, false);
case vmIntrinsics::_getFloat_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_FLOAT, !is_volatile, false); case vmIntrinsics::_putInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Relaxed, false);
case vmIntrinsics::_getDouble_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_DOUBLE, !is_volatile, false); case vmIntrinsics::_putLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Relaxed, false);
case vmIntrinsics::_getAddress_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_ADDRESS, !is_volatile, 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::_putByte_raw: return inline_unsafe_access( is_native_ptr, is_store, T_BYTE, !is_volatile, false); case vmIntrinsics::_getByte_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, !is_volatile, false); case vmIntrinsics::_getShort_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, !is_volatile, false); case vmIntrinsics::_getChar_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, !is_volatile, false); case vmIntrinsics::_getInt_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, !is_volatile, false); case vmIntrinsics::_getLong_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, !is_volatile, false); case vmIntrinsics::_getFloat_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, !is_volatile, false); case vmIntrinsics::_getDouble_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, !is_volatile, false); case vmIntrinsics::_getAddress_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, is_volatile, false); case vmIntrinsics::_putByte_raw: return inline_unsafe_access( is_native_ptr, is_store, T_BYTE, Relaxed, false);
case vmIntrinsics::_getBooleanVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, is_volatile, false); case vmIntrinsics::_putShort_raw: return inline_unsafe_access( is_native_ptr, is_store, T_SHORT, Relaxed, false);
case vmIntrinsics::_getByteVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, is_volatile, false); case vmIntrinsics::_putChar_raw: return inline_unsafe_access( is_native_ptr, is_store, T_CHAR, Relaxed, false);
case vmIntrinsics::_getShortVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, is_volatile, false); case vmIntrinsics::_putInt_raw: return inline_unsafe_access( is_native_ptr, is_store, T_INT, Relaxed, false);
case vmIntrinsics::_getCharVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, is_volatile, false); case vmIntrinsics::_putLong_raw: return inline_unsafe_access( is_native_ptr, is_store, T_LONG, Relaxed, false);
case vmIntrinsics::_getIntVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, is_volatile, false); case vmIntrinsics::_putFloat_raw: return inline_unsafe_access( is_native_ptr, is_store, T_FLOAT, Relaxed, false);
case vmIntrinsics::_getLongVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, is_volatile, false); case vmIntrinsics::_putDouble_raw: return inline_unsafe_access( is_native_ptr, is_store, T_DOUBLE, Relaxed, false);
case vmIntrinsics::_getFloatVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, is_volatile, false); case vmIntrinsics::_putAddress_raw: return inline_unsafe_access( is_native_ptr, is_store, T_ADDRESS, Relaxed, 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::_getObjectVolatile: 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, is_volatile, false); case vmIntrinsics::_getBooleanVolatile: 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, is_volatile, false); case vmIntrinsics::_getByteVolatile: 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, is_volatile, false); case vmIntrinsics::_getShortVolatile: 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, is_volatile, false); case vmIntrinsics::_getCharVolatile: 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, is_volatile, false); case vmIntrinsics::_getIntVolatile: 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, is_volatile, false); case vmIntrinsics::_getLongVolatile: 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, is_volatile, false); case vmIntrinsics::_getFloatVolatile: 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, is_volatile, false); case vmIntrinsics::_getDoubleVolatile: 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, !is_volatile, true); case vmIntrinsics::_putObjectVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Volatile, false);
case vmIntrinsics::_getCharUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, !is_volatile, true); case vmIntrinsics::_putBooleanVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Volatile, false);
case vmIntrinsics::_getIntUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, !is_volatile, true); case vmIntrinsics::_putByteVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Volatile, false);
case vmIntrinsics::_getLongUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, !is_volatile, true); 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::_putShortUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, !is_volatile, true); case vmIntrinsics::_getShortUnaligned: 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, !is_volatile, true); case vmIntrinsics::_getCharUnaligned: 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, !is_volatile, true); case vmIntrinsics::_getIntUnaligned: 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, !is_volatile, true); case vmIntrinsics::_getLongUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Relaxed, true);
case vmIntrinsics::_compareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmpxchg); case vmIntrinsics::_putShortUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Relaxed, true);
case vmIntrinsics::_compareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmpxchg); case vmIntrinsics::_putCharUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Relaxed, true);
case vmIntrinsics::_compareAndSwapLong: return inline_unsafe_load_store(T_LONG, LS_cmpxchg); 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_ordered_store(T_OBJECT); case vmIntrinsics::_putOrderedObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Release, false);
case vmIntrinsics::_putOrderedInt: return inline_unsafe_ordered_store(T_INT); case vmIntrinsics::_putOrderedInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Release, false);
case vmIntrinsics::_putOrderedLong: return inline_unsafe_ordered_store(T_LONG); case vmIntrinsics::_putOrderedLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Release, false);
case vmIntrinsics::_getAndAddInt: return inline_unsafe_load_store(T_INT, LS_xadd); case vmIntrinsics::_getObjectAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Acquire, false);
case vmIntrinsics::_getAndAddLong: return inline_unsafe_load_store(T_LONG, LS_xadd); case vmIntrinsics::_getBooleanAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Acquire, false);
case vmIntrinsics::_getAndSetInt: return inline_unsafe_load_store(T_INT, LS_xchg); case vmIntrinsics::_getByteAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Acquire, false);
case vmIntrinsics::_getAndSetLong: return inline_unsafe_load_store(T_LONG, LS_xchg); case vmIntrinsics::_getShortAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Acquire, false);
case vmIntrinsics::_getAndSetObject: return inline_unsafe_load_store(T_OBJECT, LS_xchg); 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::_loadFence:
case vmIntrinsics::_storeFence: case vmIntrinsics::_storeFence:
@ -2284,8 +2348,10 @@ const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_
return NULL; 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! 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 #ifndef PRODUCT
{ {
@ -2374,7 +2440,42 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
// the barriers get omitted and the unsafe reference begins to "pollute" // the barriers get omitted and the unsafe reference begins to "pollute"
// the alias analysis of the rest of the graph, either Compile::can_alias // the alias analysis of the rest of the graph, either Compile::can_alias
// or Compile::must_alias will throw a diagnostic assert.) // 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 // If we are reading the value of the referent field of a Reference
// object (either by using Unsafe directly or through reflection) // object (either by using Unsafe directly or through reflection)
@ -2401,22 +2502,30 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
// and it is not possible to fully distinguish unintended nulls // and it is not possible to fully distinguish unintended nulls
// from intended ones in this API. // from intended ones in this API.
if (is_volatile) { // We need to emit leading and trailing CPU membars (see below) in
// We need to emit leading and trailing CPU membars (see below) in // addition to memory membars for special access modes. This is a little
// addition to memory membars when is_volatile. This is a little // too strong, but avoids the need to insert per-alias-type
// too strong, but avoids the need to insert per-alias-type // volatile membars (for stores; compare Parse::do_put_xxx), which
// volatile membars (for stores; compare Parse::do_put_xxx), which // we cannot do effectively here because we probably only have a
// we cannot do effectively here because we probably only have a // rough approximation of type.
// rough approximation of type.
need_mem_bar = true; switch(kind) {
// For Stores, place a memory ordering barrier now. case Relaxed:
if (is_store) { case Opaque:
insert_mem_bar(Op_MemBarRelease); case Acquire:
} else { break;
if (support_IRIW_for_not_multiple_copy_atomic_cpu) { case Release:
insert_mem_bar(Op_MemBarVolatile); 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 // Memory barrier to prevent normal and 'unsafe' accesses from
@ -2460,10 +2569,9 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
} }
} }
if (p == NULL) { if (p == NULL) {
MemNode::MemOrd mo = is_volatile ? MemNode::acquire : MemNode::unordered;
// To be valid, unsafe loads may depend on other conditions than // To be valid, unsafe loads may depend on other conditions than
// the one that guards them: pin the Load node // 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 // load value
switch (type) { switch (type) {
case T_BOOLEAN: case T_BOOLEAN:
@ -2477,7 +2585,9 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
break; break;
case T_OBJECT: case T_OBJECT:
if (need_read_barrier) { 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; break;
case T_ADDRESS: case T_ADDRESS:
@ -2508,9 +2618,8 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
break; break;
} }
MemNode::MemOrd mo = is_volatile ? MemNode::release : MemNode::unordered; if (type != T_OBJECT) {
if (type != T_OBJECT ) { (void) store_to_memory(control(), adr, val, type, adr_type, mo, requires_atomic_access, unaligned, mismatched);
(void) store_to_memory(control(), adr, val, type, adr_type, mo, is_volatile, unaligned, mismatched);
} else { } else {
// Possibly an oop being stored to Java heap or native memory // Possibly an oop being stored to Java heap or native memory
if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) { if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) {
@ -2531,7 +2640,7 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
// Update IdealKit memory. // Update IdealKit memory.
__ sync_kit(this); __ sync_kit(this);
} __ else_(); { } __ 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(); } __ end_if();
// Final sync IdealKit and GraphKit. // Final sync IdealKit and GraphKit.
final_sync(ideal); final_sync(ideal);
@ -2540,14 +2649,23 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
} }
} }
if (is_volatile) { switch(kind) {
if (!is_store) { case Relaxed:
insert_mem_bar(Op_MemBarAcquire); case Opaque:
} else { case Release:
if (!support_IRIW_for_not_multiple_copy_atomic_cpu) { break;
insert_mem_bar(Op_MemBarVolatile); 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); if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder);
@ -2558,21 +2676,52 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
//----------------------------inline_unsafe_load_store---------------------------- //----------------------------inline_unsafe_load_store----------------------------
// This method serves a couple of different customers (depending on LoadStoreKind): // This method serves a couple of different customers (depending on LoadStoreKind):
// //
// LS_cmpxchg: // LS_cmp_swap:
// 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_xadd: // boolean compareAndSwapObject(Object o, long offset, Object expected, Object x);
// public int getAndAddInt( Object o, long offset, int delta) // boolean compareAndSwapInt( Object o, long offset, int expected, int x);
// public long getAndAddLong(Object o, long offset, long delta) // 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_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);
//
// 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:
// //
// LS_xchg:
// int getAndSet(Object o, long offset, int newValue) // int getAndSet(Object o, long offset, int newValue)
// long getAndSet(Object o, long offset, long newValue) // long getAndSet(Object o, long offset, long newValue)
// Object getAndSet(Object o, long offset, Object 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 // This basic scheme here is the same as inline_unsafe_access, but
// differs in enough details that combining them would make the code // differs in enough details that combining them would make the code
// overly confusing. (This is a true fact! I originally combined // overly confusing. (This is a true fact! I originally combined
@ -2589,7 +2738,9 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind
// Check the signatures. // Check the signatures.
ciSignature* sig = callee()->signature(); ciSignature* sig = callee()->signature();
rtype = sig->return_type()->basic_type(); 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. // Check the signatures.
#ifdef ASSERT #ifdef ASSERT
assert(rtype == type, "get and set must return the expected type"); assert(rtype == type, "get and set must return the expected type");
@ -2598,7 +2749,10 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind
assert(sig->type_at(1)->basic_type() == T_LONG, "get and set offset is long"); 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"); assert(sig->type_at(2)->basic_type() == type, "get and set must take expected type as new value/delta");
#endif // ASSERT #endif // ASSERT
} else if (kind == LS_cmpxchg) { break;
}
case LS_cmp_swap:
case LS_cmp_swap_weak: {
// Check the signatures. // Check the signatures.
#ifdef ASSERT #ifdef ASSERT
assert(rtype == T_BOOLEAN, "CAS must return boolean"); assert(rtype == T_BOOLEAN, "CAS must return boolean");
@ -2606,8 +2760,20 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind
assert(sig->type_at(0)->basic_type() == T_OBJECT, "CAS base is object"); 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"); assert(sig->type_at(1)->basic_type() == T_LONG, "CAS offset is long");
#endif // ASSERT #endif // ASSERT
} else { break;
ShouldNotReachHere(); }
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 #endif //PRODUCT
@ -2620,19 +2786,29 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind
Node* offset = NULL; Node* offset = NULL;
Node* oldval = NULL; Node* oldval = NULL;
Node* newval = NULL; Node* newval = NULL;
if (kind == LS_cmpxchg) { switch(kind) {
const bool two_slot_type = type2size[type] == 2; case LS_cmp_swap:
receiver = argument(0); // type: oop case LS_cmp_swap_weak:
base = argument(1); // type: oop case LS_cmp_exchange: {
offset = argument(2); // type: long const bool two_slot_type = type2size[type] == 2;
oldval = argument(4); // type: oop, int, or long receiver = argument(0); // type: oop
newval = argument(two_slot_type ? 6 : 5); // type: oop, int, or long base = argument(1); // type: oop
} else if (kind == LS_xadd || kind == LS_xchg){ offset = argument(2); // type: long
receiver = argument(0); // type: oop oldval = argument(4); // type: oop, int, or long
base = argument(1); // type: oop newval = argument(two_slot_type ? 6 : 5); // type: oop, int, or long
offset = argument(2); // type: long break;
oldval = NULL; }
newval = argument(4); // type: oop, int, or long 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. // Null check receiver.
@ -2657,11 +2833,23 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind
Compile::AliasType* alias_type = C->alias_type(adr_type); Compile::AliasType* alias_type = C->alias_type(adr_type);
assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here"); assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here");
if (kind == LS_xchg && type == T_OBJECT) { switch (kind) {
const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type); case LS_get_set:
if (tjp != NULL) { case LS_cmp_exchange: {
value_type = tjp; 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); int alias_idx = C->get_alias_index(adr_type);
@ -2671,9 +2859,22 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind
// into actual barriers on most machines, but we still need rest of // into actual barriers on most machines, but we still need rest of
// compiler to respect ordering. // 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); 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 // 4984716: MemBars must be inserted before this
// memory node in order to avoid a false // memory node in order to avoid a false
// dependency which will confuse the scheduler. // dependency which will confuse the scheduler.
@ -2684,25 +2885,45 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind
Node* load_store = NULL; Node* load_store = NULL;
switch(type) { switch(type) {
case T_INT: case T_INT:
if (kind == LS_xadd) { switch(kind) {
load_store = _gvn.transform(new GetAndAddINode(control(), mem, adr, newval, adr_type)); case LS_get_add:
} else if (kind == LS_xchg) { load_store = _gvn.transform(new GetAndAddINode(control(), mem, adr, newval, adr_type));
load_store = _gvn.transform(new GetAndSetINode(control(), mem, adr, newval, adr_type)); break;
} else if (kind == LS_cmpxchg) { case LS_get_set:
load_store = _gvn.transform(new CompareAndSwapINode(control(), mem, adr, newval, oldval)); load_store = _gvn.transform(new GetAndSetINode(control(), mem, adr, newval, adr_type));
} else { break;
ShouldNotReachHere(); 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; break;
case T_LONG: case T_LONG:
if (kind == LS_xadd) { switch(kind) {
load_store = _gvn.transform(new GetAndAddLNode(control(), mem, adr, newval, adr_type)); case LS_get_add:
} else if (kind == LS_xchg) { load_store = _gvn.transform(new GetAndAddLNode(control(), mem, adr, newval, adr_type));
load_store = _gvn.transform(new GetAndSetLNode(control(), mem, adr, newval, adr_type)); break;
} else if (kind == LS_cmpxchg) { case LS_get_set:
load_store = _gvn.transform(new CompareAndSwapLNode(control(), mem, adr, newval, oldval)); load_store = _gvn.transform(new GetAndSetLNode(control(), mem, adr, newval, adr_type));
} else { break;
ShouldNotReachHere(); 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; break;
case T_OBJECT: case T_OBJECT:
@ -2713,65 +2934,109 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind
newval = _gvn.makecon(TypePtr::NULL_PTR); newval = _gvn.makecon(TypePtr::NULL_PTR);
// Reference stores need a store barrier. // Reference stores need a store barrier.
if (kind == LS_xchg) { switch(kind) {
// If pre-barrier must execute before the oop store, old value will require do_load here. case LS_get_set: {
if (!can_move_pre_barrier()) { // If pre-barrier must execute before the oop store, old value will require do_load here.
pre_barrier(true /* do_load*/, if (!can_move_pre_barrier()) {
control(), base, adr, alias_idx, newval, value_type->make_oopptr(), pre_barrier(true /* do_load*/,
NULL /* pre_val*/, control(), base, adr, alias_idx, newval, value_type->make_oopptr(),
T_OBJECT); NULL /* pre_val*/,
} // Else move pre_barrier to use load_store value, see below. T_OBJECT);
} else if (kind == LS_cmpxchg) { } // Else move pre_barrier to use load_store value, see below.
// Same as for newval above: break;
if (_gvn.type(oldval) == TypePtr::NULL_PTR) {
oldval = _gvn.makecon(TypePtr::NULL_PTR);
} }
// The only known value which might get overwritten is oldval. case LS_cmp_swap_weak:
pre_barrier(false /* do_load */, case LS_cmp_swap:
control(), NULL, NULL, max_juint, NULL, NULL, case LS_cmp_exchange: {
oldval /* pre_val */, // Same as for newval above:
T_OBJECT); if (_gvn.type(oldval) == TypePtr::NULL_PTR) {
} else { oldval = _gvn.makecon(TypePtr::NULL_PTR);
ShouldNotReachHere(); }
// 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);
break;
}
default:
ShouldNotReachHere();
} }
#ifdef _LP64 #ifdef _LP64
if (adr->bottom_type()->is_ptr_to_narrowoop()) { if (adr->bottom_type()->is_ptr_to_narrowoop()) {
Node *newval_enc = _gvn.transform(new EncodePNode(newval, newval->bottom_type()->make_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, switch(kind) {
newval_enc, adr_type, value_type->make_narrowoop())); case LS_get_set:
} else { load_store = _gvn.transform(new GetAndSetNNode(control(), mem, adr, newval_enc, adr_type, value_type->make_narrowoop()));
assert(kind == LS_cmpxchg, "wrong LoadStore operation"); break;
Node *oldval_enc = _gvn.transform(new EncodePNode(oldval, oldval->bottom_type()->make_narrowoop())); case LS_cmp_swap_weak: {
load_store = _gvn.transform(new CompareAndSwapNNode(control(), mem, adr, Node *oldval_enc = _gvn.transform(new EncodePNode(oldval, oldval->bottom_type()->make_narrowoop()));
newval_enc, oldval_enc)); 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 } else
#endif #endif
{ switch (kind) {
if (kind == LS_xchg) { case LS_get_set:
load_store = _gvn.transform(new GetAndSetPNode(control(), mem, adr, newval, adr_type, value_type->is_oopptr())); load_store = _gvn.transform(new GetAndSetPNode(control(), mem, adr, newval, adr_type, value_type->is_oopptr()));
} else { break;
assert(kind == LS_cmpxchg, "wrong LoadStore operation"); case LS_cmp_swap_weak:
load_store = _gvn.transform(new CompareAndSwapPNode(control(), mem, adr, newval, oldval)); 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. // Emit the post barrier only when the actual store happened. This makes sense
// This makes sense to check only for compareAndSet that can fail to set the value. // to check only for LS_cmp_* that can fail to set the value.
// CAS success path is marked more likely since we anticipate this is a performance // LS_cmp_exchange does not produce any branches by default, so there is no
// critical path, while CAS failure path can use the penalty for going through unlikely // boolean result to piggyback on. TODO: When we merge CompareAndSwap with
// path as backoff. Which is still better than doing a store barrier there. // CompareAndExchange and move branches here, it would make sense to conditionalize
IdealKit ideal(this); // post_barriers for LS_cmp_exchange as well.
ideal.if_then(load_store, BoolTest::ne, ideal.ConI(0), PROB_STATIC_FREQUENT); { //
sync_kit(ideal); // CAS success path is marked more likely since we anticipate this is a performance
post_barrier(ideal.ctrl(), load_store, base, adr, alias_idx, newval, T_OBJECT, true); // critical path, while CAS failure path can use the penalty for going through unlikely
ideal.sync_kit(this); // path as backoff. Which is still better than doing a store barrier there.
} ideal.end_if(); switch (kind) {
final_sync(ideal); case LS_get_set:
} else { case LS_cmp_exchange: {
post_barrier(control(), load_store, base, adr, alias_idx, newval, T_OBJECT, true); 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; break;
default: default:
@ -2785,7 +3050,7 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind
Node* proj = _gvn.transform(new SCMemProjNode(load_store)); Node* proj = _gvn.transform(new SCMemProjNode(load_store));
set_memory(proj, alias_idx); 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 #ifdef _LP64
if (adr->bottom_type()->is_ptr_to_narrowoop()) { if (adr->bottom_type()->is_ptr_to_narrowoop()) {
load_store = _gvn.transform(new DecodeNNode(load_store, load_store->get_ptr_type())); load_store = _gvn.transform(new DecodeNNode(load_store, load_store->get_ptr_type()));
@ -2804,74 +3069,52 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind
// Add the trailing membar surrounding the access // Add the trailing membar surrounding the access
insert_mem_bar(Op_MemBarCPUOrder); 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"); assert(type2size[load_store->bottom_type()->basic_type()] == type2size[rtype], "result type should match");
set_result(load_store); set_result(load_store);
return true; return true;
} }
//----------------------------inline_unsafe_ordered_store---------------------- MemNode::MemOrd LibraryCallKit::access_kind_to_memord_LS(AccessKind kind, bool is_store) {
// public native void Unsafe.putOrderedObject(Object o, long offset, Object x); MemNode::MemOrd mo = MemNode::unset;
// public native void Unsafe.putOrderedInt(Object o, long offset, int x); switch(kind) {
// public native void Unsafe.putOrderedLong(Object o, long offset, long x); case Opaque:
bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) { case Relaxed: mo = MemNode::unordered; break;
// This is another variant of inline_unsafe_access, differing in case Acquire: mo = MemNode::acquire; break;
// that it always issues store-store ("release") barrier and ensures case Release: mo = MemNode::release; break;
// store-atomicity (which only matters for "long"). case Volatile: mo = is_store ? MemNode::release : MemNode::acquire; break;
default:
if (callee()->is_static()) return false; // caller must have the capability! ShouldNotReachHere();
#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 guarantee(mo != MemNode::unset, "Should select memory ordering");
return mo;
}
C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". MemNode::MemOrd LibraryCallKit::access_kind_to_memord(AccessKind kind) {
MemNode::MemOrd mo = MemNode::unset;
// Get arguments: switch(kind) {
Node* receiver = argument(0); // type: oop case Opaque:
Node* base = argument(1); // type: oop case Relaxed: mo = MemNode::unordered; break;
Node* offset = argument(2); // type: long case Acquire: mo = MemNode::acquire; break;
Node* val = argument(4); // type: oop, int, or long case Release: mo = MemNode::release; break;
case Volatile: mo = MemNode::seqcst; break;
// Null check receiver. default:
receiver = null_check(receiver); ShouldNotReachHere();
if (stopped()) {
return true;
} }
guarantee(mo != MemNode::unset, "Should select memory ordering");
// Build field offset expression. return mo;
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;
} }
bool LibraryCallKit::inline_unsafe_fence(vmIntrinsics::ID id) { bool LibraryCallKit::inline_unsafe_fence(vmIntrinsics::ID id) {

View file

@ -2417,6 +2417,14 @@ void IdealLoopTree::adjust_loop_exit_prob( PhaseIdealLoop *phase ) {
((bol->in(1)->Opcode() == Op_StorePConditional ) || ((bol->in(1)->Opcode() == Op_StorePConditional ) ||
(bol->in(1)->Opcode() == Op_StoreIConditional ) || (bol->in(1)->Opcode() == Op_StoreIConditional ) ||
(bol->in(1)->Opcode() == Op_StoreLConditional ) || (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_CompareAndSwapI ) ||
(bol->in(1)->Opcode() == Op_CompareAndSwapL ) || (bol->in(1)->Opcode() == Op_CompareAndSwapL ) ||
(bol->in(1)->Opcode() == Op_CompareAndSwapP ) || (bol->in(1)->Opcode() == Op_CompareAndSwapP ) ||

View file

@ -2307,6 +2307,14 @@ void Matcher::find_shared( Node *n ) {
case Op_StorePConditional: case Op_StorePConditional:
case Op_StoreIConditional: case Op_StoreIConditional:
case Op_StoreLConditional: 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_CompareAndSwapI:
case Op_CompareAndSwapL: case Op_CompareAndSwapL:
case Op_CompareAndSwapP: case Op_CompareAndSwapP:
@ -2522,6 +2530,14 @@ bool Matcher::post_store_load_barrier(const Node* vmb) {
// that a monitor exit operation contains a serializing instruction. // that a monitor exit operation contains a serializing instruction.
if (xop == Op_MemBarVolatile || 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_CompareAndSwapL ||
xop == Op_CompareAndSwapP || xop == Op_CompareAndSwapP ||
xop == Op_CompareAndSwapN || xop == Op_CompareAndSwapN ||

View file

@ -56,7 +56,9 @@ public:
}; };
typedef enum { unordered = 0, typedef enum { unordered = 0,
acquire, // Load has to acquire or be succeeded by MemBarAcquire. 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; } MemOrd;
protected: protected:
MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at ) MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at )
@ -848,34 +850,121 @@ public:
virtual uint ideal_reg() const { return Op_RegFlags; } 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--------------------------- //------------------------------CompareAndSwapLNode---------------------------
class CompareAndSwapLNode : public LoadStoreConditionalNode { class CompareAndSwapLNode : public CompareAndSwapNode {
public: 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; virtual int Opcode() const;
}; };
//------------------------------CompareAndSwapINode--------------------------- //------------------------------CompareAndSwapINode---------------------------
class CompareAndSwapINode : public LoadStoreConditionalNode { class CompareAndSwapINode : public CompareAndSwapNode {
public: 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; virtual int Opcode() const;
}; };
//------------------------------CompareAndSwapPNode--------------------------- //------------------------------CompareAndSwapPNode---------------------------
class CompareAndSwapPNode : public LoadStoreConditionalNode { class CompareAndSwapPNode : public CompareAndSwapNode {
public: 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; virtual int Opcode() const;
}; };
//------------------------------CompareAndSwapNNode--------------------------- //------------------------------CompareAndSwapNNode---------------------------
class CompareAndSwapNNode : public LoadStoreConditionalNode { class CompareAndSwapNNode : public CompareAndSwapNode {
public: public:
CompareAndSwapNNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex) : LoadStoreConditionalNode(c, mem, adr, val, ex) { } 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:
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; virtual int Opcode() const;
}; };

View file

@ -60,6 +60,8 @@ class CmpNode;
class CodeBuffer; class CodeBuffer;
class ConstraintCastNode; class ConstraintCastNode;
class ConNode; class ConNode;
class CompareAndSwapNode;
class CompareAndExchangeNode;
class CountedLoopNode; class CountedLoopNode;
class CountedLoopEndNode; class CountedLoopEndNode;
class DecodeNarrowPtrNode; class DecodeNarrowPtrNode;
@ -679,6 +681,9 @@ public:
DEFINE_CLASS_ID(Store, Mem, 1) DEFINE_CLASS_ID(Store, Mem, 1)
DEFINE_CLASS_ID(StoreVector, Store, 0) DEFINE_CLASS_ID(StoreVector, Store, 0)
DEFINE_CLASS_ID(LoadStore, Mem, 2) 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(Region, Node, 5)
DEFINE_CLASS_ID(Loop, Region, 0) DEFINE_CLASS_ID(Loop, Region, 0)

View file

@ -1117,6 +1117,44 @@ UNSAFE_END
// JSR166 ------------------------------------------------------------------ // 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)) UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
UnsafeWrapper("Unsafe_CompareAndSwapObject"); UnsafeWrapper("Unsafe_CompareAndSwapObject");
oop x = JNIHandles::resolve(x_h); oop x = JNIHandles::resolve(x_h);
@ -1384,6 +1422,10 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
{CC "compareAndSwapObject", CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSwapObject)}, {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 "compareAndSwapInt", CC "(" OBJ "J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)},
{CC "compareAndSwapLong", CC "(" OBJ "J""J""J"")Z", FN_PTR(Unsafe_CompareAndSwapLong)}, {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 "putOrderedObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetOrderedObject)},
{CC "putOrderedInt", CC "(" OBJ "JI)V", FN_PTR(Unsafe_SetOrderedInt)}, {CC "putOrderedInt", CC "(" OBJ "JI)V", FN_PTR(Unsafe_SetOrderedInt)},
{CC "putOrderedLong", CC "(" OBJ "JJ)V", FN_PTR(Unsafe_SetOrderedLong)}, {CC "putOrderedLong", CC "(" OBJ "JJ)V", FN_PTR(Unsafe_SetOrderedLong)},

View file

@ -2005,10 +2005,20 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
declare_c2_type(LoadStoreNode, Node) \ declare_c2_type(LoadStoreNode, Node) \
declare_c2_type(StorePConditionalNode, LoadStoreNode) \ declare_c2_type(StorePConditionalNode, LoadStoreNode) \
declare_c2_type(StoreLConditionalNode, LoadStoreNode) \ declare_c2_type(StoreLConditionalNode, LoadStoreNode) \
declare_c2_type(CompareAndSwapLNode, LoadStoreNode) \ declare_c2_type(CompareAndSwapNode, LoadStoreConditionalNode) \
declare_c2_type(CompareAndSwapINode, LoadStoreNode) \ declare_c2_type(CompareAndSwapLNode, CompareAndSwapNode) \
declare_c2_type(CompareAndSwapPNode, LoadStoreNode) \ declare_c2_type(CompareAndSwapINode, CompareAndSwapNode) \
declare_c2_type(CompareAndSwapNNode, LoadStoreNode) \ 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(MulNode, Node) \
declare_c2_type(MulINode, MulNode) \ declare_c2_type(MulINode, MulNode) \
declare_c2_type(MulLNode, MulNode) \ declare_c2_type(MulLNode, MulNode) \

View file

@ -128,6 +128,20 @@ public class JdkInternalMiscUnsafeAccessTestBoolean {
} }
// 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");
}
} }

View file

@ -157,6 +157,20 @@ public class JdkInternalMiscUnsafeAccessTestByte {
} }
// 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");
}
} }

View file

@ -157,6 +157,20 @@ public class JdkInternalMiscUnsafeAccessTestChar {
} }
// 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 // Unaligned
{ {
UNSAFE.putCharUnaligned(base, offset, 'b'); UNSAFE.putCharUnaligned(base, offset, 'b');

View file

@ -157,6 +157,20 @@ public class JdkInternalMiscUnsafeAccessTestDouble {
} }
// 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");
}
} }

View file

@ -157,6 +157,20 @@ public class JdkInternalMiscUnsafeAccessTestFloat {
} }
// 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");
}
} }

View file

@ -163,6 +163,20 @@ public class JdkInternalMiscUnsafeAccessTestInt {
assertEquals(x, 1, "putRelease int value"); 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 // Unaligned
{ {
UNSAFE.putIntUnaligned(base, offset, 2); UNSAFE.putIntUnaligned(base, offset, 2);
@ -199,6 +213,70 @@ public class JdkInternalMiscUnsafeAccessTestInt {
assertEquals(x, 2, "failing compareAndSwap int value"); 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 // Compare set and get
{ {
int o = UNSAFE.getAndSetInt(base, offset, 1); int o = UNSAFE.getAndSetInt(base, offset, 1);

View file

@ -163,6 +163,20 @@ public class JdkInternalMiscUnsafeAccessTestLong {
assertEquals(x, 1L, "putRelease long value"); 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 // Unaligned
{ {
UNSAFE.putLongUnaligned(base, offset, 2L); UNSAFE.putLongUnaligned(base, offset, 2L);
@ -199,6 +213,70 @@ public class JdkInternalMiscUnsafeAccessTestLong {
assertEquals(x, 2L, "failing compareAndSwap long value"); 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 // Compare set and get
{ {
long o = UNSAFE.getAndSetLong(base, offset, 1L); long o = UNSAFE.getAndSetLong(base, offset, 1L);

View file

@ -134,6 +134,20 @@ public class JdkInternalMiscUnsafeAccessTestObject {
assertEquals(x, "foo", "putRelease Object value"); 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"); UNSAFE.putObject(base, offset, "foo");
@ -152,6 +166,70 @@ public class JdkInternalMiscUnsafeAccessTestObject {
assertEquals(x, "bar", "failing compareAndSwap Object value"); 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 // Compare set and get
{ {
Object o = UNSAFE.getAndSetObject(base, offset, "foo"); Object o = UNSAFE.getAndSetObject(base, offset, "foo");

View file

@ -157,6 +157,20 @@ public class JdkInternalMiscUnsafeAccessTestShort {
} }
// 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 // Unaligned
{ {
UNSAFE.putShortUnaligned(base, offset, (short)2); UNSAFE.putShortUnaligned(base, offset, (short)2);

View file

@ -169,6 +169,22 @@ public class $Qualifier$UnsafeAccessTest$Type$ {
} }
#end[Ordered] #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[JdkInternalMisc]
#if[Unaligned] #if[Unaligned]
// Unaligned // Unaligned
@ -210,6 +226,72 @@ public class $Qualifier$UnsafeAccessTest$Type$ {
assertEquals(x, $value2$, "failing compareAndSwap $type$ value"); 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 // Compare set and get
{ {
$type$ o = UNSAFE.getAndSet$Type$(base, offset, $value1$); $type$ o = UNSAFE.getAndSet$Type$(base, offset, $value1$);
@ -244,4 +326,5 @@ public class $Qualifier$UnsafeAccessTest$Type$ {
} }
#end[!boolean] #end[!boolean]
#end[!Object] #end[!Object]
} }

View file

@ -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