This commit is contained in:
Staffan Larsen 2014-11-13 07:58:28 +01:00
commit 8adbb0b63a
17 changed files with 249 additions and 120 deletions

View File

@ -122,7 +122,7 @@ SA_LFLAGS = $(SA_LD_FLAGS) -nologo -subsystem:console -machine:$(MACHINE)
SA_LFLAGS = $(SA_LFLAGS) -map -debug
!endif
!if "$(BUILDARCH)" == "i486"
SA_LFLAGS = $(SAFESEH_FLAG) $(SA_LFLAGS)
SA_LFLAGS = /SAFESEH $(SA_LFLAGS)
!endif
SA_CFLAGS = $(SA_CFLAGS) $(MP_FLAG)

View File

@ -2734,12 +2734,12 @@ void MacroAssembler::biased_locking_exit (Address mark_addr, Register temp_reg,
// box->dhw disposition - post-conditions at DONE_LABEL.
// - Successful inflated lock: box->dhw != 0.
// Any non-zero value suffices.
// Consider G2_thread, rsp, boxReg, or unused_mark()
// Consider G2_thread, rsp, boxReg, or markOopDesc::unused_mark()
// - Successful Stack-lock: box->dhw == mark.
// box->dhw must contain the displaced mark word value
// - Failure -- icc.ZFlag == 0 and box->dhw is undefined.
// The slow-path fast_enter() and slow_enter() operators
// are responsible for setting box->dhw = NonZero (typically ::unused_mark).
// are responsible for setting box->dhw = NonZero (typically markOopDesc::unused_mark()).
// - Biased: box->dhw is undefined
//
// SPARC refworkload performance - specifically jetstream and scimark - are
@ -2855,7 +2855,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark,
// If m->owner != null goto IsLocked
// Pessimistic form: Test-and-CAS vs CAS
// The optimistic form avoids RTS->RTO cache line upgrades.
ld_ptr(Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch);
ld_ptr(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), Rscratch);
andcc(Rscratch, Rscratch, G0);
brx(Assembler::notZero, false, Assembler::pn, done);
delayed()->nop();
@ -2864,7 +2864,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark,
// Try to CAS m->owner from null to Self
// Invariant: if we acquire the lock then _recursions should be 0.
add(Rmark, ObjectMonitor::owner_offset_in_bytes()-2, Rmark);
add(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), Rmark);
mov(G2_thread, Rscratch);
cas_ptr(Rmark, G0, Rscratch);
cmp(Rscratch, G0);
@ -2948,7 +2948,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark,
// Test-and-CAS vs CAS
// Pessimistic form avoids futile (doomed) CAS attempts
// The optimistic form avoids RTS->RTO cache line upgrades.
ld_ptr(Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch);
ld_ptr(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), Rscratch);
andcc(Rscratch, Rscratch, G0);
brx(Assembler::notZero, false, Assembler::pn, done);
delayed()->nop();
@ -2957,13 +2957,13 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark,
// Try to CAS m->owner from null to Self
// Invariant: if we acquire the lock then _recursions should be 0.
add(Rmark, ObjectMonitor::owner_offset_in_bytes()-2, Rmark);
add(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), Rmark);
mov(G2_thread, Rscratch);
cas_ptr(Rmark, G0, Rscratch);
cmp(Rscratch, G0);
// ST box->displaced_header = NonZero.
// Any non-zero value suffices:
// unused_mark(), G2_thread, RBox, RScratch, rsp, etc.
// markOopDesc::unused_mark(), G2_thread, RBox, RScratch, rsp, etc.
st_ptr(Rbox, Rbox, BasicLock::displaced_header_offset_in_bytes());
// Intentional fall-through into done
}
@ -3031,30 +3031,30 @@ void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark,
// Note that we use 1-0 locking by default for the inflated case. We
// close the resultant (and rare) race by having contented threads in
// monitorenter periodically poll _owner.
ld_ptr(Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch);
ld_ptr(Rmark, ObjectMonitor::recursions_offset_in_bytes() - 2, Rbox);
ld_ptr(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), Rscratch);
ld_ptr(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions), Rbox);
xor3(Rscratch, G2_thread, Rscratch);
orcc(Rbox, Rscratch, Rbox);
brx(Assembler::notZero, false, Assembler::pn, done);
delayed()->
ld_ptr(Rmark, ObjectMonitor::EntryList_offset_in_bytes() - 2, Rscratch);
ld_ptr(Rmark, ObjectMonitor::cxq_offset_in_bytes() - 2, Rbox);
ld_ptr(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList), Rscratch);
ld_ptr(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq), Rbox);
orcc(Rbox, Rscratch, G0);
if (EmitSync & 65536) {
Label LSucc ;
brx(Assembler::notZero, false, Assembler::pn, LSucc);
delayed()->nop();
ba(done);
delayed()->st_ptr(G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2);
delayed()->st_ptr(G0, Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner));
bind(LSucc);
st_ptr(G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2);
st_ptr(G0, Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner));
if (os::is_MP()) { membar (StoreLoad); }
ld_ptr(Rmark, ObjectMonitor::succ_offset_in_bytes() - 2, Rscratch);
ld_ptr(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ), Rscratch);
andcc(Rscratch, Rscratch, G0);
brx(Assembler::notZero, false, Assembler::pt, done);
delayed()->andcc(G0, G0, G0);
add(Rmark, ObjectMonitor::owner_offset_in_bytes()-2, Rmark);
add(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), Rmark);
mov(G2_thread, Rscratch);
cas_ptr(Rmark, G0, Rscratch);
// invert icc.zf and goto done
@ -3066,7 +3066,7 @@ void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark,
brx(Assembler::notZero, false, Assembler::pn, done);
delayed()->nop();
ba(done);
delayed()->st_ptr(G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2);
delayed()->st_ptr(G0, Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner));
}
bind (LStacked);

View File

@ -1450,8 +1450,7 @@ void MacroAssembler::rtm_retry_lock_on_abort(Register retry_count_Reg, Register
void MacroAssembler::rtm_retry_lock_on_busy(Register retry_count_Reg, Register box_Reg,
Register tmp_Reg, Register scr_Reg, Label& retryLabel) {
Label SpinLoop, SpinExit, doneRetry;
// Clean monitor_value bit to get valid pointer
int owner_offset = ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value;
int owner_offset = OM_OFFSET_NO_MONITOR_VALUE_TAG(owner);
testl(retry_count_Reg, retry_count_Reg);
jccb(Assembler::zero, doneRetry);
@ -1532,7 +1531,7 @@ void MacroAssembler::rtm_stack_locking(Register objReg, Register tmpReg, Registe
// Use RTM for inflating locks
// inputs: objReg (object to lock)
// boxReg (on-stack box address (displaced header location) - KILLED)
// tmpReg (ObjectMonitor address + 2(monitor_value))
// tmpReg (ObjectMonitor address + markOopDesc::monitor_value)
void MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Register tmpReg,
Register scrReg, Register retry_on_busy_count_Reg,
Register retry_on_abort_count_Reg,
@ -1543,8 +1542,7 @@ void MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Regi
assert(tmpReg == rax, "");
assert(scrReg == rdx, "");
Label L_rtm_retry, L_decrement_retry, L_on_abort;
// Clean monitor_value bit to get valid pointer
int owner_offset = ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value;
int owner_offset = OM_OFFSET_NO_MONITOR_VALUE_TAG(owner);
// Without cast to int32_t a movptr will destroy r10 which is typically obj
movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark()));
@ -1716,7 +1714,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
atomic_incl(ExternalAddress((address)counters->total_entry_count_addr()), scrReg);
}
if (EmitSync & 1) {
// set box->dhw = unused_mark (3)
// set box->dhw = markOopDesc::unused_mark()
// Force all sync thru slow-path: slow_enter() and slow_exit()
movptr (Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark()));
cmpptr (rsp, (int32_t)NULL_WORD);
@ -1811,7 +1809,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
jmp(DONE_LABEL);
bind(IsInflated);
// The object is inflated. tmpReg contains pointer to ObjectMonitor* + 2(monitor_value)
// The object is inflated. tmpReg contains pointer to ObjectMonitor* + markOopDesc::monitor_value
#if INCLUDE_RTM_OPT
// Use the same RTM locking code in 32- and 64-bit VM.
@ -1823,25 +1821,10 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
#ifndef _LP64
// The object is inflated.
//
// TODO-FIXME: eliminate the ugly use of manifest constants:
// Use markOopDesc::monitor_value instead of "2".
// use markOop::unused_mark() instead of "3".
// The tmpReg value is an objectMonitor reference ORed with
// markOopDesc::monitor_value (2). We can either convert tmpReg to an
// objectmonitor pointer by masking off the "2" bit or we can just
// use tmpReg as an objectmonitor pointer but bias the objectmonitor
// field offsets with "-2" to compensate for and annul the low-order tag bit.
//
// I use the latter as it avoids AGI stalls.
// As such, we write "mov r, [tmpReg+OFFSETOF(Owner)-2]"
// instead of "mov r, [tmpReg+OFFSETOF(Owner)]".
//
#define OFFSET_SKEWED(f) ((ObjectMonitor::f ## _offset_in_bytes())-2)
// boxReg refers to the on-stack BasicLock in the current frame.
// We'd like to write:
// set box->_displaced_header = markOop::unused_mark(). Any non-0 value suffices.
// set box->_displaced_header = markOopDesc::unused_mark(). Any non-0 value suffices.
// This is convenient but results a ST-before-CAS penalty. The following CAS suffers
// additional latency as we have another ST in the store buffer that must drain.
@ -1853,7 +1836,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
if (os::is_MP()) {
lock();
}
cmpxchgptr(scrReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2));
cmpxchgptr(scrReg, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
} else
if ((EmitSync & 128) == 0) { // avoid ST-before-CAS
movptr(scrReg, boxReg);
@ -1862,7 +1845,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
// Using a prefetchw helps avoid later RTS->RTO upgrades and cache probes
if ((EmitSync & 2048) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) {
// prefetchw [eax + Offset(_owner)-2]
prefetchw(Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2));
prefetchw(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
}
if ((EmitSync & 64) == 0) {
@ -1871,7 +1854,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
} else {
// Can suffer RTS->RTO upgrades on shared or cold $ lines
// Test-And-CAS instead of CAS
movptr(tmpReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); // rax, = m->_owner
movptr(tmpReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); // rax, = m->_owner
testptr(tmpReg, tmpReg); // Locked ?
jccb (Assembler::notZero, DONE_LABEL);
}
@ -1887,11 +1870,11 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
if (os::is_MP()) {
lock();
}
cmpxchgptr(scrReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2));
cmpxchgptr(scrReg, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
movptr(Address(scrReg, 0), 3); // box->_displaced_header = 3
jccb (Assembler::notZero, DONE_LABEL);
get_thread (scrReg); // beware: clobbers ICCs
movptr(Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2), scrReg);
movptr(Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), scrReg);
xorptr(boxReg, boxReg); // set icc.ZFlag = 1 to indicate success
// If the CAS fails we can either retry or pass control to the slow-path.
@ -1908,7 +1891,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
// Using a prefetchw helps avoid later RTS->RTO upgrades and cache probes
if ((EmitSync & 2048) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) {
// prefetchw [eax + Offset(_owner)-2]
prefetchw(Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2));
prefetchw(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
}
if ((EmitSync & 64) == 0) {
@ -1916,7 +1899,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
xorptr (tmpReg, tmpReg);
} else {
// Can suffer RTS->RTO upgrades on shared or cold $ lines
movptr(tmpReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); // rax, = m->_owner
movptr(tmpReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); // rax, = m->_owner
testptr(tmpReg, tmpReg); // Locked ?
jccb (Assembler::notZero, DONE_LABEL);
}
@ -1928,7 +1911,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
if (os::is_MP()) {
lock();
}
cmpxchgptr(scrReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2));
cmpxchgptr(scrReg, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
// If the CAS fails we can either retry or pass control to the slow-path.
// We use the latter tactic.
@ -1951,7 +1934,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark()));
movptr (boxReg, tmpReg);
movptr (tmpReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2));
movptr(tmpReg, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
testptr(tmpReg, tmpReg);
jccb (Assembler::notZero, DONE_LABEL);
@ -1959,7 +1942,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
if (os::is_MP()) {
lock();
}
cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2));
cmpxchgptr(r15_thread, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
// Intentional fall-through into DONE_LABEL ...
#endif // _LP64
@ -2065,8 +2048,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
#if INCLUDE_RTM_OPT
if (use_rtm) {
Label L_regular_inflated_unlock;
// Clean monitor_value bit to get valid pointer
int owner_offset = ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value;
int owner_offset = OM_OFFSET_NO_MONITOR_VALUE_TAG(owner);
movptr(boxReg, Address(tmpReg, owner_offset));
testptr(boxReg, boxReg);
jccb(Assembler::notZero, L_regular_inflated_unlock);
@ -2102,7 +2084,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
get_thread (boxReg);
if ((EmitSync & 4096) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) {
// prefetchw [ebx + Offset(_owner)-2]
prefetchw(Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2));
prefetchw(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
}
// Note that we could employ various encoding schemes to reduce
@ -2111,21 +2093,21 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
// In practice the chain of fetches doesn't seem to impact performance, however.
if ((EmitSync & 65536) == 0 && (EmitSync & 256)) {
// Attempt to reduce branch density - AMD's branch predictor.
xorptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2));
orptr(boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2));
orptr(boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2));
orptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2));
xorptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList)));
orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq)));
jccb (Assembler::notZero, DONE_LABEL);
movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD);
movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD);
jmpb (DONE_LABEL);
} else {
xorptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2));
orptr(boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2));
xorptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
jccb (Assembler::notZero, DONE_LABEL);
movptr(boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2));
orptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2));
movptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList)));
orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq)));
jccb (Assembler::notZero, CheckSucc);
movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD);
movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD);
jmpb (DONE_LABEL);
}
@ -2143,7 +2125,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
// Optional pre-test ... it's safe to elide this
if ((EmitSync & 16) == 0) {
cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD);
cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), (int32_t)NULL_WORD);
jccb (Assembler::zero, LGoSlowPath);
}
@ -2173,7 +2155,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
// We currently use (3), although it's likely that switching to (2)
// is correct for the future.
movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD);
movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD);
if (os::is_MP()) {
if (VM_Version::supports_sse2() && 1 == FenceInstruction) {
mfence();
@ -2182,18 +2164,18 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
}
}
// Ratify _succ remains non-null
cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), 0);
cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), 0);
jccb (Assembler::notZero, LSuccess);
xorptr(boxReg, boxReg); // box is really EAX
if (os::is_MP()) { lock(); }
cmpxchgptr(rsp, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2));
cmpxchgptr(rsp, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
jccb (Assembler::notEqual, LSuccess);
// Since we're low on registers we installed rsp as a placeholding in _owner.
// Now install Self over rsp. This is safe as we're transitioning from
// non-null to non=null
get_thread (boxReg);
movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), boxReg);
movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), boxReg);
// Intentional fall-through into LGoSlowPath ...
bind (LGoSlowPath);
@ -2228,36 +2210,36 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
}
#else // _LP64
// It's inflated
movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2));
movptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
xorptr(boxReg, r15_thread);
orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2));
orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
jccb (Assembler::notZero, DONE_LABEL);
movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2));
orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2));
movptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq)));
orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList)));
jccb (Assembler::notZero, CheckSucc);
movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD);
movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), (int32_t)NULL_WORD);
jmpb (DONE_LABEL);
if ((EmitSync & 65536) == 0) {
Label LSuccess, LGoSlowPath ;
bind (CheckSucc);
cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD);
cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), (int32_t)NULL_WORD);
jccb (Assembler::zero, LGoSlowPath);
// I'd much rather use lock:andl m->_owner, 0 as it's faster than the
// the explicit ST;MEMBAR combination, but masm doesn't currently support
// "ANDQ M,IMM". Don't use MFENCE here. lock:add to TOS, xchg, etc
// are all faster when the write buffer is populated.
movptr (Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD);
movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), (int32_t)NULL_WORD);
if (os::is_MP()) {
lock (); addl (Address(rsp, 0), 0);
}
cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD);
cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), (int32_t)NULL_WORD);
jccb (Assembler::notZero, LSuccess);
movptr (boxReg, (int32_t)NULL_WORD); // box is really EAX
if (os::is_MP()) { lock(); }
cmpxchgptr(r15_thread, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2));
cmpxchgptr(r15_thread, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
jccb (Assembler::notEqual, LSuccess);
// Intentional fall-through into slow-path

View File

@ -2059,7 +2059,7 @@ methodHandle ClassFileParser::parse_method(bool is_interface,
u2** localvariable_table_start;
u2* localvariable_type_table_length;
u2** localvariable_type_table_start;
u2 method_parameters_length = 0;
int method_parameters_length = -1;
u1* method_parameters_data = NULL;
bool method_parameters_seen = false;
bool parsed_code_attribute = false;
@ -2278,7 +2278,8 @@ methodHandle ClassFileParser::parse_method(bool is_interface,
}
method_parameters_seen = true;
method_parameters_length = cfs->get_u1_fast();
if (method_attribute_length != (method_parameters_length * 4u) + 1u) {
const u2 real_length = (method_parameters_length * 4u) + 1u;
if (method_attribute_length != real_length) {
classfile_parse_error(
"Invalid MethodParameters method attribute length %u in class file",
method_attribute_length, CHECK_(nullHandle));
@ -2288,7 +2289,7 @@ methodHandle ClassFileParser::parse_method(bool is_interface,
cfs->skip_u2_fast(method_parameters_length);
// ignore this attribute if it cannot be reflected
if (!SystemDictionary::Parameter_klass_loaded())
method_parameters_length = 0;
method_parameters_length = -1;
} else if (method_attribute_name == vmSymbols::tag_synthetic()) {
if (method_attribute_length != 0) {
classfile_parse_error(
@ -3491,17 +3492,18 @@ void ClassFileParser::layout_fields(Handle class_loader,
real_offset = next_nonstatic_oop_offset;
next_nonstatic_oop_offset += heapOopSize;
}
// Update oop maps
// Record this oop in the oop maps
if( nonstatic_oop_map_count > 0 &&
nonstatic_oop_offsets[nonstatic_oop_map_count - 1] ==
real_offset -
int(nonstatic_oop_counts[nonstatic_oop_map_count - 1]) *
heapOopSize ) {
// Extend current oop map
// This oop is adjacent to the previous one, add to current oop map
assert(nonstatic_oop_map_count - 1 < max_nonstatic_oop_maps, "range check");
nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
} else {
// Create new oop map
// This oop is not adjacent to the previous one, create new oop map
assert(nonstatic_oop_map_count < max_nonstatic_oop_maps, "range check");
nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
@ -3623,13 +3625,24 @@ void ClassFileParser::layout_fields(Handle class_loader,
real_offset = next_nonstatic_padded_offset;
next_nonstatic_padded_offset += heapOopSize;
// Create new oop map
assert(nonstatic_oop_map_count < max_nonstatic_oop_maps, "range check");
nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
nonstatic_oop_map_count += 1;
if( first_nonstatic_oop_offset == 0 ) { // Undefined
first_nonstatic_oop_offset = real_offset;
// Record this oop in the oop maps
if( nonstatic_oop_map_count > 0 &&
nonstatic_oop_offsets[nonstatic_oop_map_count - 1] ==
real_offset -
int(nonstatic_oop_counts[nonstatic_oop_map_count - 1]) *
heapOopSize ) {
// This oop is adjacent to the previous one, add to current oop map
assert(nonstatic_oop_map_count - 1 < max_nonstatic_oop_maps, "range check");
nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
} else {
// This oop is not adjacent to the previous one, create new oop map
assert(nonstatic_oop_map_count < max_nonstatic_oop_maps, "range check");
nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
nonstatic_oop_map_count += 1;
if( first_nonstatic_oop_offset == 0 ) { // Undefined
first_nonstatic_oop_offset = real_offset;
}
}
break;

View File

@ -1120,7 +1120,7 @@ instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) {
h = context.record_result(classpath_index, e, result, THREAD);
} else {
if (DumpSharedSpaces) {
tty->print_cr("Preload Error: Cannot find %s", class_name);
tty->print_cr("Preload Warning: Cannot find %s", class_name);
}
}

View File

@ -223,7 +223,7 @@ void Dictionary::remove_classes_in_error_state() {
}
free_entry(probe);
ResourceMark rm;
tty->print_cr("Removed error class: %s", ik->external_name());
tty->print_cr("Preload Warning: Removed error class: %s", ik->external_name());
continue;
}

View File

@ -715,15 +715,17 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
if (class_list_path_len >= 3) {
if (strcmp(class_list_path_str + class_list_path_len - 3, "lib") != 0) {
if (class_list_path_len < JVM_MAXPATHLEN - 4) {
strncat(class_list_path_str, os::file_separator(), 1);
strncat(class_list_path_str, "lib", 3);
jio_snprintf(class_list_path_str + class_list_path_len,
sizeof(class_list_path_str) - class_list_path_len,
"%slib", os::file_separator());
class_list_path_len += 4;
}
}
}
class_list_path_len = (int)strlen(class_list_path_str);
if (class_list_path_len < JVM_MAXPATHLEN - 10) {
strncat(class_list_path_str, os::file_separator(), 1);
strncat(class_list_path_str, "classlist", 9);
jio_snprintf(class_list_path_str + class_list_path_len,
sizeof(class_list_path_str) - class_list_path_len,
"%sclasslist", os::file_separator());
}
class_list_path = class_list_path_str;
} else {
@ -851,7 +853,7 @@ bool MetaspaceShared::try_link_class(InstanceKlass* ik, TRAPS) {
ik->link_class(THREAD);
if (HAS_PENDING_EXCEPTION) {
ResourceMark rm;
tty->print_cr("Preload Error: Verification failed for %s",
tty->print_cr("Preload Warning: Verification failed for %s",
ik->external_name());
CLEAR_PENDING_EXCEPTION;
ik->set_in_error_state();

View File

@ -116,7 +116,11 @@ int ConstMethod::size(int code_size,
if (sizes->generic_signature_index() != 0) {
extra_bytes += sizeof(u2);
}
if (sizes->method_parameters_length() > 0) {
// This has to be a less-than-or-equal check, because we might be
// storing information from a zero-length MethodParameters
// attribute. We have to store these, because in some cases, they
// cause the reflection API to throw a MalformedParametersException.
if (sizes->method_parameters_length() >= 0) {
extra_bytes += sizeof(u2);
extra_bytes += sizes->method_parameters_length() * sizeof(MethodParametersElement);
}
@ -237,7 +241,7 @@ void ConstMethod::set_inlined_tables_length(InlineTableSizes* sizes) {
_flags |= _has_linenumber_table;
if (sizes->generic_signature_index() != 0)
_flags |= _has_generic_signature;
if (sizes->method_parameters_length() > 0)
if (sizes->method_parameters_length() >= 0)
_flags |= _has_method_parameters;
if (sizes->checked_exceptions_length() > 0)
_flags |= _has_checked_exceptions;
@ -272,7 +276,7 @@ void ConstMethod::set_inlined_tables_length(InlineTableSizes* sizes) {
if (sizes->generic_signature_index() != 0)
*(generic_signature_index_addr()) = sizes->generic_signature_index();
// New data should probably go here.
if (sizes->method_parameters_length() > 0)
if (sizes->method_parameters_length() >= 0)
*(method_parameters_length_addr()) = sizes->method_parameters_length();
if (sizes->checked_exceptions_length() > 0)
*(checked_exceptions_length_addr()) = sizes->checked_exceptions_length();
@ -283,7 +287,7 @@ void ConstMethod::set_inlined_tables_length(InlineTableSizes* sizes) {
}
int ConstMethod::method_parameters_length() const {
return has_method_parameters() ? *(method_parameters_length_addr()) : 0;
return has_method_parameters() ? *(method_parameters_length_addr()) : -1;
}
MethodParametersElement* ConstMethod::method_parameters_start() const {

View File

@ -372,6 +372,11 @@ public:
ExceptionTableElement* exception_table_start() const;
// method parameters table
// This returns -1 if no parameters are present, a non-negative
// value otherwise. Note: sometimes, there are 0-length parameters
// attributes that must be reported up to the reflection API all the
// same.
int method_parameters_length() const;
MethodParametersElement* method_parameters_start() const;

View File

@ -1657,7 +1657,17 @@ JVM_ENTRY(jobjectArray, JVM_GetMethodParameters(JNIEnv *env, jobject method))
Handle reflected_method (THREAD, JNIHandles::resolve_non_null(method));
const int num_params = mh->method_parameters_length();
if (0 != num_params) {
if (num_params < 0) {
// A -1 return value from method_parameters_length means there is no
// parameter data. Return null to indicate this to the reflection
// API.
assert(num_params == -1, "num_params should be -1 if it is less than zero");
return (jobjectArray)NULL;
} else {
// Otherwise, we return something up to reflection, even if it is
// a zero-length array. Why? Because in some cases this can
// trigger a MalformedParametersException.
// make sure all the symbols are properly formatted
for (int i = 0; i < num_params; i++) {
MethodParametersElement* params = mh->method_parameters_start();
@ -1685,8 +1695,6 @@ JVM_ENTRY(jobjectArray, JVM_GetMethodParameters(JNIEnv *env, jobject method))
result->obj_at_put(i, param);
}
return (jobjectArray)JNIHandles::make_local(env, result());
} else {
return (jobjectArray)NULL;
}
}
JVM_END

View File

@ -228,6 +228,20 @@ class ObjectMonitor {
static int Responsible_offset_in_bytes() { return offset_of(ObjectMonitor, _Responsible); }
static int Spinner_offset_in_bytes() { return offset_of(ObjectMonitor, _Spinner); }
// ObjectMonitor references can be ORed with markOopDesc::monitor_value
// as part of the ObjectMonitor tagging mechanism. When we combine an
// ObjectMonitor reference with an offset, we need to remove the tag
// value in order to generate the proper address.
//
// We can either adjust the ObjectMonitor reference and then add the
// offset or we can adjust the offset that is added to the ObjectMonitor
// reference. The latter avoids an AGI (Address Generation Interlock)
// stall so the helper macro adjusts the offset value that is returned
// to the ObjectMonitor reference manipulation code:
//
#define OM_OFFSET_NO_MONITOR_VALUE_TAG(f) \
((ObjectMonitor::f ## _offset_in_bytes()) - markOopDesc::monitor_value)
// Eventually we'll make provisions for multiple callbacks, but
// now one will suffice.
static int (*SpinCallbackFunction)(intptr_t, int);

View File

@ -806,17 +806,16 @@ oop Reflection::new_field(fieldDescriptor* fd, TRAPS) {
oop Reflection::new_parameter(Handle method, int index, Symbol* sym,
int flags, TRAPS) {
Handle name;
// A null symbol here translates to the empty string
if(NULL != sym) {
name = java_lang_String::create_from_symbol(sym, CHECK_NULL);
} else {
name = java_lang_String::create_from_str("", CHECK_NULL);
}
Handle rh = java_lang_reflect_Parameter::create(CHECK_NULL);
java_lang_reflect_Parameter::set_name(rh(), name());
if(NULL != sym) {
Handle name = java_lang_String::create_from_symbol(sym, CHECK_NULL);
java_lang_reflect_Parameter::set_name(rh(), name());
} else {
java_lang_reflect_Parameter::set_name(rh(), NULL);
}
java_lang_reflect_Parameter::set_modifiers(rh(), flags);
java_lang_reflect_Parameter::set_executable(rh(), method());
java_lang_reflect_Parameter::set_index(rh(), index);

View File

@ -243,15 +243,15 @@ class MallocHeader VALUE_OBJ_CLASS_SPEC {
size_t _flags : 8;
size_t _pos_idx : 16;
size_t _bucket_idx: 40;
#define MAX_MALLOCSITE_TABLE_SIZE ((size_t)1 << 40)
#define MAX_BUCKET_LENGTH ((size_t)(1 << 16))
#define MAX_MALLOCSITE_TABLE_SIZE right_n_bits(40)
#define MAX_BUCKET_LENGTH right_n_bits(16)
#else
size_t _size : 32;
size_t _flags : 8;
size_t _pos_idx : 8;
size_t _bucket_idx: 16;
#define MAX_MALLOCSITE_TABLE_SIZE ((size_t)(1 << 16))
#define MAX_BUCKET_LENGTH ((size_t)(1 << 8))
#define MAX_MALLOCSITE_TABLE_SIZE right_n_bits(16)
#define MAX_BUCKET_LENGTH right_n_bits(8)
#endif // _LP64
public:

View File

@ -27,7 +27,6 @@
* @requires sun.arch.data.model == "32"
* @key nmt jcmd stress
* @library /testlibrary /testlibrary/whitebox
* @ignore 8062870
* @build MallocSiteHashOverflow
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocSiteHashOverflow

View File

@ -27,7 +27,6 @@
* @summary Test to verify correctness of malloc tracking
* @key nmt jcmd
* @library /testlibrary /testlibrary/whitebox
* @ignore 8058251
* @build MallocTrackingVerify
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocTrackingVerify

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.Class;
import java.lang.String;
import java.lang.System;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CyclicBarrier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import sun.misc.Unsafe;
import sun.misc.Contended;
/*
* @test
* @bug 8015272
* @summary \@Contended within the same group to use the same oop map
*
* @run main/othervm -XX:-RestrictContended -XX:ContendedPaddingWidth=128 -Xmx128m OopMapsSameGroup
*/
public class OopMapsSameGroup {
public static final int COUNT = 10000;
public static void main(String[] args) throws Exception {
Object o01 = new Object();
Object o02 = new Object();
Object o03 = new Object();
Object o04 = new Object();
R[] rs = new R[COUNT];
for (int i = 0; i < COUNT; i++) {
R r = new R();
r.o01 = o01;
r.o02 = o02;
r.o03 = o03;
r.o04 = o04;
rs[i] = r;
}
System.gc();
for (int i = 0; i < COUNT; i++) {
R r = rs[i];
if (r.o01 != o01) throw new Error("Test Error: o01");
if (r.o02 != o02) throw new Error("Test Error: o02");
if (r.o03 != o03) throw new Error("Test Error: o03");
if (r.o04 != o04) throw new Error("Test Error: o04");
}
}
public static class R {
@Contended("group1")
Object o01;
@Contended("group1")
Object o02;
@Contended("group2")
Object o03;
@Contended("group2")
Object o04;
}
}

View File

@ -207,4 +207,13 @@ public class WhiteBox {
.findAny()
.orElse(null);
}
public native int getOffsetForName0(String name);
public int getOffsetForName(String name) throws Exception {
int offset = getOffsetForName0(name);
if (offset == -1) {
throw new RuntimeException(name + " not found");
}
return offset;
}
}