comparison src/cpu/x86/vm/x86_64.ad @ 14494:5292439ef895

8033805: Move Fast_Lock/Fast_Unlock code from .ad files to macroassembler Summary: Consolidated C2 x86 locking code in one place in macroAssembler_x86.cpp. Reviewed-by: roland
author kvn
date Mon, 24 Feb 2014 15:12:26 -0800
parents 45467c53f178
children cd5d10655495
comparison
equal deleted inserted replaced
14472:80b39937b791 14494:5292439ef895
2597 __ movdbl(Address(rsp, 0), $src$$XMMRegister); 2597 __ movdbl(Address(rsp, 0), $src$$XMMRegister);
2598 __ fld_d(Address(rsp, 0)); 2598 __ fld_d(Address(rsp, 0));
2599 %} 2599 %}
2600 2600
2601 2601
2602 // obj: object to lock
2603 // box: box address (header location) -- killed
2604 // tmp: rax -- killed
2605 // scr: rbx -- killed
2606 //
2607 // What follows is a direct transliteration of fast_lock() and fast_unlock()
2608 // from i486.ad. See that file for comments.
2609 // TODO: where possible switch from movq (r, 0) to movl(r,0) and
2610 // use the shorter encoding. (Movl clears the high-order 32-bits).
2611
2612
2613 enc_class Fast_Lock(rRegP obj, rRegP box, rax_RegI tmp, rRegP scr)
2614 %{
2615 Register objReg = as_Register((int)$obj$$reg);
2616 Register boxReg = as_Register((int)$box$$reg);
2617 Register tmpReg = as_Register($tmp$$reg);
2618 Register scrReg = as_Register($scr$$reg);
2619 MacroAssembler masm(&cbuf);
2620
2621 // Verify uniqueness of register assignments -- necessary but not sufficient
2622 assert (objReg != boxReg && objReg != tmpReg &&
2623 objReg != scrReg && tmpReg != scrReg, "invariant") ;
2624
2625 if (_counters != NULL) {
2626 masm.atomic_incl(ExternalAddress((address) _counters->total_entry_count_addr()));
2627 }
2628 if (EmitSync & 1) {
2629 // Without cast to int32_t a movptr will destroy r10 which is typically obj
2630 masm.movptr (Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ;
2631 masm.cmpptr(rsp, (int32_t)NULL_WORD) ;
2632 } else
2633 if (EmitSync & 2) {
2634 Label DONE_LABEL;
2635 if (UseBiasedLocking) {
2636 // Note: tmpReg maps to the swap_reg argument and scrReg to the tmp_reg argument.
2637 masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, false, DONE_LABEL, NULL, _counters);
2638 }
2639 // QQQ was movl...
2640 masm.movptr(tmpReg, 0x1);
2641 masm.orptr(tmpReg, Address(objReg, 0));
2642 masm.movptr(Address(boxReg, 0), tmpReg);
2643 if (os::is_MP()) {
2644 masm.lock();
2645 }
2646 masm.cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg
2647 masm.jcc(Assembler::equal, DONE_LABEL);
2648
2649 // Recursive locking
2650 masm.subptr(tmpReg, rsp);
2651 masm.andptr(tmpReg, 7 - os::vm_page_size());
2652 masm.movptr(Address(boxReg, 0), tmpReg);
2653
2654 masm.bind(DONE_LABEL);
2655 masm.nop(); // avoid branch to branch
2656 } else {
2657 Label DONE_LABEL, IsInflated, Egress;
2658
2659 masm.movptr(tmpReg, Address(objReg, 0)) ;
2660 masm.testl (tmpReg, 0x02) ; // inflated vs stack-locked|neutral|biased
2661 masm.jcc (Assembler::notZero, IsInflated) ;
2662
2663 // it's stack-locked, biased or neutral
2664 // TODO: optimize markword triage order to reduce the number of
2665 // conditional branches in the most common cases.
2666 // Beware -- there's a subtle invariant that fetch of the markword
2667 // at [FETCH], below, will never observe a biased encoding (*101b).
2668 // If this invariant is not held we'll suffer exclusion (safety) failure.
2669
2670 if (UseBiasedLocking && !UseOptoBiasInlining) {
2671 masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, true, DONE_LABEL, NULL, _counters);
2672 masm.movptr(tmpReg, Address(objReg, 0)) ; // [FETCH]
2673 }
2674
2675 // was q will it destroy high?
2676 masm.orl (tmpReg, 1) ;
2677 masm.movptr(Address(boxReg, 0), tmpReg) ;
2678 if (os::is_MP()) { masm.lock(); }
2679 masm.cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg
2680 if (_counters != NULL) {
2681 masm.cond_inc32(Assembler::equal,
2682 ExternalAddress((address) _counters->fast_path_entry_count_addr()));
2683 }
2684 masm.jcc (Assembler::equal, DONE_LABEL);
2685
2686 // Recursive locking
2687 masm.subptr(tmpReg, rsp);
2688 masm.andptr(tmpReg, 7 - os::vm_page_size());
2689 masm.movptr(Address(boxReg, 0), tmpReg);
2690 if (_counters != NULL) {
2691 masm.cond_inc32(Assembler::equal,
2692 ExternalAddress((address) _counters->fast_path_entry_count_addr()));
2693 }
2694 masm.jmp (DONE_LABEL) ;
2695
2696 masm.bind (IsInflated) ;
2697 // It's inflated
2698
2699 // TODO: someday avoid the ST-before-CAS penalty by
2700 // relocating (deferring) the following ST.
2701 // We should also think about trying a CAS without having
2702 // fetched _owner. If the CAS is successful we may
2703 // avoid an RTO->RTS upgrade on the $line.
2704 // Without cast to int32_t a movptr will destroy r10 which is typically obj
2705 masm.movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ;
2706
2707 masm.mov (boxReg, tmpReg) ;
2708 masm.movptr (tmpReg, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
2709 masm.testptr(tmpReg, tmpReg) ;
2710 masm.jcc (Assembler::notZero, DONE_LABEL) ;
2711
2712 // It's inflated and appears unlocked
2713 if (os::is_MP()) { masm.lock(); }
2714 masm.cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
2715 // Intentional fall-through into DONE_LABEL ...
2716
2717 masm.bind (DONE_LABEL) ;
2718 masm.nop () ; // avoid jmp to jmp
2719 }
2720 %}
2721
2722 // obj: object to unlock
2723 // box: box address (displaced header location), killed
2724 // RBX: killed tmp; cannot be obj nor box
2725 enc_class Fast_Unlock(rRegP obj, rax_RegP box, rRegP tmp)
2726 %{
2727
2728 Register objReg = as_Register($obj$$reg);
2729 Register boxReg = as_Register($box$$reg);
2730 Register tmpReg = as_Register($tmp$$reg);
2731 MacroAssembler masm(&cbuf);
2732
2733 if (EmitSync & 4) {
2734 masm.cmpptr(rsp, 0) ;
2735 } else
2736 if (EmitSync & 8) {
2737 Label DONE_LABEL;
2738 if (UseBiasedLocking) {
2739 masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL);
2740 }
2741
2742 // Check whether the displaced header is 0
2743 //(=> recursive unlock)
2744 masm.movptr(tmpReg, Address(boxReg, 0));
2745 masm.testptr(tmpReg, tmpReg);
2746 masm.jcc(Assembler::zero, DONE_LABEL);
2747
2748 // If not recursive lock, reset the header to displaced header
2749 if (os::is_MP()) {
2750 masm.lock();
2751 }
2752 masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box
2753 masm.bind(DONE_LABEL);
2754 masm.nop(); // avoid branch to branch
2755 } else {
2756 Label DONE_LABEL, Stacked, CheckSucc ;
2757
2758 if (UseBiasedLocking && !UseOptoBiasInlining) {
2759 masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL);
2760 }
2761
2762 masm.movptr(tmpReg, Address(objReg, 0)) ;
2763 masm.cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD) ;
2764 masm.jcc (Assembler::zero, DONE_LABEL) ;
2765 masm.testl (tmpReg, 0x02) ;
2766 masm.jcc (Assembler::zero, Stacked) ;
2767
2768 // It's inflated
2769 masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
2770 masm.xorptr(boxReg, r15_thread) ;
2771 masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ;
2772 masm.jcc (Assembler::notZero, DONE_LABEL) ;
2773 masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ;
2774 masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ;
2775 masm.jcc (Assembler::notZero, CheckSucc) ;
2776 masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD) ;
2777 masm.jmp (DONE_LABEL) ;
2778
2779 if ((EmitSync & 65536) == 0) {
2780 Label LSuccess, LGoSlowPath ;
2781 masm.bind (CheckSucc) ;
2782 masm.cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD) ;
2783 masm.jcc (Assembler::zero, LGoSlowPath) ;
2784
2785 // I'd much rather use lock:andl m->_owner, 0 as it's faster than the
2786 // the explicit ST;MEMBAR combination, but masm doesn't currently support
2787 // "ANDQ M,IMM". Don't use MFENCE here. lock:add to TOS, xchg, etc
2788 // are all faster when the write buffer is populated.
2789 masm.movptr (Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD) ;
2790 if (os::is_MP()) {
2791 masm.lock () ; masm.addl (Address(rsp, 0), 0) ;
2792 }
2793 masm.cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD) ;
2794 masm.jcc (Assembler::notZero, LSuccess) ;
2795
2796 masm.movptr (boxReg, (int32_t)NULL_WORD) ; // box is really EAX
2797 if (os::is_MP()) { masm.lock(); }
2798 masm.cmpxchgptr(r15_thread, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2));
2799 masm.jcc (Assembler::notEqual, LSuccess) ;
2800 // Intentional fall-through into slow-path
2801
2802 masm.bind (LGoSlowPath) ;
2803 masm.orl (boxReg, 1) ; // set ICC.ZF=0 to indicate failure
2804 masm.jmp (DONE_LABEL) ;
2805
2806 masm.bind (LSuccess) ;
2807 masm.testl (boxReg, 0) ; // set ICC.ZF=1 to indicate success
2808 masm.jmp (DONE_LABEL) ;
2809 }
2810
2811 masm.bind (Stacked) ;
2812 masm.movptr(tmpReg, Address (boxReg, 0)) ; // re-fetch
2813 if (os::is_MP()) { masm.lock(); }
2814 masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box
2815
2816 if (EmitSync & 65536) {
2817 masm.bind (CheckSucc) ;
2818 }
2819 masm.bind(DONE_LABEL);
2820 if (EmitSync & 32768) {
2821 masm.nop(); // avoid branch to branch
2822 }
2823 }
2824 %}
2825
2826
2827 enc_class enc_rethrow() 2602 enc_class enc_rethrow()
2828 %{ 2603 %{
2829 cbuf.set_insts_mark(); 2604 cbuf.set_insts_mark();
2830 emit_opcode(cbuf, 0xE9); // jmp entry 2605 emit_opcode(cbuf, 0xE9); // jmp entry
2831 emit_d32_reloc(cbuf, 2606 emit_d32_reloc(cbuf,
11451 %} 11226 %}
11452 11227
11453 // ============================================================================ 11228 // ============================================================================
11454 // inlined locking and unlocking 11229 // inlined locking and unlocking
11455 11230
11456 instruct cmpFastLock(rFlagsReg cr, 11231 instruct cmpFastLock(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rRegP scr) %{
11457 rRegP object, rbx_RegP box, rax_RegI tmp, rRegP scr)
11458 %{
11459 match(Set cr (FastLock object box)); 11232 match(Set cr (FastLock object box));
11460 effect(TEMP tmp, TEMP scr, USE_KILL box); 11233 effect(TEMP tmp, TEMP scr, USE_KILL box);
11461
11462 ins_cost(300); 11234 ins_cost(300);
11463 format %{ "fastlock $object,$box\t! kills $box,$tmp,$scr" %} 11235 format %{ "fastlock $object,$box\t! kills $box,$tmp,$scr" %}
11464 ins_encode(Fast_Lock(object, box, tmp, scr)); 11236 ins_encode %{
11237 __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, $scr$$Register, _counters);
11238 %}
11465 ins_pipe(pipe_slow); 11239 ins_pipe(pipe_slow);
11466 %} 11240 %}
11467 11241
11468 instruct cmpFastUnlock(rFlagsReg cr, 11242 instruct cmpFastUnlock(rFlagsReg cr, rRegP object, rax_RegP box, rRegP tmp) %{
11469 rRegP object, rax_RegP box, rRegP tmp)
11470 %{
11471 match(Set cr (FastUnlock object box)); 11243 match(Set cr (FastUnlock object box));
11472 effect(TEMP tmp, USE_KILL box); 11244 effect(TEMP tmp, USE_KILL box);
11473
11474 ins_cost(300); 11245 ins_cost(300);
11475 format %{ "fastunlock $object,$box\t! kills $box,$tmp" %} 11246 format %{ "fastunlock $object,$box\t! kills $box,$tmp" %}
11476 ins_encode(Fast_Unlock(object, box, tmp)); 11247 ins_encode %{
11248 __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register);
11249 %}
11477 ins_pipe(pipe_slow); 11250 ins_pipe(pipe_slow);
11478 %} 11251 %}
11479 11252
11480 11253
11481 // ============================================================================ 11254 // ============================================================================