1 /*
2  * Copyright (c) 2020, 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.
char_arrays_equals(Register ary1,Register ary2,Register limit,Register result,Register chr1,Register chr2,Label & Ldone)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, dont'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 
fast_lock(Register Roop,Register Rbox,Register Rscratch,Register Rscratch2,Register scratch3)81 void C2_MacroAssembler::fast_lock(Register Roop, Register Rbox, Register Rscratch, Register Rscratch2, Register scratch3) {
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 (UseBiasedLocking && !UseOptoBiasInlining) {
94     assert(scratch3 != noreg, "need extra temporary for -XX:-UseOptoBiasInlining");
95     biased_locking_enter(Roop, Rmark, Rscratch, false, scratch3, done, done);
96     // Fall through if lock not biased otherwise branch to done
97   }
98 
99   // Invariant: Rmark loaded below does not contain biased lock pattern
100 
101   ldr(Rmark, Address(Roop, oopDesc::mark_offset_in_bytes()));
102   tst(Rmark, markWord::unlocked_value);
103   b(fast_lock, ne);
104 
105   // Check for recursive lock
106   // See comments in InterpreterMacroAssembler::lock_object for
107   // explanations on the fast recursive locking check.
108   // -1- test low 2 bits
109   movs(Rscratch, AsmOperand(Rmark, lsl, 30));
110   // -2- test (hdr - SP) if the low two bits are 0
111   sub(Rscratch, Rmark, SP, eq);
112   movs(Rscratch, AsmOperand(Rscratch, lsr, exact_log2(os::vm_page_size())), eq);
113   // If still 'eq' then recursive locking OK
114   // set to zero if recursive lock, set to non zero otherwise (see discussion in JDK-8153107)
115   str(Rscratch, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
116   b(done);
117 
118   bind(fast_lock);
119   str(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
120 
121   bool allow_fallthrough_on_failure = true;
122   bool one_shot = true;
123   cas_for_lock_acquire(Rmark, Rbox, Roop, Rscratch, done, allow_fallthrough_on_failure, one_shot);
124 
125   bind(done);
126 
127   // At this point flags are set as follows:
128   //  EQ -> Success
129   //  NE -> Failure, branch to slow path
130 }
131 
fast_unlock(Register Roop,Register Rbox,Register Rscratch,Register Rscratch2)132 void C2_MacroAssembler::fast_unlock(Register Roop, Register Rbox, Register Rscratch, Register Rscratch2) {
133   assert(VM_Version::supports_ldrex(), "unsupported, yet?");
134 
135   Register Rmark      = Rscratch2;
136 
137   assert(Roop != Rscratch, "");
138   assert(Roop != Rmark, "");
139   assert(Rbox != Rscratch, "");
140   assert(Rbox != Rmark, "");
141 
142   Label done;
143 
144   if (UseBiasedLocking && !UseOptoBiasInlining) {
145     biased_locking_exit(Roop, Rscratch, done);
146   }
147 
148   ldr(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
149   // If hdr is NULL, we've got recursive locking and there's nothing more to do
150   cmp(Rmark, 0);
151   b(done, eq);
152 
153   // Restore the object header
154   bool allow_fallthrough_on_failure = true;
155   bool one_shot = true;
156   cas_for_lock_release(Rmark, Rbox, Roop, Rscratch, done, allow_fallthrough_on_failure, one_shot);
157 
158   bind(done);
159 }
160 
161