src/hotspot/cpu/aarch64/aarch64.ad
changeset 53368 91f56aee3928
parent 53073 11033c4ada54
child 53472 cb43e14dc68b
equal deleted inserted replaced
53367:c3fa35381763 53368:91f56aee3928
     1 //
     1 //
     2 // Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
     2 // Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
     3 // Copyright (c) 2014, 2018, Red Hat, Inc. All rights reserved.
     3 // Copyright (c) 2014, 2019, Red Hat, Inc. All rights reserved.
     4 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5 //
     5 //
     6 // This code is free software; you can redistribute it and/or modify it
     6 // This code is free software; you can redistribute it and/or modify it
     7 // under the terms of the GNU General Public License version 2 only, as
     7 // under the terms of the GNU General Public License version 2 only, as
     8 // published by the Free Software Foundation.
     8 // published by the Free Software Foundation.
  3416     if (UseBiasedLocking && !UseOptoBiasInlining) {
  3416     if (UseBiasedLocking && !UseOptoBiasInlining) {
  3417       __ biased_locking_enter(box, oop, disp_hdr, tmp, true, cont);
  3417       __ biased_locking_enter(box, oop, disp_hdr, tmp, true, cont);
  3418     }
  3418     }
  3419 
  3419 
  3420     // Handle existing monitor
  3420     // Handle existing monitor
  3421     // we can use AArch64's bit test and branch here but
  3421     __ tbnz(disp_hdr, exact_log2(markOopDesc::monitor_value), object_has_monitor);
  3422     // markoopDesc does not define a bit index just the bit value
       
  3423     // so assert in case the bit pos changes
       
  3424 #   define __monitor_value_log2 1
       
  3425     assert(markOopDesc::monitor_value == (1 << __monitor_value_log2), "incorrect bit position");
       
  3426     __ tbnz(disp_hdr, __monitor_value_log2, object_has_monitor);
       
  3427 #   undef __monitor_value_log2
       
  3428 
  3422 
  3429     // Set displaced_header to be (markOop of object | UNLOCK_VALUE).
  3423     // Set displaced_header to be (markOop of object | UNLOCK_VALUE).
  3430     __ orr(disp_hdr, disp_hdr, markOopDesc::unlocked_value);
  3424     __ orr(disp_hdr, disp_hdr, markOopDesc::unlocked_value);
  3431 
  3425 
  3432     // Load Compare Value application register.
  3426     // Load Compare Value application register.
  3453       __ stlxr(tmp, box, oop);
  3447       __ stlxr(tmp, box, oop);
  3454       __ cbzw(tmp, cont);
  3448       __ cbzw(tmp, cont);
  3455       __ b(retry_load);
  3449       __ b(retry_load);
  3456     }
  3450     }
  3457 
  3451 
  3458     // Formerly:
       
  3459     // __ cmpxchgptr(/*oldv=*/disp_hdr,
       
  3460     //               /*newv=*/box,
       
  3461     //               /*addr=*/oop,
       
  3462     //               /*tmp=*/tmp,
       
  3463     //               cont,
       
  3464     //               /*fail*/NULL);
       
  3465 
       
  3466     assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
  3452     assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
  3467 
  3453 
  3468     // If the compare-and-exchange succeeded, then we found an unlocked
  3454     // If the compare-and-exchange succeeded, then we found an unlocked
  3469     // object, will have now locked it will continue at label cont
  3455     // object, will have now locked it will continue at label cont
  3470 
  3456 
  3509       __ stlxr(rscratch1, rthread, tmp);
  3495       __ stlxr(rscratch1, rthread, tmp);
  3510       __ cbnzw(rscratch1, retry_load);
  3496       __ cbnzw(rscratch1, retry_load);
  3511       __ bind(fail);
  3497       __ bind(fail);
  3512     }
  3498     }
  3513 
  3499 
  3514     // Label next;
  3500     // Store a non-null value into the box to avoid looking like a re-entrant
  3515     // __ cmpxchgptr(/*oldv=*/disp_hdr,
  3501     // lock. The fast-path monitor unlock code checks for
  3516     //               /*newv=*/rthread,
  3502     // markOopDesc::monitor_value so use markOopDesc::unused_mark which has the
  3517     //               /*addr=*/tmp,
  3503     // relevant bit set, and also matches ObjectSynchronizer::slow_enter.
  3518     //               /*tmp=*/rscratch1,
  3504     __ mov(tmp, (address)markOopDesc::unused_mark());
  3519     //               /*succeed*/next,
  3505     __ str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
  3520     //               /*fail*/NULL);
       
  3521     // __ bind(next);
       
  3522 
       
  3523     // store a non-null value into the box.
       
  3524     __ str(box, Address(box, BasicLock::displaced_header_offset_in_bytes()));
       
  3525 
       
  3526     // PPC port checks the following invariants
       
  3527     // #ifdef ASSERT
       
  3528     // bne(flag, cont);
       
  3529     // We have acquired the monitor, check some invariants.
       
  3530     // addw(/*monitor=*/tmp, tmp, -ObjectMonitor::owner_offset_in_bytes());
       
  3531     // Invariant 1: _recursions should be 0.
       
  3532     // assert(ObjectMonitor::recursions_size_in_bytes() == 8, "unexpected size");
       
  3533     // assert_mem8_is_zero(ObjectMonitor::recursions_offset_in_bytes(), tmp,
       
  3534     //                        "monitor->_recursions should be 0", -1);
       
  3535     // Invariant 2: OwnerIsThread shouldn't be 0.
       
  3536     // assert(ObjectMonitor::OwnerIsThread_size_in_bytes() == 4, "unexpected size");
       
  3537     //assert_mem4_isnot_zero(ObjectMonitor::OwnerIsThread_offset_in_bytes(), tmp,
       
  3538     //                           "monitor->OwnerIsThread shouldn't be 0", -1);
       
  3539     // #endif
       
  3540 
  3506 
  3541     __ bind(cont);
  3507     __ bind(cont);
  3542     // flag == EQ indicates success
  3508     // flag == EQ indicates success
  3543     // flag == NE indicates failure
  3509     // flag == NE indicates failure
  3544 
  3510   %}
  3545   %}
  3511 
  3546 
       
  3547   // TODO
       
  3548   // reimplement this with custom cmpxchgptr code
       
  3549   // which avoids some of the unnecessary branching
       
  3550   enc_class aarch64_enc_fast_unlock(iRegP object, iRegP box, iRegP tmp, iRegP tmp2) %{
  3512   enc_class aarch64_enc_fast_unlock(iRegP object, iRegP box, iRegP tmp, iRegP tmp2) %{
  3551     MacroAssembler _masm(&cbuf);
  3513     MacroAssembler _masm(&cbuf);
  3552     Register oop = as_Register($object$$reg);
  3514     Register oop = as_Register($object$$reg);
  3553     Register box = as_Register($box$$reg);
  3515     Register box = as_Register($box$$reg);
  3554     Register disp_hdr = as_Register($tmp$$reg);
  3516     Register disp_hdr = as_Register($tmp$$reg);
  3555     Register tmp = as_Register($tmp2$$reg);
  3517     Register tmp = as_Register($tmp2$$reg);
  3556     Label cont;
  3518     Label cont;
  3557     Label object_has_monitor;
  3519     Label object_has_monitor;
  3558     Label cas_failed;
       
  3559 
  3520 
  3560     assert_different_registers(oop, box, tmp, disp_hdr);
  3521     assert_different_registers(oop, box, tmp, disp_hdr);
  3561 
  3522 
  3562     if (UseBiasedLocking && !UseOptoBiasInlining) {
  3523     if (UseBiasedLocking && !UseOptoBiasInlining) {
  3563       __ biased_locking_exit(oop, tmp, cont);
  3524       __ biased_locking_exit(oop, tmp, cont);
  3568 
  3529 
  3569     // If the displaced header is 0, we have a recursive unlock.
  3530     // If the displaced header is 0, we have a recursive unlock.
  3570     __ cmp(disp_hdr, zr);
  3531     __ cmp(disp_hdr, zr);
  3571     __ br(Assembler::EQ, cont);
  3532     __ br(Assembler::EQ, cont);
  3572 
  3533 
  3573 
       
  3574     // Handle existing monitor.
  3534     // Handle existing monitor.
  3575     __ ldr(tmp, Address(oop, oopDesc::mark_offset_in_bytes()));
  3535     __ ldr(tmp, Address(oop, oopDesc::mark_offset_in_bytes()));
  3576     __ tbnz(disp_hdr, exact_log2(markOopDesc::monitor_value), object_has_monitor);
  3536     __ tbnz(disp_hdr, exact_log2(markOopDesc::monitor_value), object_has_monitor);
  3577 
  3537 
  3578     // Check if it is still a light weight lock, this is is true if we
  3538     // Check if it is still a light weight lock, this is is true if we
  3579     // see the stack address of the basicLock in the markOop of the
  3539     // see the stack address of the basicLock in the markOop of the
  3580     // object.
  3540     // object.
  3581 
  3541 
  3582       if (UseLSE) {
  3542     if (UseLSE) {
  3583         __ mov(tmp, box);
  3543       __ mov(tmp, box);
  3584         __ casl(Assembler::xword, tmp, disp_hdr, oop);
  3544       __ casl(Assembler::xword, tmp, disp_hdr, oop);
  3585         __ cmp(tmp, box);
  3545       __ cmp(tmp, box);
  3586       } else {
  3546       __ b(cont);
  3587         Label retry_load;
  3547     } else {
  3588         if ((VM_Version::features() & VM_Version::CPU_STXR_PREFETCH))
  3548       Label retry_load;
  3589           __ prfm(Address(oop), PSTL1STRM);
  3549       if ((VM_Version::features() & VM_Version::CPU_STXR_PREFETCH))
  3590         __ bind(retry_load);
  3550         __ prfm(Address(oop), PSTL1STRM);
  3591         __ ldxr(tmp, oop);
  3551       __ bind(retry_load);
  3592         __ cmp(box, tmp);
  3552       __ ldxr(tmp, oop);
  3593         __ br(Assembler::NE, cas_failed);
  3553       __ cmp(box, tmp);
  3594         // use stlxr to ensure update is immediately visible
  3554       __ br(Assembler::NE, cont);
  3595         __ stlxr(tmp, disp_hdr, oop);
  3555       // use stlxr to ensure update is immediately visible
  3596         __ cbzw(tmp, cont);
  3556       __ stlxr(tmp, disp_hdr, oop);
  3597         __ b(retry_load);
  3557       __ cbzw(tmp, cont);
  3598       }
  3558       __ b(retry_load);
  3599 
  3559     }
  3600     // __ cmpxchgptr(/*compare_value=*/box,
  3560 
  3601     //               /*exchange_value=*/disp_hdr,
       
  3602     //               /*where=*/oop,
       
  3603     //               /*result=*/tmp,
       
  3604     //               cont,
       
  3605     //               /*cas_failed*/NULL);
       
  3606     assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
  3561     assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
  3607 
  3562 
  3608     __ bind(cas_failed);
       
  3609 
       
  3610     // Handle existing monitor.
  3563     // Handle existing monitor.
  3611     __ b(cont);
       
  3612 
       
  3613     __ bind(object_has_monitor);
  3564     __ bind(object_has_monitor);
  3614     __ add(tmp, tmp, -markOopDesc::monitor_value); // monitor
  3565     __ add(tmp, tmp, -markOopDesc::monitor_value); // monitor
  3615     __ ldr(rscratch1, Address(tmp, ObjectMonitor::owner_offset_in_bytes()));
  3566     __ ldr(rscratch1, Address(tmp, ObjectMonitor::owner_offset_in_bytes()));
  3616     __ ldr(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes()));
  3567     __ ldr(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes()));
  3617     __ eor(rscratch1, rscratch1, rthread); // Will be 0 if we are the owner.
  3568     __ eor(rscratch1, rscratch1, rthread); // Will be 0 if we are the owner.
  3624     __ orr(rscratch1, rscratch1, disp_hdr); // Will be 0 if both are 0.
  3575     __ orr(rscratch1, rscratch1, disp_hdr); // Will be 0 if both are 0.
  3625     __ cmp(rscratch1, zr);
  3576     __ cmp(rscratch1, zr);
  3626     __ cbnz(rscratch1, cont);
  3577     __ cbnz(rscratch1, cont);
  3627     // need a release store here
  3578     // need a release store here
  3628     __ lea(tmp, Address(tmp, ObjectMonitor::owner_offset_in_bytes()));
  3579     __ lea(tmp, Address(tmp, ObjectMonitor::owner_offset_in_bytes()));
  3629     __ stlr(rscratch1, tmp); // rscratch1 is zero
  3580     __ stlr(zr, tmp); // set unowned
  3630 
  3581 
  3631     __ bind(cont);
  3582     __ bind(cont);
  3632     // flag == EQ indicates success
  3583     // flag == EQ indicates success
  3633     // flag == NE indicates failure
  3584     // flag == NE indicates failure
  3634   %}
  3585   %}