1 /*
  2  * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 #include "precompiled.hpp"
 26 #include "asm/assembler.hpp"
 27 #include "asm/assembler.inline.hpp"
 28 #include "opto/c2_MacroAssembler.hpp"
 29 #include "runtime/basicLock.hpp"
 30 
 31 // TODO: 8 bytes at a time? pre-fetch?
 32 // Compare char[] arrays aligned to 4 bytes.
 33 void C2_MacroAssembler::char_arrays_equals(Register ary1, Register ary2,
 34                                            Register limit, Register result,
 35                                            Register chr1, Register chr2, Label& Ldone) {
 36   Label Lvector, Lloop;
 37 
 38   // if (ary1 == ary2)
 39   //     return true;
 40   cmpoop(ary1, ary2);
 41   b(Ldone, eq);
 42 
 43   // Note: limit contains number of bytes (2*char_elements) != 0.
 44   tst(limit, 0x2); // trailing character ?
 45   b(Lvector, eq);
 46 
 47   // compare the trailing char
 48   sub(limit, limit, sizeof(jchar));
 49   ldrh(chr1, Address(ary1, limit));
 50   ldrh(chr2, Address(ary2, limit));
 51   cmp(chr1, chr2);
 52   mov(result, 0, ne);     // not equal
 53   b(Ldone, ne);
 54 
 55   // only one char ?
 56   tst(limit, limit);
 57   mov(result, 1, eq);
 58   b(Ldone, eq);
 59 
 60   // word by word compare, don't need alignment check
 61   bind(Lvector);
 62 
 63   // Shift ary1 and ary2 to the end of the arrays, negate limit
 64   add(ary1, limit, ary1);
 65   add(ary2, limit, ary2);
 66   neg(limit, limit);
 67 
 68   bind(Lloop);
 69   ldr_u32(chr1, Address(ary1, limit));
 70   ldr_u32(chr2, Address(ary2, limit));
 71   cmp_32(chr1, chr2);
 72   mov(result, 0, ne);     // not equal
 73   b(Ldone, ne);
 74   adds(limit, limit, 2*sizeof(jchar));
 75   b(Lloop, ne);
 76 
 77   // Caller should set it:
 78   // mov(result_reg, 1);  //equal
 79 }
 80 
 81 void C2_MacroAssembler::fast_lock(Register Roop, Register Rbox, Register Rscratch, Register Rscratch2) {
 82   assert(VM_Version::supports_ldrex(), "unsupported, yet?");
 83 
 84   Register Rmark      = Rscratch2;
 85 
 86   assert(Roop != Rscratch, "");
 87   assert(Roop != Rmark, "");
 88   assert(Rbox != Rscratch, "");
 89   assert(Rbox != Rmark, "");
 90 
 91   Label fast_lock, done;
 92 
 93   if (DiagnoseSyncOnValueBasedClasses != 0) {
 94     load_klass(Rscratch, Roop);
 95     ldr_u32(Rscratch, Address(Rscratch, Klass::access_flags_offset()));
 96     tst(Rscratch, JVM_ACC_IS_VALUE_BASED_CLASS);
 97     b(done, ne);
 98   }
 99 
100   ldr(Rmark, Address(Roop, oopDesc::mark_offset_in_bytes()));
101   tst(Rmark, markWord::unlocked_value);
102   b(fast_lock, ne);
103 
104   // Check for recursive lock
105   // See comments in InterpreterMacroAssembler::lock_object for
106   // explanations on the fast recursive locking check.
107   // -1- test low 2 bits
108   movs(Rscratch, AsmOperand(Rmark, lsl, 30));
109   // -2- test (hdr - SP) if the low two bits are 0
110   sub(Rscratch, Rmark, SP, eq);
111   movs(Rscratch, AsmOperand(Rscratch, lsr, exact_log2(os::vm_page_size())), eq);
112   // If still 'eq' then recursive locking OK
113   // set to zero if recursive lock, set to non zero otherwise (see discussion in JDK-8153107)
114   str(Rscratch, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
115   b(done);
116 
117   bind(fast_lock);
118   str(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
119 
120   bool allow_fallthrough_on_failure = true;
121   bool one_shot = true;
122   cas_for_lock_acquire(Rmark, Rbox, Roop, Rscratch, done, allow_fallthrough_on_failure, one_shot);
123 
124   bind(done);
125 
126   // At this point flags are set as follows:
127   //  EQ -> Success
128   //  NE -> Failure, branch to slow path
129 }
130 
131 void C2_MacroAssembler::fast_unlock(Register Roop, Register Rbox, Register Rscratch, Register Rscratch2) {
132   assert(VM_Version::supports_ldrex(), "unsupported, yet?");
133 
134   Register Rmark      = Rscratch2;
135 
136   assert(Roop != Rscratch, "");
137   assert(Roop != Rmark, "");
138   assert(Rbox != Rscratch, "");
139   assert(Rbox != Rmark, "");
140 
141   Label done;
142 
143   ldr(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
144   // If hdr is NULL, we've got recursive locking and there's nothing more to do
145   cmp(Rmark, 0);
146   b(done, eq);
147 
148   // Restore the object header
149   bool allow_fallthrough_on_failure = true;
150   bool one_shot = true;
151   cas_for_lock_release(Rmark, Rbox, Roop, Rscratch, done, allow_fallthrough_on_failure, one_shot);
152 
153   bind(done);
154 }
155