< prev index next > src/hotspot/cpu/x86/macroAssembler_x86.cpp
Print this page
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.hpp"
#include "utilities/macros.hpp"
#include "crc32c.h"
+ #ifdef COMPILER2
+ #include "opto/c2_CodeStubs.hpp"
+ #include "opto/compile.hpp"
+ #include "opto/output.hpp"
+ #endif
+
#ifdef PRODUCT
#define BLOCK_COMMENT(str) /* nothing */
#define STOP(error) stop(error)
#else
#define BLOCK_COMMENT(str) block_comment(str)
}
// Preserves the contents of address, destroys the contents length_in_bytes and temp.
void MacroAssembler::zero_memory(Register address, Register length_in_bytes, int offset_in_bytes, Register temp) {
assert(address != length_in_bytes && address != temp && temp != length_in_bytes, "registers must be different");
- assert((offset_in_bytes & (BytesPerWord - 1)) == 0, "offset must be a multiple of BytesPerWord");
+ assert((offset_in_bytes & (BytesPerInt - 1)) == 0, "offset must be a multiple of BytesPerInt");
Label done;
testptr(length_in_bytes, length_in_bytes);
jcc(Assembler::zero, done);
+ // Emit single 32bit store to clear leading bytes, if necessary.
+ xorptr(temp, temp); // use _zero reg to clear memory (shorter code)
+ #ifdef _LP64
+ if (!is_aligned(offset_in_bytes, BytesPerWord)) {
+ movl(Address(address, offset_in_bytes), temp);
+ offset_in_bytes += BytesPerInt;
+ decrement(length_in_bytes, BytesPerInt);
+ }
+ assert((offset_in_bytes & (BytesPerWord - 1)) == 0, "offset must be a multiple of BytesPerWord");
+ testptr(length_in_bytes, length_in_bytes);
+ jcc(Assembler::zero, done);
+ #endif
+
// initialize topmost word, divide index by 2, check if odd and test if zero
// note: for the remaining code to work, index must be a multiple of BytesPerWord
#ifdef ASSERT
{
Label L;
stop("length must be a multiple of BytesPerWord");
bind(L);
}
#endif
Register index = length_in_bytes;
- xorptr(temp, temp); // use _zero reg to clear memory (shorter code)
if (UseIncDec) {
shrptr(index, 3); // divide by 8/16 and set carry flag if bit 2 was set
} else {
shrptr(index, 2); // use 2 instructions to avoid partial flag stall
shrptr(index, 1);
movptr(holder, Address(method, Method::const_offset())); // ConstMethod*
movptr(holder, Address(holder, ConstMethod::constants_offset())); // ConstantPool*
movptr(holder, Address(holder, ConstantPool::pool_holder_offset_in_bytes())); // InstanceKlass*
}
- void MacroAssembler::load_klass(Register dst, Register src, Register tmp) {
+ #ifdef _LP64
+ void MacroAssembler::load_nklass(Register dst, Register src) {
+ assert(UseCompressedClassPointers, "expect compressed class pointers");
+
+ if (!UseCompactObjectHeaders) {
+ movl(dst, Address(src, oopDesc::klass_offset_in_bytes()));
+ return;
+ }
+
+ Label fast;
+ movq(dst, Address(src, oopDesc::mark_offset_in_bytes()));
+ testb(dst, markWord::monitor_value);
+ jccb(Assembler::zero, fast);
+
+ // Fetch displaced header
+ movq(dst, Address(dst, OM_OFFSET_NO_MONITOR_VALUE_TAG(header)));
+
+ bind(fast);
+ shrq(dst, markWord::klass_shift);
+ }
+ #endif
+
+ void MacroAssembler::load_klass(Register dst, Register src, Register tmp, bool null_check_src) {
assert_different_registers(src, tmp);
assert_different_registers(dst, tmp);
+ if (null_check_src) {
+ if (UseCompactObjectHeaders) {
+ null_check(src, oopDesc::mark_offset_in_bytes());
+ } else {
+ null_check(src, oopDesc::klass_offset_in_bytes());
+ }
+ }
#ifdef _LP64
if (UseCompressedClassPointers) {
- movl(dst, Address(src, oopDesc::klass_offset_in_bytes()));
+ load_nklass(dst, src);
decode_klass_not_null(dst, tmp);
} else
#endif
movptr(dst, Address(src, oopDesc::klass_offset_in_bytes()));
}
load_klass(dst, src, tmp);
movptr(dst, Address(dst, Klass::prototype_header_offset()));
}
void MacroAssembler::store_klass(Register dst, Register src, Register tmp) {
+ assert(!UseCompactObjectHeaders, "not with compact headers");
assert_different_registers(src, tmp);
assert_different_registers(dst, tmp);
#ifdef _LP64
if (UseCompressedClassPointers) {
encode_klass_not_null(src, tmp);
movl(Address(dst, oopDesc::klass_offset_in_bytes()), src);
} else
#endif
- movptr(Address(dst, oopDesc::klass_offset_in_bytes()), src);
+ movptr(Address(dst, oopDesc::klass_offset_in_bytes()), src);
+ }
+
+ void MacroAssembler::cmp_klass(Register klass, Register obj, Register tmp) {
+ #ifdef _LP64
+ if (UseCompactObjectHeaders) {
+ // NOTE: We need to deal with possible ObjectMonitor in object header.
+ // Eventually we might be able to do simple movl & cmpl like in
+ // the CCP path below.
+ load_nklass(tmp, obj);
+ cmpl(klass, tmp);
+ } else if (UseCompressedClassPointers) {
+ cmpl(klass, Address(obj, oopDesc::klass_offset_in_bytes()));
+ } else
+ #endif
+ {
+ cmpptr(klass, Address(obj, oopDesc::klass_offset_in_bytes()));
+ }
+ }
+
+ void MacroAssembler::cmp_klass(Register src, Register dst, Register tmp1, Register tmp2) {
+ #ifdef _LP64
+ if (UseCompactObjectHeaders) {
+ // NOTE: We need to deal with possible ObjectMonitor in object header.
+ // Eventually we might be able to do simple movl & cmpl like in
+ // the CCP path below.
+ assert(tmp2 != noreg, "need tmp2");
+ assert_different_registers(src, dst, tmp1, tmp2);
+ load_nklass(tmp1, src);
+ load_nklass(tmp2, dst);
+ cmpl(tmp1, tmp2);
+ } else if (UseCompressedClassPointers) {
+ movl(tmp1, Address(src, oopDesc::klass_offset_in_bytes()));
+ cmpl(tmp1, Address(dst, oopDesc::klass_offset_in_bytes()));
+ } else
+ #endif
+ {
+ movptr(tmp1, Address(src, oopDesc::klass_offset_in_bytes()));
+ cmpptr(tmp1, Address(dst, oopDesc::klass_offset_in_bytes()));
+ }
}
void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src,
Register tmp1, Register thread_tmp) {
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
pop(rax);
}
}
#endif // !WIN32 || _LP64
+
+ // Implements fast-locking.
+ // Branches to slow upon failure to lock the object, with ZF cleared.
+ // Falls through upon success with unspecified ZF.
+ //
+ // obj: the object to be locked
+ // hdr: the (pre-loaded) header of the object, must be rax
+ // thread: the thread which attempts to lock obj
+ // tmp: a temporary register
+ void MacroAssembler::fast_lock_impl(Register obj, Register hdr, Register thread, Register tmp, Label& slow) {
+ assert(hdr == rax, "header must be in rax for cmpxchg");
+ assert_different_registers(obj, hdr, thread, tmp);
+
+ // First we need to check if the lock-stack has room for pushing the object reference.
+ // Note: we subtract 1 from the end-offset so that we can do a 'greater' comparison, instead
+ // of 'greaterEqual' below, which readily clears the ZF. This makes C2 code a little simpler and
+ // avoids one branch.
+ cmpl(Address(thread, JavaThread::lock_stack_top_offset()), LockStack::end_offset() - 1);
+ jcc(Assembler::greater, slow);
+
+ // Now we attempt to take the fast-lock.
+ // Clear lock_mask bits (locked state).
+ andptr(hdr, ~(int32_t)markWord::lock_mask_in_place);
+ movptr(tmp, hdr);
+ // Set unlocked_value bit.
+ orptr(hdr, markWord::unlocked_value);
+ lock();
+ cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes()));
+ jcc(Assembler::notEqual, slow);
+
+ // If successful, push object to lock-stack.
+ movl(tmp, Address(thread, JavaThread::lock_stack_top_offset()));
+ movptr(Address(thread, tmp), obj);
+ incrementl(tmp, oopSize);
+ movl(Address(thread, JavaThread::lock_stack_top_offset()), tmp);
+ }
+
+ // Implements fast-unlocking.
+ // Branches to slow upon failure, with ZF cleared.
+ // Falls through upon success, with unspecified ZF.
+ //
+ // obj: the object to be unlocked
+ // hdr: the (pre-loaded) header of the object, must be rax
+ // tmp: a temporary register
+ void MacroAssembler::fast_unlock_impl(Register obj, Register hdr, Register tmp, Label& slow) {
+ assert(hdr == rax, "header must be in rax for cmpxchg");
+ assert_different_registers(obj, hdr, tmp);
+
+ // Mark-word must be lock_mask now, try to swing it back to unlocked_value.
+ movptr(tmp, hdr); // The expected old value
+ orptr(tmp, markWord::unlocked_value);
+ lock();
+ cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes()));
+ jcc(Assembler::notEqual, slow);
+ // Pop the lock object from the lock-stack.
+ #ifdef _LP64
+ const Register thread = r15_thread;
+ #else
+ const Register thread = rax;
+ get_thread(thread);
+ #endif
+ subl(Address(thread, JavaThread::lock_stack_top_offset()), oopSize);
+ #ifdef ASSERT
+ movl(tmp, Address(thread, JavaThread::lock_stack_top_offset()));
+ movptr(Address(thread, tmp), 0);
+ #endif
+ }
< prev index next >