< prev index next >

src/hotspot/cpu/x86/macroAssembler_x86.cpp

Print this page
@@ -52,10 +52,16 @@
  #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)

@@ -3769,16 +3775,29 @@
  }
  
  // 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;

@@ -3787,11 +3806,10 @@
      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);

@@ -4731,16 +4749,45 @@
    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()));
  }

@@ -4749,19 +4796,59 @@
    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();

@@ -5117,11 +5204,11 @@
  }
  
  #endif // _LP64
  
  // C2 compiled method's prolog code.
- void MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b, bool is_stub) {
+ void MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b, bool is_stub, int max_monitors) {
  
    // WARNING: Initial instruction MUST be 5 bytes or longer so that
    // NativeJump::patch_verified_entry will be able to patch out the entry
    // code safely. The push to verify stack depth is ok at 5 bytes,
    // the frame allocation can be either 3 or 6 bytes. So if we don't do

@@ -5199,10 +5286,24 @@
      STOP("Stack is not properly aligned!");
      bind(L);
    }
  #endif
  
+ #if defined(_LP64) && defined(COMPILER2)
+   if (UseFastLocking && max_monitors > 0) {
+     C2CheckLockStackStub* stub = new (Compile::current()->comp_arena()) C2CheckLockStackStub();
+     Compile::current()->output()->add_stub(stub);
+     assert(!is_stub, "only methods have monitors");
+     Register thread = r15_thread;
+     movptr(rax, Address(thread, JavaThread::lock_stack_current_offset()));
+     addptr(rax, max_monitors * wordSize);
+     cmpptr(rax, Address(thread, JavaThread::lock_stack_limit_offset()));
+     jcc(Assembler::greaterEqual, stub->entry());
+     bind(stub->continuation());
+   }
+ #endif
+ 
    if (!is_stub) {
      BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
      bs->nmethod_entry_barrier(this);
    }
  }

@@ -8681,5 +8782,63 @@
      pop(rax);
    }
  }
  
  #endif // !WIN32 || _LP64
+ 
+ void MacroAssembler::fast_lock_impl(Register obj, Register hdr, Register thread, Register tmp, Label& slow, bool rt_check_stack) {
+   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.
+   if (rt_check_stack) {
+     movptr(tmp, Address(thread, JavaThread::lock_stack_current_offset()));
+     cmpptr(tmp, Address(thread, JavaThread::lock_stack_limit_offset()));
+     jcc(Assembler::greaterEqual, slow);
+   }
+ #ifdef ASSERT
+   else {
+     Label ok;
+     movptr(tmp, Address(thread, JavaThread::lock_stack_current_offset()));
+     cmpptr(tmp, Address(thread, JavaThread::lock_stack_limit_offset()));
+     jcc(Assembler::less, ok);
+     stop("Not enough room in lock stack; should have been checked in the method prologue");
+     bind(ok);
+   }
+ #endif
+ 
+   // Now we attempt to take the fast-lock.
+   // Clear lowest two header bits (locked state).
+   andptr(hdr, ~(int32_t )markWord::lock_mask_in_place);
+   movptr(tmp, hdr);
+   // Set lowest bit (unlocked state).
+   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.
+   movptr(tmp, Address(thread, JavaThread::lock_stack_current_offset()));
+   movptr(Address(tmp, 0), obj);
+   addptr(tmp, oopSize);
+   movptr(Address(thread, JavaThread::lock_stack_current_offset()), tmp);
+ }
+ 
+ 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 00 now, try to swing it back to 01 (unlocked)
+   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(rax);
+ #endif
+   subptr(Address(thread, JavaThread::lock_stack_current_offset()), oopSize);
+ }
< prev index next >