< prev index next >

src/hotspot/cpu/aarch64/aarch64.ad

Print this page
@@ -1782,10 +1782,22 @@
    if (C->output()->need_stack_bang(bangsize))
      __ generate_stack_overflow_check(bangsize);
  
    __ build_frame(framesize);
  
+   int max_monitors = C->method() != NULL ? C->max_monitors() : 0;
+   if (UseFastLocking && max_monitors > 0) {
+     C2CheckLockStackStub* stub = new (C->comp_arena()) C2CheckLockStackStub();
+     C->output()->add_stub(stub);
+     __ ldr(r9, Address(rthread, JavaThread::lock_stack_current_offset()));
+     __ ldr(r10, Address(rthread, JavaThread::lock_stack_limit_offset()));
+     __ add(r9, r9, max_monitors * oopSize);
+     __ cmp(r9, r10);
+     __ br(Assembler::GE, stub->entry());
+     __ bind(stub->continuation());
+   }
+ 
    if (C->stub_function() == NULL) {
      BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
      if (BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) {
        // Dummy labels for just measuring the code size
        Label dummy_slow_path;

@@ -3768,11 +3780,11 @@
      Register box = as_Register($box$$reg);
      Register disp_hdr = as_Register($tmp$$reg);
      Register tmp = as_Register($tmp2$$reg);
      Label cont;
      Label object_has_monitor;
-     Label no_count;
+     Label count, no_count;
  
      assert_different_registers(oop, box, tmp, disp_hdr);
  
      // Load markWord from object into displaced_header.
      __ ldr(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes()));

@@ -3786,41 +3798,50 @@
  
      // Check for existing monitor
      __ tbnz(disp_hdr, exact_log2(markWord::monitor_value), object_has_monitor);
  
      if (!UseHeavyMonitors) {
-       // Set tmp to be (markWord of object | UNLOCK_VALUE).
-       __ orr(tmp, disp_hdr, markWord::unlocked_value);
- 
-       // Initialize the box. (Must happen before we update the object mark!)
-       __ str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
- 
-       // Compare object markWord with an unlocked value (tmp) and if
-       // equal exchange the stack address of our box with object markWord.
-       // On failure disp_hdr contains the possibly locked markWord.
-       __ cmpxchg(oop, tmp, box, Assembler::xword, /*acquire*/ true,
-                  /*release*/ true, /*weak*/ false, disp_hdr);
-       __ br(Assembler::EQ, cont);
- 
-       assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
- 
-       // If the compare-and-exchange succeeded, then we found an unlocked
-       // object, will have now locked it will continue at label cont
+       if (UseFastLocking) {
+         __ fast_lock(oop, disp_hdr, tmp, rscratch1, no_count, false);
  
-       // Check if the owner is self by comparing the value in the
-       // markWord of object (disp_hdr) with the stack pointer.
-       __ mov(rscratch1, sp);
-       __ sub(disp_hdr, disp_hdr, rscratch1);
-       __ mov(tmp, (address) (~(os::vm_page_size()-1) | markWord::lock_mask_in_place));
-       // If condition is true we are cont and hence we can store 0 as the
-       // displaced header in the box, which indicates that it is a recursive lock.
-       __ ands(tmp/*==0?*/, disp_hdr, tmp);   // Sets flags for result
-       __ str(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes()));
+         // Indicate success at cont.
+         __ cmp(oop, oop);
+         __ b(count);
+       } else {
+         // Set tmp to be (markWord of object | UNLOCK_VALUE).
+         __ orr(tmp, disp_hdr, markWord::unlocked_value);
+ 
+         // Initialize the box. (Must happen before we update the object mark!)
+         __ str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
+ 
+         // Compare object markWord with an unlocked value (tmp) and if
+         // equal exchange the stack address of our box with object markWord.
+         // On failure disp_hdr contains the possibly locked markWord.
+         __ cmpxchg(oop, tmp, box, Assembler::xword, /*acquire*/ true,
+                    /*release*/ true, /*weak*/ false, disp_hdr);
+         __ br(Assembler::EQ, cont);
+ 
+         assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
+ 
+         // If the compare-and-exchange succeeded, then we found an unlocked
+         // object, will have now locked it will continue at label cont
+ 
+         // Check if the owner is self by comparing the value in the
+         // markWord of object (disp_hdr) with the stack pointer.
+         __ mov(rscratch1, sp);
+         __ sub(disp_hdr, disp_hdr, rscratch1);
+         __ mov(tmp, (address) (~(os::vm_page_size()-1) | markWord::lock_mask_in_place));
+         // If condition is true we are cont and hence we can store 0 as the
+         // displaced header in the box, which indicates that it is a recursive lock.
+         __ ands(tmp/*==0?*/, disp_hdr, tmp);   // Sets flags for result
+         __ str(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes()));
+         __ b(cont);
+       }
      } else {
        __ tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0.
+       __ b(cont);
      }
-     __ b(cont);
  
      // Handle existing monitor.
      __ bind(object_has_monitor);
  
      // The object's monitor m is unlocked iff m->owner == NULL,

@@ -3829,17 +3850,18 @@
      // Try to CAS m->owner from NULL to current thread.
      __ add(tmp, disp_hdr, (ObjectMonitor::owner_offset_in_bytes()-markWord::monitor_value));
      __ cmpxchg(tmp, zr, rthread, Assembler::xword, /*acquire*/ true,
                 /*release*/ true, /*weak*/ false, rscratch1); // Sets flags for result
  
-     // Store a non-null value into the box to avoid looking like a re-entrant
-     // lock. The fast-path monitor unlock code checks for
-     // markWord::monitor_value so use markWord::unused_mark which has the
-     // relevant bit set, and also matches ObjectSynchronizer::enter.
-     __ mov(tmp, (address)markWord::unused_mark().value());
-     __ str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
- 
+     if (!UseFastLocking) {
+       // Store a non-null value into the box to avoid looking like a re-entrant
+       // lock. The fast-path monitor unlock code checks for
+       // markWord::monitor_value so use markWord::unused_mark which has the
+       // relevant bit set, and also matches ObjectSynchronizer::enter.
+       __ mov(tmp, (address)markWord::unused_mark().value());
+       __ str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
+     }
      __ br(Assembler::EQ, cont); // CAS success means locking succeeded
  
      __ cmp(rscratch1, rthread);
      __ br(Assembler::NE, cont); // Check for recursive locking
  

@@ -3850,10 +3872,11 @@
      __ bind(cont);
      // flag == EQ indicates success
      // flag == NE indicates failure
      __ br(Assembler::NE, no_count);
  
+     __ bind(count);
      __ increment(Address(rthread, JavaThread::held_monitor_count_offset()));
  
      __ bind(no_count);
    %}
  

@@ -3863,15 +3886,15 @@
      Register box = as_Register($box$$reg);
      Register disp_hdr = as_Register($tmp$$reg);
      Register tmp = as_Register($tmp2$$reg);
      Label cont;
      Label object_has_monitor;
-     Label no_count;
+     Label count, no_count;
  
      assert_different_registers(oop, box, tmp, disp_hdr);
  
-     if (!UseHeavyMonitors) {
+     if (!UseHeavyMonitors && !UseFastLocking) {
        // Find the lock address and load the displaced header from the stack.
        __ ldr(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes()));
  
        // If the displaced header is 0, we have a recursive unlock.
        __ cmp(disp_hdr, zr);

@@ -3881,27 +3904,50 @@
      // Handle existing monitor.
      __ ldr(tmp, Address(oop, oopDesc::mark_offset_in_bytes()));
      __ tbnz(tmp, exact_log2(markWord::monitor_value), object_has_monitor);
  
      if (!UseHeavyMonitors) {
-       // Check if it is still a light weight lock, this is is true if we
-       // see the stack address of the basicLock in the markWord of the
-       // object.
+       if (UseFastLocking) {
+         __ fast_unlock(oop, tmp, box, disp_hdr, no_count);
  
-       __ cmpxchg(oop, box, disp_hdr, Assembler::xword, /*acquire*/ false,
-                  /*release*/ true, /*weak*/ false, tmp);
+         // Indicate success at cont.
+         __ cmp(oop, oop);
+         __ b(count);
+       } else {
+         // Check if it is still a light weight lock, this is is true if we
+         // see the stack address of the basicLock in the markWord of the
+         // object.
+ 
+         __ cmpxchg(oop, box, disp_hdr, Assembler::xword, /*acquire*/ false,
+                    /*release*/ true, /*weak*/ false, tmp);
+         __ b(cont);
+       }
      } else {
        __ tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0.
+       __ b(cont);
      }
-     __ b(cont);
  
      assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
  
      // Handle existing monitor.
      __ bind(object_has_monitor);
      STATIC_ASSERT(markWord::monitor_value <= INT_MAX);
      __ add(tmp, tmp, -(int)markWord::monitor_value); // monitor
+ 
+     if (UseFastLocking) {
+       // If the owner is anonymous, we need to fix it -- in an outline stub.
+       Register tmp2 = disp_hdr;
+       __ ldr(tmp2, Address(tmp, ObjectMonitor::owner_offset_in_bytes()));
+       // We cannot use tbnz here, the target might be too far away and cannot
+       // be encoded.
+       __ tst(tmp2, (uint64_t)(intptr_t) ANONYMOUS_OWNER);
+       C2HandleAnonOMOwnerStub* stub = new (Compile::current()->comp_arena()) C2HandleAnonOMOwnerStub(tmp, tmp2);
+       Compile::current()->output()->add_stub(stub);
+       __ br(Assembler::NE, stub->entry());
+       __ bind(stub->continuation());
+     }
+ 
      __ ldr(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes()));
  
      Label notRecursive;
      __ cbz(disp_hdr, notRecursive);
  

@@ -3924,10 +3970,11 @@
      __ bind(cont);
      // flag == EQ indicates success
      // flag == NE indicates failure
      __ br(Assembler::NE, no_count);
  
+     __ bind(count);
      __ decrement(Address(rthread, JavaThread::held_monitor_count_offset()));
  
      __ bind(no_count);
    %}
  

@@ -7189,20 +7236,46 @@
  
  // Load Narrow Klass Pointer
  instruct loadNKlass(iRegNNoSp dst, memory4 mem)
  %{
    match(Set dst (LoadNKlass mem));
-   predicate(!needs_acquiring_load(n));
+   predicate(!needs_acquiring_load(n) && !UseCompactObjectHeaders);
  
    ins_cost(4 * INSN_COST);
    format %{ "ldrw  $dst, $mem\t# compressed class ptr" %}
  
    ins_encode(aarch64_enc_ldrw(dst, mem));
  
    ins_pipe(iload_reg_mem);
  %}
  
+ instruct loadNKlassLilliput(iRegNNoSp dst, memory4 mem, rFlagsReg cr)
+ %{
+   match(Set dst (LoadNKlass mem));
+   effect(TEMP_DEF dst, KILL cr);
+   predicate(!needs_acquiring_load(n) && UseCompactObjectHeaders);
+ 
+   ins_cost(4 * INSN_COST);
+   format %{ "ldrw  $dst, $mem\t# compressed class ptr" %}
+   ins_encode %{
+     assert($mem$$disp == oopDesc::klass_offset_in_bytes(), "expect correct offset");
+     assert($mem$$index$$Register == noreg, "expect no index");
+     Register dst = $dst$$Register;
+     Register obj = $mem$$base$$Register;
+     C2LoadNKlassStub* stub = new (Compile::current()->comp_arena()) C2LoadNKlassStub(dst);
+     Compile::current()->output()->add_stub(stub);
+     __ ldr(dst, Address(obj, oopDesc::mark_offset_in_bytes()));
+     // NOTE: We can't use tbnz here, because the target is sometimes too far away
+     // and cannot be encoded.
+     __ tst(dst, markWord::monitor_value);
+     __ br(Assembler::NE, stub->entry());
+     __ bind(stub->continuation());
+     __ lsr(dst, dst, markWord::klass_shift);
+   %}
+   ins_pipe(pipe_slow);
+ %}
+ 
  // Load Float
  instruct loadF(vRegF dst, memory4 mem)
  %{
    match(Set dst (LoadF mem));
    predicate(!needs_acquiring_load(n));
< prev index next >