8186838: Generalize Atomic::inc/dec with templates
Reviewed-by: kbarrett, coleenp, dholmes
This commit is contained in:
parent
e840fdf694
commit
394e6a8318
@ -428,7 +428,7 @@ static unsigned __stdcall thread_native_entry(Thread* thread) {
|
||||
// When the VMThread gets here, the main thread may have already exited
|
||||
// which frees the CodeHeap containing the Atomic::add code
|
||||
if (thread != VMThread::vm_thread() && VMThread::vm_thread() != NULL) {
|
||||
Atomic::dec_ptr((intptr_t*)&os::win32::_os_thread_count);
|
||||
Atomic::dec(&os::win32::_os_thread_count);
|
||||
}
|
||||
|
||||
// If a thread has not deleted itself ("delete this") as part of its
|
||||
@ -634,7 +634,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Atomic::inc_ptr((intptr_t*)&os::win32::_os_thread_count);
|
||||
Atomic::inc(&os::win32::_os_thread_count);
|
||||
|
||||
// Store info on the Win32 thread into the OSThread
|
||||
osthread->set_thread_handle(thread_handle);
|
||||
|
@ -149,83 +149,6 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) co
|
||||
}
|
||||
|
||||
|
||||
inline void Atomic::inc (volatile jint* dest) {
|
||||
|
||||
unsigned int temp;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
strasm_nobarrier
|
||||
"1: lwarx %0, 0, %2 \n"
|
||||
" addic %0, %0, 1 \n"
|
||||
" stwcx. %0, 0, %2 \n"
|
||||
" bne- 1b \n"
|
||||
strasm_nobarrier
|
||||
: /*%0*/"=&r" (temp), "=m" (*dest)
|
||||
: /*%2*/"r" (dest), "m" (*dest)
|
||||
: "cc" strasm_nobarrier_clobber_memory);
|
||||
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) {
|
||||
|
||||
long temp;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
strasm_nobarrier
|
||||
"1: ldarx %0, 0, %2 \n"
|
||||
" addic %0, %0, 1 \n"
|
||||
" stdcx. %0, 0, %2 \n"
|
||||
" bne- 1b \n"
|
||||
strasm_nobarrier
|
||||
: /*%0*/"=&r" (temp), "=m" (*dest)
|
||||
: /*%2*/"r" (dest), "m" (*dest)
|
||||
: "cc" strasm_nobarrier_clobber_memory);
|
||||
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile void* dest) {
|
||||
inc_ptr((volatile intptr_t*)dest);
|
||||
}
|
||||
|
||||
|
||||
inline void Atomic::dec (volatile jint* dest) {
|
||||
|
||||
unsigned int temp;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
strasm_nobarrier
|
||||
"1: lwarx %0, 0, %2 \n"
|
||||
" addic %0, %0, -1 \n"
|
||||
" stwcx. %0, 0, %2 \n"
|
||||
" bne- 1b \n"
|
||||
strasm_nobarrier
|
||||
: /*%0*/"=&r" (temp), "=m" (*dest)
|
||||
: /*%2*/"r" (dest), "m" (*dest)
|
||||
: "cc" strasm_nobarrier_clobber_memory);
|
||||
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) {
|
||||
|
||||
long temp;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
strasm_nobarrier
|
||||
"1: ldarx %0, 0, %2 \n"
|
||||
" addic %0, %0, -1 \n"
|
||||
" stdcx. %0, 0, %2 \n"
|
||||
" bne- 1b \n"
|
||||
strasm_nobarrier
|
||||
: /*%0*/"=&r" (temp), "=m" (*dest)
|
||||
: /*%2*/"r" (dest), "m" (*dest)
|
||||
: "cc" strasm_nobarrier_clobber_memory);
|
||||
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile void* dest) {
|
||||
dec_ptr((volatile intptr_t*)dest);
|
||||
}
|
||||
|
||||
inline jint Atomic::xchg(jint exchange_value, volatile jint* dest) {
|
||||
|
||||
// Note that xchg_ptr doesn't necessarily do an acquire
|
||||
|
@ -61,24 +61,6 @@ inline D Atomic::PlatformAdd<4>::fetch_and_add(I add_value, D volatile* dest) co
|
||||
return old_value;
|
||||
}
|
||||
|
||||
inline void Atomic::inc (volatile jint* dest) {
|
||||
__asm__ volatile ( "lock addl $1,(%0)" :
|
||||
: "r" (dest) : "cc", "memory");
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile void* dest) {
|
||||
inc_ptr((volatile intptr_t*)dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec (volatile jint* dest) {
|
||||
__asm__ volatile ( "lock subl $1,(%0)" :
|
||||
: "r" (dest) : "cc", "memory");
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile void* dest) {
|
||||
dec_ptr((volatile intptr_t*)dest);
|
||||
}
|
||||
|
||||
inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) {
|
||||
__asm__ volatile ( "xchgl (%2),%0"
|
||||
: "=r" (exchange_value)
|
||||
@ -136,20 +118,6 @@ inline D Atomic::PlatformAdd<8>::fetch_and_add(I add_value, D volatile* dest) co
|
||||
return old_value;
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) {
|
||||
__asm__ __volatile__ ( "lock addq $1,(%0)"
|
||||
:
|
||||
: "r" (dest)
|
||||
: "cc", "memory");
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) {
|
||||
__asm__ __volatile__ ( "lock subq $1,(%0)"
|
||||
:
|
||||
: "r" (dest)
|
||||
: "cc", "memory");
|
||||
}
|
||||
|
||||
inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
|
||||
__asm__ __volatile__ ("xchgq (%2),%0"
|
||||
: "=r" (exchange_value)
|
||||
@ -176,14 +144,6 @@ inline jlong Atomic::load(const volatile jlong* src) { return *src; }
|
||||
|
||||
#else // !AMD64
|
||||
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) {
|
||||
inc((volatile jint*)dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) {
|
||||
dec((volatile jint*)dest);
|
||||
}
|
||||
|
||||
inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
|
||||
return (intptr_t)xchg((jint)exchange_value, (volatile jint*)dest);
|
||||
}
|
||||
|
@ -207,30 +207,6 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) co
|
||||
return __sync_add_and_fetch(dest, add_value);
|
||||
}
|
||||
|
||||
inline void Atomic::inc(volatile jint* dest) {
|
||||
add(1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) {
|
||||
add_ptr(1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile void* dest) {
|
||||
add_ptr(1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec(volatile jint* dest) {
|
||||
add(-1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) {
|
||||
add_ptr(-1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile void* dest) {
|
||||
add_ptr(-1, dest);
|
||||
}
|
||||
|
||||
inline jint Atomic::xchg(jint exchange_value, volatile jint* dest) {
|
||||
#ifdef ARM
|
||||
return arm_lock_test_and_set(dest, exchange_value);
|
||||
|
@ -57,26 +57,6 @@ struct Atomic::PlatformAdd
|
||||
}
|
||||
};
|
||||
|
||||
inline void Atomic::inc(volatile jint* dest)
|
||||
{
|
||||
add(1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile void* dest)
|
||||
{
|
||||
add_ptr(1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec (volatile jint* dest)
|
||||
{
|
||||
add(-1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile void* dest)
|
||||
{
|
||||
add_ptr(-1, dest);
|
||||
}
|
||||
|
||||
inline jint Atomic::xchg (jint exchange_value, volatile jint* dest)
|
||||
{
|
||||
jint res = __sync_lock_test_and_set (dest, exchange_value);
|
||||
@ -110,16 +90,6 @@ inline T Atomic::PlatformCmpxchg<byte_size>::operator()(T exchange_value,
|
||||
inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
|
||||
inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
|
||||
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest)
|
||||
{
|
||||
add_ptr(1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest)
|
||||
{
|
||||
add_ptr(-1, dest);
|
||||
}
|
||||
|
||||
inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest)
|
||||
{
|
||||
intptr_t res = __sync_lock_test_and_set (dest, exchange_value);
|
||||
|
@ -122,14 +122,6 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void Atomic::inc(volatile jint* dest) {
|
||||
Atomic::add(1, (volatile jint *)dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec(volatile jint* dest) {
|
||||
Atomic::add(-1, (volatile jint *)dest);
|
||||
}
|
||||
|
||||
#ifdef AARCH64
|
||||
template<>
|
||||
template<typename I, typename D>
|
||||
@ -151,23 +143,6 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) co
|
||||
}
|
||||
#endif // AARCH64
|
||||
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) {
|
||||
Atomic::add_ptr(1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) {
|
||||
Atomic::add_ptr(-1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile void* dest) {
|
||||
inc_ptr((volatile intptr_t*)dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile void* dest) {
|
||||
dec_ptr((volatile intptr_t*)dest);
|
||||
}
|
||||
|
||||
|
||||
inline jint Atomic::xchg(jint exchange_value, volatile jint* dest) {
|
||||
#ifdef AARCH64
|
||||
jint old_val;
|
||||
|
@ -146,84 +146,6 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) co
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
inline void Atomic::inc (volatile jint* dest) {
|
||||
|
||||
unsigned int temp;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
strasm_nobarrier
|
||||
"1: lwarx %0, 0, %2 \n"
|
||||
" addic %0, %0, 1 \n"
|
||||
" stwcx. %0, 0, %2 \n"
|
||||
" bne- 1b \n"
|
||||
strasm_nobarrier
|
||||
: /*%0*/"=&r" (temp), "=m" (*dest)
|
||||
: /*%2*/"r" (dest), "m" (*dest)
|
||||
: "cc" strasm_nobarrier_clobber_memory);
|
||||
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) {
|
||||
|
||||
long temp;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
strasm_nobarrier
|
||||
"1: ldarx %0, 0, %2 \n"
|
||||
" addic %0, %0, 1 \n"
|
||||
" stdcx. %0, 0, %2 \n"
|
||||
" bne- 1b \n"
|
||||
strasm_nobarrier
|
||||
: /*%0*/"=&r" (temp), "=m" (*dest)
|
||||
: /*%2*/"r" (dest), "m" (*dest)
|
||||
: "cc" strasm_nobarrier_clobber_memory);
|
||||
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile void* dest) {
|
||||
inc_ptr((volatile intptr_t*)dest);
|
||||
}
|
||||
|
||||
|
||||
inline void Atomic::dec (volatile jint* dest) {
|
||||
|
||||
unsigned int temp;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
strasm_nobarrier
|
||||
"1: lwarx %0, 0, %2 \n"
|
||||
" addic %0, %0, -1 \n"
|
||||
" stwcx. %0, 0, %2 \n"
|
||||
" bne- 1b \n"
|
||||
strasm_nobarrier
|
||||
: /*%0*/"=&r" (temp), "=m" (*dest)
|
||||
: /*%2*/"r" (dest), "m" (*dest)
|
||||
: "cc" strasm_nobarrier_clobber_memory);
|
||||
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) {
|
||||
|
||||
long temp;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
strasm_nobarrier
|
||||
"1: ldarx %0, 0, %2 \n"
|
||||
" addic %0, %0, -1 \n"
|
||||
" stdcx. %0, 0, %2 \n"
|
||||
" bne- 1b \n"
|
||||
strasm_nobarrier
|
||||
: /*%0*/"=&r" (temp), "=m" (*dest)
|
||||
: /*%2*/"r" (dest), "m" (*dest)
|
||||
: "cc" strasm_nobarrier_clobber_memory);
|
||||
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile void* dest) {
|
||||
dec_ptr((volatile intptr_t*)dest);
|
||||
}
|
||||
|
||||
inline jint Atomic::xchg(jint exchange_value, volatile jint* dest) {
|
||||
|
||||
// Note that xchg_ptr doesn't necessarily do an acquire
|
||||
|
@ -192,219 +192,6 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I inc, D volatile* dest) const {
|
||||
}
|
||||
|
||||
|
||||
//------------
|
||||
// Atomic::inc
|
||||
//------------
|
||||
// These methods force the value in memory to be incremented (augmented by 1).
|
||||
// Both, memory value and increment, are treated as 32bit signed binary integers.
|
||||
// No overflow exceptions are recognized, and the condition code does not hold
|
||||
// information about the value in memory.
|
||||
//
|
||||
// The value in memory is updated by using a compare-and-swap instruction. The
|
||||
// instruction is retried as often as required.
|
||||
|
||||
inline void Atomic::inc(volatile jint* dest) {
|
||||
unsigned int old, upd;
|
||||
|
||||
if (VM_Version::has_LoadAndALUAtomicV1()) {
|
||||
// tty->print_cr("Atomic::inc called... dest @%p", dest);
|
||||
__asm__ __volatile__ (
|
||||
" LGHI 2,1 \n\t" // load increment
|
||||
" LA 3,%[mem] \n\t" // force data address into ARG2
|
||||
// " LAA %[upd],%[inc],%[mem] \n\t" // increment and get old value
|
||||
// " LAA 2,2,0(3) \n\t" // actually coded instruction
|
||||
" .byte 0xeb \n\t" // LAA main opcode
|
||||
" .byte 0x22 \n\t" // R1,R3
|
||||
" .byte 0x30 \n\t" // R2,disp1
|
||||
" .byte 0x00 \n\t" // disp2,disp3
|
||||
" .byte 0x00 \n\t" // disp4,disp5
|
||||
" .byte 0xf8 \n\t" // LAA minor opcode
|
||||
" AGHI 2,1 \n\t" // calc new value in register
|
||||
" LR %[upd],2 \n\t" // move to result register
|
||||
//---< outputs >---
|
||||
: [upd] "=&d" (upd) // write-only, updated counter value
|
||||
, [mem] "+Q" (*dest) // read/write, memory to be updated atomically
|
||||
//---< inputs >---
|
||||
:
|
||||
// : [inc] "a" (inc) // read-only.
|
||||
//---< clobbered >---
|
||||
: "cc", "r2", "r3", "memory"
|
||||
);
|
||||
} else {
|
||||
__asm__ __volatile__ (
|
||||
" LLGF %[old],%[mem] \n\t" // get old value
|
||||
"0: LA %[upd],1(,%[old]) \n\t" // calc result
|
||||
" CS %[old],%[upd],%[mem] \n\t" // try to xchg res with mem
|
||||
" JNE 0b \n\t" // no success? -> retry
|
||||
//---< outputs >---
|
||||
: [old] "=&a" (old) // write-only, old counter value
|
||||
, [upd] "=&d" (upd) // write-only, updated counter value
|
||||
, [mem] "+Q" (*dest) // read/write, memory to be updated atomically
|
||||
//---< inputs >---
|
||||
:
|
||||
//---< clobbered >---
|
||||
: "cc", "memory"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) {
|
||||
unsigned long old, upd;
|
||||
|
||||
if (VM_Version::has_LoadAndALUAtomicV1()) {
|
||||
__asm__ __volatile__ (
|
||||
" LGHI 2,1 \n\t" // load increment
|
||||
" LA 3,%[mem] \n\t" // force data address into ARG2
|
||||
// " LAAG %[upd],%[inc],%[mem] \n\t" // increment and get old value
|
||||
// " LAAG 2,2,0(3) \n\t" // actually coded instruction
|
||||
" .byte 0xeb \n\t" // LAA main opcode
|
||||
" .byte 0x22 \n\t" // R1,R3
|
||||
" .byte 0x30 \n\t" // R2,disp1
|
||||
" .byte 0x00 \n\t" // disp2,disp3
|
||||
" .byte 0x00 \n\t" // disp4,disp5
|
||||
" .byte 0xe8 \n\t" // LAA minor opcode
|
||||
" AGHI 2,1 \n\t" // calc new value in register
|
||||
" LR %[upd],2 \n\t" // move to result register
|
||||
//---< outputs >---
|
||||
: [upd] "=&d" (upd) // write-only, updated counter value
|
||||
, [mem] "+Q" (*dest) // read/write, memory to be updated atomically
|
||||
//---< inputs >---
|
||||
:
|
||||
// : [inc] "a" (inc) // read-only.
|
||||
//---< clobbered >---
|
||||
: "cc", "r2", "r3", "memory"
|
||||
);
|
||||
} else {
|
||||
__asm__ __volatile__ (
|
||||
" LG %[old],%[mem] \n\t" // get old value
|
||||
"0: LA %[upd],1(,%[old]) \n\t" // calc result
|
||||
" CSG %[old],%[upd],%[mem] \n\t" // try to xchg res with mem
|
||||
" JNE 0b \n\t" // no success? -> retry
|
||||
//---< outputs >---
|
||||
: [old] "=&a" (old) // write-only, old counter value
|
||||
, [upd] "=&d" (upd) // write-only, updated counter value
|
||||
, [mem] "+Q" (*dest) // read/write, memory to be updated atomically
|
||||
//---< inputs >---
|
||||
:
|
||||
//---< clobbered >---
|
||||
: "cc", "memory"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile void* dest) {
|
||||
inc_ptr((volatile intptr_t*)dest);
|
||||
}
|
||||
|
||||
//------------
|
||||
// Atomic::dec
|
||||
//------------
|
||||
// These methods force the value in memory to be decremented (augmented by -1).
|
||||
// Both, memory value and decrement, are treated as 32bit signed binary integers.
|
||||
// No overflow exceptions are recognized, and the condition code does not hold
|
||||
// information about the value in memory.
|
||||
//
|
||||
// The value in memory is updated by using a compare-and-swap instruction. The
|
||||
// instruction is retried as often as required.
|
||||
|
||||
inline void Atomic::dec(volatile jint* dest) {
|
||||
unsigned int old, upd;
|
||||
|
||||
if (VM_Version::has_LoadAndALUAtomicV1()) {
|
||||
__asm__ __volatile__ (
|
||||
" LGHI 2,-1 \n\t" // load increment
|
||||
" LA 3,%[mem] \n\t" // force data address into ARG2
|
||||
// " LAA %[upd],%[inc],%[mem] \n\t" // increment and get old value
|
||||
// " LAA 2,2,0(3) \n\t" // actually coded instruction
|
||||
" .byte 0xeb \n\t" // LAA main opcode
|
||||
" .byte 0x22 \n\t" // R1,R3
|
||||
" .byte 0x30 \n\t" // R2,disp1
|
||||
" .byte 0x00 \n\t" // disp2,disp3
|
||||
" .byte 0x00 \n\t" // disp4,disp5
|
||||
" .byte 0xf8 \n\t" // LAA minor opcode
|
||||
" AGHI 2,-1 \n\t" // calc new value in register
|
||||
" LR %[upd],2 \n\t" // move to result register
|
||||
//---< outputs >---
|
||||
: [upd] "=&d" (upd) // write-only, updated counter value
|
||||
, [mem] "+Q" (*dest) // read/write, memory to be updated atomically
|
||||
//---< inputs >---
|
||||
:
|
||||
// : [inc] "a" (inc) // read-only.
|
||||
//---< clobbered >---
|
||||
: "cc", "r2", "r3", "memory"
|
||||
);
|
||||
} else {
|
||||
__asm__ __volatile__ (
|
||||
" LLGF %[old],%[mem] \n\t" // get old value
|
||||
// LAY not supported by inline assembler
|
||||
// "0: LAY %[upd],-1(,%[old]) \n\t" // calc result
|
||||
"0: LR %[upd],%[old] \n\t" // calc result
|
||||
" AHI %[upd],-1 \n\t"
|
||||
" CS %[old],%[upd],%[mem] \n\t" // try to xchg res with mem
|
||||
" JNE 0b \n\t" // no success? -> retry
|
||||
//---< outputs >---
|
||||
: [old] "=&a" (old) // write-only, old counter value
|
||||
, [upd] "=&d" (upd) // write-only, updated counter value
|
||||
, [mem] "+Q" (*dest) // read/write, memory to be updated atomically
|
||||
//---< inputs >---
|
||||
:
|
||||
//---< clobbered >---
|
||||
: "cc", "memory"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) {
|
||||
unsigned long old, upd;
|
||||
|
||||
if (VM_Version::has_LoadAndALUAtomicV1()) {
|
||||
__asm__ __volatile__ (
|
||||
" LGHI 2,-1 \n\t" // load increment
|
||||
" LA 3,%[mem] \n\t" // force data address into ARG2
|
||||
// " LAAG %[upd],%[inc],%[mem] \n\t" // increment and get old value
|
||||
// " LAAG 2,2,0(3) \n\t" // actually coded instruction
|
||||
" .byte 0xeb \n\t" // LAA main opcode
|
||||
" .byte 0x22 \n\t" // R1,R3
|
||||
" .byte 0x30 \n\t" // R2,disp1
|
||||
" .byte 0x00 \n\t" // disp2,disp3
|
||||
" .byte 0x00 \n\t" // disp4,disp5
|
||||
" .byte 0xe8 \n\t" // LAA minor opcode
|
||||
" AGHI 2,-1 \n\t" // calc new value in register
|
||||
" LR %[upd],2 \n\t" // move to result register
|
||||
//---< outputs >---
|
||||
: [upd] "=&d" (upd) // write-only, updated counter value
|
||||
, [mem] "+Q" (*dest) // read/write, memory to be updated atomically
|
||||
//---< inputs >---
|
||||
:
|
||||
// : [inc] "a" (inc) // read-only.
|
||||
//---< clobbered >---
|
||||
: "cc", "r2", "r3", "memory"
|
||||
);
|
||||
} else {
|
||||
__asm__ __volatile__ (
|
||||
" LG %[old],%[mem] \n\t" // get old value
|
||||
// LAY not supported by inline assembler
|
||||
// "0: LAY %[upd],-1(,%[old]) \n\t" // calc result
|
||||
"0: LGR %[upd],%[old] \n\t" // calc result
|
||||
" AGHI %[upd],-1 \n\t"
|
||||
" CSG %[old],%[upd],%[mem] \n\t" // try to xchg res with mem
|
||||
" JNE 0b \n\t" // no success? -> retry
|
||||
//---< outputs >---
|
||||
: [old] "=&a" (old) // write-only, old counter value
|
||||
, [upd] "=&d" (upd) // write-only, updated counter value
|
||||
, [mem] "+Q" (*dest) // read/write, memory to be updated atomically
|
||||
//---< inputs >---
|
||||
:
|
||||
//---< clobbered >---
|
||||
: "cc", "memory"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile void* dest) {
|
||||
dec_ptr((volatile intptr_t*)dest);
|
||||
}
|
||||
|
||||
//-------------
|
||||
// Atomic::xchg
|
||||
//-------------
|
||||
|
@ -41,14 +41,6 @@ inline void Atomic::store (jlong store_value, volatile jlong* dest) { *
|
||||
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
|
||||
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
|
||||
|
||||
inline void Atomic::inc (volatile jint* dest) { (void)add (1, dest); }
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) { (void)add_ptr(1, dest); }
|
||||
inline void Atomic::inc_ptr(volatile void* dest) { (void)add_ptr(1, dest); }
|
||||
|
||||
inline void Atomic::dec (volatile jint* dest) { (void)add (-1, dest); }
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); }
|
||||
inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest); }
|
||||
|
||||
inline jlong Atomic::load(const volatile jlong* src) { return *src; }
|
||||
|
||||
template<size_t byte_size>
|
||||
|
@ -61,24 +61,6 @@ inline D Atomic::PlatformAdd<4>::fetch_and_add(I add_value, D volatile* dest) co
|
||||
return old_value;
|
||||
}
|
||||
|
||||
inline void Atomic::inc (volatile jint* dest) {
|
||||
__asm__ volatile ( "lock addl $1,(%0)" :
|
||||
: "r" (dest) : "cc", "memory");
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile void* dest) {
|
||||
inc_ptr((volatile intptr_t*)dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec (volatile jint* dest) {
|
||||
__asm__ volatile ( "lock subl $1,(%0)" :
|
||||
: "r" (dest) : "cc", "memory");
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile void* dest) {
|
||||
dec_ptr((volatile intptr_t*)dest);
|
||||
}
|
||||
|
||||
inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) {
|
||||
__asm__ volatile ( "xchgl (%2),%0"
|
||||
: "=r" (exchange_value)
|
||||
@ -136,20 +118,6 @@ inline D Atomic::PlatformAdd<8>::fetch_and_add(I add_value, D volatile* dest) co
|
||||
return old_value;
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) {
|
||||
__asm__ __volatile__ ("lock addq $1,(%0)"
|
||||
:
|
||||
: "r" (dest)
|
||||
: "cc", "memory");
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) {
|
||||
__asm__ __volatile__ ("lock subq $1,(%0)"
|
||||
:
|
||||
: "r" (dest)
|
||||
: "cc", "memory");
|
||||
}
|
||||
|
||||
inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
|
||||
__asm__ __volatile__ ("xchgq (%2),%0"
|
||||
: "=r" (exchange_value)
|
||||
@ -176,14 +144,6 @@ inline jlong Atomic::load(const volatile jlong* src) { return *src; }
|
||||
|
||||
#else // !AMD64
|
||||
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) {
|
||||
inc((volatile jint*)dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) {
|
||||
dec((volatile jint*)dest);
|
||||
}
|
||||
|
||||
inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
|
||||
return (intptr_t)xchg((jint)exchange_value, (volatile jint*)dest);
|
||||
}
|
||||
|
@ -201,30 +201,6 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) co
|
||||
return __sync_add_and_fetch(dest, add_value);
|
||||
}
|
||||
|
||||
inline void Atomic::inc(volatile jint* dest) {
|
||||
add(1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) {
|
||||
add_ptr(1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile void* dest) {
|
||||
add_ptr(1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec(volatile jint* dest) {
|
||||
add(-1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) {
|
||||
add_ptr(-1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile void* dest) {
|
||||
add_ptr(-1, dest);
|
||||
}
|
||||
|
||||
inline jint Atomic::xchg(jint exchange_value, volatile jint* dest) {
|
||||
#ifdef ARM
|
||||
return arm_lock_test_and_set(dest, exchange_value);
|
||||
|
@ -39,15 +39,6 @@ inline void Atomic::store (jint store_value, volatile jint* dest) { *
|
||||
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
|
||||
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
|
||||
|
||||
inline void Atomic::inc (volatile jint* dest) { (void)add (1, dest); }
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) { (void)add_ptr(1, dest); }
|
||||
inline void Atomic::inc_ptr(volatile void* dest) { (void)add_ptr(1, dest); }
|
||||
|
||||
inline void Atomic::dec (volatile jint* dest) { (void)add (-1, dest); }
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); }
|
||||
inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest); }
|
||||
|
||||
|
||||
inline void Atomic::store(jlong store_value, jlong* dest) { *dest = store_value; }
|
||||
inline void Atomic::store(jlong store_value, volatile jlong* dest) { *dest = store_value; }
|
||||
inline jlong Atomic::load(const volatile jlong* src) { return *src; }
|
||||
|
@ -39,14 +39,6 @@ inline void Atomic::store (jint store_value, volatile jint* dest) { *
|
||||
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
|
||||
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
|
||||
|
||||
inline void Atomic::inc (volatile jint* dest) { (void)add (1, dest); }
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) { (void)add_ptr(1, dest); }
|
||||
inline void Atomic::inc_ptr(volatile void* dest) { (void)add_ptr(1, dest); }
|
||||
|
||||
inline void Atomic::dec (volatile jint* dest) { (void)add (-1, dest); }
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); }
|
||||
inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest); }
|
||||
|
||||
// For Sun Studio - implementation is in solaris_x86_64.il.
|
||||
|
||||
extern "C" {
|
||||
|
@ -81,30 +81,6 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) co
|
||||
return add_using_helper<intptr_t>(os::atomic_add_ptr_func, add_value, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::inc (volatile jint* dest) {
|
||||
(void)add (1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) {
|
||||
(void)add_ptr(1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile void* dest) {
|
||||
(void)add_ptr(1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec (volatile jint* dest) {
|
||||
(void)add (-1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) {
|
||||
(void)add_ptr(-1, dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile void* dest) {
|
||||
(void)add_ptr(-1, dest);
|
||||
}
|
||||
|
||||
inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) {
|
||||
return (jint)(*os::atomic_xchg_func)(exchange_value, dest);
|
||||
}
|
||||
@ -152,38 +128,6 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co
|
||||
}
|
||||
}
|
||||
|
||||
inline void Atomic::inc (volatile jint* dest) {
|
||||
// alternative for InterlockedIncrement
|
||||
__asm {
|
||||
mov edx, dest;
|
||||
lock add dword ptr [edx], 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile intptr_t* dest) {
|
||||
inc((volatile jint*)dest);
|
||||
}
|
||||
|
||||
inline void Atomic::inc_ptr(volatile void* dest) {
|
||||
inc((volatile jint*)dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec (volatile jint* dest) {
|
||||
// alternative for InterlockedDecrement
|
||||
__asm {
|
||||
mov edx, dest;
|
||||
lock sub dword ptr [edx], 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile intptr_t* dest) {
|
||||
dec((volatile jint*)dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec_ptr(volatile void* dest) {
|
||||
dec((volatile jint*)dest);
|
||||
}
|
||||
|
||||
inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) {
|
||||
// alternative for InterlockedExchange
|
||||
__asm {
|
||||
|
@ -1075,7 +1075,7 @@ ConcurrentMarkSweepGeneration::par_promote(int thread_num,
|
||||
obj_ptr, old->is_objArray(), word_sz);
|
||||
|
||||
NOT_PRODUCT(
|
||||
Atomic::inc_ptr(&_numObjectsPromoted);
|
||||
Atomic::inc(&_numObjectsPromoted);
|
||||
Atomic::add_ptr(alloc_sz, &_numWordsPromoted);
|
||||
)
|
||||
|
||||
@ -7974,7 +7974,7 @@ void CMSCollector::push_on_overflow_list(oop p) {
|
||||
|
||||
// Multi-threaded; use CAS to prepend to overflow list
|
||||
void CMSCollector::par_push_on_overflow_list(oop p) {
|
||||
NOT_PRODUCT(Atomic::inc_ptr(&_num_par_pushes);)
|
||||
NOT_PRODUCT(Atomic::inc(&_num_par_pushes);)
|
||||
assert(oopDesc::is_oop(p), "Not an oop");
|
||||
par_preserve_mark_if_necessary(p);
|
||||
oop observed_overflow_list = _overflow_list;
|
||||
|
@ -1281,7 +1281,7 @@ void ParNewGeneration::push_on_overflow_list(oop from_space_obj, ParScanThreadSt
|
||||
// XXX This is horribly inefficient when a promotion failure occurs
|
||||
// and should be fixed. XXX FIX ME !!!
|
||||
#ifndef PRODUCT
|
||||
Atomic::inc_ptr(&_num_par_pushes);
|
||||
Atomic::inc(&_num_par_pushes);
|
||||
assert(_num_par_pushes > 0, "Tautology");
|
||||
#endif
|
||||
if (from_space_obj->forwardee() == from_space_obj) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -90,7 +90,7 @@ void G1StringDedupQueue::push(uint worker_id, oop java_string) {
|
||||
}
|
||||
} else {
|
||||
// Queue is full, drop the string and update the statistics
|
||||
Atomic::inc_ptr(&_queue->_dropped);
|
||||
Atomic::inc(&_queue->_dropped);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -89,7 +89,7 @@ ParMarkBitMap::mark_obj(HeapWord* addr, size_t size)
|
||||
const idx_t end_bit = addr_to_bit(addr + size - 1);
|
||||
bool end_bit_ok = _end_bits.par_set_bit(end_bit);
|
||||
assert(end_bit_ok, "concurrency problem");
|
||||
DEBUG_ONLY(Atomic::inc_ptr(&mark_bitmap_count));
|
||||
DEBUG_ONLY(Atomic::inc(&mark_bitmap_count));
|
||||
DEBUG_ONLY(Atomic::add_ptr(size, &mark_bitmap_size));
|
||||
return true;
|
||||
}
|
||||
|
@ -520,7 +520,7 @@ void ParallelCompactData::add_obj(HeapWord* addr, size_t len)
|
||||
const size_t beg_region = obj_ofs >> Log2RegionSize;
|
||||
const size_t end_region = (obj_ofs + len - 1) >> Log2RegionSize;
|
||||
|
||||
DEBUG_ONLY(Atomic::inc_ptr(&add_obj_count);)
|
||||
DEBUG_ONLY(Atomic::inc(&add_obj_count);)
|
||||
DEBUG_ONLY(Atomic::add_ptr(len, &add_obj_size);)
|
||||
|
||||
if (beg_region == end_region) {
|
||||
|
@ -517,7 +517,7 @@ ParallelCompactData::RegionData::set_blocks_filled()
|
||||
OrderAccess::release();
|
||||
_blocks_filled = true;
|
||||
// Debug builds count the number of times the table was filled.
|
||||
DEBUG_ONLY(Atomic::inc_ptr(&_blocks_filled_count));
|
||||
DEBUG_ONLY(Atomic::inc(&_blocks_filled_count));
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -97,21 +97,21 @@ class Atomic : AllStatic {
|
||||
return add(add_value, reinterpret_cast<char* volatile*>(dest));
|
||||
}
|
||||
|
||||
// Atomically increment location. inc*() provide:
|
||||
// Atomically increment location. inc() provide:
|
||||
// <fence> increment-dest <membar StoreLoad|StoreStore>
|
||||
inline static void inc (volatile jint* dest);
|
||||
inline static void inc (volatile jshort* dest);
|
||||
inline static void inc (volatile size_t* dest);
|
||||
inline static void inc_ptr(volatile intptr_t* dest);
|
||||
inline static void inc_ptr(volatile void* dest);
|
||||
// The type D may be either a pointer type, or an integral
|
||||
// type. If it is a pointer type, then the increment is
|
||||
// scaled to the size of the type pointed to by the pointer.
|
||||
template<typename D>
|
||||
inline static void inc(D volatile* dest);
|
||||
|
||||
// Atomically decrement a location. dec*() provide:
|
||||
// Atomically decrement a location. dec() provide:
|
||||
// <fence> decrement-dest <membar StoreLoad|StoreStore>
|
||||
inline static void dec (volatile jint* dest);
|
||||
inline static void dec (volatile jshort* dest);
|
||||
inline static void dec (volatile size_t* dest);
|
||||
inline static void dec_ptr(volatile intptr_t* dest);
|
||||
inline static void dec_ptr(volatile void* dest);
|
||||
// The type D may be either a pointer type, or an integral
|
||||
// type. If it is a pointer type, then the decrement is
|
||||
// scaled to the size of the type pointed to by the pointer.
|
||||
template<typename D>
|
||||
inline static void dec(D volatile* dest);
|
||||
|
||||
// Performs atomic exchange of *dest with exchange_value. Returns old
|
||||
// prior value of *dest. xchg*() provide:
|
||||
@ -312,6 +312,22 @@ struct Atomic::AddAndFetch VALUE_OBJ_CLASS_SPEC {
|
||||
D operator()(I add_value, D volatile* dest) const;
|
||||
};
|
||||
|
||||
template<typename D>
|
||||
inline void Atomic::inc(D volatile* dest) {
|
||||
STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value);
|
||||
typedef typename Conditional<IsPointer<D>::value, ptrdiff_t, D>::type I;
|
||||
Atomic::add(I(1), dest);
|
||||
}
|
||||
|
||||
template<typename D>
|
||||
inline void Atomic::dec(D volatile* dest) {
|
||||
STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value);
|
||||
typedef typename Conditional<IsPointer<D>::value, ptrdiff_t, D>::type I;
|
||||
// Assumes two's complement integer representation.
|
||||
#pragma warning(suppress: 4146)
|
||||
Atomic::add(I(-1), dest);
|
||||
}
|
||||
|
||||
// Define the class before including platform file, which may specialize
|
||||
// the operator definition. No generic definition of specializations
|
||||
// of the operator template are provided, nor are there any generic
|
||||
@ -437,14 +453,6 @@ inline D Atomic::add_using_helper(Fn fn, I add_value, D volatile* dest) {
|
||||
reinterpret_cast<Type volatile*>(dest)));
|
||||
}
|
||||
|
||||
inline void Atomic::inc(volatile size_t* dest) {
|
||||
inc_ptr((volatile intptr_t*) dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec(volatile size_t* dest) {
|
||||
dec_ptr((volatile intptr_t*) dest);
|
||||
}
|
||||
|
||||
template<typename T, typename D, typename U>
|
||||
inline D Atomic::cmpxchg(T exchange_value,
|
||||
D volatile* dest,
|
||||
@ -591,12 +599,4 @@ inline unsigned Atomic::xchg(unsigned int exchange_value, volatile unsigned int*
|
||||
return (unsigned int)Atomic::xchg((jint)exchange_value, (volatile jint*)dest);
|
||||
}
|
||||
|
||||
inline void Atomic::inc(volatile jshort* dest) {
|
||||
(void)add(jshort(1), dest);
|
||||
}
|
||||
|
||||
inline void Atomic::dec(volatile jshort* dest) {
|
||||
(void)add(jshort(-1), dest);
|
||||
}
|
||||
|
||||
#endif // SHARE_VM_RUNTIME_ATOMIC_HPP
|
||||
|
Loading…
Reference in New Issue
Block a user