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. |
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 %} |