Skip to content

Commit 8333926

Browse files
committed
In CAS loop, update old_value from result of CAS
1 parent f6445b1 commit 8333926

File tree

6 files changed

+38
-20
lines changed

6 files changed

+38
-20
lines changed

src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,15 @@ class NativeNMethodBarrier {
119119

120120
void set_value(int value, int bit_mask) {
121121
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
122+
value &= bit_mask;
123+
int old_value = Atomic::load(guard_addr());
122124
while (true) {
123-
int old = Atomic::load(guard_addr());
124125
// Only bits in the mask are changed
125-
int new_value = value | (old & ~bit_mask);
126-
int v = Atomic::cmpxchg(guard_addr(), old, new_value, memory_order_release);
127-
if (v == old) break;
126+
int new_value = value | (old_value & ~bit_mask);
127+
if (new_value == old_value) break;
128+
int v = Atomic::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
129+
if (v == old_value) break;
130+
old_value = v;
128131
}
129132
}
130133

src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,15 @@ class NativeNMethodBarrier: public NativeInstruction {
5353

5454
void set_value(int value, int bit_mask) {
5555
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
56+
value &= bit_mask;
57+
int old_value = Atomic::load(guard_addr());
5658
while (true) {
57-
int old = Atomic::load(guard_addr());
5859
// Only bits in the mask are changed
59-
int new_value = value | (old & ~bit_mask);
60-
int v = Atomic::cmpxchg(guard_addr(), old, new_value, memory_order_release);
61-
if (v == old) break;
60+
int new_value = value | (old_value & ~bit_mask);
61+
if (new_value == old_value) break;
62+
int v = Atomic::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
63+
if (v == old_value) break;
64+
old_value = v;
6265
}
6366
}
6467

src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class NativeNMethodBarrier: public NativeInstruction {
4949

5050
void release_set_guard_value(int value, int bit_mask) {
5151
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
52+
value &= bit_mask;
5253
// Patching is not atomic.
5354
// Stale observations of the "armed" state is okay as invoking the barrier stub in that case has no
5455
// unwanted side effects. Disarming is thus a non-critical operation.
@@ -58,20 +59,22 @@ class NativeNMethodBarrier: public NativeInstruction {
5859

5960
NativeMovRegMem* mov = get_patchable_instruction_handle();
6061
uint64_t *instr = (uint64_t*)mov->instruction_address();
61-
assert(NativeMovRegMem::instruction_size >= sizeof(instr), "must be");
62+
assert(NativeMovRegMem::instruction_size == sizeof(*instr), "must be");
6263
union {
6364
u_char buf[NativeMovRegMem::instruction_size];
6465
uint64_t u64;
6566
} new_mov_instr, old_mov_instr;
67+
new_mov_instr.u64 = old_mov_instr.u64 = Atomic::load(instr);
6668
while (true) {
67-
new_mov_instr.u64 = old_mov_instr.u64 = Atomic::load(instr);
68-
int old_value = nativeMovRegMem_at(old_mov_instr.buf)->offset();
6969
// Only bits in the mask are changed
70+
int old_value = nativeMovRegMem_at(old_mov_instr.buf)->offset();
7071
int new_value = value | (old_value & ~bit_mask);
72+
if (new_value == old_value) break;
7173
nativeMovRegMem_at(new_mov_instr.buf)->set_offset(new_value, false /* no icache flush */);
7274
// Swap in the new value
7375
uint64_t v = Atomic::cmpxchg(instr, old_mov_instr.u64, new_mov_instr.u64, memory_order_release);
7476
if (v == old_mov_instr.u64) break;
77+
old_mov_instr.u64 = v;
7578
}
7679
ICache::ppc64_flush_icache_bytes(addr_at(0), NativeMovRegMem::instruction_size);
7780
}

src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,15 @@ class NativeNMethodBarrier {
113113

114114
void set_value(int value, int bit_mask) {
115115
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
116+
value &= bit_mask;
117+
int old_value = Atomic::load(guard_addr());
116118
while (true) {
117-
int old = Atomic::load(guard_addr());
118119
// Only bits in the mask are changed
119-
int new_value = value | (old & ~bit_mask);
120-
int v = Atomic::cmpxchg(guard_addr(), old, new_value, memory_order_release);
121-
if (v == old) break;
120+
int new_value = value | (old_value & ~bit_mask);
121+
if (new_value == old_value) break;
122+
int v = Atomic::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
123+
if (v == old_value) break;
124+
old_value = v;
122125
}
123126
}
124127

src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,16 @@ class NativeMethodBarrier: public NativeInstruction {
5555

5656
void set_guard_value(int value, int bit_mask) {
5757
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
58+
value &= bit_mask;
5859
int32_t* data_addr = (int32_t*)get_patchable_data_address();
60+
int old_value = Atomic::load(data_addr);
5961
while (true) {
60-
int old = Atomic::load(data_addr);
6162
// Only bits in the mask are changed
62-
int new_value = value | (old & ~bit_mask);
63-
int v = Atomic::cmpxchg(data_addr, old, new_value, memory_order_release);
64-
if (v == old) break;
63+
int new_value = value | (old_value & ~bit_mask);
64+
if (new_value == old_value) break;
65+
int v = Atomic::cmpxchg(data_addr, old_value, new_value, memory_order_release);
66+
if (v == old_value) break;
67+
old_value = v;
6568
}
6669
}
6770

src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,22 +55,25 @@ class NativeNMethodCmpBarrier: public NativeInstruction {
5555
jint get_immediate() const { return int_at(imm_offset); }
5656
void set_immediate(jint imm, int bit_mask) {
5757
assert((imm & ~bit_mask) == 0, "trying to set bits outside the mask");
58+
imm &= bit_mask;
5859

5960
uint64_t *instr = (uint64_t*)instruction_address();
6061
assert(instruction_size >= sizeof(instr), "must be");
6162
union {
6263
unsigned char buf[instruction_size];
6364
uint64_t u64;
6465
} new_mov_instr, old_mov_instr;
66+
new_mov_instr.u64 = old_mov_instr.u64 = Atomic::load(instr);
6567
while (true) {
66-
new_mov_instr.u64 = old_mov_instr.u64 = Atomic::load(instr);
6768
int old_value = nativeNMethodCmpBarrier_at(old_mov_instr.buf)->get_immediate();
6869
// Only bits in the mask are changed
6970
int new_value = imm | (old_value & ~bit_mask);
71+
if (new_value == old_value) break;
7072
nativeNMethodCmpBarrier_at(new_mov_instr.buf)->set_int_at(imm_offset, new_value);
7173
// Swap in the new value
7274
uint64_t v = Atomic::cmpxchg(instr, old_mov_instr.u64, new_mov_instr.u64, memory_order_release);
7375
if (v == old_mov_instr.u64) break;
76+
old_mov_instr.u64 = v;
7477
}
7578
}
7679
bool check_barrier(err_msg& msg) const;

0 commit comments

Comments
 (0)