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