< prev index next >

src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp

Print this page
@@ -36,16 +36,15 @@
  #include "runtime/basicLock.hpp"
  #include "runtime/os.hpp"
  #include "runtime/sharedRuntime.hpp"
  #include "runtime/stubRoutines.hpp"
  
- int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) {
+ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register tmp, Label& slow_case) {
    const int aligned_mask = BytesPerWord -1;
    const int hdr_offset = oopDesc::mark_offset_in_bytes();
    assert(hdr == rax, "hdr must be rax, for the cmpxchg instruction");
-   assert(hdr != obj && hdr != disp_hdr && obj != disp_hdr, "registers must be different");
-   Label done;
+   assert_different_registers(hdr, obj, disp_hdr, tmp);
    int null_check_offset = -1;
  
    verify_oop(obj);
  
    // save object being locked into the BasicObjectLock

@@ -60,43 +59,55 @@
      jcc(Assembler::notZero, slow_case);
    }
  
    // Load object header
    movptr(hdr, Address(obj, hdr_offset));
-   // and mark it as unlocked
-   orptr(hdr, markWord::unlocked_value);
-   // save unlocked object header into the displaced header location on the stack
-   movptr(Address(disp_hdr, 0), hdr);
-   // test if object header is still the same (i.e. unlocked), and if so, store the
-   // displaced header address in the object header - if it is not the same, get the
-   // object header instead
-   MacroAssembler::lock(); // must be immediately before cmpxchg!
-   cmpxchgptr(disp_hdr, Address(obj, hdr_offset));
-   // if the object header was the same, we're done
-   jcc(Assembler::equal, done);
-   // if the object header was not the same, it is now in the hdr register
-   // => test if it is a stack pointer into the same stack (recursive locking), i.e.:
-   //
-   // 1) (hdr & aligned_mask) == 0
-   // 2) rsp <= hdr
-   // 3) hdr <= rsp + page_size
-   //
-   // these 3 tests can be done by evaluating the following expression:
-   //
-   // (hdr - rsp) & (aligned_mask - page_size)
-   //
-   // assuming both the stack pointer and page_size have their least
-   // significant 2 bits cleared and page_size is a power of 2
-   subptr(hdr, rsp);
-   andptr(hdr, aligned_mask - os::vm_page_size());
-   // for recursive locking, the result is zero => save it in the displaced header
-   // location (NULL in the displaced hdr location indicates recursive locking)
-   movptr(Address(disp_hdr, 0), hdr);
-   // otherwise we don't care about the result and handle locking via runtime call
-   jcc(Assembler::notZero, slow_case);
-   // done
-   bind(done);
+ 
+   if (UseFastLocking) {
+ #ifdef _LP64
+     const Register thread = r15_thread;
+ #else
+     const Register thread = disp_hdr;
+     get_thread(thread);
+ #endif
+     fast_lock_impl(obj, hdr, thread, tmp, slow_case, LP64_ONLY(false) NOT_LP64(true));
+   } else {
+     Label done;
+     // mark header as unlocked
+     orptr(hdr, markWord::unlocked_value);
+     // save unlocked object header into the displaced header location on the stack
+     movptr(Address(disp_hdr, 0), hdr);
+     // test if object header is still the same (i.e. unlocked), and if so, store the
+     // displaced header address in the object header - if it is not the same, get the
+     // object header instead
+     MacroAssembler::lock(); // must be immediately before cmpxchg!
+     cmpxchgptr(disp_hdr, Address(obj, hdr_offset));
+     // if the object header was the same, we're done
+     jcc(Assembler::equal, done);
+     // if the object header was not the same, it is now in the hdr register
+     // => test if it is a stack pointer into the same stack (recursive locking), i.e.:
+     //
+     // 1) (hdr & aligned_mask) == 0
+     // 2) rsp <= hdr
+     // 3) hdr <= rsp + page_size
+     //
+     // these 3 tests can be done by evaluating the following expression:
+     //
+     // (hdr - rsp) & (aligned_mask - page_size)
+     //
+     // assuming both the stack pointer and page_size have their least
+     // significant 2 bits cleared and page_size is a power of 2
+     subptr(hdr, rsp);
+     andptr(hdr, aligned_mask - os::vm_page_size());
+     // for recursive locking, the result is zero => save it in the displaced header
+     // location (NULL in the displaced hdr location indicates recursive locking)
+     movptr(Address(disp_hdr, 0), hdr);
+     // otherwise we don't care about the result and handle locking via runtime call
+     jcc(Assembler::notZero, slow_case);
+     // done
+     bind(done);
+   }
  
    inc_held_monitor_count();
  
    return null_check_offset;
  }

@@ -106,31 +117,39 @@
    const int hdr_offset = oopDesc::mark_offset_in_bytes();
    assert(disp_hdr == rax, "disp_hdr must be rax, for the cmpxchg instruction");
    assert(hdr != obj && hdr != disp_hdr && obj != disp_hdr, "registers must be different");
    Label done;
  
-   // load displaced header
-   movptr(hdr, Address(disp_hdr, 0));
-   // if the loaded hdr is NULL we had recursive locking
-   testptr(hdr, hdr);
-   // if we had recursive locking, we are done
-   jcc(Assembler::zero, done);
+   if (!UseFastLocking) {
+     // load displaced header
+     movptr(hdr, Address(disp_hdr, 0));
+     // if the loaded hdr is NULL we had recursive locking
+     testptr(hdr, hdr);
+     // if we had recursive locking, we are done
+     jcc(Assembler::zero, done);
+   }
+ 
    // load object
    movptr(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes()));
- 
    verify_oop(obj);
-   // test if object header is pointing to the displaced header, and if so, restore
-   // the displaced header in the object - if the object header is not pointing to
-   // the displaced header, get the object header instead
-   MacroAssembler::lock(); // must be immediately before cmpxchg!
-   cmpxchgptr(hdr, Address(obj, hdr_offset));
-   // if the object header was not pointing to the displaced header,
-   // we do unlocking via runtime call
-   jcc(Assembler::notEqual, slow_case);
-   // done
-   bind(done);
  
+   if (UseFastLocking) {
+     movptr(disp_hdr, Address(obj, hdr_offset));
+     andptr(disp_hdr, ~(int32_t)markWord::lock_mask_in_place);
+     fast_unlock_impl(obj, disp_hdr, hdr, slow_case);
+   } else {
+     // test if object header is pointing to the displaced header, and if so, restore
+     // the displaced header in the object - if the object header is not pointing to
+     // the displaced header, get the object header instead
+     MacroAssembler::lock(); // must be immediately before cmpxchg!
+     cmpxchgptr(hdr, Address(obj, hdr_offset));
+     // if the object header was not pointing to the displaced header,
+     // we do unlocking via runtime call
+     jcc(Assembler::notEqual, slow_case);
+     // done
+   }
+   bind(done);
    dec_held_monitor_count();
  }
  
  
  // Defines obj, preserves var_size_in_bytes

@@ -142,32 +161,20 @@
    }
  }
  
  
  void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register t1, Register t2) {
-   assert_different_registers(obj, klass, len);
-   movptr(Address(obj, oopDesc::mark_offset_in_bytes()), checked_cast<int32_t>(markWord::prototype().value()));
- #ifdef _LP64
-   if (UseCompressedClassPointers) { // Take care not to kill klass
-     movptr(t1, klass);
-     encode_klass_not_null(t1, rscratch1);
-     movl(Address(obj, oopDesc::klass_offset_in_bytes()), t1);
-   } else
+   assert_different_registers(obj, klass, len, t1, t2);
+   movptr(t1, Address(klass, Klass::prototype_header_offset()));
+   movptr(Address(obj, oopDesc::mark_offset_in_bytes()), t1);
+ #ifndef _LP64
+   movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass);
  #endif
-   {
-     movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass);
-   }
  
    if (len->is_valid()) {
      movl(Address(obj, arrayOopDesc::length_offset_in_bytes()), len);
    }
- #ifdef _LP64
-   else if (UseCompressedClassPointers) {
-     xorptr(t1, t1);
-     store_klass_gap(obj, t1);
-   }
- #endif
  }
  
  
  // preserves obj, destroys len_in_bytes
  void C1_MacroAssembler::initialize_body(Register obj, Register len_in_bytes, int hdr_size_in_bytes, Register t1) {

@@ -240,11 +247,11 @@
    }
  
    verify_oop(obj);
  }
  
- void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, int header_size, Address::ScaleFactor f, Register klass, Label& slow_case) {
+ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, int base_offset_in_bytes, Address::ScaleFactor f, Register klass, Label& slow_case) {
    assert(obj == rax, "obj must be in rax, for cmpxchg");
    assert_different_registers(obj, len, t1, t2, klass);
  
    // determine alignment mask
    assert(!(BytesPerWord & 1), "must be a multiple of 2 for masking code to work");

@@ -253,21 +260,21 @@
    cmpptr(len, checked_cast<int32_t>(max_array_allocation_length));
    jcc(Assembler::above, slow_case);
  
    const Register arr_size = t2; // okay to be the same
    // align object end
-   movptr(arr_size, header_size * BytesPerWord + MinObjAlignmentInBytesMask);
+   movptr(arr_size, (int32_t)base_offset_in_bytes + MinObjAlignmentInBytesMask);
    lea(arr_size, Address(arr_size, len, f));
    andptr(arr_size, ~MinObjAlignmentInBytesMask);
  
    try_allocate(obj, arr_size, 0, t1, t2, slow_case);
  
    initialize_header(obj, klass, len, t1, t2);
  
    // clear rest of allocated space
    const Register len_zero = len;
-   initialize_body(obj, arr_size, header_size * BytesPerWord, len_zero);
+   initialize_body(obj, arr_size, base_offset_in_bytes, len_zero);
  
    if (CURRENT_ENV->dtrace_alloc_probes()) {
      assert(obj == rax, "must be");
      call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)));
    }

@@ -297,11 +304,11 @@
    const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9);
    assert(UseCompressedClassPointers || offset() - start_offset == ic_cmp_size, "check alignment in emit_method_entry");
  }
  
  
- void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) {
+ void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes, int max_monitors) {
    assert(bang_size_in_bytes >= frame_size_in_bytes, "stack bang size incorrect");
    // Make sure there is enough stack space for this method's activation.
    // Note that we do this before doing an enter(). This matches the
    // ordering of C2's stack overflow check / rsp decrement and allows
    // the SharedRuntime stack overflow handling to be consistent

@@ -318,10 +325,23 @@
      empty_FPU_stack();
    }
  #endif // !_LP64 && COMPILER2
    decrement(rsp, frame_size_in_bytes); // does not emit code for frame_size == 0
  
+ #ifdef _LP64
+   if (UseFastLocking && max_monitors > 0) {
+     Label ok;
+     movptr(rax, Address(r15_thread, JavaThread::lock_stack_current_offset()));
+     addptr(rax, max_monitors * wordSize);
+     cmpptr(rax, Address(r15_thread, JavaThread::lock_stack_limit_offset()));
+     jcc(Assembler::less, ok);
+     assert(StubRoutines::x86::check_lock_stack() != NULL, "need runtime call stub");
+     call(RuntimeAddress(StubRoutines::x86::check_lock_stack()));
+     bind(ok);
+   }
+ #endif
+ 
    BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
    // C1 code is not hot enough to micro optimize the nmethod entry barrier with an out-of-line stub
    bs->nmethod_entry_barrier(this, NULL /* slow_path */, NULL /* continuation */);
  }
  
< prev index next >